nsfs: Add an ioctl() to return creator UID of a userns

Started by Michael Kerrisk (man-pages) on Dec 19, 2016 · 3 messages from 2 authors · Last reply Dec 22, 2016

Subsystems (2)

Maintainers (3)

STALE3611d

open the first message on its own page

Message details and related content
# Some open questions about this patch below.
#
One of the rules regarding capabilities is:

    A process that resides in the parent of the user namespace and
    whose effective user ID matches the owner of the namespace has
    all capabilities in the namespace.

Therefore, in order to write code that discovers whether process X has
capabilities in namespace Y, we need a way to find out who the creator
of a user namespace is. This patch adds an NS_GET_CREATOR_UID ioctl()
that returns 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 <redacted>
---
 fs/nsfs.c                 | 6 ++++++
 include/uapi/linux/nsfs.h | 8 +++++---
 2 files changed, 11 insertions(+), 3 deletions(-)

Open questions:

* Would it be preferabe to separate the logic for NS_GET_CREATOR_UID
  into a small helper function?
* Is this a correct use of container_of()? I did not immediately
  see another way to get to the user_namespace struct, but I
  may well have missed something.
diff --git a/fs/nsfs.c b/fs/nsfs.c
index 5d53476..26f6d94 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -163,6 +163,7 @@ 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));
 
 	switch (ioctl) {
@@ -174,6 +175,11 @@ 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_CREATOR_UID:
+		if (ns->ops->type != CLONE_NEWUSER)
+			return -EINVAL;
+		user_ns = container_of(ns, struct user_namespace, ns);
+		return from_kuid_munged(current_user_ns(), user_ns->owner);
 	default:
 		return -ENOTTY;
 	}
diff --git a/include/uapi/linux/nsfs.h b/include/uapi/linux/nsfs.h
index 2b48df1..b3c6c78 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 creator UID for a user namespace */
+#define NS_GET_CREATOR_UID	_IO(NSIO, 0x4)
 
 #endif /* __LINUX_NSFS_H */
-- 
2.5.5
Message details and related content
On Mon, Dec 19, 2016 at 03:38:35PM +0100, Michael Kerrisk (man-pages) wrote:
quoted hunk
# Some open questions about this patch below.
#
One of the rules regarding capabilities is:

    A process that resides in the parent of the user namespace and
    whose effective user ID matches the owner of the namespace has
    all capabilities in the namespace.

Therefore, in order to write code that discovers whether process X has
capabilities in namespace Y, we need a way to find out who the creator
of a user namespace is. This patch adds an NS_GET_CREATOR_UID ioctl()
that returns 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 <redacted>
---
 fs/nsfs.c                 | 6 ++++++
 include/uapi/linux/nsfs.h | 8 +++++---
 2 files changed, 11 insertions(+), 3 deletions(-)

Open questions:

* Would it be preferabe to separate the logic for NS_GET_CREATOR_UID
  into a small helper function?
* Is this a correct use of container_of()? I did not immediately
  see another way to get to the user_namespace struct, but I
  may well have missed something.
diff --git a/fs/nsfs.c b/fs/nsfs.c
index 5d53476..26f6d94 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -163,6 +163,7 @@ 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;

12 more quoted lines

uid_t is "unsigned int", ioctl() returns long, so it may be hard to
distinguish user id-s from errors on x32.

off-topic: What is about user_ns->group? I can't find where it is used...
quoted hunk
 	default:
 		return -ENOTTY;
 	}
diff --git a/include/uapi/linux/nsfs.h b/include/uapi/linux/nsfs.h
index 2b48df1..b3c6c78 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 creator UID for a user namespace */
+#define NS_GET_CREATOR_UID	_IO(NSIO, 0x4)
 
 #endif /* __LINUX_NSFS_H */
-- 
2.5.5
Message details and related content
Hi Andrei,

On 12/21/2016 04:13 AM, Andrei Vagin wrote:
On Mon, Dec 19, 2016 at 03:38:35PM +0100, Michael Kerrisk (man-pages) wrote:
quoted
# Some open questions about this patch below.
#
One of the rules regarding capabilities is:

    A process that resides in the parent of the user namespace and
    whose effective user ID matches the owner of the namespace has
    all capabilities in the namespace.

Therefore, in order to write code that discovers whether process X has
capabilities in namespace Y, we need a way to find out who the creator
of a user namespace is. This patch adds an NS_GET_CREATOR_UID ioctl()
that returns 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 <redacted>
---
 fs/nsfs.c                 | 6 ++++++
 include/uapi/linux/nsfs.h | 8 +++++---
 2 files changed, 11 insertions(+), 3 deletions(-)

Open questions:

* Would it be preferabe to separate the logic for NS_GET_CREATOR_UID
  into a small helper function?
* Is this a correct use of container_of()? I did not immediately
  see another way to get to the user_namespace struct, but I
  may well have missed something.
diff --git a/fs/nsfs.c b/fs/nsfs.c
index 5d53476..26f6d94 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -163,6 +163,7 @@ int open_related_ns(struct ns_common *ns,
 static long ns_ioctl(struct file *filp, unsigned int ioctl,
 			unsigned long arg)
 {

16 more quoted lines

Good point. So, we could instead return the UID via a buffer pointed to 
by the ioctl() arg. That would seem better, right?
off-topic: What is about user_ns->group? I can't find where it is used...
I've no idea. Like you, I can't see any place where it's being used.

Cheers,

Michael

quoted
 	default:
 		return -ENOTTY;
 	}
diff --git a/include/uapi/linux/nsfs.h b/include/uapi/linux/nsfs.h
index 2b48df1..b3c6c78 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 creator UID for a user namespace */
+#define NS_GET_CREATOR_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/
Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help