linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/2] nsfs: Add an ioctl() to return the namespace type
       [not found] <11b302a2-aac3-5994-a12d-e93ce64f7819@gmail.com>
@ 2016-12-23  9:54 ` Michael Kerrisk (man-pages)
  2016-12-23  9:54 ` [PATCH v2 2/2] nsfs: Add an ioctl() to return owner UID of a userns Michael Kerrisk (man-pages)
  1 sibling, 0 replies; 4+ messages in thread
From: Michael Kerrisk (man-pages) @ 2016-12-23  9:54 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: mtk.manpages, Serge E. Hallyn, linux-api, linux-kernel,
	linux-fsdevel, Andrey Vagin, James Bottomley, W. Trevor King,
	Alexander Viro

Linux 4.9 added two ioctl() operations that can be used to discover:

* the parental relationships for hierarchical namespaces (user and PID)
  [NS_GET_PARENT]
* the user namespaces that owns a specified non-user-namespace
  [NS_GET_USERNS]

For no good reason that I can glean, NS_GET_USERNS was made synonymous
with NS_GET_PARENT for user namespaces. It might have been better if
NS_GET_USERNS had returned an error if the supplied file descriptor
referred to a user namespace, since it suggests that the caller may be
confused. More particularly, if it had generated an error, then I wouldn't
need the new ioctl() operation proposed here. (On the other hand, what
I propose here may be more generally useful.)

I would like to write code that discovers namespace relationships for
the purpose of understanding the namespace setup on a running system.
In particular, given a file descriptor (or pathname) for a namespace,
N, I'd like to obtain the corresponding user namespace.  Namespace N
might be a user namespace (in which case my code would just use N) or
a non-user namespace (in which case my code will use NS_GET_USERNS to
get the user namespace associated with N). The problem is that there
is no way to tell the difference by looking at the file descriptor
(and if I try to use NS_GET_USERNS on an N that is a user namespace, I
get the parent user namespace of N, which is not what I want).

This patch therefore adds a new ioctl(), NS_GET_NSTYPE, which, given
a file descriptor that refers to a user namespace, returns the
namespace type (one of the CLONE_NEW* constants).

Signed-off-by: Michael Kerrisk <mtk-manpages@gmail.com>
---
 fs/nsfs.c                 | 2 ++
 include/uapi/linux/nsfs.h | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/fs/nsfs.c b/fs/nsfs.c
index 8718af8..9f24b47 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -172,6 +172,8 @@ static long ns_ioctl(struct file *filp, unsigned int ioctl,
 		if (!ns->ops->get_parent)
 			return -EINVAL;
 		return open_related_ns(ns, ns->ops->get_parent);
+	case NS_GET_NSTYPE:
+		return ns->ops->type;
 	default:
 		return -ENOTTY;
 	}
diff --git a/include/uapi/linux/nsfs.h b/include/uapi/linux/nsfs.h
index 3af6172..2b48df1 100644
--- a/include/uapi/linux/nsfs.h
+++ b/include/uapi/linux/nsfs.h
@@ -9,5 +9,8 @@
 #define NS_GET_USERNS	_IO(NSIO, 0x1)
 /* Returns a file descriptor that refers to a parent namespace */
 #define NS_GET_PARENT	_IO(NSIO, 0x2)
