[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