/* * 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; }
char *sepol_av_to_string(policydb_t * policydbp, uint32_t tclass, sepol_access_vector_t av) { struct val_to_name v; static char avbuf[1024]; class_datum_t *cladatum; char *perm = NULL, *p; unsigned int i; int rc; int avlen = 0, len; cladatum = policydbp->class_val_to_struct[tclass - 1]; p = avbuf; for (i = 0; i < cladatum->permissions.nprim; i++) { if (av & (1 << i)) { v.val = i + 1; rc = hashtab_map(cladatum->permissions.table, perm_name, &v); if (!rc && cladatum->comdatum) { rc = hashtab_map(cladatum->comdatum-> permissions.table, perm_name, &v); } if (rc) perm = v.name; if (perm) { len = snprintf(p, sizeof(avbuf) - avlen, " %s", perm); if (len < 0 || (size_t) len >= (sizeof(avbuf) - avlen)) return NULL; p += len; avlen += len; } } } return avbuf; }
/** * 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); /* Save the old policydb and SID table to free later. */ memcpy(&oldpolicydb, &policydb, sizeof policydb); sidtab_set(&oldsidtab, &sidtab); /* Install the new policydb and SID table. */ POLICY_WRLOCK; memcpy(&policydb, &newpolicydb, sizeof policydb); sidtab_set(&sidtab, &newsidtab); seqno = ++latest_granting; POLICY_WRUNLOCK; LOAD_UNLOCK; /* Free the old policydb and SID table. */ policydb_destroy(&oldpolicydb); sidtab_destroy(&oldsidtab); avc_ss_reset(seqno); return 0; err: LOAD_UNLOCK; sidtab_destroy(&newsidtab); policydb_destroy(&newpolicydb); return rc; }