static void DNAT_parse(struct xt_option_call *cb) { const struct ipt_entry *entry = cb->xt_entry; struct ipt_natinfo *info = (void *)(*cb->target); int portok; if (entry->ip.proto == IPPROTO_TCP || entry->ip.proto == IPPROTO_UDP || entry->ip.proto == IPPROTO_SCTP || entry->ip.proto == IPPROTO_DCCP || entry->ip.proto == IPPROTO_ICMP) portok = 1; else portok = 0; xtables_option_parse(cb); switch (cb->entry->id) { case O_TO_DEST: if (cb->xflags & F_X_TO_DEST) { if (!kernel_version) get_kernel_version(); if (kernel_version > LINUX_VERSION(2, 6, 10)) xtables_error(PARAMETER_PROBLEM, "DNAT: Multiple --to-destination not supported"); } *cb->target = parse_to(cb->arg, portok, info); cb->xflags |= F_X_TO_DEST; break; case O_PERSISTENT: info->mr.range[0].flags |= NF_NAT_RANGE_PERSISTENT; break; } }
void detect_versions() { struct utsname u; char kernel_version[512]; u = get_kernel_version(); if (strstr(u.machine, "64") == NULL) { dprintf("[-] system is not using a 64-bit kernel\n"); exit(EXIT_FAILURE); } if (strstr(u.version, "-Ubuntu") == NULL) { dprintf("[-] system is not using an Ubuntu kernel\n"); exit(EXIT_FAILURE); } char *u_ver = strtok(u.version, " "); snprintf(kernel_version, 512, "%s %s", u.release, u_ver); int i; for (i = 0; i < ARRAY_SIZE(kernels); i++) { if (strcmp(kernel_version, kernels[i].kernel_version) == 0) { dprintf("[.] kernel version '%s' detected\n", kernels[i].kernel_version); kernel = i; return; } } dprintf("[-] kernel version not recognized\n"); exit(EXIT_FAILURE); }
static void DNAT_parse(struct xt_option_call *cb) { const struct ip6t_entry *entry = cb->xt_entry; struct nf_nat_range *range = cb->data; int portok; if (entry->ipv6.proto == IPPROTO_TCP || entry->ipv6.proto == IPPROTO_UDP || entry->ipv6.proto == IPPROTO_SCTP || entry->ipv6.proto == IPPROTO_DCCP || entry->ipv6.proto == IPPROTO_ICMP) portok = 1; else portok = 0; xtables_option_parse(cb); switch (cb->entry->id) { case O_TO_DEST: if (cb->xflags & F_X_TO_DEST) { if (!kernel_version) get_kernel_version(); if (kernel_version > LINUX_VERSION(2, 6, 10)) xtables_error(PARAMETER_PROBLEM, "DNAT: Multiple --to-source not supported"); } parse_to(cb->arg, portok, range); break; case O_PERSISTENT: range->flags |= NF_NAT_RANGE_PERSISTENT; break; } }
bool GetKernelVersion(char *szBuf, int bufSize) { int major, minor, len; get_kernel_version(szBuf, bufSize); if ( qsscanf(szBuf, "%d.%n%d", &major, &len, &minor) != 2 ) return false; if ( isdigit(szBuf[len + 1]) ) gSdkVersion = 100*major + minor; else gSdkVersion = 10 * (10*major + minor); return true; }
static int SNAT_parse(int c, char **argv, int invert, unsigned int *flags, const void *e, struct xt_entry_target **target) { const struct ipt_entry *entry = e; struct ipt_natinfo *info = (void *)*target; int portok; if (entry->ip.proto == IPPROTO_TCP || entry->ip.proto == IPPROTO_UDP || entry->ip.proto == IPPROTO_SCTP || entry->ip.proto == IPPROTO_DCCP || entry->ip.proto == IPPROTO_ICMP) portok = 1; else portok = 0; switch (c) { case '1': if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) xtables_error(PARAMETER_PROBLEM, "Unexpected `!' after --to-source"); if (*flags & IPT_SNAT_OPT_SOURCE) { if (!kernel_version) get_kernel_version(); if (kernel_version > LINUX_VERSION(2, 6, 10)) xtables_error(PARAMETER_PROBLEM, "Multiple --to-source not supported"); } *target = parse_to(optarg, portok, info); /* WTF do we need this for?? */ if (*flags & IPT_SNAT_OPT_RANDOM) info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; *flags |= IPT_SNAT_OPT_SOURCE; return 1; case '2': if (*flags & IPT_SNAT_OPT_SOURCE) { info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; *flags |= IPT_SNAT_OPT_RANDOM; } else *flags |= IPT_SNAT_OPT_RANDOM; return 1; case '3': info->mr.range[0].flags |= IP_NAT_RANGE_PERSISTENT; return 1; default: return 0; } }
/* This is the C kernel entry point */ void kmain(struct multiboot *mboot_header, addr_t initial_stack) { /* Store passed values, and initiate some early things * We want serial log output as early as possible */ kernel_state_flags=0; mtboot = mboot_header; i_stack = initial_stack; parse_kernel_elf(mboot_header, &kernel_elf); #if CONFIG_MODULES init_kernel_symbols(); #endif init_serial(); console_init_stage1(); load_tables(); puts("~ SeaOS Version "); char ver[32]; get_kernel_version(ver); puts(ver); puts(" Booting Up ~\n\r"); #if CONFIG_MODULES init_module_system(); #endif init_syscalls(); load_initrd(mtboot); install_timer(1000); pm_init(placement, mtboot); init_main_cpu_1(); /* Now get the management stuff going */ printk(1, "[kernel]: Starting system management\n"); init_memory(mtboot); init_main_cpu_2(); console_init_stage2(); parse_kernel_cmd((char *)(addr_t)mtboot->cmdline); init_multitasking(); init_cache(); init_dm(); init_vfs(); /* Load the rest... */ process_initrd(); init_kern_task(); get_timed(&kernel_start_time); printk(KERN_MILE, "[kernel]: Kernel is setup (%2.2d:%2.2d:%2.2d, %s, kv=%d, ts=%d bytes: ok)\n", kernel_start_time.tm_hour, kernel_start_time.tm_min, kernel_start_time.tm_sec, kernel_name, KVERSION, sizeof(task_t)); assert(!set_int(1)); if(!fork()) init(); sys_setsid(); enter_system(255); kernel_idle_task(); }
int main() { char buf[BUF_SIZE]; get_cpu_type(buf, sizeof(buf)); printf("CPU Type: %s\n", buf); get_kernel_version(buf, sizeof(buf)); printf("Kernel Version: %s\n", buf); get_uptime(buf, sizeof(buf)); calc_time(buf, buf, sizeof(buf)); printf("Time since bootup: %s\n", buf); return 0; }
/* Function which parses command options; returns true if it ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ipt_entry *entry, struct ipt_entry_target **target) { struct ipt_natinfo *info = (void *)*target; int portok; if (entry->ip.proto == IPPROTO_TCP || entry->ip.proto == IPPROTO_UDP || entry->ip.proto == IPPROTO_ICMP) portok = 1; else portok = 0; switch (c) { case '1': if (check_inverse(optarg, &invert, NULL, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' after --to-destination"); if (*flags) { if (!kernel_version) get_kernel_version(); if (kernel_version > LINUX_VERSION(2, 6, 10)) exit_error(PARAMETER_PROBLEM, "Multiple --to-destination not supported"); } *target = parse_to(optarg, portok, info); /* WTF do we need this for?? */ if (*flags & IPT_DNAT_OPT_RANDOM) info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; *flags |= IPT_DNAT_OPT_DEST; return 1; case '2': if (*flags & IPT_DNAT_OPT_DEST) { info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; *flags |= IPT_DNAT_OPT_RANDOM; } else *flags |= IPT_DNAT_OPT_RANDOM; return 1; default: return 0; } }
//-------------------------------------------------------------------------- int idaapi init(void) { // gui version? if ( callui(ui_get_hwnd).vptr == NULL && !is_idaq() ) return PLUGIN_SKIP; char buf[10]; get_kernel_version(buf, sizeof(buf)); int v1, v2; if ( qsscanf(buf, "%d.%d", &v1, &v2) != 2 || v1*10+v2 < 55 ) { warning("Sorry, the callgraph plugin required IDA v5.5 or higher\n"); return PLUGIN_SKIP; } if ( !add_menu_item(CMD_MENU "Function calls", CMD_NAME, NULL, SETMENU_APP, run_plugin, NULL) ) { msg("Failed to register menu item for <" CMD_NAME "> plugin! Please access it from the plugins submenu"); return PLUGIN_SKIP; } return PLUGIN_KEEP; }
/* Function which parses command options; returns true if it ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ipt_entry *entry, struct ipt_entry_target **target) { struct ipt_natinfo *info = (void *)*target; int portok; if (entry->ip.proto == IPPROTO_TCP || entry->ip.proto == IPPROTO_UDP || entry->ip.proto == IPPROTO_ICMP) portok = 1; else portok = 0; switch (c) { case '1': if (check_inverse(optarg, &invert, NULL, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' after --to-source"); if (*flags) { if (!kernel_version) get_kernel_version(); if (kernel_version > LINUX_VERSION(2, 6, 10)) exit_error(PARAMETER_PROBLEM, "Multiple --to-source not supported"); } *target = parse_to(optarg, portok, info); *flags = 1; return 1; default: return 0; } }
unsigned long get_kernel_addr_sysmap() { FILE *f; unsigned long addr = 0; char path[512] = "/boot/System.map-"; char version[32]; struct utsname u; u = get_kernel_version(); strcat(path, u.release); dprintf("[.] trying %s...\n", path); f = fopen(path, "r"); if (f == NULL) { dprintf("[-] open/read(%s)\n", path); return 0; } char dummy; char sname[256]; char* name = "startup_64"; int ret = 0; while (ret != EOF) { ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname); if (ret == 0) { fscanf(f, "%s\n", sname); continue; } if (!strcmp(name, sname)) { fclose(f); return addr; } } fclose(f); dprintf("[-] kernel base not found in %s\n", path); return 0; }
int main(int argc, char** argv) { int ret,quiet; struct perf_event_attr pe; struct sigaction sa; void *our_mmap; char test_string[]="Testing large sample_period..."; quiet=test_quiet(); if (!quiet) { printf("This tests behavior of large sample_period.\n"); printf("This was broken prior to Linux 3.15.\n\n"); } memset(&sa, 0, sizeof(struct sigaction)); sa.sa_sigaction = our_handler; sa.sa_flags = SA_SIGINFO; if (sigaction( SIGIO, &sa, NULL) < 0) { fprintf(stderr,"Error setting up signal handler\n"); exit(1); } /*******************************************************/ /* First try sample period that *will* cause overflows */ /*******************************************************/ count.in=0; count.out=0; count.msg=0; count.err=0; count.pri=0; count.hup=0; count.unknown=0; count.total=0; if (!quiet) { printf("Trying 1 million instructions with period 100,000\n"); printf("Should be 10 overflows\n"); } memset(&pe,0,sizeof(struct perf_event_attr)); pe.type=PERF_TYPE_HARDWARE; pe.size=sizeof(struct perf_event_attr); pe.config=PERF_COUNT_HW_INSTRUCTIONS; pe.sample_period=100000; pe.sample_type=PERF_SAMPLE_IP; pe.read_format=PERF_FORMAT_GROUP|PERF_FORMAT_ID; pe.disabled=1; pe.pinned=1; pe.exclude_kernel=1; pe.exclude_hv=1; pe.wakeup_events=1; arch_adjust_domain(&pe,quiet); fd1=perf_event_open(&pe,0,-1,-1,0); if (fd1<0) { if (!quiet) fprintf(stderr,"Error opening leader %llx\n",pe.config); test_fail(test_string); } our_mmap=mmap(NULL, (1+MMAP_PAGES)*getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0); fcntl(fd1, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC); fcntl(fd1, F_SETSIG, SIGIO); fcntl(fd1, F_SETOWN,getpid()); ioctl(fd1, PERF_EVENT_IOC_RESET, 0); ret=ioctl(fd1, PERF_EVENT_IOC_REFRESH,1); if (ret<0) { if (!quiet) { fprintf(stderr,"Error with PERF_EVENT_IOC_ENABLE of group leader: " "%d %s\n",errno,strerror(errno)); test_fail(test_string); } } instructions_million(); ret=ioctl(fd1, PERF_EVENT_IOC_DISABLE,0); close(fd1); if (!quiet) { printf("Counts, using mmap buffer %p\n",our_mmap); printf("\tPOLL_IN : %d\n",count.in); printf("\tPOLL_OUT: %d\n",count.out); printf("\tPOLL_MSG: %d\n",count.msg); printf("\tPOLL_ERR: %d\n",count.err); printf("\tPOLL_PRI: %d\n",count.pri); printf("\tPOLL_HUP: %d\n",count.hup); printf("\tUNKNOWN : %d\n",count.unknown); } if (count.total==0) { if (!quiet) printf("No overflow events generated.\n"); test_fail(test_string); } if (count.in!=0) { if (!quiet) printf("Unexpected POLL_IN interrupt.\n"); test_fail(test_string); } if (count.hup!=10) { if (!quiet) printf("POLL_HUP value %d, expected %d.\n", count.hup,10); test_fail(test_string); } /*******************************************************/ /* Next try moderate size value, should be no overflow */ /*******************************************************/ count.in=0; count.out=0; count.msg=0; count.err=0; count.pri=0; count.hup=0; count.unknown=0; count.total=0; if (!quiet) { printf("Trying 1 million instructions with period 10,000,000\n"); printf("Should be 0 overflows\n"); } memset(&pe,0,sizeof(struct perf_event_attr)); pe.type=PERF_TYPE_HARDWARE; pe.size=sizeof(struct perf_event_attr); pe.config=PERF_COUNT_HW_INSTRUCTIONS; pe.sample_period=10000000; pe.sample_type=PERF_SAMPLE_IP; pe.read_format=PERF_FORMAT_GROUP|PERF_FORMAT_ID; pe.disabled=1; pe.pinned=1; pe.exclude_kernel=1; pe.exclude_hv=1; pe.wakeup_events=1; arch_adjust_domain(&pe,quiet); fd1=perf_event_open(&pe,0,-1,-1,0); if (fd1<0) { if (!quiet) fprintf(stderr,"Error opening leader %llx\n",pe.config); test_fail(test_string); } our_mmap=mmap(NULL, (1+MMAP_PAGES)*getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0); fcntl(fd1, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC); fcntl(fd1, F_SETSIG, SIGIO); fcntl(fd1, F_SETOWN,getpid()); ioctl(fd1, PERF_EVENT_IOC_RESET, 0); ret=ioctl(fd1, PERF_EVENT_IOC_REFRESH,1); if (ret<0) { if (!quiet) { fprintf(stderr,"Error with PERF_EVENT_IOC_ENABLE of group leader: " "%d %s\n",errno,strerror(errno)); test_fail(test_string); } } instructions_million(); ret=ioctl(fd1, PERF_EVENT_IOC_DISABLE,0); close(fd1); if (!quiet) { printf("Counts, using mmap buffer %p\n",our_mmap); printf("\tPOLL_IN : %d\n",count.in); printf("\tPOLL_OUT: %d\n",count.out); printf("\tPOLL_MSG: %d\n",count.msg); printf("\tPOLL_ERR: %d\n",count.err); printf("\tPOLL_PRI: %d\n",count.pri); printf("\tPOLL_HUP: %d\n",count.hup); printf("\tUNKNOWN : %d\n",count.unknown); } if (count.total!=0) { if (!quiet) printf("Unexpected overflow events generated.\n"); test_fail(test_string); } /*******************************************************/ /* Next try large size value, should be no overflow */ /*******************************************************/ count.in=0; count.out=0; count.msg=0; count.err=0; count.pri=0; count.hup=0; count.unknown=0; count.total=0; memset(&pe,0,sizeof(struct perf_event_attr)); pe.type=PERF_TYPE_HARDWARE; pe.size=sizeof(struct perf_event_attr); pe.config=PERF_COUNT_HW_INSTRUCTIONS; pe.sample_period=(1ULL<<63)-1; pe.sample_type=PERF_SAMPLE_IP; pe.read_format=PERF_FORMAT_GROUP|PERF_FORMAT_ID; pe.disabled=1; pe.pinned=1; pe.exclude_kernel=1; pe.exclude_hv=1; pe.wakeup_events=1; if (!quiet) { printf("Trying 1 million instructions with period (2^63)-1 (%llx)\n", pe.sample_period); printf("Should be 0 overflows\n"); } arch_adjust_domain(&pe,quiet); fd1=perf_event_open(&pe,0,-1,-1,0); if (fd1<0) { if (!quiet) fprintf(stderr,"Error opening leader %llx\n",pe.config); test_fail(test_string); } our_mmap=mmap(NULL, (1+MMAP_PAGES)*getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0); fcntl(fd1, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC); fcntl(fd1, F_SETSIG, SIGIO); fcntl(fd1, F_SETOWN,getpid()); ioctl(fd1, PERF_EVENT_IOC_RESET, 0); ret=ioctl(fd1, PERF_EVENT_IOC_REFRESH,1); if (ret<0) { if (!quiet) { fprintf(stderr,"Error with PERF_EVENT_IOC_ENABLE of group leader: " "%d %s\n",errno,strerror(errno)); test_fail(test_string); } } instructions_million(); ret=ioctl(fd1, PERF_EVENT_IOC_DISABLE,0); close(fd1); if (!quiet) { printf("Counts, using mmap buffer %p\n",our_mmap); printf("\tPOLL_IN : %d\n",count.in); printf("\tPOLL_OUT: %d\n",count.out); printf("\tPOLL_MSG: %d\n",count.msg); printf("\tPOLL_ERR: %d\n",count.err); printf("\tPOLL_PRI: %d\n",count.pri); printf("\tPOLL_HUP: %d\n",count.hup); printf("\tUNKNOWN : %d\n",count.unknown); } if (count.total!=0) { if (!quiet) printf("Unexpected overflow events generated.\n"); test_fail(test_string); } /************************************************************/ /* Next try very large size value, should be no overflow */ /* In fact, on 3.15 and later the open should fail */ /************************************************************/ count.in=0; count.out=0; count.msg=0; count.err=0; count.pri=0; count.hup=0; count.unknown=0; count.total=0; memset(&pe,0,sizeof(struct perf_event_attr)); pe.type=PERF_TYPE_HARDWARE; pe.size=sizeof(struct perf_event_attr); pe.config=PERF_COUNT_HW_INSTRUCTIONS; pe.sample_period=0xc0000000000000bd; pe.sample_type=PERF_SAMPLE_IP; pe.read_format=PERF_FORMAT_GROUP|PERF_FORMAT_ID; pe.disabled=1; pe.pinned=1; pe.exclude_kernel=1; pe.exclude_hv=1; pe.wakeup_events=1; if (!quiet) { printf("Trying 1 million instructions with period %llx\n", pe.sample_period); printf("Should be 0 overflows\n"); } arch_adjust_domain(&pe,quiet); fd1=perf_event_open(&pe,0,-1,-1,0); if (fd1<0) { if (errno==EINVAL) { if (!quiet) { fprintf(stderr,"Properly failed with too-large sample_period\n"); test_pass(test_string); exit(0); } } if (!quiet) fprintf(stderr,"Error opening leader %llx\n",pe.config); test_fail(test_string); } our_mmap=mmap(NULL, (1+MMAP_PAGES)*getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0); fcntl(fd1, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC); fcntl(fd1, F_SETSIG, SIGIO); fcntl(fd1, F_SETOWN,getpid()); ioctl(fd1, PERF_EVENT_IOC_RESET, 0); ret=ioctl(fd1, PERF_EVENT_IOC_REFRESH,1); if (ret<0) { if (!quiet) { fprintf(stderr,"Error with PERF_EVENT_IOC_ENABLE of group leader: " "%d %s\n",errno,strerror(errno)); test_fail(test_string); } } instructions_million(); ret=ioctl(fd1, PERF_EVENT_IOC_DISABLE,0); close(fd1); if (!quiet) { printf("Counts, using mmap buffer %p\n",our_mmap); printf("\tPOLL_IN : %d\n",count.in); printf("\tPOLL_OUT: %d\n",count.out); printf("\tPOLL_MSG: %d\n",count.msg); printf("\tPOLL_ERR: %d\n",count.err); printf("\tPOLL_PRI: %d\n",count.pri); printf("\tPOLL_HUP: %d\n",count.hup); printf("\tUNKNOWN : %d\n",count.unknown); } if (count.total>20000) { int version; if (!quiet) printf("Stopping early, too many overflows encountered.\n"); /* This is expected before 3.15 */ version=get_kernel_version(); if (version<0x30f00) { test_fail_kernel(test_string); } else { test_fail(test_string); } } if (count.total!=0) { if (!quiet) printf("Unexpected overflow events generated.\n"); test_fail(test_string); } test_pass(test_string); return 0; }
int64_t find_sysent(const uint8_t *buffer, const uint64_t data_address, const uint64_t data_size) { uint64_t i = 0; if (get_kernel_type()) // 64 bits { int major = get_kernel_version(); /* Mavericks or higher uses new sysent table format */ if (major >= 13) { while (i < data_size) { struct newsysent *table = (struct newsysent*)(&buffer[i]); if(table[SYS_exit].sy_narg == 1 && table[SYS_fork].sy_narg == 0 && table[SYS_read].sy_narg == 3 && table[SYS_wait4].sy_narg == 4 && table[SYS_ptrace].sy_narg == 4 && table[SYS_getxattr].sy_narg == 6 && table[SYS_listxattr].sy_narg == 4 && table[SYS_recvmsg].sy_narg == 3 ) { printf("[DEBUG] exit() address is %p\n", (void*)table[SYS_exit].sy_call); return(data_address+i); } i++; } } else { while (i < data_size) { struct sysent64 *table = (struct sysent64*)(&buffer[i]); if(table[SYS_exit].sy_narg == 1 && table[SYS_fork].sy_narg == 0 && table[SYS_read].sy_narg == 3 && table[SYS_wait4].sy_narg == 4 && table[SYS_ptrace].sy_narg == 4 && table[SYS_getxattr].sy_narg == 6 && table[SYS_listxattr].sy_narg == 4 && table[SYS_recvmsg].sy_narg == 3 ) { printf("[DEBUG] exit() address is %p\n", (void*)table[SYS_exit].sy_call); return(data_address+i); } i++; } } } else // 32bits { while (i < data_size) { struct sysent *table = (struct sysent*)(&buffer[i]); if(table[SYS_exit].sy_narg == 1 && table[SYS_fork].sy_narg == 0 && table[SYS_read].sy_narg == 3 && table[SYS_wait4].sy_narg == 4 && table[SYS_ptrace].sy_narg == 4 && table[SYS_getxattr].sy_narg == 6 && table[SYS_listxattr].sy_narg == 4 && table[SYS_recvmsg].sy_narg == 3 ) { printf("[DEBUG] exit() address is %p\n", (void*)table[SYS_exit].sy_call); return(data_address+i); } i++; } } return(0); }
int main(int argc, char **argv) { int ret,status; int fd; int mmap_pages=1+MMAP_DATA_SIZE; int events_read; int child; int version; struct perf_event_attr pe; struct sigaction sa; char test_string[]="Testing PERF_RECORD_COMM_EXEC..."; quiet=test_quiet(); if (!quiet) printf("This tests PERF_RECORD_COMM_EXEC samples:\n"); memset(&sa, 0, sizeof(struct sigaction)); sa.sa_sigaction = our_handler; sa.sa_flags = SA_SIGINFO; if (sigaction( SIGIO, &sa, NULL) < 0) { fprintf(stderr,"Error setting up signal handler\n"); exit(1); } /* Fork child to measure */ /* We do this in a child as we have to exec */ child=fork(); if (child==0) { FILE *fff; if (ptrace(PTRACE_TRACEME, 0, 0, 0) == 0) { kill(getpid(),SIGTRAP); /* The actual thing to measure */ instructions_million(); /* prctl */ if (!quiet) printf("\tprctl(PR_SET_NAME,\"vmw\");\n"); prctl(PR_SET_NAME,"vmw"); /* /proc/self/comm */ if (!quiet) printf("\tcat \"krg krg krg\" > /proc/self/comm\n"); fff=fopen("/proc/self/comm","w"); if (fff!=NULL) { fprintf(fff,"krg krg krg"); fclose(fff); } /* exec */ if (!quiet) printf("\texecl(\"/bin/false\"); [should have PERF_RECORD_MISC_COMM_EXEC set]\n"); execl("/bin/false","/bin/true",NULL); instructions_million(); /* Done measuring */ } else { fprintf(stderr,"Failed ptrace...\n"); } return 1; } /* wait for child to stop */ child=wait(&status); /* Set up Instruction Event */ memset(&pe,0,sizeof(struct perf_event_attr)); pe.type=PERF_TYPE_SOFTWARE; pe.size=sizeof(struct perf_event_attr); pe.config=PERF_COUNT_SW_DUMMY; pe.sample_period=SAMPLE_FREQUENCY; pe.read_format=0; pe.disabled=1; pe.pinned=1; pe.exclude_kernel=1; pe.exclude_hv=1; pe.wakeup_events=1; pe.comm_exec=1; pe.comm=1; arch_adjust_domain(&pe,quiet); fd=perf_event_open(&pe,child,-1,-1,0); if (fd<0) { if (!quiet) { fprintf(stderr,"Problem opening leader %s\n", strerror(errno)); } version=get_kernel_version(); /* Introduced in 3.16 */ if (version<0x31000) { if (!quiet) { fprintf(stderr,"comm_exec support not added until Linux 3.16\n"); } test_fail_kernel(test_string); } test_fail(test_string); } our_mmap=mmap(NULL, mmap_pages*4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (our_mmap==MAP_FAILED) { fprintf(stderr,"mmap() failed %s!\n",strerror(errno)); test_fail(test_string); } fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC); fcntl(fd, F_SETSIG, SIGIO); fcntl(fd, F_SETOWN,getpid()); ioctl(fd, PERF_EVENT_IOC_RESET, 0); ret=ioctl(fd, PERF_EVENT_IOC_ENABLE,0); if (ret<0) { if (!quiet) { fprintf(stderr,"Error with PERF_EVENT_IOC_ENABLE " "of group leader: %d %s\n", errno,strerror(errno)); exit(1); } } /* restart child */ if ( ptrace( PTRACE_CONT, child, NULL, NULL ) == -1 ) { fprintf(stderr,"Error continuing child\n"); test_fail(test_string); } /* Wait for child to finish */ waitpid(child,&status,0); ret=ioctl(fd, PERF_EVENT_IOC_REFRESH,0); if (!quiet) { printf("Counts %d, using mmap buffer %p\n",count_total,our_mmap); } /* Drain any remaining events */ prev_head=perf_mmap_read(our_mmap,MMAP_DATA_SIZE,prev_head, global_sample_type,0,global_sample_regs_user, NULL,quiet,&events_read); munmap(our_mmap,mmap_pages*4096); close(fd); #define EXPECTED_EVENTS 3 if (events_read!=EXPECTED_EVENTS) { if (!quiet) fprintf(stderr,"Wrong number of events! Expected %d but got %d\n", EXPECTED_EVENTS,events_read); test_fail(test_string); } test_pass(test_string); return 0; }
int main(int argc, char** argv) { int fd1,quiet; struct perf_event_attr pe; char test_string[]="Testing flags invalid bits..."; quiet=test_quiet(); if (!quiet) { printf("Testing flags invalid bits.\n"); printf("This was broken prior to Linux 3.15\n"); } memset(&pe,0,sizeof(struct perf_event_attr)); pe.type=PERF_TYPE_HARDWARE; pe.size=sizeof(struct perf_event_attr); pe.config=PERF_COUNT_HW_INSTRUCTIONS; pe.disabled=0; pe.exclude_kernel=1; pe.exclude_hv=1; arch_adjust_domain(&pe,quiet); /* test 1, 0x40000000 */ fd1=perf_event_open(&pe,0,-1,-1,0x4000000); if (fd1<0) { if (errno==EINVAL) { if (!quiet) { printf("Correctly failed opening leader with flags %x\n",0x40000000); } } else { if (!quiet) { fprintf(stderr,"Unexpected error %s\n",strerror(errno)); test_fail(test_string); } } } else { close(fd1); if (!quiet) { fprintf(stderr,"Unexpectedly opened properly with flags %x\n",0x40000000); } test_fail(test_string); } /* test 1, 0x800000000 */ fd1=perf_event_open(&pe,0,-1,-1,0x8000000000ULL); if (fd1<0) { if (errno==EINVAL) { if (!quiet) { printf("Correctly failed opening leader with flags %llx\n",0x8000000000ULL); } } else { if (!quiet) { fprintf(stderr,"Unexpected error %s\n",strerror(errno)); test_fail(test_string); } } } else { int version; close(fd1); version=get_kernel_version(); if (version<0x30f00) { if (!quiet) { fprintf(stderr,"Unexpectedly opened properly with flags %llx\n",0x8000000000ULL); fprintf(stderr,"This was not fixed until Linux 3.15\n"); } test_fail_kernel(test_string); } else { if (!quiet) { fprintf(stderr,"Unexpectedly opened properly with flags %llx\n",0x8000000000ULL); } test_fail(test_string); } } test_pass(test_string); return 0; }
/* * save process' memory maps, stack contents, thread identifiers and registers */ struct snapshot *get_snapshot(int pid, int *tids, int *index, int nr_tids) { struct snapshot *res; int i, attached_tid, n_frames; long page, label, rc; struct mem_data_chunk **stacks_cover = NULL; int v_major, v_minor; int use_process_vm_readv = 0; if ((page = sysconf(_SC_PAGESIZE)) < 0) { perror("get pagesize"); return NULL; } --page; res = calloc(1, sizeof(struct snapshot)); /* * create memory_map structure corresponding to process' maps */ res->map = create_maps(pid); if (res->map == NULL) goto get_snapshot_fail; /* * get process' threads */ res->num_threads = get_threads(pid, &res->tids); if (res->num_threads < 0 || res->tids == NULL) goto get_snapshot_fail; /* * user-provided list of threads */ if (tids != NULL) { if (adjust_threads(res->tids, res->num_threads, tids, index, nr_tids) < 0) goto get_snapshot_fail; free(res->tids); res->num_threads = nr_tids; res->tids = tids; } res->cur_thr = 0; res->regs = malloc(sizeof(struct user_regs_struct)*res->num_threads); if (res->regs == NULL) { perror("malloc"); goto get_snapshot_fail; } /* * decide how to copy memory contents of the process. on newer kernels * proc_vm_readv() is used by default. on older kernels or when the option * --proc-mem is specified read the file /proc/<pid>/mem */ if (!opt_proc_mem) { if (get_kernel_version(&v_major, &v_minor) < 0) goto get_snapshot_fail; if (((v_major << 16) | v_minor) >= 0x30002) use_process_vm_readv = 1; } else { use_process_vm_readv = 0; } /* FREEZE PROCESS */ if (attach_process(pid) < 0) goto get_snapshot_fail; for (i = 0; i < res->num_threads; ++i) { /* * we have already attached to main thread. call attach_thread() * for other ones */ attached_tid = res->tids[i]; if (res->tids[i] != pid && attach_thread(res->tids[i]) < 0) goto get_snapshot_fail_attached; /* * save thread's registers */ rc = ptrace(PTRACE_GETREGS, res->tids[i], NULL, &res->regs[i]); if (rc < 0) { perror("PTRACE_GETREGS"); goto get_snapshot_fail_attached; } /* * save label on memory region. it will indicate that memory contents * upper than this point (%rsp) will needed to unwind stacks */ label = res->regs[i].rsp & ~page; rc = mem_map_add_label(res->map, (void *)label, res->num_threads); if (rc < 0) { fprintf(stderr, "failed to add label 0x%lx [rsp 0x%lx thread %d]\n", label, res->regs[i].rsp, res->tids[i]); goto get_snapshot_fail_attached; } /* * detach from thread. it will still be frozen due to SIGSTOP */ if (res->tids[i] != pid && detach_thread(res->tids[i]) < 0) goto get_snapshot_fail_attached; } /* * arrange data chunks to copy memory contents. in most cases the chunks * will start from %rsp pointing somewhere in thread's stack * to the end of the stack region */ stacks_cover = malloc(sizeof(struct mem_data_chunk*) * res->num_threads); n_frames = mem_map_build_label_cover(res->map, stack_size, stacks_cover, page + 1); if (stacks_cover == NULL) { fprintf(stderr, "error: stacks cover == NULL, n_frames=%d\n", n_frames); goto get_snapshot_fail_attached; } /* * copy memory contents */ rc = use_process_vm_readv ? copy_memory_process_vm_readv(pid, stacks_cover, n_frames) : copy_memory_proc_mem(pid, stacks_cover, n_frames); if (rc < 0) goto get_snapshot_fail_attached; /* UNFREEZE PROCESS */ if (detach_process(pid) < 0) goto get_snapshot_fail; if (opt_verbose) { for (i = 0; i < n_frames; ++i) { struct mem_data_chunk *chunk = stacks_cover[i]; printf("chunk #%d: 0x%lx-0x%lx length: %ldK\n", i, (size_t)chunk->start, (size_t)chunk->start + chunk->length, chunk->length >> 10); } } free(stacks_cover); return res; get_snapshot_fail_attached: if (attached_tid) detach_thread(attached_tid); detach_process(pid); get_snapshot_fail: if (opt_verbose) { fprintf(stderr, "maps of %d:\n", pid); print_proc_maps(pid); } free(stacks_cover); snapshot_destroy(res); return NULL; }
int init_kernel_interface( random_mode_t* random_mode ) { int changed = 0; //fd of /dev/random device random_mode->dev_random_fd = open(random_mode->random_device, O_RDWR); if (random_mode->dev_random_fd == -1) { fprintf(stderr, "ERROR: Cannnot open %s: %s\n", random_mode->random_device, strerror(errno) ); return -1; } //Refill interval if ( random_mode->refill_interval < 0 ) { fprintf(stderr, "ERROR: Expecting refill_interval to be >=0 but got %d!\n", random_mode->refill_interval); return -1; } //OS kernel version - needed to correctly get pool size random_mode->kernel_version = get_kernel_version(); if (random_mode->kernel_version == KERNEL_UNSUPPORTED) { fprintf(stderr, "ERROR: Unsupported linux kernel!\n"); return -1; } if ( random_mode->entropy_per_bit <= 0.0 || random_mode->entropy_per_bit > 1.0 ) { fprintf(stderr, "ERROR: Expecting entropy_per_bit to be >0.0 and <= 1.0 but got %g!\n", random_mode->entropy_per_bit); return -1; } //Size of /dev/random entropy pool. See /proc/sys/kernel/random/poolsize and man -S4 random //On kernel 2.6 and later default value is 4096 bits random_mode->poolsize = get_rng_poolsize(&random_mode->kernel_version); if ( random_mode->poolsize < 0 ) { fprintf(stderr, "ERROR: get_rng_poolsize has failed!\n"); return -1; } if ( random_mode->min_entropy > random_mode->poolsize || random_mode->min_entropy < 1 ) { fprintf(stderr, "ERROR: Expecting min_entropy to be >0 and <= %d but got %d!\n", random_mode->poolsize, random_mode->min_entropy); return -1; } //Compute upper limit to which we would like to fill the kernel entropy pool. //High values means that /dev/random will be dominated by csprng. Low values will hurt performance. //It should be higher than /proc/sys/kernel/random/read_wakeup_threshold (64 bits) and ///proc/sys/kernel/random/write_wakeup_threshold (128 bits) //Zero values of arguments means that user input is in % of total pool size if ( random_mode->upper_limit == 0 || random_mode->upper_limit < -100 || random_mode->upper_limit > random_mode->poolsize ) { fprintf(stderr, "ERROR: Expecting upper_limit to be >0 and <= %d\n" "or >= -100 and < 0 (negative number represents percentage of kernel poolsize as specified in file /proc/sys/kernel/random/poolsize\n" "but got %d!\n", random_mode->poolsize, random_mode->upper_limit); return -1; } if ( random_mode->upper_limit < 0) { random_mode->upper_limit = (int) ( (double) ( random_mode->poolsize) * (double) (-random_mode->upper_limit) / 100.0 ); } random_mode->read_wakeup_threshold = get_proc_value("/proc/sys/kernel/random/read_wakeup_threshold"); if ( random_mode->read_wakeup_threshold < 0 ) { fprintf(stderr, "ERROR: get_proc_value(\"/proc/sys/kernel/random/read_wakeup_threshold\") has failed!\n"); return -1; } if ( random_mode->upper_limit <= random_mode->read_wakeup_threshold ) { fprintf(stderr, "ERROR: random_mode->upper_limit should be bigger than " "\"/proc/sys/kernel/random/read_wakeup_threshold\" value of %d bits.\n", random_mode->read_wakeup_threshold); random_mode->upper_limit = random_mode->read_wakeup_threshold + 32; changed = 1; } random_mode->write_wakeup_threshold = get_proc_value("/proc/sys/kernel/random/write_wakeup_threshold"); if ( random_mode->write_wakeup_threshold < 0 ) { fprintf(stderr, "ERROR: get_proc_value(\"/proc/sys/kernel/random/write_wakeup_threshold\") has failed!\n"); return -1; } if ( random_mode->upper_limit <= random_mode->write_wakeup_threshold ) { fprintf(stderr, "ERROR: random_mode->upper_limit should be bigger than " "\"/proc/sys/kernel/random/write_wakeup_threshold\" value of %d bits.\n", random_mode->write_wakeup_threshold); random_mode->upper_limit = random_mode->write_wakeup_threshold + 32; changed = 1; } if ( random_mode->upper_limit > random_mode->poolsize) { random_mode->upper_limit = random_mode->poolsize; changed = 1; } if ( changed ) { fprintf(stderr, "ERROR: Adjusting random_mode->upper_limit to %d bits.\n", random_mode->upper_limit); } return 0; }