linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/2] Add further ioctl() operations for namespace discovery
@ 2016-12-23  9:54 Michael Kerrisk (man-pages)
  2017-01-24 21:34 ` Michael Kerrisk (man-pages)
                   ` (2 more replies)
  0 siblings, 3 replies; 15+ 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 would like to write code that discovers the nmaespace setup on a live
system.  The NS_GET_PARENT and NS_GET_USERNS ioctl() operations added in
Linux 4.9 provide much of what I want, but there are still a couple of
small pieces missing. Those pieces are added with this patch series.

Here's an example program that makes use of the new ioctl() operations.

8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---
/* ns_capable.c

   (C) 2016 Michael Kerrisk, <mtk.manpages@gmail.com>

   Licensed under the GNU General Public License v2 or later.

   Test whether a process (identified by PID) might (subject to LSM checks)
   have capabilities in a namespace (identified by a /proc/PID/ns/xxx file).
*/
#define _GNU_SOURCE
#include <sched.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <limits.h>
#include <sys/capability.h>

#ifndef NS_GET_USERNS
#define NSIO    0xb7
#define NS_GET_USERNS		_IO(NSIO, 0x1)
#define NS_GET_PARENT		_IO(NSIO, 0x2)
#define NS_GET_NSTYPE		_IO(NSIO, 0x3)
#define NS_GET_OWNER_UID	_IO(NSIO, 0x4)
#endif

#define errExit(msg) 	do { perror(msg); exit(EXIT_FAILURE); \
			} while (0)

#define fatal(msg) 	do { fprintf(stderr, "%s\n", msg); \
     			     exit(EXIT_FAILURE); } while (0)

/* Display capabilities sets of process with specified PID */

static void
show_cap(pid_t pid)
{
    cap_t caps;
    char *cap_string;

    caps = cap_get_pid(pid);
    if (caps == NULL)
	errExit("cap_get_proc");

    cap_string = cap_to_text(caps, NULL);
    if (cap_string == NULL)
	errExit("cap_to_text");

    printf("Capabilities: %s\n", cap_string);
}

/* Obtain the effective UID pf the process 'pid' by
   scanning its /proc/PID/file */

static uid_t
get_euid_of_process(pid_t pid)
{
    char path[PATH_MAX];
    char line[1024];
    int uid;

    snprintf(path, sizeof(path), "/proc/%ld/status", (long) pid);

    FILE *fp;
    fp = fopen(path, "r");
    if (fp == NULL)
	errExit("fopen-/proc/PID/status");

    for (;;) {
	if (fgets(line, sizeof(line), fp) == NULL) {

	    /* Should never happen... */

	    fprintf(stderr, "Failure scanning %s\n", path);
	    exit(EXIT_FAILURE);
	}

	if (strstr(line, "Uid:") == line) {
	    sscanf(line, "Uid: %*d %d %*d %*d", &uid);
	    return uid;
	}
    }
}

int
main(int argc, char *argv[])
{
    int ns_fd, userns_fd, pid_userns_fd;
    int nstype;
    int next_fd;
    struct stat pid_stat;
    struct stat target_stat;
    char *pid_str;
    pid_t pid;
    char path[PATH_MAX];

    if (argc < 2) {
	fprintf(stderr, "Usage: %s PID [ns-file]\n", argv[0]);
	fprintf(stderr, "\t'ns-file' is a /proc/PID/ns/xxxx file; "
		        "if omitted, use the namespace\n"
			"\treferred to by standard input "
			"(file descriptor 0)\n");
	exit(EXIT_FAILURE);
    }

    pid_str = argv[1];
    pid = atoi(pid_str);

    if (argc <= 2) {
	ns_fd = STDIN_FILENO;
    } else {
        ns_fd = open(argv[2], O_RDONLY);
        if (ns_fd == -1)
	    errExit("open-ns-file");
    }

    /* Get the relevant user namespace FD, which is 'ns_fd' if 'ns_fd' refers
       to a user namespace, otherwise the user namespace that owns 'ns_fd' */

    nstype = ioctl(ns_fd, NS_GET_NSTYPE);
    if (nstype == -1)
	errExit("ioctl-NS_GET_NSTYPE");

    if (nstype == CLONE_NEWUSER) {
	userns_fd = ns_fd;
    } else {
	userns_fd = ioctl(ns_fd, NS_GET_USERNS);
        if (userns_fd == -1)
	    errExit("ioctl-NS_GET_USERNS");
    }

    /* Obtain 'stat' info for the user namespace of the specified PID */

    snprintf(path, sizeof(path), "/proc/%s/ns/user", pid_str);

    pid_userns_fd = open(path, O_RDONLY);
    if (pid_userns_fd == -1)
	errExit("open-PID");

    if (fstat(pid_userns_fd, &pid_stat) == -1)
	errExit("fstat-PID");

    /* Get 'stat' info for the target user namesapce */

    if (fstat(userns_fd, &target_stat) == -1)
	errExit("fstat-PID");

    /* If the PID is in the target user namespace, then it has
       whatever capabilities are in its sets. */

    if (pid_stat.st_dev == target_stat.st_dev &&
		pid_stat.st_ino == target_stat.st_ino) {
        printf("PID is in target namespace\n");
	printf("Subject to LSM checks, it has the following capabilities\n");

	show_cap(pid);

	exit(EXIT_SUCCESS);
    }

    /* Otherwise, we need to walk through the ancestors of the target
       user namespace to see if PID is in an ancestor namespace */

    for (;;) {
	int f;

	next_fd = ioctl(userns_fd, NS_GET_PARENT);

	if (next_fd == -1) {
	    
	    /* The error here should be EPERM... */

	    if (errno != EPERM)
	        errExit("ioctl-NS_GET_PARENT");

	    printf("PID is not in an ancestor namespace\n");
	    printf("It has no capabilities in the target namespace\n");

	    exit(EXIT_SUCCESS);
	}

        if (fstat(next_fd, &target_stat) == -1)
	    errExit("fstat-PID");

	/* If the 'stat' info for this user namespace matches the 'stat'
	 * info for 'next_fd', then the PID is in an ancestor namespace */

        if (pid_stat.st_dev == target_stat.st_dev &&
		    pid_stat.st_ino == target_stat.st_ino)
	    break;

	/* Next time round, get the next parent */

	f = userns_fd;
	userns_fd = next_fd;
	close(f);
    }

    /* At this point, we found that PID is in an ancestor of the target
       user namespace, and 'userns_fd' refers to the immediate descendant
       user namespace of PID in the chain of user namespaces from PID to
       the target user namespace. If the effective UID of PID matches the
       owner UID of descendant user namespace, then PID has all
       capabilities in the descendant namespace(s); otherwise, it just has
       the capabilities that are in its sets. */

    uid_t owner_uid, uid;
    if (ioctl(userns_fd, NS_GET_OWNER_UID, &owner_uid) == -1) {
	perror("ioctl-NS_GET_OWNER_UID");
	exit(EXIT_FAILURE);
    }

    uid = get_euid_of_process(pid);

    printf("PID is in an ancestor namespace\n");
    if (owner_uid == uid) {
	printf("And its effective UID matches the owner "
		"of the namespace\n");
	printf("Subject to LSM checks, PID has all capabilities in "
		"that namespace!\n");
    } else {
	printf("But its effective UID does not match the owner "
		"of the namespace\n");
	printf("Subject to LSM checks, it has the following capabilities\n");
	show_cap(pid);
    }

    exit(EXIT_SUCCESS);
}
8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---

Michael Kerrisk (2):
  nsfs: Add an ioctl() to return the namespace type
  nsfs: Add an ioctl() to return owner UID of a userns

 fs/nsfs.c                 | 13 +++++++++++++
 include/uapi/linux/nsfs.h |  9 +++++++--
 2 files changed, 20 insertions(+), 2 deletions(-)

-- 
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] 15+ messages in thread

* Re: [PATCH v2 0/2] Add further ioctl() operations for namespace discovery
  2016-12-23  9:54 [PATCH v2 0/2] Add further ioctl() operations for namespace discovery Michael Kerrisk (man-pages)
@ 2017-01-24 21:34 ` Michael Kerrisk (man-pages)
  2017-01-24 22:41   ` Eric W. Biederman
  2017-01-25  1:03 ` [PATCH v4 " Michael Kerrisk (man-pages)
       [not found] ` <2c27a76e-336d-e2ad-4b30-22e29249c2e9@gmail.com>
  2 siblings, 1 reply; 15+ messages in thread
From: Michael Kerrisk (man-pages) @ 2017-01-24 21:34 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Michael Kerrisk, Serge E. Hallyn, Linux API, lkml, linux-fsdevel,
	Andrey Vagin, James Bottomley, W. Trevor King, Alexander Viro

Hi Eric,

Do you have any input for this small patch set? I've still to tweak a
comment as suggested by Trevor King, but otherwise I'd like to know if
this is good to go for the next merge window.

Cheers,

Michael


On 23 December 2016 at 22:54, Michael Kerrisk (man-pages)
<mtk.manpages@gmail.com> wrote:
> I would like to write code that discovers the nmaespace setup on a live
> system.  The NS_GET_PARENT and NS_GET_USERNS ioctl() operations added in
> Linux 4.9 provide much of what I want, but there are still a couple of
> small pieces missing. Those pieces are added with this patch series.
>
> Here's an example program that makes use of the new ioctl() operations.
>
> 8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---
> /* ns_capable.c
>
>    (C) 2016 Michael Kerrisk, <mtk.manpages@gmail.com>
>
>    Licensed under the GNU General Public License v2 or later.
>
>    Test whether a process (identified by PID) might (subject to LSM checks)
>    have capabilities in a namespace (identified by a /proc/PID/ns/xxx file).
> */
> #define _GNU_SOURCE
> #include <sched.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <stdio.h>
> #include <errno.h>
> #include <fcntl.h>
> #include <string.h>
> #include <sys/stat.h>
> #include <sys/ioctl.h>
> #include <limits.h>
> #include <sys/capability.h>
>
> #ifndef NS_GET_USERNS
> #define NSIO    0xb7
> #define NS_GET_USERNS           _IO(NSIO, 0x1)
> #define NS_GET_PARENT           _IO(NSIO, 0x2)
> #define NS_GET_NSTYPE           _IO(NSIO, 0x3)
> #define NS_GET_OWNER_UID        _IO(NSIO, 0x4)
> #endif
>
> #define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \
>                         } while (0)
>
> #define fatal(msg)      do { fprintf(stderr, "%s\n", msg); \
>                              exit(EXIT_FAILURE); } while (0)
>
> /* Display capabilities sets of process with specified PID */
>
> static void
> show_cap(pid_t pid)
> {
>     cap_t caps;
>     char *cap_string;
>
>     caps = cap_get_pid(pid);
>     if (caps == NULL)
>         errExit("cap_get_proc");
>
>     cap_string = cap_to_text(caps, NULL);
>     if (cap_string == NULL)
>         errExit("cap_to_text");
>
>     printf("Capabilities: %s\n", cap_string);
> }
>
> /* Obtain the effective UID pf the process 'pid' by
>    scanning its /proc/PID/file */
>
> static uid_t
> get_euid_of_process(pid_t pid)
> {
>     char path[PATH_MAX];
>     char line[1024];
>     int uid;
>
>     snprintf(path, sizeof(path), "/proc/%ld/status", (long) pid);
>
>     FILE *fp;
>     fp = fopen(path, "r");
>     if (fp == NULL)
>         errExit("fopen-/proc/PID/status");
>
>     for (;;) {
>         if (fgets(line, sizeof(line), fp) == NULL) {
>
>             /* Should never happen... */
>
>             fprintf(stderr, "Failure scanning %s\n", path);
>             exit(EXIT_FAILURE);
>         }
>
>         if (strstr(line, "Uid:") == line) {
>             sscanf(line, "Uid: %*d %d %*d %*d", &uid);
>             return uid;
>         }
>     }
> }
>
> int
> main(int argc, char *argv[])
> {
>     int ns_fd, userns_fd, pid_userns_fd;
>     int nstype;
>     int next_fd;
>     struct stat pid_stat;
>     struct stat target_stat;
>     char *pid_str;
>     pid_t pid;
>     char path[PATH_MAX];
>
>     if (argc < 2) {
>         fprintf(stderr, "Usage: %s PID [ns-file]\n", argv[0]);
>         fprintf(stderr, "\t'ns-file' is a /proc/PID/ns/xxxx file; "
>                         "if omitted, use the namespace\n"
>                         "\treferred to by standard input "
>                         "(file descriptor 0)\n");
>         exit(EXIT_FAILURE);
>     }
>
>     pid_str = argv[1];
>     pid = atoi(pid_str);
>
>     if (argc <= 2) {
>         ns_fd = STDIN_FILENO;
>     } else {
>         ns_fd = open(argv[2], O_RDONLY);
>         if (ns_fd == -1)
>             errExit("open-ns-file");
>     }
>
>     /* Get the relevant user namespace FD, which is 'ns_fd' if 'ns_fd' refers
>        to a user namespace, otherwise the user namespace that owns 'ns_fd' */
>
>     nstype = ioctl(ns_fd, NS_GET_NSTYPE);
>     if (nstype == -1)
>         errExit("ioctl-NS_GET_NSTYPE");
>
>     if (nstype == CLONE_NEWUSER) {
>         userns_fd = ns_fd;
>     } else {
>         userns_fd = ioctl(ns_fd, NS_GET_USERNS);
>         if (userns_fd == -1)
>             errExit("ioctl-NS_GET_USERNS");
>     }
>
>     /* Obtain 'stat' info for the user namespace of the specified PID */
>
>     snprintf(path, sizeof(path), "/proc/%s/ns/user", pid_str);
>
>     pid_userns_fd = open(path, O_RDONLY);
>     if (pid_userns_fd == -1)
>         errExit("open-PID");
>
>     if (fstat(pid_userns_fd, &pid_stat) == -1)
>         errExit("fstat-PID");
>
>     /* Get 'stat' info for the target user namesapce */
>
>     if (fstat(userns_fd, &target_stat) == -1)
>         errExit("fstat-PID");
>
>     /* If the PID is in the target user namespace, then it has
>        whatever capabilities are in its sets. */
>
>     if (pid_stat.st_dev == target_stat.st_dev &&
>                 pid_stat.st_ino == target_stat.st_ino) {
>         printf("PID is in target namespace\n");
>         printf("Subject to LSM checks, it has the following capabilities\n");
>
>         show_cap(pid);
>
>         exit(EXIT_SUCCESS);
>     }
>
>     /* Otherwise, we need to walk through the ancestors of the target
>        user namespace to see if PID is in an ancestor namespace */
>
>     for (;;) {
>         int f;
>
>         next_fd = ioctl(userns_fd, NS_GET_PARENT);
>
>         if (next_fd == -1) {
>
>             /* The error here should be EPERM... */
>
>             if (errno != EPERM)
>                 errExit("ioctl-NS_GET_PARENT");
>
>             printf("PID is not in an ancestor namespace\n");
>             printf("It has no capabilities in the target namespace\n");
>
>             exit(EXIT_SUCCESS);
>         }
>
>         if (fstat(next_fd, &target_stat) == -1)
>             errExit("fstat-PID");
>
>         /* If the 'stat' info for this user namespace matches the 'stat'
>          * info for 'next_fd', then the PID is in an ancestor namespace */
>
>         if (pid_stat.st_dev == target_stat.st_dev &&
>                     pid_stat.st_ino == target_stat.st_ino)
>             break;
>
>         /* Next time round, get the next parent */
>
>         f = userns_fd;
>         userns_fd = next_fd;
>         close(f);
>     }
>
>     /* At this point, we found that PID is in an ancestor of the target
>        user namespace, and 'userns_fd' refers to the immediate descendant
>        user namespace of PID in the chain of user namespaces from PID to
>        the target user namespace. If the effective UID of PID matches the
>        owner UID of descendant user namespace, then PID has all
>        capabilities in the descendant namespace(s); otherwise, it just has
>        the capabilities that are in its sets. */
>
>     uid_t owner_uid, uid;
>     if (ioctl(userns_fd, NS_GET_OWNER_UID, &owner_uid) == -1) {
>         perror("ioctl-NS_GET_OWNER_UID");
>         exit(EXIT_FAILURE);
>     }
>
>     uid = get_euid_of_process(pid);
>
>     printf("PID is in an ancestor namespace\n");
>     if (owner_uid == uid) {
>         printf("And its effective UID matches the owner "
>                 "of the namespace\n");
>         printf("Subject to LSM checks, PID has all capabilities in "
>                 "that namespace!\n");
>     } else {
>         printf("But its effective UID does not match the owner "
>                 "of the namespace\n");
>         printf("Subject to LSM checks, it has the following capabilities\n");
>         show_cap(pid);
>     }
>
>     exit(EXIT_SUCCESS);
> }
> 8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---
>
> Michael Kerrisk (2):
>   nsfs: Add an ioctl() to return the namespace type
>   nsfs: Add an ioctl() to return owner UID of a userns
>
>  fs/nsfs.c                 | 13 +++++++++++++
>  include/uapi/linux/nsfs.h |  9 +++++++--
>  2 files changed, 20 insertions(+), 2 deletions(-)
>
> --
> 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/



