diff options
Diffstat (limited to 'security/apparmor/capability.c')
| -rw-r--r-- | security/apparmor/capability.c | 61 |
1 files changed, 40 insertions, 21 deletions
diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c index ed0a3e6b8022..67e347192a55 100644 --- a/security/apparmor/capability.c +++ b/security/apparmor/capability.c | |||
| @@ -28,8 +28,8 @@ | |||
| 28 | */ | 28 | */ |
| 29 | #include "capability_names.h" | 29 | #include "capability_names.h" |
| 30 | 30 | ||
| 31 | struct aa_fs_entry aa_fs_entry_caps[] = { | 31 | struct aa_sfs_entry aa_sfs_entry_caps[] = { |
| 32 | AA_FS_FILE_STRING("mask", AA_FS_CAPS_MASK), | 32 | AA_SFS_FILE_STRING("mask", AA_SFS_CAPS_MASK), |
| 33 | { } | 33 | { } |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| @@ -48,15 +48,16 @@ static DEFINE_PER_CPU(struct audit_cache, audit_cache); | |||
| 48 | static void audit_cb(struct audit_buffer *ab, void *va) | 48 | static void audit_cb(struct audit_buffer *ab, void *va) |
| 49 | { | 49 | { |
| 50 | struct common_audit_data *sa = va; | 50 | struct common_audit_data *sa = va; |
| 51 | |||
| 51 | audit_log_format(ab, " capname="); | 52 | audit_log_format(ab, " capname="); |
| 52 | audit_log_untrustedstring(ab, capability_names[sa->u.cap]); | 53 | audit_log_untrustedstring(ab, capability_names[sa->u.cap]); |
| 53 | } | 54 | } |
| 54 | 55 | ||
| 55 | /** | 56 | /** |
| 56 | * audit_caps - audit a capability | 57 | * audit_caps - audit a capability |
| 58 | * @sa: audit data | ||
| 57 | * @profile: profile being tested for confinement (NOT NULL) | 59 | * @profile: profile being tested for confinement (NOT NULL) |
| 58 | * @cap: capability tested | 60 | * @cap: capability tested |
| 59 | @audit: whether an audit record should be generated | ||
| 60 | * @error: error code returned by test | 61 | * @error: error code returned by test |
| 61 | * | 62 | * |
| 62 | * Do auditing of capability and handle, audit/complain/kill modes switching | 63 | * Do auditing of capability and handle, audit/complain/kill modes switching |
| @@ -64,16 +65,13 @@ static void audit_cb(struct audit_buffer *ab, void *va) | |||
| 64 | * | 65 | * |
| 65 | * Returns: 0 or sa->error on success, error code on failure | 66 | * Returns: 0 or sa->error on success, error code on failure |
| 66 | */ | 67 | */ |
| 67 | static int audit_caps(struct aa_profile *profile, int cap, int audit, | 68 | static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile, |
| 68 | int error) | 69 | int cap, int error) |
| 69 | { | 70 | { |
| 70 | struct audit_cache *ent; | 71 | struct audit_cache *ent; |
| 71 | int type = AUDIT_APPARMOR_AUTO; | 72 | int type = AUDIT_APPARMOR_AUTO; |
| 72 | DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_CAP, OP_CAPABLE); | 73 | |
| 73 | sa.u.cap = cap; | 74 | aad(sa)->error = error; |
| 74 | aad(&sa)->error = error; | ||
| 75 | if (audit == SECURITY_CAP_NOAUDIT) | ||
| 76 | aad(&sa)->info = "optional: no audit"; | ||
| 77 | 75 | ||
| 78 | if (likely(!error)) { | 76 | if (likely(!error)) { |
| 79 | /* test if auditing is being forced */ | 77 | /* test if auditing is being forced */ |
| @@ -105,24 +103,44 @@ static int audit_caps(struct aa_profile *profile, int cap, int audit, | |||
| 105 | } | 103 | } |
| 106 | put_cpu_var(audit_cache); | 104 | put_cpu_var(audit_cache); |
| 107 | 105 | ||
| 108 | return aa_audit(type, profile, &sa, audit_cb); | 106 | return aa_audit(type, profile, sa, audit_cb); |
| 109 | } | 107 | } |
| 110 | 108 | ||
| 111 | /** | 109 | /** |
| 112 | * profile_capable - test if profile allows use of capability @cap | 110 | * profile_capable - test if profile allows use of capability @cap |
| 113 | * @profile: profile being enforced (NOT NULL, NOT unconfined) | 111 | * @profile: profile being enforced (NOT NULL, NOT unconfined) |
| 114 | * @cap: capability to test if allowed | 112 | * @cap: capability to test if allowed |
| 113 | * @audit: whether an audit record should be generated | ||
| 114 | * @sa: audit data (MAY BE NULL indicating no auditing) | ||
| 115 | * | 115 | * |
| 116 | * Returns: 0 if allowed else -EPERM | 116 | * Returns: 0 if allowed else -EPERM |
| 117 | */ | 117 | */ |
| 118 | static int profile_capable(struct aa_profile *profile, int cap) | 118 | static int profile_capable(struct aa_profile *profile, int cap, int audit, |
| 119 | struct common_audit_data *sa) | ||
| 119 | { | 120 | { |
| 120 | return cap_raised(profile->caps.allow, cap) ? 0 : -EPERM; | 121 | int error; |
| 122 | |||
| 123 | if (cap_raised(profile->caps.allow, cap) && | ||
| 124 | !cap_raised(profile->caps.denied, cap)) | ||
| 125 | error = 0; | ||
| 126 | else | ||
| 127 | error = -EPERM; | ||
| 128 | |||
| 129 | if (audit == SECURITY_CAP_NOAUDIT) { | ||
| 130 | if (!COMPLAIN_MODE(profile)) | ||
| 131 | return error; | ||
| 132 | /* audit the cap request in complain mode but note that it | ||
| 133 | * should be optional. | ||
| 134 | */ | ||
| 135 | aad(sa)->info = "optional: no audit"; | ||
| 136 | } | ||
| 137 | |||
| 138 | return audit_caps(sa, profile, cap, error); | ||
| 121 | } | 139 | } |
| 122 | 140 | ||
| 123 | /** | 141 | /** |
| 124 | * aa_capable - test permission to use capability | 142 | * aa_capable - test permission to use capability |
| 125 | * @profile: profile being tested against (NOT NULL) | 143 | * @label: label being tested for capability (NOT NULL) |
| 126 | * @cap: capability to be tested | 144 | * @cap: capability to be tested |
| 127 | * @audit: whether an audit record should be generated | 145 | * @audit: whether an audit record should be generated |
| 128 | * | 146 | * |
| @@ -130,14 +148,15 @@ static int profile_capable(struct aa_profile *profile, int cap) | |||
| 130 | * | 148 | * |
| 131 | * Returns: 0 on success, or else an error code. | 149 | * Returns: 0 on success, or else an error code. |
| 132 | */ | 150 | */ |
| 133 | int aa_capable(struct aa_profile *profile, int cap, int audit) | 151 | int aa_capable(struct aa_label *label, int cap, int audit) |
| 134 | { | 152 | { |
| 135 | int error = profile_capable(profile, cap); | 153 | struct aa_profile *profile; |
| 154 | int error = 0; | ||
| 155 | DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_CAP, OP_CAPABLE); | ||
| 136 | 156 | ||
| 137 | if (audit == SECURITY_CAP_NOAUDIT) { | 157 | sa.u.cap = cap; |
| 138 | if (!COMPLAIN_MODE(profile)) | 158 | error = fn_for_each_confined(label, profile, |
| 139 | return error; | 159 | profile_capable(profile, cap, audit, &sa)); |
| 140 | } | ||
| 141 | 160 | ||
| 142 | return audit_caps(profile, cap, audit, error); | 161 | return error; |
| 143 | } | 162 | } |
