* [RFC] xfs: fix up non-directory creation in SGID directories when umask S_IXGRP
@ 2022-03-22 6:06 Yang Xu
2022-03-22 7:09 ` xuyang2018.jy
0 siblings, 1 reply; 2+ messages in thread
From: Yang Xu @ 2022-03-22 6:06 UTC (permalink / raw)
To: linux-xfs; +Cc: djwong, pvorel, Yang Xu
Petr reported a problem that S_ISGID bit was not clean when testing ltp case
create09[1] by using umask(077).
It fails because xfs will call posix_acl_create before xfs_init_new_node calls
inode_init_owner, so S_IXGRP mode will be clear when enable CONFIG_XFS_POSIXACL
and doesn't set acl or default acl on dir, then inode_init_owner will not clear
S_ISGID bit.
The calltrace as below:
will use inode_init_owner(struct user_namespace *mnt_userns, structinode *inode)
[ 296.760675] xfs_init_new_inode+0x10e/0x6c0
[ 296.760678] xfs_create+0x401/0x610
will use posix_acl_create(dir, &mode, &default_acl, &acl);
[ 296.760681] xfs_generic_create+0x123/0x2e0
[ 296.760684] ? _raw_spin_unlock+0x16/0x30
[ 296.760687] path_openat+0xfb8/0x1210
[ 296.760689] do_filp_open+0xb4/0x120
[ 296.760691] ? file_tty_write.isra.31+0x203/0x340
[ 296.760697] ? __check_object_size+0x150/0x170
[ 296.760699] do_sys_openat2+0x242/0x310
[ 296.760702] do_sys_open+0x4b/0x80
[ 296.760704] do_syscall_64+0x3a/0x80
Fix this is simple, we can call posix_acl_create after xfs_init_new_inode completed,
so inode_init_owner can clear S_ISGID bit correctly like ext4 or btrfs does.
But commit e6a688c33238 ("xfs: initialise attr fork on inode create") has created
attr fork in advance according to acl, so a better solution is that moving these
functions into xfs_init_new_inode.
[1]https://github.com/linux-test-project/ltp/blob/master/testcases/kernel/syscalls/creat/creat09.c
Reported-by: Petr Vorel <pvorel@suse.cz>
Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com>
---
fs/xfs/xfs_inode.c | 54 +++++++++++++++++++++++++++++++++++++--
fs/xfs/xfs_iops.c | 63 ++++------------------------------------------
2 files changed, 57 insertions(+), 60 deletions(-)
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 26227d26f274..8127b83b376c 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -4,6 +4,7 @@
* All Rights Reserved.
*/
#include <linux/iversion.h>
+#include <linux/posix_acl.h>
#include "xfs.h"
#include "xfs_fs.h"
@@ -36,6 +37,7 @@
#include "xfs_reflink.h"
#include "xfs_ag.h"
#include "xfs_log_priv.h"
+#include "xfs_acl.h"
struct kmem_cache *xfs_inode_cache;
@@ -781,6 +783,36 @@ xfs_inode_inherit_flags2(
}
}
+/*
+ * Check to see if we are likely to need an extended attribute to be added to
+ * the inode we are about to allocate. This allows the attribute fork to be
+ * created during the inode allocation, reducing the number of transactions we
+ * need to do in this fast path.
+ *
+ * The security checks are optimistic, but not guaranteed. The two LSMs that
+ * require xattrs to be added here (selinux and smack) are also the only two
+ * LSMs that add a sb->s_security structure to the superblock. Hence if security
+ * is enabled and sb->s_security is set, we have a pretty good idea that we are
+ * going to be asked to add a security xattr immediately after allocating the
+ * xfs inode and instantiating the VFS inode.
+ */
+static inline bool
+xfs_create_need_xattr(
+ struct inode *dir,
+ struct posix_acl *default_acl,
+ struct posix_acl *acl)
+{
+ if (acl)
+ return true;
+ if (default_acl)
+ return true;
+#if IS_ENABLED(CONFIG_SECURITY)
+ if (dir->i_sb->s_security)
+ return true;
+#endif
+ return false;
+}
+
/*
* Initialise a newly allocated inode and return the in-core inode to the
* caller locked exclusively.
@@ -805,7 +837,7 @@ xfs_init_new_inode(
int error;
struct timespec64 tv;
struct inode *inode;
-
+ struct posix_acl *default_acl, *acl;
/*
* Protect against obviously corrupt allocation btree records. Later
* xfs_iget checks will catch re-allocation of other active in-memory
@@ -893,6 +925,9 @@ xfs_init_new_inode(
ASSERT(0);
}
+ error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
+ if (error)
+ return error;
/*
* If we need to create attributes immediately after allocating the
* inode, initialise an empty attribute fork right now. We use the
@@ -902,7 +937,9 @@ xfs_init_new_inode(
* this saves us from needing to run a separate transaction to set the
* fork offset in the immediate future.
*/
- if (init_xattrs && xfs_has_attr(mp)) {
+ if (init_xattrs &&
+ xfs_create_need_xattr(dir, default_acl, acl) &&
+ xfs_has_attr(mp)) {
ip->i_forkoff = xfs_default_attroffset(ip) >> 3;
ip->i_afp = xfs_ifork_alloc(XFS_DINODE_FMT_EXTENTS, 0);
}
@@ -916,6 +953,19 @@ xfs_init_new_inode(
/* now that we have an i_mode we can setup the inode structure */
xfs_setup_inode(ip);
+#ifdef CONFIG_XFS_POSIX_ACL
+ if (default_acl) {
+ error = __xfs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
+ if (error)
+ posix_acl_release(default_acl);
+ }
+ if (acl) {
+ error = __xfs_set_acl(inode, acl, ACL_TYPE_ACCESS);
+ if (error)
+ posix_acl_release(acl);
+ }
+#endif
+
*ipp = ip;
return 0;
}
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index b34e8e4344a8..5f9fcb6e7cf8 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -127,37 +127,6 @@ xfs_cleanup_inode(
xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
}
-/*
- * Check to see if we are likely to need an extended attribute to be added to
- * the inode we are about to allocate. This allows the attribute fork to be
- * created during the inode allocation, reducing the number of transactions we
- * need to do in this fast path.
- *
- * The security checks are optimistic, but not guaranteed. The two LSMs that
- * require xattrs to be added here (selinux and smack) are also the only two
- * LSMs that add a sb->s_security structure to the superblock. Hence if security
- * is enabled and sb->s_security is set, we have a pretty good idea that we are
- * going to be asked to add a security xattr immediately after allocating the
- * xfs inode and instantiating the VFS inode.
- */
-static inline bool
-xfs_create_need_xattr(
- struct inode *dir,
- struct posix_acl *default_acl,
- struct posix_acl *acl)
-{
- if (acl)
- return true;
- if (default_acl)
- return true;
-#if IS_ENABLED(CONFIG_SECURITY)
- if (dir->i_sb->s_security)
- return true;
-#endif
- return false;
-}
-
-
STATIC int
xfs_generic_create(
struct user_namespace *mnt_userns,
@@ -169,7 +138,6 @@ xfs_generic_create(
{
struct inode *inode;
struct xfs_inode *ip = NULL;
- struct posix_acl *default_acl, *acl;
struct xfs_name name;
int error;
@@ -184,24 +152,19 @@ xfs_generic_create(
rdev = 0;
}
- error = posix_acl_create(dir, &mode, &default_acl, &acl);
- if (error)
- return error;
-
/* Verify mode is valid also for tmpfile case */
error = xfs_dentry_mode_to_name(&name, dentry, mode);
if (unlikely(error))
- goto out_free_acl;
+ return error;
if (!tmpfile) {
error = xfs_create(mnt_userns, XFS_I(dir), &name, mode, rdev,
- xfs_create_need_xattr(dir, default_acl, acl),
- &ip);
+ true, &ip);
} else {
error = xfs_create_tmpfile(mnt_userns, XFS_I(dir), mode, &ip);
}
if (unlikely(error))
- goto out_free_acl;
+ return error;
inode = VFS_I(ip);
@@ -209,19 +172,6 @@ xfs_generic_create(
if (unlikely(error))
goto out_cleanup_inode;
-#ifdef CONFIG_XFS_POSIX_ACL
- if (default_acl) {
- error = __xfs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
- if (error)
- goto out_cleanup_inode;
- }
- if (acl) {
- error = __xfs_set_acl(inode, acl, ACL_TYPE_ACCESS);
- if (error)
- goto out_cleanup_inode;
- }
-#endif
-
xfs_setup_iops(ip);
if (tmpfile) {
@@ -240,17 +190,14 @@ xfs_generic_create(
xfs_finish_inode_setup(ip);
- out_free_acl:
- posix_acl_release(default_acl);
- posix_acl_release(acl);
- return error;
+ return 0;
out_cleanup_inode:
xfs_finish_inode_setup(ip);
if (!tmpfile)
xfs_cleanup_inode(dir, inode, dentry);
xfs_irele(ip);
- goto out_free_acl;
+ return error;
}
STATIC int
--
2.27.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [RFC] xfs: fix up non-directory creation in SGID directories when umask S_IXGRP
2022-03-22 6:06 [RFC] xfs: fix up non-directory creation in SGID directories when umask S_IXGRP Yang Xu
@ 2022-03-22 7:09 ` xuyang2018.jy
0 siblings, 0 replies; 2+ messages in thread
From: xuyang2018.jy @ 2022-03-22 7:09 UTC (permalink / raw)
To: linux-xfs; +Cc: djwong, pvorel
Since this patch miss posix_acl_release when succeed and break old logic
that only call from xfs_generic_create will call posix_acl_create.
I will resend a v1 patch. please ignore this patch
Best Regards
Yang Xu
> Petr reported a problem that S_ISGID bit was not clean when testing ltp case
> create09[1] by using umask(077).
>
> It fails because xfs will call posix_acl_create before xfs_init_new_node calls
> inode_init_owner, so S_IXGRP mode will be clear when enable CONFIG_XFS_POSIXACL
> and doesn't set acl or default acl on dir, then inode_init_owner will not clear
> S_ISGID bit.
>
> The calltrace as below:
>
> will use inode_init_owner(struct user_namespace *mnt_userns, structinode *inode)
> [ 296.760675] xfs_init_new_inode+0x10e/0x6c0
> [ 296.760678] xfs_create+0x401/0x610
> will use posix_acl_create(dir,&mode,&default_acl,&acl);
> [ 296.760681] xfs_generic_create+0x123/0x2e0
> [ 296.760684] ? _raw_spin_unlock+0x16/0x30
> [ 296.760687] path_openat+0xfb8/0x1210
> [ 296.760689] do_filp_open+0xb4/0x120
> [ 296.760691] ? file_tty_write.isra.31+0x203/0x340
> [ 296.760697] ? __check_object_size+0x150/0x170
> [ 296.760699] do_sys_openat2+0x242/0x310
> [ 296.760702] do_sys_open+0x4b/0x80
> [ 296.760704] do_syscall_64+0x3a/0x80
>
> Fix this is simple, we can call posix_acl_create after xfs_init_new_inode completed,
> so inode_init_owner can clear S_ISGID bit correctly like ext4 or btrfs does.
>
> But commit e6a688c33238 ("xfs: initialise attr fork on inode create") has created
> attr fork in advance according to acl, so a better solution is that moving these
> functions into xfs_init_new_inode.
>
> [1]https://github.com/linux-test-project/ltp/blob/master/testcases/kernel/syscalls/creat/creat09.c
> Reported-by: Petr Vorel<pvorel@suse.cz>
> Signed-off-by: Yang Xu<xuyang2018.jy@fujitsu.com>
> ---
> fs/xfs/xfs_inode.c | 54 +++++++++++++++++++++++++++++++++++++--
> fs/xfs/xfs_iops.c | 63 ++++------------------------------------------
> 2 files changed, 57 insertions(+), 60 deletions(-)
>
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index 26227d26f274..8127b83b376c 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -4,6 +4,7 @@
> * All Rights Reserved.
> */
> #include<linux/iversion.h>
> +#include<linux/posix_acl.h>
>
> #include "xfs.h"
> #include "xfs_fs.h"
> @@ -36,6 +37,7 @@
> #include "xfs_reflink.h"
> #include "xfs_ag.h"
> #include "xfs_log_priv.h"
> +#include "xfs_acl.h"
>
> struct kmem_cache *xfs_inode_cache;
>
> @@ -781,6 +783,36 @@ xfs_inode_inherit_flags2(
> }
> }
>
> +/*
> + * Check to see if we are likely to need an extended attribute to be added to
> + * the inode we are about to allocate. This allows the attribute fork to be
> + * created during the inode allocation, reducing the number of transactions we
> + * need to do in this fast path.
> + *
> + * The security checks are optimistic, but not guaranteed. The two LSMs that
> + * require xattrs to be added here (selinux and smack) are also the only two
> + * LSMs that add a sb->s_security structure to the superblock. Hence if security
> + * is enabled and sb->s_security is set, we have a pretty good idea that we are
> + * going to be asked to add a security xattr immediately after allocating the
> + * xfs inode and instantiating the VFS inode.
> + */
> +static inline bool
> +xfs_create_need_xattr(
> + struct inode *dir,
> + struct posix_acl *default_acl,
> + struct posix_acl *acl)
> +{
> + if (acl)
> + return true;
> + if (default_acl)
> + return true;
> +#if IS_ENABLED(CONFIG_SECURITY)
> + if (dir->i_sb->s_security)
> + return true;
> +#endif
> + return false;
> +}
> +
> /*
> * Initialise a newly allocated inode and return the in-core inode to the
> * caller locked exclusively.
> @@ -805,7 +837,7 @@ xfs_init_new_inode(
> int error;
> struct timespec64 tv;
> struct inode *inode;
> -
> + struct posix_acl *default_acl, *acl;
> /*
> * Protect against obviously corrupt allocation btree records. Later
> * xfs_iget checks will catch re-allocation of other active in-memory
> @@ -893,6 +925,9 @@ xfs_init_new_inode(
> ASSERT(0);
> }
>
> + error = posix_acl_create(dir,&inode->i_mode,&default_acl,&acl);
> + if (error)
> + return error;
> /*
> * If we need to create attributes immediately after allocating the
> * inode, initialise an empty attribute fork right now. We use the
> @@ -902,7 +937,9 @@ xfs_init_new_inode(
> * this saves us from needing to run a separate transaction to set the
> * fork offset in the immediate future.
> */
> - if (init_xattrs&& xfs_has_attr(mp)) {
> + if (init_xattrs&&
> + xfs_create_need_xattr(dir, default_acl, acl)&&
> + xfs_has_attr(mp)) {
> ip->i_forkoff = xfs_default_attroffset(ip)>> 3;
> ip->i_afp = xfs_ifork_alloc(XFS_DINODE_FMT_EXTENTS, 0);
> }
> @@ -916,6 +953,19 @@ xfs_init_new_inode(
> /* now that we have an i_mode we can setup the inode structure */
> xfs_setup_inode(ip);
>
> +#ifdef CONFIG_XFS_POSIX_ACL
> + if (default_acl) {
> + error = __xfs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
> + if (error)
> + posix_acl_release(default_acl);
> + }
> + if (acl) {
> + error = __xfs_set_acl(inode, acl, ACL_TYPE_ACCESS);
> + if (error)
> + posix_acl_release(acl);
> + }
> +#endif
> +
> *ipp = ip;
> return 0;
> }
> diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
> index b34e8e4344a8..5f9fcb6e7cf8 100644
> --- a/fs/xfs/xfs_iops.c
> +++ b/fs/xfs/xfs_iops.c
> @@ -127,37 +127,6 @@ xfs_cleanup_inode(
> xfs_remove(XFS_I(dir),&teardown, XFS_I(inode));
> }
>
> -/*
> - * Check to see if we are likely to need an extended attribute to be added to
> - * the inode we are about to allocate. This allows the attribute fork to be
> - * created during the inode allocation, reducing the number of transactions we
> - * need to do in this fast path.
> - *
> - * The security checks are optimistic, but not guaranteed. The two LSMs that
> - * require xattrs to be added here (selinux and smack) are also the only two
> - * LSMs that add a sb->s_security structure to the superblock. Hence if security
> - * is enabled and sb->s_security is set, we have a pretty good idea that we are
> - * going to be asked to add a security xattr immediately after allocating the
> - * xfs inode and instantiating the VFS inode.
> - */
> -static inline bool
> -xfs_create_need_xattr(
> - struct inode *dir,
> - struct posix_acl *default_acl,
> - struct posix_acl *acl)
> -{
> - if (acl)
> - return true;
> - if (default_acl)
> - return true;
> -#if IS_ENABLED(CONFIG_SECURITY)
> - if (dir->i_sb->s_security)
> - return true;
> -#endif
> - return false;
> -}
> -
> -
> STATIC int
> xfs_generic_create(
> struct user_namespace *mnt_userns,
> @@ -169,7 +138,6 @@ xfs_generic_create(
> {
> struct inode *inode;
> struct xfs_inode *ip = NULL;
> - struct posix_acl *default_acl, *acl;
> struct xfs_name name;
> int error;
>
> @@ -184,24 +152,19 @@ xfs_generic_create(
> rdev = 0;
> }
>
> - error = posix_acl_create(dir,&mode,&default_acl,&acl);
> - if (error)
> - return error;
> -
> /* Verify mode is valid also for tmpfile case */
> error = xfs_dentry_mode_to_name(&name, dentry, mode);
> if (unlikely(error))
> - goto out_free_acl;
> + return error;
>
> if (!tmpfile) {
> error = xfs_create(mnt_userns, XFS_I(dir),&name, mode, rdev,
> - xfs_create_need_xattr(dir, default_acl, acl),
> - &ip);
> + true,&ip);
> } else {
> error = xfs_create_tmpfile(mnt_userns, XFS_I(dir), mode,&ip);
> }
> if (unlikely(error))
> - goto out_free_acl;
> + return error;
>
> inode = VFS_I(ip);
>
> @@ -209,19 +172,6 @@ xfs_generic_create(
> if (unlikely(error))
> goto out_cleanup_inode;
>
> -#ifdef CONFIG_XFS_POSIX_ACL
> - if (default_acl) {
> - error = __xfs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
> - if (error)
> - goto out_cleanup_inode;
> - }
> - if (acl) {
> - error = __xfs_set_acl(inode, acl, ACL_TYPE_ACCESS);
> - if (error)
> - goto out_cleanup_inode;
> - }
> -#endif
> -
> xfs_setup_iops(ip);
>
> if (tmpfile) {
> @@ -240,17 +190,14 @@ xfs_generic_create(
>
> xfs_finish_inode_setup(ip);
>
> - out_free_acl:
> - posix_acl_release(default_acl);
> - posix_acl_release(acl);
> - return error;
> + return 0;
>
> out_cleanup_inode:
> xfs_finish_inode_setup(ip);
> if (!tmpfile)
> xfs_cleanup_inode(dir, inode, dentry);
> xfs_irele(ip);
> - goto out_free_acl;
> + return error;
> }
>
> STATIC int
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-03-22 7:10 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-22 6:06 [RFC] xfs: fix up non-directory creation in SGID directories when umask S_IXGRP Yang Xu
2022-03-22 7:09 ` xuyang2018.jy
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.