Bug #62217
closedceph_fs.h: add separate owner_{u,g}id fields
100%
Description
This task is about adding separate fields to pass inode owner's UID/GID for operations which create new inodes:
CEPH_MDS_OP_CREATE, CEPH_MDS_OP_MKNOD, CEPH_MDS_OP_MKDIR, CEPH_MDS_OP_SYMLINK.
Before we have used caller_{u,g}id fields for two purposes:
- for MDS permission checks
- to set UID/GID for new inodes
but during a long discussion around adding idmapped mounts support to cephfs kernel client we decided to extend wire protocol [1].
Originally, Christian Brauner pointed to this problem [2], but a few initial versions of "ceph: support idmapped mounts" patchset were based on a compromise between bringing idmapped mounts support and changing on-wire data structures. The only problem with this approach is that if we have UID/GID-based permission checks on the MDS side they won't work as intended. Xiubo Li pointed to this issue and said that it's critical enough to not being ignored.
This patch does not change behavior for client or MDS, because in the current client implementation we do:
req->set_inode_owner_uid_gid(perms.uid(), perms.gid());
so, these new fields contain the same value as caller_{u,g}id.
This new extension is used in a non-trivial way in the Linux kernel client:
https://github.com/mihalicyn/linux/commits/fs.idmapped.ceph
In addition to new fields we also add CEPHFS_FEATURE_HAS_OWNER_UIDGID feature bit. It can be used on the client-side
to check if MDS supports these new fields and can handle them properly.
Example (how idmapped mounts work) [4]:
1. Mount cephfs mount.ceph admin@XYZ.cephfs=/ /mnt/ceph -o mon_addr=127.0.0.1:6789,secret=very_secret_key 2. Make 1000:1000 a root dentry owner (it will be convenient because we want to use mapping 1000:0:1 for simplicity) chown 1000:1000 /mnt/ceph 3. create an idmapped mount based on a regular /mnt/ceph mount using a mount-idmapped tool that was written by Christian. [ taken from https://raw.githubusercontent.com/brauner/mount-idmapped/master/mount-idmapped.c ] ./mount-idmapped --map-mount b:1000:0:1 /mnt/ceph /mnt/ceph_idmapped "b" stands for "both", so we are creating a mapping of length 1 for both UID and GID. 1000 is a UID/GID "on-disk", 0 is a mapped UID/GID. 4. Just to be precise, let's look at which UID/GID we have now. root@ubuntu:/home/ubuntu# ls -lan /mnt/ceph total 4 drwxrwxrwx 2 1000 1000 0 Jun 1 17:51 . drwxr-xr-x 4 0 0 4096 Jun 1 16:55 .. root@ubuntu:/home/ubuntu# ls -lan /mnt/ceph_idmapped total 4 drwxrwxrwx 2 0 0 0 Jun 1 17:51 . drwxr-xr-x 4 0 0 4096 Jun 1 16:55 .. 5. Now let's create a bunch of files with different owners and through different mounts (idmapped/non-idmapped). 5.1. Create a file from 0:0 through the idmapped mount (it should appear as 1000:1000 on disk) root@ubuntu:/home/ubuntu# sudo -u#0 -g#0 touch /mnt/ceph_idmapped/created_through_idmapped_mnt_with_uid0 5.2. Create a file from 1000:1000 through the idmapped mount (should fail because 1000:1000 is not a valid UID/GID as it can't be mapped back to the "on-disk" UID/GID set). root@ubuntu:/home/ubuntu# sudo -u#1000 -g#1000 touch /mnt/ceph_idmapped/created_through_idmapped_mnt_with_uid1000 touch: cannot touch '/mnt/ceph_idmapped/created_through_idmapped_mnt_with_uid1000': Value too large for defined data type ... and we've got EOVERFLOW. That's correct! 5.3. Create a file from 0:0 but through the regular mount. (it should appear as overflowuid(=65534) in idmapped mount, because 0:0 on-disk is not mapped to the UID/GID set). root@ubuntu:/home/ubuntu# sudo -u#0 -g#0 touch /mnt/ceph/created_directly_with_uid0 5.4. Create a file from 1000:1000 but through the regular mount. (it should appear as 0:0 in idmapped mount, because 1000 (on-disk) mapped to 0). root@ubuntu:/home/ubuntu# sudo -u#1000 -g#1000 touch /mnt/ceph/created_directly_with_uid1000 6. Now let's look on the result: root@ubuntu:/home/ubuntu# ls -lan /mnt/ceph total 4 drwxrwxrwx 2 1000 1000 3 Jun 1 17:54 . drwxr-xr-x 4 0 0 4096 Jun 1 16:55 .. -rw-r--r-- 1 0 0 0 Jun 1 17:54 created_directly_with_uid0 -rw-rw-r-- 1 1000 1000 0 Jun 1 17:54 created_directly_with_uid1000 -rw-r--r-- 1 1000 1000 0 Jun 1 17:53 created_through_idmapped_mnt_with_uid0 root@ubuntu:/home/ubuntu# ls -lan /mnt/ceph_idmapped total 4 drwxrwxrwx 2 0 0 3 Jun 1 17:54 . drwxr-xr-x 4 0 0 4096 Jun 1 16:55 .. -rw-r--r-- 1 65534 65534 0 Jun 1 17:54 created_directly_with_uid0 -rw-rw-r-- 1 0 0 0 Jun 1 17:54 created_directly_with_uid1000 -rw-r--r-- 1 0 0 0 Jun 1 17:53 created_through_idmapped_mnt_with_uid0
[1] https://lore.kernel.org/lkml/CAEivzxfw1fHO2TFA4dx3u23ZKK6Q+EThfzuibrhA3RKM=ZOYLg@mail.gmail.com/
[2] https://lore.kernel.org/all/20220104140414.155198-3-brauner@kernel.org/
[3] https://lore.kernel.org/lkml/CAEivzxcBBJV6DOGzy5S7=TUjrXZfVaGaJX5z7WFzYq1w4MdtiA@mail.gmail.com/
[4] https://lore.kernel.org/lkml/CAEivzxefBRPozUPQxYgVh0gOpjsovtBuJ3w9BoqSizpST_YxTA@mail.gmail.com/#t