]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
tools: move lxc-attach to API symbols only
authorChristian Brauner <christian.brauner@ubuntu.com>
Fri, 12 Jan 2018 12:13:09 +0000 (13:13 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Tue, 6 Feb 2018 20:03:29 +0000 (21:03 +0100)
Closes #2073.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/Makefile.am
src/lxc/confile.c
src/lxc/confile.h
src/lxc/tools/arguments.c
src/lxc/tools/lxc_attach.c
src/lxc/tools/lxc_autostart.c
src/lxc/tools/tool_utils.c [new file with mode: 0644]
src/lxc/tools/tool_utils.h [new file with mode: 0644]

index 8f9a7ab2979a8868009f30b07879a66823c115d8..185d2a480790531281df67cb358765989e17c1f6 100644 (file)
@@ -4,7 +4,6 @@ pkginclude_HEADERS = \
        version.h
 
 noinst_HEADERS = \
-       tools/arguments.h \
        attach.h \
        storage/storage.h \
        storage/aufs.h \
@@ -18,6 +17,9 @@ noinst_HEADERS = \
        storage/rsync.h \
        storage/zfs.h \
        storage/storage_utils.h \
+       tools/arguments.h \
+       tools/tool_utils.h \
+       tools/tool_list.h \
        cgroups/cgroup.h \
        cgroups/cgroup_utils.h \
        caps.h \
@@ -266,7 +268,7 @@ AM_LDFLAGS += -Wl,-rpath -Wl,$(libdir)
 endif
 LDADD=liblxc.la @CAP_LIBS@ @SELINUX_LIBS@ @SECCOMP_LIBS@
 
-lxc_attach_SOURCES = tools/lxc_attach.c tools/arguments.c
+lxc_attach_SOURCES = tools/lxc_attach.c tools/arguments.c tools/tool_utils.c
 lxc_autostart_SOURCES = tools/lxc_autostart.c tools/arguments.c
 lxc_cgroup_SOURCES = tools/lxc_cgroup.c tools/arguments.c
 lxc_config_SOURCES = tools/lxc_config.c tools/arguments.c
index fa4f84da9e516382ce1384ccb80db1b92ba45a66..9950c7ea4c2561fc5307a8873e0da5bce19561c2 100644 (file)
@@ -2409,47 +2409,6 @@ signed long lxc_config_parse_arch(const char *arch)
        return -1;
 }
 
