📄 services.c
字号:
rc = mls_context_to_sid(oldc, &p, &context); if (rc) goto out_unlock; if ((p - scontext2) < scontext_len) { rc = -EINVAL; goto out_unlock; } /* Check the validity of the new context. */ if (!policydb_context_isvalid(&policydb, &context)) { rc = -EINVAL; goto out_unlock; } /* Obtain the new sid. */ rc = sidtab_context_to_sid(&sidtab, &context, sid);out_unlock: POLICY_RDUNLOCK; context_destroy(&context); kfree(scontext2);out: return rc;}static int compute_sid_handle_invalid_context( struct context *scontext, struct context *tcontext, u16 tclass, struct context *newcontext){ char *s = NULL, *t = NULL, *n = NULL; u32 slen, tlen, nlen; if (context_struct_to_string(scontext, &s, &slen) < 0) goto out; if (context_struct_to_string(tcontext, &t, &tlen) < 0) goto out; if (context_struct_to_string(newcontext, &n, &nlen) < 0) goto out; audit_log(current->audit_context, "security_compute_sid: invalid context %s" " for scontext=%s" " tcontext=%s" " tclass=%s", n, s, t, policydb.p_class_val_to_name[tclass-1]);out: kfree(s); kfree(t); kfree(n); if (!selinux_enforcing) return 0; return -EACCES;}static int security_compute_sid(u32 ssid, u32 tsid, u16 tclass, u32 specified, u32 *out_sid){ struct context *scontext = NULL, *tcontext = NULL, newcontext; struct role_trans *roletr = NULL; struct avtab_key avkey; struct avtab_datum *avdatum; struct avtab_node *node; unsigned int type_change = 0; int rc = 0; if (!ss_initialized) { switch (tclass) { case SECCLASS_PROCESS: *out_sid = ssid; break; default: *out_sid = tsid; break; } goto out; } POLICY_RDLOCK; scontext = sidtab_search(&sidtab, ssid); if (!scontext) { printk(KERN_ERR "security_compute_sid: unrecognized SID %d\n", ssid); rc = -EINVAL; goto out_unlock; } tcontext = sidtab_search(&sidtab, tsid); if (!tcontext) { printk(KERN_ERR "security_compute_sid: unrecognized SID %d\n", tsid); rc = -EINVAL; goto out_unlock; } context_init(&newcontext); /* Set the user identity. */ switch (specified) { case AVTAB_TRANSITION: case AVTAB_CHANGE: /* Use the process user identity. */ newcontext.user = scontext->user; break; case AVTAB_MEMBER: /* Use the related object owner. */ newcontext.user = tcontext->user; break; } /* Set the role and type to default values. */ switch (tclass) { case SECCLASS_PROCESS: /* Use the current role and type of process. */ newcontext.role = scontext->role; newcontext.type = scontext->type; break; default: /* Use the well-defined object role. */ newcontext.role = OBJECT_R_VAL; /* Use the type of the related object. */ newcontext.type = tcontext->type; } /* Look for a type transition/member/change rule. */ avkey.source_type = scontext->type; avkey.target_type = tcontext->type; avkey.target_class = tclass; avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_TYPE); /* If no permanent rule, also check for enabled conditional rules */ if(!avdatum) { node = avtab_search_node(&policydb.te_cond_avtab, &avkey, specified); for (; node != NULL; node = avtab_search_node_next(node, specified)) { if (node->datum.specified & AVTAB_ENABLED) { avdatum = &node->datum; break; } } } type_change = (avdatum && (avdatum->specified & specified)); if (type_change) { /* Use the type from the type transition/member/change rule. */ switch (specified) { case AVTAB_TRANSITION: newcontext.type = avtab_transition(avdatum); break; case AVTAB_MEMBER: newcontext.type = avtab_member(avdatum); break; case AVTAB_CHANGE: newcontext.type = avtab_change(avdatum); break; } } /* Check for class-specific changes. */ switch (tclass) { case SECCLASS_PROCESS: if (specified & AVTAB_TRANSITION) { /* Look for a role transition rule. */ for (roletr = policydb.role_tr; roletr; roletr = roletr->next) { if (roletr->role == scontext->role && roletr->type == tcontext->type) { /* Use the role transition rule. */ newcontext.role = roletr->new_role; break; } } } if (!type_change && !roletr) { /* No change in process role or type. */ *out_sid = ssid; goto out_unlock; } break; default: if (!type_change && (newcontext.user == tcontext->user) && mls_context_cmp(scontext, tcontext)) { /* No change in object type, owner, or MLS attributes. */ *out_sid = tsid; goto out_unlock; } break; } /* Set the MLS attributes. This is done last because it may allocate memory. */ rc = mls_compute_sid(scontext, tcontext, tclass, specified, &newcontext); if (rc) goto out_unlock; /* Check the validity of the context. */ if (!policydb_context_isvalid(&policydb, &newcontext)) { rc = compute_sid_handle_invalid_context(scontext, tcontext, tclass, &newcontext); if (rc) goto out_unlock; } /* Obtain the sid for the context. */ rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid);out_unlock: POLICY_RDUNLOCK; context_destroy(&newcontext);out: return rc;}/** * security_transition_sid - Compute the SID for a new subject/object. * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class * @out_sid: security identifier for new subject/object * * Compute a SID to use for labeling a new subject or object in the * class @tclass based on a SID pair (@ssid, @tsid). * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM * if insufficient memory is available, or %0 if the new SID was * computed successfully. */int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid){ return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, out_sid);}/** * security_member_sid - Compute the SID for member selection. * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class * @out_sid: security identifier for selected member * * Compute a SID to use when selecting a member of a polyinstantiated * object of class @tclass based on a SID pair (@ssid, @tsid). * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM * if insufficient memory is available, or %0 if the SID was * computed successfully. */int security_member_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid){ return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid);}/** * security_change_sid - Compute the SID for object relabeling. * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class * @out_sid: security identifier for selected member * * Compute a SID to use for relabeling an object of class @tclass * based on a SID pair (@ssid, @tsid). * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM * if insufficient memory is available, or %0 if the SID was * computed successfully. */int security_change_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid){ return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid);}/* * Verify that each permission that is defined under the * existing policy is still defined with the same value * in the new policy. */static int validate_perm(void *key, void *datum, void *p){ struct hashtab *h; struct perm_datum *perdatum, *perdatum2; int rc = 0; h = p; perdatum = datum; perdatum2 = hashtab_search(h, key); if (!perdatum2) { printk(KERN_ERR "security: permission %s disappeared", (char *)key); rc = -ENOENT; goto out; } if (perdatum->value != perdatum2->value) { printk(KERN_ERR "security: the value of permission %s changed", (char *)key); rc = -EINVAL; }out: return rc;}/* * Verify that each class that is defined under the * existing policy is still defined with the same * attributes in the new policy. */static int validate_class(void *key, void *datum, void *p){ struct policydb *newp; struct class_datum *cladatum, *cladatum2; int rc; newp = p; cladatum = datum; cladatum2 = hashtab_search(newp->p_classes.table, key); if (!cladatum2) { printk(KERN_ERR "security: class %s disappeared\n", (char *)key); rc = -ENOENT; goto out; } if (cladatum->value != cladatum2->value) { printk(KERN_ERR "security: the value of class %s changed\n", (char *)key); rc = -EINVAL; goto out; } if ((cladatum->comdatum && !cladatum2->comdatum) || (!cladatum->comdatum && cladatum2->comdatum)) { printk(KERN_ERR "security: the inherits clause for the access " "vector definition for class %s changed\n", (char *)key); rc = -EINVAL; goto out; } if (cladatum->comdatum) { rc = hashtab_map(cladatum->comdatum->permissions.table, validate_perm, cladatum2->comdatum->permissions.table); if (rc) { printk(" in the access vector definition for class " "%s\n", (char *)key); goto out; } } rc = hashtab_map(cladatum->permissions.table, validate_perm, cladatum2->permissions.table); if (rc) printk(" in access vector definition for class %s\n", (char *)key);out: return rc;}/* Clone the SID into the new SID table. */static int clone_sid(u32 sid, struct context *context, void *arg){ struct sidtab *s = arg; return sidtab_insert(s, sid, context);}static inline int convert_context_handle_invalid_context(struct context *context){ int rc = 0; if (selinux_enforcing) { rc = -EINVAL; } else { char *s; u32 len; context_struct_to_string(context, &s, &len); printk(KERN_ERR "security: context %s is invalid\n", s); kfree(s); } return rc;}struct convert_context_args { struct policydb *oldp; struct policydb *newp;};/* * Convert the values in the security context * structure `c' from the values specified * in the policy `p->oldp' to the values specified * in the policy `p->newp'. Verify that the * context is valid under the new policy. */static int convert_context(u32 key, struct context *c, void *p){ struct convert_context_args *args; struct context oldc; struct role_datum *role; struct type_datum *typdatum; struct user_datum *usrdatum; char *s; u32 len; int rc; args = p; rc = context_cpy(&oldc, c); if (rc) goto out; rc = -EINVAL; /* Convert the user. */ usrdatum = hashtab_search(args->newp->p_users.table, args->oldp->p_user_val_to_name[c->user - 1]); if (!usrdatum) { goto bad; } c->user = usrdatum->value; /* Convert the role. */ role = hashtab_search(args->newp->p_roles.table, args->oldp->p_role_val_to_name[c->role - 1]); if (!role) { goto bad; } c->role = role->value; /* Convert the type. */ typdatum = hashtab_search(args->newp->p_types.table, args->oldp->p_type_val_to_name[c->type - 1]); if (!typdatum) { goto bad; } c->type = typdatum->value; rc = mls_convert_context(args->oldp, args->newp, c); if (rc) goto bad; /* Check the validity of the new context. */ if (!policydb_context_isvalid(args->newp, c)) { rc = convert_context_handle_invalid_context(&oldc); if (rc) goto bad; } context_destroy(&oldc);out: return rc;bad: context_struct_to_string(&oldc, &s, &len); context_destroy(&oldc); printk(KERN_ERR "security: invalidating context %s\n", s); kfree(s); goto out;}extern void selinux_complete_init(void);/** * security_load_policy - Load a security policy configuration. * @data: binary policy data * @len: length of data in bytes * * Load a new set of security policy configuration data, * validate it and convert the SID table as necessary. * This function will flush the access vector cache after * loading the new policy. */int security_load_policy(void *data, size_t len){ struct policydb oldpolicydb, newpolicydb; struct sidtab oldsidtab, newsidtab; struct convert_context_args args; u32 seqno; int rc = 0; struct policy_file file = { data, len }, *fp = &file; LOAD_LOCK; if (!ss_initialized) { if (policydb_read(&policydb, fp)) { LOAD_UNLOCK; return -EINVAL; } if (policydb_load_isids(&policydb, &sidtab)) { LOAD_UNLOCK; policydb_destroy(&policydb); return -EINVAL; } ss_initialized = 1; LOAD_UNLOCK; selinux_complete_init(); return 0; }#if 0 sidtab_hash_eval(&sidtab, "sids");#endif if (policydb_read(&newpolicydb, fp)) { LOAD_UNLOCK; return -EINVAL; } sidtab_init(&newsidtab); /* Verify that the existing classes did not change. */ if (hashtab_map(policydb.p_classes.table, validate_class, &newpolicydb)) { printk(KERN_ERR "security: the definition of an existing " "class changed\n"); rc = -EINVAL; goto err; } /* Clone the SID table. */ sidtab_shutdown(&sidtab); if (sidtab_map(&sidtab, clone_sid, &newsidtab)) { rc = -ENOMEM; goto err; } /* Convert the internal representations of contexts in the new SID table and remove invalid SIDs. */ args.oldp = &policydb; args.newp = &newpolicydb; sidtab_map_remove_on_error(&newsidtab, convert_context, &args);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -