/* Set the context of all files associated with this VM to the new context * complete with the unique generated category. */ static int file_con_fixup (data_t *data) { security_context_t sec_con = { 0, }; context_t con = { 0, }; char mcs_str[9] = { 0, }; int ret = 0, p_ret = 0, i = 0;; p_ret = snprintf (mcs_str, sizeof (mcs_str), "s0:c%d", data->category); if (p_ret < 0 || p_ret > 9) { syslog (LOG_CRIT, "insufficient buffer size"); return -1; } for (i = 0; data->files [i] != NULL; ++i) { if (getfilecon (data->files [i], &sec_con) == -1) { syslog (LOG_CRIT, "error getting context from file: %s, error %s", data->files [i], strerror (errno)); continue; } con = context_new (sec_con); if (con == NULL) { syslog (LOG_CRIT, "Error creating new context from string: %s", sec_con); ret = -1; goto err_freecon; } if (context_range_set (con, mcs_str) == -1) { syslog (LOG_CRIT, "Error setting context range to %s, " "error: %s", mcs_str, strerror (errno)); ret = -1; goto err_confree; } syslog (LOG_INFO, "Setting context for file %s to %s", data->files [i], context_str (con)); ret = setfilecon (data->files [i], context_str (con)); if (ret != 0) syslog (LOG_CRIT, "setfilecon error:%s", strerror (errno)); context_free (con); freecon (sec_con); } return ret; err_confree: context_free (con); err_freecon: freecon (sec_con); return ret; }
int runcon_main(int argc UNUSED_PARAM, char **argv) { char *role = NULL; char *range = NULL; char *user = NULL; char *type = NULL; char *context = NULL; unsigned opts; context_t con; selinux_or_die(); #if ENABLE_FEATURE_RUNCON_LONG_OPTIONS applet_long_options = runcon_longopts; #endif opt_complementary = "-1"; opts = getopt32(argv, "r:t:u:l:ch", &role, &type, &user, &range); argv += optind; if (!(opts & OPTS_CONTEXT_COMPONENT)) { context = *argv++; if (!argv[0]) bb_error_msg_and_die("no command given"); } if (context) { con = context_new(context); if (!con) bb_error_msg_and_die("'%s' is not a valid context", context); } else { con = runcon_compute_new_context(user, role, type, range, argv[0], opts & OPTS_COMPUTE); } if (security_check_context(context_str(con))) bb_error_msg_and_die("'%s' is not a valid context", context_str(con)); if (setexeccon(context_str(con))) bb_error_msg_and_die("cannot set up security context '%s'", context_str(con)); execvp(argv[0], argv); bb_perror_msg_and_die("cannot execute '%s'", argv[0]); }
int runcon_main(int argc UNUSED_PARAM, char **argv) { char *role = NULL; char *range = NULL; char *user = NULL; char *type = NULL; char *context = NULL; unsigned opts; context_t con; selinux_or_die(); opts = getopt32long(argv, "^" "r:t:u:l:ch" "\0" "-1", runcon_longopts, &role, &type, &user, &range ); argv += optind; if (!(opts & OPTS_CONTEXT_COMPONENT)) { context = *argv++; if (!argv[0]) bb_error_msg_and_die("no command given"); } if (context) { con = context_new(context); if (!con) bb_error_msg_and_die("'%s' is not a valid context", context); } else { con = runcon_compute_new_context(user, role, type, range, argv[0], opts & OPTS_COMPUTE); } if (security_check_context(context_str(con))) bb_error_msg_and_die("'%s' is not a valid context", context_str(con)); if (setexeccon(context_str(con))) bb_error_msg_and_die("can't set up security context '%s'", context_str(con)); BB_EXECVP_or_die(argv); }
static int check_dominance(const char *pattern, const char *raw) { security_context_t ctx; context_t con; struct av_decision avd; int rc = -1; context_t my_tmp; const char *raw_range; security_class_t context_class = string_to_security_class("context"); access_vector_t context_contains_perm = string_to_av_perm(context_class, "contains"); con = context_new(raw); if (!con) return -1; raw_range = context_range_get(con); my_tmp = context_new(my_context); if (!my_tmp) { context_free(con); return -1; } ctx = NULL; if (context_range_set(my_tmp, pattern)) goto out; ctx = strdup(context_str(my_tmp)); if (!ctx) goto out; if (context_range_set(my_tmp, raw_range)) goto out; raw = context_str(my_tmp); if (!raw) goto out; rc = security_compute_av_raw(ctx, (security_context_t)raw, context_class, context_contains_perm, &avd); if (rc) goto out; rc = (context_contains_perm & avd.allowed) != context_contains_perm; out: free(ctx); context_free(my_tmp); context_free(con); return rc; }
/* This function takes a path and a mode, it calls computecon to get the label of the path object if the current process created it, then it calls matchpathcon to get the default type for the object. It substitutes the default type into label. It tells the SELinux Kernel to label all new file system objects created by the current process with this label. Returns -1 on failure. errno will be set appropriately. */ int defaultcon (char const *path, mode_t mode) { int rc = -1; char *scon = NULL; char *tcon = NULL; context_t scontext = 0, tcontext = 0; const char *contype; char *constr; char *newpath = NULL; if (! IS_ABSOLUTE_FILE_NAME (path)) { /* Generate absolute path as required by subsequent matchpathcon(), with libselinux < 2.1.5 2011-0826. */ newpath = canonicalize_filename_mode (path, CAN_MISSING); if (! newpath) error (EXIT_FAILURE, errno, _("error canonicalizing %s"), quote (path)); path = newpath; } if (matchpathcon (path, mode, &scon) < 0) { /* "No such file or directory" is a confusing error, when processing files, when in fact it was the associated default context that was not found. Therefore map the error to something more appropriate to the context in which we're using matchpathcon(). */ if (errno == ENOENT) errno = ENODATA; goto quit; } if (computecon (path, mode, &tcon) < 0) goto quit; if (!(scontext = context_new (scon))) goto quit; if (!(tcontext = context_new (tcon))) goto quit; if (!(contype = context_type_get (scontext))) goto quit; if (context_type_set (tcontext, contype)) goto quit; if (!(constr = context_str (tcontext))) goto quit; rc = setfscreatecon (constr); quit: context_free (scontext); context_free (tcontext); freecon (scon); freecon (tcon); free (newpath); return rc; }
static int mls_range_allowed(pam_handle_t *pamh, security_context_t src, security_context_t dst, int debug) { struct av_decision avd; int retval; unsigned int bit = CONTEXT__CONTAINS; context_t src_context = context_new (src); context_t dst_context = context_new (dst); context_range_set(dst_context, context_range_get(src_context)); if (debug) pam_syslog(pamh, LOG_NOTICE, "Checking if %s mls range valid for %s", dst, context_str(dst_context)); retval = security_compute_av(context_str(dst_context), dst, SECCLASS_CONTEXT, bit, &avd); context_free(src_context); context_free(dst_context); if (retval || ((bit & avd.allowed) != bit)) return 0; return 1; }
static int set_context_from_socket( const struct service_config *scp, int fd ) { security_context_t curr_context = NULL; security_context_t peer_context = NULL; security_context_t exec_context = NULL; context_t bcon = NULL; context_t pcon = NULL; security_context_t new_context = NULL; security_context_t new_exec_context = NULL; int retval = -1; const char *exepath = NULL; if (getcon(&curr_context) < 0) goto fail; if (getpeercon(fd, &peer_context) < 0) goto fail; exepath = SC_SERVER_ARGV( scp )[0]; if (getfilecon(exepath, &exec_context) < 0) goto fail; if (!(bcon = context_new(curr_context))) goto fail; if (!(pcon = context_new(peer_context))) goto fail; if (!context_range_get(pcon)) goto fail; if (context_range_set(bcon, context_range_get(pcon))) goto fail; if (!(new_context = context_str(bcon))) goto fail; if (security_compute_create(new_context, exec_context, SECCLASS_PROCESS, &new_exec_context) < 0) goto fail; retval = set_context(new_exec_context); freecon(new_exec_context); fail: context_free(pcon); context_free(bcon); freecon(exec_context); freecon(peer_context); freecon(curr_context); return retval; }
int main(int argc, char *argv[]) { security_context_t security_context; context_t context; pthread_t thread; int rc; if (argc != 2) { fprintf(stderr, "usage: %s <new domain>\n", argv[0]); return 1; } rc = getcon(&security_context); if (rc < 0) { fprintf(stderr, "%s: unable to get my context\n", argv[0]); return 1; } context = context_new(security_context); if (!context) { fprintf(stderr, "%s: unable to create context structure\n", argv[0]); return 1; } if (context_type_set(context, argv[1])) { fprintf(stderr, "%s: unable to set new type\n", argv[0]); return 1; } freecon(security_context); security_context = context_str(context); if (!security_context) { fprintf(stderr, "%s: unable to obtain new context string\n", argv[0]); return 1; } rc = pthread_create(&thread, NULL, worker, security_context); if (rc) { fprintf(stderr, "%s: unable to kick a new thread\n", argv[0]); return 1; } rc = pthread_join(thread, NULL); if (rc) { fprintf(stderr, "%s: unable to join its thread\n", argv[0]); return 1; } fprintf(stderr, "%s: setcon('%s') : %s\n", argv[0], argv[1], strerror(thread_status)); return thread_status; }
static char * SELinuxGenNewContext(const char *oldcontext, const char *mcs) { char *newcontext = NULL; char *scontext = strdup(oldcontext); context_t con; if (!scontext) goto err; con = context_new(scontext); if (!con) goto err; context_range_set(con, mcs); newcontext = strdup(context_str(con)); context_free(con); err: freecon(scontext); return newcontext; }
int main(int argc, char **argv) { int rc; security_context_t context_s; context_t context; if (argc != 2) { fprintf(stderr, "usage: %s newdomain\n", argv[0]); exit(-1); } rc = getcon(&context_s); if (rc < 0) { fprintf(stderr, "%s: unable to get my context\n", argv[0]); exit(-1); } context = context_new(context_s); if (!context) { fprintf(stderr, "%s: unable to create context structure\n", argv[0]); exit(-1); } if (context_type_set(context, argv[1])) { fprintf(stderr, "%s: unable to set new type\n", argv[0]); exit(-1); } freecon(context_s); context_s = context_str(context); if (!context_s) { fprintf(stderr, "%s: unable to obtain new context string\n", argv[0]); exit(-1); } rc = setcon(context_s); if (rc < 0) { perror("setcon failed"); exit(-1); } printf("All systems go\n"); exit(0); }
int get_default_context_with_rolelevel(const char *user, const char *role, const char *level, security_context_t fromcon, security_context_t * newcon) { int rc = 0; int freefrom = 0; context_t con; char *newfromcon; if (!level) return get_default_context_with_role(user, role, fromcon, newcon); if (!fromcon) { rc = getcon(&fromcon); if (rc < 0) return rc; freefrom = 1; } rc = -1; con = context_new(fromcon); if (!con) goto out; if (context_range_set(con, level)) goto out; newfromcon = context_str(con); if (!newfromcon) goto out; rc = get_default_context_with_role(user, role, newfromcon, newcon); out: context_free(con); if (freefrom) freecon(fromcon); return rc; }
/* Basic function to build string representation of context from * user:role:type component and sensitivity:category. * Returned string must be free'd by caller. */ static char* create_context (char *oldcontext, char *mcs) { char *newcontext = NULL, *scontext = NULL; context_t con = { 0, }; scontext = strdup(oldcontext); if (!scontext) return scontext; con = context_new(scontext); if (!con) { perror ("context_new"); return NULL; } context_range_set(con, mcs); newcontext = strdup(context_str(con)); context_free(con); return (newcontext); }
int get_ordered_context_list_with_level(const char *user, const char *level, security_context_t fromcon, security_context_t ** list) { int rc; int freefrom = 0; context_t con; char *newfromcon; if (!level) return get_ordered_context_list(user, fromcon, list); if (!fromcon) { rc = getcon(&fromcon); if (rc < 0) return rc; freefrom = 1; } rc = -1; con = context_new(fromcon); if (!con) goto out; if (context_range_set(con, level)) goto out; newfromcon = context_str(con); if (!newfromcon) goto out; rc = get_ordered_context_list(user, newfromcon, list); out: context_free(con); if (freefrom) freecon(fromcon); return rc; }
static void mkswap_selinux_setcontext(int fd, const char *path) { struct stat stbuf; if (!is_selinux_enabled()) return; if (fstat(fd, &stbuf) < 0) bb_perror_msg_and_die("fstat failed"); if (S_ISREG(stbuf.st_mode)) { security_context_t newcon; security_context_t oldcon = NULL; context_t context; if (fgetfilecon(fd, &oldcon) < 0) { if (errno != ENODATA) goto error; if (matchpathcon(path, stbuf.st_mode, &oldcon) < 0) goto error; } context = context_new(oldcon); if (!context || context_type_set(context, "swapfile_t")) goto error; newcon = context_str(context); if (!newcon) goto error; /* fsetfilecon_raw is hidden */ if (strcmp(oldcon, newcon) != 0 && fsetfilecon(fd, newcon) < 0) goto error; if (ENABLE_FEATURE_CLEAN_UP) { context_free(context); freecon(oldcon); } } return; error: bb_perror_msg_and_die("SELinux relabeling failed"); }
int main(int argc, char ** argv) { struct stat statbuf; struct swap_header_v1_2 *hdr; int i; unsigned long long maxpages; unsigned long long goodpages; unsigned long long sz; off_t offset; int force = 0; int version = 1; char *block_count = 0; char *pp; char *opt_label = NULL; unsigned char *uuid = NULL; #ifdef HAVE_LIBUUID const char *opt_uuid = NULL; uuid_t uuid_dat; #endif program_name = (argc && *argv) ? argv[0] : "mkswap"; if ((pp = strrchr(program_name, '/')) != NULL) program_name = pp+1; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); if (argc == 2 && (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) { printf(_("%s (%s)\n"), program_name, PACKAGE_STRING); exit(0); } for (i=1; i<argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'c': check=1; break; case 'f': force=1; break; case 'p': pp = argv[i]+2; if (!*pp && i+1 < argc) pp = argv[++i]; if (isnzdigit(*pp)) user_pagesize = atoi(pp); else usage(); break; case 'L': pp = argv[i]+2; if (!*pp && i+1 < argc) pp = argv[++i]; opt_label = pp; break; case 'v': version = atoi(argv[i]+2); break; case 'U': #ifdef HAVE_LIBUUID opt_uuid = argv[i]+2; if (!*opt_uuid && i+1 < argc) opt_uuid = argv[++i]; #else fprintf(stderr, _("%1$s: warning: ignore -U (UUIDs are unsupported by %1$s)\n"), program_name); #endif break; default: usage(); } } else if (!device_name) { device_name = argv[i]; } else if (!block_count) { block_count = argv[i]; } else usage(); } if (version != 1) { fprintf(stderr, _("%s: does not support swapspace version %d.\n"), program_name, version); exit(EXIT_FAILURE); } #ifdef HAVE_LIBUUID if(opt_uuid) { if (uuid_parse(opt_uuid, uuid_dat) != 0) die(_("error: UUID parsing failed")); } else uuid_generate(uuid_dat); uuid = uuid_dat; #endif init_signature_page(); /* get pagesize */ atexit(deinit_signature_page); if (!device_name) { fprintf(stderr, _("%s: error: Nowhere to set up swap on?\n"), program_name); usage(); } if (block_count) { /* this silly user specified the number of blocks explicitly */ char *tmp = NULL; long long blks; errno = 0; blks = strtoll(block_count, &tmp, 0); if ((tmp == block_count) || (tmp && *tmp) || (errno != 0 && (blks == LLONG_MAX || blks == LLONG_MIN)) || blks < 0) usage(); PAGES = blks / (pagesize / 1024); } sz = get_size(device_name); if (!PAGES) { PAGES = sz; } else if (PAGES > sz && !force) { fprintf(stderr, _("%s: error: " "size %llu KiB is larger than device size %llu KiB\n"), program_name, PAGES*(pagesize/1024), sz*(pagesize/1024)); exit(1); } if (PAGES < MIN_GOODPAGES) { fprintf(stderr, _("%s: error: swap area needs to be at least %ld KiB\n"), program_name, (long)(MIN_GOODPAGES * pagesize/1024)); usage(); } #ifdef __linux__ if (get_linux_version() >= KERNEL_VERSION(2,3,4)) maxpages = UINT_MAX + 1ULL; else if (get_linux_version() >= KERNEL_VERSION(2,2,1)) maxpages = V1_MAX_PAGES; else #endif maxpages = V1_OLD_MAX_PAGES; if (PAGES > maxpages) { PAGES = maxpages; fprintf(stderr, _("%s: warning: truncating swap area to %llu KiB\n"), program_name, PAGES * pagesize / 1024); } if (stat(device_name, &statbuf) < 0) { perror(device_name); exit(EXIT_FAILURE); } if (S_ISBLK(statbuf.st_mode)) DEV = open(device_name, O_RDWR | O_EXCL); else DEV = open(device_name, O_RDWR); if (DEV < 0) { perror(device_name); exit(1); } /* Want a block device. Probably not /dev/hda or /dev/hdb. */ if (!S_ISBLK(statbuf.st_mode)) check=0; else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) { fprintf(stderr, _("%s: error: " "will not try to make swapdevice on '%s'\n"), program_name, device_name); exit(1); } else if (check_mount()) { fprintf(stderr, _("%s: error: " "%s is mounted; will not make swapspace.\n"), program_name, device_name); exit(1); } if (check) check_blocks(); zap_bootbits(DEV, device_name, force, S_ISBLK(statbuf.st_mode)); hdr = (struct swap_header_v1_2 *) signature_page; hdr->version = 1; hdr->last_page = PAGES - 1; hdr->nr_badpages = badpages; if (badpages > PAGES - MIN_GOODPAGES) die(_("Unable to set up swap-space: unreadable")); goodpages = PAGES - badpages - 1; printf(_("Setting up swapspace version 1, size = %llu KiB\n"), goodpages * pagesize / 1024); write_signature("SWAPSPACE2"); write_uuid_and_label(uuid, opt_label); offset = 1024; if (lseek(DEV, offset, SEEK_SET) != offset) die(_("unable to rewind swap-device")); if (write_all(DEV, (char *) signature_page + offset, pagesize - offset) == -1) { fprintf(stderr, _("%s: %s: unable to write signature page: %s"), program_name, device_name, strerror(errno)); exit(1); } /* * A subsequent swapon() will fail if the signature * is not actually on disk. (This is a kernel bug.) */ #ifdef HAVE_FSYNC if (fsync(DEV)) die(_("fsync failed")); #endif #ifdef HAVE_LIBSELINUX if (S_ISREG(statbuf.st_mode) && is_selinux_enabled() > 0) { security_context_t context_string; security_context_t oldcontext; context_t newcontext; if (fgetfilecon(DEV, &oldcontext) < 0) { if (errno != ENODATA) { fprintf(stderr, _("%s: %s: unable to obtain selinux file label: %s\n"), program_name, device_name, strerror(errno)); exit(1); } if (matchpathcon(device_name, statbuf.st_mode, &oldcontext)) die(_("unable to matchpathcon()")); } if (!(newcontext = context_new(oldcontext))) die(_("unable to create new selinux context")); if (context_type_set(newcontext, SELINUX_SWAPFILE_TYPE)) die(_("couldn't compute selinux context")); context_string = context_str(newcontext); if (strcmp(context_string, oldcontext)!=0) { if (fsetfilecon(DEV, context_string)) { fprintf(stderr, _("%s: unable to relabel %s to %s: %s\n"), program_name, device_name, context_string, strerror(errno)); exit(1); } } context_free(newcontext); freecon(oldcontext); } #endif return 0; }
int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *exec_label, char **label) { int r = -EOPNOTSUPP; #ifdef HAVE_SELINUX _cleanup_freecon_ char *mycon = NULL, *peercon = NULL, *fcon = NULL; _cleanup_context_free_ context_t pcon = NULL, bcon = NULL; security_class_t sclass; const char *range = NULL; assert(socket_fd >= 0); assert(exe); assert(label); if (!mac_selinux_have()) return -EOPNOTSUPP; r = getcon_raw(&mycon); if (r < 0) return -errno; r = getpeercon_raw(socket_fd, &peercon); if (r < 0) return -errno; if (!exec_label) { /* If there is no context set for next exec let's use context of target executable */ r = getfilecon_raw(exe, &fcon); if (r < 0) return -errno; } bcon = context_new(mycon); if (!bcon) return -ENOMEM; pcon = context_new(peercon); if (!pcon) return -ENOMEM; range = context_range_get(pcon); if (!range) return -errno; r = context_range_set(bcon, range); if (r) return -errno; freecon(mycon); mycon = strdup(context_str(bcon)); if (!mycon) return -ENOMEM; sclass = string_to_security_class("process"); r = security_compute_create_raw(mycon, fcon, sclass, label); if (r < 0) return -errno; #endif return r; }
int main(int argc, char **argv) { int pid, rc, status; security_context_t context_s; context_t context; if (argc != 3) { fprintf(stderr, "usage: %s newdomain program\n", argv[0]); exit(-1); } rc = getcon(&context_s); if (rc < 0) { fprintf(stderr, "%s: unable to get my context\n", argv[0]); exit(-1); } context = context_new(context_s); if (!context) { fprintf(stderr, "%s: unable to create context structure\n", argv[0]); exit(-1); } if (context_type_set(context, argv[1])) { fprintf(stderr, "%s: unable to set new type\n", argv[0]); exit(-1); } freecon(context_s); context_s = context_str(context); if (!context_s) { fprintf(stderr, "%s: unable to obtain new context string\n", argv[0]); exit(-1); } rc = setexeccon(context_s); if (rc < 0) { fprintf(stderr, "%s: unable to set exec context to %s\n", argv[0], context_s); exit(-1); } pid = fork(); if (pid < 0) { perror("fork"); exit(-1); } else if (pid == 0) { rc = execv(argv[2], argv + 2); perror(argv[3]); exit(1); } pid = wait(&status); if (pid < 0) { perror("wait"); exit(1); } if (WIFEXITED(status)) { exit(WEXITSTATUS(status)); } exit(-1); }
int main(int argc, char **argv) { int pid, rc, len, status; security_context_t context_s; context_t context; if (argc != 3) { fprintf(stderr, "usage: %s newdomain program\n", argv[0]); exit(-1); } rc = getcon(&context_s); if (rc < 0) { fprintf(stderr, "%s: unable to get my context\n", argv[0]); exit(-1); } context = context_new(context_s); if (!context) { fprintf(stderr, "%s: unable to create context structure\n", argv[0]); exit(-1); } if (context_type_set(context, argv[1])) { fprintf(stderr, "%s: unable to set new type\n", argv[0]); exit(-1); } freecon(context_s); context_s = context_str(context); if (!context_s) { fprintf(stderr, "%s: unable to obtain new context string\n", argv[0]); exit(-1); } rc = setexeccon(context_s); if (rc < 0) { fprintf(stderr, "%s: unable to set exec context to %s\n", argv[0], context_s); exit(-1); } pid = fork(); if (pid < 0) { perror("fork"); exit(-1); } else if (pid == 0) { signal(SIGTRAP, SIG_IGN); rc = ptrace(PTRACE_TRACEME, 0, 0, 0); if (rc < 0) { perror("ptrace: PTRACE_TRACEME"); exit(-1); } execv(argv[2], argv+2); perror(argv[2]); exit(1); } repeat: pid = wait(&status); if (pid < 0) { perror("wait"); exit(-1); } if (WIFEXITED(status)) { fprintf(stderr, "Child exited with status %d.\n", WEXITSTATUS(status)); exit(WEXITSTATUS(status)); } if (WIFSTOPPED(status)) { fprintf(stderr, "Child stopped by signal %d.\n", WSTOPSIG(status)); rc = getpidcon(pid, &context_s); if (rc < 0) { perror("getpidcon"); exit(-1); } fprintf(stderr, "Child has context %s\n", context_s); fprintf(stderr, "..Resuming the child.\n"); rc = ptrace(PTRACE_CONT,pid,0,0); if (rc < 0){ perror("ptrace: PTRACE_CONT"); exit(-1); } goto repeat; } if (WIFSIGNALED(status)) { fprintf(stderr, "Child terminated by signal %d.\n", WTERMSIG(status)); fprintf(stderr, "..This is consistent with a ptrace permission denial - check the audit message.\n"); exit(1); } fprintf(stderr, "Unexpected exit status 0x%x\n", status); exit(-1); }
int main(int argc, char **argv) { struct stat statbuf; struct swap_header_v1_2 *hdr; int c; unsigned long long maxpages; unsigned long long goodpages; unsigned long long sz; off_t offset; int force = 0; int version = 1; char *block_count = 0; char *opt_label = NULL; unsigned char *uuid = NULL; #ifdef HAVE_LIBUUID const char *opt_uuid = NULL; uuid_t uuid_dat; #endif static const struct option longopts[] = { { "check", no_argument, 0, 'c' }, { "force", no_argument, 0, 'f' }, { "pagesize", required_argument, 0, 'p' }, { "label", required_argument, 0, 'L' }, { "swapversion", required_argument, 0, 'v' }, { "uuid", required_argument, 0, 'U' }, { "version", no_argument, 0, 'V' }, { "help", no_argument, 0, 'h' }, { NULL, 0, 0, 0 } }; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); atexit(close_stdout); while((c = getopt_long(argc, argv, "cfp:L:v:U:Vh", longopts, NULL)) != -1) { switch (c) { case 'c': check=1; break; case 'f': force=1; break; case 'p': user_pagesize = strtou32_or_err(optarg, _("parsing page size failed")); break; case 'L': opt_label = optarg; break; case 'v': version = strtos32_or_err(optarg, _("parsing version number failed")); break; case 'U': #ifdef HAVE_LIBUUID opt_uuid = optarg; #else warnx(_("warning: ignoring -U (UUIDs are unsupported by %s)"), program_invocation_short_name); #endif break; case 'V': printf(UTIL_LINUX_VERSION); exit(EXIT_SUCCESS); case 'h': usage(stdout); default: usage(stderr); } } if (optind < argc) device_name = argv[optind++]; if (optind < argc) block_count = argv[optind++]; if (optind != argc) { warnx(_("only one device argument is currently supported")); usage(stderr); } if (version != 1) errx(EXIT_FAILURE, _("swapspace version %d is not supported"), version); #ifdef HAVE_LIBUUID if(opt_uuid) { if (uuid_parse(opt_uuid, uuid_dat) != 0) errx(EXIT_FAILURE, _("error: parsing UUID failed")); } else uuid_generate(uuid_dat); uuid = uuid_dat; #endif init_signature_page(); /* get pagesize */ if (!device_name) { warnx(_("error: Nowhere to set up swap on?")); usage(stderr); } if (block_count) { /* this silly user specified the number of blocks explicitly */ uint64_t blks = strtou64_or_err(block_count, _("invalid block count argument")); PAGES = blks / (pagesize / 1024); } sz = get_size(device_name); if (!PAGES) PAGES = sz; else if (PAGES > sz && !force) { errx(EXIT_FAILURE, _("error: " "size %llu KiB is larger than device size %llu KiB"), PAGES*(pagesize/1024), sz*(pagesize/1024)); } if (PAGES < MIN_GOODPAGES) { warnx(_("error: swap area needs to be at least %ld KiB"), (long)(MIN_GOODPAGES * pagesize/1024)); usage(stderr); } #ifdef __linux__ if (get_linux_version() >= KERNEL_VERSION(2,3,4)) maxpages = UINT_MAX + 1ULL; else if (get_linux_version() >= KERNEL_VERSION(2,2,1)) maxpages = V1_MAX_PAGES; else #endif maxpages = V1_OLD_MAX_PAGES; if (PAGES > maxpages) { PAGES = maxpages; warnx(_("warning: truncating swap area to %llu KiB"), PAGES * pagesize / 1024); } if (is_mounted(device_name)) errx(EXIT_FAILURE, _("error: " "%s is mounted; will not make swapspace"), device_name); if (stat(device_name, &statbuf) < 0) { perror(device_name); exit(EXIT_FAILURE); } if (S_ISBLK(statbuf.st_mode)) DEV = open(device_name, O_RDWR | O_EXCL); else DEV = open(device_name, O_RDWR); if (DEV < 0) { perror(device_name); exit(EXIT_FAILURE); } if (!S_ISBLK(statbuf.st_mode)) check=0; else if (blkdev_is_misaligned(DEV)) warnx(_("warning: %s is misaligned"), device_name); if (check) check_blocks(); wipe_device(DEV, device_name, force); hdr = (struct swap_header_v1_2 *) signature_page; hdr->version = 1; hdr->last_page = PAGES - 1; hdr->nr_badpages = badpages; if (badpages > PAGES - MIN_GOODPAGES) errx(EXIT_FAILURE, _("Unable to set up swap-space: unreadable")); goodpages = PAGES - badpages - 1; printf(_("Setting up swapspace version 1, size = %llu KiB\n"), goodpages * pagesize / 1024); write_signature("SWAPSPACE2"); write_uuid_and_label(uuid, opt_label); offset = 1024; if (lseek(DEV, offset, SEEK_SET) != offset) errx(EXIT_FAILURE, _("unable to rewind swap-device")); if (write_all(DEV, (char *) signature_page + offset, pagesize - offset) == -1) err(EXIT_FAILURE, _("%s: unable to write signature page"), device_name); #ifdef HAVE_LIBSELINUX if (S_ISREG(statbuf.st_mode) && is_selinux_enabled() > 0) { security_context_t context_string; security_context_t oldcontext; context_t newcontext; if (fgetfilecon(DEV, &oldcontext) < 0) { if (errno != ENODATA) err(EXIT_FAILURE, _("%s: unable to obtain selinux file label"), device_name); if (matchpathcon(device_name, statbuf.st_mode, &oldcontext)) errx(EXIT_FAILURE, _("unable to matchpathcon()")); } if (!(newcontext = context_new(oldcontext))) errx(EXIT_FAILURE, _("unable to create new selinux context")); if (context_type_set(newcontext, SELINUX_SWAPFILE_TYPE)) errx(EXIT_FAILURE, _("couldn't compute selinux context")); context_string = context_str(newcontext); if (strcmp(context_string, oldcontext)!=0) { if (fsetfilecon(DEV, context_string)) err(EXIT_FAILURE, _("unable to relabel %s to %s"), device_name, context_string); } context_free(newcontext); freecon(oldcontext); } #endif /* * A subsequent swapon() will fail if the signature * is not actually on disk. (This is a kernel bug.) * The fsync() in close_fd() will take care of writing. */ if (close_fd(DEV) != 0) err(EXIT_FAILURE, _("write failed")); return EXIT_SUCCESS; }
int main(int argc, char **argv) { int pid, rc, status, cloneflags; security_context_t context_s; context_t context; if (argc != 4) { fprintf(stderr, "usage: %s cloneflags newdomain program\n", argv[0]); exit(-1); } cloneflags = strtol(argv[1], NULL, 0); if (!cloneflags) { fprintf(stderr, "invalid clone flags %s\n", argv[1]); exit(-1); } rc = getcon(&context_s); if (rc < 0) { fprintf(stderr, "%s: unable to get my context\n", argv[0]); exit(-1); } context = context_new(context_s); if (!context) { fprintf(stderr, "%s: unable to create context structure\n", argv[0]); exit(-1); } if (context_type_set(context, argv[2])) { fprintf(stderr, "%s: unable to set new type\n", argv[0]); exit(-1); } freecon(context_s); context_s = context_str(context); if (!context_s) { fprintf(stderr, "%s: unable to obtain new context string\n", argv[0]); exit(-1); } rc = setexeccon(context_s); if (rc < 0) { fprintf(stderr, "%s: unable to set exec context to %s\n", argv[0], context_s); exit(-1); } pid = ltp_clone_quick(cloneflags | SIGCHLD, clone_fn, argv); if (pid < 0) { perror("clone"); exit(-1); } pid = wait(&status); if (pid < 0) { perror("wait"); exit(-1); } if (WIFEXITED(status)) { fprintf(stderr, "Child exited with status %d.\n", WEXITSTATUS(status)); exit(WEXITSTATUS(status)); } if (WIFSTOPPED(status)) { fprintf(stderr, "Child stopped by signal %d.\n", WSTOPSIG(status)); fprintf(stderr, "..This shouldn't happen.\n"); fprintf(stderr, "..Killing the child.\n"); rc = kill(pid,SIGKILL); if (rc < 0) { perror("kill"); exit(-1); } exit(-1); } if (WIFSIGNALED(status)) { fprintf(stderr, "Child terminated by signal %d.\n", WTERMSIG(status)); fprintf(stderr, "..This is consistent with a share permission denial, check the audit message.\n"); exit(1); } fprintf(stderr, "Unexpected exit status 0x%x\n", status); exit(-1); }
static security_context_t context_from_env (pam_handle_t *pamh, security_context_t defaultcon, int env_params, int use_current_range, int debug) { security_context_t newcon = NULL; context_t new_context; context_t my_context = NULL; int mls_enabled = is_selinux_mls_enabled(); const char *env = NULL; char *type = NULL; if ((new_context = context_new(defaultcon)) == NULL) goto fail_set; if (env_params && (env = pam_getenv(pamh, "SELINUX_ROLE_REQUESTED")) != NULL && env[0] != '\0') { if (debug) pam_syslog(pamh, LOG_NOTICE, "Requested role: %s", env); if (get_default_type(env, &type)) { pam_syslog(pamh, LOG_NOTICE, "No default type for role %s", env); goto fail_set; } else { if (context_role_set(new_context, env)) goto fail_set; if (context_type_set(new_context, type)) goto fail_set; } } if (mls_enabled) { if ((env = pam_getenv(pamh, "SELINUX_USE_CURRENT_RANGE")) != NULL && env[0] == '1') { if (debug) pam_syslog(pamh, LOG_NOTICE, "SELINUX_USE_CURRENT_RANGE is set"); use_current_range = 1; } if (use_current_range) { security_context_t mycon = NULL; if (getcon(&mycon) != 0) goto fail_set; my_context = context_new(mycon); if (my_context == NULL) { freecon(mycon); goto fail_set; } freecon(mycon); env = context_range_get(my_context); } else { env = pam_getenv(pamh, "SELINUX_LEVEL_REQUESTED"); } if (env != NULL && env[0] != '\0') { if (debug) pam_syslog(pamh, LOG_NOTICE, "Requested level: %s", env); if (context_range_set(new_context, env)) goto fail_set; } } newcon = strdup(context_str(new_context)); if (newcon == NULL) goto fail_set; if (debug) pam_syslog(pamh, LOG_NOTICE, "Selected Security Context %s", newcon); /* Get the string value of the context and see if it is valid. */ if (security_check_context(newcon)) { pam_syslog(pamh, LOG_NOTICE, "Not a valid security context %s", newcon); send_audit_message(pamh, 0, defaultcon, newcon); freecon(newcon); newcon = NULL; goto fail_set; } /* we have to check that this user is allowed to go into the range they have specified ... role is tied to an seuser, so that'll be checked at setexeccon time */ if (mls_enabled && !mls_range_allowed(pamh, defaultcon, newcon, debug)) { pam_syslog(pamh, LOG_NOTICE, "Security context %s is not allowed for %s", defaultcon, newcon); send_audit_message(pamh, 0, defaultcon, newcon); freecon(newcon); newcon = NULL; } fail_set: free(type); context_free(my_context); context_free(new_context); send_audit_message(pamh, 0, defaultcon, NULL); return newcon; }
static security_context_t config_context (pam_handle_t *pamh, security_context_t defaultcon, int use_current_range, int debug) { security_context_t newcon=NULL; context_t new_context; int mls_enabled = is_selinux_mls_enabled(); char *response=NULL; char *type=NULL; char resp_val = 0; pam_prompt (pamh, PAM_TEXT_INFO, NULL, _("Default Security Context %s\n"), defaultcon); while (1) { if (query_response(pamh, _("Would you like to enter a different role or level?"), "n", &response, debug) == PAM_SUCCESS) { resp_val = response[0]; _pam_drop(response); } else { resp_val = 'N'; } if ((resp_val == 'y') || (resp_val == 'Y')) { if ((new_context = context_new(defaultcon)) == NULL) goto fail_set; /* Allow the user to enter role and level individually */ if (query_response(pamh, _("role:"), context_role_get(new_context), &response, debug) == PAM_SUCCESS && response[0]) { if (get_default_type(response, &type)) { pam_prompt (pamh, PAM_ERROR_MSG, NULL, _("No default type for role %s\n"), response); _pam_drop(response); continue; } else { if (context_role_set(new_context, response)) goto fail_set; if (context_type_set (new_context, type)) goto fail_set; } } _pam_drop(response); if (mls_enabled) { if (use_current_range) { security_context_t mycon = NULL; context_t my_context; if (getcon(&mycon) != 0) goto fail_set; my_context = context_new(mycon); if (my_context == NULL) { freecon(mycon); goto fail_set; } freecon(mycon); if (context_range_set(new_context, context_range_get(my_context))) { context_free(my_context); goto fail_set; } context_free(my_context); } else if (query_response(pamh, _("level:"), context_range_get(new_context), &response, debug) == PAM_SUCCESS && response[0]) { if (context_range_set(new_context, response)) goto fail_set; } _pam_drop(response); } if (debug) pam_syslog(pamh, LOG_NOTICE, "Selected Security Context %s", context_str(new_context)); /* Get the string value of the context and see if it is valid. */ if (!security_check_context(context_str(new_context))) { newcon = strdup(context_str(new_context)); if (newcon == NULL) goto fail_set; context_free(new_context); /* we have to check that this user is allowed to go into the range they have specified ... role is tied to an seuser, so that'll be checked at setexeccon time */ if (mls_enabled && !mls_range_allowed(pamh, defaultcon, newcon, debug)) { pam_syslog(pamh, LOG_NOTICE, "Security context %s is not allowed for %s", defaultcon, newcon); send_audit_message(pamh, 0, defaultcon, newcon); free(newcon); goto fail_range; } return newcon; } else { send_audit_message(pamh, 0, defaultcon, context_str(new_context)); send_text(pamh,_("Not a valid security context"),debug); } context_free(new_context); /* next time around allocates another */ } else return strdup(defaultcon); } /* end while */ return NULL; fail_set: free(type); _pam_drop(response); context_free (new_context); send_audit_message(pamh, 0, defaultcon, NULL); fail_range: return NULL; }
static security_context_t manual_context (pam_handle_t *pamh, const char *user, int debug) { security_context_t newcon=NULL; context_t new_context; int mls_enabled = is_selinux_mls_enabled(); char *type=NULL; char *response=NULL; while (1) { if (query_response(pamh, _("Would you like to enter a security context? [N] "), NULL, &response, debug) != PAM_SUCCESS) return NULL; if ((response[0] == 'y') || (response[0] == 'Y')) { if (mls_enabled) new_context = context_new ("user:role:type:level"); else new_context = context_new ("user:role:type"); if (!new_context) goto fail_set; if (context_user_set (new_context, user)) goto fail_set; _pam_drop(response); /* Allow the user to enter each field of the context individually */ if (query_response(pamh, _("role:"), NULL, &response, debug) == PAM_SUCCESS && response[0] != '\0') { if (context_role_set (new_context, response)) goto fail_set; if (get_default_type(response, &type)) goto fail_set; if (context_type_set (new_context, type)) goto fail_set; } _pam_drop(response); if (mls_enabled) { if (query_response(pamh, _("level:"), NULL, &response, debug) == PAM_SUCCESS && response[0] != '\0') { if (context_range_set (new_context, response)) goto fail_set; } _pam_drop(response); } /* Get the string value of the context and see if it is valid. */ if (!security_check_context(context_str(new_context))) { newcon = strdup(context_str(new_context)); context_free (new_context); return newcon; } else send_text(pamh,_("Not a valid security context"),debug); context_free (new_context); } else { _pam_drop(response); return NULL; } } /* end while */ fail_set: free(type); _pam_drop(response); context_free (new_context); return NULL; }
int main(int argc, char **argv) { char buf[1]; int pid, rc, rc2, fd[2], fd2[2]; security_context_t context_s; context_t context; if (argc != 3) { fprintf(stderr, "usage: %s newdomain program\n", argv[0]); exit(-1); } rc = getcon(&context_s); if (rc < 0) { fprintf(stderr, "%s: unable to get my context\n", argv[0]); exit(-1); } context = context_new(context_s); if (!context) { fprintf(stderr, "%s: unable to create context structure\n", argv[0]); exit(-1); } if (context_type_set(context, argv[1])) { fprintf(stderr, "%s: unable to set new type\n", argv[0]); exit(-1); } freecon(context_s); context_s = context_str(context); if (!context_s) { fprintf(stderr, "%s: unable to obtain new context string\n", argv[0]); exit(-1); } rc = setexeccon(context_s); if (rc < 0) { fprintf(stderr, "%s: unable to set exec context to %s\n", argv[0], context_s); exit(-1); } rc = pipe(fd); if (rc < 0) { perror("pipe"); exit(-1); } rc = pipe(fd2); if (rc < 0) { perror("pipe"); exit(-1); } pid = fork(); if (pid < 0) { perror("fork"); exit(-1); } else if (pid == 0) { dup2(fd[0],0); dup2(fd2[1],1); execv(argv[2], argv+2); buf[0] = -1; if (write(1, buf, sizeof(buf)) < 0) { perror(argv[2]); } exit(-1); } rc = read(fd2[0], buf, sizeof(buf)); if (rc < 0) { perror("read"); exit(-1); } if (buf[0]) { fprintf(stderr, "%s: child died unexpectedly\n", argv[0]); exit(-1); } rc = setpriority(0,pid,10); rc2 = write(fd[1], buf, sizeof(buf)); if (rc2 < 0) { perror("write"); exit(-1); } if (rc < 0) { perror("setnice: setnice(pid,pid)"); exit(1); } exit(0); }
int main(int argc, char **argv) { struct mkswap_control ctl = { .fd = -1 }; int c; uint64_t sz; int version = SWAP_VERSION; char *block_count = NULL, *strsz = NULL; #ifdef HAVE_LIBUUID const char *opt_uuid = NULL; uuid_t uuid_dat; #endif static const struct option longopts[] = { { "check", no_argument, 0, 'c' }, { "force", no_argument, 0, 'f' }, { "pagesize", required_argument, 0, 'p' }, { "label", required_argument, 0, 'L' }, { "swapversion", required_argument, 0, 'v' }, { "uuid", required_argument, 0, 'U' }, { "version", no_argument, 0, 'V' }, { "help", no_argument, 0, 'h' }, { NULL, 0, 0, 0 } }; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); atexit(close_stdout); while((c = getopt_long(argc, argv, "cfp:L:v:U:Vh", longopts, NULL)) != -1) { switch (c) { case 'c': ctl.check = 1; break; case 'f': ctl.force = 1; break; case 'p': ctl.user_pagesize = strtou32_or_err(optarg, _("parsing page size failed")); break; case 'L': ctl.opt_label = optarg; break; case 'v': version = strtos32_or_err(optarg, _("parsing version number failed")); if (version != SWAP_VERSION) errx(EXIT_FAILURE, _("swapspace version %d is not supported"), version); break; case 'U': #ifdef HAVE_LIBUUID opt_uuid = optarg; #else warnx(_("warning: ignoring -U (UUIDs are unsupported by %s)"), program_invocation_short_name); #endif break; case 'V': printf(UTIL_LINUX_VERSION); exit(EXIT_SUCCESS); case 'h': usage(stdout); default: usage(stderr); } } if (optind < argc) ctl.devname = argv[optind++]; if (optind < argc) block_count = argv[optind++]; if (optind != argc) { warnx(_("only one device argument is currently supported")); usage(stderr); } #ifdef HAVE_LIBUUID if(opt_uuid) { if (uuid_parse(opt_uuid, uuid_dat) != 0) errx(EXIT_FAILURE, _("error: parsing UUID failed")); } else uuid_generate(uuid_dat); ctl.uuid = uuid_dat; #endif init_signature_page(&ctl); /* get pagesize and allocate signature page */ if (!ctl.devname) { warnx(_("error: Nowhere to set up swap on?")); usage(stderr); } if (block_count) { /* this silly user specified the number of blocks explicitly */ uint64_t blks = strtou64_or_err(block_count, _("invalid block count argument")); ctl.npages = blks / (ctl.pagesize / 1024); } sz = get_size(&ctl); if (!ctl.npages) ctl.npages = sz; else if (ctl.npages > sz && !ctl.force) errx(EXIT_FAILURE, _("error: " "size %llu KiB is larger than device size %ju KiB"), ctl.npages * (ctl.pagesize / 1024), sz * (ctl.pagesize / 1024)); if (ctl.npages < MIN_GOODPAGES) errx(EXIT_FAILURE, _("error: swap area needs to be at least %ld KiB"), (long)(MIN_GOODPAGES * ctl.pagesize / 1024)); if (ctl.npages > UINT32_MAX) { /* true when swap is bigger than 17.59 terabytes */ ctl.npages = UINT32_MAX; warnx(_("warning: truncating swap area to %llu KiB"), ctl.npages * ctl.pagesize / 1024); } if (is_mounted(ctl.devname)) errx(EXIT_FAILURE, _("error: " "%s is mounted; will not make swapspace"), ctl.devname); open_device(&ctl); if (ctl.check) check_blocks(&ctl); wipe_device(&ctl); assert(ctl.hdr); ctl.hdr->version = version; ctl.hdr->last_page = ctl.npages - 1; ctl.hdr->nr_badpages = ctl.nbadpages; if ((ctl.npages - MIN_GOODPAGES) < ctl.nbadpages) errx(EXIT_FAILURE, _("Unable to set up swap-space: unreadable")); sz = (ctl.npages - ctl.nbadpages - 1) * ctl.pagesize; strsz = size_to_human_string(SIZE_SUFFIX_SPACE | SIZE_SUFFIX_3LETTER, sz); printf(_("Setting up swapspace version %d, size = %s (%ju bytes)\n"), version, strsz, sz); free(strsz); set_signature(&ctl); set_uuid_and_label(&ctl); write_header_to_device(&ctl); deinit_signature_page(&ctl); #ifdef HAVE_LIBSELINUX if (S_ISREG(ctl.devstat.st_mode) && is_selinux_enabled() > 0) { security_context_t context_string; security_context_t oldcontext; context_t newcontext; if (fgetfilecon(ctl.fd, &oldcontext) < 0) { if (errno != ENODATA) err(EXIT_FAILURE, _("%s: unable to obtain selinux file label"), ctl.devname); if (matchpathcon(ctl.devname, ctl.devstat.st_mode, &oldcontext)) errx(EXIT_FAILURE, _("unable to matchpathcon()")); } if (!(newcontext = context_new(oldcontext))) errx(EXIT_FAILURE, _("unable to create new selinux context")); if (context_type_set(newcontext, SELINUX_SWAPFILE_TYPE)) errx(EXIT_FAILURE, _("couldn't compute selinux context")); context_string = context_str(newcontext); if (strcmp(context_string, oldcontext)!=0) { if (fsetfilecon(ctl.fd, context_string)) err(EXIT_FAILURE, _("unable to relabel %s to %s"), ctl.devname, context_string); } context_free(newcontext); freecon(oldcontext); } #endif /* * A subsequent swapon() will fail if the signature * is not actually on disk. (This is a kernel bug.) * The fsync() in close_fd() will take care of writing. */ if (close_fd(ctl.fd) != 0) err(EXIT_FAILURE, _("write failed")); return EXIT_SUCCESS; }
/* This function takes a PATH of an existing file system object, and a LOCAL boolean that indicates whether the function should set the object's label to the default for the local process, or one using system wide settings. If LOCAL == true, it will ask the SELinux Kernel what the default label for all objects created should be and then sets the label on the object. Otherwise it calls matchpathcon on the object to ask the system what the default label should be, extracts the type field and then modifies the file system object. Note only the type field is updated, thus preserving MLS levels and user identity etc. of the PATH. Returns -1 on failure. errno will be set appropriately. */ static int restorecon_private (char const *path, bool local) { int rc = -1; struct stat sb; char *scon = NULL; char *tcon = NULL; context_t scontext = 0, tcontext = 0; const char *contype; char *constr; int fd; if (local) { if (getfscreatecon (&tcon) < 0) return rc; if (!tcon) { errno = ENODATA; return rc; } rc = lsetfilecon (path, tcon); freecon (tcon); return rc; } fd = open (path, O_RDONLY | O_NOFOLLOW); if (fd == -1 && (errno != ELOOP)) goto quit; if (fd != -1) { if (fstat (fd, &sb) < 0) goto quit; } else { if (lstat (path, &sb) < 0) goto quit; } if (matchpathcon (path, sb.st_mode, &scon) < 0) { /* "No such file or directory" is a confusing error, when processing files, when in fact it was the associated default context that was not found. Therefore map the error to something more appropriate to the context in which we're using matchpathcon(). */ if (errno == ENOENT) errno = ENODATA; goto quit; } if (!(scontext = context_new (scon))) goto quit; if (fd != -1) { if (fgetfilecon (fd, &tcon) < 0) goto quit; } else { if (lgetfilecon (path, &tcon) < 0) goto quit; } if (!(tcontext = context_new (tcon))) goto quit; if (!(contype = context_type_get (scontext))) goto quit; if (context_type_set (tcontext, contype)) goto quit; if (!(constr = context_str (tcontext))) goto quit; if (fd != -1) rc = fsetfilecon (fd, constr); else rc = lsetfilecon (path, constr); quit: if (fd != -1) close (fd); context_free (scontext); context_free (tcontext); freecon (scon); freecon (tcon); return rc; }
static int change_filedir_context(const char *fname, struct stat *stbuf, void *userData, int depth) { context_t context = NULL; security_context_t file_context = NULL; security_context_t context_string; int rc = FALSE; int status = 0; if (option_mask32 & OPT_NODEREFERENCE) { status = lgetfilecon(fname, &file_context); } else { status = getfilecon(fname, &file_context); } if (status < 0 && errno != ENODATA) { if ((option_mask32 & OPT_QUIET) == 0) bb_error_msg("cannot obtain security context: %s", fname); goto skip; } if (file_context == NULL && specified_context == NULL) { bb_error_msg("cannot apply partial context to unlabeled file %s", fname); goto skip; } if (specified_context == NULL) { context = set_security_context_component(file_context, user, role, type, range); if (!context) { bb_error_msg("cannot compute security context from %s", file_context); goto skip; } } else { context = context_new(specified_context); if (!context) { bb_error_msg("invalid context: %s", specified_context); goto skip; } } context_string = context_str(context); if (!context_string) { bb_error_msg("cannot obtain security context in text expression"); goto skip; } if (file_context == NULL || strcmp(context_string, file_context) != 0) { int fail; if (option_mask32 & OPT_NODEREFERENCE) { fail = lsetfilecon(fname, context_string); } else { fail = setfilecon(fname, context_string); } if ((option_mask32 & OPT_VERBOSE) || ((option_mask32 & OPT_CHANHES) && !fail)) { printf(!fail ? "context of %s changed to %s\n" : "failed to change context of %s to %s\n", fname, context_string); } if (!fail) { rc = TRUE; } else if ((option_mask32 & OPT_QUIET) == 0) { bb_error_msg("failed to change context of %s to %s", fname, context_string); } } else if (option_mask32 & OPT_VERBOSE) { printf("context of %s retained as %s\n", fname, context_string); rc = TRUE; } skip: context_free(context); freecon(file_context); return rc; }
/* * do_set_domain * It tries to replace the domain/range of the current context. */ static int do_set_domain(security_context_t old_context, char *domain, server_rec *s) { security_context_t new_context; security_context_t raw_context; context_t context; char *range; /* * Compute the new security context */ context = context_new(old_context); if (!context) { ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "SELinux: context_new(\"%s\") failed", old_context); return -1; } range = strchr(domain, ':'); if (range) *range++ = '\0'; if (domain && strcmp(domain, "*") != 0) context_type_set(context, domain); if (range && strcmp(range, "*") != 0) context_range_set(context, range); if (range) *--range = ':'; /* fixup */ new_context = context_str(context); if (!new_context) { ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "SELinux: context_str(\"%s:%s:%s:%s\") failed", context_user_get(context), context_role_get(context), context_type_get(context), context_range_get(context)); context_free(context); return -1; } /* * If old_context == new_context, we don't need to do anything */ if (selinux_trans_to_raw_context(new_context, &raw_context) < 0) { ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "SELinux: selinux_trans_to_raw_context(\"%s\") failed", new_context); context_free(context); return -1; } context_free(context); if (!strcmp(old_context, raw_context)) { freecon(raw_context); return 1; } if (setcon_raw(raw_context) < 0) { ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "SELinux: setcon_raw(\"%s\") failed", raw_context); freecon(raw_context); return -1; } freecon(raw_context); return 0; }
static int change_file_context(const char *file, unsigned long opts) { security_context_t file_context = NULL; security_context_t context_string; context_t context; int errors = 0; int status = 0; if (opts & OPT_CHCON_NODEREFERENCE) { status = lgetfilecon(file, &file_context); } else { status = getfilecon(file, &file_context); } if (status < 0 && errno != ENODATA) { if ((opts & OPT_CHCON_QUIET) == 0) fprintf(stderr, "could not obtain security context: %s\n", file); return 1; } if (file_context == NULL && specified_context == NULL) { fprintf(stderr, "can't apply partial context to unlabeled file %s", file); return 1; } if (specified_context == NULL) { context = compute_context_from_mask(file_context, opts); if (!context) { fprintf(stderr, "couldn't compute security context from %s", file_context); return 1; } } else { context = context_new(specified_context); if (!context) { fprintf(stderr, "invalid context: %s", specified_context); return 1; } } context_string = context_str(context); if (file_context == NULL || strcmp(context_string, file_context)!=0) { int fail = 0; if (opts & OPT_CHCON_NODEREFERENCE) { fail = lsetfilecon (file, context_string); } else { fail = setfilecon (file, context_string); } if ((opts & OPT_CHCON_VERBOSE) || ((opts & OPT_CHCON_CHANHES) && !fail)) { printf(!fail ? "context of %s changed to %s\n" : "failed to change context of %s to %s\n", file, context_string); } if (fail) { errors = 1; if ((opts & OPT_CHCON_QUIET) == 0) fprintf(stderr, "failed to change context of %s to %s\n", file, context_string); } } else if (opts & OPT_CHCON_VERBOSE) { printf("context of %s retained as %s\n", file, context_string); } context_free(context); freecon(file_context); if (opts & OPT_CHCON_RECURSIVE) { struct stat file_stats; if (lstat(file, &file_stats) == 0 && S_ISDIR(file_stats.st_mode)) errors |= change_dir_context(file, opts); } return errors; }
/* * Returns a new security context based on the old context and the * specified role and type. */ security_context_t get_exec_context(security_context_t old_context, const char *role, const char *type) { security_context_t new_context = NULL; context_t context = NULL; char *typebuf = NULL; debug_decl(get_exec_context, SUDO_DEBUG_SELINUX) /* We must have a role, the type is optional (we can use the default). */ if (!role) { sudo_warnx(U_("you must specify a role for type %s"), type); errno = EINVAL; goto bad; } if (!type) { if (get_default_type(role, &typebuf)) { sudo_warnx(U_("unable to get default type for role %s"), role); errno = EINVAL; goto bad; } type = typebuf; } /* * Expand old_context into a context_t so that we extract and modify * its components easily. */ context = context_new(old_context); /* * Replace the role and type in "context" with the role and * type we will be running the command as. */ if (context_role_set(context, role)) { sudo_warn(U_("failed to set new role %s"), role); goto bad; } if (context_type_set(context, type)) { sudo_warn(U_("failed to set new type %s"), type); goto bad; } /* * Convert "context" back into a string and verify it. */ if ((new_context = strdup(context_str(context))) == NULL) { sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); goto bad; } if (security_check_context(new_context) < 0) { sudo_warnx(U_("%s is not a valid context"), new_context); errno = EINVAL; goto bad; } #ifdef DEBUG sudo_warnx("Your new context is %s", new_context); #endif context_free(context); debug_return_ptr(new_context); bad: free(typebuf); context_free(context); freecon(new_context); debug_return_ptr(NULL); }