-- 
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] 15+ messages in thread

* Re: [PATCH v2 0/2] Add further ioctl() operations for namespace discovery
  2017-01-24 21:34 ` Michael Kerrisk (man-pages)
@ 2017-01-24 22:41   ` Eric W. Biederman
  2017-01-25  0:39     ` Michael Kerrisk (man-pages)
  0 siblings, 1 reply; 15+ messages in thread
From: Eric W. Biederman @ 2017-01-24 22:41 UTC (permalink / raw)
  To: Michael Kerrisk (man-pages)
  Cc: Serge E. Hallyn, Linux API, lkml, linux-fsdevel, Andrey Vagin,
	James Bottomley, W. Trevor King, Alexander Viro

"Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> writes:

> Hi Eric,
>
> Do you have any input for this small patch set? I've still to tweak a
> comment as suggested by Trevor King, but otherwise I'd like to know if
> this is good to go for the next merge window.

Apologies I have been bogged down with other things.  Basically the
code looks fine, and now that I have caught up with things I will be
happy to merge your for the next merge window.

I do wonder if returning -EOVERFLOW may be more useful than running
the overflow_uid when mapping fails.

Also, now that I think about it.  Please let's use (uid_t __user *) for
the type of argp.  I think that will be more maintainable in the long
run.  Easier to grep for etc.

Neither of these things are big or would prevent me from merging your
change just things that I think would be nice to have.

Eric

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

* Re: [PATCH v2 0/2] Add further ioctl() operations for namespace discovery
  2017-01-24 22:41   ` Eric W. Biederman
@ 2017-01-25  0:39     ` Michael Kerrisk (man-pages)
  0 siblings, 0 replies; 15+ messages in thread
From: Michael Kerrisk (man-pages) @ 2017-01-25  0:39 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: mtk.manpages, Serge E. Hallyn, Linux API, lkml, linux-fsdevel,
	Andrey Vagin, James Bottomley, W. Trevor King, Alexander Viro

Hello Eric,

On 01/25/2017 11:41 AM, Eric W. Biederman wrote:
> "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> writes:
> 
>> Hi Eric,
>>
>> Do you have any input for this small patch set? I've still to tweak a
>> comment as suggested by Trevor King, but otherwise I'd like to know if
>> this is good to go for the next merge window.
> 
> Apologies I have been bogged down with other things.  Basically the
> code looks fine, and now that I have caught up with things I will be
> happy to merge your for the next merge window.

Thanks.

> I do wonder if returning -EOVERFLOW may be more useful than running
> the overflow_uid when mapping fails.

Yes, it I think you're right. I'll fix that.

> Also, now that I think about it.  Please let's use (uid_t __user *) for
> the type of argp.  I think that will be more maintainable in the long
> run.  Easier to grep for etc.

Yes, I'll make that change.

> Neither of these things are big or would prevent me from merging your
> change just things that I think would be nice to have.

Both seem worth having to me.

Cheers,

Michael


-- 
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] 15+ messages in thread

* [PATCH v4 0/2] Add further ioctl() operations for namespace discovery
  2016-12-23  9:54 [PATCH v2 0/2] Add further ioctl() operations for namespace discovery Michael Kerrisk (man-pages)
  2017-01-24 21:34 ` Michael Kerrisk (man-pages)
@ 2017-01-25  1:03 ` Michael Kerrisk (man-pages)
  2017-01-25  1:58   ` Eric W. Biederman
       [not found] ` <2c27a76e-336d-e2ad-4b30-22e29249c2e9@gmail.com>
  2 siblings, 1 reply; 15+ messages in thread
From: Michael Kerrisk (man-pages) @ 2017-01-25  1:03 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 would like to write code that discovers the namespace setup on a live
system.  The NS_GET_PARENT and NS_GET_USERNS ioctl() operations added in
Linux 4.9 provide much of what I want, but there are still a couple of
small pieces missing. Those pieces are added with this patch series.

Here's an example program that makes use of the new ioctl() operations.

8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---
/* ns_capable.c

   (C) 2016 Michael Kerrisk, <mtk.manpages@gmail.com>

   Licensed under the GNU General Public License v2 or later.

   Test whether a process (identified by PID) might (subject to LSM checks)
   have capabilities in a namespace (identified by a /proc/PID/ns/xxx file).
*/
#define _GNU_SOURCE
#include <sched.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <limits.h>
#include <sys/capability.h>

#ifndef NS_GET_USERNS
#define NSIO    0xb7
#define NS_GET_USERNS		_IO(NSIO, 0x1)
#define NS_GET_PARENT		_IO(NSIO, 0x2)
#define NS_GET_NSTYPE		_IO(NSIO, 0x3)
#define NS_GET_OWNER_UID	_IO(NSIO, 0x4)
#endif

#define errExit(msg) 	do { perror(msg); exit(EXIT_FAILURE); \
			} while (0)

#define fatal(msg) 	do { fprintf(stderr, "%s\n", msg); \
     			     exit(EXIT_FAILURE); } while (0)

/* Display capabilities sets of process with specified PID */

static void
show_cap(pid_t pid)
{
    cap_t caps;
    char *cap_string;

    caps = cap_get_pid(pid);
    if (caps == NULL)
	errExit("cap_get_proc");

    cap_string = cap_to_text(caps, NULL);
    if (cap_string == NULL)
	errExit("cap_to_text");

    printf("Capabilities: %s\n", cap_string);
}

/* Obtain the effective UID pf the process 'pid' by
   scanning its /proc/PID/file */

static uid_t
get_euid_of_process(pid_t pid)
{
    char path[PATH_MAX];
    char line[1024];
    int uid;

    snprintf(path, sizeof(path), "/proc/%ld/status", (long) pid);

    FILE *fp;
    fp = fopen(path, "r");
    if (fp == NULL)
	errExit("fopen-/proc/PID/status");

    for (;;) {
	if (fgets(line, sizeof(line), fp) == NULL) {

	    /* Should never happen... */

	    fprintf(stderr, "Failure scanning %s\n", path);
	    exit(EXIT_FAILURE);
	}

	if (strstr(line, "Uid:") == line) {
	    sscanf(line, "Uid: %*d %d %*d %*d", &uid);
	    return uid;
	}
    }
}

int
main(int argc, char *argv[])
{
    int ns_fd, userns_fd, pid_userns_fd;
    int nstype;
    int next_fd;
    struct stat pid_stat;
    struct stat target_stat;
    char *pid_str;
    pid_t pid;
    char path[PATH_MAX];

    if (argc < 2) {
	fprintf(stderr, "Usage: %s PID [ns-file]\n", argv[0]);
	fprintf(stderr, "\t'ns-file' is a /proc/PID/ns/xxxx file; "
		        "if omitted, use the namespace\n"
			"\treferred to by standard input "
			"(file descriptor 0)\n");
	exit(EXIT_FAILURE);
    }

    pid_str = argv[1];
    pid = atoi(pid_str);

    if (argc <= 2) {
	ns_fd = STDIN_FILENO;
    } else {
        ns_fd = open(argv[2], O_RDONLY);
        if (ns_fd == -1)
	    errExit("open-ns-file");
    }

    /* Get the relevant user namespace FD, which is 'ns_fd' if 'ns_fd' refers
       to a user namespace, otherwise the user namespace that owns 'ns_fd' */

    nstype = ioctl(ns_fd, NS_GET_NSTYPE);
    if (nstype == -1)
	errExit("ioctl-NS_GET_NSTYPE");

    if (nstype == CLONE_NEWUSER) {
	userns_fd = ns_fd;
    } else {
	userns_fd = ioctl(ns_fd, NS_GET_USERNS);
        if (userns_fd == -1)
	    errExit("ioctl-NS_GET_USERNS");
    }

    /* Obtain 'stat' info for the user namespace of the specified PID */

    snprintf(path, sizeof(path), "/proc/%s/ns/user", pid_str);

    pid_userns_fd = open(path, O_RDONLY);
    if (pid_userns_fd == -1)
	errExit("open-PID");

    if (fstat(pid_userns_fd, &pid_stat) == -1)
	errExit("fstat-PID");

    /* Get 'stat' info for the target user namesapce */

    if (fstat(userns_fd, &target_stat) == -1)
	errExit("fstat-PID");

    /* If the PID is in the target user namespace, then it has
       whatever capabilities are in its sets. */

    if (pid_stat.st_dev == target_stat.st_dev &&
		pid_stat.st_ino == target_stat.st_ino) {
        printf("PID is in target namespace\n");
	printf("Subject to LSM checks, it has the following capabilities\n");

	show_cap(pid);

	exit(EXIT_SUCCESS);
    }

    /* Otherwise, we need to walk through the ancestors of the target
       user namespace to see if PID is in an ancestor namespace */

    for (;;) {
	int f;

	next_fd = ioctl(userns_fd, NS_GET_PARENT);

	if (next_fd == -1) {
	    
	    /* The error here should be EPERM... */

	    if (errno != EPERM)
	        errExit("ioctl-NS_GET_PARENT");

	    printf("PID is not in an ancestor namespace\n");
	    printf("It has no capabilities in the target namespace\n");

	    exit(EXIT_SUCCESS);
	}

        if (fstat(next_fd, &target_stat) == -1)
	    errExit("fstat-PID");

	/* If the 'stat' info for this user namespace matches the 'stat'
	 * info for 'next_fd', then the PID is in an ancestor namespace */

        if (pid_stat.st_dev == target_stat.st_dev &&
		    pid_stat.st_ino == target_stat.st_ino)
	    break;

	/* Next time round, get the next parent */

	f = userns_fd;
	userns_fd = next_fd;
	close(f);
    }

    /* At this point, we found that PID is in an ancestor of the target
       user namespace, and 'userns_fd' refers to the immediate descendant
       user namespace of PID in the chain of user namespaces from PID to
       the target user namespace. If the effective UID of PID matches the
       owner UID of descendant user namespace, then PID has all
       capabilities in the descendant namespace(s); otherwise, it just has
       the capabilities that are in its sets. */

    uid_t owner_uid, uid;
    if (ioctl(userns_fd, NS_GET_OWNER_UID, &owner_uid) == -1) {
	perror("ioctl-NS_GET_OWNER_UID");
	exit(EXIT_FAILURE);
    }

    uid = get_euid_of_process(pid);

    printf("PID is in an ancestor namespace\n");
    if (owner_uid == uid) {
	printf("And its effective UID matches the owner "
		"of the namespace\n");
	printf("Subject to LSM checks, PID has all capabilities in "
		"that namespace!\n");
    } else {
	printf("But its effective UID does not match the owner "
		"of the namespace\n");
	printf("Subject to LSM checks, it has the following capabilities\n");
	show_cap(pid);
    }

    exit(EXIT_SUCCESS);
}
8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---

Michael Kerrisk (2):
  nsfs: Add an ioctl() to return the namespace type
  nsfs: Add an ioctl() to return owner UID of a userns

 fs/nsfs.c                 | 15 +++++++++++++++
 include/uapi/linux/nsfs.h |  9 +++++++--
 2 files changed, 22 insertions(+), 2 deletions(-)

-- 
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] 15+ messages in thread

* [PATCH v4 1/2] nsfs: Add an ioctl() to return the namespace type
       [not found] ` <2c27a76e-336d-e2ad-4b30-22e29249c2e9@gmail.com>
