apparmor: add gerneric permissions struct and support fns
authorJohn Johansen <john.johansen@canonical.com>
Mon, 29 May 2017 19:16:04 +0000 (12:16 -0700)
committerJohn Johansen <john.johansen@canonical.com>
Sun, 11 Jun 2017 00:11:30 +0000 (17:11 -0700)
Signed-off-by: John Johansen <john.johansen@canonical.com>
security/apparmor/file.c
security/apparmor/include/audit.h
security/apparmor/include/perms.h
security/apparmor/lib.c

index 44549db904b312778f7adf8baffe0dab7364220a..1ee656f66aa43b8c3380c2b4783e9d82aed755ee 100644 (file)
@@ -56,15 +56,15 @@ static void file_audit_cb(struct audit_buffer *ab, void *va)
        struct common_audit_data *sa = va;
        kuid_t fsuid = current_fsuid();
 
-       if (aad(sa)->fs.request & AA_AUDIT_FILE_MASK) {
+       if (aad(sa)->request & AA_AUDIT_FILE_MASK) {
                audit_log_format(ab, " requested_mask=");
-               audit_file_mask(ab, aad(sa)->fs.request);
+               audit_file_mask(ab, aad(sa)->request);
        }
-       if (aad(sa)->fs.denied & AA_AUDIT_FILE_MASK) {
+       if (aad(sa)->denied & AA_AUDIT_FILE_MASK) {
                audit_log_format(ab, " denied_mask=");
-               audit_file_mask(ab, aad(sa)->fs.denied);
+               audit_file_mask(ab, aad(sa)->denied);
        }
-       if (aad(sa)->fs.request & AA_AUDIT_FILE_MASK) {
+       if (aad(sa)->request & AA_AUDIT_FILE_MASK) {
                audit_log_format(ab, " fsuid=%d",
                                 from_kuid(&init_user_ns, fsuid));
                audit_log_format(ab, " ouid=%d",
@@ -100,7 +100,7 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
        DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_TASK, op);
 
        sa.u.tsk = NULL;
-       aad(&sa)->fs.request = request;
+       aad(&sa)->request = request;
        aad(&sa)->name = name;
        aad(&sa)->fs.target = target;
        aad(&sa)->fs.ouid = ouid;
@@ -115,30 +115,30 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
                        mask = 0xffff;
 
                /* mask off perms that are not being force audited */
-               aad(&sa)->fs.request &= mask;
+               aad(&sa)->request &= mask;
 
-               if (likely(!aad(&sa)->fs.request))
+               if (likely(!aad(&sa)->request))
                        return 0;
                type = AUDIT_APPARMOR_AUDIT;
        } else {
                /* only report permissions that were denied */
-               aad(&sa)->fs.request = aad(&sa)->fs.request & ~perms->allow;
-               AA_BUG(!aad(&sa)->fs.request);
+               aad(&sa)->request = aad(&sa)->request & ~perms->allow;
+               AA_BUG(!aad(&sa)->request);
 
-               if (aad(&sa)->fs.request & perms->kill)
+               if (aad(&sa)->request & perms->kill)
                        type = AUDIT_APPARMOR_KILL;
 
                /* quiet known rejects, assumes quiet and kill do not overlap */
-               if ((aad(&sa)->fs.request & perms->quiet) &&
+               if ((aad(&sa)->request & perms->quiet) &&
                    AUDIT_MODE(profile) != AUDIT_NOQUIET &&
                    AUDIT_MODE(profile) != AUDIT_ALL)
-                       aad(&sa)->fs.request &= ~perms->quiet;
+                       aad(&sa)->request &= ~perms->quiet;
 
-               if (!aad(&sa)->fs.request)
+               if (!aad(&sa)->request)
                        return COMPLAIN_MODE(profile) ? 0 : aad(&sa)->error;
        }
 
-       aad(&sa)->fs.denied = aad(&sa)->fs.request & ~perms->allow;
+       aad(&sa)->denied = aad(&sa)->request & ~perms->allow;
        return aa_audit(type, profile, &sa, file_audit_cb);
 }
 
index fdc4774318ba0d12129c8f169f4d0113d099d0dc..1aeb8550fb827f33dd293c806c2260a4be6cac90 100644 (file)
@@ -107,14 +107,14 @@ struct apparmor_audit_data {
        void *profile;
        const char *name;
        const char *info;
+       u32 request;
+       u32 denied;
        union {
                /* these entries require a custom callback fn */
                struct {
                        struct aa_profile *peer;
                        struct {
                                const char *target;
-                               u32 request;
-                               u32 denied;
                                kuid_t ouid;
                        } fs;
                };
index 35e365e7aa75b3e795cc1aa27359c5da1be2f3ac..6ef23212bd664ba0adbdddb2a8c664efd7596ed1 100644 (file)
 extern const char aa_file_perm_chrs[];
 extern const char *aa_file_perm_names[];
 
+struct aa_perms {
+       u32 allow;
+       u32 audit;      /* set only when allow is set */
+
+       u32 deny;       /* explicit deny, or conflict if allow also set */
+       u32 quiet;      /* set only when ~allow | deny */
+       u32 kill;       /* set only when ~allow | deny */
+       u32 stop;       /* set only when ~allow | deny */
+
+       u32 complain;   /* accumulates only used when ~allow & ~deny */
+       u32 cond;       /* set only when ~allow and ~deny */
+
+       u32 hide;       /* set only when  ~allow | deny */
+       u32 prompt;     /* accumulates only used when ~allow & ~deny */
+
+       /* Reserved:
+        * u32 subtree; / * set only when allow is set * /
+        */
+       u16 xindex;
+};
+
+#define ALL_PERMS_MASK 0xffffffff
+
+extern struct aa_perms allperms;
+
+struct aa_profile;
+
 void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask);
+void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask);
+void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
+                       u32 chrsmask, const char **names, u32 namesmask);
+void aa_apply_modes_to_perms(struct aa_profile *profile,
+                            struct aa_perms *perms);
+void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
+                     struct aa_perms *perms);
 
 #endif /* __AA_PERM_H */
index 90d4631ddafeb1f369805b0015791af282c3c95f..a509137448236f6132f2c7b44a2413c6224848a4 100644 (file)
 #include "include/perms.h"
 #include "include/policy.h"
 
+struct aa_perms allperms = { .allow = ALL_PERMS_MASK,
+                            .quiet = ALL_PERMS_MASK,
+                            .hide = ALL_PERMS_MASK };
+
 /**
  * aa_split_fqname - split a fqname into a profile and namespace name
  * @fqname: a full qualified name in namespace profile format (NOT NULL)
@@ -188,6 +192,104 @@ void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask)
        *str = '\0';
 }
 
+void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
+{
+       const char *fmt = "%s";
+       unsigned int i, perm = 1;
+       bool prev = false;
+
+       for (i = 0; i < 32; perm <<= 1, i++) {
+               if (mask & perm) {
+                       audit_log_format(ab, fmt, names[i]);
+                       if (!prev) {
+                               prev = true;
+                               fmt = " %s";
+                       }
+               }
+       }
+}
+
+void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
+                       u32 chrsmask, const char **names, u32 namesmask)
+{
+       char str[33];
+
+       audit_log_format(ab, "\"");
+       if ((mask & chrsmask) && chrs) {
+               aa_perm_mask_to_str(str, chrs, mask & chrsmask);
+               mask &= ~chrsmask;
+               audit_log_format(ab, "%s", str);
+               if (mask & namesmask)
+                       audit_log_format(ab, " ");
+       }
+       if ((mask & namesmask) && names)
+               aa_audit_perm_names(ab, names, mask & namesmask);
+       audit_log_format(ab, "\"");
+}
+
+/**
+ * aa_apply_modes_to_perms - apply namespace and profile flags to perms
+ * @profile: that perms where computed from
+ * @perms: perms to apply mode modifiers to
+ *
+ * TODO: split into profile and ns based flags for when accumulating perms
+ */
+void aa_apply_modes_to_perms(struct aa_profile *profile, struct aa_perms *perms)
+{
+       switch (AUDIT_MODE(profile)) {
+       case AUDIT_ALL:
+               perms->audit = ALL_PERMS_MASK;
+               /* fall through */
+       case AUDIT_NOQUIET:
+               perms->quiet = 0;
+               break;
+       case AUDIT_QUIET:
+               perms->audit = 0;
+               /* fall through */
+       case AUDIT_QUIET_DENIED:
+               perms->quiet = ALL_PERMS_MASK;
+               break;
+       }
+
+       if (KILL_MODE(profile))
+               perms->kill = ALL_PERMS_MASK;
+       else if (COMPLAIN_MODE(profile))
+               perms->complain = ALL_PERMS_MASK;
+/*
+ *  TODO:
+ *     else if (PROMPT_MODE(profile))
+ *             perms->prompt = ALL_PERMS_MASK;
+ */
+}
+
+static u32 map_other(u32 x)
+{
+       return ((x & 0x3) << 8) |       /* SETATTR/GETATTR */
+               ((x & 0x1c) << 18) |    /* ACCEPT/BIND/LISTEN */
+               ((x & 0x60) << 19);     /* SETOPT/GETOPT */
+}
+
+void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
+                     struct aa_perms *perms)
+{
+       perms->deny = 0;
+       perms->kill = perms->stop = 0;
+       perms->complain = perms->cond = 0;
+       perms->hide = 0;
+       perms->prompt = 0;
+       perms->allow = dfa_user_allow(dfa, state);
+       perms->audit = dfa_user_audit(dfa, state);
+       perms->quiet = dfa_user_quiet(dfa, state);
+
+       /* for v5 perm mapping in the policydb, the other set is used
+        * to extend the general perm set
+        */
+       perms->allow |= map_other(dfa_other_allow(dfa, state));
+       perms->audit |= map_other(dfa_other_audit(dfa, state));
+       perms->quiet |= map_other(dfa_other_quiet(dfa, state));
+//     perms->xindex = dfa_user_xindex(dfa, state);
+}
+
 /**
  * aa_policy_init - initialize a policy structure
  * @policy: policy to initialize  (NOT NULL)