apparmor: refactor prepare_ns() and make usable from different views
prepare_ns() will need to be called from alternate views, and namespaces will need to be created via different interfaces. So refactor and allow specifying the view ns. Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
Родитель
5fd1b95fc9
Коммит
73688d1ed0
|
@ -125,7 +125,8 @@ static ssize_t profile_load(struct file *f, const char __user *buf, size_t size,
|
||||||
|
|
||||||
error = PTR_ERR(data);
|
error = PTR_ERR(data);
|
||||||
if (!IS_ERR(data)) {
|
if (!IS_ERR(data)) {
|
||||||
error = aa_replace_profiles(data, size, PROF_ADD);
|
error = aa_replace_profiles(__aa_current_profile()->ns, data,
|
||||||
|
size, PROF_ADD);
|
||||||
kvfree(data);
|
kvfree(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +148,8 @@ static ssize_t profile_replace(struct file *f, const char __user *buf,
|
||||||
data = aa_simple_write_to_buffer(OP_PROF_REPL, buf, size, size, pos);
|
data = aa_simple_write_to_buffer(OP_PROF_REPL, buf, size, size, pos);
|
||||||
error = PTR_ERR(data);
|
error = PTR_ERR(data);
|
||||||
if (!IS_ERR(data)) {
|
if (!IS_ERR(data)) {
|
||||||
error = aa_replace_profiles(data, size, PROF_REPLACE);
|
error = aa_replace_profiles(__aa_current_profile()->ns, data,
|
||||||
|
size, PROF_REPLACE);
|
||||||
kvfree(data);
|
kvfree(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -184,7 +184,8 @@ struct aa_profile *aa_fqlookupn_profile(struct aa_profile *base,
|
||||||
const char *fqname, size_t n);
|
const char *fqname, size_t n);
|
||||||
struct aa_profile *aa_match_profile(struct aa_ns *ns, const char *name);
|
struct aa_profile *aa_match_profile(struct aa_ns *ns, const char *name);
|
||||||
|
|
||||||
ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace);
|
ssize_t aa_replace_profiles(struct aa_ns *view, void *udata, size_t size,
|
||||||
|
bool noreplace);
|
||||||
ssize_t aa_remove_profiles(char *name, size_t size);
|
ssize_t aa_remove_profiles(char *name, size_t size);
|
||||||
void __aa_profile_list_release(struct list_head *head);
|
void __aa_profile_list_release(struct list_head *head);
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,9 @@ void aa_free_ns_kref(struct kref *kref);
|
||||||
|
|
||||||
struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name);
|
struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name);
|
||||||
struct aa_ns *aa_findn_ns(struct aa_ns *root, const char *name, size_t n);
|
struct aa_ns *aa_findn_ns(struct aa_ns *root, const char *name, size_t n);
|
||||||
struct aa_ns *aa_prepare_ns(const char *name);
|
struct aa_ns *__aa_find_or_create_ns(struct aa_ns *parent, const char *name,
|
||||||
|
struct dentry *dir);
|
||||||
|
struct aa_ns *aa_prepare_ns(struct aa_ns *root, const char *name);
|
||||||
void __aa_remove_ns(struct aa_ns *ns);
|
void __aa_remove_ns(struct aa_ns *ns);
|
||||||
|
|
||||||
static inline struct aa_profile *aa_deref_parent(struct aa_profile *p)
|
static inline struct aa_profile *aa_deref_parent(struct aa_profile *p)
|
||||||
|
|
|
@ -731,6 +731,7 @@ static int __lookup_replace(struct aa_ns *ns, const char *hname,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* aa_replace_profiles - replace profile(s) on the profile list
|
* aa_replace_profiles - replace profile(s) on the profile list
|
||||||
|
* @view: namespace load is viewed from
|
||||||
* @udata: serialized data stream (NOT NULL)
|
* @udata: serialized data stream (NOT NULL)
|
||||||
* @size: size of the serialized data stream
|
* @size: size of the serialized data stream
|
||||||
* @noreplace: true if only doing addition, no replacement allowed
|
* @noreplace: true if only doing addition, no replacement allowed
|
||||||
|
@ -741,7 +742,8 @@ static int __lookup_replace(struct aa_ns *ns, const char *hname,
|
||||||
*
|
*
|
||||||
* Returns: size of data consumed else error code on failure.
|
* Returns: size of data consumed else error code on failure.
|
||||||
*/
|
*/
|
||||||
ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
|
ssize_t aa_replace_profiles(struct aa_ns *view, void *udata, size_t size,
|
||||||
|
bool noreplace)
|
||||||
{
|
{
|
||||||
const char *ns_name, *info = NULL;
|
const char *ns_name, *info = NULL;
|
||||||
struct aa_ns *ns = NULL;
|
struct aa_ns *ns = NULL;
|
||||||
|
@ -756,7 +758,7 @@ ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* released below */
|
/* released below */
|
||||||
ns = aa_prepare_ns(ns_name);
|
ns = aa_prepare_ns(view, ns_name);
|
||||||
if (!ns) {
|
if (!ns) {
|
||||||
error = audit_policy(op, GFP_KERNEL, ns_name,
|
error = audit_policy(op, GFP_KERNEL, ns_name,
|
||||||
"failed to prepare namespace", -ENOMEM);
|
"failed to prepare namespace", -ENOMEM);
|
||||||
|
|
|
@ -181,48 +181,82 @@ struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name)
|
||||||
return aa_findn_ns(root, name, strlen(name));
|
return aa_findn_ns(root, name, strlen(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name,
|
||||||
|
struct dentry *dir)
|
||||||
|
{
|
||||||
|
struct aa_ns *ns;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
AA_BUG(!parent);
|
||||||
|
AA_BUG(!name);
|
||||||
|
AA_BUG(!mutex_is_locked(&parent->lock));
|
||||||
|
|
||||||
|
ns = alloc_ns(parent->base.hname, name);
|
||||||
|
if (!ns)
|
||||||
|
return NULL;
|
||||||
|
mutex_lock(&ns->lock);
|
||||||
|
error = __aa_fs_ns_mkdir(ns, ns_subns_dir(parent), name);
|
||||||
|
if (error) {
|
||||||
|
AA_ERROR("Failed to create interface for ns %s\n",
|
||||||
|
ns->base.name);
|
||||||
|
mutex_unlock(&ns->lock);
|
||||||
|
aa_free_ns(ns);
|
||||||
|
return ERR_PTR(error);
|
||||||
|
}
|
||||||
|
ns->parent = aa_get_ns(parent);
|
||||||
|
list_add_rcu(&ns->base.list, &parent->sub_ns);
|
||||||
|
/* add list ref */
|
||||||
|
aa_get_ns(ns);
|
||||||
|
mutex_unlock(&ns->lock);
|
||||||
|
|
||||||
|
return ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aa_create_ns - create an ns, fail if it already exists
|
||||||
|
* @parent: the parent of the namespace being created
|
||||||
|
* @name: the name of the namespace
|
||||||
|
* @dir: if not null the dir to put the ns entries in
|
||||||
|
*
|
||||||
|
* Returns: the a refcounted ns that has been add or an ERR_PTR
|
||||||
|
*/
|
||||||
|
struct aa_ns *__aa_find_or_create_ns(struct aa_ns *parent, const char *name,
|
||||||
|
struct dentry *dir)
|
||||||
|
{
|
||||||
|
struct aa_ns *ns;
|
||||||
|
|
||||||
|
AA_BUG(!mutex_is_locked(&parent->lock));
|
||||||
|
|
||||||
|
/* try and find the specified ns */
|
||||||
|
/* released by caller */
|
||||||
|
ns = aa_get_ns(__aa_find_ns(&parent->sub_ns, name));
|
||||||
|
if (!ns)
|
||||||
|
ns = __aa_create_ns(parent, name, dir);
|
||||||
|
else
|
||||||
|
ns = ERR_PTR(-EEXIST);
|
||||||
|
|
||||||
|
/* return ref */
|
||||||
|
return ns;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* aa_prepare_ns - find an existing or create a new namespace of @name
|
* aa_prepare_ns - find an existing or create a new namespace of @name
|
||||||
* @name: the namespace to find or add (MAYBE NULL)
|
* @parent: ns to treat as parent
|
||||||
|
* @name: the namespace to find or add (NOT NULL)
|
||||||
*
|
*
|
||||||
* Returns: refcounted ns or NULL if failed to create one
|
* Returns: refcounted namespace or PTR_ERR if failed to create one
|
||||||
*/
|
*/
|
||||||
struct aa_ns *aa_prepare_ns(const char *name)
|
struct aa_ns *aa_prepare_ns(struct aa_ns *parent, const char *name)
|
||||||
{
|
{
|
||||||
struct aa_ns *ns, *root;
|
struct aa_ns *ns;
|
||||||
|
|
||||||
root = aa_current_profile()->ns;
|
|
||||||
|
|
||||||
mutex_lock(&root->lock);
|
|
||||||
|
|
||||||
/* if name isn't specified the profile is loaded to the current ns */
|
|
||||||
if (!name) {
|
|
||||||
/* released by caller */
|
|
||||||
ns = aa_get_ns(root);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
mutex_lock(&parent->lock);
|
||||||
/* try and find the specified ns and if it doesn't exist create it */
|
/* try and find the specified ns and if it doesn't exist create it */
|
||||||
/* released by caller */
|
/* released by caller */
|
||||||
ns = aa_get_ns(__aa_find_ns(&root->sub_ns, name));
|
ns = aa_get_ns(__aa_find_ns(&parent->sub_ns, name));
|
||||||
if (!ns) {
|
if (!ns)
|
||||||
ns = alloc_ns(root->base.hname, name);
|
ns = __aa_create_ns(parent, name, NULL);
|
||||||
if (!ns)
|
mutex_unlock(&parent->lock);
|
||||||
goto out;
|
|
||||||
if (__aa_fs_ns_mkdir(ns, ns_subns_dir(root), name)) {
|
|
||||||
AA_ERROR("Failed to create interface for ns %s\n",
|
|
||||||
ns->base.name);
|
|
||||||
aa_free_ns(ns);
|
|
||||||
ns = NULL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
ns->parent = aa_get_ns(root);
|
|
||||||
list_add_rcu(&ns->base.list, &root->sub_ns);
|
|
||||||
/* add list ref */
|
|
||||||
aa_get_ns(ns);
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
mutex_unlock(&root->lock);
|
|
||||||
|
|
||||||
/* return ref */
|
/* return ref */
|
||||||
return ns;
|
return ns;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче