qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Anthony Liguori <aliguori@us.ibm.com>
To: qemu-devel@nongnu.org
Cc: Mark McLoughlin <markmc@redhat.com>,
	Anthony Liguori <aliguori@us.ibm.com>,
	Arnd Bergmann <arndbergmann@googlemail.com>,
	Dustin Kirkland <kirkland@canonical.com>,
	Michael Tsirkin <mst@redhat.com>,
	Juan Quintela <quintela@redhat.com>
Subject: [Qemu-devel] [PATCH 2/4] Add access control support to qemu-bridge-helper
Date: Tue,  3 Nov 2009 18:28:03 -0600	[thread overview]
Message-ID: <1257294485-27015-3-git-send-email-aliguori@us.ibm.com> (raw)
In-Reply-To: <1257294485-27015-1-git-send-email-aliguori@us.ibm.com>

We go to great lengths to restrict ourselves to just cap_net_admin as an OS
enforced security mechanism.  However, we further restrict what we allow users
to do to simply adding a tap device to a bridge interface by virtue of the fact
that this is the only functionality we expose.

This is not good enough though.  An administrator is likely to want to restrict
the bridges that an unprivileged user can access, in particular, to restrict
an unprivileged user from putting a guest on what should be isolated networks.

This patch implements a ACL mechanism that is enforced by qemu-bridge-helper.
The ACLs are fairly simple whitelist/blacklist mechanisms with a wildcard of
'all'.

An interesting feature of this ACL mechanism is that you can include external
ACL files.  The main reason to support this is so that you can set different
file system permissions on those external ACL files.  This allows an
administrator to implement rather sophisicated ACL policies based on user/group
policies via the file system.

If we fail to include an acl file, we are silent about it making this mechanism
work pretty seamlessly.  As an example:

/etc/qemu/bridge.conf root:qemu 0640

 deny all
 allow br0
 include /etc/qemu/alice.conf
 include /etc/qemu/bob.conf

/etc/qemu/alice.conf root:alice 0640
 allow br1

/etc/qemu/bob.conf root:bob 0640
 allow br2

This ACL pattern allows any user in the qemu group to get a tap device
connected to br0 (which is bridged to the physical network).

Users in the alice group can additionally get a tap device connected to br1.
This allows br1 to act as a private bridge for the alice group.

Users in the bob group can additionally get a tap device connected to br2.
This allows br2 to act as a private bridge for the bob group.

Under no circumstance can the bob group get access to br1 or can the alice
group get access to br2.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 configure            |    1 +
 qemu-bridge-helper.c |  138 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 139 insertions(+), 0 deletions(-)

diff --git a/configure b/configure
index a341e77..7c98257 100755
--- a/configure
+++ b/configure
@@ -1864,6 +1864,7 @@ printf " '%s'" "$0" "$@" >> $config_host_mak
 echo >> $config_host_mak
 
 echo "CONFIG_QEMU_SHAREDIR=\"$prefix$datasuffix\"" >> $config_host_mak
+echo "CONFIG_QEMU_CONFDIR=\"/etc/qemu\"" >> $config_host_mak
 
 case "$cpu" in
   i386|x86_64|alpha|cris|hppa|ia64|m68k|microblaze|mips|mips64|ppc|ppc64|s390|sparc|sparc64)
diff --git a/qemu-bridge-helper.c b/qemu-bridge-helper.c
index f10d37c..0d059ed 100644
--- a/qemu-bridge-helper.c
+++ b/qemu-bridge-helper.c
@@ -33,6 +33,106 @@
 
 #include "net/tap-linux.h"
 
