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>

Changed files
+8 -4
security
apparmor
+8 -4
security/apparmor/file.c
··· 618 618 fctx = file_ctx(file); 619 619 620 620 rcu_read_lock(); 621 - flabel = aa_get_newest_label(rcu_dereference(fctx->label)); 622 - rcu_read_unlock(); 621 + flabel = rcu_dereference(fctx->label); 623 622 AA_BUG(!flabel); 624 623 625 624 /* revalidate access, if task is unconfined, or the cached cred ··· 630 631 */ 631 632 denied = request & ~fctx->allow; 632 633 if (unconfined(label) || unconfined(flabel) || 633 - (!denied && aa_label_is_subset(flabel, label))) 634 + (!denied && aa_label_is_subset(flabel, label))) { 635 + rcu_read_unlock(); 634 636 goto done; 637 + } 635 638 639 + flabel = aa_get_newest_label(flabel); 640 + rcu_read_unlock(); 636 641 /* TODO: label cross check */ 637 642 638 643 if (file->f_path.mnt && path_mediated_fs(file->f_path.dentry)) ··· 646 643 else if (S_ISSOCK(file_inode(file)->i_mode)) 647 644 error = __file_sock_perm(op, label, flabel, file, request, 648 645 denied); 649 - done: 650 646 aa_put_label(flabel); 647 + 648 + done: 651 649 return error; 652 650 } 653 651