]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
python3: Support unpriv containers
authorStéphane Graber <stgraber@ubuntu.com>
Wed, 11 Dec 2013 19:46:34 +0000 (14:46 -0500)
committerStéphane Graber <stgraber@ubuntu.com>
Wed, 11 Dec 2013 22:06:41 +0000 (17:06 -0500)
This removes any existing uid check in the python3 binding and tools,
replacing those by .controllable where appropriate.

Extra checks are also added to make lxc-ls work as a user, returning as
much information as can possibly be retrieved.

Signed-off-by: Stéphane Graber <stgraber@ubuntu.com>
Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
src/lxc/lxc-device
src/lxc/lxc-ls
src/lxc/lxc-start-ephemeral.in
src/python-lxc/lxc/__init__.py

index 9d24248ec91da810eb5daeae4a302509cdbaf77f..78be6ab8791dd5d2a0b6b9c0226cd5a2cdcd9c6b 100644 (file)
@@ -66,14 +66,10 @@ subparser_add.add_argument(dest="name", metavar="NAME", nargs="?",
 args = parser.parse_args()
 
 # Some basic checks
+## Check for valid action
 if not hasattr(args, "action"):
     parser.error(_("You must specify an action."))
 
-## The user needs to be uid 0
-if not os.geteuid() == 0:
-    parser.error(_("You must be root to run this script. Try running: sudo %s"
-                   % (sys.argv[0])))
-
 ## Don't rename if no alternative name
 if not args.name:
     args.name = args.device
@@ -81,6 +77,11 @@ if not args.name:
 ## Check that the container is ready
 container = lxc.Container(args.container, args.lxcpath)
 
+## Check that we have control over the container
+if not container.controllable:
+    parser.error("Insufficent privileges to control: %s" % container.name)
+
+## Check that the container is running
 if not container.running:
     parser.error("The container must be running.")
 
index 26c9684593edc59122c0d32a1b00bef7cfb538f2..b058bd028a2e267c9191e6c046b7df46a8a57136 100755 (executable)
@@ -123,8 +123,7 @@ parser.add_argument("-P", "--lxcpath", dest="lxcpath", metavar="PATH",
                     default=lxc.default_config_path)
 
 parser.add_argument("--active", action="store_true",
-                    help=_("list only active containers "
-                           "(same as --running --frozen)"))
+                    help=_("list only active containers"))
 
 parser.add_argument("--frozen", dest="state", action="append_const",
                     const="FROZEN", help=_("list only frozen containers"))
@@ -153,7 +152,7 @@ args = parser.parse_args()
 if args.active:
     if not args.state:
         args.state = []
-    args.state += ["RUNNING", "FROZEN"]
+    args.state += ["RUNNING", "FROZEN", "UNKNOWN"]
 
 # If the output is piped, default to --one
 if not sys.stdout.isatty():
@@ -166,25 +165,27 @@ lxcpath = os.environ.get('NESTED', args.lxcpath)
 args.fancy_format = args.fancy_format.strip().split(",")
 
 # Basic checks
-## The user needs to be uid 0
-if not os.geteuid() == 0 and (args.fancy or args.state):
-    parser.error(_("You must be root to access advanced container properties. "
-                   "Try running: sudo %s"
-                   % (sys.argv[0])))
+## Check for setns
+SUPPORT_SETNS = os.path.exists("/proc/self/ns")
+SUPPORT_SETNS_NET = False
+SUPPORT_SETNS_PID = False
+if SUPPORT_SETNS:
+    SUPPORT_SETNS_NET = os.path.exists("/proc/self/ns/net")
+    SUPPORT_SETNS_PID = os.path.exists("/proc/self/ns/pid")
 
 ## Nesting requires setns to pid and net ns
 if args.nesting:
-    if not os.path.exists("/proc/self/ns/"):
+    if not SUPPORT_SETNS:
         parser.error(_("Showing nested containers requires setns support "
                        "which your kernel doesn't support."))
 
-    if not "pid" in os.listdir("/proc/self/ns/"):
+    if not SUPPORT_SETNS_NET:
         parser.error(_("Showing nested containers requires setns to the "
-                       "PID namespace which your kernel doesn't support."))
+                       "network namespace which your kernel doesn't support."))
 
-    if not "net" in os.listdir("/proc/self/ns/"):
+    if not SUPPORT_SETNS_PID:
         parser.error(_("Showing nested containers requires setns to the "
-                       "network namespace which your kernel doesn't support."))
+                       "PID namespace which your kernel doesn't support."))
 
 # List of containers, stored as dictionaries
 containers = []
@@ -203,8 +204,13 @@ for container_name in lxc.list_containers(config_path=lxcpath):
 
     container = lxc.Container(container_name, args.lxcpath)
 
+    if container.controllable:
+        state = container.state
+    else:
+        state = 'UNKNOWN'
+
     # Filter by status
-    if args.state and container.state not in args.state:
+    if args.state and state not in args.state:
         continue
 
     # Nothing more is needed if we're not printing some fancy output
@@ -214,17 +220,30 @@ for container_name in lxc.list_containers(config_path=lxcpath):
 
     # Some extra field we may want
     if 'state' in args.fancy_format or args.nesting:
-        entry['state'] = container.state
+        entry['state'] = state
 
     if 'pid' in args.fancy_format or args.nesting:
         entry['pid'] = "-"
-        if container.init_pid != -1:
+        if state == 'UNKNOWN':
+            entry['pid'] = state
+        elif container.init_pid != -1:
             entry['pid'] = str(container.init_pid)
 
     # Get the IPs
     for family, protocol in {'inet': 'ipv4', 'inet6': 'ipv6'}.items():
         if protocol in args.fancy_format or args.nesting:
             entry[protocol] = "-"
+
+            if state == 'UNKNOWN':
+                entry[protocol] = state
+                continue
+
+            # FIXME: We should get get_ips working as non-root
+            if container.running and (not SUPPORT_SETNS_NET \
+                    or os.geteuid() != 0):
+                entry[protocol] = 'UNKNOWN'
+                continue
+
             ips = container.get_ips(family=family)
             if ips:
                 entry[protocol] = ", ".join(ips)
index 0f0c398b5ccfe73bd22dda7a2bdc27ce6a713067..118b1b5f7eee7c8bf6476e975d612be8b3008b96 100644 (file)
@@ -118,11 +118,6 @@ if not args.storage_type:
 if args.keep_data and args.storage_type == "tmpfs":
     parser.error(_("You can't use -k with the tmpfs storage type."))
 
-## The user needs to be uid 0
-if not os.geteuid() == 0:
-    parser.error(_("You must be root to run this script. Try running: sudo %s"
-                   % (sys.argv[0])))
-
 # Load the orig container
 orig = lxc.Container(args.orig, args.lxcpath)
 if not orig.defined:
index c3d840c45b762beb12248a895b02132cb777eb5a..e708781116017585eca3c91b4cc74c624a567419 100644 (file)
@@ -150,9 +150,6 @@ class Container(_lxc.Container):
             Creates a new Container instance.
         """
 
-        if os.geteuid() != 0:
-            raise Exception("Running as non-root.")
-
         if config_path:
             _lxc.Container.__init__(self, name, config_path)
         else: