OSDN Git Service

apparmor: only get a label reference if the fast path check fails
authorJohn Johansen <john.johansen@canonical.com>
Wed, 18 Dec 2019 19:04:07 +0000 (11:04 -0800)
committerJohn Johansen <john.johansen@canonical.com>
Thu, 2 Jan 2020 13:31:40 +0000 (05:31 -0800)
The common fast path check can be done under rcu_read_lock() and
doesn't need a reference count on the label. Only take a reference
count if entering the slow path.

Fixes reported hackbench regression
  - sha1 79e178a57dae ("Merge tag 'apparmor-pr-2019-12-03' of
    git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor")

  hackbench -l (256000/#grp) -g #grp
   128 groups     19.679 ±0.90%

  - previous sha1 01d1dff64662 ("Merge tag 's390-5.5-2' of
    git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux")

  hackbench -l (256000/#grp) -g #grp
   128 groups     3.1689 ±3.04%

Reported-by: Vincent Guittot <vincent.guittot@linaro.org>
Tested-by: Vincent Guittot <vincent.guittot@linaro.org>
Tested-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Fixes: bce4e7e9c45e ("apparmor: reduce rcu_read_lock scope for aa_file_perm mediation")
Signed-off-by: John Johansen <john.johansen@canonical.com>
security/apparmor/file.c

index fe2ebe5..f1caf36 100644 (file)
@@ -618,8 +618,7 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
        fctx = file_ctx(file);
 
        rcu_read_lock();
-       flabel  = aa_get_newest_label(rcu_dereference(fctx->label));
-       rcu_read_unlock();
+       flabel  = rcu_dereference(fctx->label);
        AA_BUG(!flabel);
 
        /* revalidate access, if task is unconfined, or the cached cred
@@ -631,9 +630,13 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
         */
        denied = request & ~fctx->allow;
        if (unconfined(label) || unconfined(flabel) ||
-           (!denied && aa_label_is_subset(flabel, label)))
+           (!denied && aa_label_is_subset(flabel, label))) {
+               rcu_read_unlock();
                goto done;
+       }
 
+       flabel  = aa_get_newest_label(flabel);
+       rcu_read_unlock();
        /* TODO: label cross check */
 
        if (file->f_path.mnt && path_mediated_fs(file->f_path.dentry))
@@ -643,8 +646,9 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
        else if (S_ISSOCK(file_inode(file)->i_mode))
                error = __file_sock_perm(op, label, flabel, file, request,
                                         denied);
-done:
        aa_put_label(flabel);
+
+done:
        return error;
 }