@ 2017-01-25  1:03   ` Michael Kerrisk (man-pages)
  2017-01-25  1:04   ` [PATCH v4 2/2] nsfs: Add an ioctl() to return owner UID of a userns Michael Kerrisk (man-pages)
  1 sibling, 0 replies; 15+ messages in thread
From: Michael Kerrisk (man-pages) @ 2017-01-25  1:03 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 8c9fb29..5d53476 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] 15+ messages in thread

* [PATCH v4 2/2] nsfs: Add an ioctl() to return owner UID of a userns
       [not found] ` <2c27a76e-336d-e2ad-4b30-22e29249c2e9@gmail.com>
  2017-01-25  1:03   ` [PATCH v4 1/2] nsfs: Add an ioctl() to return the namespace type Michael Kerrisk (man-pages)
@ 2017-01-25  1:04   ` Michael Kerrisk (man-pages)
  1 sibling, 0 replies; 15+ messages in thread
From: Michael Kerrisk (man-pages) @ 2017-01-25  1:04 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 a new NS_GET_CREATOR_UID ioctl() that fetches
the UID (as seen in the user namespace of the caller) 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. If the owner UID does
not have a mapping in the caller's user namespace, the operation
fails with the error EOVERFLOW. (Failing with EOVERFLOW, rather than
returning the overflow UID, is probably easier to deal with in
user-space applications.)

Acked-by: Andrey Vagin <avagin@openvz.org>
Signed-off-by: Michael Kerrisk <mtk-manpages@gmail.com>

---

V4 changes:
* Improve comment describing NS_GET_OWNER_UID (thanks to
  W. Trevor King)
* Use uid_t (rather than unsigned int) as type for ioctl() argument.
* Rather than returning the overflow UID if the owner UID does not have
  a mapping in the caller's user namespace, fail with the error
  EOVERFLOW. This makes user-space coding a little easier.
  (Thanks to the suggestion from Eric Biederman.)

V3 changes:
* Fixed data type of local variable 'uid'; thanks to Andrei Vagin.

V2 changes:
* Renamed ioctl() from NS_GET_CREATOR_UID to NS_GET_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                 | 13 +++++++++++++
 include/uapi/linux/nsfs.h |  8 +++++---
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/fs/nsfs.c b/fs/nsfs.c
index 5d53476..4842617 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 @@ 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));
+	uid_t __user *argp;
+	uid_t uid;
 
 	switch (ioctl) {
 	case NS_GET_USERNS:
@@ -174,6 +178,15 @@ 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 = (uid_t __user *) arg;
+		uid = from_kuid(current_user_ns(), user_ns->owner);
+		if (uid == (uid_t)-1)
+			return -EOVERFLOW;
+		return put_user(uid, argp);
 	default:
 		return -ENOTTY;
 	}
diff --git a/include/uapi/linux/nsfs.h b/include/uapi/linux/nsfs.h
index 2b48df1..1a3ca79 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 (in the caller's user namespace) 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] 15+ messages in thread

* Re: [PATCH v4 0/2] Add further ioctl() operations for namespace discovery
  2017-01-25  1:03 ` [PATCH v4 " Michael Kerrisk (man-pages)
@ 2017-01-25  1:58   ` Eric W. Biederman
  2017-01-25  2:24     ` Michael Kerrisk (man-pages)
  0 siblings, 1 reply; 15+ messages in thread
From: Eric W. Biederman @ 2017-01-25  1:58 UTC (permalink / raw)
  To: Michael Kerrisk (man-pages)
  Cc: Serge E. Hallyn, linux-api, linux-kernel, linux-fsdevel,
	Andrey Vagin, James Bottomley, W. Trevor King, Alexander Viro

"Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> writes:

> I would like to write code that discovers the namespace setup on a live
> system.  The NS_GET_PARENT and NS_GET_USERNS ioctl() operations added in
> Linux 4.9 provide much of what I want, but there are still a couple of
> small pieces missing. Those pieces are added with this patch series.

So it looks like the -EOVERFLOW change broke your example program.
Causing it to abort if -EOVERFLOW is hit.  Do we really want to return
-EOVERFLOW?  Or do you want to fix your program?

Eric


> Here's an example program that makes use of the new ioctl() operations.
>
> 8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---
> /* ns_capable.c
>
>    (C) 2016 Michael Kerrisk, <mtk.manpages@gmail.com>
>
>    Licensed under the GNU General Public License v2 or later.
>
>    Test whether a process (identified by PID) might (subject to LSM checks)
>    have capabilities in a namespace (identified by a /proc/PID/ns/xxx file).
> */
> #define _GNU_SOURCE
> #include <sched.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <stdio.h>
> #include <errno.h>
> #include <fcntl.h>
> #include <string.h>
> #include <sys/stat.h>
> #include <sys/ioctl.h>
> #include <limits.h>
> #include <sys/capability.h>
>
> #ifndef NS_GET_USERNS
> #define NSIO    0xb7
> #define NS_GET_USERNS		_IO(NSIO, 0x1)
> #define NS_GET_PARENT		_IO(NSIO, 0x2)
> #define NS_GET_NSTYPE		_IO(NSIO, 0x3)
> #define NS_GET_OWNER_UID	_IO(NSIO, 0x4)
> #endif
>
> #define errExit(msg) 	do { perror(msg); exit(EXIT_FAILURE); \
> 			} while (0)
>
> #define fatal(msg) 	do { fprintf(stderr, "%s\n", msg); \
>      			     exit(EXIT_FAILURE); } while (0)
>
> /* Display capabilities sets of process with specified PID */
>
> static void
> show_cap(pid_t pid)
> {
>     cap_t caps;
>     char *cap_string;
>
>     caps = cap_get_pid(pid);
>     if (caps == NULL)
> 	errExit("cap_get_proc");
>
>     cap_string = cap_to_text(caps, NULL);
>     if (cap_string == NULL)
> 	errExit("cap_to_text");
>
>     printf("Capabilities: %s\n", cap_string);
> }
>
> /* Obtain the effective UID pf the process 'pid' by
>    scanning its /proc/PID/file */
>
> static uid_t
> get_euid_of_process(pid_t pid)
> {
>     char path[PATH_MAX];
>     char line[1024];
>     int uid;
>
>     snprintf(path, sizeof(path), "/proc/%ld/status", (long) pid);
>
>     FILE *fp;
>     fp = fopen(path, "r");
>     if (fp == NULL)
> 	errExit("fopen-/proc/PID/status");
>
>     for (;;) {
> 	if (fgets(line, sizeof(line), fp) == NULL) {
>
> 	    /* Should never happen... */
>
> 	    fprintf(stderr, "Failure scanning %s\n", path);
> 	    exit(EXIT_FAILURE);
> 	}
>
> 	if (strstr(line, "Uid:") == line) {
> 	    sscanf(line, "Uid: %*d %d %*d %*d", &uid);
> 	    return uid;
> 	}
>     }
> }
>
> int
> main(int argc, char *argv[])
> {
>     int ns_fd, userns_fd, pid_userns_fd;
>     int nstype;
>     int next_fd;
>     struct stat pid_stat;
>     struct stat target_stat;
>     char *pid_str;
>     pid_t pid;
>     char path[PATH_MAX];
>
>     if (argc < 2) {
> 	fprintf(stderr, "Usage: %s PID [ns-file]\n", argv[0]);
> 	fprintf(stderr, "\t'ns-file' is a /proc/PID/ns/xxxx file; "
> 		        "if omitted, use the namespace\n"
> 			"\treferred to by standard input "
> 			"(file descriptor 0)\n");
> 	exit(EXIT_FAILURE);
>     }
>
>     pid_str = argv[1];
>     pid = atoi(pid_str);
>
>     if (argc <= 2) {
> 	ns_fd = STDIN_FILENO;
>     } else {
>         ns_fd = open(argv[2], O_RDONLY);
>         if (ns_fd == -1)
> 	    errExit("open-ns-file");
>     }
>
>     /* Get the relevant user namespace FD, which is 'ns_fd' if 'ns_fd' refers
>        to a user namespace, otherwise the user namespace that owns 'ns_fd' */
>
>     nstype = ioctl(ns_fd, NS_GET_NSTYPE);
>     if (nstype == -1)
> 	errExit("ioctl-NS_GET_NSTYPE");
>
>     if (nstype == CLONE_NEWUSER) {
> 	userns_fd = ns_fd;
>     } else {
> 	userns_fd = ioctl(ns_fd, NS_GET_USERNS);
>         if (userns_fd == -1)
> 	    errExit("ioctl-NS_GET_USERNS");
>     }
>
>     /* Obtain 'stat' info for the user namespace of the specified PID */
>
>     snprintf(path, sizeof(path), "/proc/%s/ns/user", pid_str);
>
>     pid_userns_fd = open(path, O_RDONLY);
>     if (pid_userns_fd == -1)
> 	errExit("open-PID");
>
>     if (fstat(pid_userns_fd, &pid_stat) == -1)
> 	errExit("fstat-PID");
>
>     /* Get 'stat' info for the target user namesapce */
>
>     if (fstat(userns_fd, &target_stat) == -1)
> 	errExit("fstat-PID");
>
>     /* If the PID is in the target user namespace, then it has
>        whatever capabilities are in its sets. */
>
>     if (pid_stat.st_dev == target_stat.st_dev &&
> 		pid_stat.st_ino == target_stat.st_ino) {
>         printf("PID is in target namespace\n");
> 	printf("Subject to LSM checks, it has the following capabilities\n");
>
> 	show_cap(pid);
>
> 	exit(EXIT_SUCCESS);
>     }
>
>     /* Otherwise, we need to walk through the ancestors of the target
>        user namespace to see if PID is in an ancestor namespace */
>
>     for (;;) {
> 	int f;
>
> 	next_fd = ioctl(userns_fd, NS_GET_PARENT);
>
> 	if (next_fd == -1) {
> 	    
> 	    /* The error here should be EPERM... */
>
> 	    if (errno != EPERM)
> 	        errExit("ioctl-NS_GET_PARENT");
>
> 	    printf("PID is not in an ancestor namespace\n");
> 	    printf("It has no capabilities in the target namespace\n");
>
> 	    exit(EXIT_SUCCESS);
> 	}
>
>         if (fstat(next_fd, &target_stat) == -1)
> 	    errExit("fstat-PID");
>
> 	/* If the 'stat' info for this user namespace matches the 'stat'
> 	 * info for 'next_fd', then the PID is in an ancestor namespace */
>
>         if (pid_stat.st_dev == target_stat.st_dev &&
> 		    pid_stat.st_ino == target_stat.st_ino)
> 	    break;
>
> 	/* Next time round, get the next parent */
>
> 	f = userns_fd;
> 	userns_fd = next_fd;
> 	close(f);
>     }
>
>     /* At this point, we found that PID is in an ancestor of the target
>        user namespace, and 'userns_fd' refers to the immediate descendant
>        user namespace of PID in the chain of user namespaces from PID to
>        the target user namespace. If the effective UID of PID matches the
>        owner UID of descendant user namespace, then PID has all
>        capabilities in the descendant namespace(s); otherwise, it just has
>        the capabilities that are in its sets. */
>
>     uid_t owner_uid, uid;
>     if (ioctl(userns_fd, NS_GET_OWNER_UID, &owner_uid) == -1) {
> 	perror("ioctl-NS_GET_OWNER_UID");
> 	exit(EXIT_FAILURE);
>     }
>
>     uid = get_euid_of_process(pid);
>
>     printf("PID is in an ancestor namespace\n");
>     if (owner_uid == uid) {
> 	printf("And its effective UID matches the owner "
> 		"of the namespace\n");
> 	printf("Subject to LSM checks, PID has all capabilities in "
> 		"that namespace!\n");
>     } else {
> 	printf("But its effective UID does not match the owner "
> 		"of the namespace\n");
> 	printf("Subject to LSM checks, it has the following capabilities\n");
> 	show_cap(pid);
>     }
>
>     exit(EXIT_SUCCESS);
> }
> 8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---
>
> Michael Kerrisk (2):
>   nsfs: Add an ioctl() to return the namespace type
>   nsfs: Add an ioctl() to return owner UID of a userns
>
>  fs/nsfs.c                 | 15 +++++++++++++++
>  include/uapi/linux/nsfs.h |  9 +++++++--
>  2 files changed, 22 insertions(+), 2 deletions(-)
>
> -- 
> 2.5.5

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

