When posix access ACL is set, it can have an effect on file mode and it can also need to clear SGID if. - None of caller's group/supplementary groups match file owner group. AND - Caller is not priviliged (No CAP_FSETID). As of now fuser server is responsible for changing the file mode as well. But it does not know whether to clear SGID or not. So add a flag FUSE_SETXATTR_ACL_KILL_SGID and send this info with SETXATTR to let file server know that sgid needs to be cleared as well.
Unified · Split
| @@ -71,6 +71,7 @@ int fuse_set_acl(struct user_namespace *mnt_userns, struct inode *inode, · 70 unmodified lines | ||
| 71 | 71 | return -EINVAL; |
| 72 | 72 | |
| 73 | 73 | if (acl) { |
| 74 | + unsigned int extra_flags = 0; | |
| 74 | 75 | /* |
| 75 | 76 | * Fuse userspace is responsible for updating access |
| 76 | 77 | * permissions in the inode, if needed. fuse_setxattr |
| @@ -94,7 +95,11 @@ int fuse_set_acl(struct user_namespace *mnt_userns, struct inode *inode, · 17 unmodified lines | ||
| 94 | 95 | return ret; |
| 95 | 96 | } |
| 96 | 97 | |
| 97 | − ret = fuse_setxattr(inode, name, value, size, 0, 0); | |
| 98 | + if (!in_group_p(i_gid_into_mnt(&init_user_ns, inode)) && | |
| 99 | + !capable_wrt_inode_uidgid(&init_user_ns, inode, CAP_FSETID)) | |
| 100 | + extra_flags |= FUSE_SETXATTR_ACL_KILL_SGID; | |
| 101 | + | |
| 102 | + ret = fuse_setxattr(inode, name, value, size, 0, extra_flags); | |
| 98 | 103 | kfree(value); |
| 99 | 104 | } else { |
| 100 | 105 | ret = fuse_removexattr(inode, name); |
| @@ -180,6 +180,7 @@ · 179 unmodified lines | ||
| 180 | 180 | * - add FUSE_HANDLE_KILLPRIV_V2, FUSE_WRITE_KILL_SUIDGID, FATTR_KILL_SUIDGID |
| 181 | 181 | * - add FUSE_OPEN_KILL_SUIDGID |
| 182 | 182 | * - extend fuse_setxattr_in, add FUSE_SETXATTR_EXT |
| 183 | + * - add FUSE_SETXATTR_ACL_KILL_SGID | |
| 183 | 184 | */ |
| 184 | 185 | |
| 185 | 186 | #ifndef _LINUX_FUSE_H |
| @@ -454,6 +455,12 @@ struct fuse_file_lock { · 268 unmodified lines | ||
| 454 | 455 | */ |
| 455 | 456 | #define FUSE_OPEN_KILL_SUIDGID (1 << 0) |
| 456 | 457 | |
| 458 | +/** | |
| 459 | + * setxattr flags | |
| 460 | + * FUSE_SETXATTR_ACL_KILL_SGID: Clear SGID when system.posix_acl_access is set | |
| 461 | + */ | |
| 462 | +#define FUSE_SETXATTR_ACL_KILL_SGID (1 << 0) | |
| 463 | + | |
| 457 | 464 | enum fuse_opcode { |
| 458 | 465 | FUSE_LOOKUP = 1, |
| 459 | 466 | FUSE_FORGET = 2, /* no reply */ |