summary refs log tree commit diff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/apparmor/apparmorfs.c1
-rw-r--r--security/apparmor/domain.c61
-rw-r--r--security/apparmor/include/domain.h4
-rw-r--r--security/apparmor/lsm.c12
-rw-r--r--security/apparmor/procattr.c16
5 files changed, 28 insertions, 66 deletions
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index fd0d9e38b6c6..7613a28f157e 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -1052,6 +1052,7 @@ static struct aa_fs_entry aa_fs_entry_domain[] = {
 	AA_FS_FILE_BOOLEAN("change_onexec",	1),
 	AA_FS_FILE_BOOLEAN("change_profile",	1),
 	AA_FS_FILE_BOOLEAN("fix_binfmt_elf_mmap",	1),
+	AA_FS_FILE_STRING("version", "1.2"),
 	{ }
 };
 
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index d18b3f0e5534..ef4beef06e9d 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -729,8 +729,7 @@ out:
 
 /**
  * aa_change_profile - perform a one-way profile transition
- * @ns_name: name of the profile namespace to change to (MAYBE NULL)
- * @hname: name of profile to change to (MAYBE NULL)
+ * @fqname: name of profile may include namespace (NOT NULL)
  * @onexec: whether this transition is to take place immediately or at exec
  * @permtest: true if this is just a permission test
  *
@@ -742,19 +741,20 @@ out:
  *
  * Returns %0 on success, error otherwise.
  */
-int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
-		      bool permtest)
+int aa_change_profile(const char *fqname, bool onexec,
+		      bool permtest, bool stack)
 {
 	const struct cred *cred;
 	struct aa_profile *profile, *target = NULL;
-	struct aa_ns *ns = NULL;
 	struct file_perms perms = {};
-	const char *name = NULL, *info = NULL, *op;
+	const char *info = NULL, *op;
 	int error = 0;
 	u32 request;
 
-	if (!hname && !ns_name)
+	if (!fqname || !*fqname) {
+		AA_DEBUG("no profile name");
 		return -EINVAL;
+	}
 
 	if (onexec) {
 		request = AA_MAY_ONEXEC;
@@ -779,44 +779,15 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
 		return -EPERM;
 	}
 
-	if (ns_name) {
-		/* released below */
-		ns = aa_find_ns(profile->ns, ns_name);
-		if (!ns) {
-			/* we don't create new namespace in complain mode */
-			name = ns_name;
-			info = "namespace not found";
-			error = -ENOENT;
-			goto audit;
-		}
-	} else
-		/* released below */
-		ns = aa_get_ns(profile->ns);
-
-	/* if the name was not specified, use the name of the current profile */
-	if (!hname) {
-		if (unconfined(profile))
-			hname = ns->unconfined->base.hname;
-		else
-			hname = profile->base.hname;
-	}
-
-	perms = change_profile_perms(profile, ns, hname, request,
-				     profile->file.start);
-	if (!(perms.allow & request)) {
-		error = -EACCES;
-		goto audit;
-	}
-
-	/* released below */
-	target = aa_lookup_profile(ns, hname);
+	target = aa_fqlookupn_profile(profile, fqname, strlen(fqname));
 	if (!target) {
 		info = "profile not found";
 		error = -ENOENT;
 		if (permtest || !COMPLAIN_MODE(profile))
 			goto audit;
 		/* released below */
-		target = aa_new_null_profile(profile, false, hname, GFP_KERNEL);
+		target = aa_new_null_profile(profile, false, fqname,
+					     GFP_KERNEL);
 		if (!target) {
 			info = "failed null profile create";
 			error = -ENOMEM;
@@ -824,6 +795,13 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
 		}
 	}
 
+	perms = change_profile_perms(profile, target->ns, target->base.hname,
+				     request, profile->file.start);
+	if (!(perms.allow & request)) {
+		error = -EACCES;
+		goto audit;
+	}
+
 	/* check if tracing task is allowed to trace target domain */
 	error = may_change_ptraced_domain(target);
 	if (error) {
@@ -841,10 +819,9 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
 
 audit:
 	if (!permtest)
-		error = aa_audit_file(profile, &perms, op, request, name,
-				      hname, GLOBAL_ROOT_UID, info, error);
+		error = aa_audit_file(profile, &perms, op, request, NULL,
+				      fqname, GLOBAL_ROOT_UID, info, error);
 
-	aa_put_ns(ns);
 	aa_put_profile(target);
 	put_cred(cred);
 
diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h
index de04464f0a3f..30544729878a 100644
--- a/security/apparmor/include/domain.h
+++ b/security/apparmor/include/domain.h
@@ -30,7 +30,7 @@ void apparmor_bprm_committed_creds(struct linux_binprm *bprm);
 
 void aa_free_domain_entries(struct aa_domain *domain);
 int aa_change_hat(const char *hats[], int count, u64 token, bool permtest);
-int aa_change_profile(const char *ns_name, const char *name, bool onexec,
-		      bool permtest);
+int aa_change_profile(const char *fqname, bool onexec, bool permtest,
+		      bool stack);
 
 #endif /* __AA_DOMAIN_H */
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index c4bae8ae538f..264aa192032e 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -543,17 +543,17 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
 			error = aa_setprocattr_changehat(args, arg_size,
 							 AA_DO_TEST);
 		} else if (strcmp(command, "changeprofile") == 0) {
-			error = aa_setprocattr_changeprofile(args, !AA_ONEXEC,
-							     !AA_DO_TEST);
+			error = aa_change_profile(args, !AA_ONEXEC,
+						  !AA_DO_TEST, false);
 		} else if (strcmp(command, "permprofile") == 0) {
-			error = aa_setprocattr_changeprofile(args, !AA_ONEXEC,
-							     AA_DO_TEST);
+			error = aa_change_profile(args, !AA_ONEXEC, AA_DO_TEST,
+						  false);
 		} else
 			goto fail;
 	} else if (strcmp(name, "exec") == 0) {
 		if (strcmp(command, "exec") == 0)
-			error = aa_setprocattr_changeprofile(args, AA_ONEXEC,
-							     !AA_DO_TEST);
+			error = aa_change_profile(args, AA_ONEXEC, !AA_DO_TEST,
+						  false);
 		else
 			goto fail;
 	} else
diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c
index a9a9ee6659ae..3466a27bca09 100644
--- a/security/apparmor/procattr.c
+++ b/security/apparmor/procattr.c
@@ -149,19 +149,3 @@ int aa_setprocattr_changehat(char *args, size_t size, int test)
 
 	return aa_change_hat(hats, count, token, test);
 }
-
-/**
- * aa_setprocattr_changeprofile - handle procattr interface to changeprofile
- * @fqname: args received from writting to /proc/<pid>/attr/current (NOT NULL)
- * @onexec: true if change_profile should be delayed until exec
- * @test: true if this is a test of change_profile permissions
- *
- * Returns: %0 or error code if change_profile fails
- */
-int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test)
-{
-	char *name, *ns_name;
-
-	name = aa_split_fqname(fqname, &ns_name);
-	return aa_change_profile(ns_name, name, onexec, test);
-}