* Re: [PATCH v4 0/2] Add further ioctl() operations for namespace discovery
  2017-01-25  1:58   ` Eric W. Biederman
@ 2017-01-25  2:24     ` Michael Kerrisk (man-pages)
  2017-01-25  2:26       ` Eric W. Biederman
  0 siblings, 1 reply; 15+ messages in thread
From: Michael Kerrisk (man-pages) @ 2017-01-25  2:24 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Serge E. Hallyn, Linux API, lkml, linux-fsdevel, Andrey Vagin,
	James Bottomley, W. Trevor King, Alexander Viro

Hi Eric,

On 25 January 2017 at 14:58, Eric W. Biederman <ebiederm@xmission.com> wrote:
> "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> writes:
>
>> I would like to write code that discovers the namespace setup on a live
>> system.  The NS_GET_PARENT and NS_GET_USERNS ioctl() operations added in
>> Linux 4.9 provide much of what I want, but there are still a couple of
>> small pieces missing. Those pieces are added with this patch series.
>
> So it looks like the -EOVERFLOW change broke your example program.
> Causing it to abort if -EOVERFLOW is hit.  Do we really want to return
> -EOVERFLOW?  Or do you want to fix your program?

Bother! Yes, I should have kept the example program in sync. (I
overlooked that it was not any more in sync.)

So, I want to make sure I understand correctly, before I aswer your
question. Suppose we have

1. Outer namespace owned by UID 0
2. Inner namespace owned by UID 1000
3. A UID mapping in the inner namespace that maps '0 1000 1'
4. A processs, X, in the outer namespace with UID 0 (and all caps).

That's the case you're meaning, right? So, UID 0 doesn't have a
mapping into the inner namespace, but does have all capabilities in
that inner namespace, right?

Cheers,

Michael


> Eric
>
>
>> Here's an example program that makes use of the new ioctl() operations.
>>
>> 8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---
>> /* ns_capable.c
>>
>>    (C) 2016 Michael Kerrisk, <mtk.manpages@gmail.com>
>>
>>    Licensed under the GNU General Public License v2 or later.
>>
>>    Test whether a process (identified by PID) might (subject to LSM checks)
>>    have capabilities in a namespace (identified by a /proc/PID/ns/xxx file).
>> */
>> #define _GNU_SOURCE
>> #include <sched.h>
>> #include <stdlib.h>
>> #include <unistd.h>
>> #include <stdio.h>
>> #include <errno.h>
>> #include <fcntl.h>
>> #include <string.h>
>> #include <sys/stat.h>
>> #include <sys/ioctl.h>
>> #include <limits.h>
>> #include <sys/capability.h>
>>
>> #ifndef NS_GET_USERNS
>> #define NSIO    0xb7
>> #define NS_GET_USERNS         _IO(NSIO, 0x1)
>> #define NS_GET_PARENT         _IO(NSIO, 0x2)
>> #define NS_GET_NSTYPE         _IO(NSIO, 0x3)
>> #define NS_GET_OWNER_UID      _IO(NSIO, 0x4)
>> #endif
>>
>> #define errExit(msg)  do { perror(msg); exit(EXIT_FAILURE); \
>>                       } while (0)
>>
>> #define fatal(msg)    do { fprintf(stderr, "%s\n", msg); \
>>                            exit(EXIT_FAILURE); } while (0)
>>
>> /* Display capabilities sets of process with specified PID */
>>
>> static void
>> show_cap(pid_t pid)
>> {
>>     cap_t caps;
>>     char *cap_string;
>>
>>     caps = cap_get_pid(pid);
>>     if (caps == NULL)
>>       errExit("cap_get_proc");
>>
>>     cap_string = cap_to_text(caps, NULL);
>>     if (cap_string == NULL)
>>       errExit("cap_to_text");
>>
>>     printf("Capabilities: %s\n", cap_string);
>> }
>>
>> /* Obtain the effective UID pf the process 'pid' by
>>    scanning its /proc/PID/file */
>>
>> static uid_t
>> get_euid_of_process(pid_t pid)
>> {
>>     char path[PATH_MAX];
>>     char line[1024];
>>     int uid;
>>
>>     snprintf(path, sizeof(path), "/proc/%ld/status", (long) pid);
>>
>>     FILE *fp;
>>     fp = fopen(path, "r");
>>     if (fp == NULL)
>>       errExit("fopen-/proc/PID/status");
>>
>>     for (;;) {
>>       if (fgets(line, sizeof(line), fp) == NULL) {
>>
>>           /* Should never happen... */
>>
>>           fprintf(stderr, "Failure scanning %s\n", path);
>>           exit(EXIT_FAILURE);
>>       }
>>
>>       if (strstr(line, "Uid:") == line) {
>>           sscanf(line, "Uid: %*d %d %*d %*d", &uid);
>>           return uid;
>>       }
>>     }
>> }
>>
>> int
>> main(int argc, char *argv[])
>> {
>>     int ns_fd, userns_fd, pid_userns_fd;
>>     int nstype;
>>     int next_fd;
>>     struct stat pid_stat;
>>     struct stat target_stat;
>>     char *pid_str;
>>     pid_t pid;
>>     char path[PATH_MAX];
>>
>>     if (argc < 2) {
>>       fprintf(stderr, "Usage: %s PID [ns-file]\n", argv[0]);
>>       fprintf(stderr, "\t'ns-file' is a /proc/PID/ns/xxxx file; "
>>                       "if omitted, use the namespace\n"
>>                       "\treferred to by standard input "
>>                       "(file descriptor 0)\n");
>>       exit(EXIT_FAILURE);
>>     }
>>
>>     pid_str = argv[1];
>>     pid = atoi(pid_str);
>>
>>     if (argc <= 2) {
>>       ns_fd = STDIN_FILENO;
>>     } else {
>>         ns_fd = open(argv[2], O_RDONLY);
>>         if (ns_fd == -1)
>>           errExit("open-ns-file");
>>     }
>>
>>     /* Get the relevant user namespace FD, which is 'ns_fd' if 'ns_fd' refers
>>        to a user namespace, otherwise the user namespace that owns 'ns_fd' */
>>
>>     nstype = ioctl(ns_fd, NS_GET_NSTYPE);
>>     if (nstype == -1)
>>       errExit("ioctl-NS_GET_NSTYPE");
>>
>>     if (nstype == CLONE_NEWUSER) {
>>       userns_fd = ns_fd;
>>     } else {
>>       userns_fd = ioctl(ns_fd, NS_GET_USERNS);
>>         if (userns_fd == -1)
>>           errExit("ioctl-NS_GET_USERNS");
>>     }
>>
>>     /* Obtain 'stat' info for the user namespace of the specified PID */
>>
>>     snprintf(path, sizeof(path), "/proc/%s/ns/user", pid_str);
>>
>>     pid_userns_fd = open(path, O_RDONLY);
>>     if (pid_userns_fd == -1)
>>       errExit("open-PID");
>>
>>     if (fstat(pid_userns_fd, &pid_stat) == -1)
>>       errExit("fstat-PID");
>>
>>     /* Get 'stat' info for the target user namesapce */
>>
>>     if (fstat(userns_fd, &target_stat) == -1)
>>       errExit("fstat-PID");
>>
>>     /* If the PID is in the target user namespace, then it has
>>        whatever capabilities are in its sets. */
>>
>>     if (pid_stat.st_dev == target_stat.st_dev &&
>>               pid_stat.st_ino == target_stat.st_ino) {
>>         printf("PID is in target namespace\n");
>>       printf("Subject to LSM checks, it has the following capabilities\n");
>>
>>       show_cap(pid);
>>
>>       exit(EXIT_SUCCESS);
>>     }
>>
>>     /* Otherwise, we need to walk through the ancestors of the target
>>        user namespace to see if PID is in an ancestor namespace */
>>
>>     for (;;) {
>>       int f;
>>
>>       next_fd = ioctl(userns_fd, NS_GET_PARENT);
>>
>>       if (next_fd == -1) {
>>
>>           /* The error here should be EPERM... */
>>
>>           if (errno != EPERM)
>>               errExit("ioctl-NS_GET_PARENT");
>>
>>           printf("PID is not in an ancestor namespace\n");
>>           printf("It has no capabilities in the target namespace\n");
>>
>>           exit(EXIT_SUCCESS);
>>       }
>>
>>         if (fstat(next_fd, &target_stat) == -1)
>>           errExit("fstat-PID");
>>
>>       /* If the 'stat' info for this user namespace matches the 'stat'
>>        * info for 'next_fd', then the PID is in an ancestor namespace */
>>
>>         if (pid_stat.st_dev == target_stat.st_dev &&
>>                   pid_stat.st_ino == target_stat.st_ino)
>>           break;
>>
>>       /* Next time round, get the next parent */
>>
>>       f = userns_fd;
>>       userns_fd = next_fd;
>>       close(f);
>>     }
>>
>>     /* At this point, we found that PID is in an ancestor of the target
>>        user namespace, and 'userns_fd' refers to the immediate descendant
>>        user namespace of PID in the chain of user namespaces from PID to
>>        the target user namespace. If the effective UID of PID matches the
>>        owner UID of descendant user namespace, then PID has all
>>        capabilities in the descendant namespace(s); otherwise, it just has
>>        the capabilities that are in its sets. */
>>
>>     uid_t owner_uid, uid;
>>     if (ioctl(userns_fd, NS_GET_OWNER_UID, &owner_uid) == -1) {
>>       perror("ioctl-NS_GET_OWNER_UID");
>>       exit(EXIT_FAILURE);
>>     }
>>
>>     uid = get_euid_of_process(pid);
>>
>>     printf("PID is in an ancestor namespace\n");
>>     if (owner_uid == uid) {
>>       printf("And its effective UID matches the owner "
>>               "of the namespace\n");
>>       printf("Subject to LSM checks, PID has all capabilities in "
>>               "that namespace!\n");
>>     } else {
>>       printf("But its effective UID does not match the owner "
>>               "of the namespace\n");
>>       printf("Subject to LSM checks, it has the following capabilities\n");
>>       show_cap(pid);
>>     }
>>
>>     exit(EXIT_SUCCESS);
>> }
>> 8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---
>>
>> Michael Kerrisk (2):
>>   nsfs: Add an ioctl() to return the namespace type
>>   nsfs: Add an ioctl() to return owner UID of a userns
>>
>>  fs/nsfs.c                 | 15 +++++++++++++++
>>  include/uapi/linux/nsfs.h |  9 +++++++--
>>  2 files changed, 22 insertions(+), 2 deletions(-)
>>
>> --
>> 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] 15+ messages in thread

* Re: [PATCH v4 0/2] Add further ioctl() operations for namespace discovery
  2017-01-25  2:24     ` Michael Kerrisk (man-pages)
