[PATCH 29/32] nsfs: add missing id retrieval support

Christian Brauner posted 32 patches 4 months, 4 weeks ago
There is a newer version of this series
[PATCH 29/32] nsfs: add missing id retrieval support
Posted by Christian Brauner 4 months, 4 weeks ago
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;
+
+		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
Re: [PATCH 29/32] nsfs: add missing id retrieval support
Posted by Aleksa Sarai 4 months, 4 weeks ago
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)
we could have just NS_GET_ID. Of course, we would have to trust
userspace to do the right thing...

> +
> +		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/
Re: [PATCH 29/32] nsfs: add missing id retrieval support
Posted by Christian Brauner 4 months, 4 weeks ago
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.

> 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.

> 
> > +
> > +		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/
Re: [PATCH 29/32] nsfs: add missing id retrieval support
Posted by Aleksa Sarai 4 months, 4 weeks ago
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/
> 
> 

-- 
Aleksa Sarai
Senior Software Engineer (Containers)
SUSE Linux GmbH
https://www.cyphar.com/