diff options
author | John Johansen <john.johansen@canonical.com> | 2017-06-09 23:38:35 +0200 |
---|---|---|
committer | John Johansen <john.johansen@canonical.com> | 2017-06-11 02:11:42 +0200 |
commit | 290f458a4f16f9cf6cb6562b249e69fe1c3c3a07 (patch) | |
tree | 41b1a79cb019d8fbbb1b07c28e5d926656728ccd /security/apparmor/ipc.c | |
parent | apparmor: move ptrace checks to using labels (diff) | |
download | linux-290f458a4f16f9cf6cb6562b249e69fe1c3c3a07.tar.xz linux-290f458a4f16f9cf6cb6562b249e69fe1c3c3a07.zip |
apparmor: allow ptrace checks to be finer grained than just capability
Signed-off-by: John Johansen <john.johansen@canonical.com>
Diffstat (limited to 'security/apparmor/ipc.c')
-rw-r--r-- | security/apparmor/ipc.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c index f81649369f05..11e66b5bbc42 100644 --- a/security/apparmor/ipc.c +++ b/security/apparmor/ipc.c @@ -21,20 +21,76 @@ #include "include/policy.h" #include "include/ipc.h" +/** + * audit_ptrace_mask - convert mask to permission string + * @buffer: buffer to write string to (NOT NULL) + * @mask: permission mask to convert + */ +static void audit_ptrace_mask(struct audit_buffer *ab, u32 mask) +{ + switch (mask) { + case MAY_READ: + audit_log_string(ab, "read"); + break; + case MAY_WRITE: + audit_log_string(ab, "trace"); + break; + case AA_MAY_BE_READ: + audit_log_string(ab, "readby"); + break; + case AA_MAY_BE_TRACED: + audit_log_string(ab, "tracedby"); + break; + } +} + /* call back to audit ptrace fields */ static void audit_ptrace_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; + if (aad(sa)->request & AA_PTRACE_PERM_MASK) { + audit_log_format(ab, " requested_mask="); + audit_ptrace_mask(ab, aad(sa)->request); + + if (aad(sa)->denied & AA_PTRACE_PERM_MASK) { + audit_log_format(ab, " denied_mask="); + audit_ptrace_mask(ab, aad(sa)->denied); + } + } audit_log_format(ab, " peer="); aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, FLAGS_NONE, GFP_ATOMIC); } +/* TODO: conditionals */ +static int profile_ptrace_perm(struct aa_profile *profile, + struct aa_profile *peer, u32 request, + struct common_audit_data *sa) +{ + struct aa_perms perms = { }; + + /* need because of peer in cross check */ + if (profile_unconfined(profile) || + !PROFILE_MEDIATES(profile, AA_CLASS_PTRACE)) + return 0; + + aad(sa)->peer = &peer->label; + aa_profile_match_label(profile, &peer->label, AA_CLASS_PTRACE, request, + &perms); + aa_apply_modes_to_perms(profile, &perms); + return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb); +} + static int cross_ptrace_perm(struct aa_profile *tracer, struct aa_profile *tracee, u32 request, struct common_audit_data *sa) { + if (PROFILE_MEDIATES(tracer, AA_CLASS_PTRACE)) + return xcheck(profile_ptrace_perm(tracer, tracee, request, sa), + profile_ptrace_perm(tracee, tracer, + request << PTRACE_PERM_SHIFT, + sa)); /* policy uses the old style capability check for ptrace */ if (profile_unconfined(tracer) || tracer == tracee) return 0; |