]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
fixes for 4.19
authorSasha Levin <sashal@kernel.org>
Mon, 20 Jan 2020 03:18:35 +0000 (22:18 -0500)
committerSasha Levin <sashal@kernel.org>
Mon, 20 Jan 2020 03:21:26 +0000 (22:21 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.19/btrfs-rework-arguments-of-btrfs_unlink_subvol.patch [new file with mode: 0644]
queue-4.19/lsm-generalize-flag-passing-to-security_capable.patch [new file with mode: 0644]
queue-4.19/series

diff --git a/queue-4.19/btrfs-rework-arguments-of-btrfs_unlink_subvol.patch b/queue-4.19/btrfs-rework-arguments-of-btrfs_unlink_subvol.patch
new file mode 100644 (file)
index 0000000..e5d0e03
--- /dev/null
@@ -0,0 +1,151 @@
+From 1e4173b4b84f4aafc5f1756421eeea882cea7cf7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 18 Dec 2019 17:20:27 -0500
+Subject: btrfs: rework arguments of btrfs_unlink_subvol
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit 045d3967b6920b663fc010ad414ade1b24143bd1 ]
+
+btrfs_unlink_subvol takes the name of the dentry and the root objectid
+based on what kind of inode this is, either a real subvolume link or a
+empty one that we inherited as a snapshot.  We need to fix how we unlink
+in the case for BTRFS_EMPTY_SUBVOL_DIR_OBJECTID in the future, so rework
+btrfs_unlink_subvol to just take the dentry and handle getting the right
+objectid given the type of inode this is.  There is no functional change
+here, simply pushing the work into btrfs_unlink_subvol() proper.
+
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/inode.c | 46 ++++++++++++++++++++--------------------------
+ 1 file changed, 20 insertions(+), 26 deletions(-)
+
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index 6cce88d0a807..4ea9dd93a545 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -4120,18 +4120,30 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
+ }
+ static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
+-                             struct inode *dir, u64 objectid,
+-                             const char *name, int name_len)
++                             struct inode *dir, struct dentry *dentry)
+ {
+       struct btrfs_root *root = BTRFS_I(dir)->root;
++      struct btrfs_inode *inode = BTRFS_I(d_inode(dentry));
+       struct btrfs_path *path;
+       struct extent_buffer *leaf;
+       struct btrfs_dir_item *di;
+       struct btrfs_key key;
++      const char *name = dentry->d_name.name;
++      int name_len = dentry->d_name.len;
+       u64 index;
+       int ret;
++      u64 objectid;
+       u64 dir_ino = btrfs_ino(BTRFS_I(dir));
++      if (btrfs_ino(inode) == BTRFS_FIRST_FREE_OBJECTID) {
++              objectid = inode->root->root_key.objectid;
++      } else if (btrfs_ino(inode) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID) {
++              objectid = inode->location.objectid;
++      } else {
++              WARN_ON(1);
++              return -EINVAL;
++      }
++
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+@@ -4384,8 +4396,7 @@ int btrfs_delete_subvolume(struct inode *dir, struct dentry *dentry)
+       btrfs_record_snapshot_destroy(trans, BTRFS_I(dir));
+-      ret = btrfs_unlink_subvol(trans, dir, dest->root_key.objectid,
+-                                dentry->d_name.name, dentry->d_name.len);
++      ret = btrfs_unlink_subvol(trans, dir, dentry);
+       if (ret) {
+               err = ret;
+               btrfs_abort_transaction(trans, ret);
+@@ -4480,10 +4491,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
+               return PTR_ERR(trans);
+       if (unlikely(btrfs_ino(BTRFS_I(inode)) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) {
+-              err = btrfs_unlink_subvol(trans, dir,
+-                                        BTRFS_I(inode)->location.objectid,
+-                                        dentry->d_name.name,
+-                                        dentry->d_name.len);
++              err = btrfs_unlink_subvol(trans, dir, dentry);
+               goto out;
+       }
+@@ -9482,7 +9490,6 @@ static int btrfs_rename_exchange(struct inode *old_dir,
+       u64 new_ino = btrfs_ino(BTRFS_I(new_inode));
+       u64 old_idx = 0;
+       u64 new_idx = 0;
+-      u64 root_objectid;
+       int ret;
+       bool root_log_pinned = false;
+       bool dest_log_pinned = false;
+@@ -9588,10 +9595,7 @@ static int btrfs_rename_exchange(struct inode *old_dir,
+       /* src is a subvolume */
+       if (old_ino == BTRFS_FIRST_FREE_OBJECTID) {
+-              root_objectid = BTRFS_I(old_inode)->root->root_key.objectid;
+-              ret = btrfs_unlink_subvol(trans, old_dir, root_objectid,
+-                                        old_dentry->d_name.name,
+-                                        old_dentry->d_name.len);
++              ret = btrfs_unlink_subvol(trans, old_dir, old_dentry);
+       } else { /* src is an inode */
+               ret = __btrfs_unlink_inode(trans, root, BTRFS_I(old_dir),
+                                          BTRFS_I(old_dentry->d_inode),
+@@ -9607,10 +9611,7 @@ static int btrfs_rename_exchange(struct inode *old_dir,
+       /* dest is a subvolume */
+       if (new_ino == BTRFS_FIRST_FREE_OBJECTID) {
+-              root_objectid = BTRFS_I(new_inode)->root->root_key.objectid;
+-              ret = btrfs_unlink_subvol(trans, new_dir, root_objectid,
+-                                        new_dentry->d_name.name,
+-                                        new_dentry->d_name.len);
++              ret = btrfs_unlink_subvol(trans, new_dir, new_dentry);
+       } else { /* dest is an inode */
+               ret = __btrfs_unlink_inode(trans, dest, BTRFS_I(new_dir),
+                                          BTRFS_I(new_dentry->d_inode),
+@@ -9808,7 +9809,6 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+       struct inode *new_inode = d_inode(new_dentry);
+       struct inode *old_inode = d_inode(old_dentry);
+       u64 index = 0;
+-      u64 root_objectid;
+       int ret;
+       u64 old_ino = btrfs_ino(BTRFS_I(old_inode));
+       bool log_pinned = false;
+@@ -9916,10 +9916,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+                               BTRFS_I(old_inode), 1);
+       if (unlikely(old_ino == BTRFS_FIRST_FREE_OBJECTID)) {
+-              root_objectid = BTRFS_I(old_inode)->root->root_key.objectid;
+-              ret = btrfs_unlink_subvol(trans, old_dir, root_objectid,
+-                                      old_dentry->d_name.name,
+-                                      old_dentry->d_name.len);
++              ret = btrfs_unlink_subvol(trans, old_dir, old_dentry);
+       } else {
+               ret = __btrfs_unlink_inode(trans, root, BTRFS_I(old_dir),
+                                       BTRFS_I(d_inode(old_dentry)),
+@@ -9938,10 +9935,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+               new_inode->i_ctime = current_time(new_inode);
+               if (unlikely(btrfs_ino(BTRFS_I(new_inode)) ==
+                            BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) {
+-                      root_objectid = BTRFS_I(new_inode)->location.objectid;
+-                      ret = btrfs_unlink_subvol(trans, new_dir, root_objectid,
+-                                              new_dentry->d_name.name,
+-                                              new_dentry->d_name.len);
++                      ret = btrfs_unlink_subvol(trans, new_dir, new_dentry);
+                       BUG_ON(new_inode->i_nlink == 0);
+               } else {
+                       ret = btrfs_unlink_inode(trans, dest, BTRFS_I(new_dir),
+-- 
+2.20.1
+
diff --git a/queue-4.19/lsm-generalize-flag-passing-to-security_capable.patch b/queue-4.19/lsm-generalize-flag-passing-to-security_capable.patch
new file mode 100644 (file)
index 0000000..398bb56
--- /dev/null
@@ -0,0 +1,514 @@
+From ef5d271a81784711c03d90f4befc64d716de082a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Jan 2019 16:10:53 -0800
+Subject: LSM: generalize flag passing to security_capable
+
+From: Micah Morton <mortonm@chromium.org>
+
+[ Upstream commit c1a85a00ea66cb6f0bd0f14e47c28c2b0999799f ]
+
+This patch provides a general mechanism for passing flags to the
+security_capable LSM hook. It replaces the specific 'audit' flag that is
+used to tell security_capable whether it should log an audit message for
+the given capability check. The reason for generalizing this flag
+passing is so we can add an additional flag that signifies whether
+security_capable is being called by a setid syscall (which is needed by
+the proposed SafeSetID LSM).
+
+Signed-off-by: Micah Morton <mortonm@chromium.org>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: James Morris <james.morris@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/lsm_hooks.h              |  8 +++++---
+ include/linux/security.h               | 28 +++++++++++++-------------
+ kernel/capability.c                    | 22 +++++++++++---------
+ kernel/seccomp.c                       |  4 ++--
+ security/apparmor/capability.c         | 14 ++++++-------
+ security/apparmor/include/capability.h |  2 +-
+ security/apparmor/ipc.c                |  3 ++-
+ security/apparmor/lsm.c                |  4 ++--
+ security/apparmor/resource.c           |  2 +-
+ security/commoncap.c                   | 17 ++++++++--------
+ security/security.c                    | 14 +++++--------
+ security/selinux/hooks.c               | 18 ++++++++---------
+ security/smack/smack_access.c          |  2 +-
+ 13 files changed, 71 insertions(+), 67 deletions(-)
+
+diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
+index 97a020c616ad..3833c871fd45 100644
+--- a/include/linux/lsm_hooks.h
++++ b/include/linux/lsm_hooks.h
+@@ -1270,7 +1270,7 @@
+  *    @cred contains the credentials to use.
+  *    @ns contains the user namespace we want the capability in
+  *    @cap contains the capability <include/linux/capability.h>.
+- *    @audit contains whether to write an audit message or not
++ *    @opts contains options for the capable check <include/linux/security.h>
+  *    Return 0 if the capability is granted for @tsk.
+  * @syslog:
+  *    Check permission before accessing the kernel message ring or changing
+@@ -1446,8 +1446,10 @@ union security_list_options {
+                       const kernel_cap_t *effective,
+                       const kernel_cap_t *inheritable,
+                       const kernel_cap_t *permitted);
+-      int (*capable)(const struct cred *cred, struct user_namespace *ns,
+-                      int cap, int audit);
++      int (*capable)(const struct cred *cred,
++                      struct user_namespace *ns,
++                      int cap,
++                      unsigned int opts);
+       int (*quotactl)(int cmds, int type, int id, struct super_block *sb);
+       int (*quota_on)(struct dentry *dentry);
+       int (*syslog)(int type);
+diff --git a/include/linux/security.h b/include/linux/security.h
+index 75f4156c84d7..d2240605edc4 100644
+--- a/include/linux/security.h
++++ b/include/linux/security.h
+@@ -54,9 +54,12 @@ struct xattr;
+ struct xfrm_sec_ctx;
+ struct mm_struct;
++/* Default (no) options for the capable function */
++#define CAP_OPT_NONE 0x0
+ /* If capable should audit the security request */
+-#define SECURITY_CAP_NOAUDIT 0
+-#define SECURITY_CAP_AUDIT 1
++#define CAP_OPT_NOAUDIT BIT(1)
++/* If capable is being called by a setid function */
++#define CAP_OPT_INSETID BIT(2)
+ /* LSM Agnostic defines for sb_set_mnt_opts */
+ #define SECURITY_LSM_NATIVE_LABELS    1
+@@ -72,7 +75,7 @@ enum lsm_event {
+ /* These functions are in security/commoncap.c */
+ extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
+-                     int cap, int audit);
++                     int cap, unsigned int opts);
+ extern int cap_settime(const struct timespec64 *ts, const struct timezone *tz);
+ extern int cap_ptrace_access_check(struct task_struct *child, unsigned int mode);
+ extern int cap_ptrace_traceme(struct task_struct *parent);
+@@ -233,10 +236,10 @@ int security_capset(struct cred *new, const struct cred *old,
+                   const kernel_cap_t *effective,
+                   const kernel_cap_t *inheritable,
+                   const kernel_cap_t *permitted);
+-int security_capable(const struct cred *cred, struct user_namespace *ns,
+-                      int cap);
+-int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns,
+-                           int cap);
++int security_capable(const struct cred *cred,
++                     struct user_namespace *ns,
++                     int cap,
++                     unsigned int opts);
+ int security_quotactl(int cmds, int type, int id, struct super_block *sb);
+ int security_quota_on(struct dentry *dentry);
+ int security_syslog(int type);
+@@ -492,14 +495,11 @@ static inline int security_capset(struct cred *new,
+ }
+ static inline int security_capable(const struct cred *cred,
+-                                 struct user_namespace *ns, int cap)
++                                 struct user_namespace *ns,
++                                 int cap,
++                                 unsigned int opts)
+ {
+-      return cap_capable(cred, ns, cap, SECURITY_CAP_AUDIT);
+-}
+-
+-static inline int security_capable_noaudit(const struct cred *cred,
+-                                         struct user_namespace *ns, int cap) {
+-      return cap_capable(cred, ns, cap, SECURITY_CAP_NOAUDIT);
++      return cap_capable(cred, ns, cap, opts);
+ }
+ static inline int security_quotactl(int cmds, int type, int id,
+diff --git a/kernel/capability.c b/kernel/capability.c
+index 1e1c0236f55b..7718d7dcadc7 100644
+--- a/kernel/capability.c
++++ b/kernel/capability.c
+@@ -299,7 +299,7 @@ bool has_ns_capability(struct task_struct *t,
+       int ret;
+       rcu_read_lock();
+-      ret = security_capable(__task_cred(t), ns, cap);
++      ret = security_capable(__task_cred(t), ns, cap, CAP_OPT_NONE);
+       rcu_read_unlock();
+       return (ret == 0);
+@@ -340,7 +340,7 @@ bool has_ns_capability_noaudit(struct task_struct *t,
+       int ret;
+       rcu_read_lock();
+-      ret = security_capable_noaudit(__task_cred(t), ns, cap);
++      ret = security_capable(__task_cred(t), ns, cap, CAP_OPT_NOAUDIT);
+       rcu_read_unlock();
+       return (ret == 0);
+@@ -363,7 +363,9 @@ bool has_capability_noaudit(struct task_struct *t, int cap)
+       return has_ns_capability_noaudit(t, &init_user_ns, cap);
+ }
+-static bool ns_capable_common(struct user_namespace *ns, int cap, bool audit)
++static bool ns_capable_common(struct user_namespace *ns,
++                            int cap,
++                            unsigned int opts)
+ {
+       int capable;
+@@ -372,8 +374,7 @@ static bool ns_capable_common(struct user_namespace *ns, int cap, bool audit)
+               BUG();
+       }
+-      capable = audit ? security_capable(current_cred(), ns, cap) :
+-                        security_capable_noaudit(current_cred(), ns, cap);
++      capable = security_capable(current_cred(), ns, cap, opts);
+       if (capable == 0) {
+               current->flags |= PF_SUPERPRIV;
+               return true;
+@@ -394,7 +395,7 @@ static bool ns_capable_common(struct user_namespace *ns, int cap, bool audit)
+  */
+ bool ns_capable(struct user_namespace *ns, int cap)
+ {
+-      return ns_capable_common(ns, cap, true);
++      return ns_capable_common(ns, cap, CAP_OPT_NONE);
+ }
+ EXPORT_SYMBOL(ns_capable);
+@@ -412,7 +413,7 @@ EXPORT_SYMBOL(ns_capable);
+  */
+ bool ns_capable_noaudit(struct user_namespace *ns, int cap)
+ {
+-      return ns_capable_common(ns, cap, false);
++      return ns_capable_common(ns, cap, CAP_OPT_NOAUDIT);
+ }
+ EXPORT_SYMBOL(ns_capable_noaudit);
+@@ -448,10 +449,11 @@ EXPORT_SYMBOL(capable);
+ bool file_ns_capable(const struct file *file, struct user_namespace *ns,
+                    int cap)
+ {
++
+       if (WARN_ON_ONCE(!cap_valid(cap)))
+               return false;
+-      if (security_capable(file->f_cred, ns, cap) == 0)
++      if (security_capable(file->f_cred, ns, cap, CAP_OPT_NONE) == 0)
+               return true;
+       return false;
+@@ -500,10 +502,12 @@ bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns)
+ {
+       int ret = 0;  /* An absent tracer adds no restrictions */
+       const struct cred *cred;
++
+       rcu_read_lock();
+       cred = rcu_dereference(tsk->ptracer_cred);
+       if (cred)
+-              ret = security_capable_noaudit(cred, ns, CAP_SYS_PTRACE);
++              ret = security_capable(cred, ns, CAP_SYS_PTRACE,
++                                     CAP_OPT_NOAUDIT);
+       rcu_read_unlock();
+       return (ret == 0);
+ }
+diff --git a/kernel/seccomp.c b/kernel/seccomp.c
+index fd023ac24e10..56e69203b658 100644
+--- a/kernel/seccomp.c
++++ b/kernel/seccomp.c
+@@ -383,8 +383,8 @@ static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog)
+        * behavior of privileged children.
+        */
+       if (!task_no_new_privs(current) &&
+-          security_capable_noaudit(current_cred(), current_user_ns(),
+-                                   CAP_SYS_ADMIN) != 0)
++          security_capable(current_cred(), current_user_ns(),
++                                   CAP_SYS_ADMIN, CAP_OPT_NOAUDIT) != 0)
+               return ERR_PTR(-EACCES);
+       /* Allocate a new seccomp_filter */
+diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c
+index 253ef6e9d445..752f73980e30 100644
+--- a/security/apparmor/capability.c
++++ b/security/apparmor/capability.c
+@@ -110,13 +110,13 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile,
+  * profile_capable - test if profile allows use of capability @cap
+  * @profile: profile being enforced    (NOT NULL, NOT unconfined)
+  * @cap: capability to test if allowed
+- * @audit: whether an audit record should be generated
++ * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated
+  * @sa: audit data (MAY BE NULL indicating no auditing)
+  *
+  * Returns: 0 if allowed else -EPERM
+  */
+-static int profile_capable(struct aa_profile *profile, int cap, int audit,
+-                         struct common_audit_data *sa)
++static int profile_capable(struct aa_profile *profile, int cap,
++                         unsigned int opts, struct common_audit_data *sa)
+ {
+       int error;
+@@ -126,7 +126,7 @@ static int profile_capable(struct aa_profile *profile, int cap, int audit,
+       else
+               error = -EPERM;
+-      if (audit == SECURITY_CAP_NOAUDIT) {
++      if (opts & CAP_OPT_NOAUDIT) {
+               if (!COMPLAIN_MODE(profile))
+                       return error;
+               /* audit the cap request in complain mode but note that it
+@@ -142,13 +142,13 @@ static int profile_capable(struct aa_profile *profile, int cap, int audit,
+  * aa_capable - test permission to use capability
+  * @label: label being tested for capability (NOT NULL)
+  * @cap: capability to be tested
+- * @audit: whether an audit record should be generated
++ * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated
+  *
+  * Look up capability in profile capability set.
+  *
+  * Returns: 0 on success, or else an error code.
+  */
+-int aa_capable(struct aa_label *label, int cap, int audit)
++int aa_capable(struct aa_label *label, int cap, unsigned int opts)
+ {
+       struct aa_profile *profile;
+       int error = 0;
+@@ -156,7 +156,7 @@ int aa_capable(struct aa_label *label, int cap, int audit)
+       sa.u.cap = cap;
+       error = fn_for_each_confined(label, profile,
+-                      profile_capable(profile, cap, audit, &sa));
++                      profile_capable(profile, cap, opts, &sa));
+       return error;
+ }
+diff --git a/security/apparmor/include/capability.h b/security/apparmor/include/capability.h
+index e0304e2aeb7f..1b3663b6ab12 100644
+--- a/security/apparmor/include/capability.h
++++ b/security/apparmor/include/capability.h
+@@ -40,7 +40,7 @@ struct aa_caps {
+ extern struct aa_sfs_entry aa_sfs_entry_caps[];
+-int aa_capable(struct aa_label *label, int cap, int audit);
++int aa_capable(struct aa_label *label, int cap, unsigned int opts);
+ static inline void aa_free_cap_rules(struct aa_caps *caps)
+ {
+diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c
+index 527ea1557120..aacd1e95cb59 100644
+--- a/security/apparmor/ipc.c
++++ b/security/apparmor/ipc.c
+@@ -107,7 +107,8 @@ static int profile_tracer_perm(struct aa_profile *tracer,
+       aad(sa)->label = &tracer->label;
+       aad(sa)->peer = tracee;
+       aad(sa)->request = 0;
+-      aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, 1);
++      aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE,
++                                  CAP_OPT_NONE);
+       return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb);
+ }
+diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
+index 8b8b70620bbe..590ca7d8fae5 100644
+--- a/security/apparmor/lsm.c
++++ b/security/apparmor/lsm.c
+@@ -174,14 +174,14 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
+ }
+ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns,
+-                          int cap, int audit)
++                          int cap, unsigned int opts)
+ {
+       struct aa_label *label;
+       int error = 0;
+       label = aa_get_newest_cred_label(cred);
+       if (!unconfined(label))
+-              error = aa_capable(label, cap, audit);
++              error = aa_capable(label, cap, opts);
+       aa_put_label(label);
+       return error;
+diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c
+index 95fd26d09757..552ed09cb47e 100644
+--- a/security/apparmor/resource.c
++++ b/security/apparmor/resource.c
+@@ -124,7 +124,7 @@ int aa_task_setrlimit(struct aa_label *label, struct task_struct *task,
+        */
+       if (label != peer &&
+-          aa_capable(label, CAP_SYS_RESOURCE, SECURITY_CAP_NOAUDIT) != 0)
++          aa_capable(label, CAP_SYS_RESOURCE, CAP_OPT_NOAUDIT) != 0)
+               error = fn_for_each(label, profile,
+                               audit_resource(profile, resource,
+                                              new_rlim->rlim_max, peer,
+diff --git a/security/commoncap.c b/security/commoncap.c
+index 2e489d6a3ac8..3023b4ad38a7 100644
+--- a/security/commoncap.c
++++ b/security/commoncap.c
+@@ -69,7 +69,7 @@ static void warn_setuid_and_fcaps_mixed(const char *fname)
+  * kernel's capable() and has_capability() returns 1 for this case.
+  */
+ int cap_capable(const struct cred *cred, struct user_namespace *targ_ns,
+-              int cap, int audit)
++              int cap, unsigned int opts)
+ {
+       struct user_namespace *ns = targ_ns;
+@@ -223,12 +223,11 @@ int cap_capget(struct task_struct *target, kernel_cap_t *effective,
+  */
+ static inline int cap_inh_is_capped(void)
+ {
+-
+       /* they are so limited unless the current task has the CAP_SETPCAP
+        * capability
+        */
+       if (cap_capable(current_cred(), current_cred()->user_ns,
+-                      CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0)
++                      CAP_SETPCAP, CAP_OPT_NONE) == 0)
+               return 0;
+       return 1;
+ }
+@@ -1212,8 +1211,9 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
+                   || ((old->securebits & SECURE_ALL_LOCKS & ~arg2))   /*[2]*/
+                   || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS))   /*[3]*/
+                   || (cap_capable(current_cred(),
+-                                  current_cred()->user_ns, CAP_SETPCAP,
+-                                  SECURITY_CAP_AUDIT) != 0)           /*[4]*/
++                                  current_cred()->user_ns,
++                                  CAP_SETPCAP,
++                                  CAP_OPT_NONE) != 0)                 /*[4]*/
+                       /*
+                        * [1] no changing of bits that are locked
+                        * [2] no unlocking of locks
+@@ -1308,9 +1308,10 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
+ {
+       int cap_sys_admin = 0;
+-      if (cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
+-                      SECURITY_CAP_NOAUDIT) == 0)
++      if (cap_capable(current_cred(), &init_user_ns,
++                              CAP_SYS_ADMIN, CAP_OPT_NOAUDIT) == 0)
+               cap_sys_admin = 1;
++
+       return cap_sys_admin;
+ }
+@@ -1329,7 +1330,7 @@ int cap_mmap_addr(unsigned long addr)
+       if (addr < dac_mmap_min_addr) {
+               ret = cap_capable(current_cred(), &init_user_ns, CAP_SYS_RAWIO,
+-                                SECURITY_CAP_AUDIT);
++                                CAP_OPT_NONE);
+               /* set PF_SUPERPRIV if it turns out we allow the low mmap */
+               if (ret == 0)
+                       current->flags |= PF_SUPERPRIV;
+diff --git a/security/security.c b/security/security.c
+index 5ce2448f3a45..9478444bf93f 100644
+--- a/security/security.c
++++ b/security/security.c
+@@ -283,16 +283,12 @@ int security_capset(struct cred *new, const struct cred *old,
+                               effective, inheritable, permitted);
+ }
+-int security_capable(const struct cred *cred, struct user_namespace *ns,
+-                   int cap)
++int security_capable(const struct cred *cred,
++                   struct user_namespace *ns,
++                   int cap,
++                   unsigned int opts)
+ {
+-      return call_int_hook(capable, 0, cred, ns, cap, SECURITY_CAP_AUDIT);
+-}
+-
+-int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns,
+-                           int cap)
+-{
+-      return call_int_hook(capable, 0, cred, ns, cap, SECURITY_CAP_NOAUDIT);
++      return call_int_hook(capable, 0, cred, ns, cap, opts);
+ }
+ int security_quotactl(int cmds, int type, int id, struct super_block *sb)
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
+index 109ab510bdb1..040c843968dc 100644
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -1794,7 +1794,7 @@ static inline u32 signal_to_av(int sig)
+ /* Check whether a task is allowed to use a capability. */
+ static int cred_has_capability(const struct cred *cred,
+-                             int cap, int audit, bool initns)
++                             int cap, unsigned int opts, bool initns)
+ {
+       struct common_audit_data ad;
+       struct av_decision avd;
+@@ -1821,7 +1821,7 @@ static int cred_has_capability(const struct cred *cred,
+       rc = avc_has_perm_noaudit(&selinux_state,
+                                 sid, sid, sclass, av, 0, &avd);
+-      if (audit == SECURITY_CAP_AUDIT) {
++      if (!(opts & CAP_OPT_NOAUDIT)) {
+               int rc2 = avc_audit(&selinux_state,
+                                   sid, sid, sclass, av, &avd, rc, &ad, 0);
+               if (rc2)
+@@ -2341,9 +2341,9 @@ static int selinux_capset(struct cred *new, const struct cred *old,
+  */
+ static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
+-                         int cap, int audit)
++                         int cap, unsigned int opts)
+ {
+-      return cred_has_capability(cred, cap, audit, ns == &init_user_ns);
++      return cred_has_capability(cred, cap, opts, ns == &init_user_ns);
+ }
+ static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
+@@ -2417,7 +2417,7 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
+       int rc, cap_sys_admin = 0;
+       rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
+-                               SECURITY_CAP_NOAUDIT, true);
++                               CAP_OPT_NOAUDIT, true);
+       if (rc == 0)
+               cap_sys_admin = 1;
+@@ -3272,11 +3272,11 @@ static int selinux_inode_getattr(const struct path *path)
+ static bool has_cap_mac_admin(bool audit)
+ {
+       const struct cred *cred = current_cred();
+-      int cap_audit = audit ? SECURITY_CAP_AUDIT : SECURITY_CAP_NOAUDIT;
++      unsigned int opts = audit ? CAP_OPT_NONE : CAP_OPT_NOAUDIT;
+-      if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, cap_audit))
++      if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, opts))
+               return false;
+-      if (cred_has_capability(cred, CAP_MAC_ADMIN, cap_audit, true))
++      if (cred_has_capability(cred, CAP_MAC_ADMIN, opts, true))
+               return false;
+       return true;
+ }
+@@ -3680,7 +3680,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
+       case KDSKBENT:
+       case KDSKBSENT:
+               error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
+-                                          SECURITY_CAP_AUDIT, true);
++                                          CAP_OPT_NONE, true);
+               break;
+       /* default case assumes that the command will go
+diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
+index c071c356a963..a7855c61c05c 100644
+--- a/security/smack/smack_access.c
++++ b/security/smack/smack_access.c
+@@ -640,7 +640,7 @@ bool smack_privileged_cred(int cap, const struct cred *cred)
+       struct smack_known_list_elem *sklep;
+       int rc;
+-      rc = cap_capable(cred, &init_user_ns, cap, SECURITY_CAP_AUDIT);
++      rc = cap_capable(cred, &init_user_ns, cap, CAP_OPT_NONE);
+       if (rc)
+               return false;
+-- 
+2.20.1
+
index 138113fd06c9ec1a4d1d52802d0178fb72a2e759..111d24971bc64976f3f6c9fb823c5b9e7bd8f7c6 100644 (file)
@@ -27,6 +27,7 @@ arm64-dts-allwinner-a64-olinuxino-fix-sdio-supply-regulator.patch
 fix-built-in-early-load-intel-microcode-alignment.patch
 block-fix-an-integer-overflow-in-logical-block-size.patch
 arm-dts-am571x-idk-fix-gpios-property-to-have-the-correct-gpio-number.patch
+lsm-generalize-flag-passing-to-security_capable.patch
 ptrace-reintroduce-usage-of-subjective-credentials-in-ptrace_has_cap.patch
 usb-core-hub-improved-device-recognition-on-remote-wakeup.patch
 x86-resctrl-fix-an-imbalance-in-domain_remove_cpu.patch
@@ -38,6 +39,7 @@ perf-hists-fix-variable-name-s-inconsistency-in-hists__for_each-macro.patch
 perf-report-fix-incorrectly-added-dimensions-as-switch-perf-data-file.patch
 mm-shmem.c-thp-shmem-fix-conflict-of-above-47bit-hint-address-and-pmd-alignment.patch
 mm-memcg-slab-call-flush_memcg_workqueue-only-if-memcg-workqueue-is-valid.patch
+btrfs-rework-arguments-of-btrfs_unlink_subvol.patch
 btrfs-fix-invalid-removal-of-root-ref.patch
 btrfs-do-not-delete-mismatched-root-refs.patch
 btrfs-fix-memory-leak-in-qgroup-accounting.patch