Commit 2d9da9b1 authored by John Johansen's avatar John Johansen
Browse files

apparmor: allow restricting unprivileged change_profile



unprivileged unconfined can use change_profile to alter the confinement
set by the mac admin.

Allow restricting unprivileged unconfined by still allowing change_profile
but stacking the change against unconfined. This allows unconfined to
still apply system policy but allows the task to enter the new confinement.

If unprivileged unconfined is required a sysctl is provided to switch
to the previous behavior.

Reviewed-by: default avatarGeorgia Garcia <georgia.garcia@canonical.com>
Signed-off-by: default avatarJohn Johansen <john.johansen@canonical.com>
parent e105d807
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -2341,6 +2341,11 @@ static struct aa_sfs_entry aa_sfs_entry_domain[] = {
	{ }
};

static struct aa_sfs_entry aa_sfs_entry_unconfined[] = {
	AA_SFS_FILE_BOOLEAN("change_profile", 1),
	{ }
};

static struct aa_sfs_entry aa_sfs_entry_versions[] = {
	AA_SFS_FILE_BOOLEAN("v5",	1),
	AA_SFS_FILE_BOOLEAN("v6",	1),
@@ -2358,6 +2363,7 @@ static struct aa_sfs_entry aa_sfs_entry_policy[] = {
	AA_SFS_FILE_U64("outofband",		MAX_OOB_SUPPORTED),
	AA_SFS_FILE_U64("permstable32_version",	1),
	AA_SFS_FILE_STRING("permstable32", PERMS32STR),
	AA_SFS_DIR("unconfined_restrictions",   aa_sfs_entry_unconfined),
	{ }
};

+24 −0
Original line number Diff line number Diff line
@@ -1311,6 +1311,8 @@ static int change_profile_perms_wrapper(const char *op, const char *name,
	return error;
}

const char *stack_msg = "change_profile unprivileged unconfined converted to stacking";

/**
 * aa_change_profile - perform a one-way profile transition
 * @fqname: name of profile may include namespace (NOT NULL)
@@ -1370,6 +1372,28 @@ int aa_change_profile(const char *fqname, int flags)
			op = OP_CHANGE_PROFILE;
	}

	/* This should move to a per profile test. Requires pushing build
	 * into callback
	 */
	if (!stack && unconfined(label) &&
	    label == &labels_ns(label)->unconfined->label &&
	    aa_unprivileged_unconfined_restricted &&
	    /* TODO: refactor so this check is a fn */
	    cap_capable(current_cred(), &init_user_ns, CAP_MAC_OVERRIDE,
			CAP_OPT_NOAUDIT)) {
		/* regardless of the request in this case apparmor
		 * stacks against unconfined so admin set policy can't be
		 * by-passed
		 */
		stack = true;
		perms.audit = request;
		(void) fn_for_each_in_ns(label, profile,
				aa_audit_file(subj_cred, profile, &perms, op,
					      request, auditname, NULL, target,
					      GLOBAL_ROOT_UID, stack_msg, 0));
		perms.audit = 0;
	}

	if (*fqname == '&') {
		stack = true;
		/* don't have label_parse() do stacking */
+1 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
struct aa_ns;

extern int unprivileged_userns_apparmor_policy;
extern int aa_unprivileged_unconfined_restricted;

extern const char *const aa_profile_mode_names[];
#define APPARMOR_MODE_NAMES_MAX_INDEX 4
+7 −0
Original line number Diff line number Diff line
@@ -1798,6 +1798,13 @@ static struct ctl_table apparmor_sysctl_table[] = {
		.mode           = 0600,
		.proc_handler   = apparmor_dointvec,
	},
	{
		.procname       = "apparmor_restrict_unprivileged_unconfined",
		.data           = &aa_unprivileged_unconfined_restricted,
		.maxlen         = sizeof(int),
		.mode           = 0600,
		.proc_handler   = apparmor_dointvec,
	},

	{ }
};
+1 −0
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@
#include "include/resource.h"

int unprivileged_userns_apparmor_policy = 1;
int aa_unprivileged_unconfined_restricted;

const char *const aa_profile_mode_names[] = {
	"enforce",