Skip to content

Commit cf619f8

Browse files
committed
Merge tag 'fs.ovl.setgid.v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/idmapping
Pull setgid inheritance updates from Christian Brauner: "This contains the work to make setgid inheritance consistent between modifying a file and when changing ownership or mode as this has been a repeated source of very subtle bugs. The gist is that we perform the same permission checks in the write path as we do in the ownership and mode changing paths after this series where we're currently doing different things. We've already made setgid inheritance a lot more consistent and reliable in the last releases by moving setgid stripping from the individual filesystems up into the vfs. This aims to make the logic even more consistent and easier to understand and also to fix long-standing overlayfs setgid inheritance bugs. Miklos was nice enough to just let me carry the trivial overlayfs patches from Amir too. Below is a more detailed explanation how the current difference in setgid handling lead to very subtle bugs exemplified via overlayfs which is a victim of the current rules. I hope this explains why I think taking the regression risk here is worth it. A long while ago I found a few setgid inheritance bugs in overlayfs in the write path in certain conditions. Amir recently picked this back up in [1] and I jumped on board to fix this more generally. On the surface all that overlayfs would need to fix setgid inheritance would be to call file_remove_privs() or file_modified() but actually that isn't enough because the setgid inheritance api is wildly inconsistent in that area. Before this pr setgid stripping in file_remove_privs()'s old should_remove_suid() helper was inconsistent with other parts of the vfs. Specifically, it only raises ATTR_KILL_SGID if the inode is S_ISGID and S_IXGRP but not if the inode isn't in the caller's groups and the caller isn't privileged over the inode although we require this already in setattr_prepare() and setattr_copy() and so all filesystem implement this requirement implicitly because they have to use setattr_{prepare,copy}() anyway. But the inconsistency shows up in setgid stripping bugs for overlayfs in xfstests (e.g., generic/673, generic/683, generic/685, generic/686, generic/687). For example, we test whether suid and setgid stripping works correctly when performing various write-like operations as an unprivileged user (fallocate, reflink, write, etc.): echo "Test 1 - qa_user, non-exec file $verb" setup_testfile chmod a+rws $junk_file commit_and_check "$qa_user" "$verb" 64k 64k The test basically creates a file with 6666 permissions. While the file has the S_ISUID and S_ISGID bits set it does not have the S_IXGRP set. On a regular filesystem like xfs what will happen is: sys_fallocate() -> vfs_fallocate() -> xfs_file_fallocate() -> file_modified() -> __file_remove_privs() -> dentry_needs_remove_privs() -> should_remove_suid() -> __remove_privs() newattrs.ia_valid = ATTR_FORCE | kill; -> notify_change() -> setattr_copy() In should_remove_suid() we can see that ATTR_KILL_SUID is raised unconditionally because the file in the test has S_ISUID set. But we also see that ATTR_KILL_SGID won't be set because while the file is S_ISGID it is not S_IXGRP (see above) which is a condition for ATTR_KILL_SGID being raised. So by the time we call notify_change() we have attr->ia_valid set to ATTR_KILL_SUID | ATTR_FORCE. Now notify_change() sees that ATTR_KILL_SUID is set and does: ia_valid = attr->ia_valid |= ATTR_MODE attr->ia_mode = (inode->i_mode & ~S_ISUID); which means that when we call setattr_copy() later we will definitely update inode->i_mode. Note that attr->ia_mode still contains S_ISGID. Now we call into the filesystem's ->setattr() inode operation which will end up calling setattr_copy(). Since ATTR_MODE is set we will hit: if (ia_valid & ATTR_MODE) { umode_t mode = attr->ia_mode; vfsgid_t vfsgid = i_gid_into_vfsgid(mnt_userns, inode); if (!vfsgid_in_group_p(vfsgid) && !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID)) mode &= ~S_ISGID; inode->i_mode = mode; } and since the caller in the test is neither capable nor in the group of the inode the S_ISGID bit is stripped. But assume the file isn't suid then ATTR_KILL_SUID won't be raised which has the consequence that neither the setgid nor the suid bits are stripped even though it should be stripped because the inode isn't in the caller's groups and the caller isn't privileged over the inode. If overlayfs is in the mix things become a bit more complicated and the bug shows up more clearly. When e.g., ovl_setattr() is hit from ovl_fallocate()'s call to file_remove_privs() then ATTR_KILL_SUID and ATTR_KILL_SGID might be raised but because the check in notify_change() is questioning the ATTR_KILL_SGID flag again by requiring S_IXGRP for it to be stripped the S_ISGID bit isn't removed even though it should be stripped: sys_fallocate() -> vfs_fallocate() -> ovl_fallocate() -> file_remove_privs() -> dentry_needs_remove_privs() -> should_remove_suid() -> __remove_privs() newattrs.ia_valid = ATTR_FORCE | kill; -> notify_change() -> ovl_setattr() /* TAKE ON MOUNTER'S CREDS */ -> ovl_do_notify_change() -> notify_change() /* GIVE UP MOUNTER'S CREDS */ /* TAKE ON MOUNTER'S CREDS */ -> vfs_fallocate() -> xfs_file_fallocate() -> file_modified() -> __file_remove_privs() -> dentry_needs_remove_privs() -> should_remove_suid() -> __remove_privs() newattrs.ia_valid = attr_force | kill; -> notify_change() The fix for all of this is to make file_remove_privs()'s should_remove_suid() helper perform the same checks as we already require in setattr_prepare() and setattr_copy() and have notify_change() not pointlessly requiring S_IXGRP again. It doesn't make any sense in the first place because the caller must calculate the flags via should_remove_suid() anyway which would raise ATTR_KILL_SGID Note that some xfstests will now fail as these patches will cause the setgid bit to be lost in certain conditions for unprivileged users modifying a setgid file when they would've been kept otherwise. I think this risk is worth taking and I explained and mentioned this multiple times on the list [2]. Enforcing the rules consistently across write operations and chmod/chown will lead to losing the setgid bit in cases were it might've been retained before. While I've mentioned this a few times but it's worth repeating just to make sure that this is understood. For the sake of maintainability, consistency, and security this is a risk worth taking. If we really see regressions for workloads the fix is to have special setgid handling in the write path again with different semantics from chmod/chown and possibly additional duct tape for overlayfs. I'll update the relevant xfstests with if you should decide to merge this second setgid cleanup. Before that people should be aware that there might be failures for fstests where unprivileged users modify a setgid file" Link: https://lore.kernel.org/linux-fsdevel/[email protected] [1] Link: https://lore.kernel.org/linux-fsdevel/20221122142010.zchf2jz2oymx55qi@wittgenstein [2] * tag 'fs.ovl.setgid.v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/idmapping: fs: use consistent setgid checks in is_sxid() ovl: remove privs in ovl_fallocate() ovl: remove privs in ovl_copyfile() attr: use consistent sgid stripping checks attr: add setattr_should_drop_sgid() fs: move should_remove_suid() attr: add in_group_or_capable()
2 parents 6a518af + 8d84e39 commit cf619f8

File tree

9 files changed

+140
-56
lines changed

9 files changed

+140
-56
lines changed

Documentation/trace/ftrace.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2940,7 +2940,7 @@ Produces::
29402940
bash-1994 [000] .... 4342.324898: ima_get_action <-process_measurement
29412941
bash-1994 [000] .... 4342.324898: ima_match_policy <-ima_get_action
29422942
bash-1994 [000] .... 4342.324899: do_truncate <-do_last
2943-
bash-1994 [000] .... 4342.324899: should_remove_suid <-do_truncate
2943+
bash-1994 [000] .... 4342.324899: setattr_should_drop_suidgid <-do_truncate
29442944
bash-1994 [000] .... 4342.324899: notify_change <-do_truncate
29452945
bash-1994 [000] .... 4342.324900: current_fs_time <-notify_change
29462946
bash-1994 [000] .... 4342.324900: current_kernel_time <-current_fs_time

fs/attr.c

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,70 @@
1818
#include <linux/evm.h>
1919
#include <linux/ima.h>
2020

21+
#include "internal.h"
22+
23+
/**
24+
* setattr_should_drop_sgid - determine whether the setgid bit needs to be
25+
* removed
26+
* @mnt_userns: user namespace of the mount @inode was found from
27+
* @inode: inode to check
28+
*
29+
* This function determines whether the setgid bit needs to be removed.
30+
* We retain backwards compatibility and require setgid bit to be removed
31+
* unconditionally if S_IXGRP is set. Otherwise we have the exact same
32+
* requirements as setattr_prepare() and setattr_copy().
33+
*
34+
* Return: ATTR_KILL_SGID if setgid bit needs to be removed, 0 otherwise.
35+
*/
36+
int setattr_should_drop_sgid(struct user_namespace *mnt_userns,
37+
const struct inode *inode)
38+
{
39+
umode_t mode = inode->i_mode;
40+
41+
if (!(mode & S_ISGID))
42+
return 0;
43+
if (mode & S_IXGRP)
44+
return ATTR_KILL_SGID;
45+
if (!in_group_or_capable(mnt_userns, inode,
46+
i_gid_into_vfsgid(mnt_userns, inode)))
47+
return ATTR_KILL_SGID;
48+
return 0;
49+
}
50+
51+
/**
52+
* setattr_should_drop_suidgid - determine whether the set{g,u}id bit needs to
53+
* be dropped
54+
* @mnt_userns: user namespace of the mount @inode was found from
55+
* @inode: inode to check
56+
*
57+
* This function determines whether the set{g,u}id bits need to be removed.
58+
* If the setuid bit needs to be removed ATTR_KILL_SUID is returned. If the
59+
* setgid bit needs to be removed ATTR_KILL_SGID is returned. If both
60+
* set{g,u}id bits need to be removed the corresponding mask of both flags is
61+
* returned.
62+
*
63+
* Return: A mask of ATTR_KILL_S{G,U}ID indicating which - if any - setid bits
64+
* to remove, 0 otherwise.
65+
*/
66+
int setattr_should_drop_suidgid(struct user_namespace *mnt_userns,
67+
struct inode *inode)
68+
{
69+
umode_t mode = inode->i_mode;
70+
int kill = 0;
71+
72+
/* suid always must be killed */
73+
if (unlikely(mode & S_ISUID))
74+
kill = ATTR_KILL_SUID;
75+
76+
kill |= setattr_should_drop_sgid(mnt_userns, inode);
77+
78+
if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode)))
79+
return kill;
80+
81+
return 0;
82+
}
83+
EXPORT_SYMBOL(setattr_should_drop_suidgid);
84+
2185
/**
2286
* chown_ok - verify permissions to chown inode
2387
* @mnt_userns: user namespace of the mount @inode was found from
@@ -140,8 +204,7 @@ int setattr_prepare(struct user_namespace *mnt_userns, struct dentry *dentry,
140204
vfsgid = i_gid_into_vfsgid(mnt_userns, inode);
141205

142206
/* Also check the setgid bit! */
143-
if (!vfsgid_in_group_p(vfsgid) &&
144-
!capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID))
207+
if (!in_group_or_capable(mnt_userns, inode, vfsgid))
145208
attr->ia_mode &= ~S_ISGID;
146209
}
147210

