diff mbox

[13/13] AppArmor: add support for generic perm query again current profile

Message ID 1313038967-19941-14-git-send-email-john.johansen@canonical.com
State New
Headers show

Commit Message

John Johansen Aug. 11, 2011, 5:02 a.m. UTC
The generic perm query replaces the remove perm_ipc.  Also while only the
current task may set its security context, allow any task with sufficient
perms to query if the security context could be set.

Signed-off-by: John Johansen <john.johansen@canonical.com>
---
 security/apparmor/file.c             |    2 +-
 security/apparmor/include/file.h     |    2 ++
 security/apparmor/include/procattr.h |    1 +
 security/apparmor/lsm.c              |   12 ++++++++----
 security/apparmor/procattr.c         |   34 ++++++++++++++++++++++++++++++++++
 5 files changed, 46 insertions(+), 5 deletions(-)
diff mbox

Patch

diff --git a/security/apparmor/file.c b/security/apparmor/file.c
index 7312db7..2692333 100644
--- a/security/apparmor/file.c
+++ b/security/apparmor/file.c
@@ -155,7 +155,7 @@  int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
  *
  * Returns: new permission mapping
  */
-static u32 map_old_perms(u32 old)
+u32 map_old_perms(u32 old)
 {
 	u32 new = old & 0xf;
 	if (old & MAY_READ)
diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h
index ab8c6d8..632fdfb 100644
--- a/security/apparmor/include/file.h
+++ b/security/apparmor/include/file.h
@@ -186,6 +186,8 @@  static inline void aa_free_file_rules(struct aa_file_rules *rules)
 	aa_free_domain_entries(&rules->trans);
 }
 
+u32 map_old_perms(u32 old);
+
 #define ACC_FMODE(x) (("\000\004\002\006"[(x)&O_ACCMODE]) | (((x) << 1) & 0x40))
 
 /* from namei.c */
diff --git a/security/apparmor/include/procattr.h b/security/apparmor/include/procattr.h
index 6bd5f33..224ffea 100644
--- a/security/apparmor/include/procattr.h
+++ b/security/apparmor/include/procattr.h
@@ -21,5 +21,6 @@ 
 int aa_getprocattr(struct aa_profile *profile, char **string);
 int aa_setprocattr_changehat(char *args, size_t size, int test);
 int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test);
+int aa_setprocattr_perm(char *fqname, size_t size);
 
 #endif /* __AA_PROCATTR_H */
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 93dea4d..29f6378 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -559,10 +559,6 @@  static int apparmor_setprocattr(struct task_struct *task, char *name,
 		args[size] = '\0';
 	}
 
-	/* task can only write its own attributes */
-	if (current != task)
-		return -EACCES;
-
 	args = value;
 	args = strim(args);
 	command = strsep(&args, " ");
@@ -575,17 +571,25 @@  static int apparmor_setprocattr(struct task_struct *task, char *name,
 	arg_size = size - (args - (char *) value);
 	if (strcmp(name, "current") == 0) {
 		if (strcmp(command, "changehat") == 0) {
+			/* task can only write its own attributes */
+			if (current != task)
+				return -EACCES;
 			error = aa_setprocattr_changehat(args, arg_size,
 							 !AA_DO_TEST);
 		} else if (strcmp(command, "permhat") == 0) {
 			error = aa_setprocattr_changehat(args, arg_size,
 							 AA_DO_TEST);
 		} else if (strcmp(command, "changeprofile") == 0) {
+			/* task can only write its own attributes */
+			if (current != task)
+				return -EACCES;
 			error = aa_setprocattr_changeprofile(args, !AA_ONEXEC,
 							     !AA_DO_TEST);
 		} else if (strcmp(command, "permprofile") == 0) {
 			error = aa_setprocattr_changeprofile(args, !AA_ONEXEC,
 							     AA_DO_TEST);
+		} else if (strcmp(command, "perm") == 0) {
+			error = aa_setprocattr_perm(args, arg_size);
 		} else {
 			struct common_audit_data sa;
 			COMMON_AUDIT_DATA_INIT(&sa, NONE);
diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c
index 344970a..4ca37bc 100644
--- a/security/apparmor/procattr.c
+++ b/security/apparmor/procattr.c
@@ -162,3 +162,37 @@  int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test)
 	name = aa_split_fqname(fqname, &ns_name);
 	return aa_change_profile(ns_name, name, onexec, test);
 }
+
+/**
+ * aa_setprocattr_perm - generic perm test can be used to determine transition
+ * @args: args from writting to /proc/<pid>/attr/current (NOT NULL)
+ * @size: size of the args
+ */
+int aa_setprocattr_perm(char *args, size_t size)
+{
+	struct aa_profile *profile;
+	char *permstr, *val = args;
+	u32 mask, perms;
+	unsigned int state;
+
+	if (!args)
+		return -EINVAL;
+	permstr = strsep(&val, " ");
+	if (!val)
+		return -EINVAL;
+	mask = simple_strtoul(permstr, NULL, 0);
+	size -= val - args;
+
+	profile = aa_current_profile();
+	if (profile->policy) {
+		state = aa_dfa_match_len(profile->policy, profile->policy_start,
+					 args, size);
+		perms = map_old_perms(dfa_user_allow(profile->policy, state));
+	} else
+		perms = 0;
+
+	if (mask & ~perms)
+		return -EACCES;
+
+	return 0;
+}