diff options
| -rw-r--r-- | security/apparmor/include/perms.h | 3 | ||||
| -rw-r--r-- | security/apparmor/ipc.c | 53 |
2 files changed, 35 insertions, 21 deletions
diff --git a/security/apparmor/include/perms.h b/security/apparmor/include/perms.h index 2b27bb79aec4..d7b7e7115160 100644 --- a/security/apparmor/include/perms.h +++ b/security/apparmor/include/perms.h | |||
| @@ -133,6 +133,9 @@ extern struct aa_perms allperms; | |||
| 133 | #define xcheck_labels_profiles(L1, L2, FN, args...) \ | 133 | #define xcheck_labels_profiles(L1, L2, FN, args...) \ |
| 134 | xcheck_ns_labels((L1), (L2), xcheck_ns_profile_label, (FN), args) | 134 | xcheck_ns_labels((L1), (L2), xcheck_ns_profile_label, (FN), args) |
| 135 | 135 | ||
| 136 | #define xcheck_labels(L1, L2, P, FN1, FN2) \ | ||
| 137 | xcheck(fn_for_each((L1), (P), (FN1)), fn_for_each((L2), (P), (FN2))) | ||
| 138 | |||
| 136 | 139 | ||
| 137 | void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask); | 140 | void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask); |
| 138 | void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask); | 141 | void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask); |
diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c index 7ca0032e7ba9..b40678f3c1d5 100644 --- a/security/apparmor/ipc.c +++ b/security/apparmor/ipc.c | |||
| @@ -64,40 +64,48 @@ static void audit_ptrace_cb(struct audit_buffer *ab, void *va) | |||
| 64 | FLAGS_NONE, GFP_ATOMIC); | 64 | FLAGS_NONE, GFP_ATOMIC); |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | /* assumes check for PROFILE_MEDIATES is already done */ | ||
| 67 | /* TODO: conditionals */ | 68 | /* TODO: conditionals */ |
| 68 | static int profile_ptrace_perm(struct aa_profile *profile, | 69 | static int profile_ptrace_perm(struct aa_profile *profile, |
| 69 | struct aa_profile *peer, u32 request, | 70 | struct aa_label *peer, u32 request, |
| 70 | struct common_audit_data *sa) | 71 | struct common_audit_data *sa) |
| 71 | { | 72 | { |
| 72 | struct aa_perms perms = { }; | 73 | struct aa_perms perms = { }; |
| 73 | 74 | ||
| 74 | /* need because of peer in cross check */ | 75 | aad(sa)->peer = peer; |
| 75 | if (profile_unconfined(profile) || | 76 | aa_profile_match_label(profile, peer, AA_CLASS_PTRACE, request, |
| 76 | !PROFILE_MEDIATES(profile, AA_CLASS_PTRACE)) | ||
| 77 | return 0; | ||
| 78 | |||
| 79 | aad(sa)->peer = &peer->label; | ||
| 80 | aa_profile_match_label(profile, &peer->label, AA_CLASS_PTRACE, request, | ||
| 81 | &perms); | 77 | &perms); |
| 82 | aa_apply_modes_to_perms(profile, &perms); | 78 | aa_apply_modes_to_perms(profile, &perms); |
| 83 | return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb); | 79 | return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb); |
| 84 | } | 80 | } |
| 85 | 81 | ||
| 86 | static int cross_ptrace_perm(struct aa_profile *tracer, | 82 | static int profile_tracee_perm(struct aa_profile *tracee, |
| 87 | struct aa_profile *tracee, u32 request, | 83 | struct aa_label *tracer, u32 request, |
| 88 | struct common_audit_data *sa) | 84 | struct common_audit_data *sa) |
| 89 | { | 85 | { |
| 86 | if (profile_unconfined(tracee) || unconfined(tracer) || | ||
| 87 | !PROFILE_MEDIATES(tracee, AA_CLASS_PTRACE)) | ||
| 88 | return 0; | ||
| 89 | |||
| 90 | return profile_ptrace_perm(tracee, tracer, request, sa); | ||
| 91 | } | ||
| 92 | |||
| 93 | static int profile_tracer_perm(struct aa_profile *tracer, | ||
| 94 | struct aa_label *tracee, u32 request, | ||
| 95 | struct common_audit_data *sa) | ||
| 96 | { | ||
| 97 | if (profile_unconfined(tracer)) | ||
| 98 | return 0; | ||
| 99 | |||
| 90 | if (PROFILE_MEDIATES(tracer, AA_CLASS_PTRACE)) | 100 | if (PROFILE_MEDIATES(tracer, AA_CLASS_PTRACE)) |
| 91 | return xcheck(profile_ptrace_perm(tracer, tracee, request, sa), | 101 | return profile_ptrace_perm(tracer, tracee, request, sa); |
| 92 | profile_ptrace_perm(tracee, tracer, | 102 | |
| 93 | request << PTRACE_PERM_SHIFT, | 103 | /* profile uses the old style capability check for ptrace */ |
| 94 | sa)); | 104 | if (&tracer->label == tracee) |
| 95 | /* policy uses the old style capability check for ptrace */ | ||
| 96 | if (profile_unconfined(tracer) || tracer == tracee) | ||
| 97 | return 0; | 105 | return 0; |
| 98 | 106 | ||
| 99 | aad(sa)->label = &tracer->label; | 107 | aad(sa)->label = &tracer->label; |
| 100 | aad(sa)->peer = &tracee->label; | 108 | aad(sa)->peer = tracee; |
| 101 | aad(sa)->request = 0; | 109 | aad(sa)->request = 0; |
| 102 | aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, 1); | 110 | aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, 1); |
| 103 | 111 | ||
| @@ -115,10 +123,13 @@ static int cross_ptrace_perm(struct aa_profile *tracer, | |||
| 115 | int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, | 123 | int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, |
| 116 | u32 request) | 124 | u32 request) |
| 117 | { | 125 | { |
| 126 | struct aa_profile *profile; | ||
| 127 | u32 xrequest = request << PTRACE_PERM_SHIFT; | ||
| 118 | DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_PTRACE); | 128 | DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_PTRACE); |
| 119 | 129 | ||
| 120 | return xcheck_labels_profiles(tracer, tracee, cross_ptrace_perm, | 130 | return xcheck_labels(tracer, tracee, profile, |
| 121 | request, &sa); | 131 | profile_tracer_perm(profile, tracee, request, &sa), |
| 132 | profile_tracee_perm(profile, tracer, xrequest, &sa)); | ||
| 122 | } | 133 | } |
| 123 | 134 | ||
| 124 | 135 | ||
