]> Git Repo - J-linux.git/commitdiff
Merge tag 'apparmor-pr-2023-11-03' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <[email protected]>
Fri, 3 Nov 2023 19:48:17 +0000 (09:48 -1000)
committerLinus Torvalds <[email protected]>
Fri, 3 Nov 2023 19:48:17 +0000 (09:48 -1000)
Pull apparmor updates from John Johansen:
 "This adds initial support for mediating io_uring and userns creation.
  Adds a new restriction that tightens the use of change_profile, and a
  couple of optimizations to reduce performance bottle necks that have
  been found when retrieving the current task's secid and allocating
  work buffers.

  The majority of the patch set continues cleaning up and simplifying
  the code (fixing comments, removing now dead functions, and macros
  etc). Finally there are 4 bug fixes, with the regression fix having
  had a couple months of testing.

  Features:
   - optimize retrieving current task secid
   - add base io_uring mediation
   - add base userns mediation
   - improve buffer allocation
   - allow restricting unprivilege change_profile

  Cleanups:
   - Fix kernel doc comments
   - remove unused declarations
   - remove unused functions
   - remove unneeded #ifdef
   - remove unused macros
   - mark fns static
   - cleanup fn with unused return values
   - cleanup audit data
   - pass cred through to audit data
   - refcount the pdb instead of using duplicates
   - make SK_CTX macro an inline fn
   - some comment cleanups

  Bug fixes:
   - fix regression in mount mediation
   - fix invalid refenece
   - use passed in gfp flags
   - advertise avaiability of extended perms and disconnected.path"

* tag 'apparmor-pr-2023-11-03' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor: (39 commits)
  apparmor: Fix some kernel-doc comments
  apparmor: Fix one kernel-doc comment
  apparmor: Fix some kernel-doc comments
  apparmor: mark new functions static
  apparmor: Fix regression in mount mediation
  apparmor: cache buffers on percpu list if there is lock contention
  apparmor: add io_uring mediation
  apparmor: add user namespace creation mediation
  apparmor: allow restricting unprivileged change_profile
  apparmor: advertise disconnected.path is available
  apparmor: refcount the pdb
  apparmor: provide separate audit messages for file and policy checks
  apparmor: pass cred through to audit info.
  apparmor: rename audit_data->label to audit_data->subj_label
  apparmor: combine common_audit_data and apparmor_audit_data
  apparmor: rename SK_CTX() to aa_sock and make it an inline fn
  apparmor: Optimize retrieving current task secid
  apparmor: remove unused functions in policy_ns.c/.h
  apparmor: remove unneeded #ifdef in decompress_zstd()
  apparmor: fix invalid reference on profile->disconnected
  ...

1  2 
security/apparmor/apparmorfs.c
security/apparmor/lsm.c
security/apparmor/policy_unpack.c

