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; }
static int parse_components(context_t con, char **components) { components[COLOR_USER] = (char *)context_user_get(con); components[COLOR_ROLE] = (char *)context_role_get(con); components[COLOR_TYPE] = (char *)context_type_get(con); components[COLOR_RANGE] = (char *)context_range_get(con); return 0; }
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; }
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 SELinuxReserveSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainDefPtr def, pid_t pid) { security_context_t pctx; context_t ctx = NULL; const char *mcs; if (def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC) return 0; if (getpidcon(pid, &pctx) == -1) { virReportSystemError(errno, _("unable to get PID %d security context"), pid); return -1; } ctx = context_new(pctx); freecon(pctx); if (!ctx) goto err; mcs = context_range_get(ctx); if (!mcs) goto err; mcsAdd(mcs); context_free(ctx); return 0; err: context_free(ctx); return -1; }
static void disp_con(security_context_t scon) { context_t con = NULL; if (!*scon) { /* --self-exec and --self-fs etc. */ if (opts->disp_user) disp__con_val("user", NULL); if (opts->disp_role) disp__con_val("role", NULL); if (opts->disp_type) disp__con_val("type", NULL); if (opts->disp_sen) disp__con_val("sensitivity", NULL); if (opts->disp_clr) disp__con_val("clearance", NULL); if (opts->disp_mlsr) disp__con_val("mls-range", NULL); return; } if (!(con = context_new(scon))) errx(EXIT_FAILURE, "Couldn't create context from: %s", scon); if (opts->disp_user) disp__con_val("user", context_user_get(con)); if (opts->disp_role) disp__con_val("role", context_role_get(con)); if (opts->disp_type) disp__con_val("type", context_type_get(con)); if (opts->disp_sen) { const char *val = NULL; char *tmp = NULL; val = context_range_get(con); if (!val) val = ""; /* targeted has no "level" etc., any errors should happen at context_new() time */ tmp = strdup(val); if (!tmp) errx(EXIT_FAILURE, "Couldn't create context from: %s", scon); if (strchr(tmp, '-')) *strchr(tmp, '-') = 0; disp__con_val("sensitivity", tmp); free(tmp); } if (opts->disp_clr) { const char *val = NULL; char *tmp = NULL; val = context_range_get(con); if (!val) val = ""; /* targeted has no "level" etc., any errors should happen at context_new() time */ tmp = strdup(val); if (!tmp) errx(EXIT_FAILURE, "Couldn't create context from: %s", scon); if (strchr(tmp, '-')) disp__con_val("clearance", strchr(tmp, '-') + 1); else disp__con_val("clearance", tmp); free(tmp); } if (opts->disp_mlsr) disp__con_val("mls-range", context_range_get(con)); context_free(con); }
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; }
static int SELinuxGenSecurityLabel(virSecurityManagerPtr mgr, virDomainDefPtr def) { int rc = -1; char *mcs = NULL; char *scontext = NULL; int c1 = 0; int c2 = 0; context_t ctx = NULL; const char *range; virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr); VIR_DEBUG("SELinuxGenSecurityLabel %s", virSecurityManagerGetDriver(mgr)); if ((def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) && !def->seclabel.baselabel && def->seclabel.model) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("security model already defined for VM")); return rc; } if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC && def->seclabel.label) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("security label already defined for VM")); return rc; } if (def->seclabel.imagelabel) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("security image label already defined for VM")); return rc; } if (def->seclabel.model && STRNEQ(def->seclabel.model, SECURITY_SELINUX_NAME)) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("security label model %s is not supported with selinux"), def->seclabel.model); return rc; } VIR_DEBUG("SELinuxGenSecurityLabel %d", def->seclabel.type); switch (def->seclabel.type) { case VIR_DOMAIN_SECLABEL_STATIC: if (!(ctx = context_new(def->seclabel.label)) ) { virReportSystemError(errno, _("unable to allocate socket security context '%s'"), def->seclabel.label); return rc; } range = context_range_get(ctx); if (!range || !(mcs = strdup(range))) { virReportOOMError(); goto cleanup; } break; case VIR_DOMAIN_SECLABEL_DYNAMIC: do { c1 = virRandomBits(10); c2 = virRandomBits(10); if ( c1 == c2 ) { if (virAsprintf(&mcs, "s0:c%d", c1) < 0) { virReportOOMError(); goto cleanup; } } else { if (c1 > c2) { c1 ^= c2; c2 ^= c1; c1 ^= c2; } if (virAsprintf(&mcs, "s0:c%d,c%d", c1, c2) < 0) { virReportOOMError(); goto cleanup; } } } while (mcsAdd(mcs) == -1); def->seclabel.label = SELinuxGenNewContext(def->seclabel.baselabel ? def->seclabel.baselabel : data->domain_context, mcs); if (! def->seclabel.label) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("cannot generate selinux context for %s"), mcs); goto cleanup; } break; case VIR_DOMAIN_SECLABEL_NONE: /* no op */ break; default: virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("unexpected security label type '%s'"), virDomainSeclabelTypeToString(def->seclabel.type)); goto cleanup; } if (!def->seclabel.norelabel) { def->seclabel.imagelabel = SELinuxGenNewContext(data->file_context, mcs); if (!def->seclabel.imagelabel) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("cannot generate selinux context for %s"), mcs); goto cleanup; } } if (!def->seclabel.model && !(def->seclabel.model = strdup(SECURITY_SELINUX_NAME))) { virReportOOMError(); goto cleanup; } rc = 0; cleanup: if (rc != 0) { if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) VIR_FREE(def->seclabel.label); VIR_FREE(def->seclabel.imagelabel); if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC && !def->seclabel.baselabel) VIR_FREE(def->seclabel.model); } if (ctx) context_free(ctx); VIR_FREE(scontext); VIR_FREE(mcs); VIR_DEBUG("model=%s label=%s imagelabel=%s baselabel=%s", NULLSTR(def->seclabel.model), NULLSTR(def->seclabel.label), NULLSTR(def->seclabel.imagelabel), NULLSTR(def->seclabel.baselabel)); return rc; }
int main(int argc, char* argv[]) { int opt, option_index; int test_num = -1; int level = -1; context_t ctx = NULL; security_context_t ctx_check = NULL; char *path = NULL; char *log_path = NULL; time_t t; static struct option long_options[] = { {"output", required_argument, 0, 'o'}, {"test", required_argument, 0, 't'}, {"file", required_argument, 0, 'f'}, {0, 0, 0, 0} }; while ((opt = getopt_long(argc, argv, "o:t:f:", long_options, &option_index)) != -1) { switch (opt) { case 'o': log_path = optarg; if (freopen(log_path, "a+", stdout) == NULL) { exit(-1); } if (freopen(log_path, "a+", stderr) == NULL) { exit(-1); } break; case 't': test_num = atoi(optarg); break; case 'f': path = optarg; break; default: printf("bad argument.\n"); exit(-1); } } if (test_num == -1) { printf("no test specified.\n"); exit(-1); } else if (path == NULL) { printf("no path specified.\n"); exit(-1); } time(&t); printf("\n%s", ctime(&t)); getcon(&ctx_check); printf("Context: '%s'\n", ctx_check); ctx = context_new(ctx_check); const char *range = context_range_get(ctx); if (strncmp(LVL_HIGH"-", range, sizeof(LVL_HIGH"-")-1) == 0) { level = AT_HIGH; printf("process is at high\n"); } else if (strncmp(LVL_LOW"-", range, sizeof(LVL_LOW"-")-1) == 0) { level = AT_LOW; printf("process is at low\n"); } else { printf("unexpected level\n"); exit(-1); } fflush(stdout); fflush(stderr); switch(test_num) { case 1: read_low(level, path); break; case 2: read_high(level, path); break; case 3: write_low(level, path); break; case 4: write_high(level, path); break; default: printf("invalid test chosen\n"); exit(-1); break; } return 0; }
/* * 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 SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainObjPtr vm) { int rc = -1; char *mcs = NULL; char *scontext = NULL; int c1 = 0; int c2 = 0; context_t ctx = NULL; if ((vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) && !vm->def->seclabel.baselabel && vm->def->seclabel.model) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("security model already defined for VM")); return rc; } if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC && vm->def->seclabel.label) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("security label already defined for VM")); return rc; } if (vm->def->seclabel.imagelabel) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("security image label already defined for VM")); return rc; } if (vm->def->seclabel.model && STRNEQ(vm->def->seclabel.model, SECURITY_SELINUX_NAME)) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("security label model %s is not supported with selinux"), vm->def->seclabel.model); return rc; } if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC) { if (!(ctx = context_new(vm->def->seclabel.label)) ) { virReportSystemError(errno, _("unable to allocate socket security context '%s'"), vm->def->seclabel.label); return rc; } const char *range = context_range_get(ctx); if (!range || !(mcs = strdup(range))) { virReportOOMError(); goto cleanup; } } else { do { c1 = virRandom(1024); c2 = virRandom(1024); if ( c1 == c2 ) { if (virAsprintf(&mcs, "s0:c%d", c1) < 0) { virReportOOMError(); goto cleanup; } } else { if (c1 > c2) { c1 ^= c2; c2 ^= c1; c1 ^= c2; } if (virAsprintf(&mcs, "s0:c%d,c%d", c1, c2) < 0) { virReportOOMError(); goto cleanup; } } } while (mcsAdd(mcs) == -1); vm->def->seclabel.label = SELinuxGenNewContext(vm->def->seclabel.baselabel ? vm->def->seclabel.baselabel : default_domain_context, mcs); if (! vm->def->seclabel.label) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("cannot generate selinux context for %s"), mcs); goto cleanup; } } vm->def->seclabel.imagelabel = SELinuxGenNewContext(default_image_context, mcs); if (!vm->def->seclabel.imagelabel) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("cannot generate selinux context for %s"), mcs); goto cleanup; } if (!vm->def->seclabel.model && !(vm->def->seclabel.model = strdup(SECURITY_SELINUX_NAME))) { virReportOOMError(); goto cleanup; } rc = 0; cleanup: if (rc != 0) { if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) VIR_FREE(vm->def->seclabel.label); VIR_FREE(vm->def->seclabel.imagelabel); if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC && !vm->def->seclabel.baselabel) VIR_FREE(vm->def->seclabel.model); } if (ctx) context_free(ctx); VIR_FREE(scontext); VIR_FREE(mcs); VIR_DEBUG("model=%s label=%s imagelabel=%s baselabel=%s", NULLSTR(vm->def->seclabel.model), NULLSTR(vm->def->seclabel.label), NULLSTR(vm->def->seclabel.imagelabel), NULLSTR(vm->def->seclabel.baselabel)); return rc; }
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 bool testSELinuxCheckCon(context_t con, const char *user, const char *role, const char *type, int sensMin, int sensMax ATTRIBUTE_UNUSED, int catMin, int catMax) { const char *range; char *tmp; int gotSens; int gotCatOne; int gotCatTwo; if (STRNEQ(context_user_get(con), user)) { fprintf(stderr, "Expect user %s got %s\n", user, context_user_get(con)); return false; } if (STRNEQ(context_role_get(con), role)) { fprintf(stderr, "Expect role %s got %s\n", role, context_role_get(con)); return false; } if (STRNEQ(context_type_get(con), type)) { fprintf(stderr, "Expect type %s got %s\n", type, context_type_get(con)); return false; } range = context_range_get(con); if (range[0] != 's') { fprintf(stderr, "Malformed range %s, cannot find sensitivity\n", range); return false; } if (virStrToLong_i(range + 1, &tmp, 10, &gotSens) < 0 || !tmp) { fprintf(stderr, "Malformed range %s, cannot parse sensitivity\n", range + 1); return false; } if (*tmp != ':') { fprintf(stderr, "Malformed range %s, too many sensitivity values\n", tmp); return false; } tmp++; if (*tmp != 'c') { fprintf(stderr, "Malformed range %s, cannot find first category\n", tmp); return false; } tmp++; if (virStrToLong_i(tmp, &tmp, 10, &gotCatOne) < 0) { fprintf(stderr, "Malformed range %s, cannot parse category one\n", tmp); return false; } if (tmp && *tmp == ',') tmp++; if (tmp && *tmp == 'c') { tmp++; if (virStrToLong_i(tmp, &tmp, 10, &gotCatTwo) < 0) { fprintf(stderr, "Malformed range %s, cannot parse category two\n", tmp); return false; } if (*tmp != '\0') { fprintf(stderr, "Malformed range %s, junk after second category\n", tmp); return false; } if (gotCatOne == gotCatTwo) { fprintf(stderr, "Saw category pair %d,%d where cats were equal\n", gotCatOne, gotCatTwo); return false; } } else { gotCatTwo = gotCatOne; } if (gotSens != sensMin) { fprintf(stderr, "Sensitivity %d is not equal to min %d\n", gotSens, sensMin); return false; } if (gotCatOne < catMin || gotCatOne > catMax) { fprintf(stderr, "Category one %d is out of range %d-%d\n", gotCatTwo, catMin, catMax); return false; } if (gotCatTwo < catMin || gotCatTwo > catMax) { fprintf(stderr, "Category two %d is out of range %d-%d\n", gotCatTwo, catMin, catMax); return false; } if (gotCatOne > gotCatTwo) { fprintf(stderr, "Category one %d is greater than category two %d\n", gotCatOne, gotCatTwo); return false; } return true; }
static int seapp_context_lookup(enum seapp_kind kind, uid_t uid, int isSystemServer, const char *seinfo, const char *pkgname, context_t ctx) { const char *username = NULL; char *end = NULL; struct passwd *pw; struct seapp_context *cur; int i; size_t n; uid_t userid; uid_t appid; userid = uid / AID_USER; appid = uid % AID_USER; if (appid < AID_APP) { for (n = 0; n < android_id_count; n++) { if (android_ids[n].aid == appid) { username = android_ids[n].name; break; } } if (!username) goto err; } else if (appid < AID_ISOLATED_START) { username = "******"; appid -= AID_APP; } else { username = "******"; appid -= AID_ISOLATED_START; } if (appid >= CAT_MAPPING_MAX_ID || userid >= CAT_MAPPING_MAX_ID) goto err; for (i = 0; i < nspec; i++) { cur = seapp_contexts[i]; if (cur->isSystemServer != isSystemServer) continue; if (cur->user) { if (cur->prefix) { if (strncasecmp(username, cur->user, cur->len-1)) continue; } else { if (strcasecmp(username, cur->user)) continue; } } if (cur->seinfo) { if (!seinfo || strcasecmp(seinfo, cur->seinfo)) continue; } if (cur->name) { if (!pkgname || strcasecmp(pkgname, cur->name)) continue; } if (kind == SEAPP_TYPE && !cur->type) continue; else if (kind == SEAPP_DOMAIN && !cur->domain) continue; if (cur->sebool) { int value = security_get_boolean_active(cur->sebool); if (value == 0) continue; else if (value == -1) { selinux_log(SELINUX_ERROR, \ "Could not find boolean: %s ", cur->sebool); goto err; } } if (kind == SEAPP_TYPE) { if (context_type_set(ctx, cur->type)) goto oom; } else if (kind == SEAPP_DOMAIN) { if (context_type_set(ctx, cur->domain)) goto oom; } if (cur->levelFrom != LEVELFROM_NONE) { char level[255]; switch (cur->levelFrom) { case LEVELFROM_APP: snprintf(level, sizeof level, "%s:c%u,c%u", context_range_get(ctx), appid & 0xff, 256 + (appid>>8 & 0xff)); break; case LEVELFROM_USER: snprintf(level, sizeof level, "%s:c%u,c%u", context_range_get(ctx), 512 + (userid & 0xff), 768 + (userid>>8 & 0xff)); break; case LEVELFROM_ALL: snprintf(level, sizeof level, "%s:c%u,c%u,c%u,c%u", context_range_get(ctx), appid & 0xff, 256 + (appid>>8 & 0xff), 512 + (userid & 0xff), 768 + (userid>>8 & 0xff)); break; default: goto err; } if (context_range_set(ctx, level)) goto oom; } else if (cur->level) {