📄 services.c
字号:
mysids = kcalloc(maxnel, sizeof(*mysids), GFP_ATOMIC); if (!mysids) { rc = -ENOMEM; goto out_unlock; } ebitmap_for_each_bit(&user->roles, rnode, i) { if (!ebitmap_node_get_bit(rnode, i)) continue; role = policydb.role_val_to_struct[i]; usercon.role = i+1; ebitmap_for_each_bit(&role->types, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; usercon.type = j+1; if (mls_setup_user_range(fromcon, user, &usercon)) continue; rc = context_struct_compute_av(fromcon, &usercon, SECCLASS_PROCESS, PROCESS__TRANSITION, &avd); if (rc || !(avd.allowed & PROCESS__TRANSITION)) continue; rc = sidtab_context_to_sid(&sidtab, &usercon, &sid); if (rc) { kfree(mysids); goto out_unlock; } if (mynel < maxnel) { mysids[mynel++] = sid; } else { maxnel += SIDS_NEL; mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC); if (!mysids2) { rc = -ENOMEM; kfree(mysids); goto out_unlock; } memcpy(mysids2, mysids, mynel * sizeof(*mysids2)); kfree(mysids); mysids = mysids2; mysids[mynel++] = sid; } } } *sids = mysids; *nel = mynel;out_unlock: POLICY_RDUNLOCK;out: return rc;}/** * security_genfs_sid - Obtain a SID for a file in a filesystem * @fstype: filesystem type * @path: path from root of mount * @sclass: file security class * @sid: SID for path * * Obtain a SID to use for a file in a filesystem that * cannot support xattr or use a fixed labeling behavior like * transition SIDs or task SIDs. */int security_genfs_sid(const char *fstype, char *path, u16 sclass, u32 *sid){ int len; struct genfs *genfs; struct ocontext *c; int rc = 0, cmp = 0; POLICY_RDLOCK; for (genfs = policydb.genfs; genfs; genfs = genfs->next) { cmp = strcmp(fstype, genfs->fstype); if (cmp <= 0) break; } if (!genfs || cmp) { *sid = SECINITSID_UNLABELED; rc = -ENOENT; goto out; } for (c = genfs->head; c; c = c->next) { len = strlen(c->u.name); if ((!c->v.sclass || sclass == c->v.sclass) && (strncmp(c->u.name, path, len) == 0)) break; } if (!c) { *sid = SECINITSID_UNLABELED; rc = -ENOENT; goto out; } if (!c->sid[0]) { rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]); if (rc) goto out; } *sid = c->sid[0];out: POLICY_RDUNLOCK; return rc;}/** * security_fs_use - Determine how to handle labeling for a filesystem. * @fstype: filesystem type * @behavior: labeling behavior * @sid: SID for filesystem (superblock) */int security_fs_use( const char *fstype, unsigned int *behavior, u32 *sid){ int rc = 0; struct ocontext *c; POLICY_RDLOCK; c = policydb.ocontexts[OCON_FSUSE]; while (c) { if (strcmp(fstype, c->u.name) == 0) break; c = c->next; } if (c) { *behavior = c->v.behavior; if (!c->sid[0]) { rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]); if (rc) goto out; } *sid = c->sid[0]; } else { rc = security_genfs_sid(fstype, "/", SECCLASS_DIR, sid); if (rc) { *behavior = SECURITY_FS_USE_NONE; rc = 0; } else { *behavior = SECURITY_FS_USE_GENFS; } }out: POLICY_RDUNLOCK; return rc;}int security_get_bools(int *len, char ***names, int **values){ int i, rc = -ENOMEM; POLICY_RDLOCK; *names = NULL; *values = NULL; *len = policydb.p_bools.nprim; if (!*len) { rc = 0; goto out; } *names = kcalloc(*len, sizeof(char*), GFP_ATOMIC); if (!*names) goto err; *values = kcalloc(*len, sizeof(int), GFP_ATOMIC); if (!*values) goto err; for (i = 0; i < *len; i++) { size_t name_len; (*values)[i] = policydb.bool_val_to_struct[i]->state; name_len = strlen(policydb.p_bool_val_to_name[i]) + 1; (*names)[i] = kmalloc(sizeof(char) * name_len, GFP_ATOMIC); if (!(*names)[i]) goto err; strncpy((*names)[i], policydb.p_bool_val_to_name[i], name_len); (*names)[i][name_len - 1] = 0; } rc = 0;out: POLICY_RDUNLOCK; return rc;err: if (*names) { for (i = 0; i < *len; i++) kfree((*names)[i]); } kfree(*values); goto out;}int security_set_bools(int len, int *values){ int i, rc = 0; int lenp, seqno = 0; struct cond_node *cur; POLICY_WRLOCK; lenp = policydb.p_bools.nprim; if (len != lenp) { rc = -EFAULT; goto out; } for (i = 0; i < len; i++) { if (!!values[i] != policydb.bool_val_to_struct[i]->state) { audit_log(current->audit_context, GFP_ATOMIC, AUDIT_MAC_CONFIG_CHANGE, "bool=%s val=%d old_val=%d auid=%u", policydb.p_bool_val_to_name[i], !!values[i], policydb.bool_val_to_struct[i]->state, audit_get_loginuid(current->audit_context)); } if (values[i]) { policydb.bool_val_to_struct[i]->state = 1; } else { policydb.bool_val_to_struct[i]->state = 0; } } for (cur = policydb.cond_list; cur != NULL; cur = cur->next) { rc = evaluate_cond_node(&policydb, cur); if (rc) goto out; } seqno = ++latest_granting;out: POLICY_WRUNLOCK; if (!rc) { avc_ss_reset(seqno); selnl_notify_policyload(seqno); } return rc;}int security_get_bool_value(int bool){ int rc = 0; int len; POLICY_RDLOCK; len = policydb.p_bools.nprim; if (bool >= len) { rc = -EFAULT; goto out; } rc = policydb.bool_val_to_struct[bool]->state;out: POLICY_RDUNLOCK; return rc;}struct selinux_audit_rule { u32 au_seqno; struct context au_ctxt;};void selinux_audit_rule_free(struct selinux_audit_rule *rule){ if (rule) { context_destroy(&rule->au_ctxt); kfree(rule); }}int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, struct selinux_audit_rule **rule){ struct selinux_audit_rule *tmprule; struct role_datum *roledatum; struct type_datum *typedatum; struct user_datum *userdatum; int rc = 0; *rule = NULL; if (!ss_initialized) return -ENOTSUPP; switch (field) { case AUDIT_SE_USER: case AUDIT_SE_ROLE: case AUDIT_SE_TYPE: /* only 'equals' and 'not equals' fit user, role, and type */ if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL) return -EINVAL; break; case AUDIT_SE_SEN: case AUDIT_SE_CLR: /* we do not allow a range, indicated by the presense of '-' */ if (strchr(rulestr, '-')) return -EINVAL; break; default: /* only the above fields are valid */ return -EINVAL; } tmprule = kzalloc(sizeof(struct selinux_audit_rule), GFP_KERNEL); if (!tmprule) return -ENOMEM; context_init(&tmprule->au_ctxt); POLICY_RDLOCK; tmprule->au_seqno = latest_granting; switch (field) { case AUDIT_SE_USER: userdatum = hashtab_search(policydb.p_users.table, rulestr); if (!userdatum) rc = -EINVAL; else tmprule->au_ctxt.user = userdatum->value; break; case AUDIT_SE_ROLE: roledatum = hashtab_search(policydb.p_roles.table, rulestr); if (!roledatum) rc = -EINVAL; else tmprule->au_ctxt.role = roledatum->value; break; case AUDIT_SE_TYPE: typedatum = hashtab_search(policydb.p_types.table, rulestr); if (!typedatum) rc = -EINVAL; else tmprule->au_ctxt.type = typedatum->value; break; case AUDIT_SE_SEN: case AUDIT_SE_CLR: rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC); break; } POLICY_RDUNLOCK; if (rc) { selinux_audit_rule_free(tmprule); tmprule = NULL; } *rule = tmprule; return rc;}int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, struct selinux_audit_rule *rule, struct audit_context *actx){ struct context *ctxt; struct mls_level *level; int match = 0; if (!rule) { audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, "selinux_audit_rule_match: missing rule\n"); return -ENOENT; } POLICY_RDLOCK; if (rule->au_seqno < latest_granting) { audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, "selinux_audit_rule_match: stale rule\n"); match = -ESTALE; goto out; } ctxt = sidtab_search(&sidtab, ctxid); if (!ctxt) { audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, "selinux_audit_rule_match: unrecognized SID %d\n", ctxid); match = -ENOENT; goto out; } /* a field/op pair that is not caught here will simply fall through without a match */ switch (field) { case AUDIT_SE_USER: switch (op) { case AUDIT_EQUAL: match = (ctxt->user == rule->au_ctxt.user); break; case AUDIT_NOT_EQUAL: match = (ctxt->user != rule->au_ctxt.user); break; } break; case AUDIT_SE_ROLE: switch (op) { case AUDIT_EQUAL: match = (ctxt->role == rule->au_ctxt.role); break; case AUDIT_NOT_EQUAL: match = (ctxt->role != rule->au_ctxt.role); break; } break; case AUDIT_SE_TYPE: switch (op) { case AUDIT_EQUAL: match = (ctxt->type == rule->au_ctxt.type); break; case AUDIT_NOT_EQUAL: match = (ctxt->type != rule->au_ctxt.type); break; } break; case AUDIT_SE_SEN: case AUDIT_SE_CLR: level = (op == AUDIT_SE_SEN ? &ctxt->range.level[0] : &ctxt->range.level[1]); switch (op) { case AUDIT_EQUAL: match = mls_level_eq(&rule->au_ctxt.range.level[0], level); break; case AUDIT_NOT_EQUAL: match = !mls_level_eq(&rule->au_ctxt.range.level[0], level); break; case AUDIT_LESS_THAN: match = (mls_level_dom(&rule->au_ctxt.range.level[0], level) && !mls_level_eq(&rule->au_ctxt.range.level[0], level)); break; case AUDIT_LESS_THAN_OR_EQUAL: match = mls_level_dom(&rule->au_ctxt.range.level[0], level); break; case AUDIT_GREATER_THAN: match = (mls_level_dom(level, &rule->au_ctxt.range.level[0]) && !mls_level_eq(level, &rule->au_ctxt.range.level[0])); break; case AUDIT_GREATER_THAN_OR_EQUAL: match = mls_level_dom(level, &rule->au_ctxt.range.level[0]); break; } }out: POLICY_RDUNLOCK; return match;}static int (*aurule_callback)(void) = NULL;static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid, u16 class, u32 perms, u32 *retained){ int err = 0; if (event == AVC_CALLBACK_RESET && aurule_callback) err = aurule_callback(); return err;}static int __init aurule_init(void){ int err; err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET, SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); if (err) panic("avc_add_callback() failed, error %d\n", err); return err;}__initcall(aurule_init);void selinux_audit_set_callback(int (*callback)(void)){ aurule_callback = callback;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -