On 2025-09-10, Christian Brauner <[email protected]> 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 <[email protected]>
> ---
>  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/

Attachment: signature.asc
Description: PGP signature

Reply via email to