@ 2017-01-25  2:26       ` Eric W. Biederman
  2017-01-25  2:28         ` Eric W. Biederman
  0 siblings, 1 reply; 15+ messages in thread
From: Eric W. Biederman @ 2017-01-25  2:26 UTC (permalink / raw)
  To: Michael Kerrisk (man-pages)
  Cc: Serge E. Hallyn, Linux API, lkml, linux-fsdevel, Andrey Vagin,
	James Bottomley, W. Trevor King, Alexander Viro

"Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> writes:

> Hi Eric,
>
> On 25 January 2017 at 14:58, Eric W. Biederman <ebiederm@xmission.com> wrote:
>> "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> writes:
>>
>>> I would like to write code that discovers the namespace setup on a live
>>> system.  The NS_GET_PARENT and NS_GET_USERNS ioctl() operations added in
>>> Linux 4.9 provide much of what I want, but there are still a couple of
>>> small pieces missing. Those pieces are added with this patch series.
>>
>> So it looks like the -EOVERFLOW change broke your example program.
>> Causing it to abort if -EOVERFLOW is hit.  Do we really want to return
>> -EOVERFLOW?  Or do you want to fix your program?
>
> Bother! Yes, I should have kept the example program in sync. (I
> overlooked that it was not any more in sync.)
>
> So, I want to make sure I understand correctly, before I aswer your
> question. Suppose we have
>
> 1. Outer namespace owned by UID 0
> 2. Inner namespace owned by UID 1000
> 3. A UID mapping in the inner namespace that maps '0 1000 1'
> 4. A processs, X, in the outer namespace with UID 0 (and all caps).
>
> That's the case you're meaning, right?

I think so I just noticed you did not handle -EOVERFLOW in
the one NS_GET_OWNER_UID call.

> So, UID 0 doesn't have a
> mapping into the inner namespace, but does have all capabilities in
> that inner namespace, right?

That is correct.


Eric

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

* Re: [PATCH v4 0/2] Add further ioctl() operations for namespace discovery
  2017-01-25  2:26       ` Eric W. Biederman
@ 2017-01-25  2:28         ` Eric W. Biederman
  2017-01-25  3:50           ` Michael Kerrisk (man-pages)
  0 siblings, 1 reply; 15+ messages in thread
From: Eric W. Biederman @ 2017-01-25  2:28 UTC (permalink / raw)
  To: Michael Kerrisk (man-pages)
  Cc: Serge E. Hallyn, Linux API, lkml, linux-fsdevel, Andrey Vagin,
	James Bottomley, W. Trevor King, Alexander Viro

ebiederm@xmission.com (Eric W. Biederman) writes:

> "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> writes:
>
>> Hi Eric,
>>
>> On 25 January 2017 at 14:58, Eric W. Biederman <ebiederm@xmission.com> wrote:
>>> "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> writes:
>>>
>>>> I would like to write code that discovers the namespace setup on a live
>>>> system.  The NS_GET_PARENT and NS_GET_USERNS ioctl() operations added in
>>>> Linux 4.9 provide much of what I want, but there are still a couple of
>>>> small pieces missing. Those pieces are added with this patch series.
>>>
>>> So it looks like the -EOVERFLOW change broke your example program.
>>> Causing it to abort if -EOVERFLOW is hit.  Do we really want to return
>>> -EOVERFLOW?  Or do you want to fix your program?
>>
>> Bother! Yes, I should have kept the example program in sync. (I
>> overlooked that it was not any more in sync.)
>>
>> So, I want to make sure I understand correctly, before I aswer your
>> question. Suppose we have
>>
>> 1. Outer namespace owned by UID 0
>> 2. Inner namespace owned by UID 1000
>> 3. A UID mapping in the inner namespace that maps '0 1000 1'
>> 4. A processs, X, in the outer namespace with UID 0 (and all caps).
>>
>> That's the case you're meaning, right?
>
> I think so I just noticed you did not handle -EOVERFLOW in
> the one NS_GET_OWNER_UID call.
>
>> So, UID 0 doesn't have a
>> mapping into the inner namespace, but does have all capabilities in
>> that inner namespace, right?
>
> That is correct.

My concern is that the difference between returning -EOVERFLOW and
overflow_uid is primarily about usability.  If you haven't played with
the usability I don't trust that we have made the proper trade off.


Eric

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

* Re: [PATCH v4 0/2] Add further ioctl() operations for namespace discovery
  2017-01-25  2:28         ` Eric W. Biederman
@ 2017-01-25  3:50           ` Michael Kerrisk (man-pages)
  2017-01-26  4:23             ` Eric W. Biederman
  0 siblings, 1 reply; 15+ messages in thread
From: Michael Kerrisk (man-pages) @ 2017-01-25  3:50 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Serge E. Hallyn, Linux API, lkml, linux-fsdevel, Andrey Vagin,
	James Bottomley, W. Trevor King, Alexander Viro

Hi Eric,

On 25 January 2017 at 15:28, Eric W. Biederman <ebiederm@xmission.com> wrote:
> ebiederm@xmission.com (Eric W. Biederman) writes:
>
>> "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> writes:
>>
>>> Hi Eric,
>>>
>>> On 25 January 2017 at 14:58, Eric W. Biederman <ebiederm@xmission.com> wrote:
>>>> "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> writes:
>>>>
>>>>> I would like to write code that discovers the namespace setup on a live
>>>>> system.  The NS_GET_PARENT and NS_GET_USERNS ioctl() operations added in
>>>>> Linux 4.9 provide much of what I want, but there are still a couple of
>>>>> small pieces missing. Those pieces are added with this patch series.
>>>>
>>>> So it looks like the -EOVERFLOW change broke your example program.
>>>> Causing it to abort if -EOVERFLOW is hit.  Do we really want to return
>>>> -EOVERFLOW?  Or do you want to fix your program?
>>>
>>> Bother! Yes, I should have kept the example program in sync. (I
>>> overlooked that it was not any more in sync.)
>>>
>>> So, I want to make sure I understand correctly, before I aswer your
>>> question. Suppose we have
>>>
>>> 1. Outer namespace owned by UID 0
>>> 2. Inner namespace owned by UID 1000
>>> 3. A UID mapping in the inner namespace that maps '0 1000 1'
>>> 4. A processs, X, in the outer namespace with UID 0 (and all caps).
>>>
>>> That's the case you're meaning, right?
>>
>> I think so I just noticed you did not handle -EOVERFLOW in
>> the one NS_GET_OWNER_UID call.
>>
>>> So, UID 0 doesn't have a
>>> mapping into the inner namespace, but does have all capabilities in
>>> that inner namespace, right?
>>
>> That is correct.
>
> My concern is that the difference between returning -EOVERFLOW and
> overflow_uid is primarily about usability.  If you haven't played with
> the usability I don't trust that we have made the proper trade off.

