Skip to content

Commit c70c86c

Browse files
committed
apparmor: move capability checks to using labels
Signed-off-by: John Johansen <[email protected]>
1 parent 317d9a0 commit c70c86c

File tree

5 files changed

+58
-29
lines changed

5 files changed

+58
-29
lines changed

security/apparmor/capability.c

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -48,32 +48,30 @@ static DEFINE_PER_CPU(struct audit_cache, audit_cache);
4848
static void audit_cb(struct audit_buffer *ab, void *va)
4949
{
5050
struct common_audit_data *sa = va;
51+
5152
audit_log_format(ab, " capname=");
5253
audit_log_untrustedstring(ab, capability_names[sa->u.cap]);
5354
}
5455

5556
/**
5657
* audit_caps - audit a capability
58+
* @sa: audit data
5759
* @profile: profile being tested for confinement (NOT NULL)
5860
* @cap: capability tested
59-
@audit: whether an audit record should be generated
6061
* @error: error code returned by test
6162
*
6263
* Do auditing of capability and handle, audit/complain/kill modes switching
6364
* and duplicate message elimination.
6465
*
6566
* Returns: 0 or sa->error on success, error code on failure
6667
*/
67-
static int audit_caps(struct aa_profile *profile, int cap, int audit,
68-
int error)
68+
static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile,
69+
int cap, int error)
6970
{
7071
struct audit_cache *ent;
7172
int type = AUDIT_APPARMOR_AUTO;
72-
DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_CAP, OP_CAPABLE);
73-
sa.u.cap = cap;
74-
aad(&sa)->error = error;
75-
if (audit == SECURITY_CAP_NOAUDIT)
76-
aad(&sa)->info = "optional: no audit";
73+
74+
aad(sa)->error = error;
7775

7876
if (likely(!error)) {
7977
/* test if auditing is being forced */
@@ -105,39 +103,60 @@ static int audit_caps(struct aa_profile *profile, int cap, int audit,
105103
}
106104
put_cpu_var(audit_cache);
107105

108-
return aa_audit(type, profile, &sa, audit_cb);
106+
return aa_audit(type, profile, sa, audit_cb);
109107
}
110108

111109
/**
112110
* profile_capable - test if profile allows use of capability @cap
113111
* @profile: profile being enforced (NOT NULL, NOT unconfined)
114112
* @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)
115115
*
116116
* Returns: 0 if allowed else -EPERM
117117
*/
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)
119120
{
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);
121139
}
122140

123141
/**
124142
* aa_capable - test permission to use capability
125-
* @profile: profile being tested against (NOT NULL)
143+
* @label: label being tested for capability (NOT NULL)
126144
* @cap: capability to be tested
127145
* @audit: whether an audit record should be generated
128146
*
129147
* Look up capability in profile capability set.
130148
*
131149
* Returns: 0 on success, or else an error code.
132150
*/
133-
int aa_capable(struct aa_profile *profile, int cap, int audit)
151+
int aa_capable(struct aa_label *label, int cap, int audit)
134152
{
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);
136156

137-
if (audit == SECURITY_CAP_NOAUDIT) {
138-
if (!COMPLAIN_MODE(profile))
139-
return error;
140-
}
157+
sa.u.cap = cap;
158+
error = fn_for_each_confined(label, profile,
159+
profile_capable(profile, cap, audit, &sa));
141160

142-
return audit_caps(profile, cap, audit, error);
161+
return error;
143162
}

security/apparmor/include/capability.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,28 @@
1919

2020
#include "apparmorfs.h"
2121

22-
struct aa_profile;
22+
struct aa_label;
2323

2424
/* aa_caps - confinement data for capabilities
2525
* @allowed: capabilities mask
2626
* @audit: caps that are to be audited
27+
* @denied: caps that are explicitly denied
2728
* @quiet: caps that should not be audited
2829
* @kill: caps that when requested will result in the task being killed
2930
* @extended: caps that are subject finer grained mediation
3031
*/
3132
struct aa_caps {
3233
kernel_cap_t allow;
3334
kernel_cap_t audit;
35+
kernel_cap_t denied;
3436
kernel_cap_t quiet;
3537
kernel_cap_t kill;
3638
kernel_cap_t extended;
3739
};
3840

3941
extern struct aa_sfs_entry aa_sfs_entry_caps[];
4042

41-
int aa_capable(struct aa_profile *profile, int cap, int audit);
43+
int aa_capable(struct aa_label *label, int cap, int audit);
4244

4345
static inline void aa_free_cap_rules(struct aa_caps *caps)
4446
{

security/apparmor/ipc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ int aa_may_ptrace(struct aa_profile *tracer, struct aa_profile *tracee,
6868
if (profile_unconfined(tracer) || tracer == tracee)
6969
return 0;
7070
/* log this capability request */
71-
return aa_capable(tracer, CAP_SYS_PTRACE, 1);
71+
return aa_capable(&tracer->label, CAP_SYS_PTRACE, 1);
7272
}
7373

7474
/**

security/apparmor/lsm.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,20 +117,28 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
117117
kernel_cap_t *inheritable, kernel_cap_t *permitted)
118118
{
119119
struct aa_label *label;
120-
struct aa_profile *profile;
121120
const struct cred *cred;
122121

123122
rcu_read_lock();
124123
cred = __task_cred(target);
125124
label = aa_get_newest_cred_label(cred);
126-
profile = labels_profile(label);
125+
127126
/*
128127
* cap_capget is stacked ahead of this and will
129128
* initialize effective and permitted.
130129
*/
131-
if (!profile_unconfined(profile) && !COMPLAIN_MODE(profile)) {
132-
*effective = cap_intersect(*effective, profile->caps.allow);
133-
*permitted = cap_intersect(*permitted, profile->caps.allow);
130+
if (!unconfined(label)) {
131+
struct aa_profile *profile;
132+
struct label_it i;
133+
134+
label_for_each_confined(i, label, profile) {
135+
if (COMPLAIN_MODE(profile))
136+
continue;
137+
*effective = cap_intersect(*effective,
138+
profile->caps.allow);
139+
*permitted = cap_intersect(*permitted,
140+
profile->caps.allow);
141+
}
134142
}
135143
rcu_read_unlock();
136144
aa_put_label(label);
@@ -146,7 +154,7 @@ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns,
146154

147155
label = aa_get_newest_cred_label(cred);
148156
if (!unconfined(label))
149-
error = aa_capable(labels_profile(label), cap, audit);
157+
error = aa_capable(label, cap, audit);
150158
aa_put_label(label);
151159

152160
return error;

security/apparmor/resource.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task,
100100
* task has CAP_SYS_RESOURCE.
101101
*/
102102
if ((profile != labels_profile(task_label) &&
103-
aa_capable(profile, CAP_SYS_RESOURCE, 1)) ||
103+
aa_capable(&profile->label, CAP_SYS_RESOURCE, 1)) ||
104104
(profile->rlimits.mask & (1 << resource) &&
105105
new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max))
106106
error = -EACCES;

0 commit comments

Comments
 (0)