+/* Returns the type of namespace (CLONE_NEW* value) referred to by
+   file descriptor */
+#define NS_GET_NSTYPE	_IO(NSIO, 0x3)
 
 #endif /* __LINUX_NSFS_H */
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v2 2/2] nsfs: Add an ioctl() to return owner UID of a userns
       [not found] <11b302a2-aac3-5994-a12d-e93ce64f7819@gmail.com>
  2016-12-23  9:54 ` [PATCH v2 1/2] nsfs: Add an ioctl() to return the namespace type Michael Kerrisk (man-pages)
@ 2016-12-23  9:54 ` Michael Kerrisk (man-pages)
  2016-12-24  1:16   ` Andrei Vagin
  1 sibling, 1 reply; 4+ messages in thread
From: Michael Kerrisk (man-pages) @ 2016-12-23  9:54 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: mtk.manpages, Serge E. Hallyn, linux-api, linux-kernel,
	linux-fsdevel, Andrey Vagin, James Bottomley, W. Trevor King,
	Alexander Viro

I'd like to write code that discovers the user namespace hierarchy on
a running system, and also shows who owns the various user namespaces.
Currently, there is no way of getting the owner UID of a user
namespace. Therefore, this patch adds an NS_GET_CREATOR_UID ioctl()
that fetches the (munged) UID of the creator of the user namespace
referred to by the specified file descriptor.

If the supplied file descriptor does not refer to a user namespace,
the operation fails with the error EINVAL.

Signed-off-by: Michael Kerrisk <mtk-manpages@gmail.com>

---
V2 changes:
* Renamed ioctl() from NS_CREATOR_UID to NS_OWNER_UID, at the
  suggestion of Eric Biederman.
* Make ioctl() return UID via buffer pointed to by argp. (Returning
  the UID via the result value could lead to problems since a large
  unsigned int UID might be misinterpreted as an error.) Thanks to
  Andrei Vagin for pointing this out.
---
 fs/nsfs.c                 | 11 +++++++++++
 include/uapi/linux/nsfs.h |  8 +++++---
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/fs/nsfs.c b/fs/nsfs.c
index 9f24b47..9c9277c 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -7,6 +7,7 @@
 #include <linux/seq_file.h>
 #include <linux/user_namespace.h>
 #include <linux/nsfs.h>
+#include <linux/uaccess.h>
 
 static struct vfsmount *nsfs_mnt;
 
@@ -163,7 +164,10 @@ static int open_related_ns(struct ns_common *ns,
 static long ns_ioctl(struct file *filp, unsigned int ioctl,
 			unsigned long arg)
 {
+	struct user_namespace *user_ns;
 	struct ns_common *ns = get_proc_ns(file_inode(filp));
+	unsigned int __user *argp;
+	unsigned int uid;
 
 	switch (ioctl) {
 	case NS_GET_USERNS:
@@ -174,6 +178,13 @@ static long ns_ioctl(struct file *filp, unsigned int ioctl,
 		return open_related_ns(ns, ns->ops->get_parent);
 	case NS_GET_NSTYPE:
 		return ns->ops->type;
+	case NS_GET_OWNER_UID:
+		if (ns->ops->type != CLONE_NEWUSER)
+			return -EINVAL;
+		user_ns = container_of(ns, struct user_namespace, ns);
+		argp = (unsigned int __user *) arg;
+		uid = from_kuid_munged(current_user_ns(), user_ns->owner);
+		return put_user(uid, argp);
 	default:
 		return -ENOTTY;
 	}
diff --git a/include/uapi/linux/nsfs.h b/include/uapi/linux/nsfs.h
index 2b48df1..c4a925e 100644
--- a/include/uapi/linux/nsfs.h
+++ b/include/uapi/linux/nsfs.h
@@ -6,11 +6,13 @@
 #define NSIO	0xb7
 
 /* Returns a file descriptor that refers to an owning user namespace */
-#define NS_GET_USERNS	_IO(NSIO, 0x1)
+#define NS_GET_USERNS		_IO(NSIO, 0x1)
 /* Returns a file descriptor that refers to a parent namespace */
-#define NS_GET_PARENT	_IO(NSIO, 0x2)
+#define NS_GET_PARENT		_IO(NSIO, 0x2)
 /* Returns the type of namespace (CLONE_NEW* value) referred to by
    file descriptor */
-#define NS_GET_NSTYPE	_IO(NSIO, 0x3)
+#define NS_GET_NSTYPE		_IO(NSIO, 0x3)
+/* Get owner UID for a user namespace */
+#define NS_GET_OWNER_UID	_IO(NSIO, 0x4)
 
 #endif /* __LINUX_NSFS_H */
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v2 2/2] nsfs: Add an ioctl() to return owner UID of a userns
  2016-12-23  9:54 ` [PATCH v2 2/2] nsfs: Add an ioctl() to return owner UID of a userns Michael Kerrisk (man-pages)
@ 2016-12-24  1:16   ` Andrei Vagin
  0 siblings, 0 replies; 4+ messages in thread
From: Andrei Vagin @ 2016-12-24  1:16 UTC (permalink / raw)
  To: Michael Kerrisk (man-pages)
  Cc: Eric W. Biederman, Serge E. Hallyn, linux-api, linux-kernel,
	linux-fsdevel, Andrey Vagin, James Bottomley, W. Trevor King,
	Alexander Viro

On Fri, Dec 23, 2016 at 10:54:53AM +0100, Michael Kerrisk (man-pages) wrote:
> I'd like to write code that discovers the user namespace hierarchy on
> a running system, and also shows who owns the various user namespaces.
> Currently, there is no way of getting the owner UID of a user
> namespace. Therefore, this patch adds an NS_GET_CREATOR_UID ioctl()
> that fetches the (munged) UID of the creator of the user namespace
> referred to by the specified file descriptor.
> 
> If the supplied file descriptor does not refer to a user namespace,
> the operation fails with the error EINVAL.
>

Acked-by: Andrey Vagin <avagin@openvz.org>

Here is one minor comment bellow

> Signed-off-by: Michael Kerrisk <mtk-manpages@gmail.com>
> 
> ---
> V2 changes:
> * Renamed ioctl() from NS_CREATOR_UID to NS_OWNER_UID, at the
>   suggestion of Eric Biederman.
> * Make ioctl() return UID via buffer pointed to by argp. (Returning
>   the UID via the result value could lead to problems since a large
>   unsigned int UID might be misinterpreted as an error.) Thanks to
>   Andrei Vagin for pointing this out.
> ---
>  fs/nsfs.c                 | 11 +++++++++++
>  include/uapi/linux/nsfs.h |  8 +++++---
>  2 files changed, 16 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/nsfs.c b/fs/nsfs.c
> index 9f24b47..9c9277c 100644
> --- a/fs/nsfs.c
> +++ b/fs/nsfs.c
> @@ -7,6 +7,7 @@
>  #include <linux/seq_file.h>
>  #include <linux/user_namespace.h>
>  #include <linux/nsfs.h>
> +#include <linux/uaccess.h>
>  
>  static struct vfsmount *nsfs_mnt;
>  
> @@ -163,7 +164,10 @@ static int open_related_ns(struct ns_common *ns,
>  static long ns_ioctl(struct file *filp, unsigned int ioctl,
>  			unsigned long arg)
>  {
> +	struct user_namespace *user_ns;
>  	struct ns_common *ns = get_proc_ns(file_inode(filp));
> +	unsigned int __user *argp;
> +	unsigned int uid;

I think it is better to use uid_t here

>  
>  	switch (ioctl) {
>  	case NS_GET_USERNS:
> @@ -174,6 +178,13 @@ static long ns_ioctl(struct file *filp, unsigned int ioctl,
>  		return open_related_ns(ns, ns->ops->get_parent);
>  	case NS_GET_NSTYPE:
>  		return ns->ops->type;
> +	case NS_GET_OWNER_UID:
> +		if (ns->ops->type != CLONE_NEWUSER)
> +			return -EINVAL;
> +		user_ns = container_of(ns, struct user_namespace, ns);
> +		argp = (unsigned int __user *) arg;
> +		uid = from_kuid_munged(current_user_ns(), user_ns->owner);
> +		return put_user(uid, argp);
>  	default:
>  		return -ENOTTY;
>  	}
> diff --git a/include/uapi/linux/nsfs.h b/include/uapi/linux/nsfs.h
> index 2b48df1..c4a925e 100644
> --- a/include/uapi/linux/nsfs.h
> +++ b/include/uapi/linux/nsfs.h
> @@ -6,11 +6,13 @@
>  #define NSIO	0xb7
>  
>  /* Returns a file descriptor that refers to an owning user namespace */
> -#define NS_GET_USERNS	_IO(NSIO, 0x1)
> +#define NS_GET_USERNS		_IO(NSIO, 0x1)
>  /* Returns a file descriptor that refers to a parent namespace */
> -#define NS_GET_PARENT	_IO(NSIO, 0x2)
> +#define NS_GET_PARENT		_IO(NSIO, 0x2)
>  /* Returns the type of namespace (CLONE_NEW* value) referred to by
>     file descriptor */
> -#define NS_GET_NSTYPE	_IO(NSIO, 0x3)
> +#define NS_GET_NSTYPE		_IO(NSIO, 0x3)
> +/* Get owner UID for a user namespace */
> +#define NS_GET_OWNER_UID	_IO(NSIO, 0x4)
>  
>  #endif /* __LINUX_NSFS_H */
> -- 
> 2.5.5
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2 2/2] nsfs: Add an ioctl() to return owner UID of a userns
@ 2017-01-05 15:36 Michael Kerrisk (man-pages)
  0 siblings, 0 replies; 4+ messages in thread
From: Michael Kerrisk (man-pages) @ 2017-01-05 15:36 UTC (permalink / raw)
  To: Andrei Vagin
  Cc: Eric W. Biederman, Serge E. Hallyn, Linux API, lkml,
	linux-fsdevel, Andrey Vagin, James Bottomley, W. Trevor King,
	Alexander Viro

Hello Andrei,

On 24 December 2016 at 14:16, Andrei Vagin <avagin@virtuozzo.com> wrote:
> On Fri, Dec 23, 2016 at 10:54:53AM +0100, Michael Kerrisk (man-pages) wrote:
>> I'd like to write code that discovers the user namespace hierarchy on
>> a running system, and also shows who owns the various user namespaces.
>> Currently, there is no way of getting the owner UID of a user
>> namespace. Therefore, this patch adds an NS_GET_CREATOR_UID ioctl()
>> that fetches the (munged) UID of the creator of the user namespace
>> referred to by the specified file descriptor.
>>
>> If the supplied file descriptor does not refer to a user namespace,
>> the operation fails with the error EINVAL.
>
> Acked-by: Andrey Vagin <avagin@openvz.org>

Thanks for looking the patches over.

> Here is one minor comment bellow
>
>> Signed-off-by: Michael Kerrisk <mtk-manpages@gmail.com>
>>
>> ---
>> V2 changes:
>> * Renamed ioctl() from NS_CREATOR_UID to NS_OWNER_UID, at the
>>   suggestion of Eric Biederman.
>> * Make ioctl() return UID via buffer pointed to by argp. (Returning
>>   the UID via the result value could lead to problems since a large
>>   unsigned int UID might be misinterpreted as an error.) Thanks to
>>   Andrei Vagin for pointing this out.
>> ---
>>  fs/nsfs.c                 | 11 +++++++++++
>>  include/uapi/linux/nsfs.h |  8 +++++---
>>  2 files changed, 16 insertions(+), 3 deletions(-)
>>
>> diff --git a/fs/nsfs.c b/fs/nsfs.c
>> index 9f24b47..9c9277c 100644
>> --- a/fs/nsfs.c
>> +++ b/fs/nsfs.c
>> @@ -7,6 +7,7 @@
>>  #include <linux/seq_file.h>
>>  #include <linux/user_namespace.h>
>>  #include <linux/nsfs.h>
>> +#include <linux/uaccess.h>
>>
>>  static struct vfsmount *nsfs_mnt;
>>
>> @@ -163,7 +164,10 @@ static int open_related_ns(struct ns_common *ns,
>>  static long ns_ioctl(struct file *filp, unsigned int ioctl,
>>                       unsigned long arg)
>>  {
>> +     struct user_namespace *user_ns;
>>       struct ns_common *ns = get_proc_ns(file_inode(filp));
>> +     unsigned int __user *argp;
>> +     unsigned int uid;
>
> I think it is better to use uid_t here

Fair enough.

Should in fact the type for the ioctl() argument be changed? I mean,
make the following change to the line before:

-       unsigned int __user *argp;
+       uid_t __user *argp;

And further below, change:

-             argp = (unsigned int __user *) arg;
+             argp = (uid_t __user *) arg;

?

Happy New Year!

Cheers,

Michael

>>       switch (ioctl) {
>>       case NS_GET_USERNS:
>> @@ -174,6 +178,13 @@ static long ns_ioctl(struct file *filp, unsigned int ioctl,
>>               return open_related_ns(ns, ns->ops->get_parent);
>>       case NS_GET_NSTYPE:
>>               return ns->ops->type;
>> +     case NS_GET_OWNER_UID:
>> +             if (ns->ops->type != CLONE_NEWUSER)
>> +                     return -EINVAL;
>> +             user_ns = container_of(ns, struct user_namespace, ns);
>> +             argp = (unsigned int __user *) arg;
>> +             uid = from_kuid_munged(current_user_ns(), user_ns->owner);
>> +             return put_user(uid, argp);
>>       default:
>>               return -ENOTTY;
>>       }
>> diff --git a/include/uapi/linux/nsfs.h b/include/uapi/linux/nsfs.h
>> index 2b48df1..c4a925e 100644
>> --- a/include/uapi/linux/nsfs.h
>> +++ b/include/uapi/linux/nsfs.h
>> @@ -6,11 +6,13 @@
>>  #define NSIO 0xb7
>>
>>  /* Returns a file descriptor that refers to an owning user namespace */
>> -#define NS_GET_USERNS        _IO(NSIO, 0x1)
>> +#define NS_GET_USERNS                _IO(NSIO, 0x1)
>>  /* Returns a file descriptor that refers to a parent namespace */
>> -#define NS_GET_PARENT        _IO(NSIO, 0x2)
>> +#define NS_GET_PARENT                _IO(NSIO, 0x2)
>>  /* Returns the type of namespace (CLONE_NEW* value) referred to by
>>     file descriptor */
>> -#define NS_GET_NSTYPE        _IO(NSIO, 0x3)
>> +#define NS_GET_NSTYPE                _IO(NSIO, 0x3)
>> +/* Get owner UID for a user namespace */
>> +#define NS_GET_OWNER_UID     _IO(NSIO, 0x4)
>>
>>  #endif /* __LINUX_NSFS_H */
>> --
>> 2.5.5
>>



-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2017-01-05 15:37 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <11b302a2-aac3-5994-a12d-e93ce64f7819@gmail.com>
2016-12-23  9:54 ` [PATCH v2 1/2] nsfs: Add an ioctl() to return the namespace type Michael Kerrisk (man-pages)
2016-12-23  9:54 ` [PATCH v2 2/2] nsfs: Add an ioctl() to return owner UID of a userns Michael Kerrisk (man-pages)
2016-12-24  1:16   ` Andrei Vagin
2017-01-05 15:36 Michael Kerrisk (man-pages)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).