On 2025-09-11, Christian Brauner <brauner@xxxxxxxxxx> wrote: > On Thu, Sep 11, 2025 at 02:49:49AM +1000, Aleksa Sarai wrote: > > On 2025-09-10, Christian Brauner <brauner@xxxxxxxxxx> wrote: > > > The mount namespace has supported id retrieval for a while already. > > > Add support for the other types as well. > > > > > > Signed-off-by: Christian Brauner <brauner@xxxxxxxxxx> > > > --- > > > fs/nsfs.c | 74 +++++++++++++++++++++++++++++++++++++++-------- > > > include/uapi/linux/nsfs.h | 12 ++++++-- > > > 2 files changed, 72 insertions(+), 14 deletions(-) > > > > > > diff --git a/fs/nsfs.c b/fs/nsfs.c > > > index 3c6fcf652633..527480e67fd1 100644 > > > --- a/fs/nsfs.c > > > +++ b/fs/nsfs.c > > > @@ -173,6 +173,13 @@ static bool nsfs_ioctl_valid(unsigned int cmd) > > > case NS_GET_NSTYPE: > > > case NS_GET_OWNER_UID: > > > case NS_GET_MNTNS_ID: > > > + case NS_GET_NETNS_ID: > > > + case NS_GET_CGROUPNS_ID: > > > + case NS_GET_IPCNS_ID: > > > + case NS_GET_UTSNS_ID: > > > + case NS_GET_PIDNS_ID: > > > + case NS_GET_TIMENS_ID: > > > + case NS_GET_USERNS_ID: > > > case NS_GET_PID_FROM_PIDNS: > > > case NS_GET_TGID_FROM_PIDNS: > > > case NS_GET_PID_IN_PIDNS: > > > @@ -226,18 +233,6 @@ static long ns_ioctl(struct file *filp, unsigned int ioctl, > > > argp = (uid_t __user *) arg; > > > uid = from_kuid_munged(current_user_ns(), user_ns->owner); > > > return put_user(uid, argp); > > > - case NS_GET_MNTNS_ID: { > > > - __u64 __user *idp; > > > - __u64 id; > > > - > > > - if (ns->ops->type != CLONE_NEWNS) > > > - return -EINVAL; > > > - > > > - mnt_ns = container_of(ns, struct mnt_namespace, ns); > > > - idp = (__u64 __user *)arg; > > > - id = mnt_ns->ns.ns_id; > > > - return put_user(id, idp); > > > - } > > > case NS_GET_PID_FROM_PIDNS: > > > fallthrough; > > > case NS_GET_TGID_FROM_PIDNS: > > > @@ -283,6 +278,61 @@ static long ns_ioctl(struct file *filp, unsigned int ioctl, > > > ret = -ESRCH; > > > return ret; > > > } > > > + case NS_GET_MNTNS_ID: > > > + fallthrough; > > > + case NS_GET_NETNS_ID: > > > + fallthrough; > > > + case NS_GET_CGROUPNS_ID: > > > + fallthrough; > > > + case NS_GET_IPCNS_ID: > > > + fallthrough; > > > + case NS_GET_UTSNS_ID: > > > + fallthrough; > > > + case NS_GET_PIDNS_ID: > > > + fallthrough; > > > + case NS_GET_TIMENS_ID: > > > + fallthrough; > > > + case NS_GET_USERNS_ID: { > > > + __u64 __user *idp; > > > + __u64 id; > > > + int expected_type; > > > + > > > + switch (ioctl) { > > > + case NS_GET_MNTNS_ID: > > > + expected_type = CLONE_NEWNS; > > > + break; > > > + case NS_GET_NETNS_ID: > > > + expected_type = CLONE_NEWNET; > > > + break; > > > + case NS_GET_CGROUPNS_ID: > > > + expected_type = CLONE_NEWCGROUP; > > > + break; > > > + case NS_GET_IPCNS_ID: > > > + expected_type = CLONE_NEWIPC; > > > + break; > > > + case NS_GET_UTSNS_ID: > > > + expected_type = CLONE_NEWUTS; > > > + break; > > > + case NS_GET_PIDNS_ID: > > > + expected_type = CLONE_NEWPID; > > > + break; > > > + case NS_GET_TIMENS_ID: > > > + expected_type = CLONE_NEWTIME; > > > + break; > > > + case NS_GET_USERNS_ID: > > > + expected_type = CLONE_NEWUSER; > > > + break; > > > + default: > > > + return -EINVAL; > > > + } > > > + > > > + if (ns->ops->type != expected_type) > > > + return -EINVAL; > > > > While I get that having this be per-ns-type lets programs avoid being > > tricked into thinking that one namespace ID is actually another > > namespace, it feels a bit ugly to have to add a new ioctl for every new > > namespace. > > > > If we added a way to get the CLONE_* flag for a namespace (NS_GET_TYPE) > > That exists afaict: NS_GET_NSTYPE. D'oh, yeah that's all you need. > > we could have just NS_GET_ID. Of course, we would have to trust > > userspace to do the right thing... > > So NS_GET_ID can just return the id and be done with it. If userspace > wants to know what type it is they can issue a separate ioctl. But since > the id space is shared all ids of all namespaces can be compared with > each other reliably. So really for comparision you wouldn't need to > care. IOW, yes. Ah, I didn't realise they're all in the same id-space -- in that case it makes even more sense to just have a single NS_GET_ID IMHO. > > > + > > > + idp = (__u64 __user *)arg; > > > + id = ns->ns_id; > > > + return put_user(id, idp); > > > + } > > > } > > > > > > /* extensible ioctls */ > > > diff --git a/include/uapi/linux/nsfs.h b/include/uapi/linux/nsfs.h > > > index 97d8d80d139f..f7c21840cc09 100644 > > > --- a/include/uapi/linux/nsfs.h > > > +++ b/include/uapi/linux/nsfs.h > > > @@ -16,8 +16,6 @@ > > > #define NS_GET_NSTYPE _IO(NSIO, 0x3) > > > /* Get owner UID (in the caller's user namespace) for a user namespace */ > > > #define NS_GET_OWNER_UID _IO(NSIO, 0x4) > > > -/* Get the id for a mount namespace */ > > > -#define NS_GET_MNTNS_ID _IOR(NSIO, 0x5, __u64) > > > /* Translate pid from target pid namespace into the caller's pid namespace. */ > > > #define NS_GET_PID_FROM_PIDNS _IOR(NSIO, 0x6, int) > > > /* Return thread-group leader id of pid in the callers pid namespace. */ > > > @@ -42,6 +40,16 @@ struct mnt_ns_info { > > > /* Get previous namespace. */ > > > #define NS_MNT_GET_PREV _IOR(NSIO, 12, struct mnt_ns_info) > > > > > > +/* Retrieve namespace identifiers. */ > > > +#define NS_GET_MNTNS_ID _IOR(NSIO, 5, __u64) > > > +#define NS_GET_NETNS_ID _IOR(NSIO, 13, __u64) > > > +#define NS_GET_CGROUPNS_ID _IOR(NSIO, 14, __u64) > > > +#define NS_GET_IPCNS_ID _IOR(NSIO, 15, __u64) > > > +#define NS_GET_UTSNS_ID _IOR(NSIO, 16, __u64) > > > +#define NS_GET_PIDNS_ID _IOR(NSIO, 17, __u64) > > > +#define NS_GET_TIMENS_ID _IOR(NSIO, 18, __u64) > > > +#define NS_GET_USERNS_ID _IOR(NSIO, 19, __u64) > > > + > > > enum init_ns_ino { > > > IPC_NS_INIT_INO = 0xEFFFFFFFU, > > > UTS_NS_INIT_INO = 0xEFFFFFFEU, > > > > > > -- > > > 2.47.3 > > > > > > > -- > > Aleksa Sarai > > Senior Software Engineer (Containers) > > SUSE Linux GmbH > > https://www.cyphar.com/ > > -- Aleksa Sarai Senior Software Engineer (Containers) SUSE Linux GmbH https://www.cyphar.com/
Attachment:
signature.asc
Description: PGP signature