@@ -251,9 +314,8 @@ void setattr_copy(struct user_namespace *mnt_userns, struct inode *inode,
251314
inode->i_ctime = attr->ia_ctime;
252315
if (ia_valid & ATTR_MODE) {
253316
umode_t mode = attr->ia_mode;
254-
vfsgid_t vfsgid = i_gid_into_vfsgid(mnt_userns, inode);
255-
if (!vfsgid_in_group_p(vfsgid) &&
256-
!capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID))
317+
if (!in_group_or_capable(mnt_userns, inode,
318+
i_gid_into_vfsgid(mnt_userns, inode)))
257319
mode &= ~S_ISGID;
258320
inode->i_mode = mode;
259321
}
@@ -375,7 +437,7 @@ int notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
375437
}
376438
}
377439
if (ia_valid & ATTR_KILL_SGID) {
378-
if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
440+
if (mode & S_ISGID) {
379441
if (!(ia_valid & ATTR_MODE)) {
380442
ia_valid = attr->ia_valid |= ATTR_MODE;
381443
attr->ia_mode = inode->i_mode;

fs/fuse/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1313,7 +1313,7 @@ static ssize_t fuse_cache_write_iter(struct kiocb *iocb, struct iov_iter *from)
13131313
return err;
13141314

13151315
if (fc->handle_killpriv_v2 &&
1316-
should_remove_suid(file_dentry(file))) {
1316+
setattr_should_drop_suidgid(&init_user_ns, file_inode(file))) {
13171317
goto writethrough;
13181318
}
13191319

fs/inode.c

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1948,41 +1948,13 @@ void touch_atime(const struct path *path)
19481948
}
19491949
EXPORT_SYMBOL(touch_atime);
19501950

1951-
/*
1952-
* The logic we want is
1953-
*
1954-
* if suid or (sgid and xgrp)
1955-
* remove privs
1956-
*/
1957-
int should_remove_suid(struct dentry *dentry)
1958-
{
1959-
umode_t mode = d_inode(dentry)->i_mode;
1960-
int kill = 0;
1961-
1962-
/* suid always must be killed */
1963-
if (unlikely(mode & S_ISUID))
1964-
kill = ATTR_KILL_SUID;
1965-
1966-
/*
1967-
* sgid without any exec bits is just a mandatory locking mark; leave
1968-
* it alone. If some exec bits are set, it's a real sgid; kill it.
1969-
*/
1970-
if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
1971-
kill |= ATTR_KILL_SGID;
1972-
1973-
if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode)))
1974-
return kill;
1975-
1976-
return 0;
1977-
}
1978-
EXPORT_SYMBOL(should_remove_suid);
1979-
19801951
/*
19811952
* Return mask of changes for notify_change() that need to be done as a
19821953
* response to write or truncate. Return 0 if nothing has to be changed.
19831954
* Negative value on error (change should be denied).
19841955
*/
1985-
int dentry_needs_remove_privs(struct dentry *dentry)
1956+
int dentry_needs_remove_privs(struct user_namespace *mnt_userns,
1957+
struct dentry *dentry)
19861958
{
19871959
struct inode *inode = d_inode(dentry);
19881960
int mask = 0;
@@ -1991,7 +1963,7 @@ int dentry_needs_remove_privs(struct dentry *dentry)
19911963
if (IS_NOSEC(inode))
19921964
return 0;
19931965

1994-
mask = should_remove_suid(dentry);
1966+
mask = setattr_should_drop_suidgid(mnt_userns, inode);
19951967
ret = security_inode_need_killpriv(dentry);
19961968
if (ret < 0)
19971969
return ret;
@@ -2023,7 +1995,7 @@ static int __file_remove_privs(struct file *file, unsigned int flags)
20231995
if (IS_NOSEC(inode) || !S_ISREG(inode->i_mode))
20241996
return 0;
20251997

2026-
kill = dentry_needs_remove_privs(dentry);
1998+
kill = dentry_needs_remove_privs(file_mnt_user_ns(file), dentry);
20271999
if (kill < 0)
20282000
return kill;
20292001

@@ -2484,6 +2456,28 @@ struct timespec64 current_time(struct inode *inode)
24842456
}
24852457
EXPORT_SYMBOL(current_time);
24862458

