The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxc/pull/2996

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
lxc-ls without root privileges on privileged containers should not display
information. In lxc_container_new(), ongoing_create()'s result is not checked
for all possible returned values. Hence, an unprivileged user can send command
messages to the container's monitor. For example:

$ lxc-ls -P /.../tests -f
NAME     STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED
ctr -     0         -      -    -    false
$ sudo lxc-ls -P /.../tests -f
NAME     STATE   AUTOSTART GROUPS IPV4      IPV6 UNPRIVILEGED
ctr RUNNING 0         -      10.0.3.51 -    false

After this change:

$ lxc-ls -P /.../tests -f      <-------- No more display without root privileges
$ sudo lxc-ls -P /.../tests -f
NAME     STATE   AUTOSTART GROUPS IPV4      IPV6 UNPRIVILEGED
ctr RUNNING 0         -      10.0.3.37 -    false
$

Signed-off-by: Rachid Koucha <rachid.kou...@gmail.com>
Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
From 9fbe07f68da62c90ff849eb1e2d59396d2a9672f Mon Sep 17 00:00:00 2001
From: Rachid Koucha <47061324+rachid-kou...@users.noreply.github.com>
Date: Fri, 10 May 2019 18:56:12 +0200
Subject: [PATCH] lxccontainer: do not display if missing privileges

lxc-ls without root privileges on privileged containers should not display
information. In lxc_container_new(), ongoing_create()'s result is not checked
for all possible returned values. Hence, an unprivileged user can send command
messages to the container's monitor. For example:

$ lxc-ls -P /.../tests -f
NAME     STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED
ctr -     0         -      -    -    false
$ sudo lxc-ls -P /.../tests -f
NAME     STATE   AUTOSTART GROUPS IPV4      IPV6 UNPRIVILEGED
ctr RUNNING 0         -      10.0.3.51 -    false

After this change:

$ lxc-ls -P /.../tests -f      <-------- No more display without root privileges
$ sudo lxc-ls -P /.../tests -f
NAME     STATE   AUTOSTART GROUPS IPV4      IPV6 UNPRIVILEGED
ctr RUNNING 0         -      10.0.3.37 -    false
$

Signed-off-by: Rachid Koucha <rachid.kou...@gmail.com>
Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
---
 src/lxc/lxccontainer.c | 56 ++++++++++++++++++++++++++++++------------
 1 file changed, 40 insertions(+), 16 deletions(-)

diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 98f86a24e4..cea8aa5d7b 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -135,7 +135,8 @@ static bool config_file_exists(const char *lxcpath, const 
char *cname)
        return file_exists(fname);
 }
 
-/* A few functions to help detect when a container creation failed. If a
+/*
+ * A few functions to help detect when a container creation failed. If a
  * container creation was killed partway through, then trying to actually start
  * that container could harm the host. We detect this by creating a 'partial'
  * file under the container directory, and keeping an advisory lock. When
@@ -143,30 +144,39 @@ static bool config_file_exists(const char *lxcpath, const 
char *cname)
  * start a container, if we find that file, without a flock, we remove the
  * container.
  */
+enum {
+       LXC_CREATE_FAILED = -1,
+       LXC_CREATE_SUCCESS = 0,
+       LXC_CREATE_ONGOING = 1,
+       LXC_CREATE_INCOMPLETE = 2,
+};
+
 static int ongoing_create(struct lxc_container *c)
 {
+       __do_close_prot_errno int fd = -EBADF;
        __do_free char *path = NULL;
-       int fd, ret;
-       size_t len;
        struct flock lk = {0};
+       int ret;
+       size_t len;
 
        len = strlen(c->config_path) + strlen(c->name) + 10;
        path = must_realloc(NULL, len);
        ret = snprintf(path, len, "%s/%s/partial", c->config_path, c->name);
        if (ret < 0 || (size_t)ret >= len)
-               return -1;
+               return LXC_CREATE_FAILED;
 
        fd = open(path, O_RDWR | O_CLOEXEC);
        if (fd < 0) {
                if (errno != ENOENT)
-                       return -1;
+                       return LXC_CREATE_FAILED;
 
-               return 0;
+               return LXC_CREATE_SUCCESS;
        }
 
        lk.l_type = F_WRLCK;
        lk.l_whence = SEEK_SET;
-       /* F_OFD_GETLK requires that l_pid be set to 0 otherwise the kernel
+       /*
+        * F_OFD_GETLK requires that l_pid be set to 0 otherwise the kernel
         * will EINVAL us.
         */
        lk.l_pid = 0;
@@ -178,15 +188,13 @@ static int ongoing_create(struct lxc_container *c)
                        ret = 0;
        }
 
-       close(fd);
-
        /* F_OFD_GETLK will not send us back a pid so don't check it. */
        if (ret == 0)
                /* Create is still ongoing. */
-               return 1;
+               return LXC_CREATE_ONGOING;
 
        /* Create completed but partial is still there. */
-       return 2;
+       return LXC_CREATE_INCOMPLETE;
 }
 
 static int create_partial(struct lxc_container *c)
@@ -891,13 +899,14 @@ static bool do_lxcapi_start(struct lxc_container *c, int 
useinit, char * const a
                return false;
 
        ret = ongoing_create(c);
-       if (ret < 0) {
+       switch (ret) {
+       case LXC_CREATE_FAILED:
                ERROR("Failed checking for incomplete container creation");
                return false;
-       } else if (ret == 1) {
+       case LXC_CREATE_ONGOING:
                ERROR("Ongoing container creation detected");
                return false;
-       } else if (ret == 2) {
+       case LXC_CREATE_INCOMPLETE:
                ERROR("Failed to create container");
                do_lxcapi_destroy(c);
                return false;
@@ -5249,6 +5258,7 @@ struct lxc_container *lxc_container_new(const char *name, 
const char *configpath
 {
        struct lxc_container *c;
        size_t len;
+       int rc;
 
        if (!name)
                return NULL;
@@ -5302,10 +5312,24 @@ struct lxc_container *lxc_container_new(const char 
*name, const char *configpath
                goto err;
        }
 
-       if (ongoing_create(c) == 2) {
-               ERROR("Failed to complete container creation for %s", c->name);
+       rc = ongoing_create(c);
+       switch (rc) {
+       case LXC_CREATE_INCOMPLETE:
+               SYSERROR("Failed to complete container creation for %s", 
c->name);
                container_destroy(c, NULL);
                lxcapi_clear_config(c);
+               break;
+       case LXC_CREATE_ONGOING:
+               /* container creation going on */
+               break;
+       case LXC_CREATE_FAILED:
+               /* container creation failed */
+               if (errno != EACCES && errno != EPERM) {
+                       /* insufficient privileges */
+                       SYSERROR("Failed checking for incomplete container %s 
creation", c->name);
+                       goto err;
+               }
+               break;
        }
 
        c->daemonize = true;
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to