static boolean check_register_usage( struct sanity_check_ctx *ctx, uint file, int index, const char *name, boolean indirect_access ) { if (!check_file_name( ctx, file )) return FALSE; if (indirect_access) { /* Note that 'index' is an offset relative to the value of the * address register. No range checking done here. */ if (!is_any_register_declared( ctx, file )) report_error( ctx, "%s: Undeclared %s register", file_names[file], name ); ctx->regs_ind_used[file] = TRUE; } else { if (index < 0 || index >= MAX_REGISTERS) { report_error( ctx, "%s[%d]: Invalid %s index", file_names[file], index, name ); return FALSE; } if (!is_register_declared( ctx, file, index )) report_error( ctx, "%s[%d]: Undeclared %s register", file_names[file], index, name ); ctx->regs_used[file][index / BITS_IN_REG_FLAG] |= (1 << (index % BITS_IN_REG_FLAG)); } return TRUE; }
static boolean iter_declaration( struct tgsi_iterate_context *iter, struct tgsi_full_declaration *decl ) { struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter; uint file; uint i; /* No declarations allowed after the first instruction. */ if (ctx->num_instructions > 0) report_error( ctx, "Instruction expected but declaration found" ); /* Check registers' validity. * Mark the registers as declared. */ file = decl->Declaration.File; if (!check_file_name( ctx, file )) return TRUE; for (i = decl->DeclarationRange.First; i <= decl->DeclarationRange.Last; i++) { if (is_register_declared( ctx, file, i )) report_error( ctx, "%s[%u]: The same register declared more than once", file_names[file], i ); ctx->regs_decl[file][i / BITS_IN_REG_FLAG] |= (1 << (i % BITS_IN_REG_FLAG)); } return TRUE; }
static boolean iter_declaration( struct tgsi_iterate_context *iter, struct tgsi_full_declaration *decl ) { struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter; uint file; uint i; /* No declarations allowed after the first instruction. */ if (ctx->num_instructions > 0) report_error( ctx, "Instruction expected but declaration found" ); /* Check registers' validity. * Mark the registers as declared. */ file = decl->Declaration.File; if (!check_file_name( ctx, file )) return TRUE; for (i = decl->Range.First; i <= decl->Range.Last; i++) { /* declared TGSI_FILE_INPUT's for geometry and tessellation * have an implied second dimension */ uint processor = ctx->iter.processor.Processor; uint patch = decl->Semantic.Name == TGSI_SEMANTIC_PATCH || decl->Semantic.Name == TGSI_SEMANTIC_TESSOUTER || decl->Semantic.Name == TGSI_SEMANTIC_TESSINNER; if (file == TGSI_FILE_INPUT && !patch && ( processor == TGSI_PROCESSOR_GEOMETRY || processor == TGSI_PROCESSOR_TESS_CTRL || processor == TGSI_PROCESSOR_TESS_EVAL)) { uint vert; for (vert = 0; vert < ctx->implied_array_size; ++vert) { scan_register *reg = MALLOC(sizeof(scan_register)); fill_scan_register2d(reg, file, i, vert); check_and_declare(ctx, reg); } } else if (file == TGSI_FILE_OUTPUT && !patch && processor == TGSI_PROCESSOR_TESS_CTRL) { uint vert; for (vert = 0; vert < ctx->implied_out_array_size; ++vert) { scan_register *reg = MALLOC(sizeof(scan_register)); fill_scan_register2d(reg, file, i, vert); check_and_declare(ctx, reg); } } else { scan_register *reg = MALLOC(sizeof(scan_register)); if (decl->Declaration.Dimension) { fill_scan_register2d(reg, file, i, decl->Dim.Index2D); } else { fill_scan_register1d(reg, file, i); } check_and_declare(ctx, reg); } } return TRUE; }
static boolean check_register_usage( struct sanity_check_ctx *ctx, scan_register *reg, const char *name, boolean indirect_access ) { if (!check_file_name( ctx, reg->file )) { FREE(reg); return FALSE; } if (indirect_access) { /* Note that 'index' is an offset relative to the value of the * address register. No range checking done here.*/ reg->indices[0] = 0; reg->indices[1] = 0; if (!is_any_register_declared( ctx, reg->file )) report_error( ctx, "%s: Undeclared %s register", file_names[reg->file], name ); if (!is_ind_register_used(ctx, reg)) cso_hash_insert(ctx->regs_ind_used, reg->file, reg); else FREE(reg); } else { if (!is_register_declared( ctx, reg )) { if (reg->dimensions == 2) { report_error( ctx, "%s[%d][%d]: Undeclared %s register", file_names[reg->file], reg->indices[0], reg->indices[1], name ); } else { report_error( ctx, "%s[%d]: Undeclared %s register", file_names[reg->file], reg->indices[0], name ); } } if (!is_register_used( ctx, reg )) cso_hash_insert(ctx->regs_used, scan_register_key(reg), reg); else FREE(reg); } return TRUE; }
int report_data(void) { char filename[91]; FILE *fid; printf("Enter the file name for reporting statistics: "); gets(filename); printf("\n"); int error = check_file_name(filename); if (!error) { fid = fopen(filename, "r"); if (!fid) { // error in opening file printf( "Error in opening file %s: Check to make sure filename is correct and file exists.\n", filename); return FILE_ERROR; // a return here means we don't need an else clause } // Getting the data from the file. FileHeaderPtr fh_p = (FileHeaderPtr) malloc(sizeof(FileHeader)); get_file_header(fh_p, fid); char buffer[256]; printf("%s", to_string_file_header(fh_p, buffer)); fclose(fid); printf("\nReporting Statistics for %s", filename); printf("\nThe mean is: %f", fh_p->mean); printf("\nThe median is: %f", fh_p->median); printf("\nThe variance is: %f", fh_p->variance); printf("\nThe standard deviation is: %f\n", fh_p->std_dev); printf("Reporting Statistics complete. Closing %s\n", filename); free(fh_p); } return error; }
list<stack_line_info> get_stack_list(size_t maxDepth, size_t offset, bool module, bool symbolName) { assert(maxDepth <= 32); QWORD trace[33]; CONTEXT context; ::ZeroMemory(&context, sizeof(context)); context.ContextFlags = CONTEXT_FULL; #ifdef _WIN64 get_bp_sp_ip((void**)&context.Rbp, (void**)&context.Rsp, (void**)&context.Rip); #else get_bp_sp_ip((void**)&context.Ebp, (void**)&context.Esp, (void**)&context.Eip); #endif size_t depths = _stackwalk(trace, maxDepth+1, &context); list<stack_line_info> imageList; HANDLE hProcess = ::GetCurrentProcess(); for (size_t i = 1 + offset; i < depths; i++) { stack_line_info stackResult; { DWORD symbolDisplacement = 0; IMAGEHLP_LINE64 imageHelpLine; imageHelpLine.SizeOfStruct = sizeof(imageHelpLine); if (::SymGetLineFromAddr64(hProcess, trace[i], &symbolDisplacement, &imageHelpLine)) { stackResult.file = string(imageHelpLine.FileName, check_file_name(imageHelpLine.FileName)); memset(imageHelpLine.FileName, 0, stackResult.file.size() + 1); stackResult.line = (int)imageHelpLine.LineNumber; } else { stackResult.line = -1; } } if (symbolName) { static const int maxNameLength = 1024; char symbolBf[sizeof(IMAGEHLP_SYMBOL64)+maxNameLength] = { 0 }; PIMAGEHLP_SYMBOL64 symbol; DWORD64 symbolDisplacement64 = 0; symbol = (PIMAGEHLP_SYMBOL64)symbolBf; symbol->SizeOfStruct = sizeof(symbolBf); symbol->MaxNameLength = maxNameLength; if (::SymGetSymFromAddr64( hProcess, trace[i], &symbolDisplacement64, symbol) ) { stackResult.symbolName = symbol->Name; } else { stackResult.symbolName = "unknow..."; } } if (module) { IMAGEHLP_MODULE64 imageHelpModule; imageHelpModule.SizeOfStruct = sizeof(imageHelpModule); if (::SymGetModuleInfo64(hProcess, trace[i], &imageHelpModule)) { stackResult.module = string(imageHelpModule.ImageName, check_file_name(imageHelpModule.ImageName)); memset(imageHelpModule.ImageName, 0, stackResult.module.size() + 1); } } imageList.push_back(std::move(stackResult)); } return std::move(imageList); }
static std::list<stack_info> get_stack_list( void* bp, void* sp, void* ip, size_t max_depth, size_t offset, bool module, bool symbol, bool brief ) { QWORD trace[33]; CONTEXT context; ZeroMemory(&context, sizeof(context)); context.ContextFlags = CONTEXT_FULL; #ifdef _WIN64 context.Rbp = (DWORD64)bp; context.Rsp = (DWORD64)sp; context.Rip = (DWORD64)ip; #else context.Ebp = (DWORD)bp; context.Esp = (DWORD)sp; context.Eip = (DWORD)ip; #endif size_t depths = stack_walk(trace, max_depth, &context); std::list<stack_info> image_list; HANDLE hProcess = GetCurrentProcess(); for (size_t i = offset; i < depths; i++) { stack_info stack_result(brief); { DWORD symbolDisplacement = 0; IMAGEHLP_LINE64 imageHelpLine; imageHelpLine.SizeOfStruct = sizeof(imageHelpLine); if (SymGetLineFromAddr64(hProcess, trace[i], &symbolDisplacement, &imageHelpLine)) { stack_result.file_ = std::string(imageHelpLine.FileName, check_file_name(imageHelpLine.FileName)); std::memset(imageHelpLine.FileName, 0, stack_result.file_.size() + 1); stack_result.line_ = (int)imageHelpLine.LineNumber; } else { stack_result.line_ = -1; } } if (symbol) { static const int max_name_length = 1024; char symbolBf[sizeof(IMAGEHLP_SYMBOL64) + max_name_length] = { 0 }; PIMAGEHLP_SYMBOL64 symbol; DWORD64 symbolDisplacement64 = 0; symbol = (PIMAGEHLP_SYMBOL64)symbolBf; symbol->SizeOfStruct = sizeof(symbolBf); symbol->MaxNameLength = max_name_length; if (SymGetSymFromAddr64( hProcess, trace[i], &symbolDisplacement64, symbol) ) { stack_result.symbol_ = symbol->Name; } else { stack_result.symbol_ = "unknow..."; } } if (module) { IMAGEHLP_MODULE64 imageHelpModule; imageHelpModule.SizeOfStruct = sizeof(imageHelpModule); if (SymGetModuleInfo64(hProcess, trace[i], &imageHelpModule)) { stack_result.module_ = std::string(imageHelpModule.ImageName, check_file_name(imageHelpModule.ImageName)); std::memset(imageHelpModule.ImageName, 0, stack_result.module_.size() + 1); } } image_list.push_back(std::move(stack_result)); } return image_list; }
static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name) { int code; int wwid; char*path; char*mem_name; FILE*file; unsigned addr; s_vpi_value value; vpiHandle sys = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, sys); vpiHandle item = vpi_scan(argv); vpiHandle mitem; vpiHandle start_item; vpiHandle stop_item; vpiHandle left_range; vpiHandle right_range; vpiHandle word_index; /* These are left and right hand side parameters in the declaration of the memory. */ int left_addr, right_addr; /* start_addr and stop_addr are the parameters given to $readmem in the Verilog code. When not specified, start_addr is equal to the lower of the [left,right]_addr and stop_addr is equal to the higher of the [left,right]_addr. */ int start_addr, stop_addr, addr_incr; /* min_addr and max_addr are equal to start_addr and stop_addr if start_addr<stop_addr or vice versa if not... */ unsigned min_addr, max_addr; /* This is the number of words that we need from the memory. */ unsigned word_count; /*======================================== Get parameters */ if (item == 0) { vpi_printf("%s: file name parameter missing.\n", name); return 0; } /* Check then get the first argument, the file name. It is possible that Verilog would right-justify a name to fit a reg value to fit the reg width, so chop off leading white space in the process. */ if (check_file_name(name, item) == 0) { vpi_free_object(argv); return 0; } value.format = vpiStringVal; vpi_get_value(item, &value); path = strdup(value.value.str + strspn(value.value.str, " ")); /* Get and check the second parameter. It must be a memory. */ mitem = vpi_scan(argv); if (mitem == 0) { vpi_printf("%s: Missing memory parameter\n", name); free(path); return 0; } if (vpi_get(vpiType, mitem) != vpiMemory) { vpi_printf("%s: Second parameter must be a memory.\n", name); free(path); vpi_free_object(argv); return 0; } mem_name = vpi_get_str(vpiFullName, mitem); /* Get optional third parameter. It must be a constant. */ start_item = vpi_scan(argv); if (start_item!=0) { if (check_integer_constant(name, start_item) == 0) { vpi_free_object(argv); return 0; } /* Get optional forth parameter. It must be a constant. */ stop_item = vpi_scan(argv); if (stop_item!=0) { if (check_integer_constant(name, stop_item) == 0) { vpi_free_object(argv); return 0; } /* Check that there is no 5th parameter */ if (vpi_scan(argv) != 0) { vpi_printf("ERROR: %s accepts maximum 4 parameters!\n", name ); vpi_free_object(argv); return 0; } } } else { stop_item = 0; } /*======================================== Process parameters */ /* Open the data file. */ file = fopen(path, "r"); if (file == 0) { vpi_printf("%s: Unable to open %s for reading.\n", name, path); free(path); return 0; } /* Get left addr of memory */ left_range = vpi_handle(vpiLeftRange, mitem); value.format = vpiIntVal; vpi_get_value(left_range, &value); left_addr = value.value.integer; /* Get right addr of memory */ right_range = vpi_handle(vpiRightRange, mitem); value.format = vpiIntVal; vpi_get_value(right_range, &value); right_addr = value.value.integer; /* Get start_addr, stop_addr and addr_incr */ if (start_item==0) { start_addr = left_addr<right_addr ? left_addr : right_addr; stop_addr = left_addr<right_addr ? right_addr : left_addr; addr_incr = 1; } else { s_vpi_value value2; value2.format = vpiIntVal; vpi_get_value(start_item, &value2); start_addr = value2.value.integer; if (stop_item==0) { stop_addr = left_addr<right_addr ? right_addr : left_addr; addr_incr = 1; } else { s_vpi_value value3; value3.format = vpiIntVal; vpi_get_value(stop_item, &value3); stop_addr = value3.value.integer; addr_incr = start_addr<stop_addr ? 1 : -1; } } min_addr = start_addr<stop_addr ? start_addr : stop_addr ; max_addr = start_addr<stop_addr ? stop_addr : start_addr; /* We need this many words from the file. */ word_count = max_addr-min_addr+1; /* Check that start_addr and stop_addr are within the memory range */ if (left_addr<right_addr) { if (start_addr<left_addr || start_addr > right_addr) { vpi_printf("%s: Start address is out of bounds for memory \'%s\'!\n", name, mem_name); return 0; } if (stop_addr<left_addr || stop_addr > right_addr) { vpi_printf("%s: Stop address is out of bounds for memory \'%s\'!\n", name, mem_name); return 0; } } else { if (start_addr<right_addr || start_addr > left_addr) { vpi_printf("%s: Start address is out of bounds for memory \'%s\'!\n", name, mem_name); return 0; } if (stop_addr<right_addr || stop_addr > left_addr) { vpi_printf("%s: Stop address is out of bounds for memory \'%s\'!\n", name, mem_name); return 0; } } item = vpi_handle_by_index(mitem,min_addr); wwid = vpi_get(vpiSize, item); /* variable that will be uses by the lexer to pass values back to this code */ value.format = vpiVectorVal; value.value.vector = calloc((wwid+31)/32, sizeof(s_vpi_vecval)); /* Configure the readmem lexer */ if (strcmp(name,"$readmemb") == 0) sys_readmem_start_file(file, 1, wwid, value.value.vector); else sys_readmem_start_file(file, 0, wwid, value.value.vector); /*======================================== Read memory file */ /* Run through the input file and store the new contents in the memory */ addr = start_addr; while ((code = readmemlex()) != 0) { switch (code) { case MEM_ADDRESS: addr = value.value.vector->aval; /* if there is an address in the memory file, then turn off any possible warnings about not having enough words to load the memory. This is standard behavior. */ word_count = 0; break; case MEM_WORD: if (addr >= min_addr && addr <= max_addr) { word_index = vpi_handle_by_index(mitem, addr); assert(word_index); vpi_put_value(word_index, &value, 0, vpiNoDelay); if (word_count > 0) word_count -= 1; } else { vpi_printf("%s(%s): address (0x%x) out of range (0x%x:0x%x)\n", name, path, addr, start_addr, stop_addr); goto bailout; } addr += addr_incr; break; default: vpi_printf("Huh?! (%d)\n", code); break; } } if (word_count > 0) vpi_printf("%s(%s): Not enough words in the read file " "for requested range.\n", name, path); bailout: free(value.value.vector); free(path); fclose(file); return 0; }
// check profile line; if line == 0, this was generated from a command line option // return 1 if the command is to be added to the linked list of profile commands // return 0 if the command was already executed inside the function int profile_check_line(char *ptr, int lineno) { // seccomp, caps, private, user namespace if (strcmp(ptr, "noroot") == 0) { check_user_namespace(); return 0; } else if (strcmp(ptr, "seccomp") == 0) { arg_seccomp = 1; return 0; } else if (strcmp(ptr, "caps") == 0) { arg_caps_default_filter = 1; return 0; } else if (strcmp(ptr, "caps.drop all") == 0) { arg_caps_drop_all = 1; return 0; } else if (strcmp(ptr, "shell none") == 0) { arg_shell_none = 1; return 0; } else if (strcmp(ptr, "private") == 0) { arg_private = 1; return 0; } else if (strcmp(ptr, "private-dev") == 0) { arg_private_dev = 1; return 0; } else if (strcmp(ptr, "nogroups") == 0) { arg_nogroups = 1; return 0; } else if (strcmp(ptr, "netfilter") == 0) { arg_netfilter = 1; return 0; } else if (strncmp(ptr, "netfilter ", 10) == 0) { arg_netfilter = 1; arg_netfilter_file = strdup(ptr + 10); if (!arg_netfilter_file) errExit("strdup"); check_netfilter_file(arg_netfilter_file); return 0; } // seccomp drop list on top of default list if (strncmp(ptr, "seccomp ", 8) == 0) { arg_seccomp = 1; #ifdef HAVE_SECCOMP arg_seccomp_list = strdup(ptr + 8); if (!arg_seccomp_list) errExit("strdup"); #endif return 0; } // seccomp drop list without default list if (strncmp(ptr, "seccomp.drop ", 13) == 0) { arg_seccomp = 1; #ifdef HAVE_SECCOMP arg_seccomp_list_drop = strdup(ptr + 13); if (!arg_seccomp_list_drop) errExit("strdup"); #endif return 0; } // seccomp keep list if (strncmp(ptr, "seccomp.keep ", 13) == 0) { arg_seccomp = 1; #ifdef HAVE_SECCOMP arg_seccomp_list_keep= strdup(ptr + 13); if (!arg_seccomp_list_keep) errExit("strdup"); #endif return 0; } // caps drop list if (strncmp(ptr, "caps.drop ", 10) == 0) { arg_caps_drop = 1; arg_caps_list = strdup(ptr + 10); if (!arg_caps_list) errExit("strdup"); // verify seccomp list and exit if problems if (caps_check_list(arg_caps_list, NULL)) exit(1); return 0; } // caps keep list if (strncmp(ptr, "caps.keep ", 10) == 0) { arg_caps_keep = 1; arg_caps_list = strdup(ptr + 10); if (!arg_caps_list) errExit("strdup"); // verify seccomp list and exit if problems if (caps_check_list(arg_caps_list, NULL)) exit(1); return 0; } // dns if (strncmp(ptr, "dns ", 4) == 0) { uint32_t dns; if (atoip(ptr + 4, &dns)) { fprintf(stderr, "Error: invalid DNS server IP address\n"); return 1; } if (cfg.dns1 == 0) cfg.dns1 = dns; else if (cfg.dns2 == 0) cfg.dns2 = dns; else if (cfg.dns3 == 0) cfg.dns3 = dns; else { fprintf(stderr, "Error: up to 3 DNS servers can be specified\n"); return 1; } return 0; } // cpu affinity if (strncmp(ptr, "cpu ", 4) == 0) { read_cpu_list(ptr + 4); return 0; } // cgroup if (strncmp(ptr, "cgroup ", 7) == 0) { set_cgroup(ptr + 7); return 0; } // private directory if (strncmp(ptr, "private ", 8) == 0) { cfg.home_private = ptr + 8; fs_check_private_dir(); arg_private = 1; return 0; } // private list of files and directories if (strncmp(ptr, "private.keep ", 13) == 0) { cfg.home_private_keep = ptr + 13; fs_check_home_list(); arg_private = 1; return 0; } // filesystem bind if (strncmp(ptr, "bind ", 5) == 0) { if (getuid() != 0) { fprintf(stderr, "Error: --bind option is available only if running as root\n"); exit(1); } // extract two directories char *dname1 = ptr + 5; char *dname2 = split_comma(dname1); // this inserts a '0 to separate the two dierctories if (dname2 == NULL) { fprintf(stderr, "Error: mising second directory for bind\n"); exit(1); } // check directories check_file_name(dname1, lineno); check_file_name(dname2, lineno); if (strstr(dname1, "..") || strstr(dname2, "..")) { fprintf(stderr, "Error: invalid file name.\n"); exit(1); } // insert comma back *(dname2 - 1) = ','; return 1; } // rlimit if (strncmp(ptr, "rlimit", 6) == 0) { if (strncmp(ptr, "rlimit-nofile ", 14) == 0) { ptr += 14; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_nofile); arg_rlimit_nofile = 1; } else if (strncmp(ptr, "rlimit-nproc ", 13) == 0) { ptr += 13; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_nproc); arg_rlimit_nproc = 1; } else if (strncmp(ptr, "rlimit-fsize ", 13) == 0) { ptr += 13; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_fsize); arg_rlimit_fsize = 1; } else if (strncmp(ptr, "rlimit-sigpending ", 18) == 0) { ptr += 18; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_sigpending); arg_rlimit_sigpending = 1; } else { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } return 0; } // rest of filesystem if (strncmp(ptr, "blacklist ", 10) == 0) ptr += 10; else if (strncmp(ptr, "read-only ", 10) == 0) ptr += 10; else if (strncmp(ptr, "tmpfs ", 6) == 0) ptr += 6; else { if (lineno == 0) fprintf(stderr, "Error: \"%s\" as a command line option is invalid\n", ptr); else fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno); exit(1); } // some characters just don't belong in filenames check_file_name(ptr, lineno); if (strstr(ptr, "..")) { if (lineno == 0) fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); else fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno); exit(1); } return 1; }
// check profile line; if line == 0, this was generated from a command line option // return 1 if the command is to be added to the linked list of profile commands // return 0 if the command was already executed inside the function int profile_check_line(char *ptr, int lineno) { // seccomp, caps, private if (strcmp(ptr, "seccomp") == 0) { arg_seccomp = 1; return 0; } else if (strcmp(ptr, "caps") == 0) { arg_caps = 1; return 0; } else if (strcmp(ptr, "private") == 0) { arg_private = 1; return 0; } // seccomp list if (strncmp(ptr, "seccomp ", 8) == 0) { arg_seccomp = 1; #ifdef HAVE_SECCOMP arg_seccomp_list = strdup(ptr + 8); if (!arg_seccomp_list) errExit("strdup"); // verify seccomp list and exit if problems if (syscall_check_list(arg_seccomp_list, NULL)) exit(1); #endif return 0; } // private directory if (strncmp(ptr, "private ", 8) == 0) { cfg.home_private = ptr + 8; check_private_dir(); arg_private = 1; return 0; } // filesystem bind if (strncmp(ptr, "bind ", 5) == 0) { if (getuid() != 0) { fprintf(stderr, "Error: --bind option is available only if running as root\n"); exit(1); } // extract two directories char *dname1 = ptr + 5; char *dname2 = split_comma(dname1); // this inserts a '0 to separate the two dierctories if (dname2 == NULL) { fprintf(stderr, "Error: mising second directory for bind\n"); exit(1); } // check directories check_file_name(dname1, lineno); check_file_name(dname2, lineno); // insert comma back *(dname2 - 1) = ','; return 1; } // rlimit if (strncmp(ptr, "rlimit", 6) == 0) { if (strncmp(ptr, "rlimit-nofile ", 14) == 0) { ptr += 14; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_nofile); arg_rlimit_nofile = 1; } else if (strncmp(ptr, "rlimit-nproc ", 13) == 0) { ptr += 13; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_nproc); arg_rlimit_nproc = 1; } else if (strncmp(ptr, "rlimit-fsize ", 13) == 0) { ptr += 13; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_fsize); arg_rlimit_fsize = 1; } else if (strncmp(ptr, "rlimit-sigpending ", 18) == 0) { ptr += 18; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_sigpending); arg_rlimit_sigpending = 1; } else { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } return 0; } // rest of filesystem if (strncmp(ptr, "blacklist ", 10) == 0) ptr += 10; else if (strncmp(ptr, "read-only ", 10) == 0) ptr += 10; else if (strncmp(ptr, "tmpfs ", 6) == 0) ptr += 6; else { if (lineno == 0) fprintf(stderr, "Error: \"%s\" as a command line option is invalid\n", ptr); else fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno); exit(1); } // some characters just don't belong in filenames check_file_name(ptr, lineno); return 1; }