index 53a0070ff5df771e8db952ab6b8b0389c2a7ce51,a608a6bd76c54a191651d30b9161f66b40cb6146..38650e52ef57872429823462df9000aded787292
@@@ -226,7 -226,7 +226,7 @@@ static int __aafs_setup_d_inode(struct 
  
        inode->i_ino = get_next_ino();
        inode->i_mode = mode;
 -      inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
 +      simple_inode_init_ts(inode);
        inode->i_private = data;
        if (S_ISDIR(mode)) {
                inode->i_op = iops ? iops : &simple_dir_inode_operations;
@@@ -423,7 -423,7 +423,7 @@@ static ssize_t policy_update(u32 mask, 
        /* high level check about policy management - fine grained in
         * below after unpack
         */
-       error = aa_may_manage_policy(label, ns, mask);
+       error = aa_may_manage_policy(current_cred(), label, ns, mask);
        if (error)
                goto end_section;
  
@@@ -486,7 -486,8 +486,8 @@@ static ssize_t profile_remove(struct fi
        /* high level check about policy management - fine grained in
         * below after unpack
         */
-       error = aa_may_manage_policy(label, ns, AA_MAY_REMOVE_POLICY);
+       error = aa_may_manage_policy(current_cred(), label, ns,
+                                    AA_MAY_REMOVE_POLICY);
        if (error)
                goto out;
  
@@@ -618,23 -619,23 +619,23 @@@ static void profile_query_cb(struct aa_
  
        if (profile_unconfined(profile))
                return;
-       if (rules->file.dfa && *match_str == AA_CLASS_FILE) {
-               state = aa_dfa_match_len(rules->file.dfa,
-                                        rules->file.start[AA_CLASS_FILE],
+       if (rules->file->dfa && *match_str == AA_CLASS_FILE) {
+               state = aa_dfa_match_len(rules->file->dfa,
+                                        rules->file->start[AA_CLASS_FILE],
                                         match_str + 1, match_len - 1);
                if (state) {
                        struct path_cond cond = { };
  
-                       tmp = *(aa_lookup_fperms(&(rules->file), state, &cond));
+                       tmp = *(aa_lookup_fperms(rules->file, state, &cond));
                }
-       } else if (rules->policy.dfa) {
+       } else if (rules->policy->dfa) {
                if (!RULE_MEDIATES(rules, *match_str))
                        return; /* no change to current perms */
-               state = aa_dfa_match_len(rules->policy.dfa,
-                                        rules->policy.start[0],
+               state = aa_dfa_match_len(rules->policy->dfa,
+                                        rules->policy->start[0],
                                         match_str, match_len);
                if (state)
-                       tmp = *aa_lookup_perms(&rules->policy, state);
+                       tmp = *aa_lookup_perms(rules->policy, state);
        }
        aa_apply_modes_to_perms(profile, &tmp);
        aa_perms_accum_raw(perms, &tmp);
@@@ -1095,7 -1096,7 +1096,7 @@@ static int seq_profile_attach_show(stru
        struct aa_profile *profile = labels_profile(label);
        if (profile->attach.xmatch_str)
                seq_printf(seq, "%s\n", profile->attach.xmatch_str);
-       else if (profile->attach.xmatch.dfa)
+       else if (profile->attach.xmatch->dfa)
                seq_puts(seq, "<unknown>\n");
        else
                seq_printf(seq, "%s\n", profile->base.name);
@@@ -1314,7 -1315,6 +1315,6 @@@ SEQ_RAWDATA_FOPS(compressed_size)
  
  static int decompress_zstd(char *src, size_t slen, char *dst, size_t dlen)
  {
- #ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY
        if (slen < dlen) {
                const size_t wksp_len = zstd_dctx_workspace_bound();
                zstd_dctx *ctx;
@@@ -1341,7 -1341,6 +1341,6 @@@ cleanup
                kvfree(wksp);
                return ret;
        }
- #endif
  
        if (dlen < slen)
                return -EINVAL;
@@@ -1554,12 -1553,8 +1553,12 @@@ void __aafs_profile_migrate_dents(struc
  
        for (i = 0; i < AAFS_PROF_SIZEOF; i++) {
                new->dents[i] = old->dents[i];
 -              if (new->dents[i])
 -                      new->dents[i]->d_inode->i_mtime = current_time(new->dents[i]->d_inode);
 +              if (new->dents[i]) {
 +                      struct inode *inode = d_inode(new->dents[i]);
 +
 +                      inode_set_mtime_to_ts(inode,
 +                                            inode_set_ctime_current(inode));
 +              }
                old->dents[i] = NULL;
        }
  }
@@@ -1806,7 -1801,8 +1805,8 @@@ static int ns_mkdir_op(struct mnt_idma
        int error;
  
        label = begin_current_label_crit_section();
-       error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY);
+       error = aa_may_manage_policy(current_cred(), label, NULL,
+                                    AA_MAY_LOAD_POLICY);
        end_current_label_crit_section(label);
        if (error)
                return error;
@@@ -1855,7 -1851,8 +1855,8 @@@ static int ns_rmdir_op(struct inode *di
        int error;
  
        label = begin_current_label_crit_section();
-       error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY);
+       error = aa_may_manage_policy(current_cred(), label, NULL,
+                                    AA_MAY_LOAD_POLICY);
        end_current_label_crit_section(label);
        if (error)
                return error;
@@@ -2339,10 -2336,16 +2340,16 @@@ static struct aa_sfs_entry aa_sfs_entry
        AA_SFS_FILE_BOOLEAN("post_nnp_subset",  1),
        AA_SFS_FILE_BOOLEAN("computed_longest_left",    1),
        AA_SFS_DIR("attach_conditions",         aa_sfs_entry_attach),
+       AA_SFS_FILE_BOOLEAN("disconnected.path",            1),
        AA_SFS_FILE_STRING("version", "1.2"),
        { }
  };
  
+ static struct aa_sfs_entry aa_sfs_entry_unconfined[] = {
+       AA_SFS_FILE_BOOLEAN("change_profile", 1),
+       { }
+ };
  static struct aa_sfs_entry aa_sfs_entry_versions[] = {
        AA_SFS_FILE_BOOLEAN("v5",       1),
        AA_SFS_FILE_BOOLEAN("v6",       1),
        { }
  };
  
+ #define PERMS32STR "allow deny subtree cond kill complain prompt audit quiet hide xindex tag label"
  static struct aa_sfs_entry aa_sfs_entry_policy[] = {
        AA_SFS_DIR("versions",                  aa_sfs_entry_versions),
        AA_SFS_FILE_BOOLEAN("set_load",         1),
        /* number of out of band transitions supported */
        AA_SFS_FILE_U64("outofband",            MAX_OOB_SUPPORTED),
+       AA_SFS_FILE_U64("permstable32_version", 1),
+       AA_SFS_FILE_STRING("permstable32", PERMS32STR),
+       AA_SFS_DIR("unconfined_restrictions",   aa_sfs_entry_unconfined),
        { }
  };
  
@@@ -2368,6 -2375,7 +2379,7 @@@ static struct aa_sfs_entry aa_sfs_entry
  static struct aa_sfs_entry aa_sfs_entry_ns[] = {
        AA_SFS_FILE_BOOLEAN("profile",          1),
        AA_SFS_FILE_BOOLEAN("pivot_root",       0),
+       AA_SFS_FILE_STRING("mask", "userns_create"),
        { }
  };
  
@@@ -2382,6 -2390,12 +2394,12 @@@ static struct aa_sfs_entry aa_sfs_entry
        AA_SFS_DIR("label",                     aa_sfs_entry_query_label),
        { }
  };
+ static struct aa_sfs_entry aa_sfs_entry_io_uring[] = {
+       AA_SFS_FILE_STRING("mask", "sqpoll override_creds"),
+       { }
+ };
  static struct aa_sfs_entry aa_sfs_entry_features[] = {
        AA_SFS_DIR("policy",                    aa_sfs_entry_policy),
        AA_SFS_DIR("domain",                    aa_sfs_entry_domain),
        AA_SFS_DIR("ptrace",                    aa_sfs_entry_ptrace),
        AA_SFS_DIR("signal",                    aa_sfs_entry_signal),
        AA_SFS_DIR("query",                     aa_sfs_entry_query),
+       AA_SFS_DIR("io_uring",                  aa_sfs_entry_io_uring),
        { }
  };
  
@@@ -2544,7 -2559,7 +2563,7 @@@ static int aa_mk_null_file(struct dentr
  
        inode->i_ino = get_next_ino();
        inode->i_mode = S_IFCHR | S_IRUGO | S_IWUGO;
 -      inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
 +      simple_inode_init_ts(inode);
        init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO,
                           MKDEV(MEM_MAJOR, 3));
        d_instantiate(dentry, inode);
diff --combined security/apparmor/lsm.c
index 3fa325d5efac76e64e986e65b4439aec1645de3e,4d34180e97995f2e6e6279dfec1838361b68be58..4981bdf0299315e24f44ca8d65b38c48bd1247c3
@@@ -49,12 -49,19 +49,19 @@@ union aa_buffer 
        DECLARE_FLEX_ARRAY(char, buffer);
  };
  
+ struct aa_local_cache {
+       unsigned int hold;
+       unsigned int count;
+       struct list_head head;
+ };
  #define RESERVE_COUNT 2
  static int reserve_count = RESERVE_COUNT;
  static int buffer_count;
  
  static LIST_HEAD(aa_global_buffers);
  static DEFINE_SPINLOCK(aa_buffers_lock);
+ static DEFINE_PER_CPU(struct aa_local_cache, aa_local_buffers);
  
  /*
   * LSM hook functions
@@@ -116,15 -123,17 +123,17 @@@ static int apparmor_ptrace_access_check
                                        unsigned int mode)
  {
        struct aa_label *tracer, *tracee;
+       const struct cred *cred;
        int error;
  
+       cred = get_task_cred(child);
+       tracee = cred_label(cred);      /* ref count on cred */
        tracer = __begin_current_label_crit_section();
-       tracee = aa_get_task_label(child);
-       error = aa_may_ptrace(tracer, tracee,
+       error = aa_may_ptrace(current_cred(), tracer, cred, tracee,
                        (mode & PTRACE_MODE_READ) ? AA_PTRACE_READ
                                                  : AA_PTRACE_TRACE);
-       aa_put_label(tracee);
        __end_current_label_crit_section(tracer);
+       put_cred(cred);
  
        return error;
  }
  static int apparmor_ptrace_traceme(struct task_struct *parent)
  {
        struct aa_label *tracer, *tracee;
+       const struct cred *cred;
        int error;
  
        tracee = __begin_current_label_crit_section();
-       tracer = aa_get_task_label(parent);
-       error = aa_may_ptrace(tracer, tracee, AA_PTRACE_TRACE);
-       aa_put_label(tracer);
+       cred = get_task_cred(parent);
+       tracer = cred_label(cred);      /* ref count on cred */
+       error = aa_may_ptrace(cred, tracer, current_cred(), tracee,
+                             AA_PTRACE_TRACE);
+       put_cred(cred);
        __end_current_label_crit_section(tracee);
  
        return error;
  }
  
  /* Derived from security/commoncap.c:cap_capget */
 -static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
 +static int apparmor_capget(const struct task_struct *target, kernel_cap_t *effective,
                           kernel_cap_t *inheritable, kernel_cap_t *permitted)
  {
        struct aa_label *label;
@@@ -188,7 -200,7 +200,7 @@@ static int apparmor_capable(const struc
  
        label = aa_get_newest_cred_label(cred);
        if (!unconfined(label))
-               error = aa_capable(label, cap, opts);
+               error = aa_capable(cred, label, cap, opts);
        aa_put_label(label);
  
        return error;
@@@ -211,7 -223,8 +223,8 @@@ static int common_perm(const char *op, 
  
        label = __begin_current_label_crit_section();
        if (!unconfined(label))
-               error = aa_path_perm(op, label, path, 0, mask, cond);
+               error = aa_path_perm(op, current_cred(), label, path, 0, mask,
+                                    cond);
        __end_current_label_crit_section(label);
  
        return error;
@@@ -357,7 -370,8 +370,8 @@@ static int apparmor_path_link(struct de
  
        label = begin_current_label_crit_section();
        if (!unconfined(label))
-               error = aa_path_link(label, old_dentry, new_dir, new_dentry);
+               error = aa_path_link(current_cred(), label, old_dentry, new_dir,
+                                    new_dentry);
        end_current_label_crit_section(label);
  
        return error;
@@@ -396,23 -410,27 +410,27 @@@ static int apparmor_path_rename(const s
                        vfsuid = i_uid_into_vfsuid(idmap, d_backing_inode(old_dentry));
                        cond_exchange.uid = vfsuid_into_kuid(vfsuid);
  
-                       error = aa_path_perm(OP_RENAME_SRC, label, &new_path, 0,
+                       error = aa_path_perm(OP_RENAME_SRC, current_cred(),
+                                            label, &new_path, 0,
                                             MAY_READ | AA_MAY_GETATTR | MAY_WRITE |
                                             AA_MAY_SETATTR | AA_MAY_DELETE,
                                             &cond_exchange);
                        if (!error)
-                               error = aa_path_perm(OP_RENAME_DEST, label, &old_path,
+                               error = aa_path_perm(OP_RENAME_DEST, current_cred(),
+                                                    label, &old_path,
                                                     0, MAY_WRITE | AA_MAY_SETATTR |
                                                     AA_MAY_CREATE, &cond_exchange);
                }
  
                if (!error)
-                       error = aa_path_perm(OP_RENAME_SRC, label, &old_path, 0,
+                       error = aa_path_perm(OP_RENAME_SRC, current_cred(),
+                                            label, &old_path, 0,
                                             MAY_READ | AA_MAY_GETATTR | MAY_WRITE |
                                             AA_MAY_SETATTR | AA_MAY_DELETE,
                                             &cond);
                if (!error)
-                       error = aa_path_perm(OP_RENAME_DEST, label, &new_path,
+                       error = aa_path_perm(OP_RENAME_DEST, current_cred(),
+                                            label, &new_path,
                                             0, MAY_WRITE | AA_MAY_SETATTR |
                                             AA_MAY_CREATE, &cond);
  
@@@ -467,7 -485,8 +485,8 @@@ static int apparmor_file_open(struct fi
                vfsuid = i_uid_into_vfsuid(idmap, inode);
                cond.uid = vfsuid_into_kuid(vfsuid);
  
-               error = aa_path_perm(OP_OPEN, label, &file->f_path, 0,
+               error = aa_path_perm(OP_OPEN, file->f_cred,
+                                    label, &file->f_path, 0,
                                     aa_map_file_to_perms(file), &cond);
                /* todo cache full allowed permissions set and state */
                fctx->allow = aa_map_file_to_perms(file);
@@@ -507,7 -526,7 +526,7 @@@ static int common_file_perm(const char 
                return -EACCES;
  
        label = __begin_current_label_crit_section();
-       error = aa_file_perm(op, label, file, mask, in_atomic);
+       error = aa_file_perm(op, current_cred(), label, file, mask, in_atomic);
        __end_current_label_crit_section(label);
  
        return error;
@@@ -570,6 -589,114 +589,114 @@@ static int apparmor_file_mprotect(struc
                           false);
  }
  
+ #ifdef CONFIG_IO_URING
+ static const char *audit_uring_mask(u32 mask)
+ {
+       if (mask & AA_MAY_CREATE_SQPOLL)
+               return "sqpoll";
+       if (mask & AA_MAY_OVERRIDE_CRED)
+               return "override_creds";
+       return "";
+ }
+ static void audit_uring_cb(struct audit_buffer *ab, void *va)
+ {
+       struct apparmor_audit_data *ad = aad_of_va(va);
+       if (ad->request & AA_URING_PERM_MASK) {
+               audit_log_format(ab, " requested=\"%s\"",
+                                audit_uring_mask(ad->request));
+               if (ad->denied & AA_URING_PERM_MASK) {
+                       audit_log_format(ab, " denied=\"%s\"",
+                                        audit_uring_mask(ad->denied));
+               }
+       }
+       if (ad->uring.target) {
+               audit_log_format(ab, " tcontext=");
+               aa_label_xaudit(ab, labels_ns(ad->subj_label),
+                               ad->uring.target,
+                               FLAGS_NONE, GFP_ATOMIC);
+       }
+ }
+ static int profile_uring(struct aa_profile *profile, u32 request,
+                        struct aa_label *new, int cap,
+                        struct apparmor_audit_data *ad)
+ {
+       unsigned int state;
+       struct aa_ruleset *rules;
+       int error = 0;
+       AA_BUG(!profile);
+       rules = list_first_entry(&profile->rules, typeof(*rules), list);
+       state = RULE_MEDIATES(rules, AA_CLASS_IO_URING);
+       if (state) {
+               struct aa_perms perms = { };
+               if (new) {
+                       aa_label_match(profile, rules, new, state,
+                                      false, request, &perms);
+               } else {
+                       perms = *aa_lookup_perms(rules->policy, state);
+               }
+               aa_apply_modes_to_perms(profile, &perms);
+               error = aa_check_perms(profile, &perms, request, ad,
+                                      audit_uring_cb);
+       }
+       return error;
+ }
+ /**
+  * apparmor_uring_override_creds - check the requested cred override
+  * @new: the target creds
+  *
+  * Check to see if the current task is allowed to override it's credentials
+  * to service an io_uring operation.
+  */
+ static int apparmor_uring_override_creds(const struct cred *new)
+ {
+       struct aa_profile *profile;
+       struct aa_label *label;
+       int error;
+       DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_IO_URING,
+                         OP_URING_OVERRIDE);
+       ad.uring.target = cred_label(new);
+       label = __begin_current_label_crit_section();
+       error = fn_for_each(label, profile,
+                       profile_uring(profile, AA_MAY_OVERRIDE_CRED,
+                                     cred_label(new), CAP_SYS_ADMIN, &ad));
+       __end_current_label_crit_section(label);
+       return error;
+ }
+ /**
+  * apparmor_uring_sqpoll - check if a io_uring polling thread can be created
+  *
+  * Check to see if the current task is allowed to create a new io_uring
+  * kernel polling thread.
+  */
+ static int apparmor_uring_sqpoll(void)
+ {
+       struct aa_profile *profile;
+       struct aa_label *label;
+       int error;
+       DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_IO_URING,
+                         OP_URING_SQPOLL);
+       label = __begin_current_label_crit_section();
+       error = fn_for_each(label, profile,
+                       profile_uring(profile, AA_MAY_CREATE_SQPOLL,
+                                     NULL, CAP_SYS_ADMIN, &ad));
+       __end_current_label_crit_section(label);
+       return error;
+ }
+ #endif /* CONFIG_IO_URING */
  static int apparmor_sb_mount(const char *dev_name, const struct path *path,
                             const char *type, unsigned long flags, void *data)
  {
        label = __begin_current_label_crit_section();
        if (!unconfined(label)) {
                if (flags & MS_REMOUNT)
-                       error = aa_remount(label, path, flags, data);
+                       error = aa_remount(current_cred(), label, path, flags,
+                                          data);
                else if (flags & MS_BIND)
-                       error = aa_bind_mount(label, path, dev_name, flags);
+                       error = aa_bind_mount(current_cred(), label, path,
+                                             dev_name, flags);
                else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE |
                                  MS_UNBINDABLE))
-                       error = aa_mount_change_type(label, path, flags);
+                       error = aa_mount_change_type(current_cred(), label,
+                                                    path, flags);
                else if (flags & MS_MOVE)
-                       error = aa_move_mount(label, path, dev_name);
+                       error = aa_move_mount_old(current_cred(), label, path,
+                                                 dev_name);
                else
-                       error = aa_new_mount(label, dev_name, path, type,
-                                            flags, data);
+                       error = aa_new_mount(current_cred(), label, dev_name,
+                                            path, type, flags, data);
        }
        __end_current_label_crit_section(label);
  
        return error;
  }
  
+ static int apparmor_move_mount(const struct path *from_path,
+                              const struct path *to_path)
+ {
+       struct aa_label *label;
+       int error = 0;
+       label = __begin_current_label_crit_section();
+       if (!unconfined(label))
+               error = aa_move_mount(current_cred(), label, from_path,
+                                     to_path);
+       __end_current_label_crit_section(label);
+       return error;
+ }
  static int apparmor_sb_umount(struct vfsmount *mnt, int flags)
  {
        struct aa_label *label;
  
        label = __begin_current_label_crit_section();
        if (!unconfined(label))
-               error = aa_umount(label, mnt, flags);
+               error = aa_umount(current_cred(), label, mnt, flags);
        __end_current_label_crit_section(label);
  
        return error;
@@@ -623,7 -769,7 +769,7 @@@ static int apparmor_sb_pivotroot(const 
  
        label = aa_get_current_label();
        if (!unconfined(label))
-               error = aa_pivotroot(label, old_path, new_path);
+               error = aa_pivotroot(current_cred(), label, old_path, new_path);
        aa_put_label(label);
  
        return error;
@@@ -662,7 -808,7 +808,7 @@@ static int apparmor_setprocattr(const c
        char *command, *largs = NULL, *args = value;
        size_t arg_size;
        int error;
-       DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE,
+       DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE,
                          OP_SETPROCATTR);
  
        if (size == 0)
@@@ -722,11 -868,11 +868,11 @@@ out
        return error;
  
  fail:
-       aad(&sa)->label = begin_current_label_crit_section();
-       aad(&sa)->info = name;
-       aad(&sa)->error = error = -EINVAL;
-       aa_audit_msg(AUDIT_APPARMOR_DENIED, &sa, NULL);
-       end_current_label_crit_section(aad(&sa)->label);
+       ad.subj_label = begin_current_label_crit_section();
+       ad.info = name;
+       ad.error = error = -EINVAL;
+       aa_audit_msg(AUDIT_APPARMOR_DENIED, &ad, NULL);
+       end_current_label_crit_section(ad.subj_label);
        goto out;
  }
  
   * apparmor_bprm_committing_creds - do task cleanup on committing new creds
   * @bprm: binprm for the exec  (NOT NULL)
   */
 -static void apparmor_bprm_committing_creds(struct linux_binprm *bprm)
 +static void apparmor_bprm_committing_creds(const struct linux_binprm *bprm)
  {
        struct aa_label *label = aa_current_raw_label();
        struct aa_label *new_label = cred_label(bprm->cred);
   * apparmor_bprm_committed_creds() - do cleanup after new creds committed
   * @bprm: binprm for the exec  (NOT NULL)
   */
 -static void apparmor_bprm_committed_creds(struct linux_binprm *bprm)
 +static void apparmor_bprm_committed_creds(const struct linux_binprm *bprm)
  {
        /* clear out temporary/transitional state from the context */
        aa_clear_task_ctx_trans(task_ctx(current));
  
  static void apparmor_current_getsecid_subj(u32 *secid)
  {
-       struct aa_label *label = aa_get_current_label();
+       struct aa_label *label = __begin_current_label_crit_section();
        *secid = label->secid;
-       aa_put_label(label);
+       __end_current_label_crit_section(label);
  }
  
  static void apparmor_task_getsecid_obj(struct task_struct *p, u32 *secid)
@@@ -785,7 -931,8 +931,8 @@@ static int apparmor_task_setrlimit(stru
        int error = 0;
  
        if (!unconfined(label))
-               error = aa_task_setrlimit(label, task, resource, new_rlim);
+               error = aa_task_setrlimit(current_cred(), label, task,
+                                         resource, new_rlim);
        __end_current_label_crit_section(label);
  
        return error;
  static int apparmor_task_kill(struct task_struct *target, struct kernel_siginfo *info,
                              int sig, const struct cred *cred)
  {
+       const struct cred *tc;
        struct aa_label *cl, *tl;
        int error;
  
+       tc = get_task_cred(target);
+       tl = aa_get_newest_cred_label(tc);
        if (cred) {
                /*
                 * Dealing with USB IO specific behavior
                 */
                cl = aa_get_newest_cred_label(cred);
-               tl = aa_get_task_label(target);
-               error = aa_may_signal(cl, tl, sig);
+               error = aa_may_signal(cred, cl, tc, tl, sig);
                aa_put_label(cl);
-               aa_put_label(tl);
                return error;
+       } else {
+               cl = __begin_current_label_crit_section();
+               error = aa_may_signal(current_cred(), cl, tc, tl, sig);
+               __end_current_label_crit_section(cl);
        }
-       cl = __begin_current_label_crit_section();
-       tl = aa_get_task_label(target);
-       error = aa_may_signal(cl, tl, sig);
        aa_put_label(tl);
-       __end_current_label_crit_section(cl);
+       put_cred(tc);
+       return error;
+ }
+ static int apparmor_userns_create(const struct cred *cred)
+ {
+       struct aa_label *label;
+       struct aa_profile *profile;
+       int error = 0;
+       DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_TASK, AA_CLASS_NS,
+                         OP_USERNS_CREATE);
+       ad.subj_cred = current_cred();
+       label = begin_current_label_crit_section();
+       if (!unconfined(label)) {
+               error = fn_for_each(label, profile,
+                                   aa_profile_ns_perm(profile, &ad,
+                                                      AA_USERNS_CREATE));
+       }
+       end_current_label_crit_section(label);
  
        return error;
  }
@@@ -829,7 -998,7 +998,7 @@@ static int apparmor_sk_alloc_security(s
        if (!ctx)
                return -ENOMEM;
  
-       SK_CTX(sk) = ctx;
+       sk->sk_security = ctx;
  
        return 0;
  }
   */
  static void apparmor_sk_free_security(struct sock *sk)
  {
-       struct aa_sk_ctx *ctx = SK_CTX(sk);
+       struct aa_sk_ctx *ctx = aa_sock(sk);
  
-       SK_CTX(sk) = NULL;
+       sk->sk_security = NULL;
        aa_put_label(ctx->label);
        aa_put_label(ctx->peer);
        kfree(ctx);
  static void apparmor_sk_clone_security(const struct sock *sk,
                                       struct sock *newsk)
  {
-       struct aa_sk_ctx *ctx = SK_CTX(sk);
-       struct aa_sk_ctx *new = SK_CTX(newsk);
+       struct aa_sk_ctx *ctx = aa_sock(sk);
+       struct aa_sk_ctx *new = aa_sock(newsk);
  
        if (new->label)
                aa_put_label(new->label);
@@@ -879,7 -1048,8 +1048,8 @@@ static int apparmor_socket_create(int f
        if (!(kern || unconfined(label)))
                error = af_select(family,
                                  create_perm(label, family, type, protocol),
-                                 aa_af_perm(label, OP_CREATE, AA_MAY_CREATE,
+                                 aa_af_perm(current_cred(), label,
+                                            OP_CREATE, AA_MAY_CREATE,
                                             family, type, protocol));
        end_current_label_crit_section(label);
  
@@@ -907,7 -1077,7 +1077,7 @@@ static int apparmor_socket_post_create(
                label = aa_get_current_label();
  
        if (sock->sk) {
-               struct aa_sk_ctx *ctx = SK_CTX(sock->sk);
+               struct aa_sk_ctx *ctx = aa_sock(sock->sk);
  
                aa_put_label(ctx->label);
                ctx->label = aa_get_label(label);
@@@ -1092,7 -1262,7 +1262,7 @@@ static int apparmor_socket_shutdown(str
   */
  static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
  {
-       struct aa_sk_ctx *ctx = SK_CTX(sk);
+       struct aa_sk_ctx *ctx = aa_sock(sk);
  
        if (!skb->secmark)
                return 0;
  
  static struct aa_label *sk_peer_label(struct sock *sk)
  {
-       struct aa_sk_ctx *ctx = SK_CTX(sk);
+       struct aa_sk_ctx *ctx = aa_sock(sk);
  
        if (ctx->peer)
                return ctx->peer;
@@@ -1186,7 -1356,7 +1356,7 @@@ static int apparmor_socket_getpeersec_d
   */
  static void apparmor_sock_graft(struct sock *sk, struct socket *parent)
  {
-       struct aa_sk_ctx *ctx = SK_CTX(sk);
+       struct aa_sk_ctx *ctx = aa_sock(sk);
  
        if (!ctx->label)
                ctx->label = aa_get_current_label();
  static int apparmor_inet_conn_request(const struct sock *sk, struct sk_buff *skb,
                                      struct request_sock *req)
  {
-       struct aa_sk_ctx *ctx = SK_CTX(sk);
+       struct aa_sk_ctx *ctx = aa_sock(sk);
  
        if (!skb->secmark)
                return 0;
@@@ -1221,6 -1391,7 +1391,7 @@@ static struct security_hook_list apparm
        LSM_HOOK_INIT(capget, apparmor_capget),
        LSM_HOOK_INIT(capable, apparmor_capable),
  
+       LSM_HOOK_INIT(move_mount, apparmor_move_mount),
        LSM_HOOK_INIT(sb_mount, apparmor_sb_mount),
        LSM_HOOK_INIT(sb_umount, apparmor_sb_umount),
        LSM_HOOK_INIT(sb_pivotroot, apparmor_sb_pivotroot),
        LSM_HOOK_INIT(task_getsecid_obj, apparmor_task_getsecid_obj),
        LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit),
        LSM_HOOK_INIT(task_kill, apparmor_task_kill),
+       LSM_HOOK_INIT(userns_create, apparmor_userns_create),
  
  #ifdef CONFIG_AUDIT
        LSM_HOOK_INIT(audit_rule_init, aa_audit_rule_init),
        LSM_HOOK_INIT(secid_to_secctx, apparmor_secid_to_secctx),
        LSM_HOOK_INIT(secctx_to_secid, apparmor_secctx_to_secid),
        LSM_HOOK_INIT(release_secctx, apparmor_release_secctx),
+ #ifdef CONFIG_IO_URING
+       LSM_HOOK_INIT(uring_override_creds, apparmor_uring_override_creds),
+       LSM_HOOK_INIT(uring_sqpoll, apparmor_uring_sqpoll),
+ #endif
  };
  
  /*
@@@ -1635,11 -1812,32 +1812,32 @@@ static int param_set_mode(const char *v
  char *aa_get_buffer(bool in_atomic)
  {
        union aa_buffer *aa_buf;
+       struct aa_local_cache *cache;
        bool try_again = true;
        gfp_t flags = (GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
  
+       /* use per cpu cached buffers first */
+       cache = get_cpu_ptr(&aa_local_buffers);
+       if (!list_empty(&cache->head)) {
+               aa_buf = list_first_entry(&cache->head, union aa_buffer, list);
+               list_del(&aa_buf->list);
+               cache->hold--;
+               cache->count--;
+               put_cpu_ptr(&aa_local_buffers);
+               return &aa_buf->buffer[0];
+       }
+       put_cpu_ptr(&aa_local_buffers);
+       if (!spin_trylock(&aa_buffers_lock)) {
+               cache = get_cpu_ptr(&aa_local_buffers);
+               cache->hold += 1;
+               put_cpu_ptr(&aa_local_buffers);
+               spin_lock(&aa_buffers_lock);
+       } else {
+               cache = get_cpu_ptr(&aa_local_buffers);
+               put_cpu_ptr(&aa_local_buffers);
+       }
  retry:
-       spin_lock(&aa_buffers_lock);
        if (buffer_count > reserve_count ||
            (in_atomic && !list_empty(&aa_global_buffers))) {
                aa_buf = list_first_entry(&aa_global_buffers, union aa_buffer,
        if (!aa_buf) {
                if (try_again) {
                        try_again = false;
+                       spin_lock(&aa_buffers_lock);
                        goto retry;
                }
                pr_warn_once("AppArmor: Failed to allocate a memory buffer.\n");
  void aa_put_buffer(char *buf)
  {
        union aa_buffer *aa_buf;
+       struct aa_local_cache *cache;
  
        if (!buf)
                return;
        aa_buf = container_of(buf, union aa_buffer, buffer[0]);
  
-       spin_lock(&aa_buffers_lock);
-       list_add(&aa_buf->list, &aa_global_buffers);
-       buffer_count++;
-       spin_unlock(&aa_buffers_lock);
+       cache = get_cpu_ptr(&aa_local_buffers);
+       if (!cache->hold) {
+               put_cpu_ptr(&aa_local_buffers);
+               if (spin_trylock(&aa_buffers_lock)) {
+                       /* put back on global list */
+                       list_add(&aa_buf->list, &aa_global_buffers);
+                       buffer_count++;
+                       spin_unlock(&aa_buffers_lock);
+                       cache = get_cpu_ptr(&aa_local_buffers);
+                       put_cpu_ptr(&aa_local_buffers);
+                       return;
+               }
+               /* contention on global list, fallback to percpu */
+               cache = get_cpu_ptr(&aa_local_buffers);
+               cache->hold += 1;
+       }
+       /* cache in percpu list */
+       list_add(&aa_buf->list, &cache->head);
+       cache->count++;
+       put_cpu_ptr(&aa_local_buffers);
  }
  
  /*
@@@ -1726,6 -1944,15 +1944,15 @@@ static int __init alloc_buffers(void
        union aa_buffer *aa_buf;
        int i, num;
  
+       /*
+        * per cpu set of cached allocated buffers used to help reduce
+        * lock contention
+        */
+       for_each_possible_cpu(i) {
+               per_cpu(aa_local_buffers, i).hold = 0;
+               per_cpu(aa_local_buffers, i).count = 0;
+               INIT_LIST_HEAD(&per_cpu(aa_local_buffers, i).head);
+       }
        /*
         * A function may require two buffers at once. Usually the buffers are
         * used for a short period of time and are shared. On UP kernel buffers
@@@ -1765,6 -1992,7 +1992,7 @@@ static int apparmor_dointvec(struct ctl
  }
  
  static struct ctl_table apparmor_sysctl_table[] = {
+ #ifdef CONFIG_USER_NS
        {
                .procname       = "unprivileged_userns_apparmor_policy",
                .data           = &unprivileged_userns_apparmor_policy,
                .mode           = 0600,
                .proc_handler   = apparmor_dointvec,
        },
+ #endif /* CONFIG_USER_NS */
        {
                .procname       = "apparmor_display_secid_mode",
                .data           = &apparmor_display_secid_mode,
                .mode           = 0600,
                .proc_handler   = apparmor_dointvec,
        },
+       {
+               .procname       = "apparmor_restrict_unprivileged_unconfined",
+               .data           = &aa_unprivileged_unconfined_restricted,
+               .maxlen         = sizeof(int),
+               .mode           = 0600,
+               .proc_handler   = apparmor_dointvec,
+       },
        { }
  };
  
@@@ -1809,7 -2044,7 +2044,7 @@@ static unsigned int apparmor_ip_postrou
        if (sk == NULL)
                return NF_ACCEPT;
  
-       ctx = SK_CTX(sk);
+       ctx = aa_sock(sk);
        if (!apparmor_secmark_check(ctx->label, OP_SENDMSG, AA_MAY_SEND,
                                    skb->secmark, sk))
                return NF_ACCEPT;
@@@ -1868,6 -2103,69 +2103,69 @@@ static int __init apparmor_nf_ip_init(v
  __initcall(apparmor_nf_ip_init);
  #endif
  
+ static char nulldfa_src[] = {
+       #include "nulldfa.in"
+ };
+ struct aa_dfa *nulldfa;
+ static char stacksplitdfa_src[] = {
+       #include "stacksplitdfa.in"
+ };
+ struct aa_dfa *stacksplitdfa;
+ struct aa_policydb *nullpdb;
+ static int __init aa_setup_dfa_engine(void)
+ {
+       int error = -ENOMEM;
+       nullpdb = aa_alloc_pdb(GFP_KERNEL);
+       if (!nullpdb)
+               return -ENOMEM;
+       nulldfa = aa_dfa_unpack(nulldfa_src, sizeof(nulldfa_src),
+                           TO_ACCEPT1_FLAG(YYTD_DATA32) |
+                           TO_ACCEPT2_FLAG(YYTD_DATA32));
+       if (IS_ERR(nulldfa)) {
+               error = PTR_ERR(nulldfa);
+               goto fail;
+       }
+       nullpdb->dfa = aa_get_dfa(nulldfa);
+       nullpdb->perms = kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL);
+       if (!nullpdb->perms)
+               goto fail;
+       nullpdb->size = 2;
+       stacksplitdfa = aa_dfa_unpack(stacksplitdfa_src,
+                                     sizeof(stacksplitdfa_src),
+                                     TO_ACCEPT1_FLAG(YYTD_DATA32) |
+                                     TO_ACCEPT2_FLAG(YYTD_DATA32));
+       if (IS_ERR(stacksplitdfa)) {
+               error = PTR_ERR(stacksplitdfa);
+               goto fail;
+       }
+       return 0;
+ fail:
+       aa_put_pdb(nullpdb);
+       aa_put_dfa(nulldfa);
+       nullpdb = NULL;
+       nulldfa = NULL;
+       stacksplitdfa = NULL;
+       return error;
+ }
+ static void __init aa_teardown_dfa_engine(void)
+ {
+       aa_put_dfa(stacksplitdfa);
+       aa_put_dfa(nulldfa);
+       aa_put_pdb(nullpdb);
+       nullpdb = NULL;
+       stacksplitdfa = NULL;
+       nulldfa = NULL;
+ }
  static int __init apparmor_init(void)
  {
        int error;
index 913ec8d0eb6392c517bc948e50bfb5bf7fdf1e7f,3fad34b68fdc5c7f9052051f9ac82349357aed1a..47ec097d6741fe0fc6c33bfc0c844f331f704f17
  static void audit_cb(struct audit_buffer *ab, void *va)
  {
        struct common_audit_data *sa = va;
+       struct apparmor_audit_data *ad = aad(sa);
  
-       if (aad(sa)->iface.ns) {
+       if (ad->iface.ns) {
                audit_log_format(ab, " ns=");
-               audit_log_untrustedstring(ab, aad(sa)->iface.ns);
+               audit_log_untrustedstring(ab, ad->iface.ns);
        }
-       if (aad(sa)->name) {
+       if (ad->name) {
                audit_log_format(ab, " name=");
-               audit_log_untrustedstring(ab, aad(sa)->name);
+               audit_log_untrustedstring(ab, ad->name);
        }
-       if (aad(sa)->iface.pos)
-               audit_log_format(ab, " offset=%ld", aad(sa)->iface.pos);
+       if (ad->iface.pos)
+               audit_log_format(ab, " offset=%ld", ad->iface.pos);
  }
  
  /**
@@@ -63,18 -64,18 +64,18 @@@ static int audit_iface(struct aa_profil
                       int error)
  {
        struct aa_profile *profile = labels_profile(aa_current_raw_label());
-       DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL);
+       DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL);
        if (e)
-               aad(&sa)->iface.pos = e->pos - e->start;
-       aad(&sa)->iface.ns = ns_name;
+               ad.iface.pos = e->pos - e->start;
+       ad.iface.ns = ns_name;
        if (new)
-               aad(&sa)->name = new->base.hname;
+               ad.name = new->base.hname;
        else
-               aad(&sa)->name = name;
-       aad(&sa)->info = info;
-       aad(&sa)->error = error;
+               ad.name = name;
+       ad.info = info;
+       ad.error = error;
  
-       return aa_audit(AUDIT_APPARMOR_STATUS, profile, &sa, audit_cb);
+       return aa_audit(AUDIT_APPARMOR_STATUS, profile, &ad, audit_cb);
  }
  
  void __aa_loaddata_update(struct aa_loaddata *data, long revision)
  
        data->revision = revision;
        if ((data->dents[AAFS_LOADDATA_REVISION])) {
 -              d_inode(data->dents[AAFS_LOADDATA_DIR])->i_mtime =
 -                      current_time(d_inode(data->dents[AAFS_LOADDATA_DIR]));
 -              d_inode(data->dents[AAFS_LOADDATA_REVISION])->i_mtime =
 -                      current_time(d_inode(data->dents[AAFS_LOADDATA_REVISION]));
 +              struct inode *inode;
 +
 +              inode = d_inode(data->dents[AAFS_LOADDATA_DIR]);
 +              inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
 +
 +              inode = d_inode(data->dents[AAFS_LOADDATA_REVISION]);
 +              inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
        }
  }
  
@@@ -705,24 -703,29 +706,29 @@@ fail_reset
        return -EPROTO;
  }
  
- static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy,
+ static int unpack_pdb(struct aa_ext *e, struct aa_policydb **policy,
                      bool required_dfa, bool required_trans,
                      const char **info)
  {
+       struct aa_policydb *pdb;
        void *pos = e->pos;
        int i, flags, error = -EPROTO;
        ssize_t size;
  
-       size = unpack_perms_table(e, &policy->perms);
+       pdb = aa_alloc_pdb(GFP_KERNEL);
+       if (!pdb)
+               return -ENOMEM;
+       size = unpack_perms_table(e, &pdb->perms);
        if (size < 0) {
                error = size;
-               policy->perms = NULL;
+               pdb->perms = NULL;
                *info = "failed to unpack - perms";
                goto fail;
        }
-       policy->size = size;
+       pdb->size = size;
  
-       if (policy->perms) {
+       if (pdb->perms) {
                /* perms table present accept is index */
                flags = TO_ACCEPT1_FLAG(YYTD_DATA32);
        } else {
                        TO_ACCEPT2_FLAG(YYTD_DATA32);
        }
  
-       policy->dfa = unpack_dfa(e, flags);
-       if (IS_ERR(policy->dfa)) {
-               error = PTR_ERR(policy->dfa);
-               policy->dfa = NULL;
+       pdb->dfa = unpack_dfa(e, flags);
+       if (IS_ERR(pdb->dfa)) {
+               error = PTR_ERR(pdb->dfa);
+               pdb->dfa = NULL;
                *info = "failed to unpack - dfa";
                goto fail;
-       } else if (!policy->dfa) {
+       } else if (!pdb->dfa) {
                if (required_dfa) {
                        *info = "missing required dfa";
                        goto fail;
         * sadly start was given different names for file and policydb
         * but since it is optional we can try both
         */
-       if (!aa_unpack_u32(e, &policy->start[0], "start"))
+       if (!aa_unpack_u32(e, &pdb->start[0], "start"))
                /* default start state */
-               policy->start[0] = DFA_START;
-       if (!aa_unpack_u32(e, &policy->start[AA_CLASS_FILE], "dfa_start")) {
+               pdb->start[0] = DFA_START;
+       if (!aa_unpack_u32(e, &pdb->start[AA_CLASS_FILE], "dfa_start")) {
                /* default start state for xmatch and file dfa */
-               policy->start[AA_CLASS_FILE] = DFA_START;
+               pdb->start[AA_CLASS_FILE] = DFA_START;
        }       /* setup class index */
        for (i = AA_CLASS_FILE + 1; i <= AA_CLASS_LAST; i++) {
-               policy->start[i] = aa_dfa_next(policy->dfa, policy->start[0],
+               pdb->start[i] = aa_dfa_next(pdb->dfa, pdb->start[0],
                                               i);
        }
-       if (!unpack_trans_table(e, &policy->trans) && required_trans) {
+       if (!unpack_trans_table(e, &pdb->trans) && required_trans) {
                *info = "failed to unpack profile transition table";
                goto fail;
        }
        /* TODO: move compat mapping here, requires dfa merging first */
        /* TODO: move verify here, it has to be done after compat mappings */
  out:
+       *policy = pdb;
        return 0;
  
  fail:
+       aa_put_pdb(pdb);
        e->pos = pos;
        return error;
  }
@@@ -807,7 -812,7 +815,7 @@@ static struct aa_profile *unpack_profil
        const char *info = "failed to unpack profile";
        size_t ns_len;
        struct rhashtable_params params = { 0 };
-       char *key = NULL;
+       char *key = NULL, *disconnected = NULL;
        struct aa_data *data;
        int error = -EPROTO;
        kernel_cap_t tmpcap;
        }
  
        /* neither xmatch_len not xmatch_perms are optional if xmatch is set */
-       if (profile->attach.xmatch.dfa) {
+       if (profile->attach.xmatch->dfa) {
                if (!aa_unpack_u32(e, &tmp, NULL)) {
                        info = "missing xmatch len";
                        goto fail;
                }
                profile->attach.xmatch_len = tmp;
-               profile->attach.xmatch.start[AA_CLASS_XMATCH] = DFA_START;
-               if (!profile->attach.xmatch.perms) {
-                       error = aa_compat_map_xmatch(&profile->attach.xmatch);
+               profile->attach.xmatch->start[AA_CLASS_XMATCH] = DFA_START;
+               if (!profile->attach.xmatch->perms) {
+                       error = aa_compat_map_xmatch(profile->attach.xmatch);
                        if (error) {
                                info = "failed to convert xmatch permission table";
                                goto fail;
        }
  
        /* disconnected attachment string is optional */
-       (void) aa_unpack_str(e, &profile->disconnected, "disconnected");
+       (void) aa_unpack_strdup(e, &disconnected, "disconnected");
+       profile->disconnected = disconnected;
  
        /* per profile debug flags (complain, audit) */
        if (!aa_unpack_nameX(e, AA_STRUCT, "flags")) {
                if (error)
                        goto fail;
                /* Fixup: drop when we get rid of start array */
-               if (aa_dfa_next(rules->policy.dfa, rules->policy.start[0],
+               if (aa_dfa_next(rules->policy->dfa, rules->policy->start[0],
                                AA_CLASS_FILE))
-                       rules->policy.start[AA_CLASS_FILE] =
-                         aa_dfa_next(rules->policy.dfa,
-                                     rules->policy.start[0],
+                       rules->policy->start[AA_CLASS_FILE] =
+                         aa_dfa_next(rules->policy->dfa,
+                                     rules->policy->start[0],
                                      AA_CLASS_FILE);
                if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL))
                        goto fail;
-               if (!rules->policy.perms) {
-                       error = aa_compat_map_policy(&rules->policy,
+               if (!rules->policy->perms) {
+                       error = aa_compat_map_policy(rules->policy,
                                                     e->version);
                        if (error) {
                                info = "failed to remap policydb permission table";
                        }
                }
        } else {
-               rules->policy.dfa = aa_get_dfa(nulldfa);
-               rules->policy.perms = kcalloc(2, sizeof(struct aa_perms),
-                                             GFP_KERNEL);
-               if (!rules->policy.perms)
-                       goto fail;
-               rules->policy.size = 2;
+               rules->policy = aa_get_pdb(nullpdb);
        }
        /* get file rules */
        error = unpack_pdb(e, &rules->file, false, true, &info);
        if (error) {
                goto fail;
-       } else if (rules->file.dfa) {
-               if (!rules->file.perms) {
-                       error = aa_compat_map_file(&rules->file);
+       } else if (rules->file->dfa) {
+               if (!rules->file->perms) {
+                       error = aa_compat_map_file(rules->file);
                        if (error) {
                                info = "failed to remap file permission table";
                                goto fail;
                        }
                }
-       } else if (rules->policy.dfa &&
-                  rules->policy.start[AA_CLASS_FILE]) {
-               rules->file.dfa = aa_get_dfa(rules->policy.dfa);
-               rules->file.start[AA_CLASS_FILE] = rules->policy.start[AA_CLASS_FILE];
-               rules->file.perms = kcalloc(rules->policy.size,
-                                           sizeof(struct aa_perms),
-                                           GFP_KERNEL);
-               if (!rules->file.perms)
-                       goto fail;
-               memcpy(rules->file.perms, rules->policy.perms,
-                      rules->policy.size * sizeof(struct aa_perms));
-               rules->file.size = rules->policy.size;
+       } else if (rules->policy->dfa &&
+                  rules->policy->start[AA_CLASS_FILE]) {
+               rules->file = aa_get_pdb(rules->policy);
        } else {
-               rules->file.dfa = aa_get_dfa(nulldfa);
-               rules->file.perms = kcalloc(2, sizeof(struct aa_perms),
-                                           GFP_KERNEL);
-               if (!rules->file.perms)
-                       goto fail;
-               rules->file.size = 2;
+               rules->file = aa_get_pdb(nullpdb);
        }
        error = -EPROTO;
        if (aa_unpack_nameX(e, AA_STRUCT, "data")) {
@@@ -1170,7 -1157,7 +1160,7 @@@ static int verify_header(struct aa_ext 
  /**
   * verify_dfa_accept_index - verify accept indexes are in range of perms table
   * @dfa: the dfa to check accept indexes are in range
-  * table_size: the permission table size the indexes should be within
+  * @table_size: the permission table size the indexes should be within
   */
  static bool verify_dfa_accept_index(struct aa_dfa *dfa, int table_size)
  {
@@@ -1241,26 -1228,32 +1231,32 @@@ static int verify_profile(struct aa_pro
        if (!rules)
                return 0;
  
-       if ((rules->file.dfa && !verify_dfa_accept_index(rules->file.dfa,
-                                                        rules->file.size)) ||
-           (rules->policy.dfa &&
-            !verify_dfa_accept_index(rules->policy.dfa, rules->policy.size))) {
+       if (rules->file->dfa && !verify_dfa_accept_index(rules->file->dfa,
+                                                       rules->file->size)) {
+               audit_iface(profile, NULL, NULL,
+                           "Unpack: file Invalid named transition", NULL,
+                           -EPROTO);
+               return -EPROTO;
+       }
+       if (rules->policy->dfa &&
+           !verify_dfa_accept_index(rules->policy->dfa, rules->policy->size)) {
                audit_iface(profile, NULL, NULL,
-                           "Unpack: Invalid named transition", NULL, -EPROTO);
+                           "Unpack: policy Invalid named transition", NULL,
+                           -EPROTO);
                return -EPROTO;
        }
  
-       if (!verify_perms(&rules->file)) {
+       if (!verify_perms(rules->file)) {
                audit_iface(profile, NULL, NULL,
                            "Unpack: Invalid perm index", NULL, -EPROTO);
                return -EPROTO;
        }
-       if (!verify_perms(&rules->policy)) {
+       if (!verify_perms(rules->policy)) {
                audit_iface(profile, NULL, NULL,
                            "Unpack: Invalid perm index", NULL, -EPROTO);
                return -EPROTO;
        }
-       if (!verify_perms(&profile->attach.xmatch)) {
+       if (!verify_perms(profile->attach.xmatch)) {
                audit_iface(profile, NULL, NULL,
                            "Unpack: Invalid perm index", NULL, -EPROTO);
                return -EPROTO;
This page took 0.107834 seconds and 4 git commands to generate.