On 2025-09-11, Christian Brauner brauner@kernel.org wrote:
On Thu, Sep 11, 2025 at 02:49:49AM +1000, Aleksa Sarai wrote:
On 2025-09-10, Christian Brauner brauner@kernel.org 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@kernel.org
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/