Update mainline series
up to 0ee40e0e58eb ("FROMLIST: overlayfs: override_creds=off option bypass creator_cred")
Change-Id: I77a77d1faa37f99034c0115360bef63cce57d02d
diff --git a/android-mainline/FROMLIST-Add-flags-option-to-get-xattr-method-paired-to-__vfs_getxattr.patch b/android-mainline/FROMLIST-Add-flags-option-to-get-xattr-method-paired-to-__vfs_getxattr.patch
new file mode 100644
index 0000000..5918a55
--- /dev/null
+++ b/android-mainline/FROMLIST-Add-flags-option-to-get-xattr-method-paired-to-__vfs_getxattr.patch
@@ -0,0 +1,1025 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Mark Salyzyn <salyzyn@google.com>
+Date: Mon, 4 Nov 2019 08:57:10 -0800
+Subject: FROMLIST: Add flags option to get xattr method paired to
+ __vfs_getxattr
+
+Add a flag option to get xattr method that could have a bit flag of
+XATTR_NOSECURITY passed to it. XATTR_NOSECURITY is generally then
+set in the __vfs_getxattr path when called by security
+infrastructure.
+
+This handles the case of a union filesystem driver that is being
+requested by the security layer to report back the xattr data.
+
+For the use case where access is to be blocked by the security layer.
+
+The path then could be security(dentry) ->
+__vfs_getxattr(dentry...XATTR_NOSECURITY) ->
+handler->get(dentry...XATTR_NOSECURITY) ->
+__vfs_getxattr(lower_dentry...XATTR_NOSECURITY) ->
+lower_handler->get(lower_dentry...XATTR_NOSECURITY)
+which would report back through the chain data and success as
+expected, the logging security layer at the top would have the
+data to determine the access permissions and report back the target
+context that was blocked.
+
+Without the get handler flag, the path on a union filesystem would be
+the errant security(dentry) -> __vfs_getxattr(dentry) ->
+handler->get(dentry) -> vfs_getxattr(lower_dentry) -> nested ->
+security(lower_dentry, log off) -> lower_handler->get(lower_dentry)
+which would report back through the chain no data, and -EACCES.
+
+For selinux for both cases, this would translate to a correctly
+determined blocked access. In the first case with this change a correct avc
+log would be reported, in the second legacy case an incorrect avc log
+would be reported against an uninitialized u:object_r:unlabeled:s0
+context making the logs cosmetically useless for audit2allow.
+
+This patch series is inert and is the wide-spread addition of the
+flags option for xattr functions, and a replacement of __vfs_getxattr
+with __vfs_getxattr(...XATTR_NOSECURITY).
+
+Signed-off-by: Mark Salyzyn <salyzyn@android.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Acked-by: Jan Kara <jack@suse.cz>
+Acked-by: Jeff Layton <jlayton@kernel.org>
+Acked-by: David Sterba <dsterba@suse.com>
+Acked-by: Darrick J. Wong <darrick.wong@oracle.com>
+Acked-by: Mike Marshall <hubcap@omnibond.com>
+Cc: Stephen Smalley <sds@tycho.nsa.gov>
+Cc: linux-kernel@vger.kernel.org
+Cc: kernel-team@android.com
+Cc: linux-security-module@vger.kernel.org
+
+(cherry picked from (rejected from archive because of too many recipients))
+Signed-off-by: Mark Salyzyn <salyzyn@google.com>
+Bug: 133515582
+Bug: 136124883
+Bug: 129319403
+Change-Id: Iabbb8771939d5f66667a26bb23ddf4c562c349a1
+---
+ Documentation/filesystems/locking.rst | 2 +-
+ fs/9p/acl.c | 3 ++-
+ fs/9p/xattr.c | 3 ++-
+ fs/afs/xattr.c | 10 ++++----
+ fs/btrfs/xattr.c | 3 ++-
+ fs/ceph/xattr.c | 3 ++-
+ fs/cifs/xattr.c | 2 +-
+ fs/ecryptfs/inode.c | 6 +++--
+ fs/ecryptfs/mmap.c | 2 +-
+ fs/erofs/xattr.c | 3 ++-
+ fs/ext2/xattr_security.c | 2 +-
+ fs/ext2/xattr_trusted.c | 2 +-
+ fs/ext2/xattr_user.c | 2 +-
+ fs/ext4/xattr_security.c | 2 +-
+ fs/ext4/xattr_trusted.c | 2 +-
+ fs/ext4/xattr_user.c | 2 +-
+ fs/f2fs/xattr.c | 4 +--
+ fs/fuse/xattr.c | 4 +--
+ fs/gfs2/xattr.c | 3 ++-
+ fs/hfs/attr.c | 2 +-
+ fs/hfsplus/xattr.c | 3 ++-
+ fs/hfsplus/xattr_security.c | 3 ++-
+ fs/hfsplus/xattr_trusted.c | 3 ++-
+ fs/hfsplus/xattr_user.c | 3 ++-
+ fs/jffs2/security.c | 3 ++-
+ fs/jffs2/xattr_trusted.c | 3 ++-
+ fs/jffs2/xattr_user.c | 3 ++-
+ fs/jfs/xattr.c | 5 ++--
+ fs/kernfs/inode.c | 3 ++-
+ fs/nfs/nfs4proc.c | 6 +++--
+ fs/ocfs2/xattr.c | 9 ++++---
+ fs/orangefs/xattr.c | 3 ++-
+ fs/overlayfs/super.c | 8 +++---
+ fs/posix_acl.c | 2 +-
+ fs/reiserfs/xattr_security.c | 3 ++-
+ fs/reiserfs/xattr_trusted.c | 3 ++-
+ fs/reiserfs/xattr_user.c | 3 ++-
+ fs/squashfs/xattr.c | 2 +-
+ fs/ubifs/xattr.c | 3 ++-
+ fs/xattr.c | 36 +++++++++++++--------------
+ fs/xfs/xfs_xattr.c | 3 ++-
+ include/linux/xattr.h | 9 ++++---
+ include/uapi/linux/xattr.h | 7 ++++--
+ mm/shmem.c | 3 ++-
+ net/socket.c | 3 ++-
+ security/commoncap.c | 6 +++--
+ security/integrity/evm/evm_main.c | 3 ++-
+ security/selinux/hooks.c | 11 +++++---
+ security/smack/smack_lsm.c | 5 ++--
+ 49 files changed, 131 insertions(+), 88 deletions(-)
+
+diff --git a/Documentation/filesystems/locking.rst b/Documentation/filesystems/locking.rst
+index fc3a0704553c..d4798204a5ee 100644
+--- a/Documentation/filesystems/locking.rst
++++ b/Documentation/filesystems/locking.rst
+@@ -125,7 +125,7 @@ prototypes::
+ bool (*list)(struct dentry *dentry);
+ int (*get)(const struct xattr_handler *handler, struct dentry *dentry,
+ struct inode *inode, const char *name, void *buffer,
+- size_t size);
++ size_t size, int flags);
+ int (*set)(const struct xattr_handler *handler, struct dentry *dentry,
+ struct inode *inode, const char *name, const void *buffer,
+ size_t size, int flags);
+diff --git a/fs/9p/acl.c b/fs/9p/acl.c
+index 6261719f6f2a..cb14e8b312bc 100644
+--- a/fs/9p/acl.c
++++ b/fs/9p/acl.c
+@@ -214,7 +214,8 @@ int v9fs_acl_mode(struct inode *dir, umode_t *modep,
+
+ static int v9fs_xattr_get_acl(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ struct v9fs_session_info *v9ses;
+ struct posix_acl *acl;
+diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c
+index ac8ff8ca4c11..5cfa772452fd 100644
+--- a/fs/9p/xattr.c
++++ b/fs/9p/xattr.c
+@@ -139,7 +139,8 @@ ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
+
+ static int v9fs_xattr_handler_get(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ const char *full_name = xattr_full_name(handler, name);
+
+diff --git a/fs/afs/xattr.c b/fs/afs/xattr.c
+index 7af41fd5f3ee..e3a33d742e7f 100644
+--- a/fs/afs/xattr.c
++++ b/fs/afs/xattr.c
+@@ -40,7 +40,7 @@ ssize_t afs_listxattr(struct dentry *dentry, char *buffer, size_t size)
+ static int afs_xattr_get_acl(const struct xattr_handler *handler,
+ struct dentry *dentry,
+ struct inode *inode, const char *name,
+- void *buffer, size_t size)
++ void *buffer, size_t size, int flags)
+ {
+ struct afs_fs_cursor fc;
+ struct afs_status_cb *scb;
+@@ -163,7 +163,7 @@ static const struct xattr_handler afs_xattr_afs_acl_handler = {
+ static int afs_xattr_get_yfs(const struct xattr_handler *handler,
+ struct dentry *dentry,
+ struct inode *inode, const char *name,
+- void *buffer, size_t size)
++ void *buffer, size_t size, int flags)
+ {
+ struct afs_fs_cursor fc;
+ struct afs_status_cb *scb;
+@@ -334,7 +334,7 @@ static const struct xattr_handler afs_xattr_yfs_handler = {
+ static int afs_xattr_get_cell(const struct xattr_handler *handler,
+ struct dentry *dentry,
+ struct inode *inode, const char *name,
+- void *buffer, size_t size)
++ void *buffer, size_t size, int flags)
+ {
+ struct afs_vnode *vnode = AFS_FS_I(inode);
+ struct afs_cell *cell = vnode->volume->cell;
+@@ -361,7 +361,7 @@ static const struct xattr_handler afs_xattr_afs_cell_handler = {
+ static int afs_xattr_get_fid(const struct xattr_handler *handler,
+ struct dentry *dentry,
+ struct inode *inode, const char *name,
+- void *buffer, size_t size)
++ void *buffer, size_t size, int flags)
+ {
+ struct afs_vnode *vnode = AFS_FS_I(inode);
+ char text[16 + 1 + 24 + 1 + 8 + 1];
+@@ -399,7 +399,7 @@ static const struct xattr_handler afs_xattr_afs_fid_handler = {
+ static int afs_xattr_get_volume(const struct xattr_handler *handler,
+ struct dentry *dentry,
+ struct inode *inode, const char *name,
+- void *buffer, size_t size)
++ void *buffer, size_t size, int flags)
+ {
+ struct afs_vnode *vnode = AFS_FS_I(inode);
+ const char *volname = vnode->volume->name;
+diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
+index 95d9aebff2c4..1e522e145344 100644
+--- a/fs/btrfs/xattr.c
++++ b/fs/btrfs/xattr.c
+@@ -353,7 +353,8 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
+
+ static int btrfs_xattr_handler_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ name = xattr_full_name(handler, name);
+ return btrfs_getxattr(inode, name, buffer, size);
+diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
+index cb18ee637cb7..a789f1e802b7 100644
+--- a/fs/ceph/xattr.c
++++ b/fs/ceph/xattr.c
+@@ -1153,7 +1153,8 @@ int __ceph_setxattr(struct inode *inode, const char *name,
+
+ static int ceph_get_xattr_handler(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+- const char *name, void *value, size_t size)
++ const char *name, void *value, size_t size,
++ int flags)
+ {
+ if (!ceph_is_valid_xattr(name))
+ return -EOPNOTSUPP;
+diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
+index db4ba8f6077e..e44e562c46fb 100644
+--- a/fs/cifs/xattr.c
++++ b/fs/cifs/xattr.c
+@@ -199,7 +199,7 @@ static int cifs_creation_time_get(struct dentry *dentry, struct inode *inode,
+
+ static int cifs_xattr_get(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+- const char *name, void *value, size_t size)
++ const char *name, void *value, size_t size, int flags)
+ {
+ ssize_t rc = -EOPNOTSUPP;
+ unsigned int xid;
+diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
+index 18426f4855f1..c710c7533729 100644
+--- a/fs/ecryptfs/inode.c
++++ b/fs/ecryptfs/inode.c
+@@ -1018,7 +1018,8 @@ ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode,
+ goto out;
+ }
+ inode_lock(lower_inode);
+- rc = __vfs_getxattr(lower_dentry, lower_inode, name, value, size);
++ rc = __vfs_getxattr(lower_dentry, lower_inode, name, value, size,
++ XATTR_NOSECURITY);
+ inode_unlock(lower_inode);
+ out:
+ return rc;
+@@ -1103,7 +1104,8 @@ const struct inode_operations ecryptfs_main_iops = {
+
+ static int ecryptfs_xattr_get(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ return ecryptfs_getxattr(dentry, inode, name, buffer, size);
+ }
+diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
+index cffa0c1ec829..2362be3e3b4d 100644
+--- a/fs/ecryptfs/mmap.c
++++ b/fs/ecryptfs/mmap.c
+@@ -422,7 +422,7 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
+ }
+ inode_lock(lower_inode);
+ size = __vfs_getxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
+- xattr_virt, PAGE_SIZE);
++ xattr_virt, PAGE_SIZE, XATTR_NOSECURITY);
+ if (size < 0)
+ size = 8;
+ put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
+diff --git a/fs/erofs/xattr.c b/fs/erofs/xattr.c
+index a13a78725c57..144b1713ebab 100644
+--- a/fs/erofs/xattr.c
++++ b/fs/erofs/xattr.c
+@@ -463,7 +463,8 @@ int erofs_getxattr(struct inode *inode, int index,
+
+ static int erofs_xattr_generic_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ struct erofs_sb_info *const sbi = EROFS_I_SB(inode);
+
+diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c
+index 9a682e440acb..d5f6eb0b487b 100644
+--- a/fs/ext2/xattr_security.c
++++ b/fs/ext2/xattr_security.c
+@@ -11,7 +11,7 @@
+ static int
+ ext2_xattr_security_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size, int flags)
+ {
+ return ext2_xattr_get(inode, EXT2_XATTR_INDEX_SECURITY, name,
+ buffer, size);
+diff --git a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c
+index 49add1107850..8d313664f0fa 100644
+--- a/fs/ext2/xattr_trusted.c
++++ b/fs/ext2/xattr_trusted.c
+@@ -18,7 +18,7 @@ ext2_xattr_trusted_list(struct dentry *dentry)
+ static int
+ ext2_xattr_trusted_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size, int flags)
+ {
+ return ext2_xattr_get(inode, EXT2_XATTR_INDEX_TRUSTED, name,
+ buffer, size);
+diff --git a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c
+index c243a3b4d69d..712b7c95cc64 100644
+--- a/fs/ext2/xattr_user.c
++++ b/fs/ext2/xattr_user.c
+@@ -20,7 +20,7 @@ ext2_xattr_user_list(struct dentry *dentry)
+ static int
+ ext2_xattr_user_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size, int flags)
+ {
+ if (!test_opt(inode->i_sb, XATTR_USER))
+ return -EOPNOTSUPP;
+diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c
+index 197a9d8a15ef..50fb71393fb6 100644
+--- a/fs/ext4/xattr_security.c
++++ b/fs/ext4/xattr_security.c
+@@ -15,7 +15,7 @@
+ static int
+ ext4_xattr_security_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size, int flags)
+ {
+ return ext4_xattr_get(inode, EXT4_XATTR_INDEX_SECURITY,
+ name, buffer, size);
+diff --git a/fs/ext4/xattr_trusted.c b/fs/ext4/xattr_trusted.c
+index e9389e5d75c3..64bd8f86c1f1 100644
+--- a/fs/ext4/xattr_trusted.c
++++ b/fs/ext4/xattr_trusted.c
+@@ -22,7 +22,7 @@ ext4_xattr_trusted_list(struct dentry *dentry)
+ static int
+ ext4_xattr_trusted_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size, int flags)
+ {
+ return ext4_xattr_get(inode, EXT4_XATTR_INDEX_TRUSTED,
+ name, buffer, size);
+diff --git a/fs/ext4/xattr_user.c b/fs/ext4/xattr_user.c
+index d4546184b34b..b7301373820e 100644
+--- a/fs/ext4/xattr_user.c
++++ b/fs/ext4/xattr_user.c
+@@ -21,7 +21,7 @@ ext4_xattr_user_list(struct dentry *dentry)
+ static int
+ ext4_xattr_user_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size, int flags)
+ {
+ if (!test_opt(inode->i_sb, XATTR_USER))
+ return -EOPNOTSUPP;
+diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
+index 181900af2576..95cfcf1589df 100644
+--- a/fs/f2fs/xattr.c
++++ b/fs/f2fs/xattr.c
+@@ -25,7 +25,7 @@
+
+ static int f2fs_xattr_generic_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size, int flags)
+ {
+ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+
+@@ -80,7 +80,7 @@ static bool f2fs_xattr_trusted_list(struct dentry *dentry)
+
+ static int f2fs_xattr_advise_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size, int flags)
+ {
+ if (buffer)
+ *((char *)buffer) = F2FS_I(inode)->i_advise;
+diff --git a/fs/fuse/xattr.c b/fs/fuse/xattr.c
+index 20d052e08b3b..414718a51c25 100644
+--- a/fs/fuse/xattr.c
++++ b/fs/fuse/xattr.c
+@@ -176,7 +176,7 @@ int fuse_removexattr(struct inode *inode, const char *name)
+
+ static int fuse_xattr_get(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+- const char *name, void *value, size_t size)
++ const char *name, void *value, size_t size, int flags)
+ {
+ return fuse_getxattr(inode, name, value, size);
+ }
+@@ -199,7 +199,7 @@ static bool no_xattr_list(struct dentry *dentry)
+
+ static int no_xattr_get(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+- const char *name, void *value, size_t size)
++ const char *name, void *value, size_t size, int flags)
+ {
+ return -EOPNOTSUPP;
+ }
+diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
+index bbe593d16bea..a9db067a99c1 100644
+--- a/fs/gfs2/xattr.c
++++ b/fs/gfs2/xattr.c
+@@ -588,7 +588,8 @@ static int __gfs2_xattr_get(struct inode *inode, const char *name,
+
+ static int gfs2_xattr_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_holder gh;
+diff --git a/fs/hfs/attr.c b/fs/hfs/attr.c
+index 74fa62643136..08222a9c5d31 100644
+--- a/fs/hfs/attr.c
++++ b/fs/hfs/attr.c
+@@ -115,7 +115,7 @@ static ssize_t __hfs_getxattr(struct inode *inode, enum hfs_xattr_type type,
+
+ static int hfs_xattr_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *value, size_t size)
++ const char *name, void *value, size_t size, int flags)
+ {
+ return __hfs_getxattr(inode, handler->flags, value, size);
+ }
+diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c
+index bb0b27d88e50..381c2aaedbc8 100644
+--- a/fs/hfsplus/xattr.c
++++ b/fs/hfsplus/xattr.c
+@@ -839,7 +839,8 @@ static int hfsplus_removexattr(struct inode *inode, const char *name)
+
+ static int hfsplus_osx_getxattr(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ /*
+ * Don't allow retrieving properly prefixed attributes
+diff --git a/fs/hfsplus/xattr_security.c b/fs/hfsplus/xattr_security.c
+index cfbe6a3bfb1e..43e28b3a716d 100644
+--- a/fs/hfsplus/xattr_security.c
++++ b/fs/hfsplus/xattr_security.c
+@@ -15,7 +15,8 @@
+
+ static int hfsplus_security_getxattr(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer,
++ size_t size, int flags)
+ {
+ return hfsplus_getxattr(inode, name, buffer, size,
+ XATTR_SECURITY_PREFIX,
+diff --git a/fs/hfsplus/xattr_trusted.c b/fs/hfsplus/xattr_trusted.c
+index fbad91e1dada..54d926314f8c 100644
+--- a/fs/hfsplus/xattr_trusted.c
++++ b/fs/hfsplus/xattr_trusted.c
+@@ -14,7 +14,8 @@
+
+ static int hfsplus_trusted_getxattr(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer,
++ size_t size, int flags)
+ {
+ return hfsplus_getxattr(inode, name, buffer, size,
+ XATTR_TRUSTED_PREFIX,
+diff --git a/fs/hfsplus/xattr_user.c b/fs/hfsplus/xattr_user.c
+index 74d19faf255e..4d2b1ffff887 100644
+--- a/fs/hfsplus/xattr_user.c
++++ b/fs/hfsplus/xattr_user.c
+@@ -14,7 +14,8 @@
+
+ static int hfsplus_user_getxattr(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size,
++ int flags)
+ {
+
+ return hfsplus_getxattr(inode, name, buffer, size,
+diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
+index c2332e30f218..e6f42fe435af 100644
+--- a/fs/jffs2/security.c
++++ b/fs/jffs2/security.c
+@@ -50,7 +50,8 @@ int jffs2_init_security(struct inode *inode, struct inode *dir,
+ /* ---- XATTR Handler for "security.*" ----------------- */
+ static int jffs2_security_getxattr(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ return do_jffs2_getxattr(inode, JFFS2_XPREFIX_SECURITY,
+ name, buffer, size);
+diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c
+index 5d6030826c52..9dccaae549f5 100644
+--- a/fs/jffs2/xattr_trusted.c
++++ b/fs/jffs2/xattr_trusted.c
+@@ -18,7 +18,8 @@
+
+ static int jffs2_trusted_getxattr(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ return do_jffs2_getxattr(inode, JFFS2_XPREFIX_TRUSTED,
+ name, buffer, size);
+diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c
+index 9d027b4abcf9..c0983a3e810b 100644
+--- a/fs/jffs2/xattr_user.c
++++ b/fs/jffs2/xattr_user.c
+@@ -18,7 +18,8 @@
+
+ static int jffs2_user_getxattr(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ return do_jffs2_getxattr(inode, JFFS2_XPREFIX_USER,
+ name, buffer, size);
+diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
+index db41e7803163..5c79a35bf62f 100644
+--- a/fs/jfs/xattr.c
++++ b/fs/jfs/xattr.c
+@@ -925,7 +925,7 @@ static int __jfs_xattr_set(struct inode *inode, const char *name,
+
+ static int jfs_xattr_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *value, size_t size)
++ const char *name, void *value, size_t size, int flags)
+ {
+ name = xattr_full_name(handler, name);
+ return __jfs_getxattr(inode, name, value, size);
+@@ -942,7 +942,8 @@ static int jfs_xattr_set(const struct xattr_handler *handler,
+
+ static int jfs_xattr_get_os2(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *value, size_t size)
++ const char *name, void *value, size_t size,
++ int flags)
+ {
+ if (is_known_namespace(name))
+ return -EOPNOTSUPP;
+diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
+index f3eaa8869f42..22357c69a82b 100644
+--- a/fs/kernfs/inode.c
++++ b/fs/kernfs/inode.c
+@@ -308,7 +308,8 @@ int kernfs_xattr_set(struct kernfs_node *kn, const char *name,
+
+ static int kernfs_vfs_xattr_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *suffix, void *value, size_t size)
++ const char *suffix, void *value, size_t size,
++ int flags)
+ {
+ const char *name = xattr_full_name(handler, suffix);
+ struct kernfs_node *kn = inode->i_private;
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index caacf5e7f5e1..f77ddd31b57a 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -7283,7 +7283,8 @@ static int nfs4_xattr_set_nfs4_acl(const struct xattr_handler *handler,
+
+ static int nfs4_xattr_get_nfs4_acl(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *key, void *buf, size_t buflen)
++ const char *key, void *buf, size_t buflen,
++ int flags)
+ {
+ return nfs4_proc_get_acl(inode, buf, buflen);
+ }
+@@ -7308,7 +7309,8 @@ static int nfs4_xattr_set_nfs4_label(const struct xattr_handler *handler,
+
+ static int nfs4_xattr_get_nfs4_label(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *key, void *buf, size_t buflen)
++ const char *key, void *buf, size_t buflen,
++ int flags)
+ {
+ if (security_ismaclabel(key))
+ return nfs4_get_security_label(inode, buf, buflen);
+diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
+index d8507972ee13..85df32e0f851 100644
+--- a/fs/ocfs2/xattr.c
++++ b/fs/ocfs2/xattr.c
+@@ -7232,7 +7232,8 @@ int ocfs2_init_security_and_acl(struct inode *dir,
+ */
+ static int ocfs2_xattr_security_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_SECURITY,
+ name, buffer, size);
+@@ -7304,7 +7305,8 @@ const struct xattr_handler ocfs2_xattr_security_handler = {
+ */
+ static int ocfs2_xattr_trusted_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_TRUSTED,
+ name, buffer, size);
+@@ -7330,7 +7332,8 @@ const struct xattr_handler ocfs2_xattr_trusted_handler = {
+ */
+ static int ocfs2_xattr_user_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+diff --git a/fs/orangefs/xattr.c b/fs/orangefs/xattr.c
+index bdc285aea360..ef4180bff7bb 100644
+--- a/fs/orangefs/xattr.c
++++ b/fs/orangefs/xattr.c
+@@ -541,7 +541,8 @@ static int orangefs_xattr_get_default(const struct xattr_handler *handler,
+ struct inode *inode,
+ const char *name,
+ void *buffer,
+- size_t size)
++ size_t size,
++ int flags)
+ {
+ return orangefs_inode_getxattr(inode, name, buffer, size);
+
+diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
+index afbcb116a7f1..57f5f948ae0a 100644
+--- a/fs/overlayfs/super.c
++++ b/fs/overlayfs/super.c
+@@ -855,7 +855,7 @@ static unsigned int ovl_split_lowerdirs(char *str)
+ static int __maybe_unused
+ ovl_posix_acl_xattr_get(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size, int flags)
+ {
+ return ovl_xattr_get(dentry, inode, handler->name, buffer, size);
+ }
+@@ -920,7 +920,8 @@ ovl_posix_acl_xattr_set(const struct xattr_handler *handler,
+
+ static int ovl_own_xattr_get(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ return -EOPNOTSUPP;
+ }
+@@ -935,7 +936,8 @@ static int ovl_own_xattr_set(const struct xattr_handler *handler,
+
+ static int ovl_other_xattr_get(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ return ovl_xattr_get(dentry, inode, name, buffer, size);
+ }
+diff --git a/fs/posix_acl.c b/fs/posix_acl.c
+index 84ad1c90d535..cd55621e570b 100644
+--- a/fs/posix_acl.c
++++ b/fs/posix_acl.c
+@@ -832,7 +832,7 @@ EXPORT_SYMBOL (posix_acl_to_xattr);
+ static int
+ posix_acl_xattr_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *value, size_t size)
++ const char *name, void *value, size_t size, int flags)
+ {
+ struct posix_acl *acl;
+ int error;
+diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
+index 20be9a0e5870..eedfa07a4fd0 100644
+--- a/fs/reiserfs/xattr_security.c
++++ b/fs/reiserfs/xattr_security.c
+@@ -11,7 +11,8 @@
+
+ static int
+ security_get(const struct xattr_handler *handler, struct dentry *unused,
+- struct inode *inode, const char *name, void *buffer, size_t size)
++ struct inode *inode, const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ if (IS_PRIVATE(inode))
+ return -EPERM;
+diff --git a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c
+index 5ed48da3d02b..2d11d98605dd 100644
+--- a/fs/reiserfs/xattr_trusted.c
++++ b/fs/reiserfs/xattr_trusted.c
+@@ -10,7 +10,8 @@
+
+ static int
+ trusted_get(const struct xattr_handler *handler, struct dentry *unused,
+- struct inode *inode, const char *name, void *buffer, size_t size)
++ struct inode *inode, const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
+ return -EPERM;
+diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c
+index a573ca45bacc..2a59d85c69c9 100644
+--- a/fs/reiserfs/xattr_user.c
++++ b/fs/reiserfs/xattr_user.c
+@@ -9,7 +9,8 @@
+
+ static int
+ user_get(const struct xattr_handler *handler, struct dentry *unused,
+- struct inode *inode, const char *name, void *buffer, size_t size)
++ struct inode *inode, const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ if (!reiserfs_xattrs_user(inode->i_sb))
+ return -EOPNOTSUPP;
+diff --git a/fs/squashfs/xattr.c b/fs/squashfs/xattr.c
+index e1e3f3dd5a06..d8d58c990652 100644
+--- a/fs/squashfs/xattr.c
++++ b/fs/squashfs/xattr.c
+@@ -204,7 +204,7 @@ static int squashfs_xattr_handler_get(const struct xattr_handler *handler,
+ struct dentry *unused,
+ struct inode *inode,
+ const char *name,
+- void *buffer, size_t size)
++ void *buffer, size_t size, int flags)
+ {
+ return squashfs_xattr_get(inode, handler->flags, name,
+ buffer, size);
+diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
+index 9aefbb60074f..26e1a74f178e 100644
+--- a/fs/ubifs/xattr.c
++++ b/fs/ubifs/xattr.c
+@@ -669,7 +669,8 @@ int ubifs_init_security(struct inode *dentry, struct inode *inode,
+
+ static int xattr_get(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ dbg_gen("xattr '%s', ino %lu ('%pd'), buf size %zd", name,
+ inode->i_ino, dentry, size);
+diff --git a/fs/xattr.c b/fs/xattr.c
+index 142fa44fa587..9520365195cf 100644
+--- a/fs/xattr.c
++++ b/fs/xattr.c
+@@ -281,7 +281,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
+ return PTR_ERR(handler);
+ if (!handler->get)
+ return -EOPNOTSUPP;
+- error = handler->get(handler, dentry, inode, name, NULL, 0);
++ error = handler->get(handler, dentry, inode, name, NULL, 0, 0);
+ if (error < 0)
+ return error;
+
+@@ -292,32 +292,20 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
+ memset(value, 0, error + 1);
+ }
+
+- error = handler->get(handler, dentry, inode, name, value, error);
++ error = handler->get(handler, dentry, inode, name, value, error, 0);
+ *xattr_value = value;
+ return error;
+ }
+
+ ssize_t
+ __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
+- void *value, size_t size)
++ void *value, size_t size, int flags)
+ {
+ const struct xattr_handler *handler;
+-
+- handler = xattr_resolve_name(inode, &name);
+- if (IS_ERR(handler))
+- return PTR_ERR(handler);
+- if (!handler->get)
+- return -EOPNOTSUPP;
+- return handler->get(handler, dentry, inode, name, value, size);
+-}
+-EXPORT_SYMBOL(__vfs_getxattr);
+-
+-ssize_t
+-vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
+-{
+- struct inode *inode = dentry->d_inode;
+ int error;
+
++ if (flags & XATTR_NOSECURITY)
++ goto nolsm;
+ error = xattr_permission(inode, name, MAY_READ);
+ if (error)
+ return error;
+@@ -339,7 +327,19 @@ vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
+ return ret;
+ }
+ nolsm:
+- return __vfs_getxattr(dentry, inode, name, value, size);
++ handler = xattr_resolve_name(inode, &name);
++ if (IS_ERR(handler))
++ return PTR_ERR(handler);
++ if (!handler->get)
++ return -EOPNOTSUPP;
++ return handler->get(handler, dentry, inode, name, value, size, flags);
++}
++EXPORT_SYMBOL(__vfs_getxattr);
++
++ssize_t
++vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
++{
++ return __vfs_getxattr(dentry, dentry->d_inode, name, value, size, 0);
+ }
+ EXPORT_SYMBOL_GPL(vfs_getxattr);
+
+diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c
+index cb895b1df5e4..9d2030e02a37 100644
+--- a/fs/xfs/xfs_xattr.c
++++ b/fs/xfs/xfs_xattr.c
+@@ -18,7 +18,8 @@
+
+ static int
+ xfs_xattr_get(const struct xattr_handler *handler, struct dentry *unused,
+- struct inode *inode, const char *name, void *value, size_t size)
++ struct inode *inode, const char *name, void *value, size_t size,
++ int flags)
+ {
+ int xflags = handler->flags;
+ struct xfs_inode *ip = XFS_I(inode);
+diff --git a/include/linux/xattr.h b/include/linux/xattr.h
+index 6dad031be3c2..4df9dcdc48c5 100644
+--- a/include/linux/xattr.h
++++ b/include/linux/xattr.h
+@@ -30,10 +30,10 @@ struct xattr_handler {
+ const char *prefix;
+ int flags; /* fs private flags */
+ bool (*list)(struct dentry *dentry);
+- int (*get)(const struct xattr_handler *, struct dentry *dentry,
++ int (*get)(const struct xattr_handler *handler, struct dentry *dentry,
+ struct inode *inode, const char *name, void *buffer,
+- size_t size);
+- int (*set)(const struct xattr_handler *, struct dentry *dentry,
++ size_t size, int flags);
++ int (*set)(const struct xattr_handler *handler, struct dentry *dentry,
+ struct inode *inode, const char *name, const void *buffer,
+ size_t size, int flags);
+ };
+@@ -46,7 +46,8 @@ struct xattr {
+ size_t value_len;
+ };
+
+-ssize_t __vfs_getxattr(struct dentry *, struct inode *, const char *, void *, size_t);
++ssize_t __vfs_getxattr(struct dentry *dentry, struct inode *inode,
++ const char *name, void *buffer, size_t size, int flags);
+ ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
+ ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
+ int __vfs_setxattr(struct dentry *, struct inode *, const char *, const void *, size_t, int);
+diff --git a/include/uapi/linux/xattr.h b/include/uapi/linux/xattr.h
+index c1395b5bd432..1eba02616274 100644
+--- a/include/uapi/linux/xattr.h
++++ b/include/uapi/linux/xattr.h
+@@ -17,8 +17,11 @@
+ #if __UAPI_DEF_XATTR
+ #define __USE_KERNEL_XATTR_DEFS
+
+-#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
+-#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
++#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
++#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
++#ifdef __KERNEL__ /* following is kernel internal, colocated for maintenance */
++#define XATTR_NOSECURITY 0x4 /* get value, do not involve security check */
++#endif
+ #endif
+
+ /* Namespaces */
+diff --git a/mm/shmem.c b/mm/shmem.c
+index 220be9fa2c41..641570ee1c10 100644
+--- a/mm/shmem.c
++++ b/mm/shmem.c
+@@ -3221,7 +3221,8 @@ static int shmem_initxattrs(struct inode *inode,
+
+ static int shmem_xattr_handler_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+- const char *name, void *buffer, size_t size)
++ const char *name, void *buffer, size_t size,
++ int flags)
+ {
+ struct shmem_inode_info *info = SHMEM_I(inode);
+
+diff --git a/net/socket.c b/net/socket.c
+index 6a9ab7a8b1d2..6b0fea92dd02 100644
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -300,7 +300,8 @@ static const struct dentry_operations sockfs_dentry_operations = {
+
+ static int sockfs_xattr_get(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+- const char *suffix, void *value, size_t size)
++ const char *suffix, void *value, size_t size,
++ int flags)
+ {
+ if (value) {
+ if (dentry->d_name.len + 1 > size)
+diff --git a/security/commoncap.c b/security/commoncap.c
+index f4ee0ae106b2..378a2f66a73d 100644
+--- a/security/commoncap.c
++++ b/security/commoncap.c
+@@ -297,7 +297,8 @@ int cap_inode_need_killpriv(struct dentry *dentry)
+ struct inode *inode = d_backing_inode(dentry);
+ int error;
+
+- error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);
++ error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0,
++ XATTR_NOSECURITY);
+ return error > 0;
+ }
+
+@@ -586,7 +587,8 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data
+
+ fs_ns = inode->i_sb->s_user_ns;
+ size = __vfs_getxattr((struct dentry *)dentry, inode,
+- XATTR_NAME_CAPS, &data, XATTR_CAPS_SZ);
++ XATTR_NAME_CAPS, &data, XATTR_CAPS_SZ,
++ XATTR_NOSECURITY);
+ if (size == -ENODATA || size == -EOPNOTSUPP)
+ /* no data, that's ok */
+ return -ENODATA;
+diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
+index f9a81b187fae..921c8f2afcaf 100644
+--- a/security/integrity/evm/evm_main.c
++++ b/security/integrity/evm/evm_main.c
+@@ -100,7 +100,8 @@ static int evm_find_protected_xattrs(struct dentry *dentry)
+ return -EOPNOTSUPP;
+
+ list_for_each_entry_rcu(xattr, &evm_config_xattrnames, list) {
+- error = __vfs_getxattr(dentry, inode, xattr->name, NULL, 0);
++ error = __vfs_getxattr(dentry, inode, xattr->name, NULL, 0,
++ XATTR_NOSECURITY);
+ if (error < 0) {
+ if (error == -ENODATA)
+ continue;
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
+index 9625b99e677f..60cd34d25878 100644
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -554,7 +554,8 @@ static int sb_finish_set_opts(struct super_block *sb)
+ goto out;
+ }
+
+- rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0);
++ rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL,
++ 0, XATTR_NOSECURITY);
+ if (rc < 0 && rc != -ENODATA) {
+ if (rc == -EOPNOTSUPP)
+ pr_warn("SELinux: (dev %s, type "
+@@ -1380,12 +1381,14 @@ static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry,
+ return -ENOMEM;
+
+ context[len] = '\0';
+- rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
++ rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len,
++ XATTR_NOSECURITY);
+ if (rc == -ERANGE) {
+ kfree(context);
+
+ /* Need a larger buffer. Query for the right size. */
+- rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
++ rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0,
++ XATTR_NOSECURITY);
+ if (rc < 0)
+ return rc;
+
+@@ -1396,7 +1399,7 @@ static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry,
+
+ context[len] = '\0';
+ rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX,
+- context, len);
++ context, len, XATTR_NOSECURITY);
+ }
+ if (rc < 0) {
+ kfree(context);
+diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
+index abeb09c30633..73009d3d902a 100644
+--- a/security/smack/smack_lsm.c
++++ b/security/smack/smack_lsm.c
+@@ -292,7 +292,8 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
+ if (buffer == NULL)
+ return ERR_PTR(-ENOMEM);
+
+- rc = __vfs_getxattr(dp, ip, name, buffer, SMK_LONGLABEL);
++ rc = __vfs_getxattr(dp, ip, name, buffer, SMK_LONGLABEL,
++ XATTR_NOSECURITY);
+ if (rc < 0)
+ skp = ERR_PTR(rc);
+ else if (rc == 0)
+@@ -3440,7 +3441,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
+ } else {
+ rc = __vfs_getxattr(dp, inode,
+ XATTR_NAME_SMACKTRANSMUTE, trattr,
+- TRANS_TRUE_SIZE);
++ TRANS_TRUE_SIZE, XATTR_NOSECURITY);
+ if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
+ TRANS_TRUE_SIZE) != 0)
+ rc = -EINVAL;
diff --git a/android-mainline/FROMLIST-afs-xattr-use-scnprintf.patch b/android-mainline/FROMLIST-afs-xattr-use-scnprintf.patch
new file mode 100644
index 0000000..b17ff70
--- /dev/null
+++ b/android-mainline/FROMLIST-afs-xattr-use-scnprintf.patch
@@ -0,0 +1,65 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Mark Salyzyn <salyzyn@android.com>
+Date: Tue, 5 Nov 2019 07:43:49 -0800
+Subject: FROMLIST: afs: xattr: use scnprintf
+
+sprintf and snprintf are fragile in future maintenance, switch to
+using scnprintf to ensure no accidental Use After Free conditions
+are introduced.
+
+Signed-off-by: Mark Salyzyn <salyzyn@android.com>
+Cc: linux-kernel@vger.kernel.org
+Cc: linux-fsdevel@vger.kernel.org
+Cc: David Howells <dhowells@redhat.com>
+Cc: linux-afs@lists.infradead.org
+Cc: Jan Kara <jack@suse.cz>
+
+(cherry picked from https://lore.kernel.org/lkml/20191105154850.187723-1-salyzyn@android.com/)
+Signed-off-by: Mark Salyzyn <salyzyn@google.com>
+Bug: 133515582
+Bug: 136124883
+Bug: 129319403
+Change-Id: I6fca97f90f60472c1a7737898b4629b20c04c495
+---
+ fs/afs/xattr.c | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+diff --git a/fs/afs/xattr.c b/fs/afs/xattr.c
+index 5552d034090a..7af41fd5f3ee 100644
+--- a/fs/afs/xattr.c
++++ b/fs/afs/xattr.c
+@@ -228,11 +228,11 @@ static int afs_xattr_get_yfs(const struct xattr_handler *handler,
+ break;
+ case 1:
+ data = buf;
+- dsize = snprintf(buf, sizeof(buf), "%u", yacl->inherit_flag);
++ dsize = scnprintf(buf, sizeof(buf), "%u", yacl->inherit_flag);
+ break;
+ case 2:
+ data = buf;
+- dsize = snprintf(buf, sizeof(buf), "%u", yacl->num_cleaned);
++ dsize = scnprintf(buf, sizeof(buf), "%u", yacl->num_cleaned);
+ break;
+ case 3:
+ data = yacl->vol_acl->data;
+@@ -370,13 +370,15 @@ static int afs_xattr_get_fid(const struct xattr_handler *handler,
+ /* The volume ID is 64-bit, the vnode ID is 96-bit and the
+ * uniquifier is 32-bit.
+ */
+- len = sprintf(text, "%llx:", vnode->fid.vid);
++ len = scnprintf(text, sizeof(text), "%llx:", vnode->fid.vid);
+ if (vnode->fid.vnode_hi)
+- len += sprintf(text + len, "%x%016llx",
+- vnode->fid.vnode_hi, vnode->fid.vnode);
++ len += scnprintf(text + len, sizeof(text) - len, "%x%016llx",
++ vnode->fid.vnode_hi, vnode->fid.vnode);
+ else
+- len += sprintf(text + len, "%llx", vnode->fid.vnode);
+- len += sprintf(text + len, ":%x", vnode->fid.unique);
++ len += scnprintf(text + len, sizeof(text) - len, "%llx",
++ vnode->fid.vnode);
++ len += scnprintf(text + len, sizeof(text) - len, ":%x",
++ vnode->fid.unique);
+
+ if (size == 0)
+ return len;
diff --git a/android-mainline/FROMLIST-overlayfs-handle-XATTR_NOSECURITY-flag-for-get-xattr-method.patch b/android-mainline/FROMLIST-overlayfs-handle-XATTR_NOSECURITY-flag-for-get-xattr-method.patch
new file mode 100644
index 0000000..36a4b41
--- /dev/null
+++ b/android-mainline/FROMLIST-overlayfs-handle-XATTR_NOSECURITY-flag-for-get-xattr-method.patch
@@ -0,0 +1,115 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Mark Salyzyn <salyzyn@android.com>
+Date: Mon, 15 Jul 2019 15:46:45 -0700
+Subject: FROMLIST: overlayfs: handle XATTR_NOSECURITY flag for get xattr
+ method
+
+Because of the overlayfs getxattr recursion, the incoming inode fails
+to update the selinux sid resulting in avc denials being reported
+against a target context of u:object_r:unlabeled:s0.
+
+Solution is to respond to the XATTR_NOSECURITY flag in get xattr
+method that calls the __vfs_getxattr handler instead so that the
+context can be read in, rather than being denied with an -EACCES
+when vfs_getxattr handler is called.
+
+For the use case where access is to be blocked by the security layer.
+
+The path then would be security(dentry) ->
+__vfs_getxattr({dentry...XATTR_NOSECURITY}) ->
+handler->get({dentry...XATTR_NOSECURITY}) ->
+__vfs_getxattr({realdentry...XATTR_NOSECURITY}) ->
+lower_handler->get({realdentry...XATTR_NOSECURITY}) which
+would report back through the chain data and success as expected,
+the logging security layer at the top would have the data to
+determine the access permissions and report back to the logs and
+the caller that the target context was blocked.
+
+For selinux this would solve the cosmetic issue of the selinux log
+and allow audit2allow to correctly report the rule needed to address
+the access problem.
+
+Signed-off-by: Mark Salyzyn <salyzyn@android.com>
+Cc: Miklos Szeredi <miklos@szeredi.hu>
+Cc: Jonathan Corbet <corbet@lwn.net>
+Cc: Vivek Goyal <vgoyal@redhat.com>
+Cc: Eric W. Biederman <ebiederm@xmission.com>
+Cc: Amir Goldstein <amir73il@gmail.com>
+Cc: Randy Dunlap <rdunlap@infradead.org>
+Cc: Stephen Smalley <sds@tycho.nsa.gov>
+Cc: linux-unionfs@vger.kernel.org
+Cc: linux-doc@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org
+Cc: kernel-team@android.com
+Cc: linux-security-module@vger.kernel.org
+
+(cherry pick from https://lore.kernel.org/lkml/20191104215253.141818-3-salyzyn@android.com/)
+Signed-off-by: Mark Salyzyn <salyzyn@google.com>
+Bug: 133515582
+Bug: 136124883
+Bug: 129319403
+Change-Id: Ia39543c5ce617976f14d790fb88e471d575ffd65
+---
+ fs/overlayfs/inode.c | 5 +++--
+ fs/overlayfs/overlayfs.h | 2 +-
+ fs/overlayfs/super.c | 4 ++--
+ 3 files changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
+index bc14781886bf..c057e51057f7 100644
+--- a/fs/overlayfs/inode.c
++++ b/fs/overlayfs/inode.c
+@@ -363,7 +363,7 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name,
+ }
+
+ int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
+- void *value, size_t size)
++ void *value, size_t size, int flags)
+ {
+ ssize_t res;
+ const struct cred *old_cred;
+@@ -371,7 +371,8 @@ int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
+ ovl_i_dentry_upper(inode) ?: ovl_dentry_lower(dentry);
+
+ old_cred = ovl_override_creds(dentry->d_sb);
+- res = vfs_getxattr(realdentry, name, value, size);
++ res = __vfs_getxattr(realdentry, d_inode(realdentry), name,
++ value, size, flags);
+ revert_creds(old_cred);
+ return res;
+ }
+diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
+index 6934bcf030f0..ab3d031c422b 100644
+--- a/fs/overlayfs/overlayfs.h
++++ b/fs/overlayfs/overlayfs.h
+@@ -356,7 +356,7 @@ int ovl_permission(struct inode *inode, int mask);
+ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name,
+ const void *value, size_t size, int flags);
+ int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
+- void *value, size_t size);
++ void *value, size_t size, int flags);
+ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
+ struct posix_acl *ovl_get_acl(struct inode *inode, int type);
+ int ovl_update_time(struct inode *inode, struct timespec64 *ts, int flags);
+diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
+index 57f5f948ae0a..c91e7b604631 100644
+--- a/fs/overlayfs/super.c
++++ b/fs/overlayfs/super.c
+@@ -857,7 +857,7 @@ ovl_posix_acl_xattr_get(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+ const char *name, void *buffer, size_t size, int flags)
+ {
+- return ovl_xattr_get(dentry, inode, handler->name, buffer, size);
++ return ovl_xattr_get(dentry, inode, handler->name, buffer, size, flags);
+ }
+
+ static int __maybe_unused
+@@ -939,7 +939,7 @@ static int ovl_other_xattr_get(const struct xattr_handler *handler,
+ const char *name, void *buffer, size_t size,
+ int flags)
+ {
+- return ovl_xattr_get(dentry, inode, name, buffer, size);
++ return ovl_xattr_get(dentry, inode, name, buffer, size, flags);
+ }
+
+ static int ovl_other_xattr_set(const struct xattr_handler *handler,
diff --git a/android-mainline/FROMLIST-overlayfs-internal-getxattr-operations-without-sepolicy-checking.patch b/android-mainline/FROMLIST-overlayfs-internal-getxattr-operations-without-sepolicy-checking.patch
new file mode 100644
index 0000000..4bf2ed8
--- /dev/null
+++ b/android-mainline/FROMLIST-overlayfs-internal-getxattr-operations-without-sepolicy-checking.patch
@@ -0,0 +1,192 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Mark Salyzyn <salyzyn@android.com>
+Date: Tue, 23 Jul 2019 13:53:48 -0700
+Subject: FROMLIST: overlayfs: internal getxattr operations without sepolicy
+ checking
+
+Check impure, opaque, origin & meta xattr with no sepolicy audit
+(using __vfs_getxattr) since these operations are internal to
+overlayfs operations and do not disclose any data. This became
+an issue for credential override off since sys_admin would have
+been required by the caller; whereas would have been inherently
+present for the creator since it performed the mount.
+
+This is a change in operations since we do not check in the new
+ovl_do_vfs_getxattr function if the credential override is off or
+not. Reasoning is that the sepolicy check is unnecessary overhead,
+especially since the check can be expensive.
+
+Because for override credentials off, this affects _everyone_ that
+underneath performs private xattr calls without the appropriate
+sepolicy permissions and sys_admin capability. Providing blanket
+support for sys_admin would be bad for all possible callers.
+
+For the override credentials on, this will affect only the mounter,
+should it lack sepolicy permissions. Not considered a security
+problem since mounting by definition has sys_admin capabilities,
+but sepolicy contexts would still need to be crafted.
+
+It should be noted that there is precedence, __vfs_getxattr is used
+in other filesystems for their own internal trusted xattr management.
+
+Signed-off-by: Mark Salyzyn <salyzyn@android.com>
+Cc: Miklos Szeredi <miklos@szeredi.hu>
+Cc: Jonathan Corbet <corbet@lwn.net>
+Cc: Vivek Goyal <vgoyal@redhat.com>
+Cc: Eric W. Biederman <ebiederm@xmission.com>
+Cc: Amir Goldstein <amir73il@gmail.com>
+Cc: Randy Dunlap <rdunlap@infradead.org>
+Cc: Stephen Smalley <sds@tycho.nsa.gov>
+Cc: linux-unionfs@vger.kernel.org
+Cc: linux-doc@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org
+Cc: kernel-team@android.com
+Cc: linux-security-module@vger.kernel.org
+
+(cherry picked from https://lore.kernel.org/lkml/20191104215253.141818-4-salyzyn@android.com/)
+Signed-off-by: Mark Salyzyn <salyzyn@google.com>
+Bug: 133515582
+Bug: 136124883
+Bug: 129319403
+Change-Id: I34d99cc46e9e87a79efc8d05f85980bbc137f7eb
+---
+ fs/overlayfs/namei.c | 12 +++++++-----
+ fs/overlayfs/overlayfs.h | 8 ++++++++
+ fs/overlayfs/util.c | 18 +++++++++---------
+ 3 files changed, 24 insertions(+), 14 deletions(-)
+
+diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
+index e9717c2f7d45..f5aba0a0767b 100644
+--- a/fs/overlayfs/namei.c
++++ b/fs/overlayfs/namei.c
+@@ -106,10 +106,11 @@ int ovl_check_fh_len(struct ovl_fh *fh, int fh_len)
+
+ static struct ovl_fh *ovl_get_fh(struct dentry *dentry, const char *name)
+ {
+- int res, err;
++ ssize_t res;
++ int err;
+ struct ovl_fh *fh = NULL;
+
+- res = vfs_getxattr(dentry, name, NULL, 0);
++ res = ovl_do_vfs_getxattr(dentry, name, NULL, 0);
+ if (res < 0) {
+ if (res == -ENODATA || res == -EOPNOTSUPP)
+ return NULL;
+@@ -123,7 +124,7 @@ static struct ovl_fh *ovl_get_fh(struct dentry *dentry, const char *name)
+ if (!fh)
+ return ERR_PTR(-ENOMEM);
+
+- res = vfs_getxattr(dentry, name, fh, res);
++ res = ovl_do_vfs_getxattr(dentry, name, fh, res);
+ if (res < 0)
+ goto fail;
+
+@@ -141,10 +142,11 @@ static struct ovl_fh *ovl_get_fh(struct dentry *dentry, const char *name)
+ return NULL;
+
+ fail:
+- pr_warn_ratelimited("overlayfs: failed to get origin (%i)\n", res);
++ pr_warn_ratelimited("overlayfs: failed to get origin (%zi)\n", res);
+ goto out;
+ invalid:
+- pr_warn_ratelimited("overlayfs: invalid origin (%*phN)\n", res, fh);
++ pr_warn_ratelimited("overlayfs: invalid origin (%*phN)\n",
++ (int)res, fh);
+ goto out;
+ }
+
+diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
+index ab3d031c422b..55b872c28bf9 100644
+--- a/fs/overlayfs/overlayfs.h
++++ b/fs/overlayfs/overlayfs.h
+@@ -200,6 +200,14 @@ static inline bool ovl_open_flags_need_copy_up(int flags)
+ return ((OPEN_FMODE(flags) & FMODE_WRITE) || (flags & O_TRUNC));
+ }
+
++static inline ssize_t ovl_do_vfs_getxattr(struct dentry *dentry,
++ const char *name, void *buf,
++ size_t size)
++{
++ return __vfs_getxattr(dentry, d_inode(dentry), name, buf, size,
++ XATTR_NOSECURITY);
++}
++
+ /* util.c */
+ int ovl_want_write(struct dentry *dentry);
+ void ovl_drop_write(struct dentry *dentry);
+diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
+index f5678a3f8350..2050c5084a82 100644
+--- a/fs/overlayfs/util.c
++++ b/fs/overlayfs/util.c
+@@ -537,9 +537,9 @@ void ovl_copy_up_end(struct dentry *dentry)
+
+ bool ovl_check_origin_xattr(struct dentry *dentry)
+ {
+- int res;
++ ssize_t res;
+
+- res = vfs_getxattr(dentry, OVL_XATTR_ORIGIN, NULL, 0);
++ res = ovl_do_vfs_getxattr(dentry, OVL_XATTR_ORIGIN, NULL, 0);
+
+ /* Zero size value means "copied up but origin unknown" */
+ if (res >= 0)
+@@ -550,13 +550,13 @@ bool ovl_check_origin_xattr(struct dentry *dentry)
+
+ bool ovl_check_dir_xattr(struct dentry *dentry, const char *name)
+ {
+- int res;
++ ssize_t res;
+ char val;
+
+ if (!d_is_dir(dentry))
+ return false;
+
+- res = vfs_getxattr(dentry, name, &val, 1);
++ res = ovl_do_vfs_getxattr(dentry, name, &val, 1);
+ if (res == 1 && val == 'y')
+ return true;
+
+@@ -837,13 +837,13 @@ int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir)
+ /* err < 0, 0 if no metacopy xattr, 1 if metacopy xattr found */
+ int ovl_check_metacopy_xattr(struct dentry *dentry)
+ {
+- int res;
++ ssize_t res;
+
+ /* Only regular files can have metacopy xattr */
+ if (!S_ISREG(d_inode(dentry)->i_mode))
+ return 0;
+
+- res = vfs_getxattr(dentry, OVL_XATTR_METACOPY, NULL, 0);
++ res = ovl_do_vfs_getxattr(dentry, OVL_XATTR_METACOPY, NULL, 0);
+ if (res < 0) {
+ if (res == -ENODATA || res == -EOPNOTSUPP)
+ return 0;
+@@ -852,7 +852,7 @@ int ovl_check_metacopy_xattr(struct dentry *dentry)
+
+ return 1;
+ out:
+- pr_warn_ratelimited("overlayfs: failed to get metacopy (%i)\n", res);
++ pr_warn_ratelimited("overlayfs: failed to get metacopy (%zi)\n", res);
+ return res;
+ }
+
+@@ -878,7 +878,7 @@ ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value,
+ ssize_t res;
+ char *buf = NULL;
+
+- res = vfs_getxattr(dentry, name, NULL, 0);
++ res = ovl_do_vfs_getxattr(dentry, name, NULL, 0);
+ if (res < 0) {
+ if (res == -ENODATA || res == -EOPNOTSUPP)
+ return -ENODATA;
+@@ -890,7 +890,7 @@ ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value,
+ if (!buf)
+ return -ENOMEM;
+
+- res = vfs_getxattr(dentry, name, buf, res);
++ res = ovl_do_vfs_getxattr(dentry, name, buf, res);
+ if (res < 0)
+ goto fail;
+ }
diff --git a/android-mainline/FROMLIST-overlayfs-override_creds-off-option-bypass-creator_cred.patch b/android-mainline/FROMLIST-overlayfs-override_creds-off-option-bypass-creator_cred.patch
new file mode 100644
index 0000000..8c0fe2f
--- /dev/null
+++ b/android-mainline/FROMLIST-overlayfs-override_creds-off-option-bypass-creator_cred.patch
@@ -0,0 +1,557 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Mark Salyzyn <salyzyn@android.com>
+Date: Thu, 14 Jun 2018 11:15:22 -0700
+Subject: FROMLIST: overlayfs: override_creds=off option bypass creator_cred
+
+By default, all access to the upper, lower and work directories is the
+recorded mounter's MAC and DAC credentials. The incoming accesses are
+checked against the caller's credentials.
+
+If the principles of least privilege are applied, the mounter's
+credentials might not overlap the credentials of the caller's when
+accessing the overlayfs filesystem. For example, a file that a lower
+DAC privileged caller can execute, is MAC denied to the generally
+higher DAC privileged mounter, to prevent an attack vector.
+
+We add the option to turn off override_creds in the mount options; all
+subsequent operations after mount on the filesystem will be only the
+caller's credentials. The module boolean parameter and mount option
+override_creds is also added as a presence check for this "feature",
+existence of /sys/module/overlay/parameters/override_creds.
+
+It was not always this way. Circa 4.6 there was no recorded mounter's
+credentials, instead privileged access to upper or work directories
+were temporarily increased to perform the operations. The MAC
+(selinux) policies were caller's in all cases. override_creds=off
+partially returns us to this older access model minus the insecure
+temporary credential increases. This is to permit use in a system
+with non-overlapping security models for each executable including
+the agent that mounts the overlayfs filesystem. In Android
+this is the case since init, which performs the mount operations,
+has a minimal MAC set of privileges to reduce any attack surface,
+and services that use the content have a different set of MAC
+privileges (eg: read, for vendor labelled configuration, execute for
+vendor libraries and modules). The caveats are not a problem in
+the Android usage model, however they should be fixed for
+completeness and for general use in time.
+
+Signed-off-by: Mark Salyzyn <salyzyn@android.com>
+Cc: Miklos Szeredi <miklos@szeredi.hu>
+Cc: Jonathan Corbet <corbet@lwn.net>
+Cc: Vivek Goyal <vgoyal@redhat.com>
+Cc: Eric W. Biederman <ebiederm@xmission.com>
+Cc: Amir Goldstein <amir73il@gmail.com>
+Cc: Randy Dunlap <rdunlap@infradead.org>
+Cc: Stephen Smalley <sds@tycho.nsa.gov>
+Cc: linux-unionfs@vger.kernel.org
+Cc: linux-doc@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org
+Cc: kernel-team@android.com
+
+(cherry picked from https://lore.kernel.org/lkml/20191104215253.141818-5-salyzyn@android.com/)
+Signed-off-by: Mark Salyzyn <salyzyn@google.com>
+Bug: 133515582
+Bug: 136124883
+Bug: 129319403
+Change-Id: I6a82338fcb8b30b8e6f5d4c26b473730bdfd4488
+---
+ Documentation/filesystems/overlayfs.txt | 23 +++++++++++++++++++++++
+ fs/overlayfs/copy_up.c | 2 +-
+ fs/overlayfs/dir.c | 17 ++++++++++-------
+ fs/overlayfs/file.c | 20 ++++++++++----------
+ fs/overlayfs/inode.c | 18 +++++++++---------
+ fs/overlayfs/namei.c | 6 +++---
+ fs/overlayfs/overlayfs.h | 1 +
+ fs/overlayfs/ovl_entry.h | 1 +
+ fs/overlayfs/readdir.c | 4 ++--
+ fs/overlayfs/super.c | 22 +++++++++++++++++++++-
+ fs/overlayfs/util.c | 12 ++++++++++--
+ 11 files changed, 91 insertions(+), 35 deletions(-)
+
+diff --git a/Documentation/filesystems/overlayfs.txt b/Documentation/filesystems/overlayfs.txt
+index 845d689e0fd7..c7ab389571e5 100644
+--- a/Documentation/filesystems/overlayfs.txt
++++ b/Documentation/filesystems/overlayfs.txt
+@@ -102,6 +102,29 @@ Only the lists of names from directories are merged. Other content
+ such as metadata and extended attributes are reported for the upper
+ directory only. These attributes of the lower directory are hidden.
+
++credentials
++-----------
++
++By default, all access to the upper, lower and work directories is the
++recorded mounter's MAC and DAC credentials. The incoming accesses are
++checked against the caller's credentials.
++
++In the case where caller MAC or DAC credentials do not overlap, a
++use case available in older versions of the driver, the
++override_creds mount flag can be turned off and help when the use
++pattern has caller with legitimate credentials where the mounter
++does not. Several unintended side effects will occur though. The
++caller without certain key capabilities or lower privilege will not
++always be able to delete files or directories, create nodes, or
++search some restricted directories. The ability to search and read
++a directory entry is spotty as a result of the cache mechanism not
++retesting the credentials because of the assumption, a privileged
++caller can fill cache, then a lower privilege can read the directory
++cache. The uneven security model where cache, upperdir and workdir
++are opened at privilege, but accessed without creating a form of
++privilege escalation, should only be used with strict understanding
++of the side effects and of the security policies.
++
+ whiteouts and opaque directories
+ --------------------------------
+
+diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
+index b801c6353100..1c1b9415e533 100644
+--- a/fs/overlayfs/copy_up.c
++++ b/fs/overlayfs/copy_up.c
+@@ -886,7 +886,7 @@ int ovl_copy_up_flags(struct dentry *dentry, int flags)
+ dput(parent);
+ dput(next);
+ }
+- revert_creds(old_cred);
++ ovl_revert_creds(dentry->d_sb, old_cred);
+
+ return err;
+ }
+diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
+index 702aa63f6774..f4e6e6b6629a 100644
+--- a/fs/overlayfs/dir.c
++++ b/fs/overlayfs/dir.c
+@@ -536,7 +536,7 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
+ struct ovl_cattr *attr, bool origin)
+ {
+ int err;
+- const struct cred *old_cred;
++ const struct cred *old_cred, *hold_cred = NULL;
+ struct cred *override_cred;
+ struct dentry *parent = dentry->d_parent;
+
+@@ -563,14 +563,15 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
+ override_cred->fsgid = inode->i_gid;
+ if (!attr->hardlink) {
+ err = security_dentry_create_files_as(dentry,
+- attr->mode, &dentry->d_name, old_cred,
++ attr->mode, &dentry->d_name,
++ old_cred ? old_cred : current_cred(),
+ override_cred);
+ if (err) {
+ put_cred(override_cred);
+ goto out_revert_creds;
+ }
+ }
+- put_cred(override_creds(override_cred));
++ hold_cred = override_creds(override_cred);
+ put_cred(override_cred);
+
+ if (!ovl_dentry_is_whiteout(dentry))
+@@ -579,7 +580,9 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
+ err = ovl_create_over_whiteout(dentry, inode, attr);
+ }
+ out_revert_creds:
+- revert_creds(old_cred);
++ ovl_revert_creds(dentry->d_sb, old_cred ?: hold_cred);
++ if (old_cred && hold_cred)
++ put_cred(hold_cred);
+ return err;
+ }
+
+@@ -655,7 +658,7 @@ static int ovl_set_link_redirect(struct dentry *dentry)
+
+ old_cred = ovl_override_creds(dentry->d_sb);
+ err = ovl_set_redirect(dentry, false);
+- revert_creds(old_cred);
++ ovl_revert_creds(dentry->d_sb, old_cred);
+
+ return err;
+ }
+@@ -851,7 +854,7 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
+ err = ovl_remove_upper(dentry, is_dir, &list);
+ else
+ err = ovl_remove_and_whiteout(dentry, &list);
+- revert_creds(old_cred);
++ ovl_revert_creds(dentry->d_sb, old_cred);
+ if (!err) {
+ if (is_dir)
+ clear_nlink(dentry->d_inode);
+@@ -1221,7 +1224,7 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
+ out_unlock:
+ unlock_rename(new_upperdir, old_upperdir);
+ out_revert_creds:
+- revert_creds(old_cred);
++ ovl_revert_creds(old->d_sb, old_cred);
+ if (update_nlink)
+ ovl_nlink_end(new);
+ out_drop_write:
+diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c
+index e235a635d9ec..d94d6ec785a7 100644
+--- a/fs/overlayfs/file.c
++++ b/fs/overlayfs/file.c
+@@ -32,7 +32,7 @@ static struct file *ovl_open_realfile(const struct file *file,
+ old_cred = ovl_override_creds(inode->i_sb);
+ realfile = open_with_fake_path(&file->f_path, flags, realinode,
+ current_cred());
+- revert_creds(old_cred);
++ ovl_revert_creds(inode->i_sb, old_cred);
+
+ pr_debug("open(%p[%pD2/%c], 0%o) -> (%p, 0%o)\n",
+ file, file, ovl_whatisit(inode, realinode), file->f_flags,
+@@ -176,7 +176,7 @@ static loff_t ovl_llseek(struct file *file, loff_t offset, int whence)
+
+ old_cred = ovl_override_creds(inode->i_sb);
+ ret = vfs_llseek(real.file, offset, whence);
+- revert_creds(old_cred);
++ ovl_revert_creds(inode->i_sb, old_cred);
+
+ file->f_pos = real.file->f_pos;
+ inode_unlock(inode);
+@@ -242,7 +242,7 @@ static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+ old_cred = ovl_override_creds(file_inode(file)->i_sb);
+ ret = vfs_iter_read(real.file, iter, &iocb->ki_pos,
+ ovl_iocb_to_rwf(iocb));
+- revert_creds(old_cred);
++ ovl_revert_creds(file_inode(file)->i_sb, old_cred);
+
+ ovl_file_accessed(file);
+
+@@ -278,7 +278,7 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter)
+ ret = vfs_iter_write(real.file, iter, &iocb->ki_pos,
+ ovl_iocb_to_rwf(iocb));
+ file_end_write(real.file);
+- revert_creds(old_cred);
++ ovl_revert_creds(file_inode(file)->i_sb, old_cred);
+
+ /* Update size */
+ ovl_copyattr(ovl_inode_real(inode), inode);
+@@ -305,7 +305,7 @@ static int ovl_fsync(struct file *file, loff_t start, loff_t end, int datasync)
+ if (file_inode(real.file) == ovl_inode_upper(file_inode(file))) {
+ old_cred = ovl_override_creds(file_inode(file)->i_sb);
+ ret = vfs_fsync_range(real.file, start, end, datasync);
+- revert_creds(old_cred);
++ ovl_revert_creds(file_inode(file)->i_sb, old_cred);
+ }
+
+ fdput(real);
+@@ -329,7 +329,7 @@ static int ovl_mmap(struct file *file, struct vm_area_struct *vma)
+
+ old_cred = ovl_override_creds(file_inode(file)->i_sb);
+ ret = call_mmap(vma->vm_file, vma);
+- revert_creds(old_cred);
++ ovl_revert_creds(file_inode(file)->i_sb, old_cred);
+
+ if (ret) {
+ /* Drop reference count from new vm_file value */
+@@ -357,7 +357,7 @@ static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len
+
+ old_cred = ovl_override_creds(file_inode(file)->i_sb);
+ ret = vfs_fallocate(real.file, mode, offset, len);
+- revert_creds(old_cred);
++ ovl_revert_creds(file_inode(file)->i_sb, old_cred);
+
+ /* Update size */
+ ovl_copyattr(ovl_inode_real(inode), inode);
+@@ -379,7 +379,7 @@ static int ovl_fadvise(struct file *file, loff_t offset, loff_t len, int advice)
+
+ old_cred = ovl_override_creds(file_inode(file)->i_sb);
+ ret = vfs_fadvise(real.file, offset, len, advice);
+- revert_creds(old_cred);
++ ovl_revert_creds(file_inode(file)->i_sb, old_cred);
+
+ fdput(real);
+
+@@ -399,7 +399,7 @@ static long ovl_real_ioctl(struct file *file, unsigned int cmd,
+
+ old_cred = ovl_override_creds(file_inode(file)->i_sb);
+ ret = vfs_ioctl(real.file, cmd, arg);
+- revert_creds(old_cred);
++ ovl_revert_creds(file_inode(file)->i_sb, old_cred);
+
+ fdput(real);
+
+@@ -589,7 +589,7 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in,
+ flags);
+ break;
+ }
+- revert_creds(old_cred);
++ ovl_revert_creds(file_inode(file_out)->i_sb, old_cred);
+
+ /* Update size */
+ ovl_copyattr(ovl_inode_real(inode_out), inode_out);
+diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
+index c057e51057f7..3f2474fe8574 100644
+--- a/fs/overlayfs/inode.c
++++ b/fs/overlayfs/inode.c
+@@ -61,7 +61,7 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
+ inode_lock(upperdentry->d_inode);
+ old_cred = ovl_override_creds(dentry->d_sb);
+ err = notify_change(upperdentry, attr, NULL);
+- revert_creds(old_cred);
++ ovl_revert_creds(dentry->d_sb, old_cred);
+ if (!err)
+ ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
+ inode_unlock(upperdentry->d_inode);
+@@ -257,7 +257,7 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
+ stat->nlink = dentry->d_inode->i_nlink;
+
+ out:
+- revert_creds(old_cred);
++ ovl_revert_creds(dentry->d_sb, old_cred);
+
+ return err;
+ }
+@@ -291,7 +291,7 @@ int ovl_permission(struct inode *inode, int mask)
+ mask |= MAY_READ;
+ }
+ err = inode_permission(realinode, mask);
+- revert_creds(old_cred);
++ ovl_revert_creds(inode->i_sb, old_cred);
+
+ return err;
+ }
+@@ -308,7 +308,7 @@ static const char *ovl_get_link(struct dentry *dentry,
+
+ old_cred = ovl_override_creds(dentry->d_sb);
+ p = vfs_get_link(ovl_dentry_real(dentry), done);
+- revert_creds(old_cred);
++ ovl_revert_creds(dentry->d_sb, old_cred);
+ return p;
+ }
+
+@@ -351,7 +351,7 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name,
+ WARN_ON(flags != XATTR_REPLACE);
+ err = vfs_removexattr(realdentry, name);
+ }
+- revert_creds(old_cred);
++ ovl_revert_creds(dentry->d_sb, old_cred);
+
+ /* copy c/mtime */
+ ovl_copyattr(d_inode(realdentry), inode);
+@@ -373,7 +373,7 @@ int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
+ old_cred = ovl_override_creds(dentry->d_sb);
+ res = __vfs_getxattr(realdentry, d_inode(realdentry), name,
+ value, size, flags);
+- revert_creds(old_cred);
++ ovl_revert_creds(dentry->d_sb, old_cred);
+ return res;
+ }
+
+@@ -398,7 +398,7 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
+
+ old_cred = ovl_override_creds(dentry->d_sb);
+ res = vfs_listxattr(realdentry, list, size);
+- revert_creds(old_cred);
++ ovl_revert_creds(dentry->d_sb, old_cred);
+ if (res <= 0 || size == 0)
+ return res;
+
+@@ -433,7 +433,7 @@ struct posix_acl *ovl_get_acl(struct inode *inode, int type)
+
+ old_cred = ovl_override_creds(inode->i_sb);
+ acl = get_acl(realinode, type);
+- revert_creds(old_cred);
++ ovl_revert_creds(inode->i_sb, old_cred);
+
+ return acl;
+ }
+@@ -471,7 +471,7 @@ static int ovl_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ filemap_write_and_wait(realinode->i_mapping);
+
+ err = realinode->i_op->fiemap(realinode, fieinfo, start, len);
+- revert_creds(old_cred);
++ ovl_revert_creds(inode->i_sb, old_cred);
+
+ return err;
+ }
+diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
+index f5aba0a0767b..e9f989a2d57b 100644
+--- a/fs/overlayfs/namei.c
++++ b/fs/overlayfs/namei.c
+@@ -1076,7 +1076,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
+ goto out_free_oe;
+ }
+
+- revert_creds(old_cred);
++ ovl_revert_creds(dentry->d_sb, old_cred);
+ if (origin_path) {
+ dput(origin_path->dentry);
+ kfree(origin_path);
+@@ -1103,7 +1103,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
+ kfree(upperredirect);
+ out:
+ kfree(d.redirect);
+- revert_creds(old_cred);
++ ovl_revert_creds(dentry->d_sb, old_cred);
+ return ERR_PTR(err);
+ }
+
+@@ -1157,7 +1157,7 @@ bool ovl_lower_positive(struct dentry *dentry)
+ dput(this);
+ }
+ }
+- revert_creds(old_cred);
++ ovl_revert_creds(dentry->d_sb, old_cred);
+
+ return positive;
+ }
+diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
+index 55b872c28bf9..ab9802242857 100644
+--- a/fs/overlayfs/overlayfs.h
++++ b/fs/overlayfs/overlayfs.h
+@@ -213,6 +213,7 @@ int ovl_want_write(struct dentry *dentry);
+ void ovl_drop_write(struct dentry *dentry);
+ struct dentry *ovl_workdir(struct dentry *dentry);
+ const struct cred *ovl_override_creds(struct super_block *sb);
++void ovl_revert_creds(struct super_block *sb, const struct cred *oldcred);
+ struct super_block *ovl_same_sb(struct super_block *sb);
+ int ovl_can_decode_fh(struct super_block *sb);
+ struct dentry *ovl_indexdir(struct super_block *sb);
+diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
+index a8279280e88d..e847d7564999 100644
+--- a/fs/overlayfs/ovl_entry.h
++++ b/fs/overlayfs/ovl_entry.h
+@@ -17,6 +17,7 @@ struct ovl_config {
+ bool nfs_export;
+ int xino;
+ bool metacopy;
++ bool override_creds;
+ };
+
+ struct ovl_sb {
+diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
+index 47a91c9733a5..874a1b3ff99a 100644
+--- a/fs/overlayfs/readdir.c
++++ b/fs/overlayfs/readdir.c
+@@ -286,7 +286,7 @@ static int ovl_check_whiteouts(struct dentry *dir, struct ovl_readdir_data *rdd)
+ }
+ inode_unlock(dir->d_inode);
+ }
+- revert_creds(old_cred);
++ ovl_revert_creds(rdd->dentry->d_sb, old_cred);
+
+ return err;
+ }
+@@ -918,7 +918,7 @@ int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list)
+
+ old_cred = ovl_override_creds(dentry->d_sb);
+ err = ovl_dir_read_merged(dentry, list, &root);
+- revert_creds(old_cred);
++ ovl_revert_creds(dentry->d_sb, old_cred);
+ if (err)
+ return err;
+
+diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
+index c91e7b604631..1e70914f2bb4 100644
+--- a/fs/overlayfs/super.c
++++ b/fs/overlayfs/super.c
+@@ -53,6 +53,11 @@ module_param_named(xino_auto, ovl_xino_auto_def, bool, 0644);
+ MODULE_PARM_DESC(xino_auto,
+ "Auto enable xino feature");
+
++static bool __read_mostly ovl_override_creds_def = true;
++module_param_named(override_creds, ovl_override_creds_def, bool, 0644);
++MODULE_PARM_DESC(ovl_override_creds_def,
++ "Use mounter's credentials for accesses");
++
+ static void ovl_entry_stack_free(struct ovl_entry *oe)
+ {
+ unsigned int i;
+@@ -363,6 +368,9 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
+ if (ofs->config.metacopy != ovl_metacopy_def)
+ seq_printf(m, ",metacopy=%s",
+ ofs->config.metacopy ? "on" : "off");
++ if (ofs->config.override_creds != ovl_override_creds_def)
++ seq_show_option(m, "override_creds",
++ ofs->config.override_creds ? "on" : "off");
+ return 0;
+ }
+
+@@ -403,6 +411,8 @@ enum {
+ OPT_XINO_AUTO,
+ OPT_METACOPY_ON,
+ OPT_METACOPY_OFF,
++ OPT_OVERRIDE_CREDS_ON,
++ OPT_OVERRIDE_CREDS_OFF,
+ OPT_ERR,
+ };
+
+@@ -421,6 +431,8 @@ static const match_table_t ovl_tokens = {
+ {OPT_XINO_AUTO, "xino=auto"},
+ {OPT_METACOPY_ON, "metacopy=on"},
+ {OPT_METACOPY_OFF, "metacopy=off"},
++ {OPT_OVERRIDE_CREDS_ON, "override_creds=on"},
++ {OPT_OVERRIDE_CREDS_OFF, "override_creds=off"},
+ {OPT_ERR, NULL}
+ };
+
+@@ -479,6 +491,7 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
+ config->redirect_mode = kstrdup(ovl_redirect_mode_def(), GFP_KERNEL);
+ if (!config->redirect_mode)
+ return -ENOMEM;
++ config->override_creds = ovl_override_creds_def;
+
+ while ((p = ovl_next_opt(&opt)) != NULL) {
+ int token;
+@@ -559,6 +572,14 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
+ config->metacopy = false;
+ break;
+
++ case OPT_OVERRIDE_CREDS_ON:
++ config->override_creds = true;
++ break;
++
++ case OPT_OVERRIDE_CREDS_OFF:
++ config->override_creds = false;
++ break;
++
+ default:
+ pr_err("overlayfs: unrecognized mount option \"%s\" or missing value\n", p);
+ return -EINVAL;
+@@ -1695,7 +1716,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
+ ovl_dentry_lower(root_dentry), NULL);
+
+ sb->s_root = root_dentry;
+-
+ return 0;
+
+ out_free_oe:
+diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
+index 2050c5084a82..e1fd97fe37cc 100644
+--- a/fs/overlayfs/util.c
++++ b/fs/overlayfs/util.c
+@@ -37,9 +37,17 @@ const struct cred *ovl_override_creds(struct super_block *sb)
+ {
+ struct ovl_fs *ofs = sb->s_fs_info;
+
++ if (!ofs->config.override_creds)
++ return NULL;
+ return override_creds(ofs->creator_cred);
+ }
+
++void ovl_revert_creds(struct super_block *sb, const struct cred *old_cred)
++{
++ if (old_cred)
++ revert_creds(old_cred);
++}
++
+ struct super_block *ovl_same_sb(struct super_block *sb)
+ {
+ struct ovl_fs *ofs = sb->s_fs_info;
+@@ -791,7 +799,7 @@ int ovl_nlink_start(struct dentry *dentry)
+ * value relative to the upper inode nlink in an upper inode xattr.
+ */
+ err = ovl_set_nlink_upper(dentry);
+- revert_creds(old_cred);
++ ovl_revert_creds(dentry->d_sb, old_cred);
+
+ out:
+ if (err)
+@@ -809,7 +817,7 @@ void ovl_nlink_end(struct dentry *dentry)
+
+ old_cred = ovl_override_creds(dentry->d_sb);
+ ovl_cleanup_index(dentry);
+- revert_creds(old_cred);
++ ovl_revert_creds(dentry->d_sb, old_cred);
+ }
+
+ ovl_inode_unlock(inode);
diff --git a/android-mainline/series b/android-mainline/series
index bf735a3..47a97f4 100644
--- a/android-mainline/series
+++ b/android-mainline/series
@@ -2,7 +2,7 @@
# android-mainline patches
#
# Applies onto mainline a99d8080aaf3 Linux v5.4-rc6
-# Matches android-mainline c5634733fa58 ("FROMGIT: of: property: Skip adding device links to suppliers that aren't devices")
+# Matches android-mainline 0ee40e0e58eb ("FROMLIST: overlayfs: override_creds=off option bypass creator_cred")
#
ANDROID-Kbuild-LLVMLinux-allow-overriding-clang-target-triple.patch
ANDROID-net-xfrm-make-PF_KEY-SHA256-use-RFC-compliant-truncation.patch
@@ -230,3 +230,8 @@
FROMGIT-scsi-core-allow-auto-suspend-override-by-low-level-driver.patch
FROMGIT-scsi-ufs-override-auto-suspend-tunables-for-ufs.patch
FROMGIT-of-property-Skip-adding-device-links-to-suppliers-that-aren-t-devices.patch
+FROMLIST-afs-xattr-use-scnprintf.patch
+FROMLIST-Add-flags-option-to-get-xattr-method-paired-to-__vfs_getxattr.patch
+FROMLIST-overlayfs-handle-XATTR_NOSECURITY-flag-for-get-xattr-method.patch
+FROMLIST-overlayfs-internal-getxattr-operations-without-sepolicy-checking.patch
+FROMLIST-overlayfs-override_creds-off-option-bypass-creator_cred.patch