Skip to content

Commit 86b92cb

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

File tree

3 files changed

+80
-42
lines changed

3 files changed

+80
-42
lines changed

security/apparmor/include/resource.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ struct aa_rlimit {
3737
extern struct aa_sfs_entry aa_sfs_entry_rlimit[];
3838

3939
int aa_map_resource(int resource);
40-
int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *,
40+
int aa_task_setrlimit(struct aa_label *label, struct task_struct *task,
4141
unsigned int resource, struct rlimit *new_rlim);
4242

43-
void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new);
43+
void __aa_transition_rlimits(struct aa_label *old, struct aa_label *new);
4444

4545
static inline void aa_free_rlimit_rules(struct aa_rlimit *rlims)
4646
{

security/apparmor/lsm.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -625,8 +625,7 @@ static void apparmor_bprm_committing_creds(struct linux_binprm *bprm)
625625
current->pdeath_signal = 0;
626626

627627
/* reset soft limits and set hard limits for the new label */
628-
__aa_transition_rlimits(labels_profile(label),
629-
labels_profile(new_ctx->label));
628+
__aa_transition_rlimits(label, new_ctx->label);
630629
}
631630

632631
/**
@@ -646,8 +645,7 @@ static int apparmor_task_setrlimit(struct task_struct *task,
646645
int error = 0;
647646

648647
if (!unconfined(label))
649-
error = aa_task_setrlimit(labels_profile(label), task,
650-
resource, new_rlim);
648+
error = aa_task_setrlimit(label, task, resource, new_rlim);
651649
__end_current_label_crit_section(label);
652650

653651
return error;

security/apparmor/resource.c

Lines changed: 76 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
*/
1414

1515
#include <linux/audit.h>
16+
#include <linux/security.h>
1617

1718
#include "include/audit.h"
1819
#include "include/context.h"
@@ -36,6 +37,11 @@ static void audit_cb(struct audit_buffer *ab, void *va)
3637

3738
audit_log_format(ab, " rlimit=%s value=%lu",
3839
rlim_names[aad(sa)->rlim.rlim], aad(sa)->rlim.max);
40+
if (aad(sa)->peer) {
41+
audit_log_format(ab, " peer=");
42+
aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
43+
FLAGS_NONE, GFP_ATOMIC);
44+
}
3945
}
4046

4147
/**
@@ -48,13 +54,17 @@ static void audit_cb(struct audit_buffer *ab, void *va)
4854
* Returns: 0 or sa->error else other error code on failure
4955
*/
5056
static int audit_resource(struct aa_profile *profile, unsigned int resource,
51-
unsigned long value, int error)
57+
unsigned long value, struct aa_label *peer,
58+
const char *info, int error)
5259
{
5360
DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_SETRLIMIT);
5461

5562
aad(&sa)->rlim.rlim = resource;
5663
aad(&sa)->rlim.max = value;
64+
aad(&sa)->peer = peer;
65+
aad(&sa)->info = info;
5766
aad(&sa)->error = error;
67+
5868
return aa_audit(AUDIT_APPARMOR_AUTO, profile, &sa, audit_cb);
5969
}
6070

@@ -72,9 +82,21 @@ int aa_map_resource(int resource)
7282
return rlim_map[resource];
7383
}
7484

