[apparmor] [PATCH 34/36] apparmor: update profile permission query interface to use labels

John Johansen john.johansen at canonical.com
Wed May 1 21:31:19 UTC 2013


Signed-off-by: John Johansen <john.johansen at canonical.com>
---
 security/apparmor/apparmorfs.c | 101 +++++++++++++++++++++--------------------
 1 file changed, 53 insertions(+), 48 deletions(-)

diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 917e5ec..e3bef94 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -186,7 +186,7 @@ static const struct file_operations aa_fs_profile_remove = {
 };
 
 /**
- * query_profile - queries a profile and writes permissions to buf
+ * query_label - queries a label and writes permissions to buf
  * @buf: the resulting permissions string is stored here (NOT NULL)
  * @buf_len: size of buf
  * @query: binary query string to match against the dfa
@@ -195,67 +195,72 @@ static const struct file_operations aa_fs_profile_remove = {
  * The buffers pointed to by buf and query may overlap. The query buffer is
  * parsed before buf is written to.
  *
- * The query should look like "PROFILE_NAME\0DFA_STRING" where PROFILE_NAME is
- * the name of the profile, in the current namespace, that is to be queried and
- * DFA_STRING is a binary string to match against the profile's DFA.
+ * The query should look like "LABEL_NAME\0DFA_STRING" where LABEL_NAME is
+ * the name of the label, in the current namespace, that is to be queried and
+ * DFA_STRING is a binary string to match against the label(s)'s DFA.
  *
- * PROFILE_NAME must be NUL terminated. DFA_STRING may contain NUL characters
+ * LABEL_NAME must be NUL terminated. DFA_STRING may contain NUL characters
  * but must *not* be NUL terminated.
  *
  * Returns: number of characters written to buf or -errno on failure
  */
-static ssize_t query_profile(char *buf, size_t buf_len,
-			     char *query, size_t query_len)
+static ssize_t query_label(char *buf, size_t buf_len,
+			   char *query, size_t query_len)
 {
 	struct aa_profile *profile;
-	char *profile_name;
-	size_t profile_name_len;
-	u32 allow, audit, quiet;
+	struct aa_label *label;
+	struct aa_namespace *ns;
+	char *label_name, *match_str;
+	size_t label_name_len, match_len;
+	u32 allow = 0, audit = 0, quiet = 0;
+	unsigned int state;
+	int i;
 
 	if (!query_len)
 		return -EINVAL;
 
-	profile_name = query;
-	profile_name_len = strnlen(query, query_len);
-	if (!profile_name_len || profile_name_len == query_len)
+	label_name = query;
+	label_name_len = strnlen(query, query_len);
+	if (!label_name_len || label_name_len == query_len)
 		return -EINVAL;
 
-	profile = aa_lookup_profile(aa_current_profile()->ns, profile_name);
-	if (!profile)
-		return -ENOENT;
-
-	if (unconfined(profile)) {
-		allow = 0xFFFFFFFF;
-		audit = 0x00000000;
-		quiet = 0x00000000;
-	} else if (profile->policy.dfa) {
-		/**
-		 * The extra byte is to account for the null byte between the
-		 * profile name and dfa string. profile_name_len is greater
-		 * than zero and less than query_len, so a byte can be safely
-		 * added or subtracted.
-		 */
-		char *dfa = profile_name + profile_name_len + 1;
-		size_t dfa_len = query_len - profile_name_len - 1;
-		unsigned int state;
-
-		state = aa_dfa_match_len(profile->policy.dfa,
-					 profile->policy.start[0],
-					 dfa, dfa_len);
-		allow = dfa_user_allow(profile->policy.dfa, state);
-		audit = dfa_user_audit(profile->policy.dfa, state);
-		quiet = dfa_user_quiet(profile->policy.dfa, state);
-	} else {
-		aa_put_profile(profile);
-		return -EINVAL;
+	/**
+	 * The extra byte is to account for the null byte between the
+	 * profile name and dfa string. profile_name_len is greater
+	 * than zero and less than query_len, so a byte can be safely
+	 * added or subtracted.
+	 */
+	match_str = label_name + label_name_len + 1;
+	match_len = query_len - label_name_len - 1;
+
+	ns = labels_ns(aa_current_label());
+	label = aa_label_parse(ns, label_name, GFP_KERNEL);
+	if (IS_ERR(label))
+		return PTR_ERR(label);
+
+	allow = 0xffffffff;
+	audit = quiet = 0x00000000;
+	label_for_each_confined(i, label, profile) {
+		if (profile->policy.dfa) {
+			state = aa_dfa_match_len(profile->policy.dfa,
+						 profile->policy.start[0],
+						 match_str, match_len);
+			allow &= dfa_user_allow(profile->policy.dfa, state);
+			audit |= dfa_user_audit(profile->policy.dfa, state);
+			quiet |= dfa_user_quiet(profile->policy.dfa, state);
+		} else {
+			aa_put_label(label);
+			return -EINVAL;
+		}
 	}
-	aa_put_profile(profile);
+	aa_put_label(label);
 
 	return scnprintf(buf, buf_len,
 		      "allow 0x%08x\ndeny 0x%08x\naudit 0x%08x\nquiet 0x%08x\n",
 		      allow, 0, audit, quiet);
 }
 
+/* TODO: change query string to label */
 #define QUERY_CMD_PROFILE	"profile\0"
 #define QUERY_CMD_PROFILE_LEN	8
 
@@ -267,9 +272,9 @@ static ssize_t query_profile(char *buf, size_t buf_len,
  * @ppos: position in the file (MUST BE ZERO)
  *
  * Allows for one permission query per open(), write(), and read() sequence.
- * The only query currently supported is a profile-based query. For this query
- * ubuf must begin with "profile\0", followed by the profile query specific
- * format described in the query_profile() function documentation.
+ * The only query currently supported is a label-based query. For this query
+ * ubuf must begin with "label\0", followed by the profile query specific
+ * format described in the query_label() function documentation.
  *
  * Returns: number of bytes written or -errno on failure
  */
@@ -288,9 +293,9 @@ static ssize_t aa_write_access(struct file *file, const char __user *ubuf,
 
 	if (count > QUERY_CMD_PROFILE_LEN &&
 	    !memcmp(buf, QUERY_CMD_PROFILE, QUERY_CMD_PROFILE_LEN)) {
-		len = query_profile(buf, SIMPLE_TRANSACTION_LIMIT,
-				    buf + QUERY_CMD_PROFILE_LEN,
-				    count - QUERY_CMD_PROFILE_LEN);
+		len = query_label(buf, SIMPLE_TRANSACTION_LIMIT,
+				  buf + QUERY_CMD_PROFILE_LEN,
+				  count - QUERY_CMD_PROFILE_LEN);
 	} else
 		len = -EINVAL;
 
-- 
1.8.1.2




More information about the AppArmor mailing list