2459+
/**
2460+
* in_group_or_capable - check whether caller is CAP_FSETID privileged
2461+
* @mnt_userns: user namespace of the mount @inode was found from
2462+
* @inode: inode to check
2463+
* @vfsgid: the new/current vfsgid of @inode
2464+
*
2465+
* Check wether @vfsgid is in the caller's group list or if the caller is
2466+
* privileged with CAP_FSETID over @inode. This can be used to determine
2467+
* whether the setgid bit can be kept or must be dropped.
2468+
*
2469+
* Return: true if the caller is sufficiently privileged, false if not.
2470+
*/
2471+
bool in_group_or_capable(struct user_namespace *mnt_userns,
2472+
const struct inode *inode, vfsgid_t vfsgid)
2473+
{
2474+
if (vfsgid_in_group_p(vfsgid))
2475+
return true;
2476+
if (capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID))
2477+
return true;
2478+
return false;
2479+
}
2480+
24872481
/**
24882482
* mode_strip_sgid - handle the sgid bit for non-directories
24892483
* @mnt_userns: User namespace of the mount the inode was created from
@@ -2505,11 +2499,9 @@ umode_t mode_strip_sgid(struct user_namespace *mnt_userns,
25052499
return mode;
25062500
if (S_ISDIR(mode) || !dir || !(dir->i_mode & S_ISGID))
25072501
return mode;
2508-
if (in_group_p(i_gid_into_mnt(mnt_userns, dir)))
2509-
return mode;
2510-
if (capable_wrt_inode_uidgid(mnt_userns, dir, CAP_FSETID))
2502+
if (in_group_or_capable(mnt_userns, dir,
2503+
i_gid_into_vfsgid(mnt_userns, dir)))
25112504
return mode;
2512-
25132505
return mode & ~S_ISGID;
25142506
}
25152507
EXPORT_SYMBOL(mode_strip_sgid);

fs/internal.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,9 @@ extern int vfs_open(const struct path *, struct file *);
150150
* inode.c
151151
*/
152152
extern long prune_icache_sb(struct super_block *sb, struct shrink_control *sc);
153-
extern int dentry_needs_remove_privs(struct dentry *dentry);
153+
int dentry_needs_remove_privs(struct user_namespace *, struct dentry *dentry);
154+
bool in_group_or_capable(struct user_namespace *mnt_userns,
155+
const struct inode *inode, vfsgid_t vfsgid);
154156