So, I had not initially included the no-UID-mapping case, and when you
proposed -EOVERFLOW for that case, it seemed better.

On reflection, mapping to the overflow_uid seems simpler. Taking the
example shown in my other mail a short time ago, the unmapped UID 0
from the outer namespace would map to the overflow_uid (which UID my
program would print), but my program would still correctly report that
the UID 0 process in the outer namespace might (subject to LSM checks)
have capabilities in the inner namespace.

So, it seems that reverting the EOVERFLOW change is in order (and my
example program thus needs no changes). Does that sound reasonable to
you?

Cheers,

Michael

-- 
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] 15+ messages in thread

* Re: [PATCH v4 0/2] Add further ioctl() operations for namespace discovery
  2017-01-25  3:50           ` Michael Kerrisk (man-pages)
@ 2017-01-26  4:23             ` Eric W. Biederman
  2017-02-03  2:34               ` Eric W. Biederman
  0 siblings, 1 reply; 15+ messages in thread
From: Eric W. Biederman @ 2017-01-26  4:23 UTC (permalink / raw)
  To: Michael Kerrisk (man-pages)
  Cc: Serge E. Hallyn, Linux API, lkml, linux-fsdevel, Andrey Vagin,
	James Bottomley, W. Trevor King, Alexander Viro

"Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> writes:


> On 25 January 2017 at 15:28, Eric W. Biederman <ebiederm@xmission.com> wrote:

>> My concern is that the difference between returning -EOVERFLOW and
>> overflow_uid is primarily about usability.  If you haven't played with
>> the usability I don't trust that we have made the proper trade off.
>
> So, I had not initially included the no-UID-mapping case, and when you
> proposed -EOVERFLOW for that case, it seemed better.
>
> On reflection, mapping to the overflow_uid seems simpler. Taking the
> example shown in my other mail a short time ago, the unmapped UID 0
> from the outer namespace would map to the overflow_uid (which UID my
> program would print), but my program would still correctly report that
> the UID 0 process in the outer namespace might (subject to LSM checks)
> have capabilities in the inner namespace.
>
> So, it seems that reverting the EOVERFLOW change is in order (and my
> example program thus needs no changes). Does that sound reasonable to
> you?

It does.  I just care that you have thought through the tradeoffs of
that corner of the interface design.

Eric

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

* Re: [PATCH v4 0/2] Add further ioctl() operations for namespace discovery
  2017-01-26  4:23             ` Eric W. Biederman
@ 2017-02-03  2:34               ` Eric W. Biederman
  2017-02-08 14:13                 ` Michael Kerrisk (man-pages)
  0 siblings, 1 reply; 15+ messages in thread
From: Eric W. Biederman @ 2017-02-03  2:34 UTC (permalink / raw)
  To: Michael Kerrisk (man-pages)
  Cc: Serge E. Hallyn, Linux API, lkml, linux-fsdevel, Andrey Vagin,
	James Bottomley, W. Trevor King, Alexander Viro

ebiederm@xmission.com (Eric W. Biederman) writes:

> "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> writes:
>
>
>> On 25 January 2017 at 15:28, Eric W. Biederman <ebiederm@xmission.com> wrote:
>
>>> My concern is that the difference between returning -EOVERFLOW and
>>> overflow_uid is primarily about usability.  If you haven't played with
>>> the usability I don't trust that we have made the proper trade off.
>>
>> So, I had not initially included the no-UID-mapping case, and when you
>> proposed -EOVERFLOW for that case, it seemed better.
>>
>> On reflection, mapping to the overflow_uid seems simpler. Taking the
>> example shown in my other mail a short time ago, the unmapped UID 0
>> from the outer namespace would map to the overflow_uid (which UID my
>> program would print), but my program would still correctly report that
>> the UID 0 process in the outer namespace might (subject to LSM checks)
>> have capabilities in the inner namespace.
>>
>> So, it seems that reverting the EOVERFLOW change is in order (and my
>> example program thus needs no changes). Does that sound reasonable to
>> you?
>
> It does.  I just care that you have thought through the tradeoffs of
> that corner of the interface design.

So I have just reverted the EOVERFLOW change, applied the patches to
my tree and pushed this to for-next.  Otherwise this looks like this
effort will have stalled.

Eric

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

* Re: [PATCH v4 0/2] Add further ioctl() operations for namespace discovery
  2017-02-03  2:34               ` Eric W. Biederman
@ 2017-02-08 14:13                 ` Michael Kerrisk (man-pages)
  0 siblings, 0 replies; 15+ messages in thread
From: Michael Kerrisk (man-pages) @ 2017-02-08 14:13 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Serge E. Hallyn, Linux API, lkml, linux-fsdevel, Andrey Vagin,
	James Bottomley, W. Trevor King, Alexander Viro

Hi Eric,

On 3 February 2017 at 03:34, Eric W. Biederman <ebiederm@xmission.com> wrote:
> ebiederm@xmission.com (Eric W. Biederman) writes:
>
>> "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> writes:
>>
>>
>>> On 25 January 2017 at 15:28, Eric W. Biederman <ebiederm@xmission.com> wrote:
>>
>>>> My concern is that the difference between returning -EOVERFLOW and
>>>> overflow_uid is primarily about usability.  If you haven't played with
>>>> the usability I don't trust that we have made the proper trade off.
>>>
>>> So, I had not initially included the no-UID-mapping case, and when you
>>> proposed -EOVERFLOW for that case, it seemed better.
>>>
>>> On reflection, mapping to the overflow_uid seems simpler. Taking the
>>> example shown in my other mail a short time ago, the unmapped UID 0
>>> from the outer namespace would map to the overflow_uid (which UID my
>>> program would print), but my program would still correctly report that
>>> the UID 0 process in the outer namespace might (subject to LSM checks)
>>> have capabilities in the inner namespace.
>>>
>>> So, it seems that reverting the EOVERFLOW change is in order (and my
>>> example program thus needs no changes). Does that sound reasonable to
>>> you?
>>
>> It does.  I just care that you have thought through the tradeoffs of
>> that corner of the interface design.
>
> So I have just reverted the EOVERFLOW change, applied the patches to
> my tree and pushed this to for-next.  Otherwise this looks like this
> effort will have stalled.

Sorry for not following up earlier. I got a bit distracted and wanted
to make some time to further reflect on which approach was better, and
reconsider my example code. Reverting the EOVERFLOW piece seems best
to me. Thanks for applying.

Cheers,

Michael



-- 
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] 15+ messages in thread

end of thread, other threads:[~2017-02-08 15:22 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-23  9:54 [PATCH v2 0/2] Add further ioctl() operations for namespace discovery Michael Kerrisk (man-pages)
2017-01-24 21:34 ` Michael Kerrisk (man-pages)
2017-01-24 22:41   ` Eric W. Biederman
2017-01-25  0:39     ` Michael Kerrisk (man-pages)
2017-01-25  1:03 ` [PATCH v4 " Michael Kerrisk (man-pages)
2017-01-25  1:58   ` Eric W. Biederman
2017-01-25  2:24     ` Michael Kerrisk (man-pages)
2017-01-25  2:26       ` Eric W. Biederman
2017-01-25  2:28         ` Eric W. Biederman
2017-01-25  3:50           ` Michael Kerrisk (man-pages)
2017-01-26  4:23             ` Eric W. Biederman
2017-02-03  2:34               ` Eric W. Biederman
2017-02-08 14:13                 ` Michael Kerrisk (man-pages)
     [not found] ` <2c27a76e-336d-e2ad-4b30-22e29249c2e9@gmail.com>
2017-01-25  1:03   ` [PATCH v4 1/2] nsfs: Add an ioctl() to return the namespace type Michael Kerrisk (man-pages)
2017-01-25  1:04   ` [PATCH v4 2/2] nsfs: Add an ioctl() to return owner UID of a userns 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).