diff mbox

[3/3] AppArmor: add support for generic perm query

Message ID 1313092788-31164-4-git-send-email-john.johansen@canonical.com
State New
Headers show

Commit Message

John Johansen Aug. 11, 2011, 7:59 p.m. UTC
The generic perm query allow userspace (if it has sufficient permissions) to
query what permissions are being enforced.  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 544aa6b..4221037 100644
--- a/security/apparmor/include/procattr.h
+++ b/security/apparmor/include/procattr.h
@@ -22,5 +22,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_permipc(char *fqname);
+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 7459547..bca1667 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,12 +571,18 @@  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) {
@@ -588,6 +590,8 @@  static int apparmor_setprocattr(struct task_struct *task, char *name,
 							     AA_DO_TEST);
 		} else if (strcmp(command, "permipc") == 0) {
 			error = aa_setprocattr_permipc(args);
+		} 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 04a2cf8..222e56a 100644
--- a/security/apparmor/procattr.c
+++ b/security/apparmor/procattr.c
@@ -168,3 +168,37 @@  int aa_setprocattr_permipc(char *fqname)
 	/* TODO: add ipc permission querying */
 	return -ENOTSUPP;
 }
+
+/**
+ * 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;
+}