85+
static int profile_setrlimit(struct aa_profile *profile, unsigned int resource,
86+
struct rlimit *new_rlim)
87+
{
88+
int e = 0;
89+
90+
if (profile->rlimits.mask & (1 << resource) && new_rlim->rlim_max >
91+
profile->rlimits.limits[resource].rlim_max)
92+
e = -EACCES;
93+
return audit_resource(profile, resource, new_rlim->rlim_max, NULL, NULL,
94+
e);
95+
}
96+
7597
/**
7698
* aa_task_setrlimit - test permission to set an rlimit
77-
* @profile - profile confining the task (NOT NULL)
99+
* @label - label confining the task (NOT NULL)
78100
* @task - task the resource is being set on
79101
* @resource - the resource being set
80102
* @new_rlim - the new resource limit (NOT NULL)
@@ -83,14 +105,15 @@ int aa_map_resource(int resource)
83105
*
84106
* Returns: 0 or error code if setting resource failed
85107
*/
86-
int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task,
108+
int aa_task_setrlimit(struct aa_label *label, struct task_struct *task,
87109
unsigned int resource, struct rlimit *new_rlim)
88110
{
89-
struct aa_label *task_label;
111+
struct aa_profile *profile;
112+
struct aa_label *peer;
90113
int error = 0;
91114

92115
rcu_read_lock();
93-
task_label = aa_get_newest_cred_label((__task_cred(task)));
116+
peer = aa_get_newest_cred_label(__task_cred(task));
94117
rcu_read_unlock();
95118

96119
/* TODO: extend resource control to handle other (non current)
@@ -99,53 +122,70 @@ int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task,
99122
* the same profile or that the task setting the resource of another
100123
* task has CAP_SYS_RESOURCE.
101124
*/
102-
if ((profile != labels_profile(task_label) &&
103-
aa_capable(&profile->label, CAP_SYS_RESOURCE, 1)) ||
104-
(profile->rlimits.mask & (1 << resource) &&
105-
new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max))
106-
error = -EACCES;
107125

108-
aa_put_label(task_label);
109-
110-
return audit_resource(profile, resource, new_rlim->rlim_max, error);
126+
if (label != peer &&
127+
!aa_capable(label, CAP_SYS_RESOURCE, SECURITY_CAP_NOAUDIT))
128+
error = fn_for_each(label, profile,
129+
audit_resource(profile, resource,
130+
new_rlim->rlim_max, peer,
131+
"cap_sys_resoure", -EACCES));
132+
else
133+
error = fn_for_each_confined(label, profile,
134+
profile_setrlimit(profile, resource, new_rlim));
135+
aa_put_label(peer);
136+
137+
return error;
111138
}
112139

113140
/**
114141
* __aa_transition_rlimits - apply new profile rlimits
115-
* @old: old profile on task (NOT NULL)
116-
* @new: new profile with rlimits to apply (NOT NULL)
142+
* @old_l: old label on task (NOT NULL)
143+
* @new_l: new label with rlimits to apply (NOT NULL)
117144
*/
118-
void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new)
145+
void __aa_transition_rlimits(struct aa_label *old_l, struct aa_label *new_l)
119146
{
120147
unsigned int mask = 0;
121148
struct rlimit *rlim, *initrlim;
122-
int i;
149+
struct aa_profile *old, *new;
150+
struct label_it i;
151+
152+
old = labels_profile(old_l);
153+
new = labels_profile(new_l);
123154

124-
/* for any rlimits the profile controlled reset the soft limit
125-
* to the less of the tasks hard limit and the init tasks soft limit
155+
/* for any rlimits the profile controlled, reset the soft limit
156+
* to the lesser of the tasks hard limit and the init tasks soft limit
126157
*/
127-
if (old->rlimits.mask) {
128-
for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) {
129-
if (old->rlimits.mask & mask) {
130-
rlim = current->signal->rlim + i;
131-
initrlim = init_task.signal->rlim + i;
132-
rlim->rlim_cur = min(rlim->rlim_max,
133-
initrlim->rlim_cur);
158+
label_for_each_confined(i, old_l, old) {
159+
if (old->rlimits.mask) {
160+
int j;
161+
162+
for (j = 0, mask = 1; j < RLIM_NLIMITS; j++,
163+
mask <<= 1) {
164+
if (old->rlimits.mask & mask) {
165+
rlim = current->signal->rlim + j;
166+
initrlim = init_task.signal->rlim + j;
167+
rlim->rlim_cur = min(rlim->rlim_max,
168+
initrlim->rlim_cur);
169+
}
134170
}
135171
}
136172
}
137173

138174
/* set any new hard limits as dictated by the new profile */
139-
if (!new->rlimits.mask)
140-
return;
141-
for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) {
142-
if (!(new->rlimits.mask & mask))
143-
continue;
175+
label_for_each_confined(i, new_l, new) {
176+
int j;
144177

145-
rlim = current->signal->rlim + i;
146-
rlim->rlim_max = min(rlim->rlim_max,
147-
new->rlimits.limits[i].rlim_max);
148-
/* soft limit should not exceed hard limit */
149-
rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max);
178+
if (!new->rlimits.mask)
179+
continue;
180+
for (j = 0, mask = 1; j < RLIM_NLIMITS; j++, mask <<= 1) {
181+
if (!(new->rlimits.mask & mask))
182+
continue;
183+
184+
rlim = current->signal->rlim + j;
185+
rlim->rlim_max = min(rlim->rlim_max,
186+
new->rlimits.limits[j].rlim_max);
187+
/* soft limit should not exceed hard limit */
188+
rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max);
189+
}
150190
}
151191
}

0 commit comments

Comments
 (0)