+#define MAX_ACLS (128)
+#define DEFAULT_ACL_FILE CONFIG_QEMU_CONFDIR "/bridge.conf"
+
+enum {
+    ACL_ALLOW = 0,
+    ACL_ALLOW_ALL,
+    ACL_DENY,
+    ACL_DENY_ALL,
+};
+
+typedef struct ACLRule
+{
+    int type;
+    char iface[IFNAMSIZ];
+} ACLRule;
+
+static int parse_acl_file(const char *filename, ACLRule *acls, int *pacl_count)
+{
+    int acl_count = *pacl_count;
+    FILE *f;
+    char line[4096];
+
+    f = fopen(filename, "r");
+    if (f == NULL) {
+        return -1;
+    }
+
+    while (acl_count != MAX_ACLS &&
+           fgets(line, sizeof(line), f) != NULL) {
+        char *ptr = line;
+        char *cmd, *arg, *argend;
+
+        while (isspace(*ptr)) {
+            ptr++;
+        }
+
+        /* skip comments and empty lines */
+        if (*ptr == '#' || *ptr == 0) {
+            continue;
+        }
+
+        cmd = ptr;
+        arg = strchr(cmd, ' ');
+        if (arg == NULL) {
+            arg = strchr(cmd, '\t');
+        }
+
+        if (arg == NULL) {
+            fprintf(stderr, "Invalid config line:\n  %s\n", line);
+            fclose(f);
+            errno = EINVAL;
+            return -1;
+        }
+
+        *arg = 0;
+        arg++;
+        while (isspace(*arg)) {
+            arg++;
+        }
+
+        argend = arg + strlen(arg);
+        while (arg != argend && isspace(*(argend - 1))) {
+            argend--;
+        }
+        *argend = 0;
+
+        if (strcmp(cmd, "deny") == 0) {
+            if (strcmp(arg, "all") == 0) {
+                acls[acl_count].type = ACL_DENY_ALL;
+            } else {
+                acls[acl_count].type = ACL_DENY;
+                snprintf(acls[acl_count].iface, IFNAMSIZ, "%s", arg);
+            }
+            acl_count++;
+        } else if (strcmp(cmd, "allow") == 0) {
+            if (strcmp(arg, "all") == 0) {
+                acls[acl_count].type = ACL_ALLOW_ALL;
+            } else {
+                acls[acl_count].type = ACL_ALLOW;
+                snprintf(acls[acl_count].iface, IFNAMSIZ, "%s", arg);
+            }
+            acl_count++;
+        } else if (strcmp(cmd, "include") == 0) {
+            /* ignore errors */
+            parse_acl_file(arg, acls, &acl_count);
+        } else {
+            fprintf(stderr, "Unknown command `%s'\n", cmd);
+            fclose(f);
+            errno = EINVAL;
+            return -1;
+        }
+    }
+
+    *pacl_count = acl_count;
+
+    fclose(f);
+
+    return 0;
+}
+
 static int has_vnet_hdr(int fd)
 {
     unsigned int features;
@@ -95,6 +195,9 @@ int main(int argc, char **argv)
     const char *bridge;
     char iface[IFNAMSIZ];
     int index;
+    ACLRule acls[MAX_ACLS];
+    int acl_count = 0;
+    int i, access_allowed;
 
     /* parse arguments */
     if (argc < 3 || argc > 4) {
@@ -115,6 +218,41 @@ int main(int argc, char **argv)
     bridge = argv[index++];
     unixfd = atoi(argv[index++]);
 
+    /* parse default acl file */
+    if (parse_acl_file(DEFAULT_ACL_FILE, acls, &acl_count) == -1) {
+        fprintf(stderr, "failed to parse default acl file `%s'\n",
+                DEFAULT_ACL_FILE);
+        return -errno;
+    }
+
+    /* validate bridge against acl -- default policy is to deny */
+    access_allowed = 0;
+    for (i = 0; i < acl_count; i++) {
+        switch (acls[i].type) {
+        case ACL_ALLOW_ALL:
+            access_allowed = 1;
+            break;
+        case ACL_ALLOW:
+            if (strcmp(bridge, acls[i].iface) == 0) {
+                access_allowed = 1;
+            }
+            break;
+        case ACL_DENY_ALL:
+            access_allowed = 0;
+            break;
+        case ACL_DENY:
+            if (strcmp(bridge, acls[i].iface) == 0) {
+                access_allowed = 0;
+            }
+            break;
+        }
+    }
+
+    if (access_allowed == 0) {
+        fprintf(stderr, "access denied by acl file\n");
+        return -EPERM;
+    }
+
     /* open a socket to use to control the network interfaces */
     ctlfd = socket(AF_INET, SOCK_STREAM, 0);
     if (ctlfd == -1) {
-- 
1.6.2.5

  parent reply	other threads:[~2009-11-04  0:28 UTC|newest]

Thread overview: 126+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-11-04  0:28 [Qemu-devel] [PATCH 0/4] net-bridge: rootless bridge support for qemu Anthony Liguori
2009-11-04  0:28 ` [Qemu-devel] [PATCH 1/4] Add basic version of bridge helper Anthony Liguori
2009-11-04  0:28 ` Anthony Liguori [this message]
2009-11-04 13:38   ` [Qemu-devel] [PATCH 2/4] Add access control support toqemu-bridge-helper Krumme, Chris
2009-11-04 14:23     ` Anthony Liguori
2009-11-04 14:37       ` Krumme, Chris
2009-11-05 15:06   ` [Qemu-devel] [PATCH 2/4] Add access control support to qemu-bridge-helper Daniel P. Berrange
2009-11-04  0:28 ` [Qemu-devel] [PATCH 3/4] Add cap reduction support to enable use as SUID binary Anthony Liguori
2009-11-04  0:28 ` [Qemu-devel] [PATCH 4/4] Add support for -net bridge Anthony Liguori
2009-11-04 13:49   ` Krumme, Chris
2009-11-04 14:23     ` Anthony Liguori
2009-11-05 14:41   ` Avi Kivity
2009-11-05 14:45     ` Anthony Liguori
2009-11-05 14:49       ` Avi Kivity
2009-11-06  2:29       ` Jamie Lokier
2009-11-07 17:29   ` David Woodhouse
2009-11-07 22:11     ` Anthony Liguori
2009-11-08  8:27       ` Avi Kivity
2009-11-08  8:43         ` Arnd Bergmann
2009-11-08  8:55           ` Avi Kivity
2009-11-09 14:20         ` Anthony Liguori
2009-11-09 15:39           ` Jamie Lokier
2009-11-09 15:43             ` Anthony Liguori
2009-11-09 19:19               ` Jamie Lokier
2009-11-10 12:23           ` Avi Kivity
2009-11-04 12:02 ` [Qemu-devel] [PATCH 0/4] net-bridge: rootless bridge support for qemu Alexander Graf
2009-11-04 14:42   ` Anthony Liguori
2009-11-04 15:02     ` Alexander Graf
2009-11-04 16:02       ` Anthony Liguori
2009-11-04 17:04 ` [Qemu-devel] " Michael S. Tsirkin
2009-11-04 19:48   ` Anthony Liguori
2009-11-04 20:04     ` Michael S. Tsirkin
2009-11-04 20:44       ` Anthony Liguori
2009-11-05  8:17         ` Michael S. Tsirkin
2009-11-05 13:05           ` Anthony Liguori
2009-11-04 22:40 ` Dustin Kirkland
2009-11-05  0:52   ` Anthony Liguori
2009-11-05  2:12     ` Dustin Kirkland
2009-11-05  4:12 ` [Qemu-devel] " Jamie Lokier
2009-11-05  8:21   ` Michael S. Tsirkin
2009-11-06  2:03     ` Jamie Lokier
2009-11-06 11:58       ` Arnd Bergmann
2009-11-06 20:26         ` Jamie Lokier
2009-11-08 11:55           ` Michael S. Tsirkin
2009-11-05 13:11   ` Anthony Liguori
2009-11-05 14:33 ` Avi Kivity
2009-11-05 14:36   ` Avi Kivity
2009-11-05 14:46     ` Daniel P. Berrange
2009-11-05 14:53       ` Anthony Liguori
2009-11-05 16:41         ` Jamie Lokier
2009-11-05 16:51           ` Daniel P. Berrange
2009-11-06  1:53             ` Jamie Lokier
2009-11-05 14:50     ` Anthony Liguori
2009-11-05 15:05       ` Avi Kivity
2009-11-05 15:50         ` Anthony Liguori
2009-11-05 16:02           ` Avi Kivity
2009-11-05 16:19             ` Anthony Liguori
2009-11-05 16:28               ` Avi Kivity
2009-11-05 16:37               ` Jamie Lokier
2009-11-05 16:45                 ` Anthony Liguori
2009-11-05 17:20                   ` Arnd Bergmann
2009-11-05 17:42                     ` Anthony Liguori
2009-11-05 18:02                       ` Arnd Bergmann
2009-11-05 19:54                         ` Anthony Liguori
2009-11-05 18:14                       ` Avi Kivity
2009-11-05 18:11                     ` Avi Kivity
2009-11-05 19:58                       ` Anthony Liguori
2009-11-06  1:48                         ` Jamie Lokier
2009-11-06  7:22                         ` Avi Kivity
2009-11-06 10:54                           ` Jamie Lokier
2009-11-06 12:42                             ` Anthony Liguori
2009-11-07  3:44                               ` Jamie Lokier
2009-11-06 14:19                           ` Anthony Liguori
2009-11-07  9:14                             ` Avi Kivity
2009-11-07  9:43                               ` Avi Kivity
2009-11-07 14:07                                 ` Anthony Liguori
2009-11-07 21:50                                   ` Arnd Bergmann
2009-11-07 22:12                                     ` Anthony Liguori
2009-11-08  8:11                                       ` Avi Kivity
2009-11-07 14:04                               ` Anthony Liguori
2009-11-06  0:29                       ` Anthony Liguori
2009-11-06  7:26                         ` Avi Kivity
2009-11-06 16:09                           ` Anthony Liguori
2009-11-07  9:27                             ` Avi Kivity
2009-11-07 10:44                               ` Jamie Lokier
2009-11-07 11:23                                 ` Avi Kivity
2009-11-09 19:35                                   ` Jamie Lokier
2009-11-10 12:25                                     ` Avi Kivity
2009-11-10 13:33                                       ` Jamie Lokier
2009-11-07 13:59                               ` Anthony Liguori
2009-11-05 16:29         ` Jamie Lokier
2009-11-05 14:57   ` Anthony Liguori
2009-11-05 15:11     ` Avi Kivity
2009-11-05 15:33       ` Avi Kivity
2009-11-05 15:58         ` Anthony Liguori
2009-11-05 16:07           ` Avi Kivity
2009-11-06  2:19             ` Jamie Lokier
2009-11-05 16:06       ` Anthony Liguori
2009-11-05 16:15         ` Avi Kivity
2009-11-05 16:25           ` Anthony Liguori
2009-11-05 16:33             ` Avi Kivity
2009-11-05 16:50               ` Anthony Liguori
2009-11-05 17:16                 ` Scott Tsai
2009-11-05 18:19                   ` Avi Kivity
2009-11-06  2:16                     ` Jamie Lokier
2009-11-05 18:19                 ` Avi Kivity
2009-11-06  2:17                   ` Jamie Lokier
2009-11-05 15:11     ` Daniel P. Berrange
2009-11-05 15:14       ` Avi Kivity
2009-11-05 15:20         ` Daniel P. Berrange
2009-11-05 15:59         ` Anthony Liguori
2009-11-05 16:20           ` Avi Kivity
2009-11-05 16:28             ` Anthony Liguori
2009-11-05 16:35               ` Avi Kivity
2009-11-05 16:53                 ` Daniel P. Berrange
2009-11-05 17:03                   ` Anthony Liguori
2009-11-05 17:16                     ` Daniel P. Berrange
2009-11-06  2:08                       ` Jamie Lokier
2009-11-05 17:26                     ` Arnd Bergmann
2009-11-05 19:54                       ` Gerhard Stenzel
2009-11-06  2:11             ` Jamie Lokier
2009-11-05 15:00 ` [Qemu-devel] " Mark McLoughlin
2009-11-05 15:14   ` Daniel P. Berrange
2009-11-05 15:28     ` Dustin Kirkland
2009-11-05 15:06 ` Arnd Bergmann
  -- strict thread matches above, loose matches on Subject: below --
2011-10-06 15:38 [Qemu-devel] [PATCH 0/4] -net tap: " Richa Marwaha
2011-10-06 15:38 ` [Qemu-devel] [PATCH 2/4] Add access control support to qemu-bridge-helper Richa Marwaha

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1257294485-27015-3-git-send-email-aliguori@us.ibm.com \
    --to=aliguori@us.ibm.com \
    --cc=arndbergmann@googlemail.com \
    --cc=kirkland@canonical.com \
    --cc=markmc@redhat.com \
    --cc=mst@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=quintela@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).