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 | return -EINVAL; | 71 | return -EINVAL; |
| 72 | 72 | ||
| 73 | if (acl) { | 73 | if (acl) { |
| 74 | unsigned int extra_flags = 0; | ||
| 74 | /* | 75 | /* |
| 75 | * Fuse userspace is responsible for updating access | 76 | * Fuse userspace is responsible for updating access |
| 76 | * permissions in the inode, if needed. fuse_setxattr | 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 | return ret; | 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 | kfree(value); | 103 | kfree(value); |
| 99 | } else { | 104 | } else { |
| 100 | ret = fuse_removexattr(inode, name); | 105 | ret = fuse_removexattr(inode, name); |
| @@ -180,6 +180,7 @@ · 179 unmodified lines | |||
| 180 | * - add FUSE_HANDLE_KILLPRIV_V2, FUSE_WRITE_KILL_SUIDGID, FATTR_KILL_SUIDGID | 180 | * - add FUSE_HANDLE_KILLPRIV_V2, FUSE_WRITE_KILL_SUIDGID, FATTR_KILL_SUIDGID |
| 181 | * - add FUSE_OPEN_KILL_SUIDGID | 181 | * - add FUSE_OPEN_KILL_SUIDGID |
| 182 | * - extend fuse_setxattr_in, add FUSE_SETXATTR_EXT | 182 | * - extend fuse_setxattr_in, add FUSE_SETXATTR_EXT |
| 183 | * - add FUSE_SETXATTR_ACL_KILL_SGID | ||
| 183 | */ | 184 | */ |
| 184 | 185 | ||
| 185 | #ifndef _LINUX_FUSE_H | 186 | #ifndef _LINUX_FUSE_H |
| @@ -454,6 +455,12 @@ struct fuse_file_lock { · 268 unmodified lines | |||
| 454 | */ | 455 | */ |
| 455 | #define FUSE_OPEN_KILL_SUIDGID (1 << 0) | 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 | enum fuse_opcode { | 464 | enum fuse_opcode { |
| 458 | FUSE_LOOKUP = 1, | 465 | FUSE_LOOKUP = 1, |
| 459 | FUSE_FORGET = 2, /* no reply */ | 466 | FUSE_FORGET = 2, /* no reply */ |