Commit 18e99f19 authored by John Johansen's avatar John Johansen

apparmor: provide finer control over policy management

Signed-off-by: default avatarJohn Johansen <john.johansen@canonical.com>
parent e53cfe6c
...@@ -400,17 +400,16 @@ static struct aa_loaddata *aa_simple_write_to_buffer(const char __user *userbuf, ...@@ -400,17 +400,16 @@ static struct aa_loaddata *aa_simple_write_to_buffer(const char __user *userbuf,
return data; return data;
} }
static ssize_t policy_update(int binop, const char __user *buf, size_t size, static ssize_t policy_update(u32 mask, const char __user *buf, size_t size,
loff_t *pos, struct aa_ns *ns) loff_t *pos, struct aa_ns *ns)
{ {
ssize_t error; ssize_t error;
struct aa_loaddata *data; struct aa_loaddata *data;
struct aa_profile *profile = aa_current_profile(); struct aa_profile *profile = aa_current_profile();
const char *op = binop == PROF_ADD ? OP_PROF_LOAD : OP_PROF_REPL;
/* high level check about policy management - fine grained in /* high level check about policy management - fine grained in
* below after unpack * below after unpack
*/ */
error = aa_may_manage_policy(profile, ns, op); error = aa_may_manage_policy(profile, ns, mask);
if (error) if (error)
return error; return error;
...@@ -418,7 +417,7 @@ static ssize_t policy_update(int binop, const char __user *buf, size_t size, ...@@ -418,7 +417,7 @@ static ssize_t policy_update(int binop, 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(ns ? ns : profile->ns, profile, error = aa_replace_profiles(ns ? ns : profile->ns, profile,
binop, data); mask, data);
aa_put_loaddata(data); aa_put_loaddata(data);
} }
...@@ -430,7 +429,7 @@ static ssize_t profile_load(struct file *f, const char __user *buf, size_t size, ...@@ -430,7 +429,7 @@ static ssize_t profile_load(struct file *f, const char __user *buf, size_t size,
loff_t *pos) loff_t *pos)
{ {
struct aa_ns *ns = aa_get_ns(f->f_inode->i_private); struct aa_ns *ns = aa_get_ns(f->f_inode->i_private);
int error = policy_update(PROF_ADD, buf, size, pos, ns); int error = policy_update(AA_MAY_LOAD_POLICY, buf, size, pos, ns);
aa_put_ns(ns); aa_put_ns(ns);
...@@ -447,8 +446,8 @@ static ssize_t profile_replace(struct file *f, const char __user *buf, ...@@ -447,8 +446,8 @@ static ssize_t profile_replace(struct file *f, const char __user *buf,
size_t size, loff_t *pos) size_t size, loff_t *pos)
{ {
struct aa_ns *ns = aa_get_ns(f->f_inode->i_private); struct aa_ns *ns = aa_get_ns(f->f_inode->i_private);
int error = policy_update(PROF_REPLACE, buf, size, pos, ns); int error = policy_update(AA_MAY_LOAD_POLICY | AA_MAY_REPLACE_POLICY,
buf, size, pos, ns);
aa_put_ns(ns); aa_put_ns(ns);
return error; return error;
...@@ -472,7 +471,7 @@ static ssize_t profile_remove(struct file *f, const char __user *buf, ...@@ -472,7 +471,7 @@ static ssize_t profile_remove(struct file *f, const char __user *buf,
/* high level check about policy management - fine grained in /* high level check about policy management - fine grained in
* below after unpack * below after unpack
*/ */
error = aa_may_manage_policy(profile, ns, OP_PROF_RM); error = aa_may_manage_policy(profile, ns, AA_MAY_REMOVE_POLICY);
if (error) if (error)
goto out; goto out;
......
...@@ -188,6 +188,10 @@ struct aa_profile { ...@@ -188,6 +188,10 @@ struct aa_profile {
extern enum profile_mode aa_g_profile_mode; extern enum profile_mode aa_g_profile_mode;
#define AA_MAY_LOAD_POLICY AA_MAY_APPEND
#define AA_MAY_REPLACE_POLICY AA_MAY_WRITE
#define AA_MAY_REMOVE_POLICY AA_MAY_DELETE
void __aa_update_proxy(struct aa_profile *orig, struct aa_profile *new); void __aa_update_proxy(struct aa_profile *orig, struct aa_profile *new);
void aa_add_profile(struct aa_policy *common, struct aa_profile *profile); void aa_add_profile(struct aa_policy *common, struct aa_profile *profile);
...@@ -208,7 +212,7 @@ struct aa_profile *aa_fqlookupn_profile(struct aa_profile *base, ...@@ -208,7 +212,7 @@ struct aa_profile *aa_fqlookupn_profile(struct aa_profile *base,
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(struct aa_ns *view, struct aa_profile *profile, ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile,
bool noreplace, struct aa_loaddata *udata); u32 mask, struct aa_loaddata *udata);
ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_profile *profile, ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_profile *profile,
char *name, size_t size); char *name, size_t size);
void __aa_profile_list_release(struct list_head *head); void __aa_profile_list_release(struct list_head *head);
...@@ -323,6 +327,6 @@ static inline int AUDIT_MODE(struct aa_profile *profile) ...@@ -323,6 +327,6 @@ static inline int AUDIT_MODE(struct aa_profile *profile)
bool policy_view_capable(struct aa_ns *ns); bool policy_view_capable(struct aa_ns *ns);
bool policy_admin_capable(struct aa_ns *ns); bool policy_admin_capable(struct aa_ns *ns);
int aa_may_manage_policy(struct aa_profile *profile, struct aa_ns *ns, int aa_may_manage_policy(struct aa_profile *profile, struct aa_ns *ns,
const char *op); u32 mask);
#endif /* __AA_POLICY_H */ #endif /* __AA_POLICY_H */
...@@ -690,17 +690,25 @@ bool policy_admin_capable(struct aa_ns *ns) ...@@ -690,17 +690,25 @@ bool policy_admin_capable(struct aa_ns *ns)
* *
* Returns: 0 if the task is allowed to manipulate policy else error * Returns: 0 if the task is allowed to manipulate policy else error
*/ */
int aa_may_manage_policy(struct aa_profile *profile, struct aa_ns *ns, int aa_may_manage_policy(struct aa_profile *profile, struct aa_ns *ns, u32 mask)
const char *op)
{ {
const char *op;
if (mask & AA_MAY_REMOVE_POLICY)
op = OP_PROF_RM;
else if (mask & AA_MAY_REPLACE_POLICY)
op = OP_PROF_REPL;
else
op = OP_PROF_LOAD;
/* check if loading policy is locked out */ /* check if loading policy is locked out */
if (aa_g_lock_policy) if (aa_g_lock_policy)
return audit_policy(profile, op, NULL, NULL, return audit_policy(profile, op, NULL, NULL, "policy_locked",
"policy_locked", -EACCES); -EACCES);
if (!policy_admin_capable(ns)) if (!policy_admin_capable(ns))
return audit_policy(profile, op, NULL, NULL, return audit_policy(profile, op, NULL, NULL, "not policy admin",
"not policy admin", -EACCES); -EACCES);
/* TODO: add fine grained mediation of policy loads */ /* TODO: add fine grained mediation of policy loads */
return 0; return 0;
...@@ -825,7 +833,7 @@ static int __lookup_replace(struct aa_ns *ns, const char *hname, ...@@ -825,7 +833,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 * @view: namespace load is viewed from
* @label: label that is attempting to load/replace policy * @label: label that is attempting to load/replace policy
* @noreplace: true if only doing addition, no replacement allowed * @mask: permission mask
* @udata: serialized data stream (NOT NULL) * @udata: serialized data stream (NOT NULL)
* *
* unpack and replace a profile on the profile list and uses of that profile * unpack and replace a profile on the profile list and uses of that profile
...@@ -835,17 +843,17 @@ static int __lookup_replace(struct aa_ns *ns, const char *hname, ...@@ -835,17 +843,17 @@ 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(struct aa_ns *view, struct aa_profile *profile, ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile,
bool noreplace, struct aa_loaddata *udata) u32 mask, struct aa_loaddata *udata)
{ {
const char *ns_name, *info = NULL; const char *ns_name, *info = NULL;
struct aa_ns *ns = NULL; struct aa_ns *ns = NULL;
struct aa_load_ent *ent, *tmp; struct aa_load_ent *ent, *tmp;
struct aa_loaddata *rawdata_ent; struct aa_loaddata *rawdata_ent;
const char *op = OP_PROF_REPL; const char *op;
ssize_t count, error; ssize_t count, error;
LIST_HEAD(lh); LIST_HEAD(lh);
op = mask & AA_MAY_REPLACE_POLICY ? OP_PROF_REPL : OP_PROF_LOAD;
aa_get_loaddata(udata); aa_get_loaddata(udata);
/* released below */ /* released below */
error = aa_unpack(udata, &lh, &ns_name); error = aa_unpack(udata, &lh, &ns_name);
...@@ -909,15 +917,16 @@ ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, ...@@ -909,15 +917,16 @@ ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile,
struct aa_policy *policy; struct aa_policy *policy;
ent->new->rawdata = aa_get_loaddata(udata); ent->new->rawdata = aa_get_loaddata(udata);
error = __lookup_replace(ns, ent->new->base.hname, noreplace, error = __lookup_replace(ns, ent->new->base.hname,
!(mask & AA_MAY_REPLACE_POLICY),
&ent->old, &info); &ent->old, &info);
if (error) if (error)
goto fail_lock; goto fail_lock;
if (ent->new->rename) { if (ent->new->rename) {
error = __lookup_replace(ns, ent->new->rename, error = __lookup_replace(ns, ent->new->rename,
noreplace, &ent->rename, !(mask & AA_MAY_REPLACE_POLICY),
&info); &ent->rename, &info);
if (error) if (error)
goto fail_lock; goto fail_lock;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment