| From f0ab9bac26c34a547e5aff7bbf825cbbc77cb0f8 Mon Sep 17 00:00:00 2001 |
| From: Mark Salyzyn <salyzyn@google.com> |
| Date: Mon, 4 Nov 2019 08:57:10 -0800 |
| Subject: [PATCH] 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 |
| |
| Conflicts: |
| security/integrity/evm/evm_main.c |
| [rebase510(groeck): Context conflicts] |
| Signed-off-by: Guenter Roeck <groeck@chromium.org> |
| |
| [rebase515(groeck): |
| Squashed: |
| FROMLIST: Add flags option to get xattr method paired to __vfs_getxattr |
| FIXUP: FROMLIST: Add flags option to get xattr method paired to __vfs_getxattr |
| FIXUP: ima: Define new template fields xattrnames, xattrlengths and xattrvalues |
| ] |
| |
| Signed-off-by: Guenter Roeck <groeck@google.com> |
| |
| [rebase61(tzungbi): |
| Squashed: |
| FIXUP: NFSv4.1: Enable access to the NFSv4.1 'dacl' and 'sacl' attributes |
| ] |
| Signed-off-by: Tzung-Bi Shih <tzungbi@chromium.org> |
| --- |
| Documentation/filesystems/locking.rst | 2 +- |
| fs/9p/xattr.c | 3 +- |
| fs/afs/xattr.c | 10 +++---- |
| fs/btrfs/xattr.c | 3 +- |
| fs/ceph/xattr.c | 3 +- |
| fs/ecryptfs/inode.c | 6 ++-- |
| fs/ecryptfs/mmap.c | 5 ++-- |
| 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_hurd.c | 3 +- |
| 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 | 2 +- |
| 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 | 15 ++++++---- |
| fs/ntfs3/xattr.c | 2 +- |
| fs/ocfs2/xattr.c | 9 ++++-- |
| fs/orangefs/xattr.c | 3 +- |
| fs/reiserfs/xattr_security.c | 3 +- |
| fs/reiserfs/xattr_trusted.c | 3 +- |
| fs/reiserfs/xattr_user.c | 3 +- |
| fs/smb/client/xattr.c | 2 +- |
| fs/squashfs/xattr.c | 2 +- |
| fs/ubifs/xattr.c | 3 +- |
| fs/xattr.c | 43 ++++++++++++++------------- |
| fs/xfs/xfs_xattr.c | 3 +- |
| include/linux/xattr.h | 5 ++-- |
| include/uapi/linux/xattr.h | 7 +++-- |
| mm/shmem.c | 3 +- |
| net/socket.c | 3 +- |
| security/commoncap.c | 8 +++-- |
| security/integrity/evm/evm_main.c | 13 ++++---- |
| security/selinux/hooks.c | 16 ++++++---- |
| security/smack/smack_lsm.c | 7 +++-- |
| 48 files changed, 147 insertions(+), 96 deletions(-) |
| |
| diff --git a/Documentation/filesystems/locking.rst b/Documentation/filesystems/locking.rst |
| index 7be2900806c85330b9589f32e4a887b0b6857fde..b99fd5c2bab06999a9593b9075e9a5ad25c5c281 100644 |
| --- a/Documentation/filesystems/locking.rst |
| +++ b/Documentation/filesystems/locking.rst |
| @@ -135,7 +135,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 mnt_idmap *idmap, |
| struct dentry *dentry, struct inode *inode, const char *name, |
| diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c |
| index e00cf8109b3f31cb77ffb900b56ca67df480a791..a44d4038784fbec5083410b509b1d19923f79250 100644 |
| --- a/fs/9p/xattr.c |
| +++ b/fs/9p/xattr.c |
| @@ -144,7 +144,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 9048d8ccc715f5efe001ad99ceca5a4fdb32cee6..048e9478eb92e9c54ea44ffe8cab607f655fdafe 100644 |
| --- a/fs/afs/xattr.c |
| +++ b/fs/afs/xattr.c |
| @@ -36,7 +36,7 @@ static const struct afs_operation_ops afs_fetch_acl_operation = { |
| 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_operation *op; |
| struct afs_vnode *vnode = AFS_FS_I(inode); |
| @@ -138,7 +138,7 @@ static const struct afs_operation_ops yfs_fetch_opaque_acl_operation = { |
| 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_operation *op; |
| struct afs_vnode *vnode = AFS_FS_I(inode); |
| @@ -268,7 +268,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; |
| @@ -295,7 +295,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]; |
| @@ -333,7 +333,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 96828a13dd43d9ae0beb1562072c93657763c6d4..b08e3f4cb53d992769fd11b0b8ed1e0f93547506 100644 |
| --- a/fs/btrfs/xattr.c |
| +++ b/fs/btrfs/xattr.c |
| @@ -363,7 +363,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 0deae4a0f5f169b4738019487ca4a25624d3f014..c4bf9e3c07526f33277f5af931011eb330e1267e 100644 |
| --- a/fs/ceph/xattr.c |
| +++ b/fs/ceph/xattr.c |
| @@ -1310,7 +1310,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/ecryptfs/inode.c b/fs/ecryptfs/inode.c |
| index 992d9c7e64ae66f2cb094d949653e693a325c4b6..2cfa32738037c6f55d3cdcddb12a4b36d7b6409d 100644 |
| --- a/fs/ecryptfs/inode.c |
| +++ b/fs/ecryptfs/inode.c |
| @@ -1053,7 +1053,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(&init_user_ns, lower_dentry, lower_inode, name, |
| + value, size, XATTR_NOSECURITY); |
| inode_unlock(lower_inode); |
| out: |
| return rc; |
| @@ -1185,7 +1186,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 e2483acc436663bb269b01db815cabfc38a35060..ee4a06fac17df33d239927ba4bbcf7486b209866 100644 |
| --- a/fs/ecryptfs/mmap.c |
| +++ b/fs/ecryptfs/mmap.c |
| @@ -422,8 +422,9 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode) |
| goto out; |
| } |
| inode_lock(lower_inode); |
| - size = __vfs_getxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME, |
| - xattr_virt, PAGE_SIZE); |
| + size = __vfs_getxattr(&init_user_ns, lower_dentry, lower_inode, |
| + ECRYPTFS_XATTR_NAME, 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 09d341675e890e6bc9a975cc0024bf5429b78ca6..464941caacfa6a12bdab5b2f7c3568be6ee8acf9 100644 |
| --- a/fs/erofs/xattr.c |
| +++ b/fs/erofs/xattr.c |
| @@ -137,7 +137,8 @@ static bool erofs_xattr_trusted_list(struct dentry *dentry) |
| |
| 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) |
| { |
| if (handler->flags == EROFS_XATTR_INDEX_USER && |
| !test_opt(&EROFS_I_SB(inode)->opt, XATTR_USER)) |
| diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c |
| index db47b8ab153e7d3bf6e90cd29c2e775d9910d261..9b01627af5abaa14c6fb6581b91679e67597ff11 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 995f931228ce8b2c38c75e80e7da51f8007cac74..3b2fd0e0cef2c31bc7bc0d2f93c42cfd2bf10456 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 dd15072310818b678959c974df5a6a504ea43af3..d581979fd45da7bb66ad726cd703bf643fd0dbf7 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_hurd.c b/fs/ext4/xattr_hurd.c |
| index 8a5842e4cd95c6a06f346f7c74767199be3316b3..7966bb36aae3abf899772acbb2dc8d9ad0f22dbc 100644 |
| --- a/fs/ext4/xattr_hurd.c |
| +++ b/fs/ext4/xattr_hurd.c |
| @@ -21,7 +21,8 @@ ext4_xattr_hurd_list(struct dentry *dentry) |
| static int |
| ext4_xattr_hurd_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 776cf11d24ca10e016184304a15979d2c2898b94..b145a899d4b2a704fda57296f0915e4990a2ea76 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 9811eb0ab276232cf2ec249f333184fb773c23f1..825075b029fe477356c0533a726734c290905a20 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 4b70bf4e76263383c437994b37f49bd48766ce9d..d12c3898b2818b1ea01c7bd77ba189f50f340494 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 a657284faee30ad381c85f8f032f71709cdb1265..8b896d73aeaf5956a0140ca65eee4fabb3db96f7 100644 |
| --- a/fs/f2fs/xattr.c |
| +++ b/fs/f2fs/xattr.c |
| @@ -45,7 +45,7 @@ static void xattr_free(struct f2fs_sb_info *sbi, void *xattr_addr, |
| |
| 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); |
| |
| @@ -101,7 +101,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 49c01559580f4eb7427ac372f122497af308dcdd..d654de6dbefe726e1dd11da4a5832624fafff782 100644 |
| --- a/fs/fuse/xattr.c |
| +++ b/fs/fuse/xattr.c |
| @@ -180,7 +180,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) |
| { |
| if (fuse_is_bad(inode)) |
| return -EIO; |
| diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c |
| index 4fea70c0fe3d17f1059e216888ecd470452cac68..348ee299e902ff6f06bb152035179d84108cf912 100644 |
| --- a/fs/gfs2/xattr.c |
| +++ b/fs/gfs2/xattr.c |
| @@ -602,7 +602,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 6341bb248247751776a1876630fbb2db15959a0c..428ce5be8ba92bdecb8360af6d3f6081490a4356 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 58021e73c00bf7816d7b02f4a598bde2c7b0e723..12ac339aba46d59e28e47c4065bbf6578ec682a0 100644 |
| --- a/fs/hfsplus/xattr.c |
| +++ b/fs/hfsplus/xattr.c |
| @@ -838,7 +838,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 90f68ec119cddd86f8b0a7cf4eb9ad3c5188ac58..7c9706f5f481bd3e90cab013efe1b6cf4c993295 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 fdbaebc1c49a01896716c57b5599e9a01acc009a..481f308ddd63c6b4ee8c0aea2e632dfc7ac4de68 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 6464b6c3d58d69182dcbd169f73ff911bf4f07c9..4d1366308d40663265fc5c5d90730e2bc50fef20 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 437f3a2c1b5441759d191fc9002cee82bf1c6287..c8d070e426e02af032dd94a893859fc6a3bc5702 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 b7c5da2d89bdf19259d12895429c3c95791913a3..627970116817cac54aeae2efbaafe299e4c452c8 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 f64edce4927b2ee7885f751754aa542bce878cbc..33ac4b94cfed4481660377aa6581c9dd1b3df07f 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 8577ad494e056bc7c85cec768ed4ca123b07a85e..df4aa6ca2c966833f0e7605001431fada7594b5d 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); |
| @@ -943,7 +943,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 922719a343a77a21afc60c92e42d8e689010acb6..41b45929f17fa4ea22b36b66107ecc3d7c3d56aa 100644 |
| --- a/fs/kernfs/inode.c |
| +++ b/fs/kernfs/inode.c |
| @@ -320,7 +320,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 794343790ea8bbba5493f0374d5297c45f87dd4f..61f2088f25aa0cbedc181b76acb641c9edf7cf9b 100644 |
| --- a/fs/nfs/nfs4proc.c |
| +++ b/fs/nfs/nfs4proc.c |
| @@ -7710,7 +7710,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, NFS4ACL_ACL); |
| } |
| @@ -7734,7 +7735,8 @@ static int nfs4_xattr_set_nfs4_dacl(const struct xattr_handler *handler, |
| |
| static int nfs4_xattr_get_nfs4_dacl(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, NFS4ACL_DACL); |
| } |
| @@ -7757,7 +7759,8 @@ static int nfs4_xattr_set_nfs4_sacl(const struct xattr_handler *handler, |
| |
| static int nfs4_xattr_get_nfs4_sacl(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, NFS4ACL_SACL); |
| } |
| @@ -7785,7 +7788,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); |
| @@ -7863,7 +7867,8 @@ static int nfs4_xattr_set_nfs4_user(const struct xattr_handler *handler, |
| |
| static int nfs4_xattr_get_nfs4_user(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) |
| { |
| u32 mask; |
| ssize_t ret; |
| diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c |
| index 29fd391899e59dfde9b29e920f7303862b7167ff..ced43b2485b03aa6c5fc71b853c92993b3ea3e4c 100644 |
| --- a/fs/ntfs3/xattr.c |
| +++ b/fs/ntfs3/xattr.c |
| @@ -734,7 +734,7 @@ ssize_t ntfs_listxattr(struct dentry *dentry, char *buffer, size_t size) |
| |
| static int ntfs_getxattr(const struct xattr_handler *handler, struct dentry *de, |
| struct inode *inode, const char *name, void *buffer, |
| - size_t size) |
| + size_t size, int flags) |
| { |
| int err; |
| struct ntfs_inode *ni = ntfs_i(inode); |
| diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c |
| index 6510ad783c912c8408105a8c0a6a0e95ee6bd0b2..8733a5134f3a2ff82b690f1da1b3a1d7e2a7fb9f 100644 |
| --- a/fs/ocfs2/xattr.c |
| +++ b/fs/ocfs2/xattr.c |
| @@ -7236,7 +7236,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); |
| @@ -7331,7 +7332,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); |
| @@ -7358,7 +7360,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 68b62689a63e248f73881dffc7861e0ff1bc9335..b5e12244cec34232c45143eca0689784444aedf0 100644 |
| --- a/fs/orangefs/xattr.c |
| +++ b/fs/orangefs/xattr.c |
| @@ -542,7 +542,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/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c |
| index 078dd8cc312fc2000dbd30bf2b8091f4e55a3682..de8438cd5f95750ac4778db45d8236b126933950 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 0c0c74d8db0eda0788336ff02f4ceca91183fe22..6556210ff3ca52a80e0e019ddae9db3eac036119 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 88195181e1d7ee963e64fb8072b9a1593ba6bce1..1f24029fcaff606a46709f22556b5e079b09de3c 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/smb/client/xattr.c b/fs/smb/client/xattr.c |
| index 4ad5531686d81aa4e9395f58ceb04be13520b5a2..11f5de61fd45d1e60968b258125321cae6bc3f32 100644 |
| --- a/fs/smb/client/xattr.c |
| +++ b/fs/smb/client/xattr.c |
| @@ -257,7 +257,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/squashfs/xattr.c b/fs/squashfs/xattr.c |
| index e1e3f3dd5a06b9e06869381edfb9e633222b1286..d8d58c990652aacd44e65338f09347ddaed2c91a 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 406c82eab51386b6bbcb41c75802f9dff30e1b79..354404264324ca24cd7cfcc23bea930727f5b0c5 100644 |
| --- a/fs/ubifs/xattr.c |
| +++ b/fs/ubifs/xattr.c |
| @@ -689,7 +689,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 efd4736bc94b09ba4363dd8b691e09deabf4acef..10873ea88b658006f3cd445d9719e6373d155ad1 100644 |
| --- a/fs/xattr.c |
| +++ b/fs/xattr.c |
| @@ -391,7 +391,7 @@ vfs_getxattr_alloc(struct mnt_idmap *idmap, struct dentry *dentry, |
| 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; |
| |
| @@ -402,36 +402,24 @@ vfs_getxattr_alloc(struct mnt_idmap *idmap, struct dentry *dentry, |
| 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) |
| +__vfs_getxattr(struct mnt_idmap *idmap, struct dentry *dentry, |
| + struct inode *inode, const char *name, void *value, size_t size, |
| + int flags) |
| { |
| const struct xattr_handler *handler; |
| + int error; |
| |
| if (is_posix_acl_xattr(name)) |
| return -EOPNOTSUPP; |
| |
| - 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 mnt_idmap *idmap, 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(idmap, inode, name, MAY_READ); |
| if (error) |
| return error; |
| @@ -454,7 +442,20 @@ vfs_getxattr(struct mnt_idmap *idmap, struct dentry *dentry, |
| 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 mnt_idmap *idmap, struct dentry *dentry, |
| + const char *name, void *value, size_t size) |
| +{ |
| + return __vfs_getxattr(idmap, 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 43e5c219aaed568ffb5a711b4583b2cdf1723d9c..8f4dfda157194425b6a89e46736c5dec89cf4c33 100644 |
| --- a/fs/xfs/xfs_xattr.c |
| +++ b/fs/xfs/xfs_xattr.c |
| @@ -113,7 +113,8 @@ xfs_attr_change( |
| |
| 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) |
| { |
| struct xfs_da_args args = { |
| .dp = XFS_I(inode), |
| diff --git a/include/linux/xattr.h b/include/linux/xattr.h |
| index d20051865800800df5d24a0edd7a485b296ba9fa..f314722bc4774e29bf8c10fec2e148da492e3758 100644 |
| --- a/include/linux/xattr.h |
| +++ b/include/linux/xattr.h |
| @@ -40,7 +40,7 @@ struct xattr_handler { |
| bool (*list)(struct dentry *dentry); |
| int (*get)(const struct xattr_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 *, |
| struct mnt_idmap *idmap, struct dentry *dentry, |
| struct inode *inode, const char *name, const void *buffer, |
| @@ -71,7 +71,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 mnt_idmap *, struct dentry *, struct inode *, |
| + const char *, void *, size_t, int flags); |
| ssize_t vfs_getxattr(struct mnt_idmap *, struct dentry *, const char *, |
| void *, size_t); |
| ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size); |
| diff --git a/include/uapi/linux/xattr.h b/include/uapi/linux/xattr.h |
| index 9463db2dfa9d412dbf13051763416b7464876c0f..d22191a3cf09fa69dd071246ee77f29c8aa9b145 100644 |
| --- a/include/uapi/linux/xattr.h |
| +++ b/include/uapi/linux/xattr.h |
| @@ -18,8 +18,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 02e62fccc80d4973b6626988eed07ff2482980d1..8c1f7f05b750df0825a399d47007c20c796ae20a 100644 |
| --- a/mm/shmem.c |
| +++ b/mm/shmem.c |
| @@ -3645,7 +3645,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 c8b08b32f097ec5dfde66b42701be720ab05c826..a721dcf6cd5eb07fa7f30cc475bd357080504334 100644 |
| --- a/net/socket.c |
| +++ b/net/socket.c |
| @@ -369,7 +369,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 bc05211041979c120831742d25f2e6133435166c..7d85ee9d76d816f33a5c7c5a3ce98506ce0b46c3 100644 |
| --- a/security/commoncap.c |
| +++ b/security/commoncap.c |
| @@ -298,7 +298,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(&init_user_ns, dentry, inode, XATTR_NAME_CAPS, |
| + NULL, 0, XATTR_NOSECURITY); |
| return error > 0; |
| } |
| |
| @@ -651,8 +652,9 @@ int get_vfs_caps_from_disk(struct mnt_idmap *idmap, |
| return -ENODATA; |
| |
| fs_ns = inode->i_sb->s_user_ns; |
| - size = __vfs_getxattr((struct dentry *)dentry, inode, |
| - XATTR_NAME_CAPS, &data, XATTR_CAPS_SZ); |
| + size = __vfs_getxattr(&init_user_ns, (struct dentry *)dentry, inode, |
| + 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 ff9a939dad8e42d83bff26150fe9b283fdf53494..0d068c0591abcfbe264fed98ce15710284eb0249 100644 |
| --- a/security/integrity/evm/evm_main.c |
| +++ b/security/integrity/evm/evm_main.c |
| @@ -140,7 +140,9 @@ static int evm_find_protected_xattrs(struct dentry *dentry) |
| return -EOPNOTSUPP; |
| |
| list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) { |
| - error = __vfs_getxattr(dentry, inode, xattr->name, NULL, 0); |
| + error = __vfs_getxattr(&init_user_ns, dentry, inode, |
| + xattr->name, NULL, 0, |
| + XATTR_NOSECURITY); |
| if (error < 0) { |
| if (error == -ENODATA) |
| continue; |
| @@ -337,8 +339,9 @@ int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer, |
| int rc, size, total_size = 0; |
| |
| list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) { |
| - rc = __vfs_getxattr(dentry, d_backing_inode(dentry), |
| - xattr->name, NULL, 0); |
| + rc = __vfs_getxattr(&init_user_ns, dentry, |
| + d_backing_inode(dentry), |
| + xattr->name, NULL, 0, 0); |
| if (rc < 0 && rc == -ENODATA) |
| continue; |
| else if (rc < 0) |
| @@ -366,10 +369,10 @@ int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer, |
| case 'v': |
| size = rc; |
| if (buffer) { |
| - rc = __vfs_getxattr(dentry, |
| + rc = __vfs_getxattr(&init_user_ns, dentry, |
| d_backing_inode(dentry), xattr->name, |
| buffer + total_size, |
| - buffer_size - total_size); |
| + buffer_size - total_size, 0); |
| if (rc < 0) |
| return rc; |
| } |
| diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c |
| index 10350534de6d65b3a4103ae9babe42fac3682261..133ecf55478cbf38408de82972d06ec3a1025863 100644 |
| --- a/security/selinux/hooks.c |
| +++ b/security/selinux/hooks.c |
| @@ -514,7 +514,8 @@ static int sb_check_xattr_support(struct super_block *sb) |
| goto fallback; |
| } |
| |
| - rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0); |
| + rc = __vfs_getxattr(&init_user_ns, root, root_inode, |
| + XATTR_NAME_SELINUX, NULL, 0, XATTR_NOSECURITY); |
| if (rc < 0 && rc != -ENODATA) { |
| if (rc == -EOPNOTSUPP) { |
| pr_warn("SELinux: (dev %s, type %s) has no security xattr handler\n", |
| @@ -1356,12 +1357,16 @@ 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(&init_user_ns, 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(&init_user_ns, dentry, inode, |
| + XATTR_NAME_SELINUX, NULL, 0, |
| + XATTR_NOSECURITY); |
| if (rc < 0) |
| return rc; |
| |
| @@ -1371,8 +1376,9 @@ 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(&init_user_ns, dentry, inode, |
| + XATTR_NAME_SELINUX, context, len, |
| + XATTR_NOSECURITY); |
| } |
| if (rc < 0) { |
| kfree(context); |
| diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c |
| index 65130a791f5730c4f1e1eb6e442d0c31684c66ad..3b371cb0e105f89e13ad3bbe72dbe2c1824b8abf 100644 |
| --- a/security/smack/smack_lsm.c |
| +++ b/security/smack/smack_lsm.c |
| @@ -301,7 +301,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(&init_user_ns, dp, ip, name, buffer, SMK_LONGLABEL, |
| + XATTR_NOSECURITY); |
| if (rc < 0) |
| skp = ERR_PTR(rc); |
| else if (rc == 0) |
| @@ -3587,9 +3588,9 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) |
| * If there is a transmute attribute on the |
| * directory mark the inode. |
| */ |
| - rc = __vfs_getxattr(dp, inode, |
| + rc = __vfs_getxattr(&nop_mnt_idmap, 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; |
| -- |
| 2.34.1 |
| |