-int lxc_fill_elevated_privileges(char *flaglist, int *flags)
-{
-       char *token, *saveptr = NULL;
-       int i, aflag;
-       struct {
-               const char *token;
-               int flag;
-       } all_privs[] = {
-               { "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP    },
-               { "CAP",    LXC_ATTACH_DROP_CAPABILITIES },
-               { "LSM",    LXC_ATTACH_LSM_EXEC          },
-               { NULL,     0                            }
-       };
-
-       if (!flaglist) {
-               /* For the sake of backward compatibility, drop all privileges
-               *  if none is specified.
-                */
-               for (i = 0; all_privs[i].token; i++)
-                       *flags |= all_privs[i].flag;
-
-               return 0;
-       }
-
-       token = strtok_r(flaglist, "|", &saveptr);
-       while (token) {
-               aflag = -1;
-               for (i = 0; all_privs[i].token; i++)
-                       if (!strcmp(all_privs[i].token, token))
-                               aflag = all_privs[i].flag;
-               if (aflag < 0)
-                       return -1;
-
-               *flags |= aflag;
-
-               token = strtok_r(NULL, "|", &saveptr);
-       }
-
-       return 0;
-}
-
 /* Write out a configuration file. */
 void write_config(FILE *fout, struct lxc_conf *c)
 {
index d50217860408e6151774c0d61988f428a481b586..6c69bc7a5f3a2d8f4783f150241facf8eb8d2223 100644 (file)
@@ -92,8 +92,6 @@ extern int lxc_config_define_load(struct lxc_list *defines,
 /* needed for lxc-attach */
 extern signed long lxc_config_parse_arch(const char *arch);
 
-extern int lxc_fill_elevated_privileges(char *flaglist, int *flags);
-
 extern int lxc_clear_config_item(struct lxc_conf *c, const char *key);
 
 extern void write_config(FILE *fout, struct lxc_conf *c);
index 272340b65dbf53b7b3b8138f8897e0a8c0a852a5..f98053feca219222a2220869d58359e4a8aa80ab 100644 (file)
@@ -182,6 +182,13 @@ static int lxc_arguments_lxcpath_add(struct lxc_arguments *args,
        return 0;
 }
 
+void remove_trailing_slashes(char *p)
+{
+       int l = strlen(p);
+       while (--l >= 0 && (p[l] == '/' || p[l] == '\n'))
+               p[l] = '\0';
+}
+
 extern int lxc_arguments_parse(struct lxc_arguments *args, int argc,
                               char *const argv[])
 {
@@ -250,7 +257,7 @@ extern int lxc_arguments_parse(struct lxc_arguments *args, int argc,
        /* If no lxcpaths were given, use default */
        if (!args->lxcpath_cnt) {
                ret = lxc_arguments_lxcpath_add(
-                   args, lxc_global_config_value("lxc.lxcpath"));
+                   args, lxc_get_global_config_item("lxc.lxcpath"));
                if (ret < 0)
                        return ret;
        }
index 926bf079eea8d9f9761d21e4f2b3ab1a756c4016..b2c405d3ad921e8f294c5b25c53e5ed76fcac812 100644 (file)
@@ -27,6 +27,7 @@
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <termios.h>
 #include <unistd.h>
 #include <sys/ioctl.h>
 
 #include <lxc/lxccontainer.h>
 
-#include "attach.h"
 #include "arguments.h"
-#include "caps.h"
-#include "conf.h"
-#include "confile.h"
-#include "console.h"
-#include "log.h"
-#include "list.h"
-#include "mainloop.h"
-#include "utils.h"
+#include "tool_utils.h"
 
 static const struct option my_longopts[] = {
        {"elevated-privileges", optional_argument, 0, 'e'},
@@ -290,7 +283,6 @@ int main(int argc, char *argv[])
        r = lxc_log_init(&log);
        if (r)
                exit(EXIT_FAILURE);
-       lxc_log_options_no_override();
 
        if (geteuid()) {
                if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
index 48727b9f12b66b38a72ea238e6ca212a150dee13..a3d4a8a8a47d5c01e3a7cf71646c67c67899bb7f 100644 (file)
@@ -24,7 +24,6 @@
 #include <lxc/lxccontainer.h>
 
 #include "arguments.h"
-#include "list.h"
 #include "log.h"
 #include "utils.h"
 
diff --git a/src/lxc/tools/tool_utils.c b/src/lxc/tools/tool_utils.c
new file mode 100644 (file)
index 0000000..39b3881
--- /dev/null
@@ -0,0 +1,336 @@
+/* liblxcapi
+ *
+ * Copyright © 2018 Christian Brauner <christian.brauner@ubuntu.com>.
+ * Copyright © 2018 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <linux/sched.h>
+#include <sys/prctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#if HAVE_SYS_PERSONALITY_H
+#include <sys/personality.h>
+#endif
+
+#include <lxc/lxccontainer.h>
+
+#include "tool_utils.h"
+
+int lxc_fill_elevated_privileges(char *flaglist, int *flags)
+{
+       char *token, *saveptr = NULL;
+       int i, aflag;
+       struct {
+               const char *token;
+               int flag;
+       } all_privs[] = {
+               { "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP    },
+               { "CAP",    LXC_ATTACH_DROP_CAPABILITIES },
+               { "LSM",    LXC_ATTACH_LSM_EXEC          },
+               { NULL,     0                            }
+       };
+
+       if (!flaglist) {
+               /* For the sake of backward compatibility, drop all privileges
+               *  if none is specified.
+                */
+               for (i = 0; all_privs[i].token; i++)
+                       *flags |= all_privs[i].flag;
+
+               return 0;
+       }
+
+       token = strtok_r(flaglist, "|", &saveptr);
+       while (token) {
+               aflag = -1;
+               for (i = 0; all_privs[i].token; i++)
+                       if (!strcmp(all_privs[i].token, token))
+                               aflag = all_privs[i].flag;
+               if (aflag < 0)
+                       return -1;
+
+               *flags |= aflag;
+
+               token = strtok_r(NULL, "|", &saveptr);
+       }
+
+       return 0;
+}
+
+signed long lxc_config_parse_arch(const char *arch)
+{
+#if HAVE_SYS_PERSONALITY_H
+       size_t i;
+       struct per_name {
+               char *name;
+               unsigned long per;
+       } pername[] = {
+           { "x86",       PER_LINUX32 },
+           { "linux32",   PER_LINUX32 },
+           { "i386",      PER_LINUX32 },
+           { "i486",      PER_LINUX32 },
+           { "i586",      PER_LINUX32 },
+           { "i686",      PER_LINUX32 },
+           { "athlon",    PER_LINUX32 },
+           { "mips",      PER_LINUX32 },
+           { "mipsel",    PER_LINUX32 },
+           { "ppc",       PER_LINUX32 },
+           { "arm",       PER_LINUX32 },
+           { "armv7l",    PER_LINUX32 },
+           { "armhf",     PER_LINUX32 },
+           { "armel",     PER_LINUX32 },
+           { "powerpc",   PER_LINUX32 },
+           { "linux64",   PER_LINUX   },
+           { "x86_64",    PER_LINUX   },
+           { "amd64",     PER_LINUX   },
+           { "mips64",    PER_LINUX   },
+           { "mips64el",  PER_LINUX   },
+           { "ppc64",     PER_LINUX   },
+           { "ppc64le",   PER_LINUX   },
+           { "ppc64el",   PER_LINUX   },
+           { "powerpc64", PER_LINUX   },
+           { "s390x",     PER_LINUX   },
+           { "aarch64",   PER_LINUX   },
+           { "arm64",     PER_LINUX   },
+       };
+       size_t len = sizeof(pername) / sizeof(pername[0]);
+
+       for (i = 0; i < len; i++) {
+               if (!strcmp(pername[i].name, arch))
+                       return pername[i].per;
+       }
+#endif
+
+       return -1;
+}
+
+enum {
+       LXC_NS_USER,
+       LXC_NS_MNT,
+       LXC_NS_PID,
+       LXC_NS_UTS,
+       LXC_NS_IPC,
+       LXC_NS_NET,
+       LXC_NS_CGROUP,
+       LXC_NS_MAX
+};
+
+const static struct ns_info {
+       const char *proc_name;
+       int clone_flag;
+} ns_info[LXC_NS_MAX]   = {
+       [LXC_NS_USER]   = { "user",   CLONE_NEWUSER   },
+       [LXC_NS_MNT]    = { "mnt",    CLONE_NEWNS     },
+       [LXC_NS_PID]    = { "pid",    CLONE_NEWPID    },
+       [LXC_NS_UTS]    = { "uts",    CLONE_NEWUTS    },
+       [LXC_NS_IPC]    = { "ipc",    CLONE_NEWIPC    },
+       [LXC_NS_NET]    = { "net",    CLONE_NEWNET    },
+       [LXC_NS_CGROUP] = { "cgroup", CLONE_NEWCGROUP }
+};
+
+int lxc_namespace_2_cloneflag(const char *namespace)
+{
+       int i;
+       for (i = 0; i < LXC_NS_MAX; i++)
+               if (!strcasecmp(ns_info[i].proc_name, namespace))
+                       return ns_info[i].clone_flag;
+
+       fprintf(stderr, "Invalid namespace name \"%s\"", namespace);
+       return -EINVAL;
+}
+
+int lxc_fill_namespace_flags(char *flaglist, int *flags)
+{
+       char *token, *saveptr = NULL;
+       int aflag;
+
+       if (!flaglist) {
+               fprintf(stderr, "At least one namespace is needed\n");
+               return -1;
+       }
+
+       token = strtok_r(flaglist, "|", &saveptr);
+       while (token) {
+
+               aflag = lxc_namespace_2_cloneflag(token);
+               if (aflag < 0)
+                       return -1;
+
+               *flags |= aflag;
+
+               token = strtok_r(NULL, "|", &saveptr);
+       }
+
+       return 0;
+}
+
+#if HAVE_LIBCAP
+
+#ifndef PR_CAPBSET_READ
+#define PR_CAPBSET_READ 23
+#endif
+
+int lxc_caps_init(void)
+{
+       uid_t uid = getuid();
+       gid_t gid = getgid();
+       uid_t euid = geteuid();
+
+       if (!uid)
+               return 0;
+
+       if (uid && !euid) {
+               if (prctl(PR_SET_KEEPCAPS, 1)) {
+                       fprintf(stderr, "%s - Failed to set PR_SET_KEEPCAPS\n", strerror(errno));
+                       return -1;
+               }
+
+               if (setresgid(gid, gid, gid)) {
+                       fprintf(stderr, "%s - Failed to change gid to %d\n", strerror(errno), gid);
+                       return -1;
+               }
+
+               if (setresuid(uid, uid, uid)) {
+                       fprintf(stderr, "%s - Failed to change uid to %d\n", strerror(errno), uid);
+                       return -1;
+               }
+
+               if (lxc_caps_up()) {
+                       fprintf(stderr, "%s - Failed to restore capabilities\n", strerror(errno));
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+int lxc_caps_up(void)
+{
+       cap_t caps;
+       cap_value_t cap;
+       int ret;
+
+       /* when we are run as root, we don't want to play
+        * with the capabilities */
+       if (!getuid())
+               return 0;
+
+       caps = cap_get_proc();
+       if (!caps) {
+               fprintf(stderr, "%s - Failed to cap_get_proc\n", strerror(errno));
+               return -1;
+       }
+
+       for (cap = 0; cap <= CAP_LAST_CAP; cap++) {
+               cap_flag_value_t flag;
+
+               ret = cap_get_flag(caps, cap, CAP_PERMITTED, &flag);
+               if (ret) {
+                       if (errno == EINVAL) {
+                               break;
+                       } else {
+                               fprintf(stderr, "%s- Failed to call cap_get_flag\n", strerror(errno));
+                               goto out;
+                       }
+               }
+
+               ret = cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, flag);
+               if (ret) {
+                       fprintf(stderr, "%s - Failed to call cap_set_flag", strerror(errno));
+                       goto out;
+               }
+       }
+
+       ret = cap_set_proc(caps);
+       if (ret) {
+               fprintf(stderr, "%s - Failed to cap_set_proc", strerror(errno));
+               goto out;
+       }
+
+out:
+       cap_free(caps);
+       return 0;
+}
+
+#endif
+
+int lxc_wait_for_pid_status(pid_t pid)
+{
+       int status, ret;
+
+again:
+       ret = waitpid(pid, &status, 0);
+       if (ret == -1) {
+               if (errno == EINTR)
+                       goto again;
+               return -1;
+       }
+       if (ret != pid)
+               goto again;
+       return status;
+}
+
+int lxc_safe_int(const char *numstr, int *converted)
+{
+       char *err = NULL;
+       signed long int sli;
+
+       errno = 0;
+       sli = strtol(numstr, &err, 0);
+       if (errno == ERANGE && (sli == LONG_MAX || sli == LONG_MIN))
+               return -ERANGE;
+
+       if (errno != 0 && sli == 0)
+               return -EINVAL;
+
+       if (err == numstr || *err != '\0')
+               return -EINVAL;
+
+       if (sli > INT_MAX || sli < INT_MIN)
+               return -ERANGE;
+
+       *converted = (int)sli;
+       return 0;
+}
+
+int lxc_safe_long(const char *numstr, long int *converted)
+{
+       char *err = NULL;
+       signed long int sli;
+
+       errno = 0;
+       sli = strtol(numstr, &err, 0);
+       if (errno == ERANGE && (sli == LONG_MAX || sli == LONG_MIN))
+               return -ERANGE;
+
+       if (errno != 0 && sli == 0)
+               return -EINVAL;
+
+       if (err == numstr || *err != '\0')
+               return -EINVAL;
+
+       *converted = sli;
+       return 0;
+}
diff --git a/src/lxc/tools/tool_utils.h b/src/lxc/tools/tool_utils.h
new file mode 100644 (file)
index 0000000..9f0e6a0
--- /dev/null
@@ -0,0 +1,130 @@
+/* liblxcapi
+ *
+ * Copyright © 2018 Christian Brauner <christian.brauner@ubuntu.com>.
+ * Copyright © 2018 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __LXC_UTILS_H
+#define __LXC_UTILS_H
+
+/* Properly support loop devices on 32bit systems. */
+#define _FILE_OFFSET_BITS 64
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <unistd.h>
+
+#include <lxc/lxccontainer.h>
+
+#include "tool_list.h"
+
+#define TOOL_MAXPATHLEN 4096
+
+#ifndef CLONE_PARENT_SETTID
+#define CLONE_PARENT_SETTID 0x00100000
+#endif
+
+#ifndef CLONE_CHILD_CLEARTID
+#define CLONE_CHILD_CLEARTID 0x00200000
+#endif
+
+#ifndef CLONE_CHILD_SETTID
+#define CLONE_CHILD_SETTID 0x01000000
+#endif
+
+#ifndef CLONE_VFORK
+#define CLONE_VFORK 0x00004000
+#endif
+
+#ifndef CLONE_THREAD
+#define CLONE_THREAD 0x00010000
+#endif
+
+#ifndef CLONE_SETTLS
+#define CLONE_SETTLS 0x00080000
+#endif
+
+#ifndef CLONE_VM
+#define CLONE_VM 0x00000100
+#endif
+
+#ifndef CLONE_FILES
+#define CLONE_FILES 0x00000400
+#endif
+
+#ifndef CLONE_FS
+#  define CLONE_FS                0x00000200
+#endif
+#ifndef CLONE_NEWNS
+#  define CLONE_NEWNS             0x00020000
+#endif
+#ifndef CLONE_NEWCGROUP
+#  define CLONE_NEWCGROUP         0x02000000
+#endif
+#ifndef CLONE_NEWUTS
+#  define CLONE_NEWUTS            0x04000000
+#endif
+#ifndef CLONE_NEWIPC
+#  define CLONE_NEWIPC            0x08000000
+#endif
+#ifndef CLONE_NEWUSER
+#  define CLONE_NEWUSER           0x10000000
+#endif
+#ifndef CLONE_NEWPID
+#  define CLONE_NEWPID            0x20000000
+#endif
+#ifndef CLONE_NEWNET
+#  define CLONE_NEWNET            0x40000000
+#endif
+
+enum {
+       LXC_NS_USER,
+       LXC_NS_MNT,
+       LXC_NS_PID,
+       LXC_NS_UTS,
+       LXC_NS_IPC,
+       LXC_NS_NET,
+       LXC_NS_CGROUP,
+       LXC_NS_MAX
+};
+
+extern int lxc_fill_elevated_privileges(char *flaglist, int *flags);
+extern signed long lxc_config_parse_arch(const char *arch);
+extern int lxc_namespace_2_cloneflag(const char *namespace);
+extern int lxc_fill_namespace_flags(char *flaglist, int *flags);
+
+#if HAVE_LIBCAP
+#include <sys/capability.h>
+
+extern int lxc_caps_up(void);
+extern int lxc_caps_init(void);
+#else
+static inline int lxc_caps_up(void) {
+       return 0;
+}
+
+static inline int lxc_caps_init(void) {
+       return 0;
+}
+#endif
+
+extern int lxc_wait_for_pid_status(pid_t pid);
+extern int lxc_safe_int(const char *numstr, int *converted);
+extern int lxc_safe_long(const char *numstr, long int *converted);
+
+#endif /* __LXC_UTILS_H */