diff options
-rw-r--r-- | security/apparmor/apparmorfs.c | 1 | ||||
-rw-r--r-- | security/apparmor/include/ipc.h | 18 | ||||
-rw-r--r-- | security/apparmor/include/task.h | 18 | ||||
-rw-r--r-- | security/apparmor/ipc.c | 110 | ||||
-rw-r--r-- | security/apparmor/task.c | 114 |
5 files changed, 133 insertions, 128 deletions
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index d5838249cda5..d066ccc219e2 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -36,6 +36,7 @@ #include "include/policy_ns.h" #include "include/resource.h" #include "include/policy_unpack.h" +#include "include/task.h" /* * The apparmor filesystem interface used for policy load and introspection diff --git a/security/apparmor/include/ipc.h b/security/apparmor/include/ipc.h index 9cafd80f7731..a1ac6ffb95e9 100644 --- a/security/apparmor/include/ipc.h +++ b/security/apparmor/include/ipc.h @@ -13,24 +13,6 @@ #include <linux/sched.h> -struct aa_profile; - -#define AA_PTRACE_TRACE MAY_WRITE -#define AA_PTRACE_READ MAY_READ -#define AA_MAY_BE_TRACED AA_MAY_APPEND -#define AA_MAY_BE_READ AA_MAY_CREATE -#define PTRACE_PERM_SHIFT 2 - -#define AA_PTRACE_PERM_MASK (AA_PTRACE_READ | AA_PTRACE_TRACE | \ - AA_MAY_BE_READ | AA_MAY_BE_TRACED) -#define AA_SIGNAL_PERM_MASK (MAY_READ | MAY_WRITE) - -#define AA_SFS_SIG_MASK "hup int quit ill trap abrt bus fpe kill usr1 " \ - "segv usr2 pipe alrm term stkflt chld cont stop stp ttin ttou urg " \ - "xcpu xfsz vtalrm prof winch io pwr sys emt lost" - -int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, - u32 request); int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig); #endif /* __AA_IPC_H */ diff --git a/security/apparmor/include/task.h b/security/apparmor/include/task.h index f13d12373b25..13437d62c70f 100644 --- a/security/apparmor/include/task.h +++ b/security/apparmor/include/task.h @@ -77,4 +77,22 @@ static inline void aa_clear_task_ctx_trans(struct aa_task_ctx *ctx) ctx->token = 0; } +#define AA_PTRACE_TRACE MAY_WRITE +#define AA_PTRACE_READ MAY_READ +#define AA_MAY_BE_TRACED AA_MAY_APPEND +#define AA_MAY_BE_READ AA_MAY_CREATE +#define PTRACE_PERM_SHIFT 2 + +#define AA_PTRACE_PERM_MASK (AA_PTRACE_READ | AA_PTRACE_TRACE | \ + AA_MAY_BE_READ | AA_MAY_BE_TRACED) +#define AA_SIGNAL_PERM_MASK (MAY_READ | MAY_WRITE) + +#define AA_SFS_SIG_MASK "hup int quit ill trap abrt bus fpe kill usr1 " \ + "segv usr2 pipe alrm term stkflt chld cont stop stp ttin ttou urg " \ + "xcpu xfsz vtalrm prof winch io pwr sys emt lost" + +int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, + u32 request); + + #endif /* __AA_TASK_H */ diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c index fe36d112aad9..3dbbc59d440d 100644 --- a/security/apparmor/ipc.c +++ b/security/apparmor/ipc.c @@ -9,7 +9,6 @@ */ #include <linux/gfp.h> -#include <linux/ptrace.h> #include "include/audit.h" #include "include/capability.h" @@ -18,115 +17,6 @@ #include "include/ipc.h" #include "include/sig_names.h" -/** - * audit_ptrace_mask - convert mask to permission string - * @mask: permission mask to convert - * - * Returns: pointer to static string - */ -static const char *audit_ptrace_mask(u32 mask) -{ - switch (mask) { - case MAY_READ: - return "read"; - case MAY_WRITE: - return "trace"; - case AA_MAY_BE_READ: - return "readby"; - case AA_MAY_BE_TRACED: - return "tracedby"; - } - return ""; -} - -/* 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=\"%s\"", - audit_ptrace_mask(aad(sa)->request)); - - if (aad(sa)->denied & AA_PTRACE_PERM_MASK) { - audit_log_format(ab, " denied_mask=\"%s\"", - audit_ptrace_mask(aad(sa)->denied)); - } - } - audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, - FLAGS_NONE, GFP_ATOMIC); -} - -/* assumes check for PROFILE_MEDIATES is already done */ -/* TODO: conditionals */ -static int profile_ptrace_perm(struct aa_profile *profile, - struct aa_label *peer, u32 request, - struct common_audit_data *sa) -{ - struct aa_perms perms = { }; - - aad(sa)->peer = peer; - aa_profile_match_label(profile, peer, 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 profile_tracee_perm(struct aa_profile *tracee, - struct aa_label *tracer, u32 request, - struct common_audit_data *sa) -{ - if (profile_unconfined(tracee) || unconfined(tracer) || - !PROFILE_MEDIATES(tracee, AA_CLASS_PTRACE)) - return 0; - - return profile_ptrace_perm(tracee, tracer, request, sa); -} - -static int profile_tracer_perm(struct aa_profile *tracer, - struct aa_label *tracee, u32 request, - struct common_audit_data *sa) -{ - if (profile_unconfined(tracer)) - return 0; - - if (PROFILE_MEDIATES(tracer, AA_CLASS_PTRACE)) - return profile_ptrace_perm(tracer, tracee, request, sa); - - /* profile uses the old style capability check for ptrace */ - if (&tracer->label == tracee) - return 0; - - aad(sa)->label = &tracer->label; - aad(sa)->peer = tracee; - aad(sa)->request = 0; - aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, - CAP_OPT_NONE); - - return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb); -} - -/** - * aa_may_ptrace - test if tracer task can trace the tracee - * @tracer: label of the task doing the tracing (NOT NULL) - * @tracee: task label to be traced - * @request: permission request - * - * Returns: %0 else error code if permission denied or error - */ -int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, - u32 request) -{ - struct aa_profile *profile; - u32 xrequest = request << PTRACE_PERM_SHIFT; - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_PTRACE); - - return xcheck_labels(tracer, tracee, profile, - profile_tracer_perm(profile, tracee, request, &sa), - profile_tracee_perm(profile, tracer, xrequest, &sa)); -} - static inline int map_signal_num(int sig) { diff --git a/security/apparmor/task.c b/security/apparmor/task.c index d17130ee6795..503dc0877fb1 100644 --- a/security/apparmor/task.c +++ b/security/apparmor/task.c @@ -12,7 +12,12 @@ * should return to the previous cred if it has not been modified. */ +#include <linux/gfp.h> +#include <linux/ptrace.h> + +#include "include/audit.h" #include "include/cred.h" +#include "include/policy.h" #include "include/task.h" /** @@ -177,3 +182,112 @@ int aa_restore_previous_label(u64 token) return 0; } + +/** + * audit_ptrace_mask - convert mask to permission string + * @mask: permission mask to convert + * + * Returns: pointer to static string + */ +static const char *audit_ptrace_mask(u32 mask) +{ + switch (mask) { + case MAY_READ: + return "read"; + case MAY_WRITE: + return "trace"; + case AA_MAY_BE_READ: + return "readby"; + case AA_MAY_BE_TRACED: + return "tracedby"; + } + return ""; +} + +/* 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=\"%s\"", + audit_ptrace_mask(aad(sa)->request)); + + if (aad(sa)->denied & AA_PTRACE_PERM_MASK) { + audit_log_format(ab, " denied_mask=\"%s\"", + audit_ptrace_mask(aad(sa)->denied)); + } + } + audit_log_format(ab, " peer="); + aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, + FLAGS_NONE, GFP_ATOMIC); +} + +/* assumes check for PROFILE_MEDIATES is already done */ +/* TODO: conditionals */ +static int profile_ptrace_perm(struct aa_profile *profile, + struct aa_label *peer, u32 request, + struct common_audit_data *sa) +{ + struct aa_perms perms = { }; + + aad(sa)->peer = peer; + aa_profile_match_label(profile, peer, 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 profile_tracee_perm(struct aa_profile *tracee, + struct aa_label *tracer, u32 request, + struct common_audit_data *sa) +{ + if (profile_unconfined(tracee) || unconfined(tracer) || + !PROFILE_MEDIATES(tracee, AA_CLASS_PTRACE)) + return 0; + + return profile_ptrace_perm(tracee, tracer, request, sa); +} + +static int profile_tracer_perm(struct aa_profile *tracer, + struct aa_label *tracee, u32 request, + struct common_audit_data *sa) +{ + if (profile_unconfined(tracer)) + return 0; + + if (PROFILE_MEDIATES(tracer, AA_CLASS_PTRACE)) + return profile_ptrace_perm(tracer, tracee, request, sa); + + /* profile uses the old style capability check for ptrace */ + if (&tracer->label == tracee) + return 0; + + aad(sa)->label = &tracer->label; + aad(sa)->peer = tracee; + aad(sa)->request = 0; + aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, + CAP_OPT_NONE); + + return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb); +} + +/** + * aa_may_ptrace - test if tracer task can trace the tracee + * @tracer: label of the task doing the tracing (NOT NULL) + * @tracee: task label to be traced + * @request: permission request + * + * Returns: %0 else error code if permission denied or error + */ +int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, + u32 request) +{ + struct aa_profile *profile; + u32 xrequest = request << PTRACE_PERM_SHIFT; + DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_PTRACE); + + return xcheck_labels(tracer, tracee, profile, + profile_tracer_perm(profile, tracee, request, &sa), + profile_tracee_perm(profile, tracer, xrequest, &sa)); +} |