static struct aa_namespace *alloc_namespace(const char *prefix, const char *name) { struct aa_namespace *ns; ns = kzalloc(sizeof(*ns), GFP_KERNEL); AA_DEBUG("%s(%p)\n", __func__, ns); if (!ns) return NULL; if (!policy_init(&ns->base, prefix, name)) goto fail_ns; INIT_LIST_HEAD(&ns->sub_ns); rwlock_init(&ns->lock); ns->unconfined = aa_alloc_profile("unconfined"); if (!ns->unconfined) goto fail_unconfined; ns->unconfined->sid = aa_alloc_sid(); ns->unconfined->flags = PFLAG_UNCONFINED | PFLAG_IX_ON_NAME_ERROR | PFLAG_IMMUTABLE; ns->unconfined->ns = aa_get_namespace(ns); return ns; fail_unconfined: kzfree(ns->base.hname); fail_ns: kzfree(ns); return NULL; }
/** * alloc_ns - allocate, initialize and return a new namespace * @prefix: parent namespace name (MAYBE NULL) * @name: a preallocated name (NOT NULL) * * Returns: refcounted namespace or NULL on failure. */ static struct aa_ns *alloc_ns(const char *prefix, const char *name) { struct aa_ns *ns; ns = kzalloc(sizeof(*ns), GFP_KERNEL); AA_DEBUG("%s(%p)\n", __func__, ns); if (!ns) return NULL; if (!aa_policy_init(&ns->base, prefix, name, GFP_KERNEL)) goto fail_ns; INIT_LIST_HEAD(&ns->sub_ns); INIT_LIST_HEAD(&ns->rawdata_list); mutex_init(&ns->lock); init_waitqueue_head(&ns->wait); /* released by aa_free_ns() */ ns->unconfined = aa_alloc_profile("unconfined", NULL, GFP_KERNEL); if (!ns->unconfined) goto fail_unconfined; ns->unconfined->label.flags |= FLAG_IX_ON_NAME_ERROR | FLAG_IMMUTIBLE | FLAG_NS_COUNT | FLAG_UNCONFINED; ns->unconfined->mode = APPARMOR_UNCONFINED; /* ns and ns->unconfined share ns->unconfined refcount */ ns->unconfined->ns = ns; atomic_set(&ns->uniq_null, 0); aa_labelset_init(&ns->labels); return ns; fail_unconfined: kzfree(ns->base.hname); fail_ns: kzfree(ns); return NULL; }
/** * alloc_namespace - allocate, initialize and return a new namespace * @prefix: parent namespace name (MAYBE NULL) * @name: a preallocated name (NOT NULL) * * Returns: refcounted namespace or NULL on failure. */ static struct aa_namespace *alloc_namespace(const char *prefix, const char *name) { struct aa_namespace *ns; ns = kzalloc(sizeof(*ns), GFP_KERNEL); AA_DEBUG("%s(%p)\n", __func__, ns); if (!ns) return NULL; if (!policy_init(&ns->base, prefix, name)) goto fail_ns; INIT_LIST_HEAD(&ns->sub_ns); rwlock_init(&ns->lock); /* released by free_namespace */ ns->unconfined = aa_alloc_profile("unconfined"); if (!ns->unconfined) goto fail_unconfined; ns->unconfined->flags = PFLAG_UNCONFINED | PFLAG_IX_ON_NAME_ERROR | PFLAG_IMMUTABLE; /* * released by free_namespace, however __remove_namespace breaks * the cyclic references (ns->unconfined, and unconfined->ns) and * replaces with refs to parent namespace unconfined */ ns->unconfined->ns = aa_get_namespace(ns); atomic_set(&ns->uniq_null, 0); return ns; fail_unconfined: kzfree(ns->base.hname); fail_ns: kzfree(ns); return NULL; }
/** * aa_setprocattr_chagnehat - handle procattr interface to change_hat * @args: args received from writing to /proc/<pid>/attr/current (NOT NULL) * @size: size of the args * @test: true if this is a test of change_hat permissions * * Returns: %0 or error code if change_hat fails */ int aa_setprocattr_changehat(char *args, size_t size, int test) { char *hat; u64 token; const char *hats[16]; /* current hard limit on # of names */ int count = 0; hat = split_token_from_name(OP_CHANGE_HAT, args, &token); if (IS_ERR(hat)) return PTR_ERR(hat); if (!hat && !token) { AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic"); return -EINVAL; } if (hat) { /* set up hat name vector, args guaranteed null terminated * at args[size] by setprocattr. * * If there are multiple hat names in the buffer each is * separated by a \0. Ie. userspace writes them pre tokenized */ char *end = args + size; for (count = 0; (hat < end) && count < 16; ++count) { char *next = hat + strlen(hat) + 1; hats[count] = hat; hat = next; } } AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n", __func__, token, hat ? hat : NULL); return aa_change_hat(hats, count, token, test); }