155157
/*
156158
* fs-writeback.c
@@ -255,3 +257,9 @@ static inline ssize_t do_get_acl(struct user_namespace *mnt_userns,
255257
#endif
256258

257259
ssize_t __kernel_write_iter(struct file *file, struct iov_iter *from, loff_t *pos);
260+
261+
/*
262+
* fs/attr.c
263+
*/
264+
int setattr_should_drop_sgid(struct user_namespace *mnt_userns,
265+
const struct inode *inode);

fs/ocfs2/file.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,7 +1991,7 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode,
19911991
}
19921992
}
19931993

1994-
if (file && should_remove_suid(file->f_path.dentry)) {
1994+
if (file && setattr_should_drop_suidgid(&init_user_ns, file_inode(file))) {
19951995
ret = __ocfs2_write_remove_suid(inode, di_bh);
19961996
if (ret) {
19971997
mlog_errno(ret);
@@ -2279,7 +2279,7 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
22792279
* inode. There's also the dinode i_size state which
22802280
* can be lost via setattr during extending writes (we
22812281
* set inode->i_size at the end of a write. */
2282-
if (should_remove_suid(dentry)) {
2282+
if (setattr_should_drop_suidgid(&init_user_ns, inode)) {
22832283
if (meta_level == 0) {
22842284
ocfs2_inode_unlock_for_extent_tree(inode,
22852285
&di_bh,

fs/open.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ int do_truncate(struct user_namespace *mnt_userns, struct dentry *dentry,
5454
}
5555

5656
/* Remove suid, sgid, and file capabilities on truncate too */
57-
ret = dentry_needs_remove_privs(dentry);
57+
ret = dentry_needs_remove_privs(mnt_userns, dentry);
5858
if (ret < 0)
5959
return ret;
6060
if (ret)
@@ -723,10 +723,10 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
723723
return -EINVAL;
724724
if ((group != (gid_t)-1) && !setattr_vfsgid(&newattrs, gid))
725725
return -EINVAL;
726-
if (!S_ISDIR(inode->i_mode))
727-
newattrs.ia_valid |=
728-
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
729726
inode_lock(inode);
727+
if (!S_ISDIR(inode->i_mode))
728+
newattrs.ia_valid |= ATTR_KILL_SUID | ATTR_KILL_PRIV |
729+
setattr_should_drop_sgid(mnt_userns, inode);
730730
/* Continue to send actual fs values, not the mount values. */
731731
error = security_path_chown(
732732
path,

fs/overlayfs/file.c

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -517,9 +517,16 @@ static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len
517517
const struct cred *old_cred;
518518
int ret;
519519

520+
inode_lock(inode);
521+
/* Update mode */
522+
ovl_copyattr(inode);
523+
ret = file_remove_privs(file);
524+
if (ret)
525+
goto out_unlock;
526+
520527
ret = ovl_real_fdget(file, &real);
521528
if (ret)
522-
return ret;
529+
goto out_unlock;
523530

524531
old_cred = ovl_override_creds(file_inode(file)->i_sb);
525532
ret = vfs_fallocate(real.file, mode, offset, len);
@@ -530,6 +537,9 @@ static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len
530537

531538
fdput(real);
532539

540+
out_unlock:
541+
inode_unlock(inode);
542+
533543
return ret;
534544
}
535545

@@ -567,14 +577,23 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in,
567577
const struct cred *old_cred;
568578
loff_t ret;
569579

580+
inode_lock(inode_out);
581+
if (op != OVL_DEDUPE) {
582+
/* Update mode */
583+
ovl_copyattr(inode_out);
584+
ret = file_remove_privs(file_out);
585+
if (ret)
586+
goto out_unlock;
587+
}
588+
570589
ret = ovl_real_fdget(file_out, &real_out);
571590
if (ret)
572-
return ret;
591+
goto out_unlock;
573592

574593
ret = ovl_real_fdget(file_in, &real_in);
575594
if (ret) {
576595
fdput(real_out);
577-
return ret;
596+
goto out_unlock;
578597
}
579598

580599
old_cred = ovl_override_creds(file_inode(file_out)->i_sb);
@@ -603,6 +622,9 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in,
603622
fdput(real_in);
604623
fdput(real_out);
605624

625+
out_unlock:
626+
inode_unlock(inode_out);
627+
606628
return ret;
607629
}
608630

include/linux/fs.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3133,7 +3133,7 @@ extern void __destroy_inode(struct inode *);
31333133
extern struct inode *new_inode_pseudo(struct super_block *sb);
31343134
extern struct inode *new_inode(struct super_block *sb);
31353135
extern void free_inode_nonrcu(struct inode *inode);
3136-
extern int should_remove_suid(struct dentry *);
3136+
extern int setattr_should_drop_suidgid(struct user_namespace *, struct inode *);
31373137
extern int file_remove_privs(struct file *);
31383138

31393139
/*
@@ -3564,7 +3564,7 @@ int __init list_bdev_fs_names(char *buf, size_t size);
35643564

35653565
static inline bool is_sxid(umode_t mode)
35663566
{
3567-
return (mode & S_ISUID) || ((mode & S_ISGID) && (mode & S_IXGRP));
3567+
return mode & (S_ISUID | S_ISGID);
35683568
}
35693569

35703570
static inline int check_sticky(struct user_namespace *mnt_userns,

0 commit comments

Comments
 (0)