Signed-off-by: John Johansen <[email protected]>
---
 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


-- 
AppArmor mailing list
[email protected]
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/apparmor

Reply via email to