From 03e6adc680f319e34228cb8e5ea3cc18b400ad36 Mon Sep 17 00:00:00 2001 From: 2xsec Date: Fri, 29 Jun 2018 23:39:03 +0900 Subject: [PATCH] tools: remote tool_list, tool_utils Signed-off-by: 2xsec --- src/lxc/Makefile.am | 2 - src/lxc/tools/tool_list.h | 167 ----- src/lxc/tools/tool_utils.c | 1219 ------------------------------------ src/lxc/tools/tool_utils.h | 237 ------- 4 files changed, 1625 deletions(-) delete mode 100644 src/lxc/tools/tool_list.h delete mode 100644 src/lxc/tools/tool_utils.c delete mode 100644 src/lxc/tools/tool_utils.h diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am index 57c552390..da647740b 100644 --- a/src/lxc/Makefile.am +++ b/src/lxc/Makefile.am @@ -17,8 +17,6 @@ noinst_HEADERS = \ 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 \ diff --git a/src/lxc/tools/tool_list.h b/src/lxc/tools/tool_list.h deleted file mode 100644 index 9858081ab..000000000 --- a/src/lxc/tools/tool_list.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * lxc: linux Container library - * - * (C) Copyright IBM Corp. 2007, 2008 - * - * Authors: - * Daniel Lezcano - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __LXC_LIST_H -#define __LXC_LIST_H - -#include - -struct lxc_list { - void *elem; - struct lxc_list *next; - struct lxc_list *prev; -}; - -#define lxc_init_list(l) \ - { \ - .next = l, .prev = l \ - } - -/* - * Iterate through an lxc list. An example for an idiom would be: - * - * struct lxc_list *iterator; - * lxc_list_for_each(iterator, list) { - * type *tmp; - * tmp = iterator->elem; - * } - */ -#define lxc_list_for_each(__iterator, __list) \ - for (__iterator = (__list)->next; __iterator != __list; \ - __iterator = __iterator->next) - -/* Iterate safely through an lxc list. An example for an appropriate use case - * would be: - * - * struct lxc_list *cur, *next; - * lxc_list_for_each_safe(cur, list, next) { - * type *tmp; - * tmp = cur->elem; - * } - */ -#define lxc_list_for_each_safe(__iterator, __list, __next) \ - for (__iterator = (__list)->next, __next = __iterator->next; \ - __iterator != __list; __iterator = __next, __next = __next->next) - -/* Initalize list. */ -static inline void lxc_list_init(struct lxc_list *list) -{ - list->elem = NULL; - list->next = list->prev = list; -} - -/* Add an element to a list. See lxc_list_add() and lxc_list_add_tail() for an - * idiom. - */ -static inline void lxc_list_add_elem(struct lxc_list *list, void *elem) -{ - list->elem = elem; -} - -/* Retrieve first element of list. */ -static inline void *lxc_list_first_elem(struct lxc_list *list) -{ - return list->next->elem; -} - -/* Retrieve last element of list. */ -static inline void *lxc_list_last_elem(struct lxc_list *list) -{ - return list->prev->elem; -} - -/* Determine if list is empty. */ -static inline int lxc_list_empty(struct lxc_list *list) -{ - return list == list->next; -} - -/* Workhorse to be called from lxc_list_add() and lxc_list_add_tail(). */ -static inline void __lxc_list_add(struct lxc_list *new, struct lxc_list *prev, - struct lxc_list *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/* Idiom to add an element to the beginning of an lxc list: - * - * struct lxc_list *tmp = malloc(sizeof(*tmp)); - * if (tmp == NULL) - * return 1; - * lxc_list_add_elem(tmp, elem); - * lxc_list_add(list, tmp); - */ -static inline void lxc_list_add(struct lxc_list *head, struct lxc_list *list) -{ - __lxc_list_add(list, head, head->next); -} - -/* Idiom to add an element to the end of an lxc list: - * - * struct lxc_list *tmp = malloc(sizeof(*tmp)); - * if (tmp == NULL) - * return 1; - * lxc_list_add_elem(tmp, elem); - * lxc_list_add_tail(list, tmp); - */ -static inline void lxc_list_add_tail(struct lxc_list *head, - struct lxc_list *list) -{ - __lxc_list_add(list, head->prev, head); -} - -/* Idiom to remove an element from a list: - * struct lxc_list *cur, *next; - * lxc_list_for_each_safe(cur, list, next) { - * lxc_list_del(cur); - * free(cur->elem); - * free(cur); - * } - */ -static inline void lxc_list_del(struct lxc_list *list) -{ - struct lxc_list *next, *prev; - - next = list->next; - prev = list->prev; - next->prev = prev; - prev->next = next; -} - -/* Return length of the list. */ -static inline size_t lxc_list_len(struct lxc_list *list) -{ - size_t i = 0; - struct lxc_list *iter; - - lxc_list_for_each(iter, list) { - i++; - } - - return i; -} - -#endif /* __LXC_LIST_H */ diff --git a/src/lxc/tools/tool_utils.c b/src/lxc/tools/tool_utils.c deleted file mode 100644 index 89382f67c..000000000 --- a/src/lxc/tools/tool_utils.c +++ /dev/null @@ -1,1219 +0,0 @@ -/* liblxcapi - * - * Copyright © 2018 Christian Brauner . - * 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 _GNU_SOURCE -#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" - -#if HAVE_SYS_PERSONALITY_H -#include -#endif - -#include - -#include "arguments.h" -#include "tool_utils.h" - -#ifndef HAVE_STRLCPY -#include "include/strlcpy.h" -#endif - -#ifndef HAVE_STRLCAT -#include "include/strlcat.h" -#endif - -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; -} - -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 wait_for_pid(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; - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) - return -1; - return 0; -} - -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_uint(const char *numstr, unsigned int *converted) -{ - char *err = NULL; - unsigned long int uli; - - while (isspace(*numstr)) - numstr++; - - if (*numstr == '-') - return -EINVAL; - - errno = 0; - uli = strtoul(numstr, &err, 0); - if (errno == ERANGE && uli == ULONG_MAX) - return -ERANGE; - - if (err == numstr || *err != '\0') - return -EINVAL; - - if (uli > UINT_MAX) - return -ERANGE; - - *converted = (unsigned int)uli; - return 0; -} - -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; -} - -void lxc_free_array(void **array, lxc_free_fn element_free_fn) -{ - void **p; - for (p = array; p && *p; p++) - element_free_fn(*p); - free((void*)array); -} - -int lxc_grow_array(void ***array, size_t* capacity, size_t new_size, size_t capacity_increment) -{ - size_t new_capacity; - void **new_array; - - /* first time around, catch some trivial mistakes of the user - * only initializing one of these */ - if (!*array || !*capacity) { - *array = NULL; - *capacity = 0; - } - - new_capacity = *capacity; - while (new_size + 1 > new_capacity) - new_capacity += capacity_increment; - if (new_capacity != *capacity) { - /* we have to reallocate */ - new_array = realloc(*array, new_capacity * sizeof(void *)); - if (!new_array) - return -1; - memset(&new_array[*capacity], 0, (new_capacity - (*capacity)) * sizeof(void *)); - *array = new_array; - *capacity = new_capacity; - } - - /* array has sufficient elements */ - return 0; -} - -char **lxc_string_split(const char *string, char _sep) -{ - char *token, *str, *saveptr = NULL; - char sep[2] = {_sep, '\0'}; - char **tmp = NULL, **result = NULL; - size_t result_capacity = 0; - size_t result_count = 0; - size_t len; - int r, saved_errno; - - if (!string) - return calloc(1, sizeof(char *)); - - len = strlen(string); - str = alloca(len + 1); - (void)strlcpy(str, string, len + 1); - - for (; (token = strtok_r(str, sep, &saveptr)); str = NULL) { - r = lxc_grow_array((void ***)&result, &result_capacity, result_count + 1, 16); - if (r < 0) - goto error_out; - result[result_count] = strdup(token); - if (!result[result_count]) - goto error_out; - result_count++; - } - - /* if we allocated too much, reduce it */ - tmp = realloc(result, (result_count + 1) * sizeof(char *)); - if (!tmp) - goto error_out; - result = tmp; - /* Make sure we don't return uninitialized memory. */ - if (result_count == 0) - *result = NULL; - return result; -error_out: - saved_errno = errno; - lxc_free_array((void **)result, free); - errno = saved_errno; - return NULL; -} - -char **lxc_normalize_path(const char *path) -{ - char **components; - char **p; - size_t components_len = 0; - size_t pos = 0; - - components = lxc_string_split(path, '/'); - if (!components) - return NULL; - for (p = components; *p; p++) - components_len++; - - /* resolve '.' and '..' */ - for (pos = 0; pos < components_len; ) { - if (!strcmp(components[pos], ".") || (!strcmp(components[pos], "..") && pos == 0)) { - /* eat this element */ - free(components[pos]); - memmove(&components[pos], &components[pos+1], sizeof(char *) * (components_len - pos)); - components_len--; - } else if (!strcmp(components[pos], "..")) { - /* eat this and the previous element */ - free(components[pos - 1]); - free(components[pos]); - memmove(&components[pos-1], &components[pos+1], sizeof(char *) * (components_len - pos)); - components_len -= 2; - pos--; - } else { - pos++; - } - } - - return components; -} - -char *lxc_string_join(const char *sep, const char **parts, bool use_as_prefix) -{ - char *result; - char **p; - size_t sep_len = strlen(sep); - size_t result_len = use_as_prefix * sep_len; - size_t buf_len; - - /* calculate new string length */ - for (p = (char **)parts; *p; p++) - result_len += (p > (char **)parts) * sep_len + strlen(*p); - - buf_len = result_len + 1; - result = calloc(buf_len, 1); - if (!result) - return NULL; - - if (use_as_prefix) - (void)strlcpy(result, sep, buf_len); - - for (p = (char **)parts; *p; p++) { - if (p > (char **)parts) - (void)strlcat(result, sep, buf_len); - (void)strlcat(result, *p, buf_len); - } - - return result; -} - -int is_dir(const char *path) -{ - struct stat statbuf; - int ret = stat(path, &statbuf); - if (ret == 0 && S_ISDIR(statbuf.st_mode)) - return 1; - return 0; -} - -size_t lxc_array_len(void **array) -{ - void **p; - size_t result = 0; - - for (p = array; p && *p; p++) - result++; - - return result; -} - -/* - * Given the '-t' template option to lxc-create, figure out what to - * do. If the template is a full executable path, use that. If it - * is something like 'sshd', then return $templatepath/lxc-sshd. - * On success return the template, on error return NULL. - */ -char *get_template_path(const char *t) -{ - int ret, len; - char *tpath; - - if (t[0] == '/' && access(t, X_OK) == 0) { - tpath = strdup(t); - return tpath; - } - - len = strlen(LXCTEMPLATEDIR) + strlen(t) + strlen("/lxc-") + 1; - tpath = malloc(len); - if (!tpath) - return NULL; - ret = snprintf(tpath, len, "%s/lxc-%s", LXCTEMPLATEDIR, t); - if (ret < 0 || ret >= len) { - free(tpath); - return NULL; - } - if (access(tpath, X_OK) < 0) { - fprintf(stderr, "Bad template: %s\n", t); - free(tpath); - return NULL; - } - - return tpath; -} - -int mkdir_p(const char *dir, mode_t mode) -{ - const char *tmp = dir; - const char *orig = dir; - char *makeme; - - do { - dir = tmp + strspn(tmp, "/"); - tmp = dir + strcspn(dir, "/"); - makeme = strndup(orig, dir - orig); - if (*makeme) { - if (mkdir(makeme, mode) && errno != EEXIST) { - fprintf(stderr, "Failed to create directory \"%s\"\n", makeme); - free(makeme); - return -1; - } - } - free(makeme); - } while(tmp != dir); - - return 0; -} - -bool file_exists(const char *f) -{ - struct stat statbuf; - - return stat(f, &statbuf) == 0; -} - -bool switch_to_ns(pid_t pid, const char *ns) { - int fd, ret; - char nspath[TOOL_MAXPATHLEN]; - - /* Switch to new ns */ - ret = snprintf(nspath, TOOL_MAXPATHLEN, "/proc/%d/ns/%s", pid, ns); - if (ret < 0 || ret >= TOOL_MAXPATHLEN) - return false; - - fd = open(nspath, O_RDONLY); - if (fd < 0) { - fprintf(stderr, "Failed to open %s\n", nspath); - return false; - } - - ret = setns(fd, 0); - if (ret) { - fprintf(stderr, "Failed to set process %d to %s of %d\n", pid, ns, fd); - close(fd); - return false; - } - close(fd); - return true; -} - -static bool complete_word(char ***result, char *start, char *end, size_t *cap, size_t *cnt) -{ - int r; - - r = lxc_grow_array((void ***)result, cap, 2 + *cnt, 16); - if (r < 0) - return false; - (*result)[*cnt] = strndup(start, end - start); - if (!(*result)[*cnt]) - return false; - (*cnt)++; - - return true; -} - -/* - * Given a a string 'one two "three four"', split into three words, - * one, two, and "three four" - */ -char **lxc_string_split_quoted(char *string) -{ - char *nextword = string, *p, state; - char **result = NULL; - size_t result_capacity = 0; - size_t result_count = 0; - - if (!string || !*string) - return calloc(1, sizeof(char *)); - - // TODO I'm *not* handling escaped quote - state = ' '; - for (p = string; *p; p++) { - switch(state) { - case ' ': - if (isspace(*p)) - continue; - else if (*p == '"' || *p == '\'') { - nextword = p; - state = *p; - continue; - } - nextword = p; - state = 'a'; - continue; - case 'a': - if (isspace(*p)) { - complete_word(&result, nextword, p, &result_capacity, &result_count); - state = ' '; - continue; - } - continue; - case '"': - case '\'': - if (*p == state) { - complete_word(&result, nextword+1, p, &result_capacity, &result_count); - state = ' '; - continue; - } - continue; - } - } - - if (state == 'a') - complete_word(&result, nextword, p, &result_capacity, &result_count); - - return realloc(result, (result_count + 1) * sizeof(char *)); -} - -int lxc_char_left_gc(const char *buffer, size_t len) -{ - size_t i; - for (i = 0; i < len; i++) { - if (buffer[i] == ' ' || - buffer[i] == '\t') - continue; - return i; - } - return 0; -} - -int lxc_char_right_gc(const char *buffer, size_t len) -{ - int i; - for (i = len - 1; i >= 0; i--) { - if (buffer[i] == ' ' || - buffer[i] == '\t' || - buffer[i] == '\n' || - buffer[i] == '\0') - continue; - return i + 1; - } - return 0; -} - -struct new_config_item *parse_line(char *buffer) -{ - char *dot, *key, *line, *linep, *value; - int ret = 0; - char *dup = buffer; - struct new_config_item *new = NULL; - - linep = line = strdup(dup); - if (!line) - return NULL; - - line += lxc_char_left_gc(line, strlen(line)); - - /* martian option - don't add it to the config itself */ - if (strncmp(line, "lxc.", 4)) - goto on_error; - - ret = -1; - dot = strchr(line, '='); - if (!dot) { - fprintf(stderr, "Invalid configuration item: %s\n", line); - goto on_error; - } - - *dot = '\0'; - value = dot + 1; - - key = line; - key[lxc_char_right_gc(key, strlen(key))] = '\0'; - - value += lxc_char_left_gc(value, strlen(value)); - value[lxc_char_right_gc(value, strlen(value))] = '\0'; - - if (*value == '\'' || *value == '\"') { - size_t len; - - len = strlen(value); - if (len > 1 && value[len - 1] == *value) { - value[len - 1] = '\0'; - value++; - } - } - - ret = -1; - new = malloc(sizeof(struct new_config_item)); - if (!new) - goto on_error; - - new->key = strdup(key); - new->val = strdup(value); - if (!new->val || !new->key) - goto on_error; - ret = 0; - -on_error: - free(linep); - if (ret < 0 && new) { - free(new->key); - free(new->val); - free(new); - new = NULL; - } - - return new; -} - -int lxc_config_define_add(struct lxc_list *defines, char *arg) -{ - struct lxc_list *dent; - - dent = malloc(sizeof(struct lxc_list)); - if (!dent) - return -1; - - dent->elem = parse_line(arg); - if (!dent->elem) { - free(dent); - return -1; - } - - lxc_list_add_tail(defines, dent); - return 0; -} - -bool lxc_config_define_load(struct lxc_list *defines, struct lxc_container *c) -{ - struct lxc_list *it; - bool bret = true; - - lxc_list_for_each(it, defines) { - struct new_config_item *new_item = it->elem; - bret = c->set_config_item(c, new_item->key, new_item->val); - if (!bret) - break; - } - - lxc_config_define_free(defines); - return bret; -} - -void lxc_config_define_free(struct lxc_list *defines) -{ - struct lxc_list *it, *next; - - lxc_list_for_each_safe(it, defines, next) { - struct new_config_item *new_item = it->elem; - free(new_item->key); - free(new_item->val); - lxc_list_del(it); - free(it); - } -} - -int lxc_read_from_file(const char *filename, void* buf, size_t count) -{ - int fd = -1, saved_errno; - ssize_t ret; - - fd = open(filename, O_RDONLY | O_CLOEXEC); - if (fd < 0) - return -1; - - if (!buf || !count) { - char buf2[100]; - size_t count2 = 0; - while ((ret = read(fd, buf2, 100)) > 0) - count2 += ret; - if (ret >= 0) - ret = count2; - } else { - memset(buf, 0, count); - ret = read(fd, buf, count); - } - - saved_errno = errno; - close(fd); - errno = saved_errno; - return ret; -} - -char **lxc_string_split_and_trim(const char *string, char _sep) -{ - char *token, *str, *saveptr = NULL; - char sep[2] = { _sep, '\0' }; - char **result = NULL; - size_t result_capacity = 0; - size_t result_count = 0; - int r, saved_errno; - size_t i = 0; - size_t len; - - if (!string) - return calloc(1, sizeof(char *)); - - len = strlen(string); - str = alloca(len + 1); - (void)strlcpy(str, string, len + 1); - - for (; (token = strtok_r(str, sep, &saveptr)); str = NULL) { - while (token[0] == ' ' || token[0] == '\t') - token++; - i = strlen(token); - while (i > 0 && (token[i - 1] == ' ' || token[i - 1] == '\t')) { - token[i - 1] = '\0'; - i--; - } - r = lxc_grow_array((void ***)&result, &result_capacity, result_count + 1, 16); - if (r < 0) - goto error_out; - result[result_count] = strdup(token); - if (!result[result_count]) - goto error_out; - result_count++; - } - - /* if we allocated too much, reduce it */ - return realloc(result, (result_count + 1) * sizeof(char *)); -error_out: - saved_errno = errno; - lxc_free_array((void **)result, free); - errno = saved_errno; - return NULL; -} - -char *lxc_append_paths(const char *first, const char *second) -{ - int ret; - size_t len; - char *result = NULL; - const char *pattern = "%s%s"; - - len = strlen(first) + strlen(second) + 1; - if (second[0] != '/') { - len += 1; - pattern = "%s/%s"; - } - - result = calloc(1, len); - if (!result) - return NULL; - - ret = snprintf(result, len, pattern, first, second); - if (ret < 0 || (size_t)ret >= len) { - free(result); - return NULL; - } - - return result; -} - -bool dir_exists(const char *path) -{ - struct stat sb; - int ret; - - ret = stat(path, &sb); - if (ret < 0) - /* Could be something other than eexist, just say "no". */ - return false; - return S_ISDIR(sb.st_mode); -} - -char *lxc_string_replace(const char *needle, const char *replacement, - const char *haystack) -{ - ssize_t len = -1, saved_len = -1; - char *result = NULL; - size_t replacement_len = strlen(replacement); - size_t needle_len = strlen(needle); - - /* should be executed exactly twice */ - while (len == -1 || result == NULL) { - char *p; - char *last_p; - ssize_t part_len; - - if (len != -1) { - result = calloc(1, len + 1); - if (!result) - return NULL; - saved_len = len; - } - - len = 0; - - for (last_p = (char *)haystack, p = strstr(last_p, needle); p; last_p = p, p = strstr(last_p, needle)) { - part_len = (ssize_t)(p - last_p); - if (result && part_len > 0) - memcpy(&result[len], last_p, part_len); - len += part_len; - if (result && replacement_len > 0) - memcpy(&result[len], replacement, replacement_len); - len += replacement_len; - p += needle_len; - } - part_len = strlen(last_p); - if (result && part_len > 0) - memcpy(&result[len], last_p, part_len); - len += part_len; - } - - /* make sure we did the same thing twice, - * once for calculating length, the other - * time for copying data */ - if (saved_len != len) { - free(result); - return NULL; - } - /* make sure we didn't overwrite any buffer, - * due to calloc the string should be 0-terminated */ - if (result[len] != '\0') { - free(result); - return NULL; - } - - return result; -} - -ssize_t lxc_write_nointr(int fd, const void* buf, size_t count) -{ - ssize_t ret; -again: - ret = write(fd, buf, count); - if (ret < 0 && errno == EINTR) - goto again; - return ret; -} - -char *get_rundir() -{ - char *rundir; - const char *homedir; - - if (geteuid() == 0) { - rundir = strdup(RUNTIME_PATH); - return rundir; - } - - rundir = getenv("XDG_RUNTIME_DIR"); - if (rundir) { - rundir = strdup(rundir); - return rundir; - } - - homedir = getenv("HOME"); - if (!homedir) - return NULL; - - rundir = malloc(sizeof(char) * (17 + strlen(homedir))); - sprintf(rundir, "%s/.cache/lxc/run/", homedir); - - return rundir; -} - -char *must_copy_string(const char *entry) -{ - char *ret; - - if (!entry) - return NULL; - do { - ret = strdup(entry); - } while (!ret); - - return ret; -} - - -void *must_realloc(void *orig, size_t sz) -{ - void *ret; - - do { - ret = realloc(orig, sz); - } while (!ret); - - return ret; -} - -char *must_make_path(const char *first, ...) -{ - va_list args; - char *cur, *dest; - size_t full_len = strlen(first); - size_t buf_len; - - dest = must_copy_string(first); - - va_start(args, first); - while ((cur = va_arg(args, char *)) != NULL) { - full_len += strlen(cur); - if (cur[0] != '/') - full_len++; - - buf_len = full_len + 1; - dest = must_realloc(dest, buf_len); - - if (cur[0] != '/') - (void)strlcat(dest, "/", buf_len); - (void)strlcat(dest, cur, buf_len); - } - va_end(args); - - return dest; -} - -int rm_r(char *dirname) -{ - int ret; - struct dirent *direntp; - DIR *dir; - int r = 0; - - dir = opendir(dirname); - if (!dir) - return -1; - - while ((direntp = readdir(dir))) { - char *pathname; - struct stat mystat; - - if (!strcmp(direntp->d_name, ".") || - !strcmp(direntp->d_name, "..")) - continue; - - pathname = must_make_path(dirname, direntp->d_name, NULL); - - ret = lstat(pathname, &mystat); - if (ret < 0) { - r = -1; - goto next; - } - - if (!S_ISDIR(mystat.st_mode)) - goto next; - - ret = rm_r(pathname); - if (ret < 0) - r = -1; - next: - free(pathname); - } - - ret = rmdir(dirname); - if (ret < 0) - r = -1; - - ret = closedir(dir); - if (ret < 0) - r = -1; - - return r; -} - -ssize_t lxc_read_nointr(int fd, void* buf, size_t count) -{ - ssize_t ret; -again: - ret = read(fd, buf, count); - if (ret < 0 && errno == EINTR) - goto again; - return ret; -} - -static int mount_fs(const char *source, const char *target, const char *type) -{ - /* the umount may fail */ - if (umount(target) < 0) - - if (mount(source, target, type, 0, NULL) < 0) - return -1; - - return 0; -} - -void lxc_setup_fs(void) -{ - (void)mount_fs("proc", "/proc", "proc"); - - /* if /dev has been populated by us, /dev/shm does not exist */ - if (access("/dev/shm", F_OK)) - (void)mkdir("/dev/shm", 0777); - - /* if we can't mount /dev/shm, continue anyway */ - (void)mount_fs("shmfs", "/dev/shm", "tmpfs"); - - /* If we were able to mount /dev/shm, then /dev exists */ - /* Sure, but it's read-only per config :) */ - if (access("/dev/mqueue", F_OK)) - (void)mkdir("/dev/mqueue", 0666); - - /* continue even without posix message queue support */ - (void)mount_fs("mqueue", "/dev/mqueue", "mqueue"); -} - -struct clone_arg { - int (*fn)(void *); - void *arg; -}; - -static int do_clone(void *arg) -{ - struct clone_arg *clone_arg = arg; - return clone_arg->fn(clone_arg->arg); -} - -pid_t lxc_clone(int (*fn)(void *), void *arg, int flags) -{ - struct clone_arg clone_arg = { - .fn = fn, - .arg = arg, - }; - - size_t stack_size = lxc_getpagesize(); - void *stack = alloca(stack_size); - pid_t ret; - -#ifdef __ia64__ - ret = __clone2(do_clone, stack, stack_size, flags | SIGCHLD, &clone_arg); -#else - ret = clone(do_clone, stack + stack_size, flags | SIGCHLD, &clone_arg); -#endif - return ret; -} diff --git a/src/lxc/tools/tool_utils.h b/src/lxc/tools/tool_utils.h deleted file mode 100644 index ed361e30f..000000000 --- a/src/lxc/tools/tool_utils.h +++ /dev/null @@ -1,237 +0,0 @@ -/* liblxcapi - * - * Copyright © 2018 Christian Brauner . - * 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 "config.h" - -#include -#include -#include -#include -#include - -#include - -#include "tool_list.h" - -#define TOOL_MAXPATHLEN 4096 -#define TOOL_NUMSTRLEN64 21 - -#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 !defined(__NR_setns) && !defined(__NR_set_ns) - #if defined(__x86_64__) - #define __NR_setns 308 - #elif defined(__i386__) - #define __NR_setns 346 - #elif defined(__arm__) - #define __NR_setns 375 - #elif defined(__aarch64__) - #define __NR_setns 375 - #elif defined(__powerpc__) - #define __NR_setns 350 - #elif defined(__s390__) - #define __NR_setns 339 - #endif -#endif - -/* Define setns() if missing from the C library */ -#ifndef HAVE_SETNS -static inline int setns(int fd, int nstype) -{ -#ifdef __NR_setns - return syscall(__NR_setns, fd, nstype); -#elif defined(__NR_set_ns) - return syscall(__NR_set_ns, fd, nstype); -#else - errno = ENOSYS; - return -1; -#endif -} -#endif - -#if HAVE_LIBCAP -#include - -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 wait_for_pid(pid_t pid); -extern int lxc_wait_for_pid_status(pid_t pid); -extern int lxc_safe_uint(const char *numstr, unsigned int *converted); -extern int lxc_safe_int(const char *numstr, int *converted); -extern int lxc_safe_long(const char *numstr, long int *converted); - -typedef void (*lxc_free_fn)(void *); -extern void lxc_free_array(void **array, lxc_free_fn element_free_fn); -extern size_t lxc_array_len(void **array); -extern int lxc_grow_array(void ***array, size_t *capacity, size_t new_size, - size_t capacity_increment); -extern char **lxc_string_split(const char *string, char _sep); -extern char **lxc_normalize_path(const char *path); -extern char *lxc_string_join(const char *sep, const char **parts, - bool use_as_prefix); -extern char **lxc_string_split_quoted(char *string); -extern char **lxc_string_split_and_trim(const char *string, char _sep); -extern char *lxc_append_paths(const char *first, const char *second); -extern char *lxc_string_replace(const char *needle, const char *replacement, - const char *haystack); -extern char *must_copy_string(const char *entry); -extern void *must_realloc(void *orig, size_t sz); -extern char *must_make_path(const char *first, ...); - -extern int mkdir_p(const char *dir, mode_t mode); -extern int rm_r(char *dirname); -extern bool file_exists(const char *f); -extern bool dir_exists(const char *path); -extern int is_dir(const char *path); -extern int lxc_read_from_file(const char *filename, void* buf, size_t count); - -extern char *get_template_path(const char *t); - -extern bool switch_to_ns(pid_t pid, const char *ns); - -extern int lxc_config_define_add(struct lxc_list *defines, char *arg); -extern bool lxc_config_define_load(struct lxc_list *defines, - struct lxc_container *c); -extern void lxc_config_define_free(struct lxc_list *defines); -extern int lxc_char_left_gc(const char *buffer, size_t len); -extern int lxc_char_right_gc(const char *buffer, size_t len); - -struct new_config_item { - char *key; - char *val; -}; -extern struct new_config_item *parse_line(char *buffer); - -extern ssize_t lxc_read_nointr(int fd, void* buf, size_t count); -extern ssize_t lxc_write_nointr(int fd, const void* buf, size_t count); - -extern char *get_rundir(); - -extern void lxc_setup_fs(void); - -static inline uint64_t lxc_getpagesize(void) -{ - int64_t pgsz; - - pgsz = sysconf(_SC_PAGESIZE); - if (pgsz <= 0) - pgsz = 1 << 12; - - return pgsz; -} - -#if defined(__ia64__) -int __clone2(int (*__fn) (void *__arg), void *__child_stack_base, - size_t __child_stack_size, int __flags, void *__arg, ...); -#else -int clone(int (*fn)(void *), void *child_stack, - int flags, void *arg, ... - /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ ); -#endif - -extern pid_t lxc_clone(int (*fn)(void *), void *arg, int flags); - -#endif /* __LXC_UTILS_H */ -- 2.39.5