summary refs log tree commit diff
path: root/security
diff options
context:
space:
mode:
authorJohn Johansen <john.johansen@canonical.com>2019-12-18 11:04:07 -0800
committerJohn Johansen <john.johansen@canonical.com>2020-01-02 05:31:40 -0800
commit20d4e80d255dd7cfecb53743bc550ebcad04549d (patch)
treec740dec5f800df330c303db8018620b8bb0371f1 /security
parent9c95a278ba7ca3ccc111c165cc74cb23c744fc85 (diff)
downloadlinux-20d4e80d255dd7cfecb53743bc550ebcad04549d.tar.gz
apparmor: only get a label reference if the fast path check fails
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>
Diffstat (limited to 'security')
-rw-r--r--security/apparmor/file.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/security/apparmor/file.c b/security/apparmor/file.c
index fe2ebe5e865e..f1caf3674e1c 100644
--- a/security/apparmor/file.c
+++ b/security/apparmor/file.c
@@ -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;
 }