--- security/apparmor/apparmor.h | 10 ++++++++++ security/apparmor/apparmorfs.c | 4 ++-- security/apparmor/lsm.c | 15 ++++++--------- security/apparmor/module_interface.c | 2 ++ 4 files changed, 20 insertions(+), 11 deletions(-) --- a/security/apparmor/apparmor.h +++ b/security/apparmor/apparmor.h @@ -158,8 +158,17 @@ struct aa_namespace { * @file_rules: dfa containing the profiles file rules * @flags: flags controlling profile behavior * @isstale: flag indicating if profile is stale + * @set_caps: capabilities that are being set + * @capabilities: capabilities mask + * @audit_caps: caps that are to be audited + * @quiet_caps: caps that should not be audited * @capabilities: capabilities granted by the process * @count: reference count of the profile + * @task_contexts: list of tasks confined by profile + * @lock: lock for the task_contexts list + * @network_families: basic network permissions + * @audit_network: which network permissions to force audit + * @quiet_network: which network permissions to quiet rejects * * The AppArmor profile contains the basic confinement data. Each profile * has a name, and all nonstale profile are in a profile namespace. @@ -183,6 +192,7 @@ struct aa_profile { } flags; int isstale; + kernel_cap_t set_caps; kernel_cap_t capabilities; kernel_cap_t audit_caps; kernel_cap_t quiet_caps; --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -103,8 +103,8 @@ static struct file_operations apparmorfs static ssize_t aa_features_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) { - const char *features = "file=3.0 capability=1.0 network=1.0 " - "change_hat=1.3 change_profile=1.0 " + const char *features = "file=3.0 capability=2.0 network=1.0 " + "change_hat=1.4 change_profile=1.0 " "aanamespaces=1.0"; return simple_read_from_buffer(buf, size, ppos, features, --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -210,19 +210,16 @@ static int apparmor_ptrace(struct task_s static int apparmor_capable(struct task_struct *task, int cap) { int error; + struct aa_task_context *cxt; /* cap_capable returns 0 on success, else -EPERM */ error = cap_capable(task, cap); - if (!error) { - struct aa_task_context *cxt; - - rcu_read_lock(); - cxt = aa_task_context(task); - if (cxt) - error = aa_capability(cxt, cap); - rcu_read_unlock(); - } + rcu_read_lock(); + cxt = aa_task_context(task); + if (cxt && (!error || cap_raised(cxt->profile->set_caps, cap))) + error = aa_capability(cxt, cap); + rcu_read_unlock(); return error; } --- a/security/apparmor/module_interface.c +++ b/security/apparmor/module_interface.c @@ -316,6 +316,8 @@ static struct aa_profile *aa_unpack_prof goto fail; if (!aa_is_u32(e, &(profile->quiet_caps), NULL)) goto fail; + if (!aa_is_u32(e, &(profile->set_caps), NULL)) + goto fail; size = aa_is_array(e, "net_allowed_af"); if (size) {