Skip to content

Commit fa9b63a

Browse files
committed
apparmor: add user namespace creation mediation
Unprivileged user namespace creation is often used as a first step in privilege escalation attacks. Instead of disabling it at the sysrq level, which blocks its legitimate use as for setting up a sandbox, allow control on a per domain basis. This allows an admin to quickly lock down a system while also still allowing legitimate use. Reviewed-by: Georgia Garcia <georgia.garcia@canonical.com> Signed-off-by: John Johansen <john.johansen@canonical.com>
1 parent 2d9da9b commit fa9b63a

File tree

7 files changed

+75
-2
lines changed

7 files changed

+75
-2
lines changed

security/apparmor/apparmorfs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2375,6 +2375,7 @@ static struct aa_sfs_entry aa_sfs_entry_mount[] = {
23752375
static struct aa_sfs_entry aa_sfs_entry_ns[] = {
23762376
AA_SFS_FILE_BOOLEAN("profile", 1),
23772377
AA_SFS_FILE_BOOLEAN("pivot_root", 0),
2378+
AA_SFS_FILE_STRING("mask", "userns_create"),
23782379
{ }
23792380
};
23802381

security/apparmor/audit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ static const char *const aa_class_names[] = {
5858
"io_uring",
5959
"module",
6060
"lsm",
61-
"unknown",
61+
"namespace",
6262
"unknown",
6363
"unknown",
6464
"unknown",

security/apparmor/include/apparmor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#define AA_CLASS_IO_URING 18
3434
#define AA_CLASS_MODULE 19
3535
#define AA_CLASS_DISPLAY_LSM 20
36+
#define AA_CLASS_NS 21
3637

3738
#define AA_CLASS_X 31
3839
#define AA_CLASS_DBUS 32

security/apparmor/include/audit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ enum audit_type {
103103
#define OP_PROF_LOAD "profile_load"
104104
#define OP_PROF_RM "profile_remove"
105105

106+
#define OP_USERNS_CREATE "userns_create"
106107

107108
struct apparmor_audit_data {
108109
int error;

security/apparmor/include/task.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,10 @@ int aa_may_ptrace(const struct cred *tracer_cred, struct aa_label *tracer,
9696
u32 request);
9797

9898

99+
100+
#define AA_USERNS_CREATE 8
101+
102+
int aa_profile_ns_perm(struct aa_profile *profile,
103+
struct apparmor_audit_data *ad, u32 request);
104+
99105
#endif /* __AA_TASK_H */

security/apparmor/lsm.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,27 @@ static int apparmor_task_kill(struct task_struct *target, struct kernel_siginfo
836836
return error;
837837
}
838838

839+
static int apparmor_userns_create(const struct cred *cred)
840+
{
841+
struct aa_label *label;
842+
struct aa_profile *profile;
843+
int error = 0;
844+
DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_TASK, AA_CLASS_NS,
845+
OP_USERNS_CREATE);
846+
847+
ad.subj_cred = current_cred();
848+
849+
label = begin_current_label_crit_section();
850+
if (!unconfined(label)) {
851+
error = fn_for_each(label, profile,
852+
aa_profile_ns_perm(profile, &ad,
853+
AA_USERNS_CREATE));
854+
}
855+
end_current_label_crit_section(label);
856+
857+
return error;
858+
}
859+
839860
/**
840861
* apparmor_sk_alloc_security - allocate and attach the sk_security field
841862
*/
@@ -1313,6 +1334,7 @@ static struct security_hook_list apparmor_hooks[] __ro_after_init = {
13131334
LSM_HOOK_INIT(task_getsecid_obj, apparmor_task_getsecid_obj),
13141335
LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit),
13151336
LSM_HOOK_INIT(task_kill, apparmor_task_kill),
1337+
LSM_HOOK_INIT(userns_create, apparmor_userns_create),
13161338

13171339
#ifdef CONFIG_AUDIT
13181340
LSM_HOOK_INIT(audit_rule_init, aa_audit_rule_init),
@@ -1784,13 +1806,15 @@ static int apparmor_dointvec(struct ctl_table *table, int write,
17841806
}
17851807

17861808
static struct ctl_table apparmor_sysctl_table[] = {
1809+
#ifdef CONFIG_USER_NS
17871810
{
17881811
.procname = "unprivileged_userns_apparmor_policy",
17891812
.data = &unprivileged_userns_apparmor_policy,
17901813
.maxlen = sizeof(int),
17911814
.mode = 0600,
17921815
.proc_handler = apparmor_dointvec,
17931816
},
1817+
#endif /* CONFIG_USER_NS */
17941818
{
17951819
.procname = "apparmor_display_secid_mode",
17961820
.data = &apparmor_display_secid_mode,
@@ -1805,7 +1829,6 @@ static struct ctl_table apparmor_sysctl_table[] = {
18051829
.mode = 0600,
18061830
.proc_handler = apparmor_dointvec,
18071831
},
1808-
18091832
{ }
18101833
};
18111834

security/apparmor/task.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,3 +298,44 @@ int aa_may_ptrace(const struct cred *tracer_cred, struct aa_label *tracer,
298298
profile_tracee_perm(tracee_cred, profile, tracer,
299299
xrequest, &sa));
300300
}
301+
302+
/* call back to audit ptrace fields */
303+
static void audit_ns_cb(struct audit_buffer *ab, void *va)
304+
{
305+
struct apparmor_audit_data *ad = aad_of_va(va);
306+
307+
if (ad->request & AA_USERNS_CREATE)
308+
audit_log_format(ab, " requested=\"userns_create\"");
309+
310+
if (ad->denied & AA_USERNS_CREATE)
311+
audit_log_format(ab, " denied=\"userns_create\"");
312+
}
313+
314+
int aa_profile_ns_perm(struct aa_profile *profile,
315+
struct apparmor_audit_data *ad,
316+
u32 request)
317+
{
318+
struct aa_perms perms = { };
319+
int error = 0;
320+
321+
ad->subj_label = &profile->label;
322+
ad->request = request;
323+
324+
if (!profile_unconfined(profile)) {
325+
struct aa_ruleset *rules = list_first_entry(&profile->rules,
326+
typeof(*rules),
327+
list);
328+
aa_state_t state;
329+
330+
state = RULE_MEDIATES(rules, ad->class);
331+
if (!state)
332+
/* TODO: add flag to complain about unmediated */
333+
return 0;
334+
perms = *aa_lookup_perms(rules->policy, state);
335+
aa_apply_modes_to_perms(profile, &perms);
336+
error = aa_check_perms(profile, &perms, request, ad,
337+
audit_ns_cb);
338+
}
339+
340+
return error;
341+
}

0 commit comments

Comments
 (0)