commit 85d35cce63aeeda0a3f06570cf8c828a84dd5cbf Author: overweight <5324761+overweight@user.noreply.gitee.com> Date: Mon Sep 30 11:03:07 2019 -0400 Package init diff --git a/0001-confile-add-lxc.isulad.init.args-config-interface.patch b/0001-confile-add-lxc.isulad.init.args-config-interface.patch new file mode 100644 index 0000000..66ccc2b --- /dev/null +++ b/0001-confile-add-lxc.isulad.init.args-config-interface.patch @@ -0,0 +1,222 @@ +From a6f57fc8bbe7b0e2d2d77f300c3c84a2956634b6 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Thu, 10 Jan 2019 06:54:37 -0500 +Subject: [PATCH 001/122] confile: add lxc.isulad.init.args config interface + +lxc.isulad.init.args config interface is used to specify the args for +the container. + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 13 +++++++++++ + src/lxc/conf.h | 8 +++++++ + src/lxc/confile.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ + src/lxc/lxccontainer.c | 30 +++++++++++++++++++++++++ + 4 files changed, 112 insertions(+) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index d95bc4c..f20d629 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4014,6 +4014,18 @@ void lxc_clear_includes(struct lxc_conf *conf) + } + } + ++/*isulad clear init args*/ ++int lxc_clear_init_args(struct lxc_conf *lxc_conf) ++{ ++ int i; ++ ++ for (i = 0; i < lxc_conf->init_argc; i++) ++ free(lxc_conf->init_argv[i]); ++ free(lxc_conf->init_argv); ++ ++ return 0; ++} ++ + void lxc_conf_free(struct lxc_conf *conf) + { + if (!conf) +@@ -4057,6 +4069,7 @@ void lxc_conf_free(struct lxc_conf *conf) + lxc_clear_limits(conf, "lxc.prlimit"); + lxc_clear_sysctls(conf, "lxc.sysctl"); + lxc_clear_procs(conf, "lxc.proc"); ++ lxc_clear_init_args(conf); + free(conf->cgroup_meta.dir); + free(conf->cgroup_meta.controllers); + free(conf); +diff --git a/src/lxc/conf.h b/src/lxc/conf.h +index 41f67cf..95c3027 100644 +--- a/src/lxc/conf.h ++++ b/src/lxc/conf.h +@@ -376,6 +376,10 @@ struct lxc_conf { + + /* procs */ + struct lxc_list procs; ++ ++ /* isulad add: init args used to repalce init_cmd*/ ++ char **init_argv; ++ size_t init_argc; + }; + + extern int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, +@@ -442,4 +446,8 @@ extern int lxc_clear_sysctls(struct lxc_conf *c, const char *key); + extern int setup_proc_filesystem(struct lxc_list *procs, pid_t pid); + extern int lxc_clear_procs(struct lxc_conf *c, const char *key); + ++/* isulad add begin */ ++int lxc_clear_init_args(struct lxc_conf *lxc_conf); ++/* isulad add end */ ++ + #endif /* __LXC_CONF_H */ +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index 05c6823..7297b35 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -150,6 +150,10 @@ lxc_config_define(tty_dir); + lxc_config_define(uts_name); + lxc_config_define(sysctl); + lxc_config_define(proc); ++/*isulad add begin*/ ++lxc_config_define(init_args); ++/*isulad add end*/ ++ + + static struct lxc_config_t config_jump_table[] = { + { "lxc.arch", set_config_personality, get_config_personality, clr_config_personality, }, +@@ -234,6 +238,10 @@ static struct lxc_config_t config_jump_table[] = { + { "lxc.uts.name", set_config_uts_name, get_config_uts_name, clr_config_uts_name, }, + { "lxc.sysctl", set_config_sysctl, get_config_sysctl, clr_config_sysctl, }, + { "lxc.proc", set_config_proc, get_config_proc, clr_config_proc, }, ++ ++ /*isulad add begin*/ ++ { "lxc.isulad.init.args", set_config_init_args, get_config_init_args, clr_config_init_args, }, ++ /*isulad add end*/ + }; + + static const size_t config_jump_table_size = sizeof(config_jump_table) / sizeof(struct lxc_config_t); +@@ -2184,6 +2192,33 @@ static int set_config_namespace_share(const char *key, const char *value, + return set_config_string_item(&lxc_conf->ns_share[ns_idx], value); + } + ++/* isulad: set config for init args */ ++static int set_config_init_args(const char *key, const char *value, ++ struct lxc_conf *lxc_conf, void *data) ++{ ++ int ret = 0; ++ char *tmp = NULL; ++ char *new_value = NULL; ++ ++ ret = set_config_string_item(&new_value, value); ++ if (ret || !new_value) ++ return ret; ++ ++ tmp = realloc(lxc_conf->init_argv, (lxc_conf->init_argc + 1) * sizeof(char *)); ++ if (!tmp) { ++ ERROR("Out of memory"); ++ free(new_value); ++ return -1; ++ } ++ ++ lxc_conf->init_argv = (char **)tmp; ++ ++ lxc_conf->init_argv[lxc_conf->init_argc] = new_value; ++ lxc_conf->init_argc++; ++ ++ return 0; ++} ++ + struct parse_line_conf { + struct lxc_conf *conf; + bool from_include; +@@ -3716,6 +3751,25 @@ static int get_config_namespace_share(const char *key, char *retv, int inlen, + return fulllen; + } + ++/* isulad: get config init args */ ++static int get_config_init_args(const char *key, char *retv, int inlen, ++ struct lxc_conf *c, void *data) ++{ ++ int i, len, fulllen = 0; ++ struct lxc_list *it; ++ ++ if (!retv) ++ inlen = 0; ++ else ++ memset(retv, 0, inlen); ++ ++ for (i = 0; i < c->init_argc; i++) { ++ strprint(retv, inlen, "%s", c->init_argv[i]); ++ } ++ ++ return fulllen; ++} ++ + /* Callbacks to clear config items. */ + static inline int clr_config_personality(const char *key, struct lxc_conf *c, + void *data) +@@ -4520,6 +4574,13 @@ static int clr_config_net_ipv6_address(const char *key, + return 0; + } + ++/* isulad: clr config init args*/ ++static inline int clr_config_init_args(const char *key, struct lxc_conf *c, ++ void *data) ++{ ++ return lxc_clear_init_args(c); ++} ++ + static int get_config_net_nic(const char *key, char *retv, int inlen, + struct lxc_conf *c, void *data) + { +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index ad70886..b4cacce 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -847,6 +847,31 @@ static bool wait_on_daemonized_start(struct lxc_handler *handler, int pid) + return true; + } + ++/* isulad: use init argv as init cmd */ ++static char **use_init_args(char **init_argv, size_t init_args) ++{ ++ size_t i; ++ int nargs = 0; ++ char **argv; ++ ++ if (!init_argv) ++ return NULL; ++ ++ do { ++ argv = malloc(sizeof(char *)); ++ } while (!argv); ++ ++ argv[0] = NULL; ++ for (i = 0; i < init_args; i++) ++ push_arg(&argv, init_argv[i], &nargs); ++ ++ if (nargs == 0) { ++ free(argv); ++ return NULL; ++ } ++ return argv; ++} ++ + static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const argv[]) + { + int ret; +@@ -903,6 +928,11 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a + argv = init_cmd = split_init_cmd(conf->init_cmd); + } + ++ /* isulad: use init argv as init cmd */ ++ if (!argv) { ++ argv = init_cmd = use_init_args(conf->init_argv, conf->init_argc); ++ } ++ + /* ... otherwise use default_args. */ + if (!argv) { + if (useinit) { +-- +1.8.3.1 + diff --git a/0002-namespace-add-support-share-namespace-by-path.patch b/0002-namespace-add-support-share-namespace-by-path.patch new file mode 100644 index 0000000..87c2c5c --- /dev/null +++ b/0002-namespace-add-support-share-namespace-by-path.patch @@ -0,0 +1,35 @@ +From d1e8ab945fadac5ee11eb150b1cdfb6aeec407c2 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Thu, 10 Jan 2019 08:42:19 -0500 +Subject: [PATCH 002/122] namespace: add support share namespace by path + +Signed-off-by: LiFeng +--- + src/lxc/confile_utils.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/src/lxc/confile_utils.c b/src/lxc/confile_utils.c +index 7280463..9049ce8 100644 +--- a/src/lxc/confile_utils.c ++++ b/src/lxc/confile_utils.c +@@ -789,6 +789,17 @@ int lxc_inherit_namespace(const char *lxcname_or_pid, const char *lxcpath, + int fd, pid; + char *dup, *lastslash; + ++ /* isulad: add support share namespace by path. ++ * e.g. "lxc.namespace.share.net = /proc/PID/ns/net or /var/run/netns/net" ++ */ ++ if (file_exists(lxcname_or_pid) && !dir_exists(lxcname_or_pid)) { ++ fd = open(lxcname_or_pid, O_RDONLY | O_CLOEXEC); ++ if (fd < 0) ++ return -EINVAL; ++ ++ return fd; ++ } ++ + lastslash = strrchr(lxcname_or_pid, '/'); + if (lastslash) { + dup = strdup(lxcname_or_pid); +-- +1.8.3.1 + diff --git a/0003-confile-add-lxc.isulad.populate.device-interface.patch b/0003-confile-add-lxc.isulad.populate.device-interface.patch new file mode 100644 index 0000000..4dd2ad8 --- /dev/null +++ b/0003-confile-add-lxc.isulad.populate.device-interface.patch @@ -0,0 +1,406 @@ +From 8a8f3a04e8a6f3494a072ffe0cc9124049c5ba63 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Fri, 11 Jan 2019 01:51:25 -0500 +Subject: [PATCH 003/122] confile: add lxc.isulad.populate.device interface + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++--- + src/lxc/conf.h | 28 +++++++++++- + src/lxc/confile.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 269 insertions(+), 8 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index f20d629..20b7aba 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -2745,6 +2745,10 @@ struct lxc_conf *lxc_conf_init(void) + memset(&new->cgroup_meta, 0, sizeof(struct lxc_cgroup)); + memset(&new->ns_share, 0, sizeof(char *) * LXC_NS_MAX); + ++ /* isulad add begin */ ++ lxc_list_init(&new->populate_devs); ++ /* isulad add end */ ++ + return new; + } + +@@ -3487,6 +3491,85 @@ static bool execveat_supported(void) + return true; + } + ++/* isulad: setup devices which will be populated in the container.*/ ++static int setup_populate_devs(const struct lxc_rootfs *rootfs, struct lxc_list *devs) ++{ ++ int ret; ++ char *pathdirname; ++ char path[MAXPATHLEN]; ++ mode_t cmask; ++ mode_t file_mode = 0; ++ struct lxc_populate_devs *dev_elem; ++ struct lxc_list *it; ++ ++ INFO("Populating devices into container"); ++ cmask = umask(S_IXUSR | S_IXGRP | S_IXOTH); ++ lxc_list_for_each(it, devs) { ++ dev_elem = it->elem; ++ ++ ret = snprintf(path, MAXPATHLEN, "%s/%s", rootfs->path ? rootfs->mount : "", dev_elem->name); ++ if (ret < 0 || ret >= MAXPATHLEN) ++ return -1; ++ ++ /* create any missing directories */ ++ pathdirname = strdup(path); ++ pathdirname = dirname(pathdirname); ++ ret = mkdir_p(pathdirname, 0750); ++ free(pathdirname); ++ if (ret < 0) { ++ WARN("Failed to create target directory"); ++ return -1; ++ } ++ ++ if (!strcmp(dev_elem->type, "c")) { ++ file_mode = dev_elem->file_mode | S_IFCHR; ++ } else if (!strcmp(dev_elem->type, "b")) { ++ file_mode = dev_elem->file_mode | S_IFBLK; ++ } else { ++ ERROR("Failed to parse devices type '%s'", dev_elem->type); ++ return -1; ++ } ++ ++ DEBUG("Try to mknod '%s':'%d':'%d':'%d'\n", path, ++ file_mode, dev_elem->maj, dev_elem->min); ++ ++ ret = mknod(path, file_mode, makedev(dev_elem->maj, dev_elem->min)); ++ if (ret && errno != EEXIST) { ++ SYSERROR("Failed to mknod '%s':'%d':'%d':'%d'", dev_elem->name, ++ file_mode, dev_elem->maj, dev_elem->min); ++ ++ char hostpath[MAXPATHLEN]; ++ FILE *pathfile; ++ ++ // Unprivileged containers cannot create devices, so ++ // try to bind mount the device from the host ++ ret = snprintf(hostpath, MAXPATHLEN, "/dev/%s", dev_elem->name); ++ if (ret < 0 || ret >= MAXPATHLEN) ++ return -1; ++ pathfile = fopen(path, "wb"); ++ if (!pathfile) { ++ SYSERROR("Failed to create device mount target '%s'", path); ++ return -1; ++ } ++ fclose(pathfile); ++ if (safe_mount(hostpath, path, 0, MS_BIND, NULL, ++ rootfs->path ? rootfs->mount : NULL) != 0) { ++ SYSERROR("Failed bind mounting device %s from host into container", ++ dev_elem->name); ++ return -1; ++ } ++ } ++ if (chown(path, dev_elem->uid, dev_elem->gid) < 0) { ++ ERROR("Error chowning %s", path); ++ return -1; ++ } ++ } ++ umask(cmask); ++ ++ INFO("Populated devices into container /dev"); ++ return 0; ++} ++ + int lxc_setup(struct lxc_handler *handler) + { + int ret; +@@ -3584,6 +3667,16 @@ int lxc_setup(struct lxc_handler *handler) + return -1; + } + ++ /*isulad: move mount entrues here, before we do lxc_fill_autodev and populate devices */ ++ if (!lxc_list_empty(&lxc_conf->mount_list)) { ++ ret = setup_mount_entries(lxc_conf, &lxc_conf->rootfs, ++ &lxc_conf->mount_list, name, lxcpath); ++ if (ret < 0) { ++ ERROR("Failed to setup mount entries"); ++ return -1; ++ } ++ } ++ + ret = run_lxc_hooks(name, "mount", lxc_conf, NULL); + if (ret < 0) { + ERROR("Failed to run mount hooks"); +@@ -3604,12 +3697,11 @@ int lxc_setup(struct lxc_handler *handler) + } + } + +- if (!lxc_list_empty(&lxc_conf->mount_list)) { +- ret = setup_mount_entries(lxc_conf, &lxc_conf->rootfs, +- &lxc_conf->mount_list, name, lxcpath); +- if (ret < 0) { +- ERROR("Failed to setup mount entries"); +- return -1; ++ /* isulad: setup devices which will be populated in the container. */ ++ if (!lxc_list_empty(&lxc_conf->populate_devs)) { ++ if (setup_populate_devs(&lxc_conf->rootfs, &lxc_conf->populate_devs)) { ++ ERROR("Failed to setup devices in the container"); ++ return -1;; + } + } + +@@ -4026,6 +4118,22 @@ int lxc_clear_init_args(struct lxc_conf *lxc_conf) + return 0; + } + ++/*isulad: clear populate devices*/ ++int lxc_clear_populate_devices(struct lxc_conf *c) ++{ ++ struct lxc_list *it,*next; ++ ++ lxc_list_for_each_safe(it, &c->populate_devs, next) { ++ struct lxc_populate_devs *dev_elem = it->elem; ++ lxc_list_del(it); ++ free(dev_elem->name); ++ free(dev_elem->type); ++ free(dev_elem); ++ free(it); ++ } ++ return 0; ++} ++ + void lxc_conf_free(struct lxc_conf *conf) + { + if (!conf) +@@ -4069,9 +4177,12 @@ void lxc_conf_free(struct lxc_conf *conf) + lxc_clear_limits(conf, "lxc.prlimit"); + lxc_clear_sysctls(conf, "lxc.sysctl"); + lxc_clear_procs(conf, "lxc.proc"); +- lxc_clear_init_args(conf); + free(conf->cgroup_meta.dir); + free(conf->cgroup_meta.controllers); ++ /* isulad add begin */ ++ lxc_clear_init_args(conf); ++ lxc_clear_populate_devices(conf); ++ /* isulad add end */ + free(conf); + } + +diff --git a/src/lxc/conf.h b/src/lxc/conf.h +index 95c3027..cced868 100644 +--- a/src/lxc/conf.h ++++ b/src/lxc/conf.h +@@ -171,6 +171,26 @@ struct lxc_rootfs { + }; + + /* ++ * iSulad: Defines a structure to store the devices which will ++ * be attached in container ++ * @name : the target device name in container ++ * @type : the type of target device "c" or "b" ++ * @mode : file mode for the device ++ * @maj : major number for the device ++ * @min : minor number for the device ++ */ ++struct lxc_populate_devs { ++ char *name; ++ char *type; ++ mode_t file_mode; ++ int maj; ++ int min; ++ uid_t uid; ++ gid_t gid; ++}; ++ ++ ++/* + * Automatic mounts for LXC to perform inside the container + */ + enum { +@@ -377,9 +397,13 @@ struct lxc_conf { + /* procs */ + struct lxc_list procs; + +- /* isulad add: init args used to repalce init_cmd*/ ++ /* isulad add begin */ ++ /* init args used to repalce init_cmd*/ + char **init_argv; + size_t init_argc; ++ /* populate devices*/ ++ struct lxc_list populate_devs; ++ /* isulad add end */ + }; + + extern int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, +@@ -448,6 +472,8 @@ extern int lxc_clear_procs(struct lxc_conf *c, const char *key); + + /* isulad add begin */ + int lxc_clear_init_args(struct lxc_conf *lxc_conf); ++int lxc_clear_populate_devices(struct lxc_conf *c); ++ + /* isulad add end */ + + #endif /* __LXC_CONF_H */ +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index 7297b35..e3212d3 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -152,6 +152,7 @@ lxc_config_define(sysctl); + lxc_config_define(proc); + /*isulad add begin*/ + lxc_config_define(init_args); ++lxc_config_define(populate_device); + /*isulad add end*/ + + +@@ -241,6 +242,7 @@ static struct lxc_config_t config_jump_table[] = { + + /*isulad add begin*/ + { "lxc.isulad.init.args", set_config_init_args, get_config_init_args, clr_config_init_args, }, ++ { "lxc.isulad.populate.device", set_config_populate_device, get_config_populate_device, clr_config_populate_device, }, + /*isulad add end*/ + }; + +@@ -2219,6 +2221,93 @@ static int set_config_init_args(const char *key, const char *value, + return 0; + } + ++/* isulad: set config for init args */ ++static int set_config_populate_device(const char *key, const char *value, ++ struct lxc_conf *lxc_conf, void *data) ++{ ++ int ret = 0, major = 0, minor = 0; ++ uid_t uid = (uid_t)-1; ++ gid_t gid = (gid_t)-1; ++ char name[PATH_MAX] = {0}; ++ char type[3] = {0}; ++ char *replace_value = NULL; ++ mode_t filemode = 0; ++ struct lxc_list *iter; ++ struct lxc_list *dev_list = NULL; ++ struct lxc_populate_devs *dev_elem = NULL; ++ ++ if (lxc_config_value_empty(value)) ++ return lxc_clear_populate_devices(lxc_conf); ++ ++ /* lxc.populate.device = PATH_IN_CONTAINER:DEVICETYPE:MAJOR:MINOR:MODE:UID:GID ++ * For e.g. lxc.populate.device = /dev/sda:b:8:0:0666:0:0 ++ */ ++ ret = sscanf(value, "%[^:]:%2[^:]:%i:%i:%i:%u:%u", name, type, &major, &minor, &filemode, &uid, &gid); ++ if (ret != 7) ++ return -1; ++ ++ /* find existing list element */ ++ lxc_list_for_each(iter, &lxc_conf->populate_devs) { ++ dev_elem = iter->elem; ++ ++ if (strcmp(name, dev_elem->name) != 0) ++ continue; ++ ++ replace_value = strdup(type); ++ if (!replace_value) ++ return -1; ++ ++ free(dev_elem->type); ++ dev_elem->type = replace_value; ++ dev_elem->file_mode = filemode; ++ dev_elem->maj = major; ++ dev_elem->min = minor; ++ dev_elem->uid = (uid_t)uid; ++ dev_elem->gid = (gid_t)gid; ++ return 0; ++ } ++ ++ /* allocate list element */ ++ dev_list = malloc(sizeof(*dev_list)); ++ if (!dev_list) ++ goto on_error; ++ ++ lxc_list_init(dev_list); ++ ++ dev_elem = malloc(sizeof(*dev_elem)); ++ if (!dev_elem) ++ goto on_error; ++ memset(dev_elem, 0, sizeof(*dev_elem)); ++ ++ dev_elem->name = strdup(name); ++ if (!dev_elem->name) ++ goto on_error; ++ ++ dev_elem->type = strdup(type); ++ if (!dev_elem->type) ++ goto on_error; ++ ++ dev_elem->file_mode = filemode; ++ dev_elem->maj = major; ++ dev_elem->min = minor; ++ ++ lxc_list_add_elem(dev_list, dev_elem); ++ ++ lxc_list_add_tail(&lxc_conf->populate_devs, dev_list); ++ ++ return 0; ++ ++on_error: ++ free(dev_list); ++ if (dev_elem) { ++ free(dev_elem->name); ++ free(dev_elem->type); ++ free(dev_elem); ++ } ++ return -1; ++ ++} ++ + struct parse_line_conf { + struct lxc_conf *conf; + bool from_include; +@@ -3770,6 +3859,34 @@ static int get_config_init_args(const char *key, char *retv, int inlen, + return fulllen; + } + ++/* isulad: get config populate device ++ * If you ask for 'lxc.populate.device', then all populate device ++ * entries will be printed, in 'lxc.populate.device = path_in_container:type:major:minor:mode:uid:gid' format. ++ * For e.g. lxc.populate.device = /dev/sda:b:8:0:0666:0:0 ++ */ ++static int get_config_populate_device(const char *key, char *retv, int inlen, ++ struct lxc_conf *c, void *data) ++{ ++ int len; ++ struct lxc_list *it; ++ int fulllen = 0; ++ ++ if (!retv) ++ inlen = 0; ++ else ++ memset(retv, 0, inlen); ++ ++ lxc_list_for_each(it, &c->populate_devs) { ++ struct lxc_populate_devs *elem = it->elem; ++ strprint(retv, inlen, "lxc.populate.device = %s:%s:%d:%d:%o:%u:%u\n", ++ elem->name, elem->type, elem->maj, ++ elem->min, elem->file_mode, elem->uid, elem->gid); ++ } ++ ++ return fulllen; ++} ++ ++ + /* Callbacks to clear config items. */ + static inline int clr_config_personality(const char *key, struct lxc_conf *c, + void *data) +@@ -4581,6 +4698,13 @@ static inline int clr_config_init_args(const char *key, struct lxc_conf *c, + return lxc_clear_init_args(c); + } + ++/* isulad: clr config populate devices*/ ++static inline int clr_config_populate_device(const char *key, struct lxc_conf *c, ++ void *data) ++{ ++ return lxc_clear_populate_devices(c); ++} ++ + static int get_config_net_nic(const char *key, char *retv, int inlen, + struct lxc_conf *c, void *data) + { +-- +1.8.3.1 + diff --git a/0004-support-isulad-fifo-log.patch b/0004-support-isulad-fifo-log.patch new file mode 100644 index 0000000..b328314 --- /dev/null +++ b/0004-support-isulad-fifo-log.patch @@ -0,0 +1,96 @@ +From e5e1a628b279c604fe5eaf0cc6646e6510dfe6f7 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Fri, 11 Jan 2019 16:11:34 +0800 +Subject: [PATCH 004/122] support isulad fifo log + +support isulad fifo log in lxc3.0 + +Signed-off-by: LiFeng +--- + src/lxc/log.c | 42 ++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 40 insertions(+), 2 deletions(-) + +diff --git a/src/lxc/log.c b/src/lxc/log.c +index 1e0cc6a..4e74459 100644 +--- a/src/lxc/log.c ++++ b/src/lxc/log.c +@@ -68,6 +68,7 @@ static int syslog_enable = 0; + int lxc_quiet_specified; + int lxc_log_use_global_fd; + static int lxc_loglevel_specified; ++static bool isulad_use_log_fifo_flag = false; + + static char log_prefix[LXC_LOG_PREFIX_SIZE] = "lxc"; + static char *log_fname = NULL; +@@ -138,6 +139,37 @@ static char *lxc_log_get_va_msg(struct lxc_log_event *event) + return msg; + } + ++static const char *isulad_use_log_fifo(const char *file) ++{ ++#define ISULAD_FIFO_PREFIX "fifo:" ++ ++ if (strncmp(file, ISULAD_FIFO_PREFIX, strlen(ISULAD_FIFO_PREFIX)) == 0) { ++ isulad_use_log_fifo_flag = true; ++ return (file + strlen(ISULAD_FIFO_PREFIX)); ++ } ++ return file; ++} ++ ++static int isulad_open_fifo(const char *file_path) ++{ ++#define LOG_FIFO_SIZE (1024 * 1024) ++ int fd = -1; ++ ++ fd = lxc_unpriv(open(file_path, O_RDWR | O_NONBLOCK | O_CLOEXEC, 0640)); ++ if (fd == -1) { ++ fprintf(stderr, "Open fifo %s failed: %s\n", file_path, strerror(errno)); ++ return -1; ++ } ++ ++ if (fcntl(fd, F_SETPIPE_SZ, LOG_FIFO_SIZE) == -1) { ++ printf("Set fifo buffer size failed: %s", strerror(errno)); ++ close(fd); ++ return -1; ++ } ++ ++ return fd; ++} ++ + /*---------------------------------------------------------------------------*/ + static int log_append_syslog(const struct lxc_log_appender *appender, + struct lxc_log_event *event) +@@ -609,7 +641,11 @@ static int __lxc_log_set_file(const char *fname, int create_dirs) + return -1; + } + +- lxc_log_fd = log_open(fname); ++ if (isulad_use_log_fifo_flag) { ++ lxc_log_fd = isulad_open_fifo(fname); ++ } else { ++ lxc_log_fd = log_open(fname); ++ } + if (lxc_log_fd == -1) + return -1; + +@@ -642,6 +678,7 @@ int lxc_log_init(struct lxc_log *log) + { + int ret; + int lxc_priority = LXC_LOG_LEVEL_ERROR; ++ const char *tmp_log_fname; + + if (!log) + return -1; +@@ -673,7 +710,8 @@ int lxc_log_init(struct lxc_log *log) + if (strcmp(log->file, "none") == 0) + return 0; + +- ret = __lxc_log_set_file(log->file, 1); ++ tmp_log_fname = isulad_use_log_fifo(log->file); ++ ret = __lxc_log_set_file(tmp_log_fname, 1); + if (ret < 0) { + ERROR("Failed to enable logfile"); + return -1; +-- +1.8.3.1 + diff --git a/0005-auto-mount-cgroup-sys-and-proc.patch b/0005-auto-mount-cgroup-sys-and-proc.patch new file mode 100644 index 0000000..192542d --- /dev/null +++ b/0005-auto-mount-cgroup-sys-and-proc.patch @@ -0,0 +1,80 @@ +From f3c5a99c7bd1ecef02051489a97cbe0a1def254f Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Thu, 10 Jan 2019 20:40:19 +0800 +Subject: [PATCH 005/122] auto mount cgroup sys and proc + +Signed-off-by: LiFeng +--- + src/lxc/cgroups/cgfsng.c | 8 ++++++-- + src/lxc/conf.c | 15 ++++++++++++--- + 2 files changed, 18 insertions(+), 5 deletions(-) + +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index acc6c30..aff2b5e 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -1648,6 +1648,10 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, + + /* Mount tmpfs */ + tmpfspath = must_make_path(root, "/sys/fs/cgroup", NULL); ++ if (mkdir_p(tmpfspath, 0755) < 0) { ++ ERROR("Failed to create directory: %s", tmpfspath); ++ goto on_error; ++ } + ret = safe_mount(NULL, tmpfspath, "tmpfs", + MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME, + "size=10240k,mode=755", root); +@@ -1700,8 +1704,8 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, + continue; + } + +- path2 = must_make_path(controllerpath, h->container_base_path, +- ops->container_cgroup, NULL); ++ // Ignore ops->container_cgroup so we will not see directory lxc after /sys/fs/cgroup/xxx in container ++ path2 = must_make_path(controllerpath, h->container_base_path, NULL); + ret = mkdir_p(path2, 0755); + if (ret < 0) { + free(controllerpath); +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 20b7aba..18753d1 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -670,8 +670,8 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha + { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "%r/proc/sysrq-trigger", "%r/proc/sysrq-trigger", NULL, MS_BIND, NULL }, + { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, NULL, "%r/proc/sysrq-trigger", NULL, MS_REMOUNT|MS_BIND|MS_RDONLY, NULL }, + { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW, "proc", "%r/proc", "proc", MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL }, +- { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW, "sysfs", "%r/sys", "sysfs", 0, NULL }, +- { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO, "sysfs", "%r/sys", "sysfs", MS_RDONLY, NULL }, ++ { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW, "sysfs", "%r/sys", "sysfs", MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL }, ++ { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO, "sysfs", "%r/sys", "sysfs", MS_RDONLY|MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL }, + { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED, "sysfs", "%r/sys", "sysfs", MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL }, + { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED, NULL, "%r/sys", NULL, MS_REMOUNT|MS_BIND|MS_RDONLY, NULL }, + { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED, "sysfs", "%r/sys/devices/virtual/net", "sysfs", 0, NULL }, +@@ -710,6 +710,15 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha + return -1; + } + ++ if (mkdir_p(destination, 0755) < 0) { ++ SYSERROR("Failed to create mount target '%s'", destination); ++ saved_errno = errno; ++ free(source); ++ free(destination); ++ errno = saved_errno; ++ return -1; ++ } ++ + mflags = add_required_remount_flags(source, destination, + default_mounts[i].flags); + r = safe_mount(source, destination, default_mounts[i].fstype, +@@ -717,7 +726,7 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha + conf->rootfs.path ? conf->rootfs.mount : NULL); + saved_errno = errno; + if (r < 0 && errno == ENOENT) { +- INFO("Mount source or target for \"%s\" on \"%s\" does " ++ INFO("Mount source for \"%s\" on \"%s\" does " + "not exist. Skipping", source, destination); + r = 0; + } else if (r < 0) { +-- +1.8.3.1 + diff --git a/0006-conf.c-fix-bug-when-set-no-ro-mount-mount-propagatio.patch b/0006-conf.c-fix-bug-when-set-no-ro-mount-mount-propagatio.patch new file mode 100644 index 0000000..2c549ef --- /dev/null +++ b/0006-conf.c-fix-bug-when-set-no-ro-mount-mount-propagatio.patch @@ -0,0 +1,39 @@ +From 32f9ca00819b53c1f3bc933da8d489b3766c184d Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Fri, 11 Jan 2019 16:55:01 +0800 +Subject: [PATCH 006/122] conf.c: fix bug when set no ro mount, mount + propagation will be skipped + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 18753d1..37a5ff7 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -2087,6 +2087,9 @@ static int mount_entry(const char *fsname, const char *target, + } + } + ++#ifdef HAVE_STATVFS ++ skipremount: ++#endif + if (pflags) { + ret = mount(NULL, target, NULL, pflags, NULL); + if (ret < 0) { +@@ -2103,10 +2106,6 @@ static int mount_entry(const char *fsname, const char *target, + DEBUG("Changed mount propagation for \"%s\"", target); + } + +- +-#ifdef HAVE_STATVFS +-skipremount: +-#endif + DEBUG("Mounted \"%s\" on \"%s\" with filesystem type \"%s\"", + srcpath ? srcpath : "(null)", target, fstype); + +-- +1.8.3.1 + diff --git a/0007-use-isulad-log-format.patch b/0007-use-isulad-log-format.patch new file mode 100644 index 0000000..e71c533 --- /dev/null +++ b/0007-use-isulad-log-format.patch @@ -0,0 +1,74 @@ +From efd10df536bcbfa56369c82bda4adc77b0ea7240 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Fri, 11 Jan 2019 17:00:48 +0800 +Subject: [PATCH 007/122] use isulad log format + +use isulad log format + +Signed-off-by: LiFeng +--- + src/lxc/log.c | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) + +diff --git a/src/lxc/log.c b/src/lxc/log.c +index 4e74459..91fb7ef 100644 +--- a/src/lxc/log.c ++++ b/src/lxc/log.c +@@ -139,6 +139,7 @@ static char *lxc_log_get_va_msg(struct lxc_log_event *event) + return msg; + } + ++/* use fifo to save log */ + static const char *isulad_use_log_fifo(const char *file) + { + #define ISULAD_FIFO_PREFIX "fifo:" +@@ -150,6 +151,7 @@ static const char *isulad_use_log_fifo(const char *file) + return file; + } + ++/* open isulad fifo */ + static int isulad_open_fifo(const char *file_path) + { + #define LOG_FIFO_SIZE (1024 * 1024) +@@ -349,6 +351,8 @@ static int log_append_logfile(const struct lxc_log_appender *appender, + ssize_t ret; + int fd_to_use = -1; + const char *log_container_name; ++ const char *isulad_prefix; ++ size_t isulad_len = 0; + + #ifndef NO_LXC_CONF + if (current_config) +@@ -367,11 +371,14 @@ static int log_append_logfile(const struct lxc_log_appender *appender, + if (lxc_unix_epoch_to_utc(date_time, LXC_LOG_TIME_SIZE, &event->timestamp) < 0) + return -1; + ++ /* use isulad log format */ ++ if (log_container_name && strlen(log_container_name) > 15) { ++ isulad_len = strlen(log_container_name) - 15; ++ } ++ isulad_prefix = log_container_name ? (log_container_name + isulad_len) : log_prefix; + n = snprintf(buffer, sizeof(buffer), +- "%s%s%s %s %-8s %s - %s:%s:%d - ", +- log_prefix, +- log_container_name ? " " : "", +- log_container_name ? log_container_name : "", ++ "%15s %s %-8s %s - %s:%s:%d - ", ++ isulad_prefix, + date_time, + lxc_log_priority_to_string(event->priority), + event->category, +@@ -752,7 +759,9 @@ int lxc_log_init(struct lxc_log *log) + + if (lxc_log_fd != -1) { + lxc_log_category_lxc.appender = &log_appender_logfile; +- lxc_log_category_lxc.appender->next = &log_appender_stderr; ++ if (!lxc_quiet_specified) ++ if (!log->quiet) ++ lxc_log_category_lxc.appender->next = &log_appender_stderr; + } + + return ret; +-- +1.8.3.1 + diff --git a/0008-isulad-modify-exit-code-and-stop-signal.patch b/0008-isulad-modify-exit-code-and-stop-signal.patch new file mode 100644 index 0000000..02516d7 --- /dev/null +++ b/0008-isulad-modify-exit-code-and-stop-signal.patch @@ -0,0 +1,106 @@ +From a5754c856857cee09e307e4e8459e8e99167e46a Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Fri, 11 Jan 2019 17:44:53 +0800 +Subject: [PATCH 008/122] isulad: modify exit code and stop signal + +1. modify default stop signal and disable reboot by signal. +2. send '128 + signal' if container is killed by signal. + +Signed-off-by: LiFeng +--- + src/lxc/lxccontainer.c | 6 ++---- + src/lxc/start.c | 33 ++++++++++++++++----------------- + 2 files changed, 18 insertions(+), 21 deletions(-) + +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index b4cacce..1d7f5be 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -2069,7 +2069,8 @@ static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout) + { + int killret, ret; + pid_t pid; +- int haltsignal = SIGPWR, state_client_fd = -EBADF; ++ // isulad: keep default signal the same as docker ++ int haltsignal = SIGTERM, state_client_fd = -EBADF; + lxc_state_t states[MAX_STATE] = {0}; + + if (!c) +@@ -2082,11 +2083,8 @@ static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout) + if (pid <= 0) + return true; + +- /* Detect whether we should send SIGRTMIN + 3 (e.g. systemd). */ + if (c->lxc_conf && c->lxc_conf->haltsignal) + haltsignal = c->lxc_conf->haltsignal; +- else if (task_blocks_signal(pid, (SIGRTMIN + 3))) +- haltsignal = (SIGRTMIN + 3); + + /* Add a new state client before sending the shutdown signal so that we + * don't miss a state. +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 72e2de2..d64bdac 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -1893,11 +1893,14 @@ out_abort: + return -1; + } + ++// isulad: send '128 + signal' if container is killed by signal. ++#define ExitSignalOffset 128 ++ + int __lxc_start(const char *name, struct lxc_handler *handler, + struct lxc_operations* ops, void *data, const char *lxcpath, + bool daemonize, int *error_num) + { +- int ret, status; ++ int ret, status, exit_code; + struct lxc_conf *conf = handler->conf; + + ret = lxc_init(name, handler); +@@ -1966,22 +1969,18 @@ int __lxc_start(const char *name, struct lxc_handler *handler, + * reboot. This should mean it was an lxc-execute which simply exited. + * In any case, treat it as a 'halt'. + */ ++ // isulad: recored log for container init exit + if (WIFSIGNALED(status)) { +- switch(WTERMSIG(status)) { +- case SIGINT: /* halt */ +- DEBUG("Container \"%s\" is halting", name); +- break; +- case SIGHUP: /* reboot */ +- DEBUG("Container \"%s\" is rebooting", name); +- handler->conf->reboot = REBOOT_REQ; +- break; +- case SIGSYS: /* seccomp */ +- DEBUG("Container \"%s\" violated its seccomp policy", name); +- break; +- default: +- DEBUG("Unknown exit status for container \"%s\" init %d", name, WTERMSIG(status)); +- break; +- } ++ int signal = WTERMSIG(status); ++ signal = WTERMSIG(status); ++ exit_code = ExitSignalOffset + signal; ++ ERROR("Container \"%s\" init exited with signal %d", name, signal); ++ } else if (WIFEXITED(status)) { ++ exit_code = WEXITSTATUS(status); ++ ERROR("Container \"%s\" init exited with status %d", name, exit_code); ++ } else { ++ exit_code = -1; ++ ERROR("Container \"%s\" init exited with unknown status", name); + } + + ret = lxc_restore_phys_nics_to_netns(handler); +@@ -1994,7 +1993,7 @@ int __lxc_start(const char *name, struct lxc_handler *handler, + handler->pinfd = -1; + } + +- lxc_monitor_send_exit_code(name, status, handler->lxcpath); ++ lxc_monitor_send_exit_code(name, exit_code, handler->lxcpath); + lxc_error_set_and_log(handler->pid, status); + if (error_num) + *error_num = handler->exit_status; +-- +1.8.3.1 + diff --git a/0009-lxc_start-add-default-terminal-fifos.patch b/0009-lxc_start-add-default-terminal-fifos.patch new file mode 100644 index 0000000..ecc7c0e --- /dev/null +++ b/0009-lxc_start-add-default-terminal-fifos.patch @@ -0,0 +1,538 @@ +From ca1b4a1738d4c409ddabbc5e75b8da7438b2792f Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Fri, 11 Jan 2019 21:52:11 -0500 +Subject: [PATCH 009/122] lxc_start: add default terminal fifos + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 4 + + src/lxc/lxccontainer.c | 30 +++++++ + src/lxc/lxccontainer.h | 10 +++ + src/lxc/terminal.c | 194 +++++++++++++++++++++++++++++++++++++++++++++- + src/lxc/terminal.h | 16 ++++ + src/lxc/tools/arguments.h | 5 ++ + src/lxc/tools/lxc_start.c | 11 +++ + src/lxc/utils.c | 23 ++++++ + src/lxc/utils.h | 4 + + 9 files changed, 294 insertions(+), 3 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 37a5ff7..7b7f95b 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -2714,6 +2714,10 @@ struct lxc_conf *lxc_conf_init(void) + new->console.slave = -1; + new->console.name[0] = '\0'; + memset(&new->console.ringbuf, 0, sizeof(struct lxc_ringbuf)); ++ /* isulad init console fifos */ ++ new->console.init_fifo[0] = NULL; ++ new->console.init_fifo[1] = NULL; ++ lxc_list_init(&new->console.fifos); + new->maincmd_fd = -1; + new->nbd_idx = -1; + new->rootfs.mount = strdup(default_rootfs_mount); +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index 1d7f5be..318c71e 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -4961,6 +4961,33 @@ out: + return ret; + } + ++/* isulad add set console fifos*/ ++static bool do_lxcapi_set_terminal_default_fifos(struct lxc_container *c, const char *in, const char *out) ++{ ++ struct lxc_conf *conf; ++ ++ if (!c || !c->lxc_conf || !in || !out) ++ return false; ++ if (container_mem_lock(c)) { ++ ERROR("Error getting mem lock"); ++ return false; ++ } ++ ++ conf = c->lxc_conf; ++ if (conf->console.init_fifo[0]) ++ free(conf->console.init_fifo[0]); ++ conf->console.init_fifo[0] = strdup(in); ++ ++ if (conf->console.init_fifo[1]) ++ free(conf->console.init_fifo[1]); ++ conf->console.init_fifo[1] = strdup(out); ++ ++ container_mem_unlock(c); ++ return true; ++} ++ ++WRAP_API_2(bool, lxcapi_set_terminal_default_fifos, const char *, const char *) ++ + struct lxc_container *lxc_container_new(const char *name, const char *configpath) + { + struct lxc_container *c; +@@ -5084,6 +5111,9 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath + c->migrate = lxcapi_migrate; + c->console_log = lxcapi_console_log; + ++ /* isulad add begin */ ++ c->set_terminal_init_fifos = lxcapi_set_terminal_default_fifos; ++ /* isulad add end */ + return c; + + err: +diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h +index 9e06215..486531e 100644 +--- a/src/lxc/lxccontainer.h ++++ b/src/lxc/lxccontainer.h +@@ -847,6 +847,16 @@ struct lxc_container { + * \return \c true if the container was rebooted successfully, else \c false. + */ + bool (*reboot2)(struct lxc_container *c, int timeout); ++ ++ /*! isulad add ++ * \brief An API call to change the path of the console default fifos ++ * ++ * \param c Container. ++ * \param path Value of the console path. ++ * ++ * \return \c true on success, else \c false. ++ */ ++ bool (*set_terminal_init_fifos)(struct lxc_container *c, const char *in, const char *out); + }; + + /*! +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index 4060e7f..c507712 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -364,6 +364,20 @@ static int lxc_terminal_write_log_file(struct lxc_terminal *terminal, char *buf, + return bytes_read; + } + ++/* isulad: forward data to all fifos */ ++static void lxc_forward_data_to_fifo(struct lxc_list *list, char *buf, int r) ++{ ++ struct lxc_list *it,*next; ++ struct lxc_fifos_fd *elem = NULL; ++ ++ lxc_list_for_each_safe(it, list, next) { ++ elem = it->elem; ++ lxc_write_nointr(elem->out_fd, buf, r); ++ } ++ ++ return; ++} ++ + int lxc_terminal_io_cb(int fd, uint32_t events, void *data, + struct lxc_epoll_descr *descr) + { +@@ -384,7 +398,13 @@ int lxc_terminal_io_cb(int fd, uint32_t events, void *data, + terminal->tty_state = NULL; + } + terminal->peer = -EBADF; +- } else { ++ close(fd); ++ return LXC_MAINLOOP_CONTINUE; /* isulad: do not close mainloop when peer close*/ ++ } else if (lxc_terminal_is_fifo(fd, &terminal->fifos)) { ++ /* isulad: delete fifos when the client close */ ++ lxc_terminal_delete_fifo(fd, &terminal->fifos); ++ return LXC_MAINLOOP_CONTINUE; ++ } else { + ERROR("Handler received unexpected file descriptor"); + } + close(fd); +@@ -392,7 +412,7 @@ int lxc_terminal_io_cb(int fd, uint32_t events, void *data, + return LXC_MAINLOOP_CLOSE; + } + +- if (fd == terminal->peer) ++ if (fd == terminal->peer || lxc_terminal_is_fifo(fd, &terminal->fifos)) + w = lxc_write_nointr(terminal->master, buf, r); + + w_rbuf = w_log = 0; +@@ -401,6 +421,9 @@ int lxc_terminal_io_cb(int fd, uint32_t events, void *data, + if (terminal->peer >= 0) + w = lxc_write_nointr(terminal->peer, buf, r); + ++ /* isulad: forward data to fifos */ ++ lxc_forward_data_to_fifo(&terminal->fifos, buf, r); ++ + /* write to terminal ringbuffer */ + if (terminal->buffer_size > 0) + w_rbuf = lxc_ringbuf_write(&terminal->ringbuf, buf, r); +@@ -450,6 +473,27 @@ static int lxc_terminal_mainloop_add_peer(struct lxc_terminal *terminal) + return 0; + } + ++/* isulad add fifo to mainloop */ ++static int lxc_console_mainloop_add_fifo(struct lxc_terminal *terminal) ++{ ++ int ret = 0; ++ struct lxc_list *it,*next; ++ struct lxc_fifos_fd *elem = NULL; ++ ++ lxc_list_for_each_safe(it, &terminal->fifos, next) { ++ elem = it->elem; ++ if (elem->in_fd >= 0) { ++ ret = lxc_mainloop_add_handler(terminal->descr, elem->in_fd, ++ lxc_terminal_io_cb, terminal); ++ if (ret) { ++ ERROR("console fifo %s not added to mainloop", elem->in_fifo); ++ return -1; ++ } ++ } ++ } ++ return ret; ++} ++ + int lxc_terminal_mainloop_add(struct lxc_epoll_descr *descr, + struct lxc_terminal *terminal) + { +@@ -473,7 +517,20 @@ int lxc_terminal_mainloop_add(struct lxc_epoll_descr *descr, + */ + terminal->descr = descr; + +- return lxc_terminal_mainloop_add_peer(terminal); ++ ret = lxc_terminal_mainloop_add_peer(terminal); ++ if (ret < 0) { ++ ERROR("Failed to add handler for terminal peer to mainloop"); ++ return -1; ++ } ++ ++ /* isulad add fifo to mainloop */ ++ ret = lxc_console_mainloop_add_fifo(terminal); ++ if (ret < 0) { ++ ERROR("Failed to add handler for terminal fifos to mainloop"); ++ return -1; ++ } ++ ++ return 0; + } + + int lxc_setup_tios(int fd, struct termios *oldtios) +@@ -812,6 +869,9 @@ void lxc_terminal_delete(struct lxc_terminal *terminal) + if (terminal->log_fd >= 0) + close(terminal->log_fd); + terminal->log_fd = -1; ++ ++ /* isulad: delete all fifos */ ++ lxc_terminal_delete_fifo(-1, &terminal->fifos); + } + + /** +@@ -880,6 +940,77 @@ int lxc_terminal_create_log_file(struct lxc_terminal *terminal) + return 0; + } + ++/* isulad: open terminal fifos */ ++static int terminal_fifo_open(const char *fifo_path, int flags) ++{ ++ int fd = -1; ++ ++ fd = open(fifo_path, flags); ++ if (fd < 0) { ++ WARN("Failed to open fifo %s to send message: %s.", fifo_path, ++ strerror(errno)); ++ return -1; ++ } ++ ++ return fd; ++} ++ ++/* isulad: set terminal fifos */ ++static int lxc_terminal_set_fifo(struct lxc_terminal *console, const char *in, const char *out) ++{ ++ int fifofd_in = -1, fifofd_out = -1; ++ struct lxc_fifos_fd *fifo_elem = NULL; ++ ++ if (!in || !out) ++ return -1; ++ ++ if (!fifo_exists(in) || !fifo_exists(out)) { ++ ERROR("File %s or %s does not refer to a FIFO", in, out); ++ return -1; ++ } ++ ++ fifofd_in = terminal_fifo_open(in, O_RDONLY | O_NONBLOCK | O_CLOEXEC); ++ if (fifofd_in < 0) { ++ ERROR("Failed to open FIFO: %s", in); ++ return -1; ++ } ++ ++ fifofd_out = terminal_fifo_open(out, O_WRONLY | O_NONBLOCK | O_CLOEXEC); ++ if (fifofd_out < 0) { ++ ERROR("Failed to open FIFO: %s", out); ++ close(fifofd_in); ++ return -1; ++ } ++ ++ fifo_elem = malloc(sizeof(*fifo_elem)); ++ if (!fifo_elem) { ++ close(fifofd_in); ++ close(fifofd_out); ++ return -1; ++ } ++ memset(fifo_elem, 0, sizeof(*fifo_elem)); ++ ++ fifo_elem->in_fifo = strdup(in); ++ fifo_elem->out_fifo = strdup(out); ++ fifo_elem->in_fd = fifofd_in; ++ fifo_elem->out_fd = fifofd_out; ++ lxc_list_add_elem(&fifo_elem->node, fifo_elem); ++ lxc_list_add_tail(&console->fifos, &fifo_elem->node); ++ ++ return fifofd_in; ++} ++ ++/* isulad: add default fifos */ ++static int lxc_terminal_fifo_default(struct lxc_terminal *terminal) ++{ ++ if (!terminal->init_fifo[0] || !terminal->init_fifo[1]) { ++ ERROR("Invalid default terminal fifos"); ++ return -1; ++ } ++ ++ return lxc_terminal_set_fifo(terminal, terminal->init_fifo[0], terminal->init_fifo[1]); ++} ++ + int lxc_terminal_create(struct lxc_terminal *terminal) + { + int ret; +@@ -902,6 +1033,13 @@ int lxc_terminal_create(struct lxc_terminal *terminal) + goto err; + } + ++ /* isulad: make master NONBLOCK */ ++ ret = fd_nonblock(terminal->master); ++ if (ret < 0) { ++ SYSERROR("Failed to set O_NONBLOCK flag on terminal master"); ++ goto err; ++ } ++ + ret = fd_cloexec(terminal->slave, true); + if (ret < 0) { + SYSERROR("Failed to set FD_CLOEXEC flag on terminal slave"); +@@ -914,6 +1052,13 @@ int lxc_terminal_create(struct lxc_terminal *terminal) + goto err; + } + ++ /* isulad: open fifos */ ++ ret = lxc_terminal_fifo_default(terminal); ++ if (ret < 0) { ++ ERROR("Failed to allocate fifo terminal"); ++ goto err; ++ } ++ + return 0; + + err: +@@ -1198,12 +1343,55 @@ void lxc_terminal_init(struct lxc_terminal *terminal) + lxc_terminal_info_init(&terminal->proxy); + } + ++/* isulad: judge the fd whether is fifo */ ++static bool lxc_terminal_is_fifo(int fd, struct lxc_list *list) ++{ ++ struct lxc_list *it,*next; ++ struct lxc_fifos_fd *elem = NULL; ++ ++ lxc_list_for_each_safe(it, list, next) { ++ elem = it->elem; ++ if (elem->in_fd == fd) ++ return true; ++ } ++ ++ return false; ++} ++ ++/* isulad: if fd == -1, means delete all the fifos*/ ++int lxc_terminal_delete_fifo(int fd, struct lxc_list *list) ++{ ++ struct lxc_list *it,*next; ++ struct lxc_fifos_fd *elem = NULL; ++ ++ lxc_list_for_each_safe(it, list, next) { ++ elem = it->elem; ++ if (elem->in_fd == fd || -1 == fd) { ++ INFO("Delete fifo fd %d", fd); ++ lxc_list_del(it); ++ if (elem->in_fifo) ++ free(elem->in_fifo); ++ if (elem->out_fifo) ++ free(elem->out_fifo); ++ close(elem->in_fd); ++ close(elem->out_fd); ++ free(elem); ++ } ++ } ++ ++ return 0; ++} ++ + void lxc_terminal_conf_free(struct lxc_terminal *terminal) + { + free(terminal->log_path); + free(terminal->path); + if (terminal->buffer_size > 0 && terminal->ringbuf.addr) + lxc_ringbuf_release(&terminal->ringbuf); ++ /*isulad: free console fifos */ ++ free(terminal->init_fifo[0]); ++ free(terminal->init_fifo[1]); ++ lxc_terminal_delete_fifo(-1, &terminal->fifos); + } + + int lxc_terminal_map_ids(struct lxc_conf *c, struct lxc_terminal *terminal) +diff --git a/src/lxc/terminal.h b/src/lxc/terminal.h +index bfd271f..d25da65 100644 +--- a/src/lxc/terminal.h ++++ b/src/lxc/terminal.h +@@ -115,6 +115,17 @@ struct lxc_terminal { + /* the in-memory ringbuffer */ + struct lxc_ringbuf ringbuf; + }; ++ char *init_fifo[2]; /* isulad: default fifos for the start */ ++ struct lxc_list fifos; /* isulad: fifos used to forward teminal */ ++}; ++ ++/* isulad: fifo struct */ ++struct lxc_fifos_fd { ++ char *in_fifo; ++ char *out_fifo; ++ int in_fd; ++ int out_fd; ++ struct lxc_list node; + }; + + /** +@@ -295,4 +306,9 @@ extern void lxc_terminal_init(struct lxc_terminal *terminal); + extern int lxc_terminal_map_ids(struct lxc_conf *c, + struct lxc_terminal *terminal); + ++/* isulad: judge the fd whether is fifo*/ ++static bool lxc_terminal_is_fifo(int fd, struct lxc_list *list); ++/* isulad: if fd == -1, means delete all the fifos*/ ++int lxc_terminal_delete_fifo(int fd, struct lxc_list *list); ++ + #endif /* __LXC_TERMINAL_H */ +diff --git a/src/lxc/tools/arguments.h b/src/lxc/tools/arguments.h +index 810050a..b7af2b5 100644 +--- a/src/lxc/tools/arguments.h ++++ b/src/lxc/tools/arguments.h +@@ -62,6 +62,7 @@ struct lxc_arguments { + + /* for lxc-start */ + const char *share_ns[32]; /* size must be greater than LXC_NS_MAX */ ++ const char *terminal_fifos[2]; /* isulad add, fifos used to redirct stdin/out/err */ + + /* for lxc-console */ + unsigned int ttynum; +@@ -172,6 +173,10 @@ struct lxc_arguments { + #define OPT_SHARE_IPC OPT_USAGE - 4 + #define OPT_SHARE_UTS OPT_USAGE - 5 + #define OPT_SHARE_PID OPT_USAGE - 6 ++/* isulad add begin */ ++#define OPT_INPUT_FIFO OPT_USAGE - 7 ++#define OPT_OUTPUT_FIFO OPT_USAGE - 8 ++/* isulad add end*/ + + extern int lxc_arguments_parse(struct lxc_arguments *args, int argc, + char *const argv[]); +diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c +index 4553cb5..8f03f11 100644 +--- a/src/lxc/tools/lxc_start.c ++++ b/src/lxc/tools/lxc_start.c +@@ -69,6 +69,8 @@ static const struct option my_longopts[] = { + {"share-ipc", required_argument, 0, OPT_SHARE_IPC}, + {"share-uts", required_argument, 0, OPT_SHARE_UTS}, + {"share-pid", required_argument, 0, OPT_SHARE_PID}, ++ {"in-fifo", required_argument, 0, OPT_INPUT_FIFO}, ++ {"out-fifo", required_argument, 0, OPT_OUTPUT_FIFO}, + LXC_COMMON_OPTIONS + }; + +@@ -140,6 +142,12 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) + case OPT_SHARE_PID: + args->share_ns[LXC_NS_PID] = arg; + break; ++ case OPT_INPUT_FIFO: ++ args->terminal_fifos[0] = arg; ++ break; ++ case OPT_OUTPUT_FIFO: ++ args->terminal_fifos[1] = arg; ++ break; + } + return 0; + } +@@ -322,6 +330,9 @@ int main(int argc, char *argv[]) + if (my_args.close_all_fds) + c->want_close_all_fds(c, true); + ++ if (my_args.terminal_fifos[0] && my_args.terminal_fifos[1]) ++ c->set_terminal_init_fifos(c, my_args.terminal_fifos[0], my_args.terminal_fifos[1]); ++ + if (args == default_args) + err = c->start(c, 0, NULL) ? EXIT_SUCCESS : EXIT_FAILURE; + else +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index 6e9165a..67c3b3e 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -611,6 +611,19 @@ bool dir_exists(const char *path) + return S_ISDIR(sb.st_mode); + } + ++bool fifo_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_ISFIFO(sb.st_mode); ++} ++ ++ + /* Note we don't use SHA-1 here as we don't want to depend on HAVE_GNUTLS. + * FNV has good anti collision properties and we're not worried + * about pre-image resistance or one-way-ness, we're just trying to make +@@ -1715,6 +1728,16 @@ int fd_cloexec(int fd, bool cloexec) + return 0; + } + ++/* isulad: fd_nonblock */ ++int fd_nonblock(int fd) ++{ ++ long flags; ++ ++ flags = fcntl(fd, F_GETFL); ++ ++ return fcntl(fd, F_SETFL, flags | O_NONBLOCK); ++} ++ + int recursive_destroy(char *dirname) + { + int ret; +diff --git a/src/lxc/utils.h b/src/lxc/utils.h +index 94196d0..2d38178 100644 +--- a/src/lxc/utils.h ++++ b/src/lxc/utils.h +@@ -147,6 +147,8 @@ extern gid_t get_ns_gid(gid_t orig); + + extern bool dir_exists(const char *path); + ++extern bool fifo_exists(const char *path); ++ + #define FNV1A_64_INIT ((uint64_t)0xcbf29ce484222325ULL) + extern uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval); + +@@ -242,4 +244,6 @@ extern int fd_cloexec(int fd, bool cloexec); + extern int recursive_destroy(char *dirname); + extern int lxc_setup_keyring(void); + ++extern int fd_nonblock(int fd); ++ + #endif /* __LXC_UTILS_H */ +-- +1.8.3.1 + diff --git a/0010-Save-pid-ppid-info-into-file-for-isulad.patch b/0010-Save-pid-ppid-info-into-file-for-isulad.patch new file mode 100644 index 0000000..b36818a --- /dev/null +++ b/0010-Save-pid-ppid-info-into-file-for-isulad.patch @@ -0,0 +1,453 @@ +From 25c94a75d742ee2c66d431ebf73c9cd0fc2e4f42 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Fri, 11 Jan 2019 22:53:56 -0500 +Subject: [PATCH 010/122] Save pid/ppid info into file for isulad + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 1 + + src/lxc/conf.h | 2 + + src/lxc/lxccontainer.c | 24 ++++++++++ + src/lxc/lxccontainer.h | 10 ++++ + src/lxc/start.c | 41 +++++++++++++++++ + src/lxc/tools/arguments.h | 2 + + src/lxc/tools/lxc_start.c | 20 ++++++++ + src/lxc/utils.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++ + src/lxc/utils.h | 66 +++++++++++++++++++++++++++ + 9 files changed, 280 insertions(+) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 7b7f95b..0b4b63b 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4194,6 +4194,7 @@ void lxc_conf_free(struct lxc_conf *conf) + /* isulad add begin */ + lxc_clear_init_args(conf); + lxc_clear_populate_devices(conf); ++ free(conf->container_info_file); + /* isulad add end */ + free(conf); + } +diff --git a/src/lxc/conf.h b/src/lxc/conf.h +index cced868..e0954f9 100644 +--- a/src/lxc/conf.h ++++ b/src/lxc/conf.h +@@ -403,6 +403,8 @@ struct lxc_conf { + size_t init_argc; + /* populate devices*/ + struct lxc_list populate_devs; ++ ++ char *container_info_file; + /* isulad add end */ + }; + +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index 318c71e..5679b9b 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -4988,6 +4988,29 @@ static bool do_lxcapi_set_terminal_default_fifos(struct lxc_container *c, const + + WRAP_API_2(bool, lxcapi_set_terminal_default_fifos, const char *, const char *) + ++/* isulad add set info file path */ ++static bool do_lxcapi_set_container_info_file(struct lxc_container *c, const char *info_file) ++{ ++ struct lxc_conf *conf; ++ ++ if (!c || !c->lxc_conf || !info_file) ++ return false; ++ if (container_mem_lock(c)) { ++ ERROR("Error getting mem lock"); ++ return false; ++ } ++ ++ conf = c->lxc_conf; ++ if (conf->container_info_file) ++ free(conf->container_info_file); ++ conf->container_info_file = strdup(info_file); ++ ++ container_mem_unlock(c); ++ return true; ++} ++ ++WRAP_API_1(bool, lxcapi_set_container_info_file, const char *) ++ + struct lxc_container *lxc_container_new(const char *name, const char *configpath) + { + struct lxc_container *c; +@@ -5113,6 +5136,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath + + /* isulad add begin */ + c->set_terminal_init_fifos = lxcapi_set_terminal_default_fifos; ++ c->set_container_info_file = lxcapi_set_container_info_file; + /* isulad add end */ + return c; + +diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h +index 486531e..3c845fe 100644 +--- a/src/lxc/lxccontainer.h ++++ b/src/lxc/lxccontainer.h +@@ -857,6 +857,16 @@ struct lxc_container { + * \return \c true on success, else \c false. + */ + bool (*set_terminal_init_fifos)(struct lxc_container *c, const char *in, const char *out); ++ ++ /*! isulad add ++ * \brief An API call to set the path of info file ++ * ++ * \param c Container. ++ * \param info_file Value of the path of info file. ++ * ++ * \return \c true on success, else \c false. ++ */ ++ bool (*set_container_info_file) (struct lxc_container *c, const char *info_file); + }; + + /*! +diff --git a/src/lxc/start.c b/src/lxc/start.c +index d64bdac..9d71dd7 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -1553,6 +1553,39 @@ static inline int do_share_ns(void *arg) + return 0; + } + ++/* isuald: save pid/ppid info */ ++static int lxc_save_container_info(char *filename, pid_t pid) ++{ ++ FILE *pid_fp = NULL; ++ int ret = 0; ++ pid_t p_pid = 0; ++ unsigned long long start_at = 0; ++ unsigned long long p_start_at = 0; ++ ++ pid_fp = fopen(filename, "w"); ++ if (pid_fp == NULL) { ++ SYSERROR("Failed to create pidfile '%s'",filename); ++ ret = -1; ++ goto out; ++ } ++ ++ start_at = lxc_get_process_startat(pid); ++ ++ p_pid = getpid(); ++ p_start_at = lxc_get_process_startat(p_pid); ++ ++ if (fprintf(pid_fp, "%d %llu %d %llu\n", pid, start_at, p_pid, p_start_at) < 0) { ++ SYSERROR("Failed to write '%s'", filename); ++ ret = -1; ++ goto out; ++ } ++out: ++ if (pid_fp) ++ fclose(pid_fp); ++ pid_fp = NULL; ++ return ret; ++} ++ + /* lxc_spawn() performs crucial setup tasks and clone()s the new process which + * exec()s the requested container binary. + * Note that lxc_spawn() runs in the parent namespaces. Any operations performed +@@ -1683,6 +1716,14 @@ static int lxc_spawn(struct lxc_handler *handler) + } + TRACE("Cloned child process %d", handler->pid); + ++ /* isulad: save pid/ppid info into file*/ ++ if (handler->conf->container_info_file) { ++ if (lxc_save_container_info(handler->conf->container_info_file, handler->pid)) { ++ ERROR("Failed to save cloned container pid"); ++ goto out_delete_net; ++ } ++ } ++ + for (i = 0; i < LXC_NS_MAX; i++) + if (handler->ns_on_clone_flags & ns_info[i].clone_flag) + INFO("Cloned %s", ns_info[i].flag_name); +diff --git a/src/lxc/tools/arguments.h b/src/lxc/tools/arguments.h +index b7af2b5..b6df23f 100644 +--- a/src/lxc/tools/arguments.h ++++ b/src/lxc/tools/arguments.h +@@ -63,6 +63,7 @@ struct lxc_arguments { + /* for lxc-start */ + const char *share_ns[32]; /* size must be greater than LXC_NS_MAX */ + const char *terminal_fifos[2]; /* isulad add, fifos used to redirct stdin/out/err */ ++ const char *container_info; /* isulad: file used to store pid and ppid info of container */ + + /* for lxc-console */ + unsigned int ttynum; +@@ -176,6 +177,7 @@ struct lxc_arguments { + /* isulad add begin */ + #define OPT_INPUT_FIFO OPT_USAGE - 7 + #define OPT_OUTPUT_FIFO OPT_USAGE - 8 ++#define OPT_CONTAINER_INFO OPT_USAGE - 9 + /* isulad add end*/ + + extern int lxc_arguments_parse(struct lxc_arguments *args, int argc, +diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c +index 8f03f11..2f94d67 100644 +--- a/src/lxc/tools/lxc_start.c ++++ b/src/lxc/tools/lxc_start.c +@@ -69,8 +69,11 @@ static const struct option my_longopts[] = { + {"share-ipc", required_argument, 0, OPT_SHARE_IPC}, + {"share-uts", required_argument, 0, OPT_SHARE_UTS}, + {"share-pid", required_argument, 0, OPT_SHARE_PID}, ++ /* isulad add begin */ + {"in-fifo", required_argument, 0, OPT_INPUT_FIFO}, + {"out-fifo", required_argument, 0, OPT_OUTPUT_FIFO}, ++ {"container-pidfile", required_argument, 0, OPT_CONTAINER_INFO}, ++ /* isulad add end */ + LXC_COMMON_OPTIONS + }; + +@@ -148,6 +151,9 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) + case OPT_OUTPUT_FIFO: + args->terminal_fifos[1] = arg; + break; ++ case OPT_CONTAINER_INFO: ++ args->container_info = arg; ++ break; + } + return 0; + } +@@ -189,6 +195,7 @@ int main(int argc, char *argv[]) + struct lxc_log log; + int err = EXIT_FAILURE; + char *rcfile = NULL; ++ char *container_info_file = NULL; /* isulad: info file*/ + char *const default_args[] = { + "/sbin/init", + NULL, +@@ -313,6 +320,18 @@ int main(int argc, char *argv[]) + goto out; + } + ++ /* isulad: container info file used to store pid and ppid info of container*/ ++ if (my_args.container_info != NULL) { ++ if (ensure_path(&container_info_file, my_args.container_info) < 0) { ++ ERROR("Failed to ensure container's piddile '%s'", my_args.container_info); ++ goto out; ++ } ++ if (!c->set_container_info_file(c, container_info_file)) { ++ ERROR("Failed to set container's piddile '%s'", container_info_file); ++ goto out; ++ } ++ } ++ + if (my_args.console) + if (!c->set_config_item(c, "lxc.console.path", my_args.console)) + goto out; +@@ -353,5 +372,6 @@ int main(int argc, char *argv[]) + + out: + lxc_container_put(c); ++ free(container_info_file); + exit(err); + } +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index 67c3b3e..4728284 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -1828,3 +1828,117 @@ int lxc_setup_keyring(void) + + return ret; + } ++ ++/* isulad: read file to buffer */ ++static int lxc_file2str(const char *filename, char ret[], int cap) ++{ ++ int fd, num_read; ++ ++ if ((fd = open(filename, O_RDONLY | O_CLOEXEC)) == -1) ++ return -1;/*lint !e960*/ ++ if ((num_read = read(fd, ret, cap - 1)) <= 0) ++ num_read = -1;/*lint !e960*/ ++ else ++ ret[num_read] = 0;/*lint !e613*//*lint !e960*/ ++ close(fd); ++ ++ return num_read; ++} ++ ++/* isuald: lxc_stat2proc() makes sure it can handle arbitrary executable file basenames ++ * for `cmd', i.e. those with embedded whitespace or embedded ')'s. ++ * Such names confuse %s (see scanf(3)), so the string is split and %39c ++ * is used instead. (except for embedded ')' "(%[^)]c)" would work. ++ */ ++static proc_t *lxc_stat2proc(char *S) ++{ ++ int num; ++ proc_t *P = NULL; ++ char *tmp = NULL; ++ ++ if (!S) ++ return NULL;/*lint !e960*/ ++ ++ tmp = strrchr(S, ')'); /* split into "PID (cmd" and "" *//*lint !e586*/ ++ if (!tmp) ++ return NULL;/*lint !e960*/ ++ *tmp = '\0'; /* replace trailing ')' with NUL */ ++ ++ P = malloc(sizeof(proc_t)); ++ if (!P) ++ return NULL;/*lint !e960*/ ++ memset(P, 0x00, sizeof(proc_t)); ++ ++ /* parse these two strings separately, skipping the leading "(". */ ++ num = sscanf(S, "%d (%15c", &P->pid, P->cmd); /* comm[16] in kernel */ ++ if (num < 0 && errno) { ++ ERROR("Call sscanf error: %s", strerror(errno)); ++ free(P); ++ return NULL; ++ } ++ num = sscanf(tmp + 2, /* skip space after ')' too */ ++ "%c " ++ "%d %d %d %d %d " ++ "%lu %lu %lu %lu %lu " ++ "%Lu %Lu %Lu %Lu " /* utime stime cutime cstime *//*lint !e566*/ ++ "%ld %ld %ld %ld " ++ "%Lu " /* start_time *//*lint !e566*/ ++ "%lu " ++ "%ld " ++ "%lu %lu %lu %lu %lu %lu " ++ "%*s %*s %*s %*s " /* discard, no RT signals & Linux 2.1 used hex */ ++ "%lu %lu %lu " ++ "%d %d " ++ "%lu %lu", ++ &P->state, ++ &P->ppid, &P->pgrp, &P->session, &P->tty, &P->tpgid, ++ &P->flags, &P->min_flt, &P->cmin_flt, &P->maj_flt, &P->cmaj_flt, ++ &P->utime, &P->stime, &P->cutime, &P->cstime,/*lint !e561*/ ++ &P->priority, &P->nice, &P->timeout, &P->it_real_value, ++ &P->start_time,/*lint !e561*/ ++ &P->vsize, ++ &P->rss, ++ &P->rss_rlim, &P->start_code, &P->end_code, &P->start_stack, &P->kstk_esp, ++ &P->kstk_eip, ++ &P->wchan, &P->nswap, &P->cnswap, ++ &P->exit_signal, &P->processor, /* 2.2.1 ends with "exit_signal" */ ++ &P->rtprio, &P->sched /* both added to 2.5.18 */ ++ ); ++ ++ if (P->tty == 0) ++ P->tty = -1; /* the old notty val, update elsewhere bef. moving to 0 *//*lint !e960*/ ++ return P; ++} ++ ++/* isulad: get starttime of process pid */ ++unsigned long long lxc_get_process_startat(pid_t pid) ++{ ++ int sret = 0; ++ unsigned long long startat = 0; ++ proc_t *pid_info = NULL; ++ char filename[PATH_MAX] = {0}; ++ char sbuf[1024] = {0}; /* bufs for stat */ ++ ++ sret = snprintf(filename, sizeof(filename), "/proc/%d/stat", pid); ++ if (sret < 0 || sret >= sizeof(filename)) {/*lint !e574*/ ++ ERROR("Failed to sprintf filename"); ++ goto out; ++ } ++ ++ if ((lxc_file2str(filename, sbuf, sizeof(sbuf))) == -1) { ++ SYSERROR("Failed to read pidfile %s", filename); ++ goto out; ++ } ++ ++ pid_info = lxc_stat2proc(sbuf); ++ if (!pid_info) {/*lint !e574*/ ++ ERROR("Failed to get proc stat info"); ++ goto out; ++ } ++ ++ startat = pid_info->start_time; ++out: ++ free(pid_info); ++ return startat; ++} ++ +diff --git a/src/lxc/utils.h b/src/lxc/utils.h +index 2d38178..8e4ed89 100644 +--- a/src/lxc/utils.h ++++ b/src/lxc/utils.h +@@ -56,6 +56,71 @@ extern char *get_rundir(void); + #endif + #endif + ++/* isuald: ++ ld cutime, cstime, priority, nice, timeout, it_real_value, rss, ++ c state, ++ d ppid, pgrp, session, tty, tpgid, ++ s signal, blocked, sigignore, sigcatch, ++ lu flags, min_flt, cmin_flt, maj_flt, cmaj_flt, utime, stime, ++ lu rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip, ++ lu start_time, vsize, wchan, nswap, cnswap, ++*/ ++ ++/* Basic data structure which holds all information we can get about a process. ++ * (unless otherwise specified, fields are read from /proc/#/stat) ++ * ++ * Most of it comes from task_struct in linux/sched.h ++ */ ++typedef struct proc_t { ++ // 1st 16 bytes ++ int pid; /* process id */ ++ int ppid; /* pid of parent process */ ++ ++ char state; /* single-char code for process state (S=sleeping) */ ++ ++ unsigned long long ++ utime, /* user-mode CPU time accumulated by process */ ++ stime, /* kernel-mode CPU time accumulated by process */ ++ // and so on... ++ cutime, /* cumulative utime of process and reaped children */ ++ cstime, /* cumulative stime of process and reaped children */ ++ start_time; /* start time of process -- seconds since 1-1-70 */ ++ ++ long ++ priority, /* kernel scheduling priority */ ++ timeout, /* ? */ ++ nice, /* standard unix nice level of process */ ++ rss, /* resident set size from /proc/#/stat (pages) */ ++ it_real_value; /* ? */ ++ unsigned long ++ rtprio, /* real-time priority */ ++ sched, /* scheduling class */ ++ vsize, /* number of pages of virtual memory ... */ ++ rss_rlim, /* resident set size limit? */ ++ flags, /* kernel flags for the process */ ++ min_flt, /* number of minor page faults since process start */ ++ maj_flt, /* number of major page faults since process start */ ++ cmin_flt, /* cumulative min_flt of process and child processes */ ++ cmaj_flt, /* cumulative maj_flt of process and child processes */ ++ nswap, /* ? */ ++ cnswap, /* cumulative nswap ? */ ++ start_code, /* address of beginning of code segment */ ++ end_code, /* address of end of code segment */ ++ start_stack, /* address of the bottom of stack for the process */ ++ kstk_esp, /* kernel stack pointer */ ++ kstk_eip, /* kernel instruction pointer */ ++ wchan; /* address of kernel wait channel proc is sleeping in */ ++ ++ char cmd[16]; /* basename of executable file in call to exec(2) */ ++ int ++ pgrp, /* process group id */ ++ session, /* session id */ ++ tty, /* full device number of controlling terminal */ ++ tpgid, /* terminal process group id */ ++ exit_signal, /* might not be SIGCHLD */ ++ processor; /* current (or most recent?) CPU */ ++} proc_t; ++ + static inline int lxc_set_cloexec(int fd) + { + return fcntl(fd, F_SETFD, FD_CLOEXEC); +@@ -245,5 +310,6 @@ extern int recursive_destroy(char *dirname); + extern int lxc_setup_keyring(void); + + extern int fd_nonblock(int fd); ++extern int unsigned long long lxc_get_process_startat(pid_t pid); + + #endif /* __LXC_UTILS_H */ +-- +1.8.3.1 + diff --git a/0011-Add-exit-FIFO-to-monitor-state-of-lxc-monitor.patch b/0011-Add-exit-FIFO-to-monitor-state-of-lxc-monitor.patch new file mode 100644 index 0000000..5e2454a --- /dev/null +++ b/0011-Add-exit-FIFO-to-monitor-state-of-lxc-monitor.patch @@ -0,0 +1,261 @@ +From dab4938915c64b201434719712dd5222a11b9dcf Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Sat, 12 Jan 2019 02:07:15 -0500 +Subject: [PATCH 011/122] Add exit FIFO to monitor state of [lxc monitor] + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 3 +++ + src/lxc/conf.h | 2 ++ + src/lxc/confile.c | 8 ++++---- + src/lxc/lxccontainer.c | 20 +++++++++++++++++++- + src/lxc/lxccontainer.h | 6 ++++++ + src/lxc/start.c | 10 ++++++++++ + src/lxc/start.h | 2 ++ + src/lxc/terminal.c | 4 ++-- + src/lxc/tools/arguments.h | 2 ++ + src/lxc/tools/lxc_start.c | 9 +++++++++ + 10 files changed, 59 insertions(+), 7 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 0b4b63b..bc45e44 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -2759,6 +2759,7 @@ struct lxc_conf *lxc_conf_init(void) + + /* isulad add begin */ + lxc_list_init(&new->populate_devs); ++ new->exit_fd = -1; + /* isulad add end */ + + return new; +@@ -4195,6 +4196,8 @@ void lxc_conf_free(struct lxc_conf *conf) + lxc_clear_init_args(conf); + lxc_clear_populate_devices(conf); + free(conf->container_info_file); ++ if (conf->exit_fd != -1) ++ close(conf->exit_fd); + /* isulad add end */ + free(conf); + } +diff --git a/src/lxc/conf.h b/src/lxc/conf.h +index e0954f9..2d939cd 100644 +--- a/src/lxc/conf.h ++++ b/src/lxc/conf.h +@@ -405,6 +405,8 @@ struct lxc_conf { + struct lxc_list populate_devs; + + char *container_info_file; ++ ++ int exit_fd; /* exit fifo fd*/ + /* isulad add end */ + }; + +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index e3212d3..cbef2e2 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -240,10 +240,10 @@ static struct lxc_config_t config_jump_table[] = { + { "lxc.sysctl", set_config_sysctl, get_config_sysctl, clr_config_sysctl, }, + { "lxc.proc", set_config_proc, get_config_proc, clr_config_proc, }, + +- /*isulad add begin*/ +- { "lxc.isulad.init.args", set_config_init_args, get_config_init_args, clr_config_init_args, }, +- { "lxc.isulad.populate.device", set_config_populate_device, get_config_populate_device, clr_config_populate_device, }, +- /*isulad add end*/ ++ /*isulad add begin*/ ++ { "lxc.isulad.init.args", set_config_init_args, get_config_init_args, clr_config_init_args, }, ++ { "lxc.isulad.populate.device", set_config_populate_device, get_config_populate_device, clr_config_populate_device, }, ++ /*isulad add end*/ + }; + + static const size_t config_jump_table_size = sizeof(config_jump_table) / sizeof(struct lxc_config_t); +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index 5679b9b..8029f33 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -295,6 +295,10 @@ static void lxc_container_free(struct lxc_container *c) + free(c->config_path); + c->config_path = NULL; + ++ /* isulad: free exit fifo */ ++ free(c->exit_fifo); ++ c->exit_fifo = NULL; ++ + free(c); + } + +@@ -882,7 +886,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a + NULL, + }; + char **init_cmd = NULL; +- int keepfds[3] = {-1, -1, -1}; ++ int keepfds[4] = {-1, -1, -1, -1}; + + /* container does exist */ + if (!c) +@@ -1077,6 +1081,16 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a + } + } + ++ /* isulad: open exit fifo */ ++ if (c->exit_fifo) { ++ conf->exit_fd = open(c->exit_fifo, O_WRONLY | O_NONBLOCK | O_CLOEXEC); ++ if (conf->exit_fd < 0) { ++ ERROR("Failed to open exit fifo %s: %s.", c->exit_fifo, strerror(errno)); ++ ret = 1; ++ goto on_error; ++ } ++ } ++ + conf->reboot = REBOOT_NONE; + + /* Unshare the mount namespace if requested */ +@@ -1111,6 +1125,10 @@ reboot: + keepfds[0] = handler->conf->maincmd_fd; + keepfds[1] = handler->state_socket_pair[0]; + keepfds[2] = handler->state_socket_pair[1]; ++ /* isulad: keep exit fifo fd */ ++ if (conf->exit_fd >= 0) { ++ keepfds[3] = conf->exit_fd; ++ } + ret = lxc_check_inherited(conf, c->daemonize, keepfds, + sizeof(keepfds) / sizeof(keepfds[0])); + if (ret < 0) { +diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h +index 3c845fe..503038a 100644 +--- a/src/lxc/lxccontainer.h ++++ b/src/lxc/lxccontainer.h +@@ -81,6 +81,12 @@ struct lxc_container { + */ + char *pidfile; + ++ /*! isulad: ++ * \private ++ * exit FIFO File to open used monitor the state of lxc monitor process. ++ */ ++ char *exit_fifo; ++ + /*! + * \private + * Container semaphore lock. +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 9d71dd7..9365d11 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -730,6 +730,7 @@ struct lxc_handler *lxc_init_handler(const char *name, struct lxc_conf *conf, + handler->nsfd[i] = -1; + + handler->name = name; ++ handler->exit_code = -1; /* isulad: record exit code of container */ + + if (daemonize && handler->conf->reboot == REBOOT_NONE) { + /* Create socketpair() to synchronize on daemonized startup. +@@ -1005,6 +1006,14 @@ void lxc_fini(const char *name, struct lxc_handler *handler) + */ + lxc_monitor_send_state(name, STOPPED, handler->lxcpath); + ++ ++ /* isuald: write exit code to exit fifo */ ++ if (handler->conf->exit_fd >= 0) { ++ ret = write(handler->conf->exit_fd, &handler->exit_code, sizeof(int)); ++ if (ret != sizeof(int)) ++ SYSERROR("Failed to write to exit code to exit fifo."); ++ } ++ + /* The command socket is closed so no one can acces the command + * socket anymore so there's no need to lock it. + */ +@@ -2038,6 +2047,7 @@ int __lxc_start(const char *name, struct lxc_handler *handler, + lxc_error_set_and_log(handler->pid, status); + if (error_num) + *error_num = handler->exit_status; ++ handler->exit_code = exit_code; /* isuald: record exit code*/ + + out_fini: + lxc_delete_network(handler); +diff --git a/src/lxc/start.h b/src/lxc/start.h +index df987dc..f59bf54 100644 +--- a/src/lxc/start.h ++++ b/src/lxc/start.h +@@ -133,6 +133,8 @@ struct lxc_handler { + int exit_status; + + struct cgroup_ops *cgroup_ops; ++ ++ int exit_code;/* isulad: record the exit code of container */ + }; + + struct execute_args { +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index c507712..508e2e6 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -1004,8 +1004,8 @@ static int lxc_terminal_set_fifo(struct lxc_terminal *console, const char *in, c + static int lxc_terminal_fifo_default(struct lxc_terminal *terminal) + { + if (!terminal->init_fifo[0] || !terminal->init_fifo[1]) { +- ERROR("Invalid default terminal fifos"); +- return -1; ++ DEBUG("Invalid default terminal fifos"); ++ return 0; + } + + return lxc_terminal_set_fifo(terminal, terminal->init_fifo[0], terminal->init_fifo[1]); +diff --git a/src/lxc/tools/arguments.h b/src/lxc/tools/arguments.h +index b6df23f..61f4a0a 100644 +--- a/src/lxc/tools/arguments.h ++++ b/src/lxc/tools/arguments.h +@@ -64,6 +64,7 @@ struct lxc_arguments { + const char *share_ns[32]; /* size must be greater than LXC_NS_MAX */ + const char *terminal_fifos[2]; /* isulad add, fifos used to redirct stdin/out/err */ + const char *container_info; /* isulad: file used to store pid and ppid info of container */ ++ const char *exit_monitor_fifo; /* isulad: fifo used to monitor state of monitor process */ + + /* for lxc-console */ + unsigned int ttynum; +@@ -178,6 +179,7 @@ struct lxc_arguments { + #define OPT_INPUT_FIFO OPT_USAGE - 7 + #define OPT_OUTPUT_FIFO OPT_USAGE - 8 + #define OPT_CONTAINER_INFO OPT_USAGE - 9 ++#define OPT_EXIT_FIFO OPT_USAGE - 10 + /* isulad add end*/ + + extern int lxc_arguments_parse(struct lxc_arguments *args, int argc, +diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c +index 2f94d67..60c7d70 100644 +--- a/src/lxc/tools/lxc_start.c ++++ b/src/lxc/tools/lxc_start.c +@@ -73,6 +73,7 @@ static const struct option my_longopts[] = { + {"in-fifo", required_argument, 0, OPT_INPUT_FIFO}, + {"out-fifo", required_argument, 0, OPT_OUTPUT_FIFO}, + {"container-pidfile", required_argument, 0, OPT_CONTAINER_INFO}, ++ {"exit-fifo", required_argument, 0, OPT_EXIT_FIFO}, + /* isulad add end */ + LXC_COMMON_OPTIONS + }; +@@ -154,6 +155,9 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) + case OPT_CONTAINER_INFO: + args->container_info = arg; + break; ++ case OPT_EXIT_FIFO: ++ args->exit_monitor_fifo = arg; ++ break; + } + return 0; + } +@@ -332,6 +336,11 @@ int main(int argc, char *argv[]) + } + } + ++ /* isulad: fifo used to monitor state of monitor process */ ++ if (my_args.exit_monitor_fifo != NULL) { ++ c->exit_fifo = strdup(my_args.exit_monitor_fifo); ++ } ++ + if (my_args.console) + if (!c->set_config_item(c, "lxc.console.path", my_args.console)) + goto out; +-- +1.8.3.1 + diff --git a/0012-Init-fifos-in-lxc_attach_terminal.patch b/0012-Init-fifos-in-lxc_attach_terminal.patch new file mode 100644 index 0000000..1e2815a --- /dev/null +++ b/0012-Init-fifos-in-lxc_attach_terminal.patch @@ -0,0 +1,28 @@ +From 1ea4f8a2c3d3070fa9aafd9f055bed3b9018198b Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Sat, 12 Jan 2019 03:23:53 -0500 +Subject: [PATCH 012/122] Init fifos in lxc_attach_terminal + +Signed-off-by: LiFeng +--- + src/lxc/terminal.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index 508e2e6..410f643 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -1341,6 +1341,10 @@ void lxc_terminal_init(struct lxc_terminal *terminal) + terminal->peer = -EBADF; + terminal->log_fd = -EBADF; + lxc_terminal_info_init(&terminal->proxy); ++ /* isulad init console fifos */ ++ terminal->init_fifo[0] = NULL; ++ terminal->init_fifo[1] = NULL; ++ lxc_list_init(&terminal->fifos); + } + + /* isulad: judge the fd whether is fifo */ +-- +1.8.3.1 + diff --git a/0013-isulad-set-env-home-in-container.patch b/0013-isulad-set-env-home-in-container.patch new file mode 100644 index 0000000..c78deaf --- /dev/null +++ b/0013-isulad-set-env-home-in-container.patch @@ -0,0 +1,139 @@ +From 4fad66dc56b5863b3e272408b265eddf244434ef Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Sat, 12 Jan 2019 14:42:27 +0800 +Subject: [PATCH 013/122] isulad: set env home in container + +Signed-off-by: LiFeng +--- + src/lxc/attach.c | 5 +++++ + src/lxc/cgroups/cgfsng.c | 5 +++-- + src/lxc/conf.c | 2 +- + src/lxc/start.c | 4 ++++ + src/lxc/utils.c | 29 +++++++++++++++++++++++++++++ + src/lxc/utils.h | 3 +++ + 6 files changed, 45 insertions(+), 3 deletions(-) + +diff --git a/src/lxc/attach.c b/src/lxc/attach.c +index e7ba705..2bbf1eb 100644 +--- a/src/lxc/attach.c ++++ b/src/lxc/attach.c +@@ -876,6 +876,11 @@ static int attach_child_main(struct attach_clone_payload *payload) + else + new_gid = ns_root_gid; + ++ // isulad: set env home in container ++ if (lxc_setup_env_home(new_uid) < 0) { ++ goto on_error; ++ } ++ + if ((init_ctx->container && init_ctx->container->lxc_conf && + init_ctx->container->lxc_conf->no_new_privs) || + (options->attach_flags & LXC_ATTACH_NO_NEW_PRIVS)) { +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index aff2b5e..3e702b3 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -1704,8 +1704,9 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, + continue; + } + +- // Ignore ops->container_cgroup so we will not see directory lxc after /sys/fs/cgroup/xxx in container +- path2 = must_make_path(controllerpath, h->container_base_path, NULL); ++ // isulad: ignore ops->container_cgroup so we will not see directory lxc after /sys/fs/cgroup/xxx in container, ++ // isulad: ignore h->container_base_path so we will not see subgroup of /sys/fs/cgroup/xxx/subgroup in container ++ path2 = must_make_path(controllerpath, NULL); + ret = mkdir_p(path2, 0755); + if (ret < 0) { + free(controllerpath); +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index bc45e44..5065e69 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -3680,7 +3680,7 @@ int lxc_setup(struct lxc_handler *handler) + return -1; + } + +- /*isulad: move mount entrues here, before we do lxc_fill_autodev and populate devices */ ++ /*isulad: move mount entries here, before we do lxc_fill_autodev and populate devices */ + if (!lxc_list_empty(&lxc_conf->mount_list)) { + ret = setup_mount_entries(lxc_conf, &lxc_conf->rootfs, + &lxc_conf->mount_list, name, lxcpath); +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 9365d11..b13326c 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -1398,6 +1398,10 @@ static int do_start(void *data) + new_uid = handler->conf->init_uid; + new_gid = handler->conf->init_gid; + ++ // isulad: set env home in container ++ if (lxc_setup_env_home(new_uid) < 0) ++ goto out_warn_father; ++ + /* Avoid unnecessary syscalls. */ + if (new_uid == nsuid) + new_uid = LXC_INVALID_UID; +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index 4728284..74e74a1 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -45,6 +45,7 @@ + #include + #include + #include ++#include + + #include "config.h" + #include "log.h" +@@ -1829,6 +1830,34 @@ int lxc_setup_keyring(void) + return ret; + } + ++// isulad: set env home in container ++int lxc_setup_env_home(uid_t uid) ++{ ++#define __DEFAULT_HOMEDIR__ "/" ++ int ret = 0; ++ char *homedir; ++ struct passwd pwd, *result = NULL; ++ char buf[BUFSIZ]; ++ ++ ret = getpwuid_r(uid, &pwd, buf, BUFSIZ, &result); ++ if (ret || !result || !result->pw_dir) { ++ WARN("User invalid, can not find user '%u'", uid); ++ homedir = __DEFAULT_HOMEDIR__; ++ } else { ++ homedir = result->pw_dir; ++ } ++ ++ // if we didn't configure HOME, set it based on uid ++ if (setenv("HOME", homedir, 0) < 0) { ++ SYSERROR("Unable to set env 'HOME'"); ++ return -1; ++ } ++ ++ NOTICE("Setted env 'HOME' to %s", homedir); ++ return 0; ++} ++ ++ + /* isulad: read file to buffer */ + static int lxc_file2str(const char *filename, char ret[], int cap) + { +diff --git a/src/lxc/utils.h b/src/lxc/utils.h +index 8e4ed89..364bf67 100644 +--- a/src/lxc/utils.h ++++ b/src/lxc/utils.h +@@ -309,6 +309,9 @@ extern int fd_cloexec(int fd, bool cloexec); + extern int recursive_destroy(char *dirname); + extern int lxc_setup_keyring(void); + ++// isulad: set env home in container ++extern int lxc_setup_env_home(uid_t uid); ++ + extern int fd_nonblock(int fd); + extern int unsigned long long lxc_get_process_startat(pid_t pid); + +-- +1.8.3.1 + diff --git a/0014-support-rotate-for-container-log-file.patch b/0014-support-rotate-for-container-log-file.patch new file mode 100644 index 0000000..318276c --- /dev/null +++ b/0014-support-rotate-for-container-log-file.patch @@ -0,0 +1,93 @@ +From e30d1a025a5f74c90a60a36fb6b61ccce18b88cf Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Sat, 12 Jan 2019 15:29:56 +0800 +Subject: [PATCH 014/122] support rotate for container log file + +support rotate for container log file + +Signed-off-by: LiFeng +--- + src/lxc/confile.c | 3 +++ + src/lxc/terminal.c | 40 ++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 43 insertions(+) + +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index cbef2e2..e782211 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -1802,11 +1802,14 @@ static int set_config_console_rotate(const char *key, const char *value, + if (lxc_safe_uint(value, &lxc_conf->console.log_rotate) < 0) + return -1; + ++ /* ++ * isulad: support rotate muti-files + if (lxc_conf->console.log_rotate > 1) { + ERROR("The \"lxc.console.rotate\" config key can only be set " + "to 0 or 1"); + return -1; + } ++ */ + + return 0; + } +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index 410f643..3bb3a52 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -229,6 +229,39 @@ static int lxc_terminal_truncate_log_file(struct lxc_terminal *terminal) + return lxc_unpriv(ftruncate(terminal->log_fd, 0)); + } + ++/* ++ * isuald: support mult-logfiles ++ * */ ++static int lxc_terminal_rename_old_log_file(struct lxc_terminal *terminal) ++{ ++ int ret; ++ size_t i; ++ char tmp[PATH_MAX] = {0}; ++ char *rename_fname = NULL; ++ ++ for (i = terminal->log_rotate - 1; i > 1; i--) { ++ ret = sprintf(tmp, "%s.%d", terminal->log_path, i); ++ if (ret < 0) ++ return -EFBIG; ++ if (rename_fname) ++ free(rename_fname); ++ rename_fname = strdup(tmp); ++ ret = sprintf(tmp, "%s.%d", terminal->log_path, (i - 1)); ++ if (ret < 0) { ++ free(rename_fname); ++ return -EFBIG; ++ } ++ ret = lxc_unpriv(rename(tmp, rename_fname)); ++ if (ret < 0 && errno != ENOENT) ++ return ret; ++ } ++ ++ if (rename_fname) ++ free(rename_fname); ++ ++ return 0; ++} ++ + static int lxc_terminal_rotate_log_file(struct lxc_terminal *terminal) + { + int ret; +@@ -242,6 +275,13 @@ static int lxc_terminal_rotate_log_file(struct lxc_terminal *terminal) + if (terminal->log_fd < 0) + return -EBADF; + ++ /* isuald: rotate old log file first */ ++ ret = lxc_terminal_rename_old_log_file(terminal); ++ if(ret != 0) { ++ ERROR("Rename old log file failed"); ++ return ret; ++ } ++ + len = strlen(terminal->log_path) + sizeof(".1"); + tmp = alloca(len); + +-- +1.8.3.1 + diff --git a/0015-fix-high-gcc-compile-bug.patch b/0015-fix-high-gcc-compile-bug.patch new file mode 100644 index 0000000..af55a22 --- /dev/null +++ b/0015-fix-high-gcc-compile-bug.patch @@ -0,0 +1,41 @@ +From d4c2a04690f61c6d42c69f53b96cc039e94d5256 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Sat, 12 Jan 2019 16:28:41 +0800 +Subject: [PATCH 015/122] fix high gcc compile bug + +fix high gcc compile bug + +Signed-off-by: LiFeng +--- + src/lxc/terminal.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index 3bb3a52..7aa4730 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -235,18 +235,18 @@ static int lxc_terminal_truncate_log_file(struct lxc_terminal *terminal) + static int lxc_terminal_rename_old_log_file(struct lxc_terminal *terminal) + { + int ret; +- size_t i; ++ unsigned int i; + char tmp[PATH_MAX] = {0}; + char *rename_fname = NULL; + + for (i = terminal->log_rotate - 1; i > 1; i--) { +- ret = sprintf(tmp, "%s.%d", terminal->log_path, i); ++ ret = sprintf(tmp, "%s.%u", terminal->log_path, i); + if (ret < 0) + return -EFBIG; + if (rename_fname) + free(rename_fname); + rename_fname = strdup(tmp); +- ret = sprintf(tmp, "%s.%d", terminal->log_path, (i - 1)); ++ ret = sprintf(tmp, "%s.%u", terminal->log_path, (i - 1)); + if (ret < 0) { + free(rename_fname); + return -EFBIG; +-- +1.8.3.1 + diff --git a/0016-add-masked-paths-and-ro-paths.patch b/0016-add-masked-paths-and-ro-paths.patch new file mode 100644 index 0000000..373a8a0 --- /dev/null +++ b/0016-add-masked-paths-and-ro-paths.patch @@ -0,0 +1,381 @@ +From 478dfb4eadd6812bd63fc0d37cf1acad21a58e6a Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Sat, 12 Jan 2019 15:55:52 +0800 +Subject: [PATCH 016/122] add masked paths and ro paths + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + src/lxc/conf.h | 8 ++++ + src/lxc/confile.c | 113 ++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 255 insertions(+), 1 deletion(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 5065e69..537f956 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -1343,6 +1343,95 @@ static int lxc_mount_rootfs(struct lxc_conf *conf) + return 0; + } + ++ ++// maskPath masks the top of the specified path inside a container to avoid ++// security issues from processes reading information from non-namespace aware ++// mounts ( proc/kcore ). ++static bool mask_path(const char *path) ++{ ++ int ret; ++ ++ if (!path) ++ return true; ++ ++ ret = mount("/dev/null", path, "", MS_BIND, ""); ++ if (ret < 0 && errno != ENOENT) { ++ if (errno == ENOTDIR) { ++ ret = mount("tmpfs", path, "tmpfs", MS_RDONLY, ""); ++ if (ret < 0) ++ goto error; ++ return true; ++ } ++ goto error; ++ } ++ return true; ++ ++error: ++ SYSERROR("Failed to mask path \"%s\": %s", path, strerror(errno)); ++ return false; ++} ++ ++// remount_readonly will bind over the top of an existing path and ensure that it is read-only. ++static bool remount_readonly(const char *path) ++{ ++ int ret, savederrno, i; ++ ++ if (!path) ++ return true; ++ ++ for (i = 0; i < 5; i++) { ++ ret = mount("", path, "", MS_REMOUNT | MS_RDONLY, ""); ++ if (ret < 0 && errno != ENOENT) { ++ if (errno == EINVAL) { ++ // Probably not a mountpoint, use bind-mount ++ ret = mount(path, path, "", MS_BIND, ""); ++ if (ret < 0) ++ goto on_error; ++ ret = mount(path, path, "", MS_BIND | MS_REMOUNT | MS_RDONLY | MS_REC | \ ++ MS_NOEXEC | MS_NOSUID | MS_NODEV, ""); ++ if (ret < 0) ++ goto on_error; ++ } else if (errno == EBUSY) { ++ DEBUG("Try to mount \"%s\" to readonly after 100ms.", path); ++ usleep(100 * 1000); ++ continue; ++ } else { ++ goto on_error; ++ } ++ } ++ return true; ++ } ++ ++on_error: ++ SYSERROR("Unable to mount \"%s\" to readonly", path); ++ return false; ++} ++ ++// isulad: setup rootfs masked paths ++static int setup_rootfs_maskedpaths(struct lxc_list *maskedpaths) ++{ ++ struct lxc_list *it; ++ ++ lxc_list_for_each(it, maskedpaths) { ++ if (!mask_path((char *)it->elem)) ++ return -1; ++ } ++ ++ return 0; ++} ++// isulad: setup rootfs ro paths ++static int setup_rootfs_ropaths(struct lxc_list *ropaths) ++{ ++ struct lxc_list *it; ++ ++ lxc_list_for_each(it, ropaths) { ++ if (!remount_readonly((char *)it->elem)) ++ return -1; ++ } ++ ++ return 0; ++} ++ + int lxc_chroot(const struct lxc_rootfs *rootfs) + { + int i, ret; +@@ -2759,6 +2848,8 @@ struct lxc_conf *lxc_conf_init(void) + + /* isulad add begin */ + lxc_list_init(&new->populate_devs); ++ lxc_list_init(&new->rootfs.maskedpaths); ++ lxc_list_init(&new->rootfs.ropaths); + new->exit_fd = -1; + /* isulad add end */ + +@@ -3759,6 +3850,22 @@ int lxc_setup(struct lxc_handler *handler) + if (ret < 0) + return -1; + ++ //isulad: setup rootfs masked paths ++ if (!lxc_list_empty(&lxc_conf->rootfs.maskedpaths)) { ++ if (setup_rootfs_maskedpaths(&lxc_conf->rootfs.maskedpaths)) { ++ ERROR("failed to setup maskedpaths"); ++ return -1; ++ } ++ } ++ ++ // isulad: setup rootfs ro paths ++ if (!lxc_list_empty(&lxc_conf->rootfs.ropaths)) { ++ if (setup_rootfs_ropaths(&lxc_conf->rootfs.ropaths)) { ++ ERROR("failed to setup readonlypaths"); ++ return -1; ++ } ++ } ++ + ret = setup_personality(lxc_conf->personality); + if (ret < 0) { + ERROR("Failed to set personality"); +@@ -4147,6 +4254,32 @@ int lxc_clear_populate_devices(struct lxc_conf *c) + return 0; + } + ++/*isulad: clear rootfs masked paths*/ ++int lxc_clear_rootfs_masked_paths(struct lxc_conf *c) ++{ ++ struct lxc_list *it,*next; ++ ++ lxc_list_for_each_safe(it, &c->rootfs.maskedpaths, next) { ++ lxc_list_del(it); ++ free(it->elem); ++ free(it); ++ } ++ return 0; ++} ++ ++/*isulad: clear rootfs ro paths*/ ++int lxc_clear_rootfs_ro_paths(struct lxc_conf *c) ++{ ++ struct lxc_list *it,*next; ++ ++ lxc_list_for_each_safe(it, &c->rootfs.ropaths, next) { ++ lxc_list_del(it); ++ free(it->elem); ++ free(it); ++ } ++ return 0; ++} ++ + void lxc_conf_free(struct lxc_conf *conf) + { + if (!conf) +@@ -4195,6 +4328,8 @@ void lxc_conf_free(struct lxc_conf *conf) + /* isulad add begin */ + lxc_clear_init_args(conf); + lxc_clear_populate_devices(conf); ++ lxc_clear_rootfs_masked_paths(conf); ++ lxc_clear_rootfs_ro_paths(conf); + free(conf->container_info_file); + if (conf->exit_fd != -1) + close(conf->exit_fd); +diff --git a/src/lxc/conf.h b/src/lxc/conf.h +index 2d939cd..7927812 100644 +--- a/src/lxc/conf.h ++++ b/src/lxc/conf.h +@@ -160,6 +160,8 @@ struct lxc_tty_info { + * @options : mount options + * @mountflags : the portion of @options that are flags + * @data : the portion of @options that are not flags ++ * @maskedpaths: A list of paths to be msked over inside the container ++ * @ropaths : A list of paths to be remounted with readonly inside the container + */ + struct lxc_rootfs { + char *path; +@@ -168,6 +170,10 @@ struct lxc_rootfs { + char *options; + unsigned long mountflags; + char *data; ++ /* isulad: maskedpaths */ ++ struct lxc_list maskedpaths; ++ /* isulad: ropaths */ ++ struct lxc_list ropaths; + }; + + /* +@@ -477,6 +483,8 @@ extern int lxc_clear_procs(struct lxc_conf *c, const char *key); + /* isulad add begin */ + int lxc_clear_init_args(struct lxc_conf *lxc_conf); + int lxc_clear_populate_devices(struct lxc_conf *c); ++int lxc_clear_rootfs_masked_paths(struct lxc_conf *c); ++int lxc_clear_rootfs_ro_paths(struct lxc_conf *c); + + /* isulad add end */ + +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index e782211..e199965 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -139,6 +139,8 @@ lxc_config_define(pty_max); + lxc_config_define(rootfs_mount); + lxc_config_define(rootfs_options); + lxc_config_define(rootfs_path); ++lxc_config_define(rootfs_masked_paths); ++lxc_config_define(rootfs_ro_paths); + lxc_config_define(seccomp_profile); + lxc_config_define(selinux_context); + lxc_config_define(signal_halt); +@@ -243,6 +245,8 @@ static struct lxc_config_t config_jump_table[] = { + /*isulad add begin*/ + { "lxc.isulad.init.args", set_config_init_args, get_config_init_args, clr_config_init_args, }, + { "lxc.isulad.populate.device", set_config_populate_device, get_config_populate_device, clr_config_populate_device, }, ++ { "lxc.isulad.rootfs.maskedpaths", set_config_rootfs_masked_paths, get_config_rootfs_masked_paths, clr_config_rootfs_masked_paths, }, ++ { "lxc.isulad.rootfs.ropaths", set_config_rootfs_ro_paths, get_config_rootfs_ro_paths, clr_config_rootfs_ro_paths, }, + /*isulad add end*/ + }; + +@@ -2224,7 +2228,7 @@ static int set_config_init_args(const char *key, const char *value, + return 0; + } + +-/* isulad: set config for init args */ ++/* isulad: set config for populate device */ + static int set_config_populate_device(const char *key, const char *value, + struct lxc_conf *lxc_conf, void *data) + { +@@ -2308,6 +2312,62 @@ on_error: + free(dev_elem); + } + return -1; ++} ++ ++/* isulad: set config for rootfs masked paths */ ++static int set_config_rootfs_masked_paths(const char *key, const char *value, ++ struct lxc_conf *lxc_conf, void *data) ++{ ++ struct lxc_list *list_item = NULL; ++ ++ if (lxc_config_value_empty(value)) ++ return lxc_clear_rootfs_masked_paths(lxc_conf); ++ ++ list_item = malloc(sizeof(*list_item)); ++ if (!list_item) ++ goto on_error; ++ ++ list_item->elem = strdup(value); ++ ++ if (!list_item->elem) ++ goto on_error; ++ ++ lxc_list_add_tail(&lxc_conf->rootfs.maskedpaths, list_item); ++ ++ return 0; ++ ++on_error: ++ free(list_item); ++ ++ return -1; ++} ++ ++/* isulad: set config for rootfs ro paths */ ++static int set_config_rootfs_ro_paths(const char *key, const char *value, ++ struct lxc_conf *lxc_conf, void *data) ++{ ++ struct lxc_list *list_item = NULL; ++ ++ if (lxc_config_value_empty(value)) ++ return lxc_clear_rootfs_ro_paths(lxc_conf); ++ ++ list_item = malloc(sizeof(*list_item)); ++ if (!list_item) ++ goto on_error; ++ ++ list_item->elem = strdup(value); ++ ++ if (!list_item->elem) ++ goto on_error; ++ ++ lxc_list_add_tail(&lxc_conf->rootfs.ropaths, list_item); ++ ++ return 0; ++ ++on_error: ++ free(list_item); ++ ++ return -1; + + } + +@@ -3889,6 +3949,43 @@ static int get_config_populate_device(const char *key, char *retv, int inlen, + return fulllen; + } + ++// isulad: get config rootfs masked paths ++static int get_config_rootfs_masked_paths(const char *key, char *retv, int inlen, ++ struct lxc_conf *c, void *data) ++{ ++ int len, fulllen = 0; ++ struct lxc_list *it; ++ ++ if (!retv) ++ inlen = 0; ++ else ++ memset(retv, 0, inlen); ++ ++ lxc_list_for_each(it, &c->rootfs.maskedpaths) { ++ strprint(retv, inlen, "%s\n", (char *)it->elem); ++ } ++ ++ return fulllen; ++} ++ ++// isulad: get config rootfs ro paths ++static int get_config_rootfs_ro_paths(const char *key, char *retv, int inlen, ++ struct lxc_conf *c, void *data) ++{ ++ int len, fulllen = 0; ++ struct lxc_list *it; ++ ++ if (!retv) ++ inlen = 0; ++ else ++ memset(retv, 0, inlen); ++ ++ lxc_list_for_each(it, &c->rootfs.ropaths) { ++ strprint(retv, inlen, "%s\n", (char *)it->elem); ++ } ++ ++ return fulllen; ++} + + /* Callbacks to clear config items. */ + static inline int clr_config_personality(const char *key, struct lxc_conf *c, +@@ -4708,6 +4805,20 @@ static inline int clr_config_populate_device(const char *key, struct lxc_conf *c + return lxc_clear_populate_devices(c); + } + ++/* isulad: clr config rootfs masked paths */ ++static inline int clr_config_rootfs_masked_paths(const char *key, struct lxc_conf *c, ++ void *data) ++{ ++ return lxc_clear_rootfs_masked_paths(c); ++} ++ ++/* isulad: clr config rootfs ro paths */ ++static inline int clr_config_rootfs_ro_paths(const char *key, struct lxc_conf *c, ++ void *data) ++{ ++ return lxc_clear_rootfs_ro_paths(c); ++} ++ + static int get_config_net_nic(const char *key, char *retv, int inlen, + struct lxc_conf *c, void *data) + { +-- +1.8.3.1 + diff --git a/0017-isulad-check-cgroup-cpu.shares-after-setted.patch b/0017-isulad-check-cgroup-cpu.shares-after-setted.patch new file mode 100644 index 0000000..46330e8 --- /dev/null +++ b/0017-isulad-check-cgroup-cpu.shares-after-setted.patch @@ -0,0 +1,99 @@ +From b4cf90f64f23198555372e4d1ca1a1a7ea0ee81f Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Mon, 14 Jan 2019 11:03:03 +0800 +Subject: [PATCH 017/122] isulad: check cgroup cpu.shares after setted + +Signed-off-by: LiFeng +--- + src/lxc/cgroups/cgfsng.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 61 insertions(+) + +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index 3e702b3..ab5732b 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -2204,6 +2204,42 @@ static int cg_legacy_set_data(struct cgroup_ops *ops, const char *filename, + return ret; + } + ++/* Called from setup_limits - here we have the container's cgroup_data because ++ * we created the cgroups. ++ */ ++static int cg_legacy_get_data(struct cgroup_ops *ops, const char *filename, ++ char *value, size_t len) ++{ ++ char *fullpath, *p; ++ struct hierarchy *h; ++ int ret = 0; ++ char *controller = NULL; ++ ++ len = strlen(filename); ++ controller = alloca(len + 1); ++ (void)strlcpy(controller, filename, len + 1); ++ ++ p = strchr(controller, '.'); ++ if (p) ++ *p = '\0'; ++ ++ ++ h = get_hierarchy(ops, controller); ++ if (!h) { ++ ERROR("Failed to setup limits for the \"%s\" controller. " ++ "The controller seems to be unused by \"cgfsng\" cgroup " ++ "driver or not enabled on the cgroup hierarchy", ++ controller); ++ errno = ENOENT; ++ return -ENOENT; ++ } ++ ++ fullpath = must_make_path(h->container_full_path, filename, NULL); ++ ret = lxc_read_from_file(fullpath, value, len); ++ free(fullpath); ++ return ret; ++} ++ + static bool __cg_legacy_setup_limits(struct cgroup_ops *ops, + struct lxc_list *cgroup_settings, + bool do_devices) +@@ -2211,6 +2247,8 @@ static bool __cg_legacy_setup_limits(struct cgroup_ops *ops, + struct lxc_list *iterator, *next, *sorted_cgroup_settings; + struct lxc_cgroup *cg; + bool ret = false; ++ char value[21]; ++ long long int readvalue, setvalue; + + if (lxc_list_empty(cgroup_settings)) + return true; +@@ -2236,6 +2274,29 @@ static bool __cg_legacy_setup_limits(struct cgroup_ops *ops, + DEBUG("Set controller \"%s\" set to \"%s\"", + cg->subsystem, cg->value); + } ++ // isulad: check cpu shares ++ if (strcmp(cg->subsystem, "cpu.shares") == 0) { ++ if (cg_legacy_get_data(ops, cg->subsystem, value, sizeof(value)) < 0) { ++ SYSERROR("Error get %s", cg->subsystem); ++ goto out; ++ } ++ trim(value); ++ if (lxc_safe_long_long(cg->value, &setvalue) != 0) { ++ SYSERROR("Invalid value %s", cg->value); ++ goto out; ++ } ++ if (lxc_safe_long_long(value, &readvalue) != 0) { ++ SYSERROR("Invalid value %s", value); ++ goto out; ++ } ++ if (setvalue > readvalue) { ++ ERROR("The maximum allowed cpu-shares is %s", value); ++ goto out; ++ } else if (setvalue < readvalue) { ++ ERROR("The minimum allowed cpu-shares is %s", value); ++ goto out; ++ } ++ } + } + + ret = true; +-- +1.8.3.1 + diff --git a/0018-lxc-attach-add-support-terminal-fifos.patch b/0018-lxc-attach-add-support-terminal-fifos.patch new file mode 100644 index 0000000..a6f8b6e --- /dev/null +++ b/0018-lxc-attach-add-support-terminal-fifos.patch @@ -0,0 +1,410 @@ +From d6a38c35cb5986f1263e3dd1b6206217e34a2ec8 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Mon, 14 Jan 2019 02:18:26 -0500 +Subject: [PATCH 018/122] lxc-attach: add support terminal fifos + +1. support terminal fifos to redirect terminal +2. support lxc-attach run in background + +Signed-off-by: LiFeng +--- + src/lxc/attach.c | 18 ++++- + src/lxc/attach_options.h | 3 + + src/lxc/terminal.c | 27 +++++-- + src/lxc/tools/arguments.h | 2 +- + src/lxc/tools/lxc_attach.c | 181 +++++++++++++++++++++++++++++++++++++++++---- + 5 files changed, 204 insertions(+), 27 deletions(-) + +diff --git a/src/lxc/attach.c b/src/lxc/attach.c +index 2bbf1eb..1886bde 100644 +--- a/src/lxc/attach.c ++++ b/src/lxc/attach.c +@@ -988,12 +988,23 @@ on_error: + } + + static int lxc_attach_terminal(struct lxc_conf *conf, +- struct lxc_terminal *terminal) ++ struct lxc_terminal *terminal, lxc_attach_options_t *options) + { + int ret; + + lxc_terminal_init(terminal); + ++ /* isulad: if we pass fifo in option, use them as init fifos */ ++ if (options->init_fifo[0] && options->init_fifo[1]) { ++ if (terminal->init_fifo[0]) ++ free(terminal->init_fifo[0]); ++ terminal->init_fifo[0] = strdup(options->init_fifo[0]); ++ ++ if (terminal->init_fifo[1]) ++ free(terminal->init_fifo[1]); ++ terminal->init_fifo[1] = strdup(options->init_fifo[1]); ++ } ++ + ret = lxc_terminal_create(terminal); + if (ret < 0) { + ERROR("Failed to create terminal"); +@@ -1203,7 +1214,7 @@ int lxc_attach(const char *name, const char *lxcpath, + } + + if (options->attach_flags & LXC_ATTACH_TERMINAL) { +- ret = lxc_attach_terminal(conf, &terminal); ++ ret = lxc_attach_terminal(conf, &terminal, options); + if (ret < 0) { + ERROR("Failed to setup new terminal"); + free(cwd); +@@ -1489,7 +1500,7 @@ int lxc_attach(const char *name, const char *lxcpath, + } + + if (pid == 0) { +- if (options->attach_flags & LXC_ATTACH_TERMINAL) { ++ if (options->attach_flags & LXC_ATTACH_TERMINAL && terminal.tty_state) { + ret = pthread_sigmask(SIG_SETMASK, + &terminal.tty_state->oldmask, NULL); + if (ret < 0) { +@@ -1497,7 +1508,6 @@ int lxc_attach(const char *name, const char *lxcpath, + _exit(EXIT_FAILURE); + } + } +- + ret = attach_child_main(&payload); + if (ret < 0) + ERROR("Failed to exec"); +diff --git a/src/lxc/attach_options.h b/src/lxc/attach_options.h +index 193fd7e..081618c 100644 +--- a/src/lxc/attach_options.h ++++ b/src/lxc/attach_options.h +@@ -135,6 +135,8 @@ typedef struct lxc_attach_options_t { + + /*! File descriptor to log output. */ + int log_fd; ++ ++ char *init_fifo[2]; /* isulad: default fifos for the start */ + } lxc_attach_options_t; + + /*! Default attach options to use */ +@@ -153,6 +155,7 @@ typedef struct lxc_attach_options_t { + /* .stdout_fd = */ 1, \ + /* .stderr_fd = */ 2, \ + /* .log_fd = */ -EBADF, \ ++ /* .init_fifo = */ {NULL, NULL}, \ + } + + /*! +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index 7aa4730..ee3aef2 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -514,7 +514,7 @@ static int lxc_terminal_mainloop_add_peer(struct lxc_terminal *terminal) + } + + /* isulad add fifo to mainloop */ +-static int lxc_console_mainloop_add_fifo(struct lxc_terminal *terminal) ++static int lxc_terminal_mainloop_add_fifo(struct lxc_terminal *terminal) + { + int ret = 0; + struct lxc_list *it,*next; +@@ -564,7 +564,7 @@ int lxc_terminal_mainloop_add(struct lxc_epoll_descr *descr, + } + + /* isulad add fifo to mainloop */ +- ret = lxc_console_mainloop_add_fifo(terminal); ++ ret = lxc_terminal_mainloop_add_fifo(terminal); + if (ret < 0) { + ERROR("Failed to add handler for terminal fifos to mainloop"); + return -1; +@@ -789,13 +789,28 @@ void lxc_terminal_free(struct lxc_conf *conf, int fd) + static int lxc_terminal_peer_default(struct lxc_terminal *terminal) + { + struct lxc_terminal_state *ts; +- const char *path; ++ const char *path = NULL; + int ret = 0; + + if (terminal->path) + path = terminal->path; +- else +- path = "/dev/tty"; ++ ++ /* isulad: if no console was given, try current controlling terminal, there ++ * won't be one if we were started as a daemon (-d) ++ */ ++ if (!path && !access("/dev/tty", F_OK)) { ++ int fd; ++ fd = open("/dev/tty", O_RDWR); ++ if (fd >= 0) { ++ close(fd); ++ path = "/dev/tty"; ++ } ++ } ++ ++ if (!path) { ++ DEBUG("Not have a controlling terminal"); ++ return 0; ++ } + + terminal->peer = lxc_unpriv(open(path, O_RDWR | O_CLOEXEC)); + if (terminal->peer < 0) { +@@ -1355,7 +1370,7 @@ int lxc_terminal_prepare_login(int fd) + if (ret < 0) + return -1; + +- ret = lxc_terminal_set_stdfds(fd); ++ ret = set_stdfds(fd); + if (ret < 0) + return -1; + +diff --git a/src/lxc/tools/arguments.h b/src/lxc/tools/arguments.h +index 61f4a0a..047e9f1 100644 +--- a/src/lxc/tools/arguments.h ++++ b/src/lxc/tools/arguments.h +@@ -62,7 +62,7 @@ struct lxc_arguments { + + /* for lxc-start */ + const char *share_ns[32]; /* size must be greater than LXC_NS_MAX */ +- const char *terminal_fifos[2]; /* isulad add, fifos used to redirct stdin/out/err */ ++ char *terminal_fifos[2]; /* isulad add, fifos used to redirct stdin/out/err */ + const char *container_info; /* isulad: file used to store pid and ppid info of container */ + const char *exit_monitor_fifo; /* isulad: fifo used to monitor state of monitor process */ + +diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c +index 8c8e7d3..6d0ffe5 100644 +--- a/src/lxc/tools/lxc_attach.c ++++ b/src/lxc/tools/lxc_attach.c +@@ -75,6 +75,8 @@ static const struct option my_longopts[] = { + {"set-var", required_argument, 0, 'v'}, + {"pty-log", required_argument, 0, 'L'}, + {"rcfile", required_argument, 0, 'f'}, ++ {"in-fifo", required_argument, 0, OPT_INPUT_FIFO}, /* isulad add terminal fifos*/ ++ {"out-fifo", required_argument, 0, OPT_OUTPUT_FIFO}, + LXC_COMMON_OPTIONS + }; + +@@ -133,6 +135,9 @@ Options :\n\ + .log_file = "none", + }; + ++// isulad: send '128 + signal' if container is killed by signal. ++#define ExitSignalOffset 128 ++ + static int my_parser(struct lxc_arguments *args, int c, char *arg) + { + int ret; +@@ -190,6 +195,12 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) + case 'f': + args->rcfile = arg; + break; ++ case OPT_INPUT_FIFO: ++ args->terminal_fifos[0] = arg; ++ break; ++ case OPT_OUTPUT_FIFO: ++ args->terminal_fifos[1] = arg; ++ break; + } + + return 0; +@@ -253,10 +264,143 @@ static int lxc_attach_create_log_file(const char *log_file) + return fd; + } + ++/*isulad: attach with terminal*/ ++static int do_attach_foreground(struct lxc_container *c, lxc_attach_command_t *command, ++ lxc_attach_options_t *attach_options, ++ char **errmsg) ++{ ++ int ret = 0; ++ pid_t pid; ++ int wexit = -1; ++ int signal; ++ ++ if (command->program) ++ ret = c->attach(c, lxc_attach_run_command, command, attach_options, &pid); ++ else ++ ret = c->attach(c, lxc_attach_run_shell, NULL, attach_options, &pid); ++ if (ret < 0) ++ goto out; ++ ++ ret = lxc_wait_for_pid_status(pid); ++ if (ret < 0) ++ goto out; ++ ++ if (WIFEXITED(ret)) ++ wexit = WEXITSTATUS(ret); ++ else ++ wexit = -1; ++ ++ if (WIFSIGNALED(ret)) { ++ signal = WTERMSIG(ret); ++ wexit = ExitSignalOffset + signal; ++ } ++out: ++ //if (c->lxc_conf->errmsg) ++ // *errmsg = strdup(c->lxc_conf->errmsg); ++ return wexit; ++} ++ ++static void close_msg_pipe(int *errpipe) ++{ ++ if (errpipe[0] >= 0) { ++ close(errpipe[0]); ++ errpipe[0] = -1; ++ } ++ if (errpipe[1] >= 0) { ++ close(errpipe[1]); ++ errpipe[1] = -1; ++ } ++} ++ ++/*isulad: attach without terminal in background */ ++static int do_attach_background(struct lxc_container *c, lxc_attach_command_t *command, ++ lxc_attach_options_t *attach_options, ++ char **errmsg) ++{ ++ int ret = 0; ++ int msgpipe[2]; ++ pid_t pid = 0; ++ ssize_t size_read; ++ char msgbuf[BUFSIZ + 1] = {0}; ++ ++ //pipdfd for get error message of child or grandchild process. ++ if (pipe2(msgpipe, O_CLOEXEC) != 0) { ++ SYSERROR("Failed to init msgpipe"); ++ return -1; ++ } ++ ++ pid = fork(); ++ if (pid < 0) { ++ close_msg_pipe(msgpipe); ++ return -1; ++ } ++ ++ if (pid != 0) { ++ close(msgpipe[1]); ++ msgpipe[1] = -1; ++ size_read = read(msgpipe[0], msgbuf, BUFSIZ); ++ if (size_read > 0) { ++ *errmsg = strdup(msgbuf); ++ ret = -1; ++ } ++ ++ close(msgpipe[0]); ++ msgpipe[0] = -1; ++ ++ return ret; ++ } ++ ++ /* second fork to be reparented by init */ ++ pid = fork(); ++ if (pid < 0) { ++ SYSERROR("Error doing dual-fork"); ++ close_msg_pipe(msgpipe); ++ exit(1); ++ } ++ if (pid != 0) { ++ close_msg_pipe(msgpipe); ++ exit(0); ++ } ++ ++ close(msgpipe[0]); ++ msgpipe[0] = -1; ++ ++ if (null_stdfds() < 0) { ++ ERROR("failed to close fds"); ++ exit(1); ++ } ++ setsid(); ++ ++ if (command->program) ++ ret = c->attach(c, lxc_attach_run_command, command, attach_options, &pid); ++ else ++ ret = c->attach(c, lxc_attach_run_shell, NULL, attach_options, &pid); ++ if (ret < 0) { ++ //if (c->lxc_conf->errmsg) ++ // lxc_write_error_message(msgpipe[1], "%s", c->lxc_conf->errmsg); ++ close(msgpipe[1]); ++ msgpipe[1] = -1; ++ ret = -1; ++ goto out; ++ } ++ ++ close(msgpipe[1]); ++ msgpipe[1] = -1; ++ ++ ret = wait_for_pid(pid); ++out: ++ lxc_container_put(c); ++ if (ret) ++ exit(EXIT_FAILURE); ++ else ++ exit(0); ++} ++ + int main(int argc, char *argv[]) + { + int ret = -1; + int wexit = 0; ++ char *errmsg = NULL; + struct lxc_log log; + pid_t pid; + lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT; +@@ -316,8 +460,13 @@ int main(int argc, char *argv[]) + if (elevated_privileges) + attach_options.attach_flags &= ~(elevated_privileges); + +- if (stdfd_is_pty()) ++ if (my_args.terminal_fifos[0] && my_args.terminal_fifos[1]) { ++ attach_options.init_fifo[0] = my_args.terminal_fifos[0]; ++ attach_options.init_fifo[1] = my_args.terminal_fifos[1]; ++ attach_options.attach_flags |= LXC_ATTACH_TERMINAL; ++ } else if (stdfd_is_pty()) { + attach_options.attach_flags |= LXC_ATTACH_TERMINAL; ++ } + + attach_options.namespaces = namespace_flags; + attach_options.personality = new_personality; +@@ -332,27 +481,27 @@ int main(int argc, char *argv[]) + + if (my_args.console_log) { + attach_options.log_fd = lxc_attach_create_log_file(my_args.console_log); +- if (attach_options.log_fd < 0) +- goto out; ++ if (attach_options.log_fd < 0) { ++ ERROR("Failed to create log file for %s", c->name); ++ lxc_container_put(c); ++ exit(EXIT_FAILURE); ++ } + } + +- if (command.program) +- ret = c->attach(c, lxc_attach_run_command, &command, &attach_options, &pid); ++ /* isulad: add do attach background */ ++ if (attach_options.attach_flags & LXC_ATTACH_TERMINAL) ++ wexit = do_attach_foreground(c, &command, &attach_options, &errmsg); + else +- ret = c->attach(c, lxc_attach_run_shell, NULL, &attach_options, &pid); +- if (ret < 0) +- goto out; ++ wexit = do_attach_background(c, &command, &attach_options, &errmsg); + +- ret = lxc_wait_for_pid_status(pid); +- if (ret < 0) +- goto out; +- +- if (WIFEXITED(ret)) +- wexit = WEXITSTATUS(ret); ++ if (errmsg) { ++ fprintf(stderr, "%s:%s:%s:%d starting container process caused \"%s\"", c->name, ++ __FILE__, __func__, __LINE__, errmsg); ++ free(errmsg); ++ } + +-out: + lxc_container_put(c); +- if (ret >= 0) ++ if (wexit >= 0) + exit(wexit); + + exit(EXIT_FAILURE); +-- +1.8.3.1 + diff --git a/0019-remount-cgroup-readonly-and-make-soft-link-of-subcgr.patch b/0019-remount-cgroup-readonly-and-make-soft-link-of-subcgr.patch new file mode 100644 index 0000000..055fd2f --- /dev/null +++ b/0019-remount-cgroup-readonly-and-make-soft-link-of-subcgr.patch @@ -0,0 +1,87 @@ +From bd056022ef54a8dc6a859495f0edde96471bd7e5 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Mon, 14 Jan 2019 13:51:01 +0800 +Subject: [PATCH 019/122] remount cgroup readonly and make soft link of + subcgroup + +Signed-off-by: LiFeng +--- + src/lxc/cgroups/cgfsng.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index ab5732b..705985f 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -1621,6 +1621,7 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, + int i, ret; + char *tmpfspath = NULL; + bool has_cgns = false, retval = false, wants_force_mount = false; ++ char **merged = NULL; + + if ((type & LXC_AUTO_CGROUP_MASK) == 0) + return true; +@@ -1667,6 +1668,14 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, + continue; + controller++; + ++ // isulad: symlink subcgroup ++ if (strchr(controller, ',') != NULL) { ++ int pret; ++ pret = lxc_append_string(&merged, controller); ++ if (pret < 0) ++ goto on_error; ++ } ++ + controllerpath = must_make_path(tmpfspath, controller, NULL); + if (dir_exists(controllerpath)) { + free(controllerpath); +@@ -1721,10 +1730,45 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, + if (ret < 0) + goto on_error; + } ++ ++ // isulad: symlink subcgroup ++ if (merged) { ++ char **mc; ++ for (mc = merged; *mc; mc++) { ++ char *token; ++ char *merge = must_copy_string(*mc); ++ lxc_iterate_parts(token, merge, ",") { ++ int mret; ++ char *link; ++ link = must_make_path(tmpfspath, token, NULL); ++ mret = symlink(*mc, link); ++ if (mret < 0 && errno != EEXIST) { ++ SYSERROR("Failed to create link %s for target %s", link, merge); ++ free(merge); ++ free(link); ++ goto on_error; ++ } ++ free(link); ++ } ++ free(merge); ++ } ++ } ++ ++ ++ // isulad: remount /sys/fs/cgroup to readonly ++ if (type == LXC_AUTO_CGROUP_FULL_RO || type == LXC_AUTO_CGROUP_RO) { ++ ret = mount(tmpfspath, tmpfspath, "bind", ++ MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_RELATIME|MS_RDONLY|MS_BIND|MS_REMOUNT, NULL); ++ if (ret < 0) { ++ SYSERROR("Failed to remount /sys/fs/cgroup."); ++ goto on_error; ++ } ++ } + retval = true; + + on_error: + free(tmpfspath); ++ lxc_free_array((void **)merged, free); + return retval; + } + +-- +1.8.3.1 + diff --git a/0020-fix-log-error-when-symlink-subcgroup.patch b/0020-fix-log-error-when-symlink-subcgroup.patch new file mode 100644 index 0000000..ce875dc --- /dev/null +++ b/0020-fix-log-error-when-symlink-subcgroup.patch @@ -0,0 +1,44 @@ +From ab9da60c84c2b37049e514d7a597fc8747dbc52f Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Mon, 14 Jan 2019 15:33:12 +0800 +Subject: [PATCH 020/122] fix log error when symlink subcgroup + +Signed-off-by: LiFeng +--- + src/lxc/cgroups/cgfsng.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index 705985f..7f2a200 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -1736,21 +1736,21 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, + char **mc; + for (mc = merged; *mc; mc++) { + char *token; +- char *merge = must_copy_string(*mc); +- lxc_iterate_parts(token, merge, ",") { ++ char *copy = must_copy_string(*mc); ++ lxc_iterate_parts(token, copy, ",") { + int mret; + char *link; + link = must_make_path(tmpfspath, token, NULL); + mret = symlink(*mc, link); + if (mret < 0 && errno != EEXIST) { +- SYSERROR("Failed to create link %s for target %s", link, merge); +- free(merge); ++ SYSERROR("Failed to create link %s for target %s", link, *mc); ++ free(copy); + free(link); + goto on_error; + } + free(link); + } +- free(merge); ++ free(copy); + } + } + +-- +1.8.3.1 + diff --git a/0021-lxc-attch-add-error-message.patch b/0021-lxc-attch-add-error-message.patch new file mode 100644 index 0000000..f0d7687 --- /dev/null +++ b/0021-lxc-attch-add-error-message.patch @@ -0,0 +1,374 @@ +From 54f592ec7a2a79b7e5ecdec5b9bf484536e90438 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Mon, 14 Jan 2019 04:29:40 -0500 +Subject: [PATCH 021/122] lxc-attch: add error message + +Signed-off-by: LiFeng +--- + src/lxc/attach.c | 49 +++++++++++++++++++++++++++++++++++++++++----- + src/lxc/attach.h | 4 ++-- + src/lxc/attach_options.h | 6 +++--- + src/lxc/conf.c | 27 +++++++++++++++++++++---- + src/lxc/conf.h | 3 +++ + src/lxc/lxccontainer.c | 4 ++-- + src/lxc/tools/lxc_attach.c | 8 ++++---- + src/lxc/tools/lxc_ls.c | 4 ++-- + src/lxc/utils.c | 21 ++++++++++++++++++++ + src/lxc/utils.h | 1 + + 10 files changed, 105 insertions(+), 22 deletions(-) + +diff --git a/src/lxc/attach.c b/src/lxc/attach.c +index 1886bde..570b9d0 100644 +--- a/src/lxc/attach.c ++++ b/src/lxc/attach.c +@@ -757,10 +757,15 @@ static int attach_child_main(struct attach_clone_payload *payload) + gid_t ns_root_gid = 0; + lxc_attach_options_t* options = payload->options; + struct lxc_proc_context_info* init_ctx = payload->init_ctx; ++ int msg_fd = -1; + bool needs_lsm = (options->namespaces & CLONE_NEWNS) && + (options->attach_flags & LXC_ATTACH_LSM) && + init_ctx->lsm_label; + ++ /*isulad: record errpipe fd*/ ++ msg_fd = init_ctx->container->lxc_conf->errpipe[1]; ++ init_ctx->container->lxc_conf->errpipe[1] = -1; ++ + /* A description of the purpose of this functionality is provided in the + * lxc-attach(1) manual page. We have to remount here and not in the + * parent process, otherwise /proc may not properly reflect the new pid +@@ -980,7 +985,7 @@ static int attach_child_main(struct attach_clone_payload *payload) + goto on_error; + + /* We're done, so we can now do whatever the user intended us to do. */ +- _exit(payload->exec_function(payload->exec_payload)); ++ _exit(payload->exec_function(payload->exec_payload, msg_fd)); + + on_error: + lxc_put_attach_clone_payload(payload); +@@ -1085,7 +1090,7 @@ static inline void lxc_attach_terminal_close_log(struct lxc_terminal *terminal) + + int lxc_attach(const char *name, const char *lxcpath, + lxc_attach_exec_t exec_function, void *exec_payload, +- lxc_attach_options_t *options, pid_t *attached_process) ++ lxc_attach_options_t *options, pid_t *attached_process, char **err_msg) + { + int i, ret, status; + int ipc_sockets[2]; +@@ -1268,6 +1273,15 @@ int lxc_attach(const char *name, const char *lxcpath, + return -1; + } + ++ ++ /* isulad: pipdfd for get error message of child or grandchild process. */ ++ if (pipe2(conf->errpipe, O_CLOEXEC) != 0) { ++ SYSERROR("Failed to init errpipe"); ++ free(cwd); ++ lxc_proc_put_context_info(init_ctx); ++ return -1; ++ } ++ + /* Create intermediate subprocess, two reasons: + * 1. We can't setns() in the child itself, since we want to make + * sure we are properly attached to the pidns. +@@ -1291,6 +1305,11 @@ int lxc_attach(const char *name, const char *lxcpath, + /* close unneeded file descriptors */ + close(ipc_sockets[1]); + free(cwd); ++ ++ /* isulad: close errpipe */ ++ close(conf->errpipe[1]); ++ conf->errpipe[1] = -1; ++ + lxc_proc_close_ns_fd(init_ctx); + if (options->attach_flags & LXC_ATTACH_TERMINAL) + lxc_attach_terminal_close_slave(&terminal); +@@ -1399,6 +1418,19 @@ int lxc_attach(const char *name, const char *lxcpath, + + *attached_process = attached_pid; + ++ /* isulad: read error msg from pipe */ ++ ssize_t size_read; ++ char errbuf[BUFSIZ + 1] = {0}; ++ ++ size_read = read(conf->errpipe[0], errbuf, BUFSIZ); ++ if (size_read > 0) { ++ if (err_msg) ++ *err_msg = strdup(errbuf); ++ if (!(*err_msg)) ++ ERROR("Out of memory"); ++ goto close_mainloop; ++ } ++ + /* Now shut down communication with child, we're done. */ + shutdown(ipc_sockets[0], SHUT_RDWR); + close(ipc_sockets[0]); +@@ -1439,7 +1471,11 @@ int lxc_attach(const char *name, const char *lxcpath, + + /* close unneeded file descriptors */ + close(ipc_sockets[0]); +- ipc_sockets[0] = -EBADF; ++ ipc_sockets[0] = -EBADF;\ ++ ++ /* isulad: close errpipe */ ++ close(conf->errpipe[0]); ++ conf->errpipe[0] = -1; + + if (options->attach_flags & LXC_ATTACH_TERMINAL) { + lxc_attach_terminal_close_master(&terminal); +@@ -1539,7 +1575,7 @@ int lxc_attach(const char *name, const char *lxcpath, + _exit(0); + } + +-int lxc_attach_run_command(void *payload) ++int lxc_attach_run_command(void *payload, int msg_fd) + { + int ret = -1; + lxc_attach_command_t *cmd = payload; +@@ -1556,11 +1592,14 @@ int lxc_attach_run_command(void *payload) + } + } + ++ /* isulad: write errorm messages */ ++ lxc_write_error_message(msg_fd, "exec: \"%s\": %s", cmd->program, strerror(errno)); ++ + SYSERROR("Failed to exec \"%s\"", cmd->program); + return ret; + } + +-int lxc_attach_run_shell(void* payload) ++int lxc_attach_run_shell(void* payload, int msg_fd) + { + uid_t uid; + struct passwd pwent; +diff --git a/src/lxc/attach.h b/src/lxc/attach.h +index 4bf9578..e62b98b 100644 +--- a/src/lxc/attach.h ++++ b/src/lxc/attach.h +@@ -42,7 +42,7 @@ struct lxc_proc_context_info { + }; + + extern int lxc_attach(const char *name, const char *lxcpath, +- lxc_attach_exec_t exec_function, void *exec_payload, +- lxc_attach_options_t *options, pid_t *attached_process); ++ lxc_attach_exec_t exec_function, void *exec_payload, ++ lxc_attach_options_t *options, pid_t *attached_process, char **err_msg); + + #endif /* __LXC_ATTACH_H */ +diff --git a/src/lxc/attach_options.h b/src/lxc/attach_options.h +index 081618c..7b0a8cb 100644 +--- a/src/lxc/attach_options.h ++++ b/src/lxc/attach_options.h +@@ -71,7 +71,7 @@ enum { + * + * \return Function should return \c 0 on success, and any other value to denote failure. + */ +-typedef int (*lxc_attach_exec_t)(void* payload); ++typedef int (*lxc_attach_exec_t)(void* payload, int msg_fd); + + /*! + * LXC attach options for \ref lxc_container \c attach(). +@@ -173,7 +173,7 @@ typedef struct lxc_attach_command_t { + * + * \return \c -1 on error, exit code of lxc_attach_command_t program on success. + */ +-extern int lxc_attach_run_command(void* payload); ++extern int lxc_attach_run_command(void* payload, int msg_fd); + + /*! + * \brief Run a shell command in the container. +@@ -182,7 +182,7 @@ extern int lxc_attach_run_command(void* payload); + * + * \return Exit code of shell. + */ +-extern int lxc_attach_run_shell(void* payload); ++extern int lxc_attach_run_shell(void* payload, int msg_fd); + + #ifdef __cplusplus + } +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 537f956..8d8230f 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -2803,10 +2803,6 @@ struct lxc_conf *lxc_conf_init(void) + new->console.slave = -1; + new->console.name[0] = '\0'; + memset(&new->console.ringbuf, 0, sizeof(struct lxc_ringbuf)); +- /* isulad init console fifos */ +- new->console.init_fifo[0] = NULL; +- new->console.init_fifo[1] = NULL; +- lxc_list_init(&new->console.fifos); + new->maincmd_fd = -1; + new->nbd_idx = -1; + new->rootfs.mount = strdup(default_rootfs_mount); +@@ -2851,6 +2847,14 @@ struct lxc_conf *lxc_conf_init(void) + lxc_list_init(&new->rootfs.maskedpaths); + lxc_list_init(&new->rootfs.ropaths); + new->exit_fd = -1; ++ /* isulad init console fifos */ ++ new->console.init_fifo[0] = NULL; ++ new->console.init_fifo[1] = NULL; ++ lxc_list_init(&new->console.fifos); ++ ++ new->errmsg = NULL; ++ new->errpipe[0] = -1; ++ new->errpipe[1] = -1; + /* isulad add end */ + + return new; +@@ -4280,6 +4284,19 @@ int lxc_clear_rootfs_ro_paths(struct lxc_conf *c) + return 0; + } + ++/*isulad: close error pipe */ ++void lxc_close_error_pipe(int *errpipe) ++{ ++ if (errpipe[0] >= 0) { ++ close(errpipe[0]); ++ errpipe[0] = -1; ++ } ++ if (errpipe[1] >= 0) { ++ close(errpipe[1]); ++ errpipe[1] = -1; ++ } ++} ++ + void lxc_conf_free(struct lxc_conf *conf) + { + if (!conf) +@@ -4333,6 +4350,8 @@ void lxc_conf_free(struct lxc_conf *conf) + free(conf->container_info_file); + if (conf->exit_fd != -1) + close(conf->exit_fd); ++ free(conf->errmsg); ++ lxc_close_error_pipe(conf->errpipe); + /* isulad add end */ + free(conf); + } +diff --git a/src/lxc/conf.h b/src/lxc/conf.h +index 7927812..db474e1 100644 +--- a/src/lxc/conf.h ++++ b/src/lxc/conf.h +@@ -413,6 +413,9 @@ struct lxc_conf { + char *container_info_file; + + int exit_fd; /* exit fifo fd*/ ++ ++ char *errmsg; /* record error messages */ ++ int errpipe[2];//pipdfd for get error message of child or grandchild process. + /* isulad add end */ + }; + +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index 8029f33..31f4819 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -4063,7 +4063,7 @@ static int lxcapi_attach(struct lxc_container *c, lxc_attach_exec_t exec_functio + + current_config = c->lxc_conf; + +- ret = lxc_attach(c->name, c->config_path, exec_function, exec_payload, options, attached_process); ++ ret = lxc_attach(c->name, c->config_path, exec_function, exec_payload, options, attached_process, &c->lxc_conf->errmsg); + current_config = NULL; + return ret; + } +@@ -4080,7 +4080,7 @@ static int do_lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options + command.program = (char*)program; + command.argv = (char**)argv; + +- r = lxc_attach(c->name, c->config_path, lxc_attach_run_command, &command, options, &pid); ++ r = lxc_attach(c->name, c->config_path, lxc_attach_run_command, &command, options, &pid, NULL); + if (r < 0) { + ERROR("ups"); + return r; +diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c +index 6d0ffe5..a590fd1 100644 +--- a/src/lxc/tools/lxc_attach.c ++++ b/src/lxc/tools/lxc_attach.c +@@ -295,8 +295,8 @@ static int do_attach_foreground(struct lxc_container *c, lxc_attach_command_t *c + wexit = ExitSignalOffset + signal; + } + out: +- //if (c->lxc_conf->errmsg) +- // *errmsg = strdup(c->lxc_conf->errmsg); ++ if (c->lxc_conf->errmsg) ++ *errmsg = strdup(c->lxc_conf->errmsg); + return wexit; + } + +@@ -376,8 +376,8 @@ static int do_attach_background(struct lxc_container *c, lxc_attach_command_t *c + else + ret = c->attach(c, lxc_attach_run_shell, NULL, attach_options, &pid); + if (ret < 0) { +- //if (c->lxc_conf->errmsg) +- // lxc_write_error_message(msgpipe[1], "%s", c->lxc_conf->errmsg); ++ if (c->lxc_conf->errmsg) ++ lxc_write_error_message(msgpipe[1], "%s", c->lxc_conf->errmsg); + close(msgpipe[1]); + msgpipe[1] = -1; + ret = -1; +diff --git a/src/lxc/tools/lxc_ls.c b/src/lxc/tools/lxc_ls.c +index cb3eb1e..e261c7b 100644 +--- a/src/lxc/tools/lxc_ls.c ++++ b/src/lxc/tools/lxc_ls.c +@@ -122,7 +122,7 @@ struct wrapargs { + /* + * Takes struct wrapargs as argument. + */ +-static int ls_get_wrapper(void *wrap); ++static int ls_get_wrapper(void *wrap, int msgfd); + + /* + * To calculate swap usage we should not simply check memory.usage_in_bytes and +@@ -1023,7 +1023,7 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) + return 0; + } + +-static int ls_get_wrapper(void *wrap) ++static int ls_get_wrapper(void *wrap, int msgfd) + { + int ret = -1; + size_t len = 0; +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index 74e74a1..8ec9f46 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -1971,3 +1971,24 @@ out: + return startat; + } + ++/* isulad: write error message */ ++void lxc_write_error_message(int errfd, const char *format, ...) ++{ ++ int ret; ++ char errbuf[BUFSIZ + 1] = {0}; ++ ssize_t sret; ++ va_list argp; ++ ++ if (errfd <= 0) ++ return; ++ ++ va_start(argp, format); ++ ret = vsnprintf(errbuf, BUFSIZ, format, argp); ++ va_end(argp); ++ if (ret < 0) ++ SYSERROR("Failed to call vsnprintf"); ++ sret = write(errfd, errbuf, strlen(errbuf)); ++ if (sret < 0) ++ SYSERROR("Write errbuf failed"); ++} ++ +diff --git a/src/lxc/utils.h b/src/lxc/utils.h +index 364bf67..3d56fd9 100644 +--- a/src/lxc/utils.h ++++ b/src/lxc/utils.h +@@ -314,5 +314,6 @@ extern int lxc_setup_env_home(uid_t uid); + + extern int fd_nonblock(int fd); + extern int unsigned long long lxc_get_process_startat(pid_t pid); ++extern void lxc_write_error_message(int errfd, const char *format, ...); + + #endif /* __LXC_UTILS_H */ +-- +1.8.3.1 + diff --git a/0022-support-rootfs-mount-propagation.patch b/0022-support-rootfs-mount-propagation.patch new file mode 100644 index 0000000..f3153e0 --- /dev/null +++ b/0022-support-rootfs-mount-propagation.patch @@ -0,0 +1,507 @@ +From daa98c9452fcebe022bd6dcad29633719ef6917e Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Mon, 14 Jan 2019 17:02:02 +0800 +Subject: [PATCH 022/122] support rootfs mount propagation + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 230 ++++++++++++++++++++++++++-------------- + src/lxc/conf.h | 2 +- + src/lxc/confile.c | 8 +- + src/lxc/criu.c | 4 +- + src/lxc/storage/btrfs.c | 4 +- + src/lxc/storage/dir.c | 9 +- + src/lxc/storage/overlay.c | 4 +- + src/lxc/storage/storage_utils.c | 4 +- + src/lxc/storage/zfs.c | 4 +- + 9 files changed, 165 insertions(+), 104 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 8d8230f..55d1e45 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -1296,11 +1296,102 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) + return 0; + } + ++static void null_endofword(char *word) ++{ ++ while (*word && *word != ' ' && *word != '\t') ++ word++; ++ *word = '\0'; ++} ++ ++/* skip @nfields spaces in @src */ ++static char *get_field(char *src, int nfields) ++{ ++ int i; ++ char *p = src; ++ ++ for (i = 0; i < nfields; i++) { ++ while (*p && *p != ' ' && *p != '\t') ++ p++; ++ ++ if (!*p) ++ break; ++ ++ p++; ++ } ++ ++ return p; ++} ++ ++static int rootfs_parent_mount_private(char *rootfs) ++{ ++ /* walk /proc/self/mountinfo and change parent of rootfs to private */ ++ FILE *f = fopen("/proc/self/mountinfo", "r"); ++ char *line = NULL; ++ char *parent = NULL, *options = NULL; ++ size_t len = 0; ++ int ret = 0; ++ ++ if (!f) { ++ SYSERROR("Failed to open /proc/self/mountinfo to make parent of rootfs to private"); ++ return -1; ++ } ++ ++ while (getline(&line, &len, f) != -1) { ++ char *target, *opts, *tmptarget; ++ target = get_field(line, 4); ++ if (!target) ++ continue; ++ tmptarget = strdup(target); ++ if (!tmptarget) ++ continue; ++ null_endofword(tmptarget); ++ if (!strstr(rootfs, tmptarget)) { ++ free(tmptarget); ++ continue; ++ } ++ if (!parent || strlen(tmptarget) > strlen(parent)) { ++ free(parent); ++ parent = tmptarget; ++ } else { ++ free(tmptarget); ++ continue; ++ } ++ opts = get_field(target, 2); ++ if (!opts) ++ continue; ++ null_endofword(opts); ++ free(options); ++ options = strdup(opts); ++ if (!options) ++ continue; ++ } ++ ++ if (!parent || !options) { ++ ERROR("Could not find parent mount of %s", rootfs); ++ ret = -1; ++ } else { ++ if (strstr(options, "shared")) { ++ if (mount(NULL, parent, NULL, MS_PRIVATE, NULL)) { ++ SYSERROR("Failed to make %s private", parent); ++ ret = -1; ++ } ++ DEBUG("Mounted parent %s of rootfs %s to private", parent, rootfs); ++ } ++ } ++ free(parent); ++ free(options); ++ fclose(f); ++ free(line); ++ return ret; ++} ++ + static int lxc_mount_rootfs(struct lxc_conf *conf) + { + int ret; + struct lxc_storage *bdev; + const struct lxc_rootfs *rootfs = &conf->rootfs; ++ unsigned long flags, mntflags, pflags; ++ char *mntdata; + + if (!rootfs->path) { + ret = mount("", "/", NULL, MS_SLAVE | MS_REC, 0); +@@ -1319,6 +1410,44 @@ static int lxc_mount_rootfs(struct lxc_conf *conf) + return -1; + } + ++ // isulad-start: support mount propagations of rootfs ++ //Get rootfs mnt propagation options, such as slave or shared ++ if (parse_mntopts(conf->rootfs.options, &mntflags, &pflags, &mntdata) < 0) { ++ free(mntdata); ++ return -1; ++ } ++ free(mntdata); ++ ++ flags = MS_SLAVE | MS_REC; ++ if (pflags) ++ flags = pflags; ++ ++ /* Mount propagation inside container can not greater than host. ++ * So we must change propagation of root according to flags, default is rslave. ++ * That means shared propagation inside container is disabled by default. ++ */ ++ ret = mount("", "/", NULL, flags, NULL); ++ if (ret < 0) { ++ SYSERROR("Failed to make / to propagation flags %lu.", flags); ++ return -1; ++ } ++ ++ /* Make parent mount private to make sure following bind mount does ++ * not propagate in other namespaces. Also it will help with kernel ++ * check pass in pivot_root. (IS_SHARED(new_mnt->mnt_parent)) ++ */ ++ ret = rootfs_parent_mount_private(conf->rootfs.mount); ++ if (ret != 0) { ++ ERROR("Failed to make parent of rootfs %s to private.", conf->rootfs.mount); ++ return -1; ++ } ++ ++ ret = mount(conf->rootfs.mount, conf->rootfs.mount, "bind", MS_BIND | MS_REC, NULL); ++ if (ret < 0) { ++ SYSERROR("Failed to mount rootfs %s", conf->rootfs.mount); ++ return -1; ++ }// isulad-end: support mount propagations of rootfs ++ + bdev = storage_init(conf); + if (!bdev) { + ERROR("Failed to mount rootfs \"%s\" onto \"%s\" with options \"%s\"", +@@ -1960,7 +2089,7 @@ static int lxc_setup_console(const struct lxc_rootfs *rootfs, + return lxc_setup_ttydir_console(rootfs, console, ttydir); + } + +-static void parse_mntopt(char *opt, unsigned long *flags, char **data, size_t size) ++static void parse_mntopt(char *opt, unsigned long *mflags, unsigned long *pflags, char **data, size_t size) + { + struct mount_opt *mo; + +@@ -1970,26 +2099,40 @@ static void parse_mntopt(char *opt, unsigned long *flags, char **data, size_t si + for (mo = &mount_opt[0]; mo->name != NULL; mo++) { + if (strncmp(opt, mo->name, strlen(mo->name)) == 0) { + if (mo->clear) +- *flags &= ~mo->flag; ++ *mflags &= ~mo->flag; + else +- *flags |= mo->flag; ++ *mflags |= mo->flag; + return; + } + } + ++ /* If opt is found in propagation_opt, set or clear flags. */ ++ for (mo = &propagation_opt[0]; mo->name != NULL; mo++) { ++ if (strncmp(opt, mo->name, strlen(mo->name)) != 0) ++ continue; ++ ++ if (mo->clear) ++ *pflags &= ~mo->flag; ++ else ++ *pflags |= mo->flag; ++ ++ return; ++ } ++ + if (strlen(*data)) + (void)strlcat(*data, ",", size); + + (void)strlcat(*data, opt, size); + } + +-int parse_mntopts(const char *mntopts, unsigned long *mntflags, char **mntdata) ++int parse_mntopts(const char *mntopts, unsigned long *mntflags, unsigned long *pflags, char **mntdata) + { + char *data, *p, *s; + size_t size; + + *mntdata = NULL; + *mntflags = 0L; ++ *pflags = 0L; + + if (!mntopts) + return 0; +@@ -2007,7 +2150,7 @@ int parse_mntopts(const char *mntopts, unsigned long *mntflags, char **mntdata) + *data = 0; + + lxc_iterate_parts(p, s, ",") +- parse_mntopt(p, mntflags, &data, size); ++ parse_mntopt(p, mntflags, pflags, &data, size); + + if (*data) + *mntdata = data; +@@ -2018,71 +2161,6 @@ int parse_mntopts(const char *mntopts, unsigned long *mntflags, char **mntdata) + return 0; + } + +-static void parse_propagationopt(char *opt, unsigned long *flags) +-{ +- struct mount_opt *mo; +- +- /* If opt is found in propagation_opt, set or clear flags. */ +- for (mo = &propagation_opt[0]; mo->name != NULL; mo++) { +- if (strncmp(opt, mo->name, strlen(mo->name)) != 0) +- continue; +- +- if (mo->clear) +- *flags &= ~mo->flag; +- else +- *flags |= mo->flag; +- +- return; +- } +-} +- +-int parse_propagationopts(const char *mntopts, unsigned long *pflags) +-{ +- char *p, *s; +- +- if (!mntopts) +- return 0; +- +- s = strdup(mntopts); +- if (!s) { +- SYSERROR("Failed to allocate memory"); +- return -ENOMEM; +- } +- +- *pflags = 0L; +- lxc_iterate_parts(p, s, ",") +- parse_propagationopt(p, pflags); +- free(s); +- +- return 0; +-} +- +-static void null_endofword(char *word) +-{ +- while (*word && *word != ' ' && *word != '\t') +- word++; +- *word = '\0'; +-} +- +-/* skip @nfields spaces in @src */ +-static char *get_field(char *src, int nfields) +-{ +- int i; +- char *p = src; +- +- for (i = 0; i < nfields; i++) { +- while (*p && *p != ' ' && *p != '\t') +- p++; +- +- if (!*p) +- break; +- +- p++; +- } +- +- return p; +-} +- + static int mount_entry(const char *fsname, const char *target, + const char *fstype, unsigned long mountflags, + unsigned long pflags, const char *data, bool optional, +@@ -2289,10 +2367,9 @@ static inline int mount_entry_on_generic(struct mntent *mntent, + const char *lxc_path) + { + int ret; +- unsigned long mntflags; ++ unsigned long mntflags, pflags; + char *mntdata; + bool dev, optional, relative; +- unsigned long pflags = 0; + char *rootfs_path = NULL; + + optional = hasmntopt(mntent, "optional") != NULL; +@@ -2312,11 +2389,7 @@ static inline int mount_entry_on_generic(struct mntent *mntent, + } + cull_mntent_opt(mntent); + +- ret = parse_propagationopts(mntent->mnt_opts, &pflags); +- if (ret < 0) +- return -1; +- +- ret = parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata); ++ ret = parse_mntopts(mntent->mnt_opts, &mntflags, &pflags, &mntdata); + if (ret < 0) + return -1; + +@@ -3544,7 +3617,8 @@ int lxc_setup_rootfs_prepare_root(struct lxc_conf *conf, const char *name, + return 0; + } + +- remount_all_slave(); ++ if (!conf->rootfs.options) ++ remount_all_slave(); + + ret = run_lxc_hooks(name, "pre-mount", conf, NULL); + if (ret < 0) { +diff --git a/src/lxc/conf.h b/src/lxc/conf.h +index db474e1..7393dbf 100644 +--- a/src/lxc/conf.h ++++ b/src/lxc/conf.h +@@ -463,7 +463,7 @@ extern int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, + extern int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), + void *data, const char *fn_name); + extern int parse_mntopts(const char *mntopts, unsigned long *mntflags, +- char **mntdata); ++ unsigned long *pflags, char **mntdata); + extern int parse_propagationopts(const char *mntopts, unsigned long *pflags); + extern void tmp_proc_unmount(struct lxc_conf *lxc_conf); + extern void remount_all_slave(void); +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index e199965..db63b55 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -2065,16 +2065,10 @@ static int set_config_rootfs_options(const char *key, const char *value, + char *mdata = NULL, *opts = NULL; + struct lxc_rootfs *rootfs = &lxc_conf->rootfs; + +- ret = parse_mntopts(value, &mflags, &mdata); ++ ret = parse_mntopts(value, &mflags, &pflags, &mdata); + if (ret < 0) + return -EINVAL; + +- ret = parse_propagationopts(value, &pflags); +- if (ret < 0) { +- free(mdata); +- return -EINVAL; +- } +- + ret = set_config_string_item(&opts, value); + if (ret < 0) { + free(mdata); +diff --git a/src/lxc/criu.c b/src/lxc/criu.c +index 31c1940..bb97859 100644 +--- a/src/lxc/criu.c ++++ b/src/lxc/criu.c +@@ -389,9 +389,9 @@ static void exec_criu(struct cgroup_ops *cgroup_ops, struct lxc_conf *conf, + while (getmntent_r(mnts, &mntent, buf, sizeof(buf))) { + char *fmt, *key, *val, *mntdata; + char arg[2 * PATH_MAX + 2]; +- unsigned long flags; ++ unsigned long flags, pflags; + +- if (parse_mntopts(mntent.mnt_opts, &flags, &mntdata) < 0) ++ if (parse_mntopts(mntent.mnt_opts, &flags, &pflags, &mntdata) < 0) + goto err; + + free(mntdata); +diff --git a/src/lxc/storage/btrfs.c b/src/lxc/storage/btrfs.c +index bbfce61..a02c215 100644 +--- a/src/lxc/storage/btrfs.c ++++ b/src/lxc/storage/btrfs.c +@@ -212,7 +212,7 @@ bool btrfs_detect(const char *path) + + int btrfs_mount(struct lxc_storage *bdev) + { +- unsigned long mntflags; ++ unsigned long mntflags, pflags; + char *mntdata; + const char *src; + int ret; +@@ -223,7 +223,7 @@ int btrfs_mount(struct lxc_storage *bdev) + if (!bdev->src || !bdev->dest) + return -22; + +- if (parse_mntopts(bdev->mntopts, &mntflags, &mntdata) < 0) { ++ if (parse_mntopts(bdev->mntopts, &mntflags, &pflags, &mntdata) < 0) { + free(mntdata); + return -22; + } +diff --git a/src/lxc/storage/dir.c b/src/lxc/storage/dir.c +index 79b6469..c7b5ee2 100644 +--- a/src/lxc/storage/dir.c ++++ b/src/lxc/storage/dir.c +@@ -170,20 +170,13 @@ int dir_mount(struct lxc_storage *bdev) + if (!bdev->src || !bdev->dest) + return -22; + +- ret = parse_mntopts(bdev->mntopts, &mntflags, &mntdata); ++ ret = parse_mntopts(bdev->mntopts, &mntflags, &pflags, &mntdata); + if (ret < 0) { + ERROR("Failed to parse mount options \"%s\"", bdev->mntopts); + free(mntdata); + return -EINVAL; + } + +- ret = parse_propagationopts(bdev->mntopts, &pflags); +- if (ret < 0) { +- ERROR("Failed to parse propagation options \"%s\"", bdev->mntopts); +- free(mntdata); +- return -EINVAL; +- } +- + src = lxc_storage_get_path(bdev->src, bdev->type); + + ret = mount(src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags | pflags, mntdata); +diff --git a/src/lxc/storage/overlay.c b/src/lxc/storage/overlay.c +index 01546b1..90408a3 100644 +--- a/src/lxc/storage/overlay.c ++++ b/src/lxc/storage/overlay.c +@@ -495,7 +495,7 @@ int ovl_mount(struct lxc_storage *bdev) + char *options_work, *work, *lastslash; + int lastslashidx; + size_t len, len2; +- unsigned long mntflags; ++ unsigned long mntflags, pflags; + char *mntdata; + int ret, ret2; + +@@ -575,7 +575,7 @@ int ovl_mount(struct lxc_storage *bdev) + memcpy(work + lastslashidx, "olwork", STRLITERALLEN("olwork")); + work[lastslashidx + STRLITERALLEN("olwork")] = '\0'; + +- ret = parse_mntopts(bdev->mntopts, &mntflags, &mntdata); ++ ret = parse_mntopts(bdev->mntopts, &mntflags, &pflags, &mntdata); + if (ret < 0) { + ERROR("Failed to parse mount options"); + free(mntdata); +diff --git a/src/lxc/storage/storage_utils.c b/src/lxc/storage/storage_utils.c +index fa4e727..46e08a3 100644 +--- a/src/lxc/storage/storage_utils.c ++++ b/src/lxc/storage/storage_utils.c +@@ -396,7 +396,7 @@ int find_fstype_cb(char *buffer, void *data) + const char *options; + } *cbarg = data; + +- unsigned long mntflags; ++ unsigned long mntflags, pflags; + char *mntdata; + char *fstype; + +@@ -411,7 +411,7 @@ int find_fstype_cb(char *buffer, void *data) + DEBUG("Trying to mount \"%s\"->\"%s\" with FSType \"%s\"", cbarg->rootfs, + cbarg->target, fstype); + +- if (parse_mntopts(cbarg->options, &mntflags, &mntdata) < 0) { ++ if (parse_mntopts(cbarg->options, &mntflags, &pflags, &mntdata) < 0) { + free(mntdata); + return 0; + } +diff --git a/src/lxc/storage/zfs.c b/src/lxc/storage/zfs.c +index ba104da..752b0c5 100644 +--- a/src/lxc/storage/zfs.c ++++ b/src/lxc/storage/zfs.c +@@ -184,7 +184,7 @@ int zfs_mount(struct lxc_storage *bdev) + size_t oldlen, newlen, totallen; + char *mntdata, *tmp; + const char *src; +- unsigned long mntflags; ++ unsigned long mntflags, pflags; + char cmd_output[PATH_MAX] = {0}; + + if (strcmp(bdev->type, "zfs")) +@@ -193,7 +193,7 @@ int zfs_mount(struct lxc_storage *bdev) + if (!bdev->src || !bdev->dest) + return -22; + +- ret = parse_mntopts(bdev->mntopts, &mntflags, &mntdata); ++ ret = parse_mntopts(bdev->mntopts, &mntflags, &pflags, &mntdata); + if (ret < 0) { + ERROR("Failed to parse mount options"); + free(mntdata); +-- +1.8.3.1 + diff --git a/0023-attach.c-change-uid-and-gid-from-lxc-container-confi.patch b/0023-attach.c-change-uid-and-gid-from-lxc-container-confi.patch new file mode 100644 index 0000000..4e32882 --- /dev/null +++ b/0023-attach.c-change-uid-and-gid-from-lxc-container-confi.patch @@ -0,0 +1,31 @@ +From 37203bfbe3ff71fb158175bb436e0748e84415ef Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Mon, 14 Jan 2019 17:09:57 +0800 +Subject: [PATCH 023/122] attach.c: change uid and gid from lxc container + config + +Signed-off-by: LiFeng +--- + src/lxc/attach.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/lxc/attach.c b/src/lxc/attach.c +index 570b9d0..e6e4b0d 100644 +--- a/src/lxc/attach.c ++++ b/src/lxc/attach.c +@@ -1146,6 +1146,12 @@ int lxc_attach(const char *name, const char *lxcpath, + } + conf = init_ctx->container->lxc_conf; + ++ // isulad: always switch uid and gid for attach ++ if (options->uid == -1) ++ options->uid = init_ctx->container->lxc_conf->init_uid; ++ if (options->gid == -1) ++ options->gid = init_ctx->container->lxc_conf->init_gid; ++ + if (!fetch_seccomp(init_ctx->container, options)) + WARN("Failed to get seccomp policy"); + +-- +1.8.3.1 + diff --git a/0024-isulad-support-symlink-in-mount-entry-and-not-permit.patch b/0024-isulad-support-symlink-in-mount-entry-and-not-permit.patch new file mode 100644 index 0000000..2469900 --- /dev/null +++ b/0024-isulad-support-symlink-in-mount-entry-and-not-permit.patch @@ -0,0 +1,821 @@ +From 205213bbf95886772aa0b8974507741d5012dd45 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Mon, 14 Jan 2019 20:12:06 +0800 +Subject: [PATCH 024/122] isulad: support symlink in mount entry, and not + permit mount to /proc + +Signed-off-by: LiFeng +--- + src/lxc/Makefile.am | 2 + + src/lxc/conf.c | 108 ++++++++++- + src/lxc/path.c | 546 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + src/lxc/path.h | 70 +++++++ + 4 files changed, 721 insertions(+), 5 deletions(-) + create mode 100644 src/lxc/path.c + create mode 100644 src/lxc/path.h + +diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am +index 08e2fab..f2928b7 100644 +--- a/src/lxc/Makefile.am ++++ b/src/lxc/Makefile.am +@@ -12,6 +12,7 @@ noinst_HEADERS = attach.h \ + confile_utils.h \ + criu.h \ + error.h \ ++ path.h \ + file_utils.h \ + ../include/netns_ifaddrs.h \ + initutils.h \ +@@ -95,6 +96,7 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \ + commands_utils.c commands_utils.h \ + conf.c conf.h \ + confile.c confile.h \ ++ path.c path.h \ + confile_utils.c confile_utils.h \ + criu.c criu.h \ + error.c error.h \ +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 55d1e45..800573a 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -77,6 +77,7 @@ + #include "storage/overlay.h" + #include "syscall_wrappers.h" + #include "terminal.h" ++#include "path.h" + #include "utils.h" + + #ifdef MAJOR_IN_MKDEV +@@ -2309,6 +2310,79 @@ static void cull_mntent_opt(struct mntent *mntent) + } + } + ++/* isulad: checkMountDestination checks to ensure that the mount destination is not over the top of /proc. ++ * dest is required to be an abs path and have any symlinks resolved before calling this function. */ ++static int check_mount_destination(const char *rootfs, const char *dest) ++{ ++ const char *invalid_destinations[] = { ++ "/proc", ++ NULL ++ }; ++ // White list, it should be sub directories of invalid destinations ++ const char *valid_destinations[] = { ++ // These entries can be bind mounted by files emulated by fuse, ++ // so commands like top, free displays stats in container. ++ "/proc/cpuinfo", ++ "/proc/diskstats", ++ "/proc/meminfo", ++ "/proc/stat", ++ "/proc/swaps", ++ "/proc/uptime", ++ "/proc/net/dev", ++ NULL ++ }; ++ const char **valid, **invalid; ++ ++ for(valid = valid_destinations; *valid != NULL; valid++) { ++ char *fullpath, *relpath; ++ const char *parts[3] = { ++ rootfs, ++ *valid, ++ NULL ++ }; ++ fullpath = lxc_string_join("/", parts, false); ++ if (!fullpath) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ relpath = path_relative(fullpath, dest); ++ free(fullpath); ++ if (!relpath) ++ return -1; ++ if (!strcmp(relpath, ".")) { ++ free(relpath); ++ return 0; ++ } ++ free(relpath); ++ } ++ ++ for(invalid = invalid_destinations; *invalid != NULL; invalid++) { ++ char *fullpath, *relpath; ++ const char *parts[3] = { ++ rootfs, ++ *invalid, ++ NULL ++ }; ++ fullpath = lxc_string_join("/", parts, false); ++ if (!fullpath) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ relpath = path_relative(fullpath, dest); ++ free(fullpath); ++ if (!relpath) ++ return -1; ++ if (!strcmp(relpath, ".") || strncmp(relpath, "..", 2)) { ++ ERROR("%s cannot be mounted because it is located inside %s", dest, *invalid); ++ free(relpath); ++ return -1; ++ } ++ free(relpath); ++ } ++ ++ return 0; ++} ++ + static int mount_entry_create_dir_file(const struct mntent *mntent, + const char *path, + const struct lxc_rootfs *rootfs, +@@ -2370,7 +2444,8 @@ static inline int mount_entry_on_generic(struct mntent *mntent, + unsigned long mntflags, pflags; + char *mntdata; + bool dev, optional, relative; +- char *rootfs_path = NULL; ++ char *rootfs_path = NULL, *rpath = NULL; ++ const char *dest = path; + + optional = hasmntopt(mntent, "optional") != NULL; + dev = hasmntopt(mntent, "dev") != NULL; +@@ -2379,9 +2454,29 @@ static inline int mount_entry_on_generic(struct mntent *mntent, + if (rootfs && rootfs->path) + rootfs_path = rootfs->mount; + +- ret = mount_entry_create_dir_file(mntent, path, rootfs, lxc_name, +- lxc_path); ++ // isulad: ensure that the destination of the bind mount is resolved of symlinks at mount time because ++ // any previous mounts can invalidate the next mount's destination. ++ // this can happen when a user specifies mounts within other mounts to cause breakouts or other ++ // evil stuff to try to escape the container's rootfs. ++ if (rootfs_path) { ++ rpath = follow_symlink_in_scope(path, rootfs_path); ++ if (!rpath) { ++ ERROR("Failed to get real path for '%s'", path); ++ return -1; ++ } ++ dest = rpath; ++ ++ ret = check_mount_destination(rootfs_path, dest); ++ if (ret) { ++ ERROR("Mount destination is invalid: '%s'", dest); ++ free(rpath); ++ return -1; ++ } ++ } ++ ++ ret = mount_entry_create_dir_file(mntent, dest, rootfs, lxc_name, lxc_path); + if (ret < 0) { ++ free(rpath); + if (optional) + return 0; + +@@ -2390,13 +2485,16 @@ static inline int mount_entry_on_generic(struct mntent *mntent, + cull_mntent_opt(mntent); + + ret = parse_mntopts(mntent->mnt_opts, &mntflags, &pflags, &mntdata); +- if (ret < 0) ++ if (ret < 0) { ++ free(rpath); + return -1; ++ } + +- ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type, mntflags, ++ ret = mount_entry(mntent->mnt_fsname, dest, mntent->mnt_type, mntflags, + pflags, mntdata, optional, dev, relative, rootfs_path); + + free(mntdata); ++ free(rpath); + return ret; + } + +diff --git a/src/lxc/path.c b/src/lxc/path.c +new file mode 100644 +index 0000000..e917dcb +--- /dev/null ++++ b/src/lxc/path.c +@@ -0,0 +1,546 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "path.h" ++#include "log.h" ++ ++lxc_log_define(lxc_path_ui, lxc); ++ ++#define ISSLASH(C) ((C) == '/') ++#define IS_ABSOLUTE_FILE_NAME(F) (ISSLASH ((F)[0])) ++#define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F)) ++ ++bool specify_current_dir(const char *path) ++{ ++ char *basec = NULL, *bname = NULL; ++ bool res = false; ++ ++ basec = strdup(path); ++ if (!basec) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ ++ bname = basename(basec); ++ res = !strcmp(bname, "."); ++ free(basec); ++ return res; ++} ++ ++bool has_traling_path_separator(const char *path) ++{ ++ return path && strlen(path) && (path[strlen(path) - 1] == '/'); ++} ++ ++// PreserveTrailingDotOrSeparator returns the given cleaned path ++// and appends a trailing `/.` or `/` if its corresponding original ++// path ends with a trailing `/.` or `/`. If the cleaned ++// path already ends in a `.` path segment, then another is not added. If the ++// clean path already ends in a path separator, then another is not added. ++char *preserve_trailing_dot_or_separator(const char *cleanedpath, ++ const char *originalpath) ++{ ++ char *respath = NULL; ++ size_t len; ++ ++ len = strlen(cleanedpath) + 3; ++ respath = malloc(len); ++ if (!respath) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ memset(respath, 0x00, len); ++ strcat(respath, cleanedpath); ++ ++ if (!specify_current_dir(cleanedpath) && specify_current_dir(originalpath)) { ++ if (!has_traling_path_separator(respath)) ++ strcat(respath, "/"); ++ strcat(respath, "."); ++ } ++ ++ if (!has_traling_path_separator(respath) && ++ has_traling_path_separator(originalpath)) ++ strcat(respath, "/"); ++ ++ return respath; ++} ++ ++ ++// Split splits path immediately following the final Separator, ++// separating it into a directory and file name component. ++// If there is no Separator in path, Split returns an empty dir ++// and file set to path. ++// The returned values have the property that path = dir+file. ++bool filepath_split(const char *path, char **dir, char **base) ++{ ++ ssize_t i; ++ size_t len; ++ ++ len = strlen(path); ++ i = len - 1; ++ while (i >= 0 && path[i] != '/') ++ i--; ++ ++ *dir = malloc(i + 2); ++ if (!*dir) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ memcpy(*dir, path, i + 1); ++ *(*dir + i + 1) = '\0'; ++ ++ *base = strdup(path + i + 1); ++ if (!*base) { ++ ERROR("Out of memory"); ++ free(*dir); ++ *dir = NULL; ++ return false; ++ } ++ ++ return true; ++} ++ ++/* ++ * cleanpath is similar to realpath of glibc, but not expands symbolic links, ++ * and not check the existence of components of the path. ++ */ ++char *cleanpath(const char *path, char *resolved) ++{ ++ char *rpath, *dest; ++ const char *start, *end, *rpath_limit; ++ ++ if (path == NULL || path[0] == '\0') ++ return NULL; ++ ++ if (resolved == NULL) { ++ rpath = malloc(PATH_MAX); ++ if (rpath == NULL) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ } else { ++ rpath = resolved; ++ } ++ rpath_limit = rpath + PATH_MAX; ++ ++ if (!IS_ABSOLUTE_FILE_NAME(path)) { ++ if (!getcwd(rpath, PATH_MAX)) { ++ ERROR("Failed to getcwd"); ++ rpath[0] = '\0'; ++ goto error; ++ } ++ dest = strchr(rpath, '\0'); ++ start = path; ++ } else { ++ dest = rpath; ++ *dest++ = '/'; ++ start = path; ++ } ++ ++ for (end = start; *start; start = end) { ++ /* Skip sequence of multiple path-separators. */ ++ while (ISSLASH(*start)) ++ ++start; ++ ++ /* Find end of path component. */ ++ for (end = start; *end && !ISSLASH(*end); ++end) ++ /* Nothing. */; ++ ++ if (end - start == 0) { ++ break; ++ } else if (end - start == 1 && start[0] == '.') { ++ /* nothing */; ++ } else if (end - start == 2 && start[0] == '.' && start[1] == '.') { ++ /* Back up to previous component, ignore if at root already. */ ++ if (dest > rpath + 1) ++ for (--dest; dest > rpath && !ISSLASH(dest[-1]); --dest) ++ continue; ++ } else { ++ size_t new_size; ++ ++ if (!ISSLASH(dest[-1])) ++ *dest++ = '/'; ++ ++ if (dest + (end - start) >= rpath_limit) { ++ long long dest_offset = dest - rpath; ++ char *new_rpath; ++ ++ if (resolved) { ++ printf("Path is to long"); ++ if (dest > rpath + 1) ++ dest--; ++ *dest = '\0'; ++ goto error; ++ } ++ ++ new_size = rpath_limit - rpath; ++ if (end - start + 1 > PATH_MAX) ++ new_size += end - start + 1; ++ else ++ new_size += PATH_MAX; ++ new_rpath = (char *) realloc(rpath, new_size); ++ if (new_rpath == NULL) { ++ ERROR("Out of memory"); ++ goto error; ++ } ++ rpath = new_rpath; ++ rpath_limit = rpath + new_size; ++ ++ dest = rpath + dest_offset; ++ } ++ ++ memcpy(dest, start, end - start); ++ dest += end - start; ++ *dest = '\0'; ++ } ++ } ++ if (dest > rpath + 1 && ISSLASH(dest[-1])) ++ --dest; ++ *dest = '\0'; ++ ++ return rpath; ++ ++error: ++ if (resolved == NULL) ++ free(rpath); ++ return NULL; ++} ++ ++// evalSymlinksInScope will evaluate symlinks in `path` within a scope `root` and return ++// a result guaranteed to be contained within the scope `root`, at the time of the call. ++// Symlinks in `root` are not evaluated and left as-is. ++// Errors encountered while attempting to evaluate symlinks in path will be returned. ++// Non-existing paths are valid and do not constitute an error. ++// `path` has to contain `root` as a prefix, or else an error will be returned. ++// Trying to break out from `root` does not constitute an error. ++// ++// Example: ++// If /foo/bar -> /outside, ++// FollowSymlinkInScope("/foo/bar", "/foo") == "/foo/outside" instead of "/oustide" ++char *eval_symlinks_in_scope(const char *fullpath, const char *rootpath) ++{ ++ char resroot[PATH_MAX] = {0}, *root = NULL; ++ char *rpath, *dest, *prefix, *extra_buf = NULL; ++ const char *start, *end, *rpath_limit; ++ int num_links = 0; ++ size_t prefix_len; ++ ++ if (!fullpath || !rootpath) ++ return NULL; ++ ++ root = cleanpath(rootpath, resroot); ++ if (!root) { ++ ERROR("Failed to get cleaned path"); ++ return NULL; ++ } ++ ++ if (!strcmp(fullpath, root)) ++ return strdup(fullpath); ++ ++ if (!strstr(fullpath, root)) { ++ ERROR("Path '%s' is not in '%s'", fullpath, root); ++ return NULL; ++ } ++ ++ rpath = malloc(PATH_MAX); ++ if (rpath == NULL) { ++ ERROR("Out of memory"); ++ goto error; ++ return NULL; ++ } ++ rpath_limit = rpath + PATH_MAX; ++ ++ prefix = root; ++ prefix_len = strlen(prefix); ++ if (!strcmp(prefix, "/")) ++ prefix_len = 0; ++ ++ dest = rpath; ++ if (prefix_len) { ++ memcpy(rpath, prefix, prefix_len); ++ dest += prefix_len; ++ } ++ *dest++ = '/'; ++ start = fullpath + prefix_len; ++ ++ for (end = start; *start; start = end) { ++ struct stat st; ++ int n; ++ ++ /* Skip sequence of multiple path-separators. */ ++ while (ISSLASH(*start)) ++ ++start; ++ ++ /* Find end of path component. */ ++ for (end = start; *end && !ISSLASH(*end); ++end) ++ /* Nothing. */; ++ ++ if (end - start == 0) { ++ break; ++ } else if (end - start == 1 && start[0] == '.') { ++ /* nothing */; ++ } else if (end - start == 2 && start[0] == '.' && start[1] == '.') { ++ /* Back up to previous component, ignore if at root already. */ ++ if (dest > rpath + prefix_len + 1) ++ for (--dest; dest > rpath && !ISSLASH(dest[-1]); --dest) ++ continue; ++ } else { ++ size_t new_size; ++ ++ if (!ISSLASH(dest[-1])) ++ *dest++ = '/'; ++ ++ if (dest + (end - start) >= rpath_limit) { ++ long long dest_offset = dest - rpath; ++ char *new_rpath; ++ ++ new_size = rpath_limit - rpath; ++ if (end - start + 1 > PATH_MAX) ++ new_size += end - start + 1; ++ else ++ new_size += PATH_MAX; ++ new_rpath = (char *) realloc(rpath, new_size); ++ if (new_rpath == NULL) { ++ ERROR("Out of memory"); ++ goto error; ++ } ++ rpath = new_rpath; ++ rpath_limit = rpath + new_size; ++ ++ dest = rpath + dest_offset; ++ } ++ ++ memcpy(dest, start, end - start); ++ dest += end - start; ++ *dest = '\0'; ++ ++ if (lstat(rpath, &st) < 0) { ++ // if rpath does not exist, accept it ++ continue; ++ } ++ ++ if (S_ISLNK(st.st_mode)) { ++ char *buf; ++ size_t len; ++ ++ if (++num_links > MAXSYMLINKS) { ++ ERROR("Too many links in '%s'", fullpath); ++ goto error; ++ } ++ ++ buf = malloc(PATH_MAX); ++ if (!buf) { ++ ERROR("Out of memory"); ++ goto error; ++ } ++ ++ n = readlink(rpath, buf, PATH_MAX - 1); ++ if (n < 0) { ++ free(buf); ++ goto error; ++ } ++ buf[n] = '\0'; ++ ++ if (!extra_buf) { ++ extra_buf = malloc(PATH_MAX); ++ if (!extra_buf) { ++ ERROR("Out of memory"); ++ free(buf); ++ goto error; ++ } ++ } ++ ++ len = strlen(end); ++ if ((long int)(n + len) >= PATH_MAX) { ++ free(buf); ++ ERROR("Path is too long"); ++ goto error; ++ } ++ ++ /* Careful here, end may be a pointer into extra_buf... */ ++ memmove(&extra_buf[n], end, len + 1); ++ fullpath = end = memcpy(extra_buf, buf, n); ++ ++ if (IS_ABSOLUTE_FILE_NAME(buf)) { ++ if (prefix_len) ++ memcpy(rpath, prefix, prefix_len); ++ dest = rpath + prefix_len; ++ *dest++ = '/'; /* It's an absolute symlink */ ++ } else { ++ /* Back up to previous component, ignore if at root ++ already: */ ++ if (dest > rpath + prefix_len + 1) ++ for (--dest; dest > rpath && !ISSLASH(dest[-1]); --dest) ++ continue; ++ } ++ } ++ } ++ } ++ if (dest > rpath + prefix_len + 1 && ISSLASH(dest[-1])) ++ --dest; ++ *dest = '\0'; ++ ++ if (extra_buf) ++ free(extra_buf); ++ ++ return rpath; ++ ++error: ++ if (extra_buf) ++ free(extra_buf); ++ free(rpath); ++ return NULL; ++} ++ ++// FollowSymlinkInScope is a wrapper around evalSymlinksInScope that returns an ++// absolute path. This function handles paths in a platform-agnostic manner. ++char *follow_symlink_in_scope(const char *fullpath, const char *rootpath) ++{ ++ char resfull[PATH_MAX] = {0}, *full = NULL; ++ char resroot[PATH_MAX] = {0}, *root = NULL; ++ ++ full = cleanpath(fullpath, resfull); ++ if (!full) { ++ ERROR("Failed to get cleaned path"); ++ return NULL; ++ } ++ ++ root = cleanpath(rootpath, resroot); ++ if (!root) { ++ ERROR("Failed to get cleaned path"); ++ return NULL; ++ } ++ ++ return eval_symlinks_in_scope(full, root); ++} ++ ++// GetResourcePath evaluates `path` in the scope of the container's rootpath, with proper path ++// sanitisation. Symlinks are all scoped to the rootpath of the container, as ++// though the container's rootpath was `/`. ++// ++// The BaseFS of a container is the host-facing path which is bind-mounted as ++// `/` inside the container. This method is essentially used to access a ++// particular path inside the container as though you were a process in that ++// container. ++int get_resource_path(const char *rootpath, const char *path, ++ char **scopepath) ++{ ++ char resolved[PATH_MAX] = {0}, *cleanedpath = NULL; ++ char *fullpath = NULL; ++ size_t len; ++ ++ if (!rootpath || !path || !scopepath) ++ return -1; ++ ++ *scopepath = NULL; ++ ++ cleanedpath = cleanpath(path, resolved); ++ if (!cleanedpath) { ++ ERROR("Failed to get cleaned path"); ++ return -1; ++ } ++ ++ len = strlen(rootpath) + strlen(cleanedpath) + 1; ++ fullpath = malloc(len); ++ if (!fullpath) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ snprintf(fullpath, len, "%s%s", rootpath, cleanedpath); ++ ++ *scopepath = follow_symlink_in_scope(fullpath, rootpath); ++ ++ free(fullpath); ++ return 0; ++} ++ ++// Rel returns a relative path that is lexically equivalent to targpath when ++// joined to basepath with an intervening separator. That is, ++// Join(basepath, Rel(basepath, targpath)) is equivalent to targpath itself. ++// On success, the returned path will always be relative to basepath, ++// even if basepath and targpath share no elements. ++// An error is returned if targpath can't be made relative to basepath or if ++// knowing the current working directory would be necessary to compute it. ++// Rel calls Clean on the result. ++char *path_relative(const char *basepath, const char *targpath) ++{ ++ char resbase[PATH_MAX] = {0}, *base = NULL; ++ char restarg[PATH_MAX] = {0}, *targ = NULL; ++ size_t bl = 0, tl = 0, b0 = 0, bi = 0, t0 = 0, ti = 0; ++ ++ base = cleanpath(basepath, resbase); ++ if (!base) { ++ ERROR("Failed to get cleaned path"); ++ return NULL; ++ } ++ ++ targ = cleanpath(targpath, restarg); ++ if (!targ) { ++ ERROR("Failed to get cleaned path"); ++ return NULL; ++ } ++ ++ if (strcmp(base, targ) == 0) ++ return strdup("."); ++ ++ bl = strlen(base); ++ tl = strlen(targ); ++ while(true) { ++ while(bi < bl && !ISSLASH(base[bi])) ++ bi++; ++ while(ti < tl && !ISSLASH(targ[ti])) ++ ti++; ++ //not the same string ++ if (((bi - b0) != (ti - t0)) || strncmp(base + b0, targ + t0, bi - b0)) ++ break; ++ if (bi < bl) ++ bi++; ++ if (ti < tl) ++ ti++; ++ b0 = bi; ++ t0 = ti; ++ } ++ ++ if (b0 != bl) { ++ // Base elements left. Must go up before going down. ++ int seps = 0, i; ++ size_t ncopyed = 0, seps_size; ++ char *buf; ++ ++ for (bi = b0; bi < bl; bi++) { ++ if (ISSLASH(base[bi])) ++ seps++; ++ } ++ //strlen(..) + strlen(/..) + '\0' ++ seps_size = 2 + seps * 3 + 1; ++ if (t0 != tl) ++ seps_size += 1 + tl - t0; ++ ++ buf = calloc(seps_size, 1); ++ if (!buf) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ buf[ncopyed++] = '.'; ++ buf[ncopyed++] = '.'; ++ for (i = 0; i < seps; i++) { ++ buf[ncopyed++] = '/'; ++ buf[ncopyed++] = '.'; ++ buf[ncopyed++] = '.'; ++ } ++ if (t0 != tl) { ++ buf[ncopyed++] = '/'; ++ memcpy(buf + ncopyed, targ + t0, tl - t0 + 1); ++ } ++ return buf; ++ } ++ ++ return strdup(targ + t0); ++} +\ No newline at end of file +diff --git a/src/lxc/path.h b/src/lxc/path.h +new file mode 100644 +index 0000000..e3a04cc +--- /dev/null ++++ b/src/lxc/path.h +@@ -0,0 +1,70 @@ ++#ifndef __LCRD_PATH_H_ ++#define __LCRD_PATH_H_ ++ ++#include ++ ++bool specify_current_dir(const char *path); ++ ++bool has_traling_path_separator(const char *path); ++ ++// PreserveTrailingDotOrSeparator returns the given cleaned path ++// and appends a trailing `/.` or `/` if its corresponding original ++// path ends with a trailing `/.` or `/`. If the cleaned ++// path already ends in a `.` path segment, then another is not added. If the ++// clean path already ends in a path separator, then another is not added. ++char *preserve_trailing_dot_or_separator(const char *cleanedpath, ++ const char *originalpath); ++ ++ ++// Split splits path immediately following the final Separator, ++// separating it into a directory and file name component. ++// If there is no Separator in path, Split returns an empty dir ++// and file set to path. ++// The returned values have the property that path = dir+file. ++bool filepath_split(const char *path, char **dir, char **base); ++ ++/* ++ * cleanpath is similar to realpath of glibc, but not expands symbolic links, ++ * and not check the existence of components of the path. ++ */ ++char *cleanpath(const char *path, char *resolved); ++ ++// evalSymlinksInScope will evaluate symlinks in `path` within a scope `root` and return ++// a result guaranteed to be contained within the scope `root`, at the time of the call. ++// Symlinks in `root` are not evaluated and left as-is. ++// Errors encountered while attempting to evaluate symlinks in path will be returned. ++// Non-existing paths are valid and do not constitute an error. ++// `path` has to contain `root` as a prefix, or else an error will be returned. ++// Trying to break out from `root` does not constitute an error. ++// ++// Example: ++// If /foo/bar -> /outside, ++// FollowSymlinkInScope("/foo/bar", "/foo") == "/foo/outside" instead of "/oustide" ++char *eval_symlinks_in_scope(const char *fullpath, const char *rootpath); ++ ++// FollowSymlinkInScope is a wrapper around evalSymlinksInScope that returns an ++// absolute path. This function handles paths in a platform-agnostic manner. ++char *follow_symlink_in_scope(const char *fullpath, const char *rootpath); ++ ++// GetResourcePath evaluates `path` in the scope of the container's rootpath, with proper path ++// sanitisation. Symlinks are all scoped to the rootpath of the container, as ++// though the container's rootpath was `/`. ++// ++// The BaseFS of a container is the host-facing path which is bind-mounted as ++// `/` inside the container. This method is essentially used to access a ++// particular path inside the container as though you were a process in that ++// container. ++int get_resource_path(const char *rootpath, const char *path, ++ char **scopepath); ++ ++// Rel returns a relative path that is lexically equivalent to targpath when ++// joined to basepath with an intervening separator. That is, ++// Join(basepath, Rel(basepath, targpath)) is equivalent to targpath itself. ++// On success, the returned path will always be relative to basepath, ++// even if basepath and targpath share no elements. ++// An error is returned if targpath can't be made relative to basepath or if ++// knowing the current working directory would be necessary to compute it. ++// Rel calls Clean on the result. ++char *path_relative(const char *basepath, const char *targpath); ++ ++#endif +-- +1.8.3.1 + diff --git a/0025-support-oci-hooks.patch b/0025-support-oci-hooks.patch new file mode 100644 index 0000000..9001974 --- /dev/null +++ b/0025-support-oci-hooks.patch @@ -0,0 +1,3087 @@ +From a32efb4b476da94f343aa56e400b180a7686079e Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Mon, 14 Jan 2019 17:47:17 +0800 +Subject: [PATCH 025/122] support oci hooks + +support oci hooks + +Signed-off-by: LiFeng +--- + configure.ac | 3 + + src/lxc/Makefile.am | 13 +- + src/lxc/conf.c | 528 ++++++++++++++++- + src/lxc/conf.h | 9 + + src/lxc/json/defs.c | 198 +++++++ + src/lxc/json/defs.h | 37 ++ + src/lxc/json/json_common.c | 1196 ++++++++++++++++++++++++++++++++++++++ + src/lxc/json/json_common.h | 185 ++++++ + src/lxc/json/oci_runtime_hooks.c | 53 ++ + src/lxc/json/oci_runtime_hooks.h | 15 + + src/lxc/json/oci_runtime_spec.c | 196 +++++++ + src/lxc/json/oci_runtime_spec.h | 37 ++ + src/lxc/json/read-file.c | 94 +++ + src/lxc/json/read-file.h | 11 + + src/lxc/lxccontainer.c | 66 +++ + src/lxc/lxccontainer.h | 7 + + src/lxc/start.c | 17 + + src/lxc/utils.c | 66 ++- + src/lxc/utils.h | 2 + + 19 files changed, 2716 insertions(+), 17 deletions(-) + create mode 100644 src/lxc/json/defs.c + create mode 100644 src/lxc/json/defs.h + create mode 100755 src/lxc/json/json_common.c + create mode 100755 src/lxc/json/json_common.h + create mode 100644 src/lxc/json/oci_runtime_hooks.c + create mode 100644 src/lxc/json/oci_runtime_hooks.h + create mode 100644 src/lxc/json/oci_runtime_spec.c + create mode 100644 src/lxc/json/oci_runtime_spec.h + create mode 100644 src/lxc/json/read-file.c + create mode 100644 src/lxc/json/read-file.h + +diff --git a/configure.ac b/configure.ac +index 950c8dd..4da52a2 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -120,6 +120,9 @@ AM_CONDITIONAL([DISTRO_UBUNTU], [test "x$with_distro" = "xubuntu"]) + + AC_CONFIG_LINKS([config/etc/default.conf:config/etc/${distroconf}]) + ++# Check yajl ++PKG_CHECK_MODULES([YAJL], [yajl >= 2],[],[AC_MSG_ERROR([You must install yajl >= 2])]) ++ + # Check for init system type + AC_MSG_CHECKING([for init system type]) + AC_ARG_WITH([init-script], +diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am +index f2928b7..5678b8d 100644 +--- a/src/lxc/Makefile.am ++++ b/src/lxc/Makefile.am +@@ -43,6 +43,11 @@ noinst_HEADERS = attach.h \ + ../tests/lxctest.h \ + tools/arguments.h \ + storage/storage_utils.h \ ++ json/defs.h \ ++ json/json_common.h \ ++ json/oci_runtime_hooks.h \ ++ json/oci_runtime_spec.h \ ++ json/read-file.h \ + utils.h + + if IS_BIONIC +@@ -140,6 +145,11 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \ + terminal.c \ + utils.c utils.h \ + version.h \ ++ json/json_common.c json/json_common.h \ ++ json/defs.h json/defs.c \ ++ json/oci_runtime_hooks.c json/oci_runtime_hooks.h \ ++ json/oci_runtime_spec.c json/oci_runtime_spec.h \ ++ json/read-file.c json/read-file.h \ + $(LSM_SOURCES) + + if IS_BIONIC +@@ -192,6 +202,7 @@ AM_CFLAGS = -DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \ + -I $(top_srcdir)/src \ + -I $(top_srcdir)/src/lxc \ + -I $(top_srcdir)/src/lxc/storage \ ++ -I $(top_srcdir)/src/lxc/json \ + -I $(top_srcdir)/src/lxc/cgroups + + if ENABLE_APPARMOR +@@ -224,7 +235,7 @@ liblxc_la_CFLAGS = -fPIC \ + liblxc_la_LDFLAGS = -pthread \ + -Wl,-no-undefined \ + -Wl,-soname,liblxc.so.$(firstword $(subst ., ,@LXC_ABI@)) \ +- -version-info @LXC_ABI_MAJOR@ ++ -version-info @LXC_ABI_MAJOR@ @YAJL_LIBS@ + + liblxc_la_LIBADD = $(CAP_LIBS) \ + $(GNUTLS_LIBS) \ +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 800573a..6a14de1 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -53,6 +53,7 @@ + #include + #include + #include ++#include + + #include "af_unix.h" + #include "caps.h" +@@ -137,7 +138,10 @@ char *lxchook_names[NUM_LXC_HOOKS] = { + "post-stop", + "clone", + "destroy", +- "start-host" ++ "start-host", ++ "oci-prestart", ++ "oci-poststart", ++ "oci-poststop" + }; + + struct mount_opt { +@@ -4082,13 +4086,530 @@ int lxc_setup(struct lxc_handler *handler) + return 0; + } + ++struct oci_hook_conf { ++ defs_hook *ocihook; ++ ++ int errfd; ++ int which; ++}; ++ ++struct wait_conf { ++ pid_t pid; ++ unsigned long long startat; ++ int timeout; ++ int errfd; ++ int which; ++}; ++ ++static char* generate_json_str(const char *name, const char *lxcpath, const char *rootfs) ++{ ++ char *cpid = NULL; ++ char *inmsg = NULL; ++ int rc = 0, ret = 0; ++ size_t size; ++ ++ if (!name || !lxcpath || !rootfs) { ++ ERROR("Invalid arguments"); ++ return NULL; ++ } ++ cpid = getenv("LXC_PID"); ++ if (!cpid) { ++ ERROR("Get container %s pid failed: %s", name, strerror(errno)); ++ cpid = "-1"; ++ } ++ // {"ociVersion":"","id":"xxx","pid":777,"root":"xxx","bundlePath":"xxx"} ++ size = 1 + 16 + 5 + strlen(name) + 3 + 6 + strlen(cpid) + 1 ++ + 7 + strlen(rootfs) + 3 + 13 + strlen(lxcpath) + 1 + strlen(name) + 3 + 1; ++ inmsg = malloc(size); ++ if (!inmsg) { ++ ERROR("Out of memory"); ++ ret = -1; ++ goto out_free; ++ } ++ rc = snprintf(inmsg, size, ++ "{\"ociVersion\":\"\",\"id\":\"%s\",\"pid\":%s,\"root\":\"%s\",\"bundlePath\":\"%s/%s\"}", ++ name, cpid, rootfs, lxcpath, name); ++ if (rc < 0 || rc >= size) { ++ ERROR("Create json string failed"); ++ ret = -1; ++ } ++ ++out_free: ++ if (ret) { ++ free(inmsg); ++ inmsg = NULL; ++ } ++ return inmsg; ++} ++ ++static char **merge_ocihook_env(char **oldenvs, size_t env_len, size_t *merge_env_len) ++{ ++ char **result; ++ size_t result_len = env_len; ++ size_t i, j; ++ char *tmpenv; ++ char *lxc_envs[] = {"LXC_CGNS_AWARE", "LXC_PID", "LXC_ROOTFS_MOUNT", ++ "LXC_CONFIG_FILE", "LXC_CGROUP_PATH", "LXC_ROOTFS_PATH", "LXC_NAME"}; ++ char *lxcenv_buf; ++ ++ result_len += (sizeof(lxc_envs) / sizeof(char *)) + 1; ++ result = malloc(sizeof(char *) * result_len); ++ if (!result) ++ return NULL; ++ memset(result, 0, sizeof(char *) * result_len); ++ ++ for(i = 0; i < env_len; i++) { ++ if (oldenvs[i]) ++ result[i] = strdup(oldenvs[i]); ++ } ++ ++ for(j = 0; j < (sizeof(lxc_envs) / sizeof(char *)); j++) { ++ tmpenv = getenv(lxc_envs[j]); ++ if (tmpenv && i < (result_len - 1)) { ++ lxcenv_buf = malloc(strlen(tmpenv) + 1 + strlen(lxc_envs[j]) + 1); ++ if (!lxcenv_buf) { ++ lxc_free_array((void **)result, free); ++ return NULL; ++ } ++ if (sprintf(lxcenv_buf, "%s=%s", lxc_envs[j], tmpenv) < 0) { ++ free(lxcenv_buf); ++ continue; ++ } ++ result[i++] = lxcenv_buf; ++ lxcenv_buf = NULL; ++ } ++ } ++ ++ *merge_env_len = i; ++ return result; ++} ++ ++static struct lxc_popen_FILE *lxc_popen_ocihook(char *commandpath, char **args, int args_len, ++ char **envs, int env_len, const char *instr) ++{ ++ int ret; ++ struct lxc_popen_FILE *fp = NULL; ++ int pipe_fds[2] = {-1, -1}; ++ int pipe_msg[2] = {-1, -1}; ++ pid_t child_pid; ++ ++ ret = pipe2(pipe_fds, O_CLOEXEC | O_NONBLOCK); ++ if (ret < 0) ++ return NULL; ++ ++ ret = pipe2(pipe_msg, O_CLOEXEC | O_NONBLOCK); ++ if (ret < 0) { ++ ERROR("Pipe msg failure"); ++ close(pipe_fds[0]); ++ close(pipe_fds[1]); ++ return NULL; ++ } ++ ++ child_pid = fork(); ++ if (child_pid < 0) ++ goto on_error; ++ ++ if (child_pid == 0) { ++ /* child */ ++ size_t result_capacity; ++ int r; ++ char **real_args; ++ ++ close(pipe_msg[1]); ++ if (pipe_msg[0] != STDIN_FILENO) ++ dup2(pipe_msg[0], STDIN_FILENO); ++ else { ++ if (fcntl(pipe_msg[0], F_SETFD, 0) != 0) { ++ SYSERROR("Failed to remove FD_CLOEXEC from fd."); ++ exit(127); ++ } ++ } ++ close(pipe_msg[0]); ++ ++ close(pipe_fds[0]); ++ ++ /* duplicate stdout */ ++ if (pipe_fds[1] != STDOUT_FILENO) ++ ret = dup2(pipe_fds[1], STDOUT_FILENO); ++ else ++ ret = fcntl(pipe_fds[1], F_SETFD, 0); ++ if (ret < 0) { ++ close(pipe_fds[1]); ++ _exit(EXIT_FAILURE); ++ } ++ ++ /* duplicate stderr */ ++ if (pipe_fds[1] != STDERR_FILENO) ++ ret = dup2(pipe_fds[1], STDERR_FILENO); ++ else ++ ret = fcntl(pipe_fds[1], F_SETFD, 0); ++ close(pipe_fds[1]); ++ if (ret < 0) ++ _exit(EXIT_FAILURE); ++ ++ /* ++ * Unblock signals. ++ * This is the main/only reason ++ * why we do our lousy popen() emulation. ++ */ ++ { ++ sigset_t mask; ++ sigfillset(&mask); ++ sigprocmask(SIG_UNBLOCK, &mask, NULL); ++ } ++ ++ result_capacity = args_len; ++ real_args = malloc(sizeof(char *) * (result_capacity + 2 + 1)); ++ if (!real_args) ++ _exit(EXIT_FAILURE); ++ memset(real_args, 0, sizeof(char *) * (result_capacity + 2 + 1)); ++ real_args[0] = strdup("sh"); ++ real_args[1] = strdup(commandpath); ++ for(r = 2; r < (args_len + 1); r++) ++ real_args[r] = strdup(args[r-1]); ++ ++ if (env_len > 0) ++ execvpe("/bin/sh", real_args, envs); ++ else ++ execvp("/bin/sh", real_args); ++ exit(127); ++ } ++ ++ /* parent */ ++ ++ close(pipe_fds[1]); ++ pipe_fds[1] = -1; ++ ++ close(pipe_msg[0]); ++ pipe_msg[0]= -1; ++ if (instr) { ++ size_t len = strlen(instr); ++ if (lxc_write_nointr(pipe_msg[1], instr, len) != len) { ++ WARN("Write instr: %s failed", instr); ++ } ++ } ++ close(pipe_msg[1]); ++ pipe_msg[1]= -1; ++ ++ fp = calloc(1, sizeof(*fp)); ++ if (!fp) { ++ ERROR("Failed to allocate memory"); ++ goto on_error; ++ } ++ ++ fp->child_pid = child_pid; ++ fp->pipe = pipe_fds[0]; ++ ++ return fp; ++ ++on_error: ++ ++ if (pipe_fds[0] >= 0) ++ close(pipe_fds[0]); ++ ++ if (pipe_fds[1] >= 0) ++ close(pipe_fds[1]); ++ ++ if (pipe_msg[0] >= 0) ++ close(pipe_msg[0]); ++ ++ if (pipe_msg[1] >= 0) ++ close(pipe_msg[1]); ++ ++ if (fp) ++ free(fp); ++ ++ return NULL; ++} ++ ++void* wait_ocihook_timeout(void *arg) ++{ ++ bool alive = false; ++ struct wait_conf *conf = (struct wait_conf *)arg; ++ ++ if (!conf || conf->timeout < 1) ++ goto out; ++ ++ sleep(conf->timeout); ++ ++ alive = lxc_process_alive(conf->pid, conf->startat); ++ ++ if (alive) { ++ ERROR("%s:%d: running %s hook caused \"hook ran past specified timeout of %.1fs\"", ++ __FILE__, __LINE__, ++ (conf->which == LXCHOOK_START_HOST) ? "prestart" : lxchook_names[conf->which], ++ (double)conf->timeout); ++ ++ if (conf->errfd >= 0) { ++ lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"hook ran past specified timeout of %.1fs\"", ++ __FILE__, __LINE__, ++ (conf->which == LXCHOOK_START_HOST) ? "prestart" : lxchook_names[conf->which], ++ (double)conf->timeout); ++ } ++ ++ if (kill(conf->pid, SIGKILL) && errno != ESRCH) { ++ ERROR("Send kill signal failed"); ++ goto out; ++ } ++ } ++ ++out: ++ free(conf); ++ return ((void *)0); ++} ++ ++static int run_ocihook_buffer(struct oci_hook_conf *oconf, char *inmsg) ++{ ++ struct lxc_popen_FILE *f; ++ char output[LXC_LOG_BUFFER_SIZE] = {0}; ++ int ret; ++ pthread_t ptid; ++ int err; ++ struct wait_conf *conf = NULL; ++ pthread_attr_t attr; ++ char *buffer = oconf->ocihook->path; ++ char *err_args_msg = NULL; ++ char *err_envs_msg = NULL; ++ char **hookenvs = NULL; ++ size_t hookenvs_len = 0; ++ ++ hookenvs = merge_ocihook_env(oconf->ocihook->env, oconf->ocihook->env_len, &hookenvs_len); ++ if (!hookenvs) { ++ ERROR("Out of memory."); ++ return -1; ++ } ++ ++ f = lxc_popen_ocihook(buffer, oconf->ocihook->args, oconf->ocihook->args_len, hookenvs, hookenvs_len, inmsg); ++ lxc_free_array((void **)hookenvs, free); ++ if (!f) { ++ SYSERROR("Failed to popen() %s.", buffer); ++ return -1; ++ } ++ ++ conf = malloc(sizeof(struct wait_conf)); ++ if (!conf) { ++ SYSERROR("Failed to malloc."); ++ goto on_error; ++ } ++ ++ memset(conf, 0x00, sizeof(struct wait_conf)); ++ ++ conf->pid = f->child_pid; ++ conf->startat = lxc_get_process_startat(conf->pid); ++ ++ INFO("hook_conf timeout %d", oconf->ocihook->timeout); ++ if(oconf->ocihook->timeout > 0) ++ conf->timeout = oconf->ocihook->timeout; ++ else { ++ conf->timeout = 30; ++ INFO("Set hook timeout 30s"); ++ } ++ conf->errfd = oconf->errfd; ++ conf->which = oconf->which; ++ ++ pthread_attr_init(&attr); ++ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); ++ err = pthread_create(&ptid, &attr, wait_ocihook_timeout, conf); ++ if (err != 0) { ++ ERROR("Create wait timeout thread failed"); ++ goto on_error; ++ } ++ ++ ret = lxc_wait_for_pid_status(f->child_pid); ++ ++ lxc_read_nointr(f->pipe, output, sizeof(output) - 1); ++ close(f->pipe); ++ free(f); ++ ++ if (ret == -1) { ++ SYSERROR("Script exited with error."); ++ goto print_hook; ++ } else if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) { ++ ERROR("Script exited with status %d. output:%s", WEXITSTATUS(ret), output); ++ if (conf->errfd >= 0) { ++ lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"error running hook: exit status %d, output:%s\"", ++ __FILE__, __LINE__, ++ (conf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[conf->which], ++ WEXITSTATUS(ret), output); ++ } ++ ++ goto print_hook; ++ } else if (WIFSIGNALED(ret)) { ++ ERROR("Script terminated by signal %d.", WTERMSIG(ret)); ++ if (conf->errfd >= 0) { ++ lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"error running hook: Script terminated by signal %d\"", ++ __FILE__, __LINE__, ++ (conf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[conf->which], ++ WTERMSIG(ret)); ++ } ++ ++ goto print_hook; ++ } ++ ++ return 0; ++ ++on_error: ++ if (f) { ++ if (f->pipe >= 0) ++ close(f->pipe); ++ free(f); ++ } ++ ++print_hook: ++ if (oconf->ocihook->args) ++ err_args_msg = lxc_string_join(" ", (const char **)oconf->ocihook->args, false); ++ if (oconf->ocihook->env) ++ err_envs_msg = lxc_string_join(" ", (const char **)oconf->ocihook->env, false); ++ ERROR("Hook script command: \"%s\", args: \"%s\", envs: \"%s\", timeout: %d.", ++ buffer, err_args_msg ? err_args_msg : "", ++ err_envs_msg ? err_envs_msg : "", conf->timeout); ++ ++ free(err_args_msg); ++ free(err_envs_msg); ++ return -1; ++} ++ ++static int run_ocihook_script_argv(const char *name, const char *section, ++ struct oci_hook_conf *oconf, ++ const char *lxcpath, const char *rootfs) ++{ ++ int ret; ++ const char *script = oconf->ocihook->path; ++ char *inmsg; ++ ++ INFO("Executing script \"%s\" for container \"%s\", config section \"%s\".", ++ script, name, section); ++ ++ inmsg = generate_json_str(name, lxcpath, rootfs); ++ if (!inmsg) { ++ return -1; ++ } ++ ++ ret = run_ocihook_buffer(oconf, inmsg); ++ free(inmsg); ++ inmsg = NULL; ++ return ret; ++} ++ ++static char *get_root_path(const char *path, const char *backend) ++{ ++ char *ret = NULL; ++ char *tmp = NULL; ++ ++ if (!path) { ++ ret = strdup("/"); ++ return ret; ++ } ++ if (!backend) { ++ goto default_out; ++ } ++ ++ if (strcmp(backend, "aufs") == 0 || ++ strcmp(backend, "overlayfs") == 0 || ++ strcmp(backend, "loop") == 0) { ++ tmp = strrchr(path, ':'); ++ tmp++; ++ ret = strdup(tmp); ++ if (!ret) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ return ret; ++ } ++ ++default_out: ++ ret = strdup(path); ++ if (!ret) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ return ret; ++} ++ ++static int run_oci_hooks(const char *name, const char *lxcpath, struct lxc_conf *lc, int which, int errfd) ++{ ++ struct oci_hook_conf work_conf = {0}; ++ oci_runtime_spec_hooks *ocihooks = NULL; ++ size_t i; ++ int ret = 0; ++ char *rootpath; ++ ++ if (!lc || !lc->ocihooks) { ++ return -1; ++ } ++ ++ rootpath = get_root_path(lc->rootfs.path, lc->rootfs.bdev_type); ++ if (!rootpath) { ++ ERROR("Get container %s rootpath failed.", name); ++ return -1; ++ } ++ ++ work_conf.errfd = errfd; ++ work_conf.which = which; ++ switch (which) { ++ case OCI_HOOK_PRESTART: ++ for (i = 0; i < lc->ocihooks->prestart_len; i++) { ++ work_conf.ocihook = lc->ocihooks->prestart[i]; ++ ret = run_ocihook_script_argv(name, "lxc", &work_conf, lxcpath, rootpath); ++ if (ret != 0) ++ break; ++ } ++ break; ++ case OCI_HOOK_POSTSTART: ++ for (i = 0; i < lc->ocihooks->poststart_len; i++) { ++ work_conf.ocihook = lc->ocihooks->poststart[i]; ++ ret = run_ocihook_script_argv(name, "lxc", &work_conf, lxcpath, rootpath); ++ if (ret != 0) ++ break; ++ } ++ break; ++ case OCI_HOOK_POSTSTOP: ++ for (i = 0; i < lc->ocihooks->poststop_len; i++) { ++ work_conf.ocihook = lc->ocihooks->poststop[i]; ++ ret = run_ocihook_script_argv(name, "lxc", &work_conf, lxcpath, rootpath); ++ if (ret != 0) ++ break; ++ } ++ break; ++ default: ++ ret = -1; ++ } ++ if (rootpath) ++ free(rootpath); ++ return ret; ++} ++ + int run_lxc_hooks(const char *name, char *hookname, struct lxc_conf *conf, + char *argv[]) + { + struct lxc_list *it; + int which = -1; + +- if (strcmp(hookname, "pre-start") == 0) ++ if (strcmp(hookname, "oci-prestart") == 0) { ++ int ret; ++ which = OCI_HOOK_PRESTART; ++ if (!argv || !argv[0]) { ++ ERROR("oci hook require lxcpath"); ++ return -1; ++ } ++ return run_oci_hooks(name, argv[0], conf, which, conf->errpipe[1]); ++ } else if (strcmp(hookname, "oci-poststart") == 0) { ++ int ret; ++ which = OCI_HOOK_POSTSTART; ++ if (!argv || !argv[0]) { ++ ERROR("oci hook require lxcpath"); ++ return -1; ++ } ++ return run_oci_hooks(name, argv[0], conf, which, conf->errpipe[1]); ++ } else if (strcmp(hookname, "oci-poststop") == 0) { ++ int ret; ++ which = OCI_HOOK_POSTSTOP; ++ if (!argv || !argv[0]) { ++ ERROR("oci hook require lxcpath"); ++ return -1; ++ } ++ return run_oci_hooks(name, argv[0], conf, which, conf->errpipe[1]); ++ } else if (strcmp(hookname, "pre-start") == 0) + which = LXCHOOK_PRESTART; + else if (strcmp(hookname, "start-host") == 0) + which = LXCHOOK_START_HOST; +@@ -4476,6 +4997,9 @@ void lxc_conf_free(struct lxc_conf *conf) + + if (current_config == conf) + current_config = NULL; ++ // isulad: free oci hooks ++ if (conf->ocihooks) ++ free_oci_runtime_spec_hooks(conf->ocihooks); + lxc_terminal_conf_free(&conf->console); + free(conf->rootfs.mount); + free(conf->rootfs.bdev_type); +diff --git a/src/lxc/conf.h b/src/lxc/conf.h +index 7393dbf..2263e47 100644 +--- a/src/lxc/conf.h ++++ b/src/lxc/conf.h +@@ -35,6 +35,7 @@ + #include + #include + ++#include "oci_runtime_hooks.h" + #include "compiler.h" + #include "config.h" + #include "list.h" +@@ -239,6 +240,9 @@ enum lxchooks { + LXCHOOK_CLONE, + LXCHOOK_DESTROY, + LXCHOOK_START_HOST, ++ OCI_HOOK_PRESTART, ++ OCI_HOOK_POSTSTART, ++ OCI_HOOK_POSTSTOP, + NUM_LXC_HOOKS + }; + +@@ -307,6 +311,11 @@ struct lxc_conf { + struct lxc_list hooks[NUM_LXC_HOOKS]; + }; + ++ /* ++ * isulad: support oci hook ++ * */ ++ oci_runtime_spec_hooks *ocihooks; ++ + char *lsm_aa_profile; + unsigned int lsm_aa_allow_incomplete; + char *lsm_se_context; +diff --git a/src/lxc/json/defs.c b/src/lxc/json/defs.c +new file mode 100644 +index 0000000..38df2f7 +--- /dev/null ++++ b/src/lxc/json/defs.c +@@ -0,0 +1,198 @@ ++// Generated from defs.json. Do not edit! ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE ++#endif ++#include ++#include ++#include "securec.h" ++#include "defs.h" ++ ++defs_hook *make_defs_hook(yajl_val tree, struct parser_context *ctx, parser_error *err) { ++ defs_hook *ret = NULL; ++ *err = 0; ++ if (tree == NULL) ++ return ret; ++ ret = safe_malloc(sizeof(*ret)); ++ { ++ yajl_val val = get_val(tree, "path", yajl_t_string); ++ if (val) { ++ char *str = YAJL_GET_STRING(val); ++ ret->path = safe_strdup(str ? str : ""); ++ } ++ } ++ { ++ yajl_val tmp = get_val(tree, "args", yajl_t_array); ++ if (tmp && YAJL_GET_ARRAY(tmp)) { ++ size_t i; ++ ret->args_len = YAJL_GET_ARRAY(tmp)->len; ++ ret->args = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) * sizeof(*ret->args)); ++ for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) { ++ yajl_val val = YAJL_GET_ARRAY(tmp)->values[i]; ++ if (val) { ++ char *str = YAJL_GET_STRING(val); ++ ret->args[i] = safe_strdup(str ? str : ""); ++ } ++ } ++ } ++ } ++ { ++ yajl_val tmp = get_val(tree, "env", yajl_t_array); ++ if (tmp && YAJL_GET_ARRAY(tmp)) { ++ size_t i; ++ ret->env_len = YAJL_GET_ARRAY(tmp)->len; ++ ret->env = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) * sizeof(*ret->env)); ++ for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) { ++ yajl_val val = YAJL_GET_ARRAY(tmp)->values[i]; ++ if (val) { ++ char *str = YAJL_GET_STRING(val); ++ ret->env[i] = safe_strdup(str ? str : ""); ++ } ++ } ++ } ++ } ++ { ++ yajl_val val = get_val(tree, "timeout", yajl_t_number); ++ if (val) { ++ int invalid = common_safe_int(YAJL_GET_NUMBER(val), (int *)&ret->timeout); ++ if (invalid) { ++ if (asprintf(err, "Invalid value '%s' with type 'integer' for key 'timeout': %s", YAJL_GET_NUMBER(val), strerror(-invalid)) < 0) ++ *err = safe_strdup("error allocating memory"); ++ free_defs_hook(ret); ++ return NULL; ++ } ++ } ++ } ++ if (ret->path == NULL) { ++ if (asprintf(err, "Required field '%s' not present", "path") < 0) ++ *err = safe_strdup("error allocating memory"); ++ free_defs_hook(ret); ++ return NULL; ++ } ++ ++ if (tree->type == yajl_t_object && (ctx->options & PARSE_OPTIONS_STRICT)) { ++ int i; ++ for (i = 0; i < tree->u.object.len; i++) ++ if (strcmp(tree->u.object.keys[i], "path") && ++ strcmp(tree->u.object.keys[i], "args") && ++ strcmp(tree->u.object.keys[i], "env") && ++ strcmp(tree->u.object.keys[i], "timeout")) { ++ if (ctx->stderr > 0) ++ fprintf(ctx->stderr, "WARNING: unknown key found: %s\n", tree->u.object.keys[i]); ++ } ++ } ++ return ret; ++} ++ ++void free_defs_hook(defs_hook *ptr) { ++ if (!ptr) ++ return; ++ free(ptr->path); ++ ptr->path = NULL; ++ if (ptr->args) { ++ size_t i; ++ for (i = 0; i < ptr->args_len; i++) { ++ if (ptr->args[i]) { ++ free(ptr->args[i]); ++ ptr->args[i] = NULL; ++ } ++ } ++ free(ptr->args); ++ ptr->args = NULL; ++ } ++ if (ptr->env) { ++ size_t i; ++ for (i = 0; i < ptr->env_len; i++) { ++ if (ptr->env[i]) { ++ free(ptr->env[i]); ++ ptr->env[i] = NULL; ++ } ++ } ++ free(ptr->env); ++ ptr->env = NULL; ++ } ++ free(ptr); ++} ++ ++yajl_gen_status gen_defs_hook(yajl_gen g, defs_hook *ptr, struct parser_context *ctx, parser_error *err) { ++ yajl_gen_status stat = yajl_gen_status_ok; ++ *err = 0; ++ stat = reformat_start_map(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr && ptr->path)) { ++ char *str = ""; ++ stat = reformat_map_key(g, "path", strlen("path")); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (ptr && ptr->path) { ++ str = ptr->path; ++ } ++ stat = reformat_string(g, str, strlen(str)); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr && ptr->args)) { ++ size_t len = 0, i; ++ stat = reformat_map_key(g, "args", strlen("args")); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (ptr && ptr->args) { ++ len = ptr->args_len; ++ } ++ if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) ++ yajl_gen_config(g, yajl_gen_beautify, 0); ++ stat = reformat_start_array(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ for (i = 0; i < len; i++) { ++ stat = reformat_string(g, ptr->args[i], strlen(ptr->args[i])); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ stat = reformat_end_array(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) ++ yajl_gen_config(g, yajl_gen_beautify, 1); ++ } ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr && ptr->env)) { ++ size_t len = 0, i; ++ stat = reformat_map_key(g, "env", strlen("env")); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (ptr && ptr->env) { ++ len = ptr->env_len; ++ } ++ if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) ++ yajl_gen_config(g, yajl_gen_beautify, 0); ++ stat = reformat_start_array(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ for (i = 0; i < len; i++) { ++ stat = reformat_string(g, ptr->env[i], strlen(ptr->env[i])); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ stat = reformat_end_array(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) ++ yajl_gen_config(g, yajl_gen_beautify, 1); ++ } ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr && ptr->timeout)) { ++ long long int num = 0; ++ stat = reformat_map_key(g, "timeout", strlen("timeout")); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (ptr && ptr->timeout) { ++ num = (long long int)ptr->timeout; ++ } ++ stat = reformat_int(g, num); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ stat = reformat_end_map(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ return yajl_gen_status_ok; ++} +diff --git a/src/lxc/json/defs.h b/src/lxc/json/defs.h +new file mode 100644 +index 0000000..0bbd8ac +--- /dev/null ++++ b/src/lxc/json/defs.h +@@ -0,0 +1,37 @@ ++// Generated from defs.json. Do not edit! ++#ifndef DEFS_SCHEMA_H ++#define DEFS_SCHEMA_H ++ ++#include ++#include ++#include "json_common.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef struct { ++ char *path; ++ ++ char **args; ++ size_t args_len; ++ ++ char **env; ++ size_t env_len; ++ ++ int timeout; ++ ++} ++defs_hook; ++ ++void free_defs_hook(defs_hook *ptr); ++ ++defs_hook *make_defs_hook(yajl_val tree, struct parser_context *ctx, parser_error *err); ++ ++yajl_gen_status gen_defs_hook(yajl_gen g, defs_hook *ptr, struct parser_context *ctx, parser_error *err); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/src/lxc/json/json_common.c b/src/lxc/json/json_common.c +new file mode 100755 +index 0000000..8b91844 +--- /dev/null ++++ b/src/lxc/json/json_common.c +@@ -0,0 +1,1196 @@ ++// Auto generated file. Do not edit! ++#define _GNU_SOURCE ++#include ++#include ++#include ++#include "json_common.h" ++ ++#define MAX_NUM_STR_LEN 21 ++ ++yajl_gen_status reformat_number(void *ctx, const char *str, size_t len) { ++ yajl_gen g = (yajl_gen) ctx; ++ return yajl_gen_number(g, str, len); ++} ++ ++yajl_gen_status reformat_uint(void *ctx, long long unsigned int num) { ++ char numstr[MAX_NUM_STR_LEN]; ++ int ret; ++ ++ ret = sprintf(numstr, "%llu", num); ++ if (ret < 0) { ++ return yajl_gen_in_error_state; ++ } ++ return reformat_number(ctx, (const char *)numstr, strlen(numstr)); ++} ++ ++yajl_gen_status reformat_int(void *ctx, long long int num) { ++ char numstr[MAX_NUM_STR_LEN]; ++ int ret; ++ ++ ret = sprintf(numstr, "%lld", num); ++ if (ret < 0) { ++ return yajl_gen_in_error_state; ++ } ++ return reformat_number(ctx, (const char *)numstr, strlen(numstr)); ++} ++ ++yajl_gen_status reformat_double(void *ctx, double num) { ++ yajl_gen g = (yajl_gen) ctx; ++ return yajl_gen_double(g, num); ++} ++ ++yajl_gen_status reformat_string(void *ctx, const char *str, size_t len) { ++ yajl_gen g = (yajl_gen) ctx; ++ return yajl_gen_string(g, (const unsigned char *)str, len); ++} ++ ++yajl_gen_status reformat_null(void *ctx) { ++ yajl_gen g = (yajl_gen) ctx; ++ return yajl_gen_null(g); ++} ++ ++yajl_gen_status reformat_bool(void *ctx, int boolean) { ++ yajl_gen g = (yajl_gen) ctx; ++ return yajl_gen_bool(g, boolean); ++} ++ ++yajl_gen_status reformat_map_key(void *ctx, const char *str, size_t len) { ++ yajl_gen g = (yajl_gen) ctx; ++ return yajl_gen_string(g, (const unsigned char *)str, len); ++} ++ ++yajl_gen_status reformat_start_map(void *ctx) { ++ yajl_gen g = (yajl_gen) ctx; ++ return yajl_gen_map_open(g); ++} ++ ++yajl_gen_status reformat_end_map(void *ctx) { ++ yajl_gen g = (yajl_gen) ctx; ++ return yajl_gen_map_close(g); ++} ++ ++yajl_gen_status reformat_start_array(void *ctx) { ++ yajl_gen g = (yajl_gen) ctx; ++ return yajl_gen_array_open(g); ++} ++ ++yajl_gen_status reformat_end_array(void *ctx) { ++ yajl_gen g = (yajl_gen) ctx; ++ return yajl_gen_array_close(g); ++} ++ ++bool json_gen_init(yajl_gen *g, struct parser_context *ctx) { ++ *g = yajl_gen_alloc(NULL); ++ if (NULL == *g) { ++ return false; ++ ++ } ++ yajl_gen_config(*g, yajl_gen_beautify, !(ctx->options & GEN_OPTIONS_SIMPLIFY)); ++ yajl_gen_config(*g, yajl_gen_validate_utf8, 1); ++ return true; ++} ++ ++yajl_val get_val(yajl_val tree, const char *name, yajl_type type) { ++ const char *path[] = { name, NULL }; ++ return yajl_tree_get(tree, path, type); ++} ++ ++void *safe_malloc(size_t size) { ++ void *ret = NULL; ++ if (size == 0) { ++ abort(); ++ } ++ ret = calloc(1, size); ++ if (ret == NULL) { ++ abort(); ++ } ++ return ret; ++} ++ ++int common_safe_double(const char *numstr, double *converted) { ++ char *err_str = NULL; ++ double d; ++ ++ if (!numstr) { ++ return -EINVAL; ++ } ++ ++ errno = 0; ++ d = strtod(numstr, &err_str); ++ if (errno > 0) { ++ return -errno; ++ } ++ ++ if (!err_str || err_str == numstr || *err_str != '\0') { ++ return -EINVAL; ++ } ++ ++ *converted = d; ++ return 0; ++} ++ ++int common_safe_uint8(const char *numstr, uint8_t *converted) { ++ char *err = NULL; ++ unsigned long int uli; ++ ++ if (!numstr) { ++ return -EINVAL; ++ } ++ ++ errno = 0; ++ uli = strtoul(numstr, &err, 0); ++ if (errno > 0) { ++ return -errno; ++ } ++ ++ if (!err || err == numstr || *err != '\0') { ++ return -EINVAL; ++ } ++ ++ if (uli > UINT8_MAX) { ++ return -ERANGE; ++ } ++ ++ *converted = (uint8_t)uli; ++ return 0; ++} ++ ++int common_safe_uint16(const char *numstr, uint16_t *converted) { ++ char *err = NULL; ++ unsigned long int uli; ++ ++ if (!numstr) { ++ return -EINVAL; ++ } ++ ++ errno = 0; ++ uli = strtoul(numstr, &err, 0); ++ if (errno > 0) { ++ return -errno; ++ } ++ ++ if (!err || err == numstr || *err != '\0') { ++ return -EINVAL; ++ } ++ ++ if (uli > UINT16_MAX) { ++ return -ERANGE; ++ } ++ ++ *converted = (uint16_t)uli; ++ return 0; ++} ++ ++int common_safe_uint32(const char *numstr, uint32_t *converted) { ++ char *err = NULL; ++ unsigned long long int ull; ++ ++ if (!numstr) { ++ return -EINVAL; ++ } ++ ++ errno = 0; ++ ull = strtoull(numstr, &err, 0); ++ if (errno > 0) { ++ return -errno; ++ } ++ ++ if (!err || err == numstr || *err != '\0') { ++ return -EINVAL; ++ } ++ ++ if (ull > UINT32_MAX) { ++ return -ERANGE; ++ } ++ ++ *converted = (uint32_t)ull; ++ return 0; ++} ++ ++int common_safe_uint64(const char *numstr, uint64_t *converted) { ++ char *err = NULL; ++ unsigned long long int ull; ++ ++ if (!numstr) { ++ return -EINVAL; ++ } ++ ++ errno = 0; ++ ull = strtoull(numstr, &err, 0); ++ if (errno > 0) { ++ return -errno; ++ } ++ ++ if (!err || err == numstr || *err != '\0') { ++ return -EINVAL; ++ } ++ ++ *converted = (uint64_t)ull; ++ return 0; ++} ++ ++int common_safe_uint(const char *numstr, unsigned int *converted) { ++ char *err = NULL; ++ unsigned long long int ull; ++ ++ if (!numstr) { ++ return -EINVAL; ++ } ++ ++ errno = 0; ++ ull = strtoull(numstr, &err, 0); ++ if (errno > 0) { ++ return -errno; ++ } ++ ++ if (!err || err == numstr || *err != '\0') { ++ return -EINVAL; ++ } ++ ++ if (ull > UINT_MAX) { ++ return -ERANGE; ++ } ++ ++ *converted = (unsigned int)ull; ++ return 0; ++} ++ ++int common_safe_int8(const char *numstr, int8_t *converted) { ++ char *err = NULL; ++ long int li; ++ ++ if (!numstr) { ++ return -EINVAL; ++ } ++ ++ errno = 0; ++ li = strtol(numstr, &err, 0); ++ if (errno > 0) { ++ return -errno; ++ } ++ ++ if (!err || err == numstr || *err != '\0') { ++ return -EINVAL; ++ } ++ ++ if (li > INT8_MAX || li < INT8_MIN) { ++ return -ERANGE; ++ } ++ ++ *converted = (int8_t)li; ++ return 0; ++} ++ ++int common_safe_int16(const char *numstr, int16_t *converted) { ++ char *err = NULL; ++ long int li; ++ ++ if (!numstr) { ++ return -EINVAL; ++ } ++ ++ errno = 0; ++ li = strtol(numstr, &err, 0); ++ if (errno > 0) { ++ return -errno; ++ } ++ ++ if (!err || err == numstr || *err != '\0') { ++ return -EINVAL; ++ } ++ ++ if (li > INT16_MAX || li < INT16_MIN) { ++ return -ERANGE; ++ } ++ ++ *converted = (int16_t)li; ++ return 0; ++} ++ ++int common_safe_int32(const char *numstr, int32_t *converted) { ++ char *err = NULL; ++ long long int lli; ++ ++ if (!numstr) { ++ return -EINVAL; ++ } ++ ++ errno = 0; ++ lli = strtol(numstr, &err, 0); ++ if (errno > 0) { ++ return -errno; ++ } ++ ++ if (!err || err == numstr || *err != '\0') { ++ return -EINVAL; ++ } ++ ++ if (lli > INT32_MAX || lli < INT32_MIN) { ++ return -ERANGE; ++ } ++ ++ *converted = (int32_t)lli; ++ return 0; ++} ++ ++int common_safe_int64(const char *numstr, int64_t *converted) { ++ char *err = NULL; ++ long long int lli; ++ ++ if (!numstr) { ++ return -EINVAL; ++ } ++ ++ errno = 0; ++ lli = strtoll(numstr, &err, 0); ++ if (errno > 0) { ++ return -errno; ++ } ++ ++ if (!err || err == numstr || *err != '\0') { ++ return -EINVAL; ++ } ++ ++ *converted = (int64_t)lli; ++ return 0; ++} ++ ++int common_safe_int(const char *numstr, int *converted) { ++ char *err = NULL; ++ long long int lli; ++ ++ if (!numstr) { ++ return -EINVAL; ++ } ++ ++ errno = 0; ++ lli = strtol(numstr, &err, 0); ++ if (errno > 0) { ++ return -errno; ++ } ++ ++ if (!err || err == numstr || *err != '\0') { ++ return -EINVAL; ++ } ++ ++ if (lli > INT_MAX || lli < INT_MIN) { ++ return -ERANGE; ++ } ++ ++ *converted = (int)lli; ++ return 0; ++} ++ ++char *safe_strdup(const char *src) ++{ ++ char *dst = NULL; ++ ++ if (!src) { ++ return NULL; ++ } ++ ++ dst = strdup(src); ++ if (!dst) { ++ abort(); ++ } ++ ++ return dst; ++} ++ ++ ++yajl_gen_status gen_json_map_int_int(void *ctx, json_map_int_int *map, struct parser_context *ptx, parser_error *err) { ++ yajl_gen_status stat = yajl_gen_status_ok; ++ yajl_gen g = (yajl_gen) ctx; ++ size_t len = 0, i = 0; ++ if (map) { ++ len = map->len; ++ } ++ if (!len && !(ptx->options & GEN_OPTIONS_SIMPLIFY)) { ++ yajl_gen_config(g, yajl_gen_beautify, 0); ++ } ++ stat = reformat_start_map(g); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ ++ } ++ for (i = 0; i < len; i++) { ++ char numstr[MAX_NUM_STR_LEN]; ++ int nret; ++ nret = sprintf(numstr, "%lld", (long long int)map->keys[i]); ++ if (nret < 0) { ++ if (!*err && asprintf(err, "Error to print string") < 0) { ++ *(err) = safe_strdup("error allocating memory"); ++ } ++ return yajl_gen_in_error_state; ++ } ++ stat = reformat_string(g, numstr, strlen(numstr)); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ stat = reformat_int(g, map->values[i]); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ } ++ ++ stat = reformat_end_map(g); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ if (!len && !(ptx->options & GEN_OPTIONS_SIMPLIFY)) { ++ yajl_gen_config(g, yajl_gen_beautify, 1); ++ } ++ return yajl_gen_status_ok; ++} ++ ++void free_json_map_int_int(json_map_int_int *map) { ++ if (map) { ++ size_t i; ++ for (i = 0; i < map->len; i++) { ++ // No need to free key for type int ++ // No need to free value for type int ++ } ++ free(map->keys); ++ map->keys = NULL; ++ free(map->values); ++ map->values = NULL; ++ free(map); ++ } ++} ++json_map_int_int *make_json_map_int_int(yajl_val src, struct parser_context *ctx, parser_error *err) { ++ json_map_int_int *ret = NULL; ++ if (src && YAJL_GET_OBJECT(src)) { ++ size_t i; ++ size_t len = YAJL_GET_OBJECT(src)->len; ++ ret = safe_malloc(sizeof(*ret)); ++ ret->len = len; ++ ret->keys = safe_malloc((len + 1) * sizeof(int)); ++ ret->values = safe_malloc((len + 1) * sizeof(int)); ++ for (i = 0; i < len; i++) { ++ const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; ++ yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; ++ ++ if (srckey) { ++ int invalid; ++ invalid = common_safe_int(srckey, &(ret->keys[i])); ++ if (invalid) { ++ if (!*err && asprintf(err, "Invalid key '%s' with type 'int': %s", srckey, strerror(-invalid)) < 0) { ++ *(err) = safe_strdup("error allocating memory"); ++ } ++ free_json_map_int_int(ret); ++ return NULL; ++ } ++ } ++ ++ if (srcval) { ++ int invalid; ++ if (!YAJL_IS_NUMBER(srcval)) { ++ if (!*err && asprintf(err, "Invalid value with type 'int' for key '%s'", srckey) < 0) { ++ *(err) = safe_strdup("error allocating memory"); ++ } ++ free_json_map_int_int(ret); ++ return NULL; ++ } ++ invalid = common_safe_int(YAJL_GET_NUMBER(srcval), &(ret->values[i])); ++ if (invalid) { ++ if (!*err && asprintf(err, "Invalid value with type 'int' for key '%s': %s", srckey, strerror(-invalid)) < 0) { ++ *(err) = safe_strdup("error allocating memory"); ++ } ++ free_json_map_int_int(ret); ++ return NULL; ++ } ++ } ++ } ++ } ++ return ret; ++} ++int append_json_map_int_int(json_map_int_int *map, int key, int val) { ++ size_t len; ++ int *keys; ++ int *vals; ++ ++ if (!map) { ++ return -1; ++ } ++ ++ if ((SIZE_MAX / sizeof(int) - 1) < map->len) { ++ return -1; ++ } ++ ++ len = map->len + 1; ++ keys = safe_malloc(len * sizeof(int)); ++ vals = safe_malloc(len * sizeof(int)); ++ ++ if (map->len) { ++ if (memcpy(keys, map->keys, map->len * sizeof(int)) != EOK) { ++ free(keys); ++ free(vals); ++ return -1; ++ } ++ if (memcpy(vals, map->values, map->len * sizeof(int)) != EOK) { ++ free(keys); ++ free(vals); ++ return -1; ++ } ++ } ++ free(map->keys); ++ map->keys = keys; ++ free(map->values); ++ map->values = vals; ++ map->keys[map->len] = key; ++ map->values[map->len] = val; ++ ++ map->len++; ++ return 0; ++} ++ ++yajl_gen_status gen_json_map_int_bool(void *ctx, json_map_int_bool *map, struct parser_context *ptx, parser_error *err) { ++ yajl_gen_status stat = yajl_gen_status_ok; ++ yajl_gen g = (yajl_gen) ctx; ++ size_t len = 0, i = 0; ++ if (map) { ++ len = map->len; ++ } ++ if (!len && !(ptx->options & GEN_OPTIONS_SIMPLIFY)) { ++ yajl_gen_config(g, yajl_gen_beautify, 0); ++ } ++ stat = reformat_start_map(g); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ ++ } ++ for (i = 0; i < len; i++) { ++ char numstr[MAX_NUM_STR_LEN]; ++ int nret; ++ nret = sprintf(numstr, "%lld", (long long int)map->keys[i]); ++ if (nret < 0) { ++ if (!*err && asprintf(err, "Error to print string") < 0) { ++ *(err) = safe_strdup("error allocating memory"); ++ } ++ return yajl_gen_in_error_state; ++ } ++ stat = reformat_string(g, numstr, strlen(numstr)); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ stat = reformat_bool(g, map->values[i]); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ } ++ ++ stat = reformat_end_map(g); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ if (!len && !(ptx->options & GEN_OPTIONS_SIMPLIFY)) { ++ yajl_gen_config(g, yajl_gen_beautify, 1); ++ } ++ return yajl_gen_status_ok; ++} ++ ++void free_json_map_int_bool(json_map_int_bool *map) { ++ if (map) { ++ size_t i; ++ for (i = 0; i < map->len; i++) { ++ // No need to free key for type int ++ // No need to free value for type bool ++ } ++ free(map->keys); ++ map->keys = NULL; ++ free(map->values); ++ map->values = NULL; ++ free(map); ++ } ++} ++json_map_int_bool *make_json_map_int_bool(yajl_val src, struct parser_context *ctx, parser_error *err) { ++ json_map_int_bool *ret = NULL; ++ if (src && YAJL_GET_OBJECT(src)) { ++ size_t i; ++ size_t len = YAJL_GET_OBJECT(src)->len; ++ ret = safe_malloc(sizeof(*ret)); ++ ret->len = len; ++ ret->keys = safe_malloc((len + 1) * sizeof(int)); ++ ret->values = safe_malloc((len + 1) * sizeof(bool)); ++ for (i = 0; i < len; i++) { ++ const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; ++ yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; ++ ++ if (srckey) { ++ int invalid; ++ invalid = common_safe_int(srckey, &(ret->keys[i])); ++ if (invalid) { ++ if (!*err && asprintf(err, "Invalid key '%s' with type 'int': %s", srckey, strerror(-invalid)) < 0) { ++ *(err) = safe_strdup("error allocating memory"); ++ } ++ free_json_map_int_bool(ret); ++ return NULL; ++ } ++ } ++ ++ if (srcval) { ++ if (YAJL_IS_TRUE(srcval)) { ++ ret->values[i] = true; ++ } else if (YAJL_IS_FALSE(srcval)) { ++ ret->values[i] = false; ++ } else { ++ if (!*err && asprintf(err, "Invalid value with type 'bool' for key '%s'", srckey) < 0) { ++ *(err) = safe_strdup("error allocating memory"); ++ } ++ free_json_map_int_bool(ret); ++ return NULL; ++ } ++ } ++ } ++ } ++ return ret; ++} ++int append_json_map_int_bool(json_map_int_bool *map, int key, bool val) { ++ size_t len; ++ int *keys; ++ bool *vals; ++ ++ if (!map) { ++ return -1; ++ } ++ ++ if ((SIZE_MAX / sizeof(int) - 1) < map->len || (SIZE_MAX / sizeof(bool) - 1) < map->len) { ++ return -1; ++ } ++ ++ len = map->len + 1; ++ keys = safe_malloc(len * sizeof(int)); ++ vals = safe_malloc(len * sizeof(bool)); ++ ++ if (map->len) { ++ if (memcpy(keys, map->keys, map->len * sizeof(int)) != EOK) { ++ free(keys); ++ free(vals); ++ return -1; ++ } ++ if (memcpy(vals, map->values, map->len * sizeof(bool)) != EOK) { ++ free(keys); ++ free(vals); ++ return -1; ++ } ++ } ++ free(map->keys); ++ map->keys = keys; ++ free(map->values); ++ map->values = vals; ++ map->keys[map->len] = key; ++ map->values[map->len] = val; ++ ++ map->len++; ++ return 0; ++} ++ ++yajl_gen_status gen_json_map_int_string(void *ctx, json_map_int_string *map, struct parser_context *ptx, parser_error *err) { ++ yajl_gen_status stat = yajl_gen_status_ok; ++ yajl_gen g = (yajl_gen) ctx; ++ size_t len = 0, i = 0; ++ if (map) { ++ len = map->len; ++ } ++ if (!len && !(ptx->options & GEN_OPTIONS_SIMPLIFY)) { ++ yajl_gen_config(g, yajl_gen_beautify, 0); ++ } ++ stat = reformat_start_map(g); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ ++ } ++ for (i = 0; i < len; i++) { ++ char numstr[MAX_NUM_STR_LEN]; ++ int nret; ++ nret = sprintf(numstr, "%lld", (long long int)map->keys[i]); ++ if (nret < 0) { ++ if (!*err && asprintf(err, "Error to print string") < 0) { ++ *(err) = safe_strdup("error allocating memory"); ++ } ++ return yajl_gen_in_error_state; ++ } ++ stat = reformat_string(g, numstr, strlen(numstr)); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ stat = reformat_string(g, map->values[i], strlen(map->values[i]));; ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ } ++ ++ stat = reformat_end_map(g); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ if (!len && !(ptx->options & GEN_OPTIONS_SIMPLIFY)) { ++ yajl_gen_config(g, yajl_gen_beautify, 1); ++ } ++ return yajl_gen_status_ok; ++} ++ ++void free_json_map_int_string(json_map_int_string *map) { ++ if (map) { ++ size_t i; ++ for (i = 0; i < map->len; i++) { ++ // No need to free key for type int ++ free(map->values[i]); ++ map->values[i] = NULL; ++ } ++ free(map->keys); ++ map->keys = NULL; ++ free(map->values); ++ map->values = NULL; ++ free(map); ++ } ++} ++json_map_int_string *make_json_map_int_string(yajl_val src, struct parser_context *ctx, parser_error *err) { ++ json_map_int_string *ret = NULL; ++ if (src && YAJL_GET_OBJECT(src)) { ++ size_t i; ++ size_t len = YAJL_GET_OBJECT(src)->len; ++ ret = safe_malloc(sizeof(*ret)); ++ ret->len = len; ++ ret->keys = safe_malloc((len + 1) * sizeof(int)); ++ ret->values = safe_malloc((len + 1) * sizeof(char *)); ++ for (i = 0; i < len; i++) { ++ const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; ++ yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; ++ ++ if (srckey) { ++ int invalid; ++ invalid = common_safe_int(srckey, &(ret->keys[i])); ++ if (invalid) { ++ if (!*err && asprintf(err, "Invalid key '%s' with type 'int': %s", srckey, strerror(-invalid)) < 0) { ++ *(err) = safe_strdup("error allocating memory"); ++ } ++ free_json_map_int_string(ret); ++ return NULL; ++ } ++ } ++ ++ if (srcval) { ++ if (!YAJL_IS_STRING(srcval)) { ++ if (!*err && asprintf(err, "Invalid value with type 'string' for key '%s'", srckey) < 0) { ++ *(err) = safe_strdup("error allocating memory"); ++ } ++ free_json_map_int_string(ret); ++ return NULL; ++ } ++ char *str = YAJL_GET_STRING(srcval); ++ ret->values[i] = safe_strdup(str ? str : ""); ++ } ++ } ++ } ++ return ret; ++} ++int append_json_map_int_string(json_map_int_string *map, int key, const char *val) { ++ size_t len; ++ int *keys; ++ char **vals; ++ ++ if (!map) { ++ return -1; ++ } ++ ++ if ((SIZE_MAX / sizeof(int) - 1) < map->len || (SIZE_MAX / sizeof(char *) - 1) < map->len) { ++ return -1; ++ } ++ ++ len = map->len + 1; ++ keys = safe_malloc(len * sizeof(int)); ++ vals = safe_malloc(len * sizeof(char *)); ++ ++ if (map->len) { ++ if (memcpy(keys, map->keys, map->len * sizeof(int)) != EOK) { ++ free(keys); ++ free(vals); ++ return -1; ++ } ++ if (memcpy(vals, map->values, map->len * sizeof(char *)) != EOK) { ++ free(keys); ++ free(vals); ++ return -1; ++ } ++ } ++ free(map->keys); ++ map->keys = keys; ++ free(map->values); ++ map->values = vals; ++ map->keys[map->len] = key; ++ map->values[map->len] = safe_strdup(val ? val : ""); ++ ++ map->len++; ++ return 0; ++} ++ ++yajl_gen_status gen_json_map_string_int(void *ctx, json_map_string_int *map, struct parser_context *ptx, parser_error *err) { ++ yajl_gen_status stat = yajl_gen_status_ok; ++ yajl_gen g = (yajl_gen) ctx; ++ size_t len = 0, i = 0; ++ if (map) { ++ len = map->len; ++ } ++ if (!len && !(ptx->options & GEN_OPTIONS_SIMPLIFY)) { ++ yajl_gen_config(g, yajl_gen_beautify, 0); ++ } ++ stat = reformat_start_map(g); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ ++ } ++ for (i = 0; i < len; i++) { ++ stat = reformat_string(g, map->keys[i], strlen(map->keys[i])); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ stat = reformat_int(g, map->values[i]); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ } ++ ++ stat = reformat_end_map(g); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ if (!len && !(ptx->options & GEN_OPTIONS_SIMPLIFY)) { ++ yajl_gen_config(g, yajl_gen_beautify, 1); ++ } ++ return yajl_gen_status_ok; ++} ++ ++void free_json_map_string_int(json_map_string_int *map) { ++ if (map) { ++ size_t i; ++ for (i = 0; i < map->len; i++) { ++ free(map->keys[i]); ++ map->keys[i] = NULL; ++ // No need to free value for type int ++ } ++ free(map->keys); ++ map->keys = NULL; ++ free(map->values); ++ map->values = NULL; ++ free(map); ++ } ++} ++json_map_string_int *make_json_map_string_int(yajl_val src, struct parser_context *ctx, parser_error *err) { ++ json_map_string_int *ret = NULL; ++ if (src && YAJL_GET_OBJECT(src)) { ++ size_t i; ++ size_t len = YAJL_GET_OBJECT(src)->len; ++ ret = safe_malloc(sizeof(*ret)); ++ ret->len = len; ++ ret->keys = safe_malloc((len + 1) * sizeof(char *)); ++ ret->values = safe_malloc((len + 1) * sizeof(int)); ++ for (i = 0; i < len; i++) { ++ const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; ++ yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; ++ ret->keys[i] = safe_strdup(srckey ? srckey : ""); ++ ++ if (srcval) { ++ int invalid; ++ if (!YAJL_IS_NUMBER(srcval)) { ++ if (!*err && asprintf(err, "Invalid value with type 'int' for key '%s'", srckey) < 0) { ++ *(err) = safe_strdup("error allocating memory"); ++ } ++ free_json_map_string_int(ret); ++ return NULL; ++ } ++ invalid = common_safe_int(YAJL_GET_NUMBER(srcval), &(ret->values[i])); ++ if (invalid) { ++ if (!*err && asprintf(err, "Invalid value with type 'int' for key '%s': %s", srckey, strerror(-invalid)) < 0) { ++ *(err) = safe_strdup("error allocating memory"); ++ } ++ free_json_map_string_int(ret); ++ return NULL; ++ } ++ } ++ } ++ } ++ return ret; ++} ++int append_json_map_string_int(json_map_string_int *map, const char *key, int val) { ++ size_t len; ++ char **keys; ++ int *vals; ++ ++ if (!map) { ++ return -1; ++ } ++ ++ if ((SIZE_MAX / sizeof(char *) - 1) < map->len || (SIZE_MAX / sizeof(int) - 1) < map->len) { ++ return -1; ++ } ++ ++ len = map->len + 1; ++ keys = safe_malloc(len * sizeof(char *)); ++ vals = safe_malloc(len * sizeof(int)); ++ ++ if (map->len) { ++ if (memcpy(keys, map->keys, map->len * sizeof(char *)) != EOK) { ++ free(keys); ++ free(vals); ++ return -1; ++ } ++ if (memcpy(vals, map->values, map->len * sizeof(int)) != EOK) { ++ free(keys); ++ free(vals); ++ return -1; ++ } ++ } ++ free(map->keys); ++ map->keys = keys; ++ free(map->values); ++ map->values = vals; ++ map->keys[map->len] = safe_strdup(key ? key : ""); ++ map->values[map->len] = val; ++ ++ map->len++; ++ return 0; ++} ++ ++yajl_gen_status gen_json_map_string_bool(void *ctx, json_map_string_bool *map, struct parser_context *ptx, parser_error *err) { ++ yajl_gen_status stat = yajl_gen_status_ok; ++ yajl_gen g = (yajl_gen) ctx; ++ size_t len = 0, i = 0; ++ if (map) { ++ len = map->len; ++ } ++ if (!len && !(ptx->options & GEN_OPTIONS_SIMPLIFY)) { ++ yajl_gen_config(g, yajl_gen_beautify, 0); ++ } ++ stat = reformat_start_map(g); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ ++ } ++ for (i = 0; i < len; i++) { ++ stat = reformat_string(g, map->keys[i], strlen(map->keys[i])); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ stat = reformat_bool(g, map->values[i]); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ } ++ ++ stat = reformat_end_map(g); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ if (!len && !(ptx->options & GEN_OPTIONS_SIMPLIFY)) { ++ yajl_gen_config(g, yajl_gen_beautify, 1); ++ } ++ return yajl_gen_status_ok; ++} ++ ++void free_json_map_string_bool(json_map_string_bool *map) { ++ if (map) { ++ size_t i; ++ for (i = 0; i < map->len; i++) { ++ free(map->keys[i]); ++ map->keys[i] = NULL; ++ // No need to free value for type bool ++ } ++ free(map->keys); ++ map->keys = NULL; ++ free(map->values); ++ map->values = NULL; ++ free(map); ++ } ++} ++json_map_string_bool *make_json_map_string_bool(yajl_val src, struct parser_context *ctx, parser_error *err) { ++ json_map_string_bool *ret = NULL; ++ if (src && YAJL_GET_OBJECT(src)) { ++ size_t i; ++ size_t len = YAJL_GET_OBJECT(src)->len; ++ ret = safe_malloc(sizeof(*ret)); ++ ret->len = len; ++ ret->keys = safe_malloc((len + 1) * sizeof(char *)); ++ ret->values = safe_malloc((len + 1) * sizeof(bool)); ++ for (i = 0; i < len; i++) { ++ const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; ++ yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; ++ ret->keys[i] = safe_strdup(srckey ? srckey : ""); ++ ++ if (srcval) { ++ if (YAJL_IS_TRUE(srcval)) { ++ ret->values[i] = true; ++ } else if (YAJL_IS_FALSE(srcval)) { ++ ret->values[i] = false; ++ } else { ++ if (!*err && asprintf(err, "Invalid value with type 'bool' for key '%s'", srckey) < 0) { ++ *(err) = safe_strdup("error allocating memory"); ++ } ++ free_json_map_string_bool(ret); ++ return NULL; ++ } ++ } ++ } ++ } ++ return ret; ++} ++int append_json_map_string_bool(json_map_string_bool *map, const char *key, bool val) { ++ size_t len; ++ char **keys; ++ bool *vals; ++ ++ if (!map) { ++ return -1; ++ } ++ ++ if ((SIZE_MAX / sizeof(char *) - 1) < map->len || (SIZE_MAX / sizeof(bool) - 1) < map->len) { ++ return -1; ++ } ++ ++ len = map->len + 1; ++ keys = safe_malloc(len * sizeof(char *)); ++ vals = safe_malloc(len * sizeof(bool)); ++ ++ if (map->len) { ++ if (memcpy(keys, map->keys, map->len * sizeof(char *)) != EOK) { ++ free(keys); ++ free(vals); ++ return -1; ++ } ++ if (memcpy(vals, map->values, map->len * sizeof(bool)) != EOK) { ++ free(keys); ++ free(vals); ++ return -1; ++ } ++ } ++ free(map->keys); ++ map->keys = keys; ++ free(map->values); ++ map->values = vals; ++ map->keys[map->len] = safe_strdup(key ? key : ""); ++ map->values[map->len] = val; ++ ++ map->len++; ++ return 0; ++} ++ ++yajl_gen_status gen_json_map_string_string(void *ctx, json_map_string_string *map, struct parser_context *ptx, parser_error *err) { ++ yajl_gen_status stat = yajl_gen_status_ok; ++ yajl_gen g = (yajl_gen) ctx; ++ size_t len = 0, i = 0; ++ if (map) { ++ len = map->len; ++ } ++ if (!len && !(ptx->options & GEN_OPTIONS_SIMPLIFY)) { ++ yajl_gen_config(g, yajl_gen_beautify, 0); ++ } ++ stat = reformat_start_map(g); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ ++ } ++ for (i = 0; i < len; i++) { ++ stat = reformat_string(g, map->keys[i], strlen(map->keys[i])); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ stat = reformat_string(g, map->values[i], strlen(map->values[i]));; ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ } ++ ++ stat = reformat_end_map(g); ++ if (yajl_gen_status_ok != stat) { ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ if (!len && !(ptx->options & GEN_OPTIONS_SIMPLIFY)) { ++ yajl_gen_config(g, yajl_gen_beautify, 1); ++ } ++ return yajl_gen_status_ok; ++} ++ ++void free_json_map_string_string(json_map_string_string *map) { ++ if (map) { ++ size_t i; ++ for (i = 0; i < map->len; i++) { ++ free(map->keys[i]); ++ map->keys[i] = NULL; ++ free(map->values[i]); ++ map->values[i] = NULL; ++ } ++ free(map->keys); ++ map->keys = NULL; ++ free(map->values); ++ map->values = NULL; ++ free(map); ++ } ++} ++json_map_string_string *make_json_map_string_string(yajl_val src, struct parser_context *ctx, parser_error *err) { ++ json_map_string_string *ret = NULL; ++ if (src && YAJL_GET_OBJECT(src)) { ++ size_t i; ++ size_t len = YAJL_GET_OBJECT(src)->len; ++ ret = safe_malloc(sizeof(*ret)); ++ ret->len = len; ++ ret->keys = safe_malloc((len + 1) * sizeof(char *)); ++ ret->values = safe_malloc((len + 1) * sizeof(char *)); ++ for (i = 0; i < len; i++) { ++ const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; ++ yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; ++ ret->keys[i] = safe_strdup(srckey ? srckey : ""); ++ ++ if (srcval) { ++ if (!YAJL_IS_STRING(srcval)) { ++ if (!*err && asprintf(err, "Invalid value with type 'string' for key '%s'", srckey) < 0) { ++ *(err) = safe_strdup("error allocating memory"); ++ } ++ free_json_map_string_string(ret); ++ return NULL; ++ } ++ char *str = YAJL_GET_STRING(srcval); ++ ret->values[i] = safe_strdup(str ? str : ""); ++ } ++ } ++ } ++ return ret; ++} ++int append_json_map_string_string(json_map_string_string *map, const char *key, const char *val) { ++ size_t len; ++ char **keys; ++ char **vals; ++ ++ if (!map) { ++ return -1; ++ } ++ ++ if ((SIZE_MAX / sizeof(char *) - 1) < map->len) { ++ return -1; ++ } ++ ++ len = map->len + 1; ++ keys = safe_malloc(len * sizeof(char *)); ++ vals = safe_malloc(len * sizeof(char *)); ++ ++ if (map->len) { ++ if (memcpy(keys, map->keys, map->len * sizeof(char *)) != EOK) { ++ free(keys); ++ free(vals); ++ return -1; ++ } ++ if (memcpy(vals, map->values, map->len * sizeof(char *)) != EOK) { ++ free(keys); ++ free(vals); ++ return -1; ++ } ++ } ++ free(map->keys); ++ map->keys = keys; ++ free(map->values); ++ map->values = vals; ++ map->keys[map->len] = safe_strdup(key ? key : ""); ++ map->values[map->len] = safe_strdup(val ? val : ""); ++ ++ map->len++; ++ return 0; ++} +diff --git a/src/lxc/json/json_common.h b/src/lxc/json/json_common.h +new file mode 100755 +index 0000000..904fe3c +--- /dev/null ++++ b/src/lxc/json/json_common.h +@@ -0,0 +1,185 @@ ++// Auto generated file. Do not edit! ++#ifndef _JSON_COMMON_H ++#define _JSON_COMMON_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "securec.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++# undef linux ++ ++//options to report error if there is unknown key found in json ++# define PARSE_OPTIONS_STRICT 0x01 ++//options to generate all key and value ++# define GEN_OPTIONS_ALLKEYVALUE 0x02 ++//options to generate simplify(no indent) json string ++# define GEN_OPTIONS_SIMPLIFY 0x04 ++ ++#define GEN_SET_ERROR_AND_RETURN(stat, err) { \ ++ if (!*(err)) {\ ++ if (asprintf(err, "%s: %s: %d: error generating json, errcode: %d", __FILE__, __func__, __LINE__, stat) < 0) { \ ++ *(err) = safe_strdup("error allocating memory"); \ ++ } \ ++ }\ ++ return stat; \ ++ } ++ ++typedef char *parser_error; ++ ++struct parser_context { ++ unsigned int options; ++ FILE *stderr; ++}; ++ ++yajl_gen_status reformat_number(void *ctx, const char *str, size_t len); ++ ++yajl_gen_status reformat_uint(void *ctx, long long unsigned int num); ++ ++yajl_gen_status reformat_int(void *ctx, long long int num); ++ ++yajl_gen_status reformat_double(void *ctx, double num); ++ ++yajl_gen_status reformat_string(void *ctx, const char *str, size_t len); ++ ++yajl_gen_status reformat_null(void *ctx); ++ ++yajl_gen_status reformat_bool(void *ctx, int boolean); ++ ++yajl_gen_status reformat_map_key(void *ctx, const char *str, size_t len); ++ ++yajl_gen_status reformat_start_map(void *ctx); ++ ++yajl_gen_status reformat_end_map(void *ctx); ++ ++yajl_gen_status reformat_start_array(void *ctx); ++ ++yajl_gen_status reformat_end_array(void *ctx); ++ ++bool json_gen_init(yajl_gen *g, struct parser_context *ctx); ++ ++yajl_val get_val(yajl_val tree, const char *name, yajl_type type); ++ ++void *safe_malloc(size_t size); ++ ++int common_safe_double(const char *numstr, double *converted); ++ ++int common_safe_uint8(const char *numstr, uint8_t *converted); ++ ++int common_safe_uint16(const char *numstr, uint16_t *converted); ++ ++int common_safe_uint32(const char *numstr, uint32_t *converted); ++ ++int common_safe_uint64(const char *numstr, uint64_t *converted); ++ ++int common_safe_uint(const char *numstr, unsigned int *converted); ++ ++int common_safe_int8(const char *numstr, int8_t *converted); ++ ++int common_safe_int16(const char *numstr, int16_t *converted); ++ ++int common_safe_int32(const char *numstr, int32_t *converted); ++ ++int common_safe_int64(const char *numstr, int64_t *converted); ++ ++int common_safe_int(const char *numstr, int *converted); ++ ++char *safe_strdup(const char *src); ++ ++typedef struct { ++ int *keys; ++ int *values; ++ size_t len; ++} json_map_int_int; ++ ++void free_json_map_int_int(json_map_int_int *map); ++ ++json_map_int_int *make_json_map_int_int(yajl_val src, struct parser_context *ctx, parser_error *err); ++ ++yajl_gen_status gen_json_map_int_int(void *ctx, json_map_int_int *map, struct parser_context *ptx, parser_error *err); ++ ++int append_json_map_int_int(json_map_int_int *map, int key, int val); ++ ++typedef struct { ++ int *keys; ++ bool *values; ++ size_t len; ++} json_map_int_bool; ++ ++void free_json_map_int_bool(json_map_int_bool *map); ++ ++json_map_int_bool *make_json_map_int_bool(yajl_val src, struct parser_context *ctx, parser_error *err); ++ ++yajl_gen_status gen_json_map_int_bool(void *ctx, json_map_int_bool *map, struct parser_context *ptx, parser_error *err); ++ ++int append_json_map_int_bool(json_map_int_bool *map, int key, bool val); ++ ++typedef struct { ++ int *keys; ++ char **values; ++ size_t len; ++} json_map_int_string; ++ ++void free_json_map_int_string(json_map_int_string *map); ++ ++json_map_int_string *make_json_map_int_string(yajl_val src, struct parser_context *ctx, parser_error *err); ++ ++yajl_gen_status gen_json_map_int_string(void *ctx, json_map_int_string *map, struct parser_context *ptx, parser_error *err); ++ ++int append_json_map_int_string(json_map_int_string *map, int key, const char *val); ++ ++typedef struct { ++ char **keys; ++ int *values; ++ size_t len; ++} json_map_string_int; ++ ++void free_json_map_string_int(json_map_string_int *map); ++ ++json_map_string_int *make_json_map_string_int(yajl_val src, struct parser_context *ctx, parser_error *err); ++ ++yajl_gen_status gen_json_map_string_int(void *ctx, json_map_string_int *map, struct parser_context *ptx, parser_error *err); ++ ++int append_json_map_string_int(json_map_string_int *map, const char *key, int val); ++ ++typedef struct { ++ char **keys; ++ bool *values; ++ size_t len; ++} json_map_string_bool; ++ ++void free_json_map_string_bool(json_map_string_bool *map); ++ ++json_map_string_bool *make_json_map_string_bool(yajl_val src, struct parser_context *ctx, parser_error *err); ++ ++yajl_gen_status gen_json_map_string_bool(void *ctx, json_map_string_bool *map, struct parser_context *ptx, parser_error *err); ++ ++int append_json_map_string_bool(json_map_string_bool *map, const char *key, bool val); ++ ++typedef struct { ++ char **keys; ++ char **values; ++ size_t len; ++} json_map_string_string; ++ ++void free_json_map_string_string(json_map_string_string *map); ++ ++json_map_string_string *make_json_map_string_string(yajl_val src, struct parser_context *ctx, parser_error *err); ++ ++yajl_gen_status gen_json_map_string_string(void *ctx, json_map_string_string *map, struct parser_context *ptx, parser_error *err); ++ ++int append_json_map_string_string(json_map_string_string *map, const char *key, const char *val); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +\ No newline at end of file +diff --git a/src/lxc/json/oci_runtime_hooks.c b/src/lxc/json/oci_runtime_hooks.c +new file mode 100644 +index 0000000..3aa134e +--- /dev/null ++++ b/src/lxc/json/oci_runtime_hooks.c +@@ -0,0 +1,53 @@ ++/****************************************************************************** ++ * Copyright (C), 1988-1999, Huawei Tech. Co., Ltd. ++ * FileName: oci_runtime_hooks.c ++ * Author: maoweiyong Version: 0.1 Date: 2018-11-07 ++ * Explanation: provide oci runtime hooks functions ++ ******************************************************************************/ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE ++#endif ++#include ++#include "oci_runtime_hooks.h" ++ ++#include "log.h" ++#include "utils.h" ++ ++#define PARSE_ERR_BUFFER_SIZE 1024 ++ ++oci_runtime_spec_hooks *oci_runtime_spec_hooks_parse_file(const char *filename, ++ struct parser_context *ctx, parser_error *err) ++{ ++ yajl_val tree; ++ size_t filesize; ++ ++ if (!filename || !err) { ++ return NULL; ++ } ++ *err = NULL; ++ struct parser_context tmp_ctx; ++ if (!ctx) { ++ ctx = &tmp_ctx; ++ memset(&tmp_ctx, 0, sizeof(tmp_ctx)); ++ } ++ char *content = read_file(filename, &filesize); ++ char errbuf[PARSE_ERR_BUFFER_SIZE]; ++ if (content == NULL) { ++ if (asprintf(err, "cannot read the file: %s", filename) < 0) { ++ *err = strdup("error allocating memory"); ++ } ++ return NULL; ++ } ++ tree = yajl_tree_parse(content, errbuf, sizeof(errbuf)); ++ free(content); ++ if (tree == NULL) { ++ if (asprintf(err, "cannot parse the file: %s", errbuf) < 0) { ++ *err = strdup("error allocating memory"); ++ } ++ return NULL; ++ } ++ oci_runtime_spec_hooks *ptr = make_oci_runtime_spec_hooks(tree, ctx, ++ err); ++ yajl_tree_free(tree); ++ return ptr; ++} +diff --git a/src/lxc/json/oci_runtime_hooks.h b/src/lxc/json/oci_runtime_hooks.h +new file mode 100644 +index 0000000..bf570c9 +--- /dev/null ++++ b/src/lxc/json/oci_runtime_hooks.h +@@ -0,0 +1,15 @@ ++/****************************************************************************** ++ * Copyright (C), 1988-1999, Huawei Tech. Co., Ltd. ++ * FileName: oci_runtime_hooks.h ++ * Author: tanyifeng Version: 0.1 Date: 2018-11-08 ++ * Explanation: provide container oci runtime hooks function definition ++ ******************************************************************************/ ++#ifndef _CONTAINER_HOOKS_H ++# define _CONTAINER_HOOKS_H ++ ++# include "oci_runtime_spec.h" ++ ++oci_runtime_spec_hooks *oci_runtime_spec_hooks_parse_file(const char *filename, ++ struct parser_context *ctx, parser_error *err); ++ ++#endif +diff --git a/src/lxc/json/oci_runtime_spec.c b/src/lxc/json/oci_runtime_spec.c +new file mode 100644 +index 0000000..1f6073c +--- /dev/null ++++ b/src/lxc/json/oci_runtime_spec.c +@@ -0,0 +1,196 @@ ++// Generated from spec.json. Do not edit! ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE ++#endif ++#include ++#include ++#include "securec.h" ++#include "oci_runtime_spec.h" ++ ++oci_runtime_spec_hooks *make_oci_runtime_spec_hooks(yajl_val tree, struct parser_context *ctx, parser_error *err) { ++ oci_runtime_spec_hooks *ret = NULL; ++ *err = 0; ++ if (tree == NULL) ++ return ret; ++ ret = safe_malloc(sizeof(*ret)); ++ { ++ yajl_val tmp = get_val(tree, "prestart", yajl_t_array); ++ if (tmp && YAJL_GET_ARRAY(tmp)) { ++ size_t i; ++ ret->prestart_len = YAJL_GET_ARRAY(tmp)->len; ++ ret->prestart = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) * sizeof(*ret->prestart)); ++ for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) { ++ yajl_val val = YAJL_GET_ARRAY(tmp)->values[i]; ++ ret->prestart[i] = make_defs_hook(val, ctx, err); ++ if (ret->prestart[i] == NULL) { ++ free_oci_runtime_spec_hooks(ret); ++ return NULL; ++ } ++ } ++ } ++ } ++ { ++ yajl_val tmp = get_val(tree, "poststart", yajl_t_array); ++ if (tmp && YAJL_GET_ARRAY(tmp)) { ++ size_t i; ++ ret->poststart_len = YAJL_GET_ARRAY(tmp)->len; ++ ret->poststart = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) * sizeof(*ret->poststart)); ++ for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) { ++ yajl_val val = YAJL_GET_ARRAY(tmp)->values[i]; ++ ret->poststart[i] = make_defs_hook(val, ctx, err); ++ if (ret->poststart[i] == NULL) { ++ free_oci_runtime_spec_hooks(ret); ++ return NULL; ++ } ++ } ++ } ++ } ++ { ++ yajl_val tmp = get_val(tree, "poststop", yajl_t_array); ++ if (tmp && YAJL_GET_ARRAY(tmp)) { ++ size_t i; ++ ret->poststop_len = YAJL_GET_ARRAY(tmp)->len; ++ ret->poststop = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) * sizeof(*ret->poststop)); ++ for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) { ++ yajl_val val = YAJL_GET_ARRAY(tmp)->values[i]; ++ ret->poststop[i] = make_defs_hook(val, ctx, err); ++ if (ret->poststop[i] == NULL) { ++ free_oci_runtime_spec_hooks(ret); ++ return NULL; ++ } ++ } ++ } ++ } ++ ++ if (tree->type == yajl_t_object && (ctx->options & PARSE_OPTIONS_STRICT)) { ++ int i; ++ for (i = 0; i < tree->u.object.len; i++) ++ if (strcmp(tree->u.object.keys[i], "prestart") && ++ strcmp(tree->u.object.keys[i], "poststart") && ++ strcmp(tree->u.object.keys[i], "poststop")) { ++ if (ctx->stderr > 0) ++ fprintf(ctx->stderr, "WARNING: unknown key found: %s\n", tree->u.object.keys[i]); ++ } ++ } ++ return ret; ++} ++ ++void free_oci_runtime_spec_hooks(oci_runtime_spec_hooks *ptr) { ++ if (!ptr) ++ return; ++ if (ptr->prestart) { ++ size_t i; ++ for (i = 0; i < ptr->prestart_len; i++) ++ if (ptr->prestart[i]) { ++ free_defs_hook(ptr->prestart[i]); ++ ptr->prestart[i] = NULL; ++ } ++ free(ptr->prestart); ++ ptr->prestart = NULL; ++ } ++ if (ptr->poststart) { ++ size_t i; ++ for (i = 0; i < ptr->poststart_len; i++) ++ if (ptr->poststart[i]) { ++ free_defs_hook(ptr->poststart[i]); ++ ptr->poststart[i] = NULL; ++ } ++ free(ptr->poststart); ++ ptr->poststart = NULL; ++ } ++ if (ptr->poststop) { ++ size_t i; ++ for (i = 0; i < ptr->poststop_len; i++) ++ if (ptr->poststop[i]) { ++ free_defs_hook(ptr->poststop[i]); ++ ptr->poststop[i] = NULL; ++ } ++ free(ptr->poststop); ++ ptr->poststop = NULL; ++ } ++ free(ptr); ++} ++ ++yajl_gen_status gen_oci_runtime_spec_hooks(yajl_gen g, oci_runtime_spec_hooks *ptr, struct parser_context *ctx, parser_error *err) { ++ yajl_gen_status stat = yajl_gen_status_ok; ++ *err = 0; ++ stat = reformat_start_map(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr && ptr->prestart)) { ++ size_t len = 0, i; ++ stat = reformat_map_key(g, "prestart", strlen("prestart")); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (ptr && ptr->prestart) { ++ len = ptr->prestart_len; ++ } ++ if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) ++ yajl_gen_config(g, yajl_gen_beautify, 0); ++ stat = reformat_start_array(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ for (i = 0; i < len; i++) { ++ stat = gen_defs_hook(g, ptr->prestart[i], ctx, err); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ stat = reformat_end_array(g); ++ if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) ++ yajl_gen_config(g, yajl_gen_beautify, 1); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr && ptr->poststart)) { ++ size_t len = 0, i; ++ stat = reformat_map_key(g, "poststart", strlen("poststart")); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (ptr && ptr->poststart) { ++ len = ptr->poststart_len; ++ } ++ if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) ++ yajl_gen_config(g, yajl_gen_beautify, 0); ++ stat = reformat_start_array(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ for (i = 0; i < len; i++) { ++ stat = gen_defs_hook(g, ptr->poststart[i], ctx, err); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ stat = reformat_end_array(g); ++ if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) ++ yajl_gen_config(g, yajl_gen_beautify, 1); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr && ptr->poststop)) { ++ size_t len = 0, i; ++ stat = reformat_map_key(g, "poststop", strlen("poststop")); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (ptr && ptr->poststop) { ++ len = ptr->poststop_len; ++ } ++ if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) ++ yajl_gen_config(g, yajl_gen_beautify, 0); ++ stat = reformat_start_array(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ for (i = 0; i < len; i++) { ++ stat = gen_defs_hook(g, ptr->poststop[i], ctx, err); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ stat = reformat_end_array(g); ++ if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) ++ yajl_gen_config(g, yajl_gen_beautify, 1); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ stat = reformat_end_map(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ return yajl_gen_status_ok; ++} +diff --git a/src/lxc/json/oci_runtime_spec.h b/src/lxc/json/oci_runtime_spec.h +new file mode 100644 +index 0000000..ef3f161 +--- /dev/null ++++ b/src/lxc/json/oci_runtime_spec.h +@@ -0,0 +1,37 @@ ++// Generated from spec.json. Do not edit! ++#ifndef OCI_RUNTIME_SPEC_SCHEMA_H ++#define OCI_RUNTIME_SPEC_SCHEMA_H ++ ++#include ++#include ++#include "json_common.h" ++#include "defs.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef struct { ++ defs_hook **prestart; ++ size_t prestart_len; ++ ++ defs_hook **poststart; ++ size_t poststart_len; ++ ++ defs_hook **poststop; ++ size_t poststop_len; ++ ++} ++oci_runtime_spec_hooks; ++ ++void free_oci_runtime_spec_hooks(oci_runtime_spec_hooks *ptr); ++ ++oci_runtime_spec_hooks *make_oci_runtime_spec_hooks(yajl_val tree, struct parser_context *ctx, parser_error *err); ++ ++yajl_gen_status gen_oci_runtime_spec_hooks(yajl_gen g, oci_runtime_spec_hooks *ptr, struct parser_context *ctx, parser_error *err); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/src/lxc/json/read-file.c b/src/lxc/json/read-file.c +new file mode 100644 +index 0000000..ad0eda1 +--- /dev/null ++++ b/src/lxc/json/read-file.c +@@ -0,0 +1,94 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "read-file.h" ++ ++#ifndef O_CLOEXEC ++#define O_CLOEXEC 02000000 ++#endif ++ ++char *fread_file(FILE *stream, size_t *length) ++{ ++ char *buf = NULL, *tmpbuf = NULL; ++ size_t off = 0; ++ ++ while (1) { ++ size_t ret, newsize; ++ ++ newsize = off + BUFSIZ + 1; ++ tmpbuf = (char *)calloc(1, newsize); ++ if (tmpbuf == NULL) { ++ goto out; ++ } ++ ++ if (buf) { ++ memcpy(tmpbuf, buf, off); ++ ++ memset(buf, 0, off); ++ ++ free(buf); ++ } ++ ++ buf = tmpbuf; ++ ret = fread(buf + off, 1, BUFSIZ, stream); ++ if (!ret && ferror(stream)) { ++ tmpbuf = NULL; ++ goto out; ++ } ++ if (ret < BUFSIZ || feof(stream)) { ++ *length = off + ret + 1; ++ buf[*length - 1] = '\0'; ++ return buf; ++ } ++ off += BUFSIZ; ++ } ++out: ++ if (buf) { ++ free(buf); ++ } ++ if (tmpbuf) { ++ free(tmpbuf); ++ } ++ return NULL; ++ ++} ++ ++char *read_file(const char *path, size_t *length) ++{ ++ char *buf = NULL; ++ char rpath[PATH_MAX + 1] = {0}; ++ int fd, tmperrno; ++ FILE *fp; ++ ++ if (!path || !length) { ++ return NULL; ++ } ++ ++ if (strlen(path) > PATH_MAX || NULL == realpath(path, rpath)) { ++ return NULL; ++ } ++ ++ fd = open(rpath, O_RDONLY | O_CLOEXEC, 0640); ++ if (fd < 0) { ++ return NULL; ++ } ++ ++ fp = fdopen(fd, "r"); ++ tmperrno = errno; ++ if (!fp) { ++ close(fd); ++ errno = tmperrno; ++ return NULL; ++ } ++ ++ buf = fread_file(fp, length); ++ fclose(fp); ++ return buf; ++} +diff --git a/src/lxc/json/read-file.h b/src/lxc/json/read-file.h +new file mode 100644 +index 0000000..5d6e0eb +--- /dev/null ++++ b/src/lxc/json/read-file.h +@@ -0,0 +1,11 @@ ++#ifndef READ_FILE_H ++#define READ_FILE_H ++ ++#include ++#include ++ ++extern char *fread_file(FILE *stream, size_t *length); ++ ++extern char *read_file(const char *path, size_t *length); ++ ++#endif +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index 31f4819..68134d8 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -271,6 +271,9 @@ static void lxc_container_free(struct lxc_container *c) + free(c->configfile); + c->configfile = NULL; + ++ free(c->ocihookfile); ++ c->ocihookfile = NULL; ++ + free(c->error_string); + c->error_string = NULL; + +@@ -612,6 +615,30 @@ static bool load_config_locked(struct lxc_container *c, const char *fname) + return true; + } + ++static bool load_ocihooks_locked(struct lxc_container *c) ++{ ++ parser_error err = NULL; ++ oci_runtime_spec_hooks *hooks; ++ ++ if (!c->lxc_conf) ++ c->lxc_conf = lxc_conf_init(); ++ ++ if (!c->lxc_conf) ++ return false; ++ ++ hooks = oci_runtime_spec_hooks_parse_file(c->ocihookfile, NULL, &err); ++ if (!hooks) { ++ fprintf(stderr, "parse oci hooks config failed: %s\n", err); ++ free(err); ++ return true; ++ } ++ c->lxc_conf->ocihooks = hooks; ++ ++ if (err) ++ free(err); ++ return true; ++} ++ + static bool do_lxcapi_load_config(struct lxc_container *c, const char *alt_file) + { + int lret; +@@ -645,6 +672,9 @@ static bool do_lxcapi_load_config(struct lxc_container *c, const char *alt_file) + + ret = load_config_locked(c, fname); + ++ if (ret && file_exists(c->ocihookfile)) ++ ret = load_ocihooks_locked(c); ++ + if (need_disklock) + container_disk_unlock(c); + else +@@ -3242,6 +3272,37 @@ static bool set_config_filename(struct lxc_container *c) + return true; + } + ++/* ++ * isulad: set oci hook file path ++ * */ ++static bool set_oci_hook_config_filename(struct lxc_container *c) ++{ ++#define OCI_HOOK_JSON_FILE_NAME "ocihooks.json" ++ char *newpath; ++ int len, ret; ++ ++ if (!c->config_path) ++ return false; ++ ++ /* $lxc_path + "/" + c->name + "/" + "config" + '\0' */ ++ len = strlen(c->config_path) + strlen(c->name) + strlen(OCI_HOOK_JSON_FILE_NAME) + 3; ++ newpath = malloc(len); ++ if (!newpath) ++ return false; ++ ++ ret = snprintf(newpath, len, "%s/%s/%s", c->config_path, c->name, OCI_HOOK_JSON_FILE_NAME); ++ if (ret < 0 || ret >= len) { ++ fprintf(stderr, "Error printing out config file name\n"); ++ free(newpath); ++ return false; ++ } ++ ++ free(c->ocihookfile); ++ c->ocihookfile = newpath; ++ ++ return true; ++} ++ + static bool do_lxcapi_set_config_path(struct lxc_container *c, const char *path) + { + char *p; +@@ -5081,6 +5142,11 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath + goto err; + } + ++ if (!set_oci_hook_config_filename(c)) { ++ fprintf(stderr, "Error allocating oci hooks file pathname\n"); ++ goto err; ++ } ++ + if (file_exists(c->configfile) && !lxcapi_load_config(c, NULL)) { + fprintf(stderr, "Failed to load config for %s\n", name); + goto err; +diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h +index 503038a..5d23cc7 100644 +--- a/src/lxc/lxccontainer.h ++++ b/src/lxc/lxccontainer.h +@@ -77,6 +77,13 @@ struct lxc_container { + + /*! + * \private ++ * isulad: support oci hook from json file ++ * full path of json file ++ * */ ++ char *ocihookfile; ++ ++ /*! ++ * \private + * File to store pid. + */ + char *pidfile; +diff --git a/src/lxc/start.c b/src/lxc/start.c +index b13326c..63f5af8 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -1887,6 +1887,16 @@ static int lxc_spawn(struct lxc_handler *handler) + goto out_delete_net; + } + ++ /* isulad: Run oci prestart hook at here */ ++ char* oci_hook_args[1]; ++ oci_hook_args[0] = alloca(strlen(lxcpath) + 1); ++ (void)strlcpy(oci_hook_args[0], lxcpath, strlen(lxcpath)); ++ ret = run_lxc_hooks(name, "oci-prestart", conf, oci_hook_args); ++ if (ret < 0) { ++ ERROR("Failed to run oci prestart hooks"); ++ goto out_delete_net; ++ } ++ + /* Tell the child to complete its initialization and wait for it to exec + * or return an error. (The child will never return + * LXC_SYNC_READY_START+1. It will either close the sync pipe, causing +@@ -1922,6 +1932,13 @@ static int lxc_spawn(struct lxc_handler *handler) + if (ret < 0) + goto out_abort; + ++ /* isulad: Run oci prestart hook at here */ ++ ret = run_lxc_hooks(name, "oci-poststart", conf, oci_hook_args); ++ if (ret < 0) { ++ ERROR("Failed to run oci poststart hooks"); ++ goto out_delete_net; ++ } ++ + ret = lxc_set_state(name, handler, RUNNING); + if (ret < 0) { + ERROR("Failed to set state to \"%s\"", lxc_state2str(RUNNING)); +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index 8ec9f46..d1a22f7 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -1864,11 +1864,11 @@ static int lxc_file2str(const char *filename, char ret[], int cap) + int fd, num_read; + + if ((fd = open(filename, O_RDONLY | O_CLOEXEC)) == -1) +- return -1;/*lint !e960*/ ++ return -1; + if ((num_read = read(fd, ret, cap - 1)) <= 0) +- num_read = -1;/*lint !e960*/ ++ num_read = -1; + else +- ret[num_read] = 0;/*lint !e613*//*lint !e960*/ ++ ret[num_read] = 0; + close(fd); + + return num_read; +@@ -1886,16 +1886,16 @@ static proc_t *lxc_stat2proc(char *S) + char *tmp = NULL; + + if (!S) +- return NULL;/*lint !e960*/ ++ return NULL; + +- tmp = strrchr(S, ')'); /* split into "PID (cmd" and "" *//*lint !e586*/ ++ tmp = strrchr(S, ')'); /* split into "PID (cmd" and "" */ + if (!tmp) +- return NULL;/*lint !e960*/ ++ return NULL; + *tmp = '\0'; /* replace trailing ')' with NUL */ + + P = malloc(sizeof(proc_t)); + if (!P) +- return NULL;/*lint !e960*/ ++ return NULL; + memset(P, 0x00, sizeof(proc_t)); + + /* parse these two strings separately, skipping the leading "(". */ +@@ -1909,9 +1909,9 @@ static proc_t *lxc_stat2proc(char *S) + "%c " + "%d %d %d %d %d " + "%lu %lu %lu %lu %lu " +- "%Lu %Lu %Lu %Lu " /* utime stime cutime cstime *//*lint !e566*/ ++ "%Lu %Lu %Lu %Lu " /* utime stime cutime cstime */ + "%ld %ld %ld %ld " +- "%Lu " /* start_time *//*lint !e566*/ ++ "%Lu " /* start_time */ + "%lu " + "%ld " + "%lu %lu %lu %lu %lu %lu " +@@ -1922,9 +1922,9 @@ static proc_t *lxc_stat2proc(char *S) + &P->state, + &P->ppid, &P->pgrp, &P->session, &P->tty, &P->tpgid, + &P->flags, &P->min_flt, &P->cmin_flt, &P->maj_flt, &P->cmaj_flt, +- &P->utime, &P->stime, &P->cutime, &P->cstime,/*lint !e561*/ ++ &P->utime, &P->stime, &P->cutime, &P->cstime, + &P->priority, &P->nice, &P->timeout, &P->it_real_value, +- &P->start_time,/*lint !e561*/ ++ &P->start_time, + &P->vsize, + &P->rss, + &P->rss_rlim, &P->start_code, &P->end_code, &P->start_stack, &P->kstk_esp, +@@ -1935,7 +1935,7 @@ static proc_t *lxc_stat2proc(char *S) + ); + + if (P->tty == 0) +- P->tty = -1; /* the old notty val, update elsewhere bef. moving to 0 *//*lint !e960*/ ++ P->tty = -1; /* the old notty val, update elsewhere bef. moving to 0 */ + return P; + } + +@@ -1949,7 +1949,7 @@ unsigned long long lxc_get_process_startat(pid_t pid) + char sbuf[1024] = {0}; /* bufs for stat */ + + sret = snprintf(filename, sizeof(filename), "/proc/%d/stat", pid); +- if (sret < 0 || sret >= sizeof(filename)) {/*lint !e574*/ ++ if (sret < 0 || sret >= sizeof(filename)) { + ERROR("Failed to sprintf filename"); + goto out; + } +@@ -1960,7 +1960,7 @@ unsigned long long lxc_get_process_startat(pid_t pid) + } + + pid_info = lxc_stat2proc(sbuf); +- if (!pid_info) {/*lint !e574*/ ++ if (!pid_info) { + ERROR("Failed to get proc stat info"); + goto out; + } +@@ -1992,3 +1992,41 @@ void lxc_write_error_message(int errfd, const char *format, ...) + SYSERROR("Write errbuf failed"); + } + ++bool lxc_process_alive(pid_t pid, unsigned long long start_time) ++{ ++ int ret; ++ int sret = 0; ++ bool alive = true; ++ proc_t *pid_info = NULL; ++ char filename[PATH_MAX] = {0}; ++ char sbuf[1024] = {0}; /* bufs for stat */ ++ ++ sret = kill(pid, 0); ++ if (sret < 0 && errno == ESRCH) ++ return false; ++ ++ sret = snprintf(filename, sizeof(filename), "/proc/%d/stat", pid); ++ if (sret < 0 || sret >= sizeof(filename)) { ++ ERROR("Failed to sprintf filename"); ++ goto out; ++ } ++ ++ if ((lxc_file2str(filename, sbuf, sizeof(sbuf))) == -1) { ++ ERROR("Failed to read pidfile %s", filename); ++ alive = false; ++ goto out; ++ } ++ ++ pid_info = lxc_stat2proc(sbuf); ++ if (!pid_info) { ++ ERROR("Failed to get proc stat info"); ++ alive = false; ++ goto out; ++ } ++ ++ if (start_time != pid_info->start_time) ++ alive = false; ++out: ++ free(pid_info); ++ return alive; ++} +diff --git a/src/lxc/utils.h b/src/lxc/utils.h +index 3d56fd9..abc88ca 100644 +--- a/src/lxc/utils.h ++++ b/src/lxc/utils.h +@@ -316,4 +316,6 @@ extern int fd_nonblock(int fd); + extern int unsigned long long lxc_get_process_startat(pid_t pid); + extern void lxc_write_error_message(int errfd, const char *format, ...); + ++extern bool lxc_process_alive(pid_t pid, unsigned long long start_time); ++ + #endif /* __LXC_UTILS_H */ +-- +1.8.3.1 + diff --git a/0026-remove-filelock-and-do-not-destroy-directory-when-de.patch b/0026-remove-filelock-and-do-not-destroy-directory-when-de.patch new file mode 100644 index 0000000..a786d69 --- /dev/null +++ b/0026-remove-filelock-and-do-not-destroy-directory-when-de.patch @@ -0,0 +1,132 @@ +From 693b1ab25741606299037bc660387a5d109f238c Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Mon, 14 Jan 2019 21:13:00 +0800 +Subject: [PATCH 026/122] remove filelock and do not destroy directory when + destroy container + +Signed-off-by: LiFeng +--- + src/lxc/lxccontainer.c | 14 ++++++++++++-- + src/lxc/lxclock.c | 25 +++++++++++++++++++++++++ + src/lxc/lxclock.h | 5 +++++ + src/lxc/storage/dir.c | 12 +----------- + 4 files changed, 43 insertions(+), 13 deletions(-) + +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index 68134d8..81c0ec3 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -2996,8 +2996,14 @@ static bool container_destroy(struct lxc_container *c, + bool bret = false; + int ret = 0; + +- if (!c || !do_lxcapi_is_defined(c)) ++ if (!c) + return false; ++ // isulad: if container is not defined, we need to remove disk lock file ++ // which is created in lxc_container_new. ++ if (!do_lxcapi_is_defined(c)) { ++ container_disk_removelock(c); ++ return false; ++ } + + conf = c->lxc_conf; + if (container_disk_lock(c)) +@@ -3124,12 +3130,16 @@ out: + free(path); + + container_disk_unlock(c); ++ if (bret) { ++ if (container_disk_removelock(c)) ++ bret = false; ++ } + return bret; + } + + static bool do_lxcapi_destroy(struct lxc_container *c) + { +- if (!c || !lxcapi_is_defined(c)) ++ if (!c) + return false; + + if (has_snapshots(c)) { +diff --git a/src/lxc/lxclock.c b/src/lxc/lxclock.c +index e3d4654..8890968 100644 +--- a/src/lxc/lxclock.c ++++ b/src/lxc/lxclock.c +@@ -198,6 +198,21 @@ on_error: + return l; + } + ++static int lxc_removelock(struct lxc_lock *l) ++{ ++ int ret = 0; ++ ++ if (l->type == LXC_LOCK_FLOCK) { ++ ret = unlink(l->u.f.fname); ++ if (ret && errno != ENOENT) { ++ SYSERROR("Error unlink %s", l->u.f.fname); ++ return ret; ++ } ++ } ++ ++ return ret; ++} ++ + int lxclock(struct lxc_lock *l, int timeout) + { + struct flock lk; +@@ -386,3 +401,13 @@ void container_disk_unlock(struct lxc_container *c) + lxcunlock(c->slock); + lxcunlock(c->privlock); + } ++ ++int container_disk_removelock(struct lxc_container *c) ++{ ++ int ret; ++ ++ ret = lxc_removelock(c->slock); ++ if (ret) ++ return ret; ++ return lxc_removelock(c->privlock); ++} +diff --git a/src/lxc/lxclock.h b/src/lxc/lxclock.h +index 364a71b..e86bc34 100644 +--- a/src/lxc/lxclock.h ++++ b/src/lxc/lxclock.h +@@ -174,4 +174,9 @@ extern int container_disk_lock(struct lxc_container *c); + */ + extern void container_disk_unlock(struct lxc_container *c); + ++/*! ++ * \brief isulad: remove the containers disk lock file. ++ */ ++int container_disk_removelock(struct lxc_container *c); ++ + #endif +diff --git a/src/lxc/storage/dir.c b/src/lxc/storage/dir.c +index c7b5ee2..deeecec 100644 +--- a/src/lxc/storage/dir.c ++++ b/src/lxc/storage/dir.c +@@ -123,17 +123,7 @@ int dir_create(struct lxc_storage *bdev, const char *dest, const char *n, + + int dir_destroy(struct lxc_storage *orig) + { +- int ret; +- const char *src; +- +- src = lxc_storage_get_path(orig->src, orig->src); +- +- ret = lxc_rmdir_onedev(src, NULL); +- if (ret < 0) { +- ERROR("Failed to delete \"%s\"", src); +- return -1; +- } +- ++ // isulad: do not destroy rootfs for directory, it should be managed by caller + return 0; + } + +-- +1.8.3.1 + diff --git a/0027-fix-bug-of-memory-leak.patch b/0027-fix-bug-of-memory-leak.patch new file mode 100644 index 0000000..40c3e7c --- /dev/null +++ b/0027-fix-bug-of-memory-leak.patch @@ -0,0 +1,78 @@ +From 4f4a8726feb02b846d9602feac517fc4dfbe1ede Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Mon, 14 Jan 2019 21:24:25 +0800 +Subject: [PATCH 027/122] fix bug of memory leak + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 11 +++++++++++ + src/lxc/conf.h | 1 + + src/lxc/lxccontainer.c | 11 +++++++---- + 3 files changed, 19 insertions(+), 4 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 6a14de1..e076bf2 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4822,6 +4822,16 @@ int lxc_clear_procs(struct lxc_conf *c, const char *key) + return 0; + } + ++int lxc_clear_namespace(struct lxc_conf *c) ++{ ++ int i; ++ for (i = 0; i < LXC_NS_MAX; i++) { ++ free(c->ns_share[i]); ++ c->ns_share[i] = NULL; ++ } ++ return 0; ++} ++ + int lxc_clear_groups(struct lxc_conf *c) + { + struct lxc_list *it, *next; +@@ -5036,6 +5046,7 @@ void lxc_conf_free(struct lxc_conf *conf) + lxc_clear_limits(conf, "lxc.prlimit"); + lxc_clear_sysctls(conf, "lxc.sysctl"); + lxc_clear_procs(conf, "lxc.proc"); ++ lxc_clear_namespace(conf); + free(conf->cgroup_meta.dir); + free(conf->cgroup_meta.controllers); + /* isulad add begin */ +diff --git a/src/lxc/conf.h b/src/lxc/conf.h +index 2263e47..44feb98 100644 +--- a/src/lxc/conf.h ++++ b/src/lxc/conf.h +@@ -491,6 +491,7 @@ extern int setup_sysctl_parameters(struct lxc_list *sysctls); + extern int lxc_clear_sysctls(struct lxc_conf *c, const char *key); + extern int setup_proc_filesystem(struct lxc_list *procs, pid_t pid); + extern int lxc_clear_procs(struct lxc_conf *c, const char *key); ++extern int lxc_clear_namespace(struct lxc_conf *c); + + /* isulad add begin */ + int lxc_clear_init_args(struct lxc_conf *lxc_conf); +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index 81c0ec3..e6272fc 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -5418,10 +5418,13 @@ int list_active_containers(const char *lxcpath, char ***nret, + continue; + } + +- if (array_contains(&ct_name, p, ct_name_cnt)) { +- if (is_hashed) +- free(p); +- continue; ++ ++ if (ct_name && ct_name_cnt) { ++ if (array_contains(&ct_name, p, ct_name_cnt)) { ++ if (is_hashed) ++ free(p); ++ continue; ++ } + } + + if (!add_to_array(&ct_name, p, ct_name_cnt)) { +-- +1.8.3.1 + diff --git a/0028-support-rootfs-for-container.patch b/0028-support-rootfs-for-container.patch new file mode 100644 index 0000000..996cd47 --- /dev/null +++ b/0028-support-rootfs-for-container.patch @@ -0,0 +1,123 @@ +From 53fa77bebc3e896396036cb3a482f75f138da788 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Tue, 15 Jan 2019 09:45:44 +0800 +Subject: [PATCH 028/122] support rootfs / for container + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 53 insertions(+), 8 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index e076bf2..f429491 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -888,9 +888,6 @@ static int lxc_setup_ttys(struct lxc_conf *conf) + char *ttydir = ttys->dir; + char path[PATH_MAX], lxcpath[PATH_MAX]; + +- if (!conf->rootfs.path) +- return 0; +- + for (i = 0; i < ttys->max; i++) { + struct lxc_terminal_info *tty = &ttys->tty[i]; + +@@ -1394,7 +1391,7 @@ static int lxc_mount_rootfs(struct lxc_conf *conf) + { + int ret; + struct lxc_storage *bdev; +- const struct lxc_rootfs *rootfs = &conf->rootfs; ++ struct lxc_rootfs *rootfs = &conf->rootfs; + unsigned long flags, mntflags, pflags; + char *mntdata; + +@@ -1405,6 +1402,17 @@ static int lxc_mount_rootfs(struct lxc_conf *conf) + return -1; + } + ++ // isulad: bind mount / to rootfs.mount. then we can do pivot root even if we use / as root. ++ if (!access(rootfs->mount, F_OK)) { ++ rootfs->path = strdup("/"); ++ if (mount("/", rootfs->mount, NULL, MS_BIND, 0)) { ++ SYSERROR("Failed to mount / to %s.", rootfs->mount); ++ return -1; ++ } ++ } else { ++ INFO("Use '/' as container rootfs, but no valid mountpoint provided. Something may go wrong."); ++ } ++ + return 0; + } + +@@ -3854,6 +3862,35 @@ static int setup_populate_devs(const struct lxc_rootfs *rootfs, struct lxc_list + return 0; + } + ++// isulad: setup rootfs mountopts ++static int setup_rootfs_mountopts(const struct lxc_rootfs *rootfs) ++{ ++ unsigned long mntflags, pflags; ++ char *mntdata; ++ ++ // only remount / when container shares rootfs with host. ++ if(!rootfs || !rootfs->path || strcmp(rootfs->path, "/")) ++ return 0; ++ if (!rootfs->options) ++ return 0; ++ ++ if (parse_mntopts(rootfs->options, &mntflags, &pflags, &mntdata) < 0) { ++ free(mntdata); ++ return -1; ++ } ++ free(mntdata); ++ ++ if (mntflags & MS_RDONLY) { ++ DEBUG("remounting / as readonly"); ++ if (mount("/", "/", NULL, MS_BIND |MS_REMOUNT| MS_RDONLY, 0)) { ++ SYSERROR("Failed to make / readonly."); ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++ + int lxc_setup(struct lxc_handler *handler) + { + int ret; +@@ -4020,12 +4057,20 @@ int lxc_setup(struct lxc_handler *handler) + return -1; + } + +- ret = lxc_setup_devpts(lxc_conf); +- if (ret < 0) { +- ERROR("Failed to setup new devpts instance"); ++ /* isulad: remount rootfs readonly if necessary */ ++ if (setup_rootfs_mountopts(&lxc_conf->rootfs)) { ++ ERROR("failed to set rootfs for '%s'", name); + return -1; + } + ++ if (lxc_conf->rootfs.path) { ++ ret = lxc_setup_devpts(lxc_conf); ++ if (ret < 0) { ++ ERROR("Failed to setup new devpts instance"); ++ return -1; ++ } ++ } ++ + ret = lxc_create_ttys(handler); + if (ret < 0) + return -1; +@@ -4184,7 +4229,7 @@ static char **merge_ocihook_env(char **oldenvs, size_t env_len, size_t *merge_en + return result; + } + +-static struct lxc_popen_FILE *lxc_popen_ocihook(char *commandpath, char **args, int args_len, ++static struct lxc_popen_FILE *lxc_popen_ocihook(char *commandpath, char **args, int args_len, + char **envs, int env_len, const char *instr) + { + int ret; +-- +1.8.3.1 + diff --git a/0029-add-start-timeout-to-limit-start-time.patch b/0029-add-start-timeout-to-limit-start-time.patch new file mode 100644 index 0000000..fcb2344 --- /dev/null +++ b/0029-add-start-timeout-to-limit-start-time.patch @@ -0,0 +1,436 @@ +From 96dc86e154cd49f9a999409e4fb679ed78e16af6 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Mon, 14 Jan 2019 21:38:07 -0500 +Subject: [PATCH 029/122] add start timeout to limit start time + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 6 +-- + src/lxc/execute.c | 4 +- + src/lxc/lxc.h | 8 ++-- + src/lxc/lxccontainer.c | 21 ++++++++- + src/lxc/lxccontainer.h | 16 +++++++ + src/lxc/start.c | 106 +++++++++++++++++++++++++++++++++++++++++++--- + src/lxc/start.h | 6 +-- + src/lxc/tools/arguments.h | 2 + + src/lxc/tools/lxc_start.c | 26 ++++++++++++ + 9 files changed, 175 insertions(+), 20 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index f429491..439353b 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4381,14 +4381,12 @@ void* wait_ocihook_timeout(void *arg) + + if (alive) { + ERROR("%s:%d: running %s hook caused \"hook ran past specified timeout of %.1fs\"", +- __FILE__, __LINE__, +- (conf->which == LXCHOOK_START_HOST) ? "prestart" : lxchook_names[conf->which], ++ __FILE__, __LINE__, lxchook_names[conf->which], + (double)conf->timeout); + + if (conf->errfd >= 0) { + lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"hook ran past specified timeout of %.1fs\"", +- __FILE__, __LINE__, +- (conf->which == LXCHOOK_START_HOST) ? "prestart" : lxchook_names[conf->which], ++ __FILE__, __LINE__, lxchook_names[conf->which], + (double)conf->timeout); + } + +diff --git a/src/lxc/execute.c b/src/lxc/execute.c +index 45ca67e..d388e63 100644 +--- a/src/lxc/execute.c ++++ b/src/lxc/execute.c +@@ -111,12 +111,12 @@ static struct lxc_operations execute_start_ops = { + + int lxc_execute(const char *name, char *const argv[], int quiet, + struct lxc_handler *handler, const char *lxcpath, +- bool daemonize, int *error_num) ++ bool daemonize, int *error_num, unsigned int start_timeout) + { + struct execute_args args = {.argv = argv, .quiet = quiet}; + + TRACE("Doing lxc_execute"); + handler->conf->is_execute = true; + return __lxc_start(name, handler, &execute_start_ops, &args, lxcpath, +- daemonize, error_num); ++ daemonize, error_num, start_timeout); + } +diff --git a/src/lxc/lxc.h b/src/lxc/lxc.h +index 22e3509..687b4b2 100644 +--- a/src/lxc/lxc.h ++++ b/src/lxc/lxc.h +@@ -55,7 +55,7 @@ struct lxc_handler; + */ + extern int lxc_start(const char *name, char *const argv[], + struct lxc_handler *handler, const char *lxcpath, +- bool daemonize, int *error_num); ++ bool daemonize, int *error_num, unsigned int start_timeout); + + /* + * Start the specified command inside an application container +@@ -66,9 +66,9 @@ extern int lxc_start(const char *name, char *const argv[], + * @daemonize : whether or not the container is daemonized + * Returns 0 on success, < 0 otherwise + */ +-extern int lxc_execute(const char *name, char *const argv[], int quiet, +- struct lxc_handler *handler, const char *lxcpath, +- bool daemonize, int *error_num); ++int lxc_execute(const char *name, char *const argv[], int quiet, ++ struct lxc_handler *handler, const char *lxcpath, ++ bool daemonize, int *error_num, unsigned int start_timeout); + + /* + * Close the fd associated with the monitoring +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index e6272fc..beae459 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -1169,10 +1169,10 @@ reboot: + + if (useinit) + ret = lxc_execute(c->name, argv, 1, handler, c->config_path, +- c->daemonize, &c->error_num); ++ c->daemonize, &c->error_num, c->start_timeout); + else + ret = lxc_start(c->name, argv, handler, c->config_path, +- c->daemonize, &c->error_num); ++ c->daemonize, &c->error_num, c->start_timeout); + + if (conf->reboot == REBOOT_REQ) { + INFO("Container requested reboot"); +@@ -5100,6 +5100,22 @@ static bool do_lxcapi_set_container_info_file(struct lxc_container *c, const cha + + WRAP_API_1(bool, lxcapi_set_container_info_file, const char *) + ++/* isulad add start timeout */ ++static bool do_lxcapi_set_start_timeout(struct lxc_container *c, unsigned int start_timeout) ++{ ++ if (!c || !c->lxc_conf) ++ return false; ++ if (container_mem_lock(c)) { ++ ERROR("Error getting mem lock"); ++ return false; ++ } ++ c->start_timeout = start_timeout; ++ container_mem_unlock(c); ++ return true; ++} ++ ++WRAP_API_1(bool, lxcapi_set_start_timeout, unsigned int) ++ + struct lxc_container *lxc_container_new(const char *name, const char *configpath) + { + struct lxc_container *c; +@@ -5231,6 +5247,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath + /* isulad add begin */ + c->set_terminal_init_fifos = lxcapi_set_terminal_default_fifos; + c->set_container_info_file = lxcapi_set_container_info_file; ++ c->set_start_timeout = lxcapi_set_start_timeout; + /* isulad add end */ + return c; + +diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h +index 5d23cc7..77de704 100644 +--- a/src/lxc/lxccontainer.h ++++ b/src/lxc/lxccontainer.h +@@ -94,6 +94,12 @@ struct lxc_container { + */ + char *exit_fifo; + ++ /*! isulad: ++ * \private ++ * start_timeout. ++ */ ++ unsigned int start_timeout; ++ + /*! + * \private + * Container semaphore lock. +@@ -880,6 +886,16 @@ struct lxc_container { + * \return \c true on success, else \c false. + */ + bool (*set_container_info_file) (struct lxc_container *c, const char *info_file); ++ ++ /*! isulad add ++ * \brief An API call to set start timeout ++ * ++ * \param c Container. ++ * \param start_timeout Value of start timeout. ++ * ++ * \return \c true on success, else \c false. ++ */ ++ bool (*set_start_timeout)(struct lxc_container *c, unsigned int start_timeout); + }; + + /*! +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 63f5af8..f7be9e4 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -93,7 +93,22 @@ extern void mod_all_rdeps(struct lxc_container *c, bool inc); + static bool do_destroy_container(struct lxc_handler *handler); + static int lxc_rmdir_onedev_wrapper(void *data); + static void lxc_destroy_container_on_signal(struct lxc_handler *handler, +- const char *name); ++ const char *name); ++ ++/* isulad: start timeout thread */ ++typedef enum { ++ START_INIT, ++ START_TIMEOUT, ++ START_MAX, ++} start_timeout_t; ++ ++static start_timeout_t global_timeout_state = START_INIT; ++static sem_t global_timeout_sem; ++ ++struct start_timeout_conf { ++ unsigned int timeout; ++ int errfd; ++}; + + static void print_top_failing_dir(const char *path) + { +@@ -1897,6 +1912,12 @@ static int lxc_spawn(struct lxc_handler *handler) + goto out_delete_net; + } + ++ if (START_TIMEOUT == global_timeout_state) { ++ //lxc_write_error_message(conf->errpipe[1], "Starting the container \"%s\" timeout.", name); ++ ERROR("Starting the container \"%s\" timeout.", name); ++ goto out_delete_net; ++ } ++ + /* Tell the child to complete its initialization and wait for it to exec + * or return an error. (The child will never return + * LXC_SYNC_READY_START+1. It will either close the sync pipe, causing +@@ -1936,7 +1957,13 @@ static int lxc_spawn(struct lxc_handler *handler) + ret = run_lxc_hooks(name, "oci-poststart", conf, oci_hook_args); + if (ret < 0) { + ERROR("Failed to run oci poststart hooks"); +- goto out_delete_net; ++ goto out_abort; ++ } ++ ++ if (START_TIMEOUT == global_timeout_state) { ++ //lxc_write_error_message(conf->errpipe[1], "Starting the container \"%s\" timeout.", name); ++ ERROR("Starting the container \"%s\" timeout.", name); ++ goto out_abort; + } + + ret = lxc_set_state(name, handler, RUNNING); +@@ -1964,12 +1991,71 @@ out_abort: + return -1; + } + ++/* isulad: start timeout thread function */ ++static void* wait_start_timeout(void *arg) ++{ ++ struct start_timeout_conf *conf = (struct start_timeout_conf *)arg; ++ ++ sem_post(&global_timeout_sem); ++ ++ if (!conf || conf->timeout < 1) ++ goto out; ++ ++ sleep(conf->timeout); ++ ++ global_timeout_state = START_TIMEOUT; ++ ++out: ++ free(conf); ++ return ((void *)0); ++} ++ ++/* isulad: create start timeout thread */ ++static int create_start_timeout_thread(struct lxc_conf *conf, unsigned int start_timeout) ++{ ++ int ret = 0; ++ pthread_t ptid; ++ pthread_attr_t attr; ++ struct start_timeout_conf *timeout_conf = NULL; ++ ++ if (sem_init(&global_timeout_sem, 0, 0)) { ++ ERROR("Failed to init start timeout semaphore");/*lint !e613*/ ++ ret = -1; ++ return ret; ++ } ++ ++ timeout_conf = malloc(sizeof(struct start_timeout_conf)); ++ if (!timeout_conf) { ++ ERROR("Failed to malloc start timeout conf"); ++ ret = -1; ++ goto out; ++ } ++ ++ memset(timeout_conf, 0, sizeof(struct start_timeout_conf)); ++ timeout_conf->errfd = conf->errpipe[1]; ++ timeout_conf->timeout = start_timeout; ++ ++ pthread_attr_init(&attr); ++ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); ++ ret = pthread_create(&ptid, &attr, wait_start_timeout, timeout_conf); ++ if (ret != 0) { ++ ERROR("Create start wait timeout thread failed"); ++ free(timeout_conf); ++ goto out; ++ } ++ ++ sem_wait(&global_timeout_sem); ++out: ++ sem_destroy(&global_timeout_sem); ++ return ret; ++} ++ + // isulad: send '128 + signal' if container is killed by signal. + #define ExitSignalOffset 128 + + int __lxc_start(const char *name, struct lxc_handler *handler, + struct lxc_operations* ops, void *data, const char *lxcpath, +- bool daemonize, int *error_num) ++ bool daemonize, int *error_num, unsigned int start_timeout) + { + int ret, status, exit_code; + struct lxc_conf *conf = handler->conf; +@@ -1983,8 +2069,18 @@ int __lxc_start(const char *name, struct lxc_handler *handler, + handler->data = data; + handler->daemonize = daemonize; + ++ /* isulad: add start timeout limit */ ++ if (start_timeout > 0) { ++ ret = create_start_timeout_thread(conf, start_timeout); ++ if (ret) { ++ ERROR("Failed to create start timeout thread for container \"%s\".", name); ++ goto out_fini_nonet; ++ } ++ } ++ + if (!attach_block_device(handler->conf)) { + ERROR("Failed to attach block device"); ++ ret = -1; + goto out_fini_nonet; + } + +@@ -2114,14 +2210,14 @@ static struct lxc_operations start_ops = { + }; + + int lxc_start(const char *name, char *const argv[], struct lxc_handler *handler, +- const char *lxcpath, bool daemonize, int *error_num) ++ const char *lxcpath, bool daemonize, int *error_num, unsigned int start_timeout) + { + struct start_args start_arg = { + .argv = argv, + }; + + TRACE("Doing lxc_start"); +- return __lxc_start(name, handler, &start_ops, &start_arg, lxcpath, daemonize, error_num); ++ return __lxc_start(name, handler, &start_ops, &start_arg, lxcpath, daemonize, error_num, start_timeout); + } + + static void lxc_destroy_container_on_signal(struct lxc_handler *handler, +diff --git a/src/lxc/start.h b/src/lxc/start.h +index f59bf54..a96f2ae 100644 +--- a/src/lxc/start.h ++++ b/src/lxc/start.h +@@ -174,9 +174,9 @@ extern void lxc_fini(const char *name, struct lxc_handler *handler); + */ + extern int lxc_check_inherited(struct lxc_conf *conf, bool closeall, + int *fds_to_ignore, size_t len_fds); +-extern int __lxc_start(const char *, struct lxc_handler *, +- struct lxc_operations *, void *, const char *, bool, +- int *); ++extern int __lxc_start(const char *name, struct lxc_handler *handler, ++ struct lxc_operations* ops, void *data, const char *lxcpath, ++ bool daemonize, int *error_num, unsigned int start_timeout); + + extern int resolve_clone_flags(struct lxc_handler *handler); + +diff --git a/src/lxc/tools/arguments.h b/src/lxc/tools/arguments.h +index 047e9f1..afab9f5 100644 +--- a/src/lxc/tools/arguments.h ++++ b/src/lxc/tools/arguments.h +@@ -65,6 +65,7 @@ struct lxc_arguments { + char *terminal_fifos[2]; /* isulad add, fifos used to redirct stdin/out/err */ + const char *container_info; /* isulad: file used to store pid and ppid info of container */ + const char *exit_monitor_fifo; /* isulad: fifo used to monitor state of monitor process */ ++ unsigned int start_timeout; /* isulad: Seconds for waiting on a container to start before it is killed*/ + + /* for lxc-console */ + unsigned int ttynum; +@@ -180,6 +181,7 @@ struct lxc_arguments { + #define OPT_OUTPUT_FIFO OPT_USAGE - 8 + #define OPT_CONTAINER_INFO OPT_USAGE - 9 + #define OPT_EXIT_FIFO OPT_USAGE - 10 ++#define OPT_START_TIMEOUT OPT_USAGE - 11 + /* isulad add end*/ + + extern int lxc_arguments_parse(struct lxc_arguments *args, int argc, +diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c +index 60c7d70..f37f8a6 100644 +--- a/src/lxc/tools/lxc_start.c ++++ b/src/lxc/tools/lxc_start.c +@@ -40,6 +40,7 @@ + #include + #include + #include ++#include + + #include + +@@ -74,6 +75,7 @@ static const struct option my_longopts[] = { + {"out-fifo", required_argument, 0, OPT_OUTPUT_FIFO}, + {"container-pidfile", required_argument, 0, OPT_CONTAINER_INFO}, + {"exit-fifo", required_argument, 0, OPT_EXIT_FIFO}, ++ {"start-timeout", required_argument, 0, OPT_START_TIMEOUT}, + /* isulad add end */ + LXC_COMMON_OPTIONS + }; +@@ -108,6 +110,18 @@ Options :\n\ + .pidfile = NULL, + }; + ++static bool is_non_negative_num(const char *s) ++{ ++ if (!s || !strcmp(s, "")) ++ return false; ++ while(*s != '\0') { ++ if(!isdigit(*s)) ++ return false; ++ ++s; ++ } ++ return true; ++} ++ + static int my_parser(struct lxc_arguments *args, int c, char *arg) + { + switch (c) { +@@ -158,6 +172,13 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) + case OPT_EXIT_FIFO: + args->exit_monitor_fifo = arg; + break; ++ case OPT_START_TIMEOUT: ++ if(!is_non_negative_num(arg)) { ++ fprintf(stderr, "Error start timeout parameter:%s.\n", arg); ++ return -1; ++ } ++ args->start_timeout = (unsigned int)atoi(arg); ++ break; + } + return 0; + } +@@ -341,6 +362,11 @@ int main(int argc, char *argv[]) + c->exit_fifo = strdup(my_args.exit_monitor_fifo); + } + ++ /* isulad: add start timeout */ ++ if(my_args.start_timeout) { ++ c->set_start_timeout(c, my_args.start_timeout); ++ } ++ + if (my_args.console) + if (!c->set_config_item(c, "lxc.console.path", my_args.console)) + goto out; +-- +1.8.3.1 + diff --git a/0030-support-block-device-as-rootfs.patch b/0030-support-block-device-as-rootfs.patch new file mode 100644 index 0000000..4f2f3b4 --- /dev/null +++ b/0030-support-block-device-as-rootfs.patch @@ -0,0 +1,287 @@ +From 3d30577047030ebf63101324509f1d1ecfb837b8 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Tue, 15 Jan 2019 16:00:30 +0800 +Subject: [PATCH 030/122] support block device as rootfs + +Signed-off-by: LiFeng +--- + src/lxc/Makefile.am | 1 + + src/lxc/conf.c | 10 ++--- + src/lxc/storage/block.c | 86 +++++++++++++++++++++++++++++++++++++++++ + src/lxc/storage/block.h | 41 ++++++++++++++++++++ + src/lxc/storage/dir.c | 10 +---- + src/lxc/storage/storage.c | 18 +++++++++ + src/lxc/storage/storage_utils.c | 2 +- + 7 files changed, 153 insertions(+), 15 deletions(-) + create mode 100644 src/lxc/storage/block.c + create mode 100644 src/lxc/storage/block.h + +diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am +index 5678b8d..260a7eb 100644 +--- a/src/lxc/Makefile.am ++++ b/src/lxc/Makefile.am +@@ -130,6 +130,7 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \ + start.c start.h \ + storage/btrfs.c storage/btrfs.h \ + storage/dir.c storage/dir.h \ ++ storage/block.c storage/block.h \ + storage/loop.c storage/loop.h \ + storage/lvm.c storage/lvm.h \ + storage/nbd.c storage/nbd.h \ +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 439353b..88763ee 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -3865,13 +3865,10 @@ static int setup_populate_devs(const struct lxc_rootfs *rootfs, struct lxc_list + // isulad: setup rootfs mountopts + static int setup_rootfs_mountopts(const struct lxc_rootfs *rootfs) + { +- unsigned long mntflags, pflags; ++ unsigned long mflags, mntflags, pflags; + char *mntdata; + +- // only remount / when container shares rootfs with host. +- if(!rootfs || !rootfs->path || strcmp(rootfs->path, "/")) +- return 0; +- if (!rootfs->options) ++ if(!rootfs || !rootfs->options) + return 0; + + if (parse_mntopts(rootfs->options, &mntflags, &pflags, &mntdata) < 0) { +@@ -3881,8 +3878,9 @@ static int setup_rootfs_mountopts(const struct lxc_rootfs *rootfs) + free(mntdata); + + if (mntflags & MS_RDONLY) { ++ mflags = add_required_remount_flags("/", NULL, MS_BIND | MS_REC | mntflags | pflags | MS_REMOUNT); + DEBUG("remounting / as readonly"); +- if (mount("/", "/", NULL, MS_BIND |MS_REMOUNT| MS_RDONLY, 0)) { ++ if (mount("/", "/", NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, 0) < 0) { + SYSERROR("Failed to make / readonly."); + return -1; + } +diff --git a/src/lxc/storage/block.c b/src/lxc/storage/block.c +new file mode 100644 +index 0000000..eb75e70 +--- /dev/null ++++ b/src/lxc/storage/block.c +@@ -0,0 +1,86 @@ ++/* ++ * 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 _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++#include ++#include ++ ++#include "config.h" ++#include "log.h" ++#include "storage.h" ++#include "storage_utils.h" ++#include "utils.h" ++ ++lxc_log_define(blk, lxc); ++ ++int blk_destroy(struct lxc_storage *orig) ++{ ++ return 0; ++} ++ ++bool blk_detect(const char *path) ++{ ++ struct stat statbuf; ++ int ret; ++ ++ if (!strncmp(path, "blk:", 4)) ++ return true; ++ ++ ret = stat(path, &statbuf); ++ if (ret == -1 && errno == EPERM) { ++ SYSERROR("blk_detect: failed to look at \"%s\"", path); ++ return false; ++ } ++ ++ if (ret == 0 && S_ISBLK(statbuf.st_mode)) ++ return true; ++ ++ return false; ++} ++ ++int blk_mount(struct lxc_storage *bdev) ++{ ++ const char *src; ++ if (strcmp(bdev->type, "blk")) ++ return -22; ++ ++ if (!bdev->src || !bdev->dest) ++ return -22; ++ ++ src = lxc_storage_get_path(bdev->src, bdev->type); ++ ++ return mount_unknown_fs(src, bdev->dest, bdev->mntopts); ++} ++ ++int blk_umount(struct lxc_storage *bdev) ++{ ++ if (strcmp(bdev->type, "blk")) ++ return -22; ++ ++ if (!bdev->src || !bdev->dest) ++ return -22; ++ ++ return umount(bdev->dest); ++} +diff --git a/src/lxc/storage/block.h b/src/lxc/storage/block.h +new file mode 100644 +index 0000000..2fa7565 +--- /dev/null ++++ b/src/lxc/storage/block.h +@@ -0,0 +1,41 @@ ++/* ++ * 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_BLK_H ++#define __LXC_BLK_H ++ ++#include ++#include ++ ++struct lxc_storage; ++ ++struct bdev_specs; ++ ++struct lxc_conf; ++ ++extern int blk_destroy(struct lxc_storage *orig); ++extern bool blk_detect(const char *path); ++extern int blk_mount(struct lxc_storage *bdev); ++extern int blk_umount(struct lxc_storage *bdev); ++ ++#endif /* __LXC_BLK_H */ +diff --git a/src/lxc/storage/dir.c b/src/lxc/storage/dir.c +index deeecec..2b548d0 100644 +--- a/src/lxc/storage/dir.c ++++ b/src/lxc/storage/dir.c +@@ -150,7 +150,7 @@ bool dir_detect(const char *path) + int dir_mount(struct lxc_storage *bdev) + { + int ret; +- unsigned long mflags = 0, mntflags = 0, pflags = 0; ++ unsigned long mntflags = 0, pflags = 0; + char *mntdata; + const char *src; + +@@ -169,13 +169,7 @@ int dir_mount(struct lxc_storage *bdev) + + src = lxc_storage_get_path(bdev->src, bdev->type); + +- ret = mount(src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags | pflags, mntdata); +- if ((0 == ret) && (mntflags & MS_RDONLY)) { +- DEBUG("Remounting \"%s\" on \"%s\" readonly", +- src ? src : "(none)", bdev->dest ? bdev->dest : "(none)"); +- mflags = add_required_remount_flags(src, bdev->dest, MS_BIND | MS_REC | mntflags | pflags | MS_REMOUNT); +- ret = mount(src, bdev->dest, "bind", mflags, mntdata); +- } ++ ret = mount(src, bdev->dest, "bind", MS_BIND | MS_REC | (mntflags & ~MS_RDONLY) | pflags, mntdata); + + if (ret < 0) { + SYSERROR("Failed to mount \"%s\" on \"%s\"", src, bdev->dest); +diff --git a/src/lxc/storage/storage.c b/src/lxc/storage/storage.c +index c4f4c2e..18f754a 100644 +--- a/src/lxc/storage/storage.c ++++ b/src/lxc/storage/storage.c +@@ -61,6 +61,7 @@ + #include "storage_utils.h" + #include "utils.h" + #include "zfs.h" ++#include "block.h" + + #ifndef HAVE_STRLCPY + #include "include/strlcpy.h" +@@ -114,6 +115,21 @@ static const struct lxc_storage_ops loop_ops = { + .can_backup = true, + }; + ++/* block */ ++static const struct lxc_storage_ops blk_ops = { ++ .detect = &blk_detect, ++ .mount = &blk_mount, ++ .umount = &blk_umount, ++ .clone_paths = NULL, ++ .destroy = &blk_destroy, ++ .create = NULL, ++ .copy = NULL, ++ .snapshot = NULL, ++ .can_snapshot = false, ++ .can_backup = true, ++}; ++ ++ + /* lvm */ + static const struct lxc_storage_ops lvm_ops = { + .detect = &lvm_detect, +@@ -199,6 +215,8 @@ static const struct lxc_storage_type bdevs[] = { + { .name = "overlayfs", .ops = &ovl_ops, }, + { .name = "loop", .ops = &loop_ops, }, + { .name = "nbd", .ops = &nbd_ops, }, ++ //isulad: block device ++ { .name = "blk", .ops = &blk_ops, } + }; + + static const size_t numbdevs = sizeof(bdevs) / sizeof(struct lxc_storage_type); +diff --git a/src/lxc/storage/storage_utils.c b/src/lxc/storage/storage_utils.c +index 46e08a3..b4dcb57 100644 +--- a/src/lxc/storage/storage_utils.c ++++ b/src/lxc/storage/storage_utils.c +@@ -416,7 +416,7 @@ int find_fstype_cb(char *buffer, void *data) + return 0; + } + +- if (mount(cbarg->rootfs, cbarg->target, fstype, mntflags, mntdata)) { ++ if (mount(cbarg->rootfs, cbarg->target, fstype, (mntflags & ~MS_RDONLY), mntdata)) { + SYSDEBUG("Failed to mount"); + free(mntdata); + return 0; +-- +1.8.3.1 + diff --git a/0031-clean-add-clean-resources-api.patch b/0031-clean-add-clean-resources-api.patch new file mode 100644 index 0000000..755910f --- /dev/null +++ b/0031-clean-add-clean-resources-api.patch @@ -0,0 +1,488 @@ +From 37d787b93122a6b61d99a3d71f6101f405031a95 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Tue, 15 Jan 2019 04:20:57 -0500 +Subject: [PATCH 031/122] clean: add clean resources api + +Signed-off-by: LiFeng +--- + src/lxc/cgroups/cgfsng.c | 124 +++++++++++++++++------------------------ + src/lxc/cgroups/cgroup.c | 2 +- + src/lxc/cgroups/cgroup.h | 4 +- + src/lxc/lxccontainer.c | 18 ++++++ + src/lxc/lxccontainer.h | 10 ++++ + src/lxc/start.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++ + src/lxc/start.h | 4 ++ + 7 files changed, 228 insertions(+), 75 deletions(-) + +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index 7f2a200..8b913a6 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -1050,12 +1050,15 @@ static int cgroup_rmdir(struct hierarchy **hierarchies, + int ret; + struct hierarchy *h = hierarchies[i]; + +- if (!h->container_full_path) +- continue; ++ if (!h->container_full_path) { ++ h->container_full_path = must_make_path(h->mountpoint, h->container_base_path, container_cgroup, NULL); ++ } + + ret = recursive_destroy(h->container_full_path); +- if (ret < 0) +- WARN("Failed to destroy \"%s\"", h->container_full_path); ++ if (ret < 0) { ++ ERROR("Failed to destroy \"%s\"", h->container_full_path); ++ return -1; ++ } + + free(h->container_full_path); + h->container_full_path = NULL; +@@ -1102,7 +1105,8 @@ static int cgroup_rmdir_wrapper(void *data) + return cgroup_rmdir(arg->hierarchies, arg->container_cgroup); + } + +-__cgfsng_ops static void cgfsng_payload_destroy(struct cgroup_ops *ops, ++/* isulad: fix return bool instead of void*/ ++__cgfsng_ops static bool cgfsng_payload_destroy(struct cgroup_ops *ops, + struct lxc_handler *handler) + { + int ret; +@@ -1113,6 +1117,8 @@ __cgfsng_ops static void cgfsng_payload_destroy(struct cgroup_ops *ops, + wrap.hierarchies = ops->hierarchies; + wrap.conf = handler->conf; + ++ INFO("cgfsng_payload_destroy.%p, %s", ops->hierarchies, ops->container_cgroup); ++ + if (handler->conf && !lxc_list_empty(&handler->conf->id_map)) + ret = userns_exec_1(handler->conf, cgroup_rmdir_wrapper, &wrap, + "cgroup_rmdir_wrapper"); +@@ -1120,8 +1126,10 @@ __cgfsng_ops static void cgfsng_payload_destroy(struct cgroup_ops *ops, + ret = cgroup_rmdir(ops->hierarchies, ops->container_cgroup); + if (ret < 0) { + WARN("Failed to destroy cgroups"); +- return; ++ return false; + } ++ ++ return true; + } + + static bool cg_unified_create_cgroup(struct hierarchy *h, char *cgname) +@@ -1232,12 +1240,20 @@ static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname) + { + int ret; + ++ h->container_full_path = must_make_path(h->mountpoint, h->container_base_path, cgname, NULL); ++ ++ if (file_exists(h->container_full_path)) { // it must not already exist ++ ERROR("Cgroup path \"%s\" already exist.", h->container_full_path); ++ //lxc_write_error_message(errfd, "%s:%d: Cgroup path \"%s\" already exist.", ++ // __FILE__, __LINE__, h->fullcgpath); ++ return false; ++ } ++ + if (!cg_legacy_handle_cpuset_hierarchy(h, cgname)) { + ERROR("Failed to handle legacy cpuset controller"); + return false; + } + +- h->container_full_path = must_make_path(h->mountpoint, h->container_base_path, cgname, NULL); + ret = mkdir_eexist_on_last(h->container_full_path, 0755); + if (ret < 0) { + ERROR("Failed to create cgroup \"%s\"", h->container_full_path); +@@ -1259,83 +1275,26 @@ static void remove_path_for_hierarchy(struct hierarchy *h, char *cgname) + h->container_full_path = NULL; + } + +-/* Try to create the same cgroup in all hierarchies. Start with cgroup_pattern; +- * next cgroup_pattern-1, -2, ..., -999. +- */ ++/* isulad: create hierarchies path, if fail, return the error */ + __cgfsng_ops static bool cgfsng_payload_create(struct cgroup_ops *ops, + struct lxc_handler *handler) + { + int i; +- size_t len; +- char *container_cgroup, *offset, *tmp; +- int idx = 0; +- struct lxc_conf *conf = handler->conf; +- +- if (ops->container_cgroup) { +- WARN("cgfsng_create called a second time: %s", ops->container_cgroup); +- return false; +- } ++ char *container_cgroup = ops->container_cgroup; + +- if (!conf) +- return false; +- +- if (conf->cgroup_meta.dir) +- tmp = lxc_string_join("/", (const char *[]){conf->cgroup_meta.dir, handler->name, NULL}, false); +- else +- tmp = lxc_string_replace("%n", handler->name, ops->cgroup_pattern); +- if (!tmp) { +- ERROR("Failed expanding cgroup name pattern"); ++ if (!container_cgroup) { ++ ERROR("cgfsng_create container_cgroup is invalid"); + return false; + } + +- len = strlen(tmp) + 5; /* leave room for -NNN\0 */ +- container_cgroup = must_realloc(NULL, len); +- (void)strlcpy(container_cgroup, tmp, len); +- free(tmp); +- offset = container_cgroup + len - 5; +- +-again: +- if (idx == 1000) { +- ERROR("Too many conflicting cgroup names"); +- goto out_free; +- } +- +- if (idx) { +- int ret; +- +- ret = snprintf(offset, 5, "-%d", idx); +- if (ret < 0 || (size_t)ret >= 5) { +- FILE *f = fopen("/dev/null", "w"); +- if (f) { +- fprintf(f, "Workaround for GCC7 bug: " +- "https://gcc.gnu.org/bugzilla/" +- "show_bug.cgi?id=78969"); +- fclose(f); +- } +- } +- } +- + for (i = 0; ops->hierarchies[i]; i++) { + if (!create_path_for_hierarchy(ops->hierarchies[i], container_cgroup)) { +- int j; +- ERROR("Failed to create cgroup \"%s\"", ops->hierarchies[i]->container_full_path); +- free(ops->hierarchies[i]->container_full_path); +- ops->hierarchies[i]->container_full_path = NULL; +- for (j = 0; j < i; j++) +- remove_path_for_hierarchy(ops->hierarchies[j], container_cgroup); +- idx++; +- goto again; ++ SYSERROR("Failed to create %s", ops->hierarchies[i]->container_full_path); ++ return false; + } + } + +- ops->container_cgroup = container_cgroup; +- + return true; +- +-out_free: +- free(container_cgroup); +- +- return false; + } + + __cgfsng_ops static bool cgfsng_payload_enter(struct cgroup_ops *ops, pid_t pid) +@@ -2701,9 +2660,15 @@ static bool cg_init(struct cgroup_ops *ops) + return cg_hybrid_init(ops); + } + +-__cgfsng_ops static bool cgfsng_data_init(struct cgroup_ops *ops) ++__cgfsng_ops static bool cgfsng_data_init(struct cgroup_ops *ops, struct lxc_handler *handler) + { + const char *cgroup_pattern; ++ char *container_cgroup, *tmp; ++ struct lxc_conf *conf = handler->conf; ++ size_t len; ++ ++ if (!conf) ++ return false; + + /* copy system-wide cgroup information */ + cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern"); +@@ -2714,6 +2679,22 @@ __cgfsng_ops static bool cgfsng_data_init(struct cgroup_ops *ops) + } + ops->cgroup_pattern = must_copy_string(cgroup_pattern); + ++ /* isulad: init ops->container_cgroup here instead of in cgfsng_payload_create*/ ++ if (conf->cgroup_meta.dir) ++ tmp = lxc_string_join("/", (const char *[]){conf->cgroup_meta.dir, handler->name, NULL}, false); ++ else ++ tmp = lxc_string_replace("%n", handler->name, ops->cgroup_pattern); ++ if (!tmp) { ++ ERROR("Failed expanding cgroup name pattern"); ++ return false; ++ } ++ ++ len = strlen(tmp) + 1; ++ container_cgroup = must_realloc(NULL, len); ++ (void)strlcpy(container_cgroup, tmp, len); ++ free(tmp); ++ ops->container_cgroup = container_cgroup; ++ + return true; + } + +@@ -2735,7 +2716,6 @@ struct cgroup_ops *cgfsng_ops_init(void) + + cgfsng_ops->data_init = cgfsng_data_init; + cgfsng_ops->destroy = cgfsng_payload_destroy; +- cgfsng_ops->destroy = cgfsng_payload_destroy; + cgfsng_ops->payload_create = cgfsng_payload_create; + cgfsng_ops->payload_enter = cgfsng_payload_enter; + cgfsng_ops->escape = cgfsng_escape; +diff --git a/src/lxc/cgroups/cgroup.c b/src/lxc/cgroups/cgroup.c +index 04e0311..8e7aef9 100644 +--- a/src/lxc/cgroups/cgroup.c ++++ b/src/lxc/cgroups/cgroup.c +@@ -50,7 +50,7 @@ struct cgroup_ops *cgroup_init(struct lxc_handler *handler) + return NULL; + } + +- if (!cgroup_ops->data_init(cgroup_ops)) ++ if (!cgroup_ops->data_init(cgroup_ops, handler)) + return NULL; + + TRACE("Initialized cgroup driver %s", cgroup_ops->driver); +diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h +index ba4c153..fa4871e 100644 +--- a/src/lxc/cgroups/cgroup.h ++++ b/src/lxc/cgroups/cgroup.h +@@ -123,8 +123,8 @@ struct cgroup_ops { + */ + cgroup_layout_t cgroup_layout; + +- bool (*data_init)(struct cgroup_ops *ops); +- void (*destroy)(struct cgroup_ops *ops, struct lxc_handler *handler); ++ bool (*data_init)(struct cgroup_ops *ops, struct lxc_handler *handler); ++ bool (*destroy)(struct cgroup_ops *ops, struct lxc_handler *handler); + bool (*payload_create)(struct cgroup_ops *ops, struct lxc_handler *handler); + bool (*payload_enter)(struct cgroup_ops *ops, pid_t pid); + const char *(*get_cgroup)(struct cgroup_ops *ops, const char *controller); +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index beae459..38059fa 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -5116,6 +5116,23 @@ static bool do_lxcapi_set_start_timeout(struct lxc_container *c, unsigned int s + + WRAP_API_1(bool, lxcapi_set_start_timeout, unsigned int) + ++/* isulad add clean resources */ ++static bool do_lxcapi_clean_container_resource(struct lxc_container *c, pid_t pid) ++{ ++ int ret; ++ ++ if (!c) ++ return false; ++ ++ ret = do_lxcapi_clean_resource(c->name, c->config_path, c->lxc_conf, pid); ++ if (ret) ++ ERROR("Failed to clean container %s resource", c->name); ++ return ret == 0; ++ ++} ++ ++WRAP_API_1(bool, lxcapi_clean_container_resource, pid_t) ++ + struct lxc_container *lxc_container_new(const char *name, const char *configpath) + { + struct lxc_container *c; +@@ -5248,6 +5265,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath + c->set_terminal_init_fifos = lxcapi_set_terminal_default_fifos; + c->set_container_info_file = lxcapi_set_container_info_file; + c->set_start_timeout = lxcapi_set_start_timeout; ++ c->clean_container_resource = lxcapi_clean_container_resource; + /* isulad add end */ + return c; + +diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h +index 77de704..679ca42 100644 +--- a/src/lxc/lxccontainer.h ++++ b/src/lxc/lxccontainer.h +@@ -896,6 +896,16 @@ struct lxc_container { + * \return \c true on success, else \c false. + */ + bool (*set_start_timeout)(struct lxc_container *c, unsigned int start_timeout); ++ ++ /*! isulad add ++ * \brief An API call to clean resources of container ++ * ++ * \param c Container. ++ * \param pid Value of container process. ++ * ++ * \return \c true on success, else \c false. ++ */ ++ bool (*clean_container_resource) (struct lxc_container *c, pid_t pid); + }; + + /*! +diff --git a/src/lxc/start.c b/src/lxc/start.c +index f7be9e4..08d753a 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -1895,6 +1895,11 @@ static int lxc_spawn(struct lxc_handler *handler) + if (ret < 0) + SYSERROR("Failed to set environment variable: LXC_PID=%s", pidstr); + ++ if (handler->cgroup_ops->container_cgroup) { ++ if (setenv("LXC_CGROUP_PATH", handler->cgroup_ops->container_cgroup, 1)) ++ SYSERROR("Failed to set environment variable: LXC_CGROUP_PATH=%s.", handler->cgroup_ops->container_cgroup); ++ } ++ + /* Run any host-side start hooks */ + ret = run_lxc_hooks(name, "start-host", conf, NULL); + if (ret < 0) { +@@ -2289,3 +2294,139 @@ static bool do_destroy_container(struct lxc_handler *handler) + + return storage_destroy(handler->conf); + } ++ ++/*isulad: init handler for clean */ ++static struct lxc_handler *lxc_init_clean_handler(char *name, char *lxcpath, struct lxc_conf *conf, pid_t pid) ++{ ++ int i; ++ struct lxc_handler *handler; ++ ++ handler = malloc(sizeof(*handler)); ++ if (!handler) ++ return NULL; ++ ++ memset(handler, 0, sizeof(*handler)); ++ ++ /* Note that am_guest_unpriv() checks the effective uid. We ++ * probably don't care if we are real root only if we are running ++ * as root so this should be fine. ++ */ ++ handler->am_root = !am_guest_unpriv(); ++ handler->data_sock[0] = handler->data_sock[1] = -1; ++ handler->conf = conf; ++ handler->lxcpath = lxcpath; ++ handler->pinfd = -1; ++ handler->sigfd = -EBADF; ++ handler->init_died = false; ++ handler->pid = pid; ++ handler->state_socket_pair[0] = handler->state_socket_pair[1] = -1; ++ if (handler->conf->reboot == REBOOT_NONE) ++ lxc_list_init(&handler->conf->state_clients); ++ ++ for (i = 0; i < LXC_NS_MAX; i++) ++ handler->nsfd[i] = -1; ++ ++ handler->name = name; ++ handler->exit_code = -1; /* isulad: record exit code of container */ ++ ++ handler->cgroup_ops = cgroup_init(handler); ++ if (!handler->cgroup_ops) { ++ ERROR("Failed to initialize cgroup driver"); ++ goto on_error; ++ } ++ ++ INFO("Container \"%s\" 's clean handler is initialized.", name); ++ ++ return handler; ++ ++on_error: ++ lxc_free_handler(handler); ++ ++ return NULL; ++} ++ ++/*isulad: set env for clean resources */ ++static void clean_resource_set_env(struct lxc_handler *handler) ++{ ++ const char *name = handler->name; ++ struct lxc_conf *conf = handler->conf; ++ char pidstr[20]; ++ ++ /* Start of environment variable setup for hooks. */ ++ if (name && setenv("LXC_NAME", name, 1)) ++ SYSERROR("Failed to set environment variable: LXC_NAME=%s.", name); ++ ++ if (conf->rcfile && setenv("LXC_CONFIG_FILE", conf->rcfile, 1)) ++ SYSERROR("Failed to set environment variable: LXC_CONFIG_FILE=%s.", conf->rcfile); ++ ++ if (conf->rootfs.mount && setenv("LXC_ROOTFS_MOUNT", conf->rootfs.mount, 1)) ++ SYSERROR("Failed to set environment variable: LXC_ROOTFS_MOUNT=%s.", conf->rootfs.mount); ++ ++ if (conf->rootfs.path && setenv("LXC_ROOTFS_PATH", conf->rootfs.path, 1)) ++ SYSERROR("Failed to set environment variable: LXC_ROOTFS_PATH=%s.", conf->rootfs.path); ++ ++ if (conf->console.path && setenv("LXC_CONSOLE", conf->console.path, 1)) ++ SYSERROR("Failed to set environment variable: LXC_CONSOLE=%s.", conf->console.path); ++ ++ if (conf->console.log_path && setenv("LXC_CONSOLE_LOGPATH", conf->console.log_path, 1)) ++ SYSERROR("Failed to set environment variable: LXC_CONSOLE_LOGPATH=%s.", conf->console.log_path); ++ ++ if (setenv("LXC_CGNS_AWARE", "1", 1)) ++ SYSERROR("Failed to set environment variable LXC_CGNS_AWARE=1."); ++ ++ ++ snprintf(pidstr, 20, "%d", handler->pid); ++ if (setenv("LXC_PID", pidstr, 1)) ++ SYSERROR("Failed to set environment variable: LXC_PID=%s.", pidstr); ++ ++ if (handler->cgroup_ops->container_cgroup) { ++ if (setenv("LXC_CGROUP_PATH", handler->cgroup_ops->container_cgroup, 1)) ++ SYSERROR("Failed to set environment variable: LXC_CGROUP_PATH=%s.", handler->cgroup_ops->container_cgroup); ++ } ++ /* End of environment variable setup for hooks. */ ++} ++ ++/*isulad: do_lxcapi_clean_resource */ ++int do_lxcapi_clean_resource(char *name, char *lxcpath, struct lxc_conf *conf, pid_t pid) ++{ ++ int ret = 0; ++ struct lxc_handler *handler = NULL; ++ int retry_count = 0; ++ int max_retry = 10; ++ ++ handler = lxc_init_clean_handler(name, lxcpath, conf, pid); ++ if (!handler) { ++ ERROR("Failed to init container %s clean handler", name); ++ ret = -1; ++ goto out; ++ } ++ ++ clean_resource_set_env(handler); ++ ++ char* oci_hook_args[1]; ++ oci_hook_args[0] = alloca(strlen(handler->lxcpath) + 1); ++ (void)strlcpy(oci_hook_args[0], handler->lxcpath, strlen(handler->lxcpath)); ++ ++ if (run_lxc_hooks(handler->name, "oci-poststop", handler->conf, oci_hook_args)) { ++ ERROR("Failed to run lxc.hook.post-stop for container \"%s\".", handler->name); ++ ret = -1; ++ } ++ ++retry: ++ if (!handler->cgroup_ops->destroy(handler->cgroup_ops, handler)) { ++ if (retry_count < max_retry) { ++ usleep(100 * 1000); /* 100 millisecond */ ++ retry_count++; ++ goto retry; ++ } ++ ERROR("Failed to destroy cgroup for container \"%s\".", handler->name); ++ ret = -1; ++ } ++ ++ ++out_fini_handler: ++ lxc_free_handler(handler); ++out: ++ return ret; ++} ++ +diff --git a/src/lxc/start.h b/src/lxc/start.h +index a96f2ae..1d84325 100644 +--- a/src/lxc/start.h ++++ b/src/lxc/start.h +@@ -180,4 +180,8 @@ extern int __lxc_start(const char *name, struct lxc_handler *handler, + + extern int resolve_clone_flags(struct lxc_handler *handler); + ++/*isulad: do_lxcapi_clean_resource */ ++extern int do_lxcapi_clean_resource(char *name, char *lxcpath, struct lxc_conf *conf, pid_t pid); ++ ++ + #endif +-- +1.8.3.1 + diff --git a/0032-Drop-all-caps-when-cap.keep-ISULAD_KEEP_NONE.patch b/0032-Drop-all-caps-when-cap.keep-ISULAD_KEEP_NONE.patch new file mode 100644 index 0000000..a93a188 --- /dev/null +++ b/0032-Drop-all-caps-when-cap.keep-ISULAD_KEEP_NONE.patch @@ -0,0 +1,33 @@ +From 37c5a4630e798ff4a24f1336560c41b2b8fec01b Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Tue, 15 Jan 2019 05:39:39 -0500 +Subject: [PATCH 032/122] Drop all caps when cap.keep=ISULAD_KEEP_NONE + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 88763ee..54b967b 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -2805,6 +2805,15 @@ static int dropcaps_except(struct lxc_list *caps) + lxc_list_for_each (iterator, caps) { + keep_entry = iterator->elem; + ++ /* isulad: Do not keep any cap*/ ++ if (strcmp(keep_entry, "ISULAD_KEEP_NONE") == 0) { ++ DEBUG("Do not keep any capability"); ++ for(i = 0; i < numcaps; i++) { ++ caplist[i] = 0; ++ } ++ break; ++ } ++ + capid = parse_cap(keep_entry); + if (capid == -2) + continue; +-- +1.8.3.1 + diff --git a/0033-support-mount-squashfs-in-mount-entry.patch b/0033-support-mount-squashfs-in-mount-entry.patch new file mode 100644 index 0000000..5354551 --- /dev/null +++ b/0033-support-mount-squashfs-in-mount-entry.patch @@ -0,0 +1,369 @@ +From e7f83b7c8b21942051e86e094d867cc79ff93524 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Tue, 15 Jan 2019 19:54:13 +0800 +Subject: [PATCH 033/122] support mount squashfs in mount entry + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 88 +++++++++++++++++++++++++++++++++++++++-- + src/lxc/storage/loop.c | 36 ++++++++++++++--- + src/lxc/storage/storage_utils.c | 36 ++++++++++++++++- + src/lxc/utils.c | 33 ++++++++++++++-- + src/lxc/utils.h | 1 + + 5 files changed, 181 insertions(+), 13 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 54b967b..fea0f59 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -78,6 +78,7 @@ + #include "storage/overlay.h" + #include "syscall_wrappers.h" + #include "terminal.h" ++#include "loop.h" + #include "path.h" + #include "utils.h" + +@@ -2444,6 +2445,82 @@ static int mount_entry_create_dir_file(const struct mntent *mntent, + return 0; + } + ++static int mount_entry_with_loop_dev(const char *src, const char *dest, const char *fstype, ++ char *mnt_opts, const char *rootfs) ++{ ++ int srcfd = -1, destfd, ret, saved_errno; ++ char srcbuf[50], destbuf[50]; // only needs enough for /proc/self/fd/ ++ const char *mntsrc = src; ++ int max_retry = 5; ++ struct lxc_storage loop; ++ ++ if (!rootfs) ++ rootfs = ""; ++ ++ /* todo - allow symlinks for relative paths if 'allowsymlinks' option is passed */ ++ if (src && src[0] != '/') { ++ INFO("this is a relative mount"); ++ srcfd = open_without_symlink(src, NULL); ++ if (srcfd < 0) ++ return srcfd; ++ ret = snprintf(srcbuf, sizeof(srcbuf), "/proc/self/fd/%d", srcfd); ++ if (ret < 0 || ret > sizeof(srcbuf)) { ++ close(srcfd); ++ ERROR("Failed to print string"); ++ return -EINVAL; ++ } ++ mntsrc = srcbuf; ++ } ++ ++ destfd = open_without_symlink(dest, rootfs); ++ if (destfd < 0) { ++ if (srcfd != -1) { ++ saved_errno = errno; ++ close(srcfd); ++ errno = saved_errno; ++ } ++ return destfd; ++ } ++ ++ ret = snprintf(destbuf, sizeof(destbuf), "/proc/self/fd/%d", destfd); ++ if (ret < 0 || ret > sizeof(destbuf)) { ++ if (srcfd != -1) ++ close(srcfd); ++ close(destfd); ++ ERROR("Out of memory"); ++ return -EINVAL; ++ } ++ ++retry: ++ loop.src = (char *)mntsrc; ++ loop.dest = destbuf; ++ loop.mntopts = mnt_opts; ++ loop.type = "loop"; ++ loop.lofd = -1; ++ ret = loop_mount(&loop); ++ if (ret < 0) { ++ /* If loop is used by other program, mount may fail. So ++ * we do retry to ensure mount ok */ ++ if (max_retry > 0) { ++ max_retry--; ++ DEBUG("mount entry with loop dev failed, retry mount." ++ "retry count left %d", max_retry); ++ goto retry; ++ } ++ } ++ if (loop.lofd != -1) ++ close(loop.lofd); ++ if (srcfd != -1) ++ close(srcfd); ++ close(destfd); ++ if (ret < 0) { ++ SYSERROR("Failed to mount %s onto %s", src, dest); ++ return ret; ++ } ++ ++ return 0; ++} ++ + /* rootfs, lxc_name, and lxc_path can be NULL when the container is created + * without a rootfs. */ + static inline int mount_entry_on_generic(struct mntent *mntent, +@@ -2502,8 +2579,14 @@ static inline int mount_entry_on_generic(struct mntent *mntent, + return -1; + } + +- ret = mount_entry(mntent->mnt_fsname, dest, mntent->mnt_type, mntflags, +- pflags, mntdata, optional, dev, relative, rootfs_path); ++ // isulad: support squashfs ++ if (strcmp(mntent->mnt_type, "squashfs") == 0) { ++ ret = mount_entry_with_loop_dev(mntent->mnt_fsname, dest, mntent->mnt_type, ++ mntent->mnt_opts, rootfs_path); ++ } else { ++ ret = mount_entry(mntent->mnt_fsname, dest, mntent->mnt_type, mntflags, ++ pflags, mntdata, optional, dev, relative, rootfs_path); ++ } + + free(mntdata); + free(rpath); +@@ -3897,7 +3980,6 @@ static int setup_rootfs_mountopts(const struct lxc_rootfs *rootfs) + return 0; + } + +- + int lxc_setup(struct lxc_handler *handler) + { + int ret; +diff --git a/src/lxc/storage/loop.c b/src/lxc/storage/loop.c +index 35cb13e..760def8 100644 +--- a/src/lxc/storage/loop.c ++++ b/src/lxc/storage/loop.c +@@ -41,6 +41,7 @@ + #include "loop.h" + #include "storage.h" + #include "storage_utils.h" ++#include "lxclock.h" + #include "utils.h" + + lxc_log_define(loop, lxc); +@@ -236,9 +237,11 @@ bool loop_detect(const char *path) + + int loop_mount(struct lxc_storage *bdev) + { +- int ret, loopfd; ++ int ret = 0; ++ int loopfd, lret; + char loname[PATH_MAX]; + const char *src; ++ struct lxc_lock *l = NULL; + + if (strcmp(bdev->type, "loop")) + return -22; +@@ -246,13 +249,29 @@ int loop_mount(struct lxc_storage *bdev) + if (!bdev->src || !bdev->dest) + return -22; + ++ /* isulad: do lock before mount, so we can avoid use loop which is used by ++ * other starting contianers */ ++ l = lxc_newlock("mount_lock", "mount_lock"); ++ if (!l) { ++ SYSERROR("create file lock error when mount fs"); ++ return -1; ++ } ++ ++ lret = lxclock(l, 0); ++ if (lret) { ++ SYSERROR("try to lock failed when mount fs"); ++ ret = -1; ++ goto out; ++ } ++ + /* skip prefix */ + src = lxc_storage_get_path(bdev->src, bdev->type); + + loopfd = lxc_prepare_loop_dev(src, loname, LO_FLAGS_AUTOCLEAR); + if (loopfd < 0) { + ERROR("Failed to prepare loop device for loop file \"%s\"", src); +- return -1; ++ ret = -1; ++ goto out; + } + DEBUG("Prepared loop device \"%s\"", loname); + +@@ -261,14 +280,21 @@ int loop_mount(struct lxc_storage *bdev) + ERROR("Failed to mount rootfs \"%s\" on \"%s\" via loop device \"%s\"", + bdev->src, bdev->dest, loname); + close(loopfd); +- return -1; ++ ret = -1; ++ goto out; + } + + bdev->lofd = loopfd; + DEBUG("Mounted rootfs \"%s\" on \"%s\" via loop device \"%s\"", + bdev->src, bdev->dest, loname); +- +- return 0; ++out: ++ lret = lxcunlock(l); ++ if (lret) { ++ SYSERROR("try to unlock failed when mount fs"); ++ ret = -1; ++ } ++ lxc_putlock(l); ++ return ret; + } + + int loop_umount(struct lxc_storage *bdev) +diff --git a/src/lxc/storage/storage_utils.c b/src/lxc/storage/storage_utils.c +index b4dcb57..0a87778 100644 +--- a/src/lxc/storage/storage_utils.c ++++ b/src/lxc/storage/storage_utils.c +@@ -339,10 +339,14 @@ int is_blktype(struct lxc_storage *b) + return 0; + } + ++// isulad: recored error ++static char **mount_errors = NULL; ++ + int mount_unknown_fs(const char *rootfs, const char *target, + const char *options) + { + size_t i; ++ char *errs = NULL; + int ret; + struct cbarg { + const char *rootfs; +@@ -371,15 +375,30 @@ int mount_unknown_fs(const char *rootfs, const char *target, + ret = lxc_file_for_each_line(fsfile[i], find_fstype_cb, &cbarg); + if (ret < 0) { + ERROR("Failed to parse \"%s\"", fsfile[i]); ++ lxc_free_array((void**)mount_errors, free); ++ mount_errors = NULL; + return -1; + } + +- if (ret) ++ if (ret) { ++ lxc_free_array((void**)mount_errors, free); ++ mount_errors = NULL; + return 0; ++ } ++ } ++ ++ if (mount_errors != NULL) { ++ errs = lxc_string_join("\n", (const char **)mount_errors, false); ++ if (errs == NULL) { ++ ERROR("failed to join mount errors"); ++ } + } + +- ERROR("Failed to determine FSType for \"%s\"", rootfs); ++ ERROR("Failed to determine FSType for \"%s\": %s", rootfs, errs ? errs : "unknown reason"); + ++ free(errs); ++ lxc_free_array((void**)mount_errors, free); ++ mount_errors = NULL; + return -1; + } + +@@ -399,6 +418,8 @@ int find_fstype_cb(char *buffer, void *data) + unsigned long mntflags, pflags; + char *mntdata; + char *fstype; ++ char mount_err[BUFSIZ] = {0}; ++ int ret; + + /* we don't try 'nodev' entries */ + if (strstr(buffer, "nodev")) +@@ -419,6 +440,17 @@ int find_fstype_cb(char *buffer, void *data) + if (mount(cbarg->rootfs, cbarg->target, fstype, (mntflags & ~MS_RDONLY), mntdata)) { + SYSDEBUG("Failed to mount"); + free(mntdata); ++ // isulad: recored error ++ ret = snprintf(mount_err, BUFSIZ, "\t\tmount %s onto %s with FSType %s failed: %s", ++ cbarg->rootfs, cbarg->target, fstype, strerror(errno)); ++ if (ret < 0 || (size_t)ret >= BUFSIZ) { ++ ERROR("failed to format output mount error"); ++ return 0; ++ } ++ ++ if (lxc_append_string(&mount_errors, mount_err) < 0) { ++ ERROR("failed to append mount error"); ++ } + return 0; + } + +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index d1a22f7..120a13d 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -1053,7 +1053,7 @@ static int open_if_safe(int dirfd, const char *nextpath) + * + * Return an open fd for the path, or <0 on error. + */ +-static int open_without_symlink(const char *target, const char *prefix_skip) ++int open_without_symlink(const char *target, const char *prefix_skip) + { + int curlen = 0, dirfd, fulllen, i; + char *dup; +@@ -1473,6 +1473,9 @@ static int lxc_get_unused_loop_dev(char *name_loop) + { + int loop_nr, ret; + int fd_ctl = -1, fd_tmp = -1; ++ // isulad: retry and try mknod ++ int max_retry = 200; ++ bool try_mknod = true; + + fd_ctl = open("/dev/loop-control", O_RDWR | O_CLOEXEC); + if (fd_ctl < 0) { +@@ -1489,10 +1492,34 @@ static int lxc_get_unused_loop_dev(char *name_loop) + ret = snprintf(name_loop, LO_NAME_SIZE, "/dev/loop%d", loop_nr); + if (ret < 0 || ret >= LO_NAME_SIZE) + goto on_error; +- ++retry: + fd_tmp = open(name_loop, O_RDWR | O_CLOEXEC); +- if (fd_tmp < 0) ++ if (fd_tmp < 0) { ++ /* Success of LOOP_CTL_GET_FREE doesn't mean /dev/loop$i is ready, ++ * we try to make node by ourself to avoid wait. */ ++ if (try_mknod) { ++ /* Do not check result of mknod because LOOP_CTL_GET_FREE ++ * alse do mknod, so this mknod may fail as node already ++ * exist. If we can open the node without error, we can ++ * say that it's be created successfully. ++ * ++ * note: 7 is the major device number of loopback devices ++ * in kernel. ++ */ ++ mknod(name_loop, S_IFBLK | 0640, makedev(7, loop_nr)); ++ try_mknod = false; ++ goto retry; ++ } ++ /* we need to wait some time to make sure it's ready for open if ++ * it can't open even if we have already try to make node by ourself. */ ++ if (max_retry > 0) { ++ max_retry--; ++ usleep(5000); /* 5 millisecond */ ++ goto retry; ++ } + SYSERROR("Failed to open loop \"%s\"", name_loop); ++ goto on_error; ++ } + + on_error: + close(fd_ctl); +diff --git a/src/lxc/utils.h b/src/lxc/utils.h +index abc88ca..4313942 100644 +--- a/src/lxc/utils.h ++++ b/src/lxc/utils.h +@@ -224,6 +224,7 @@ extern bool cgns_supported(void); + extern char *choose_init(const char *rootfs); + extern bool switch_to_ns(pid_t pid, const char *ns); + extern char *get_template_path(const char *t); ++extern int open_without_symlink(const char *target, const char *prefix_skip); + extern int safe_mount(const char *src, const char *dest, const char *fstype, + unsigned long flags, const void *data, + const char *rootfs); +-- +1.8.3.1 + diff --git a/0034-some-small-bugfix.patch b/0034-some-small-bugfix.patch new file mode 100644 index 0000000..b3bf1b2 --- /dev/null +++ b/0034-some-small-bugfix.patch @@ -0,0 +1,155 @@ +From 8e7742314071cbb163c1fc6ab4eb96bffd6bc64a Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Tue, 15 Jan 2019 20:39:11 +0800 +Subject: [PATCH 034/122] some small bugfix + +1. support new container without load config to save time +2. try to create workdir if not exist + +Signed-off-by: LiFeng +--- + src/lxc/attach.c | 16 ++++++++++++++++ + src/lxc/lxc.h | 5 +++++ + src/lxc/lxccontainer.c | 21 +++++++++++++++++---- + src/lxc/lxccontainer.h | 12 ++++++++++++ + src/lxc/start.c | 12 ++++++++---- + 5 files changed, 58 insertions(+), 8 deletions(-) + +diff --git a/src/lxc/attach.c b/src/lxc/attach.c +index e6e4b0d..8cbbf96 100644 +--- a/src/lxc/attach.c ++++ b/src/lxc/attach.c +@@ -806,6 +806,22 @@ static int attach_child_main(struct attach_clone_payload *payload) + TRACE("Dropped capabilities"); + } + ++ /* isulad: set workdir */ ++ if (init_ctx && init_ctx->container && init_ctx->container->lxc_conf && init_ctx->container->lxc_conf->init_cwd) { ++ char *init_cwd; ++ init_cwd = init_ctx->container->lxc_conf->init_cwd; ++ /* try to create workdir if not exist */ ++ struct stat st; ++ if (stat(init_cwd, &st) < 0 && mkdir_p(init_cwd, 0750) < 0) { ++ SYSERROR("Try to create directory \"%s\" as workdir failed when attach", init_cwd); ++ goto on_error; ++ } ++ if (chdir(init_cwd)) { ++ SYSERROR("Could not change directory to \"%s\" when attach", init_cwd); ++ goto on_error; ++ } ++ } ++ + /* Always set the environment (specify (LXC_ATTACH_KEEP_ENV, NULL, NULL) + * if you want this to be a no-op). + */ +diff --git a/src/lxc/lxc.h b/src/lxc/lxc.h +index 687b4b2..5df5080 100644 +--- a/src/lxc/lxc.h ++++ b/src/lxc/lxc.h +@@ -104,6 +104,11 @@ extern lxc_state_t lxc_state(const char *name, const char *lxcpath); + extern struct lxc_container *lxc_container_new(const char *name, const char *configpath); + + /* ++ * Create a new container without loading config. ++ */ ++extern struct lxc_container *lxc_container_without_config_new(const char *name, const char *configpath); ++ ++/* + * Returns 1 on success, 0 on failure. + */ + extern int lxc_container_get(struct lxc_container *c); +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index 38059fa..e99c41c 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -5133,7 +5133,7 @@ static bool do_lxcapi_clean_container_resource(struct lxc_container *c, pid_t pi + + WRAP_API_1(bool, lxcapi_clean_container_resource, pid_t) + +-struct lxc_container *lxc_container_new(const char *name, const char *configpath) ++static struct lxc_container *do_lxc_container_new(const char *name, const char *configpath, bool load_config) + { + struct lxc_container *c; + size_t len; +@@ -5190,9 +5190,11 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath + goto err; + } + +- if (file_exists(c->configfile) && !lxcapi_load_config(c, NULL)) { +- fprintf(stderr, "Failed to load config for %s\n", name); +- goto err; ++ if (load_config) { ++ if (file_exists(c->configfile) && !lxcapi_load_config(c, NULL)) { ++ fprintf(stderr, "Failed to load config for %s\n", name); ++ goto err; ++ } + } + + if (ongoing_create(c) == 2) { +@@ -5274,6 +5276,17 @@ err: + return NULL; + } + ++// isulad: new container without load config to save time ++struct lxc_container *lxc_container_without_config_new(const char *name, const char *configpath) ++{ ++ return do_lxc_container_new(name, configpath, false); ++} ++ ++struct lxc_container *lxc_container_new(const char *name, const char *configpath) ++{ ++ return do_lxc_container_new(name, configpath, true); ++} ++ + int lxc_get_wait_states(const char **states) + { + int i; +diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h +index 679ca42..a00e0ec 100644 +--- a/src/lxc/lxccontainer.h ++++ b/src/lxc/lxccontainer.h +@@ -1040,6 +1040,18 @@ struct lxc_console_log { + struct lxc_container *lxc_container_new(const char *name, const char *configpath); + + /*! ++ * \brief Create a new container without loading config. ++ * ++ * \param name Name to use for container. ++ * \param configpath Full path to configuration file to use. ++ * ++ * \return Newly-allocated container, or \c NULL on error. ++ * ++ * \note This function can only used for listing container. ++ */ ++struct lxc_container *lxc_container_without_config_new(const char *name, const char *configpath); ++ ++/*! + * \brief Add a reference to the specified container. + * + * \param c Container. +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 08d753a..040909c 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -1364,10 +1364,14 @@ static int do_start(void *data) + setsid(); + + if (handler->conf->init_cwd) { +- ret = chdir(handler->conf->init_cwd); +- if (ret < 0) { +- SYSERROR("Could not change directory to \"%s\"", +- handler->conf->init_cwd); ++ /* isulad: try to craete workdir if not exist */ ++ struct stat st; ++ if (stat(handler->conf->init_cwd, &st) < 0 && mkdir_p(handler->conf->init_cwd, 0755) < 0) { ++ SYSERROR("Try to create directory \"%s\" as workdir failed", handler->conf->init_cwd); ++ goto out_warn_father; ++ } ++ if (chdir(handler->conf->init_cwd)) { ++ SYSERROR("Could not change directory to \"%s\"", handler->conf->init_cwd); + goto out_warn_father; + } + } +-- +1.8.3.1 + diff --git a/0035-lxc-fixup-builds-with-newer-glibc.patch b/0035-lxc-fixup-builds-with-newer-glibc.patch new file mode 100644 index 0000000..15a2a4e --- /dev/null +++ b/0035-lxc-fixup-builds-with-newer-glibc.patch @@ -0,0 +1,25 @@ +From b84e0641198d562f8da88dcf98e24f55358523c7 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Wed, 16 Jan 2019 20:53:25 +0800 +Subject: [PATCH 035/122] lxc: fixup builds with newer glibc + +Signed-off-by: LiFeng +--- + src/lxc/utils.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index 120a13d..c8fb993 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -44,6 +44,7 @@ + #include + #include + #include ++#include + #include + #include + +-- +1.8.3.1 + diff --git a/0036-drop_caps-add-drop-caps-of-current-process.patch b/0036-drop_caps-add-drop-caps-of-current-process.patch new file mode 100644 index 0000000..cd4641d --- /dev/null +++ b/0036-drop_caps-add-drop-caps-of-current-process.patch @@ -0,0 +1,256 @@ +From 191cff886b75864a9304eb5e56fa29662978ffec Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Tue, 15 Jan 2019 22:55:06 -0500 +Subject: [PATCH 036/122] drop_caps: add drop caps of current process + +Signed-off-by: LiFeng +--- + src/lxc/attach.c | 26 +++++++++++++--- + src/lxc/cgroups/cgfsng.c | 35 ++++++++++----------- + src/lxc/conf.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ + src/lxc/conf.h | 1 + + src/lxc/start.c | 16 ++++++++++ + 5 files changed, 135 insertions(+), 22 deletions(-) + +diff --git a/src/lxc/attach.c b/src/lxc/attach.c +index 8cbbf96..3f60fe1 100644 +--- a/src/lxc/attach.c ++++ b/src/lxc/attach.c +@@ -936,11 +936,6 @@ static int attach_child_main(struct attach_clone_payload *payload) + TRACE("Loaded seccomp profile"); + } + +- close(payload->ipc_socket); +- payload->ipc_socket = -EBADF; +- lxc_proc_put_context_info(init_ctx); +- payload->init_ctx = NULL; +- + /* The following is done after the communication socket is shut down. + * That way, all errors that might (though unlikely) occur up until this + * point will have their messages printed to the original stderr (if +@@ -997,9 +992,30 @@ static int attach_child_main(struct attach_clone_payload *payload) + if (new_gid == ns_root_gid) + new_gid = LXC_INVALID_GID; + ++ if (prctl(PR_SET_KEEPCAPS, 1) < 0) { ++ SYSERROR("Failed to keep permitted capabilities"); ++ goto on_error; ++ } ++ + if (!lxc_switch_uid_gid(new_uid, new_gid)) + goto on_error; + ++ if (prctl(PR_SET_KEEPCAPS, 0) < 0) { ++ SYSERROR("Failed to clear permitted capabilities"); ++ goto on_error; ++ } ++ ++ if (init_ctx->container && init_ctx->container->lxc_conf && ++ lxc_drop_caps(init_ctx->container->lxc_conf) != 0) { ++ ERROR("Failed to drop caps."); ++ goto on_error; ++ } ++ ++ close(payload->ipc_socket); ++ payload->ipc_socket = -EBADF; ++ lxc_proc_put_context_info(init_ctx); ++ payload->init_ctx = NULL; ++ + /* We're done, so we can now do whatever the user intended us to do. */ + _exit(payload->exec_function(payload->exec_payload, msg_fd)); + +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index 8b913a6..bc1481d 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -2664,11 +2664,11 @@ __cgfsng_ops static bool cgfsng_data_init(struct cgroup_ops *ops, struct lxc_han + { + const char *cgroup_pattern; + char *container_cgroup, *tmp; +- struct lxc_conf *conf = handler->conf; ++ struct lxc_conf *conf = NULL; + size_t len; + +- if (!conf) +- return false; ++ if (handler) ++ conf = handler->conf; + + /* copy system-wide cgroup information */ + cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern"); +@@ -2680,21 +2680,22 @@ __cgfsng_ops static bool cgfsng_data_init(struct cgroup_ops *ops, struct lxc_han + ops->cgroup_pattern = must_copy_string(cgroup_pattern); + + /* isulad: init ops->container_cgroup here instead of in cgfsng_payload_create*/ +- if (conf->cgroup_meta.dir) +- tmp = lxc_string_join("/", (const char *[]){conf->cgroup_meta.dir, handler->name, NULL}, false); +- else +- tmp = lxc_string_replace("%n", handler->name, ops->cgroup_pattern); +- if (!tmp) { +- ERROR("Failed expanding cgroup name pattern"); +- return false; +- } +- +- len = strlen(tmp) + 1; +- container_cgroup = must_realloc(NULL, len); +- (void)strlcpy(container_cgroup, tmp, len); +- free(tmp); +- ops->container_cgroup = container_cgroup; ++ if (conf) { ++ if (conf->cgroup_meta.dir) ++ tmp = lxc_string_join("/", (const char *[]){conf->cgroup_meta.dir, handler->name, NULL}, false); ++ else ++ tmp = lxc_string_replace("%n", handler->name, ops->cgroup_pattern); ++ if (!tmp) { ++ ERROR("Failed expanding cgroup name pattern"); ++ return false; ++ } + ++ len = strlen(tmp) + 1; ++ container_cgroup = must_realloc(NULL, len); ++ (void)strlcpy(container_cgroup, tmp, len); ++ free(tmp); ++ ops->container_cgroup = container_cgroup; ++ } + return true; + } + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index fea0f59..6134ed3 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4220,6 +4220,85 @@ int lxc_setup(struct lxc_handler *handler) + return 0; + } + ++/* isulad drop caps for container*/ ++int lxc_drop_caps(struct lxc_conf *conf) ++{ ++#define __DEF_CAP_TO_MASK(x) (1U << ((x) & 31)) ++#if HAVE_LIBCAP ++ struct lxc_list *iterator; ++ char *keep_entry; ++ int i, capid; ++ int numcaps = lxc_caps_last_cap() + 1; ++ struct lxc_list *caps = NULL; ++ ++ if (lxc_list_empty(&conf->keepcaps)) ++ return 0; ++ ++ caps = &conf->keepcaps; ++ ++ if (numcaps <= 0 || numcaps > 200) ++ return -1; ++ ++ // caplist[i] is 1 if we keep capability i ++ int *caplist = alloca(numcaps * sizeof(int)); ++ memset(caplist, 0, numcaps * sizeof(int)); ++ ++ lxc_list_for_each(iterator, caps) { ++ ++ keep_entry = iterator->elem; ++ /* isulad: Do not keep any cap*/ ++ if (strcmp(keep_entry, "ISULAD_KEEP_NONE") == 0) { ++ DEBUG("Do not keep any capability"); ++ for(i = 0; i < numcaps; i++) { ++ caplist[i] = 0; ++ } ++ break; ++ } ++ ++ capid = parse_cap(keep_entry); ++ ++ if (capid == -2) ++ continue; ++ ++ if (capid < 0) { ++ ERROR("unknown capability %s", keep_entry); ++ return -1; ++ } ++ ++ DEBUG("keep capability '%s' (%d)", keep_entry, capid); ++ ++ caplist[capid] = 1; ++ } ++ ++ struct __user_cap_header_struct cap_header_data; ++ struct __user_cap_data_struct cap_data_data[2]; ++ ++ cap_user_header_t cap_header = &cap_header_data; ++ cap_user_data_t cap_data = &cap_data_data[0]; ++ ++ memset(cap_header, 0 ,sizeof(struct __user_cap_header_struct)); ++ memset(cap_data, 0, sizeof(struct __user_cap_data_struct) * 2); ++ ++ cap_header->pid = 0; ++ cap_header->version = _LINUX_CAPABILITY_VERSION; ++ ++ for (i = 0; i < numcaps; i++) { ++ if (caplist[i]) { ++ cap_data[CAP_TO_INDEX(i)].effective = cap_data[CAP_TO_INDEX(i)].effective | __DEF_CAP_TO_MASK(i); ++ cap_data[CAP_TO_INDEX(i)].permitted = cap_data[CAP_TO_INDEX(i)].permitted | __DEF_CAP_TO_MASK(i); ++ cap_data[CAP_TO_INDEX(i)].inheritable = cap_data[CAP_TO_INDEX(i)].inheritable | __DEF_CAP_TO_MASK(i); ++ } ++ } ++ ++ if (capset(cap_header, cap_data)) { ++ SYSERROR("Failed to set capabilitys"); ++ return -1; ++ } ++ ++#endif ++ return 0; ++} ++ + struct oci_hook_conf { + defs_hook *ocihook; + +diff --git a/src/lxc/conf.h b/src/lxc/conf.h +index 44feb98..b92c48e 100644 +--- a/src/lxc/conf.h ++++ b/src/lxc/conf.h +@@ -498,6 +498,7 @@ int lxc_clear_init_args(struct lxc_conf *lxc_conf); + int lxc_clear_populate_devices(struct lxc_conf *c); + int lxc_clear_rootfs_masked_paths(struct lxc_conf *c); + int lxc_clear_rootfs_ro_paths(struct lxc_conf *c); ++int lxc_drop_caps(struct lxc_conf *conf); + + /* isulad add end */ + +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 040909c..357e81d 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -1411,6 +1411,11 @@ static int do_start(void *data) + } + } + ++ if (prctl(PR_SET_KEEPCAPS, 1) < 0) { ++ SYSERROR("Failed to keep permitted capabilities"); ++ goto out_warn_father; ++ } ++ + /* The container has been setup. We can now switch to an unprivileged + * uid/gid. + */ +@@ -1448,6 +1453,17 @@ static int do_start(void *data) + goto out_warn_father; + } + ++ /* isulad: drop the cap of current process */ ++ if (prctl(PR_SET_KEEPCAPS, 0) < 0) { ++ SYSERROR("Failed to clear permitted capabilities"); ++ goto out_warn_father; ++ } ++ ++ if (lxc_drop_caps(handler->conf)) { ++ SYSERROR("Failed to drop caps"); ++ goto out_warn_father; ++ } ++ + /* After this call, we are in error because this ops should not return + * as it execs. + */ +-- +1.8.3.1 + diff --git a/0037-restore-default-signal-handlers-and-set-umask-0027.patch b/0037-restore-default-signal-handlers-and-set-umask-0027.patch new file mode 100644 index 0000000..6ae6146 --- /dev/null +++ b/0037-restore-default-signal-handlers-and-set-umask-0027.patch @@ -0,0 +1,113 @@ +From 9eadf4f23de1863de62710b08b624a468048a773 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Tue, 15 Jan 2019 23:14:14 -0500 +Subject: [PATCH 037/122] restore default signal handlers and set umask 0027 + +Signed-off-by: LiFeng +--- + src/lxc/attach.c | 22 +++++++++++++++++++++- + src/lxc/conf.c | 3 +++ + src/lxc/start.c | 18 +++++++++++++++++- + 3 files changed, 41 insertions(+), 2 deletions(-) + +diff --git a/src/lxc/attach.c b/src/lxc/attach.c +index 3f60fe1..4ccdd74 100644 +--- a/src/lxc/attach.c ++++ b/src/lxc/attach.c +@@ -750,7 +750,7 @@ static void lxc_put_attach_clone_payload(struct attach_clone_payload *p) + + static int attach_child_main(struct attach_clone_payload *payload) + { +- int fd, lsm_fd, ret; ++ int fd, lsm_fd, ret, i; + uid_t new_uid; + gid_t new_gid; + uid_t ns_root_uid = 0; +@@ -761,11 +761,31 @@ static int attach_child_main(struct attach_clone_payload *payload) + bool needs_lsm = (options->namespaces & CLONE_NEWNS) && + (options->attach_flags & LXC_ATTACH_LSM) && + init_ctx->lsm_label; ++ sigset_t mask; ++ + + /*isulad: record errpipe fd*/ + msg_fd = init_ctx->container->lxc_conf->errpipe[1]; + init_ctx->container->lxc_conf->errpipe[1] = -1; + ++ /*isulad: set system umask 0027 for safe control */ ++ umask(0027); ++ ++ /*isulad: restore default signal handlers and unblock all signals*/ ++ for (i = 1; i < NSIG; i++) ++ signal(i, SIG_DFL); ++ ++ ret = sigfillset(&mask); ++ if (ret < 0) { ++ SYSERROR("Failed to fill signal mask"); ++ goto on_error;; ++ } ++ ret = sigprocmask(SIG_UNBLOCK, &mask, NULL); ++ if (ret < 0) { ++ SYSERROR("Failed to set signal mask"); ++ goto on_error; ++ } ++ + /* A description of the purpose of this functionality is provided in the + * lxc-attach(1) manual page. We have to remount here and not in the + * parent process, otherwise /proc may not properly reflect the new pid +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 6134ed3..88cebfd 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4180,6 +4180,9 @@ int lxc_setup(struct lxc_handler *handler) + } + } + ++ /*isulad: set system umask 0027 for safe control*/ ++ umask(0027); ++ + ret = setup_personality(lxc_conf->personality); + if (ret < 0) { + ERROR("Failed to set personality"); +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 357e81d..708ab7f 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -1103,7 +1103,7 @@ void lxc_abort(const char *name, struct lxc_handler *handler) + + static int do_start(void *data) + { +- int ret; ++ int ret, i; + char path[PATH_MAX]; + uid_t new_uid; + gid_t new_gid; +@@ -1112,9 +1112,25 @@ static int do_start(void *data) + gid_t nsgid = 0; + int devnull_fd = -1; + struct lxc_handler *handler = data; ++ sigset_t mask; + + lxc_sync_fini_parent(handler); + ++ /*isulad: restore default signal handlers and unblock all signals*/ ++ for (i = 1; i < NSIG; i++) ++ signal(i, SIG_DFL); ++ ++ ret = sigfillset(&mask); ++ if (ret < 0) { ++ SYSERROR("Failed to fill signal mask"); ++ goto out_warn_father;; ++ } ++ ret = sigprocmask(SIG_UNBLOCK, &mask, NULL); ++ if (ret < 0) { ++ SYSERROR("Failed to set signal mask"); ++ goto out_warn_father; ++ } ++ + /* This prctl must be before the synchro, so if the parent dies before + * we set the parent death signal, we will detect its death with the + * synchro right after, otherwise we have a window where the parent can +-- +1.8.3.1 + diff --git a/0038-make-the-given-terminal-as-controlling-terminal.patch b/0038-make-the-given-terminal-as-controlling-terminal.patch new file mode 100644 index 0000000..fff5c08 --- /dev/null +++ b/0038-make-the-given-terminal-as-controlling-terminal.patch @@ -0,0 +1,46 @@ +From 05bdc32a321530e46325ca7fe8f67f9195f54962 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Tue, 15 Jan 2019 23:24:21 -0500 +Subject: [PATCH 038/122] make the given terminal as controlling terminal + +Avoid warning when start cmd /bin/sh : +sh: cannot set terminal process group (-1): Inappropriate ioctl for device +sh: no job control in this shell + +Signed-off-by: LiFeng +--- + src/lxc/start.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 708ab7f..ec61b32 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -1330,7 +1330,15 @@ static int do_start(void *data) + * setup on its console ie. the pty allocated in lxc_terminal_setup() so + * make sure that that pty is stdin,stdout,stderr. + */ ++ setsid(); + if (handler->conf->console.slave >= 0) { ++ /* isulad:make the given terminal as controlling terminal to avoid warning ++ * sh: cannot set terminal process group (-1): Inappropriate ioctl for device ++ * sh: no job control in this shell */ ++ if (ioctl(handler->conf->console.slave, TIOCSCTTY, NULL) < 0) { ++ ERROR("Faild to make the given terminal the controlling terminal of the calling process"); ++ goto out_warn_father; ++ } + if (handler->daemonize || !handler->conf->is_execute) + ret = set_stdfds(handler->conf->console.slave); + else +@@ -1377,8 +1385,6 @@ static int do_start(void *data) + devnull_fd = -1; + } + +- setsid(); +- + if (handler->conf->init_cwd) { + /* isulad: try to craete workdir if not exist */ + struct stat st; +-- +1.8.3.1 + diff --git a/0039-print-error-message-when-container-start-failed.patch b/0039-print-error-message-when-container-start-failed.patch new file mode 100644 index 0000000..36dc467 --- /dev/null +++ b/0039-print-error-message-when-container-start-failed.patch @@ -0,0 +1,816 @@ +From b8925094ceb77cc94c8305725aae4877636c13c1 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Wed, 16 Jan 2019 14:38:38 +0800 +Subject: [PATCH 039/122] print error message when container start failed + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/attach.c | 6 +-- + src/lxc/cgroups/cgfsng.c | 22 +++++++-- + src/lxc/cgroups/cgroup.c | 4 +- + src/lxc/cgroups/cgroup.h | 2 + + src/lxc/conf.c | 122 ++++++++++++++++++++++++++-------------------- + src/lxc/conf.h | 5 +- + src/lxc/execute.c | 3 +- + src/lxc/lxccontainer.c | 37 ++++++++++++-- + src/lxc/start.c | 14 ++++-- + src/lxc/start.h | 2 +- + src/lxc/tools/lxc_start.c | 3 ++ + 11 files changed, 147 insertions(+), 73 deletions(-) + +diff --git a/src/lxc/attach.c b/src/lxc/attach.c +index 4ccdd74..b44ea74 100644 +--- a/src/lxc/attach.c ++++ b/src/lxc/attach.c +@@ -1396,7 +1396,7 @@ int lxc_attach(const char *name, const char *lxcpath, + + /* Setup resource limits */ + if (!lxc_list_empty(&conf->limits)) { +- ret = setup_resource_limits(&conf->limits, pid); ++ ret = setup_resource_limits(&conf->limits, pid, -1); + if (ret < 0) + goto on_error; + } +@@ -1650,8 +1650,8 @@ int lxc_attach_run_command(void *payload, int msg_fd) + } + } + +- /* isulad: write errorm messages */ +- lxc_write_error_message(msg_fd, "exec: \"%s\": %s", cmd->program, strerror(errno)); ++ /* isulad: write error messages */ ++ lxc_write_error_message(msg_fd, "exec: \"%s\": %s.", cmd->program, strerror(errno)); + + SYSERROR("Failed to exec \"%s\"", cmd->program); + return ret; +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index bc1481d..47b12a6 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -1236,7 +1236,7 @@ static int mkdir_eexist_on_last(const char *dir, mode_t mode) + return 0; + } + +-static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname) ++static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname, int errfd) + { + int ret; + +@@ -1244,8 +1244,8 @@ static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname) + + if (file_exists(h->container_full_path)) { // it must not already exist + ERROR("Cgroup path \"%s\" already exist.", h->container_full_path); +- //lxc_write_error_message(errfd, "%s:%d: Cgroup path \"%s\" already exist.", +- // __FILE__, __LINE__, h->fullcgpath); ++ lxc_write_error_message(errfd, "%s:%d: Cgroup path \"%s\" already exist.", ++ __FILE__, __LINE__, h->container_full_path); + return false; + } + +@@ -1288,7 +1288,7 @@ __cgfsng_ops static bool cgfsng_payload_create(struct cgroup_ops *ops, + } + + for (i = 0; ops->hierarchies[i]; i++) { +- if (!create_path_for_hierarchy(ops->hierarchies[i], container_cgroup)) { ++ if (!create_path_for_hierarchy(ops->hierarchies[i], container_cgroup, ops->errfd)) { + SYSERROR("Failed to create %s", ops->hierarchies[i]->container_full_path); + return false; + } +@@ -2203,6 +2203,11 @@ static int cg_legacy_set_data(struct cgroup_ops *ops, const char *filename, + + fullpath = must_make_path(h->container_full_path, filename, NULL); + ret = lxc_write_to_file(fullpath, value, strlen(value), false, 0666); ++ if (ret) { ++ lxc_write_error_message(ops->errfd, ++ "%s:%d: setting cgroup config for ready process caused \"failed to write %s to %s: %s\".", ++ __FILE__, __LINE__, value, fullpath, strerror(errno)); ++ } + free(fullpath); + return ret; + } +@@ -2294,9 +2299,15 @@ static bool __cg_legacy_setup_limits(struct cgroup_ops *ops, + } + if (setvalue > readvalue) { + ERROR("The maximum allowed cpu-shares is %s", value); ++ lxc_write_error_message(ops->errfd, ++ "%s:%d: setting cgroup config for ready process caused \"The maximum allowed cpu-shares is %s\".", ++ __FILE__, __LINE__, value); + goto out; + } else if (setvalue < readvalue) { + ERROR("The minimum allowed cpu-shares is %s", value); ++ lxc_write_error_message(ops->errfd, ++ "%s:%d: setting cgroup config for ready process caused \"The minimum allowed cpu-shares is %s\".", ++ __FILE__, __LINE__, value); + goto out; + } + } +@@ -2699,7 +2710,7 @@ __cgfsng_ops static bool cgfsng_data_init(struct cgroup_ops *ops, struct lxc_han + return true; + } + +-struct cgroup_ops *cgfsng_ops_init(void) ++struct cgroup_ops *cgfsng_ops_init(int errfd) + { + struct cgroup_ops *cgfsng_ops; + +@@ -2715,6 +2726,7 @@ struct cgroup_ops *cgfsng_ops_init(void) + return NULL; + } + ++ cgfsng_ops->errfd = errfd; + cgfsng_ops->data_init = cgfsng_data_init; + cgfsng_ops->destroy = cgfsng_payload_destroy; + cgfsng_ops->payload_create = cgfsng_payload_create; +diff --git a/src/lxc/cgroups/cgroup.c b/src/lxc/cgroups/cgroup.c +index 8e7aef9..7442c31 100644 +--- a/src/lxc/cgroups/cgroup.c ++++ b/src/lxc/cgroups/cgroup.c +@@ -38,13 +38,13 @@ + + lxc_log_define(cgroup, lxc); + +-extern struct cgroup_ops *cgfsng_ops_init(void); ++extern struct cgroup_ops *cgfsng_ops_init(int errfd); + + struct cgroup_ops *cgroup_init(struct lxc_handler *handler) + { + struct cgroup_ops *cgroup_ops; + +- cgroup_ops = cgfsng_ops_init(); ++ cgroup_ops = cgfsng_ops_init(handler->conf->errpipe[1]); + if (!cgroup_ops) { + ERROR("Failed to initialize cgroup driver"); + return NULL; +diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h +index fa4871e..b6116f6 100644 +--- a/src/lxc/cgroups/cgroup.h ++++ b/src/lxc/cgroups/cgroup.h +@@ -92,6 +92,8 @@ struct cgroup_ops { + char **cgroup_use; + char *cgroup_pattern; + char *container_cgroup; ++ /* isulad: errfd */ ++ int errfd; + + /* @hierarchies + * - A NULL-terminated array of struct hierarchy, one per legacy +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 88cebfd..8fa63f7 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -2414,6 +2414,8 @@ static int mount_entry_create_dir_file(const struct mntent *mntent, + ret = mkdir_p(path, 0755); + if (ret < 0 && errno != EEXIST) { + SYSERROR("Failed to create directory \"%s\"", path); ++ lxc_write_error_message(rootfs->errfd, "%s:%d: mkdir %s: %s.", ++ __FILE__, __LINE__, path, strerror(errno)); + return -1; + } + } +@@ -2435,12 +2437,17 @@ static int mount_entry_create_dir_file(const struct mntent *mntent, + free(p1); + if (ret < 0 && errno != EEXIST) { + SYSERROR("Failed to create directory \"%s\"", path); ++ lxc_write_error_message(rootfs->errfd, "%s:%d: mkdir %s: %s.", ++ __FILE__, __LINE__, p2, strerror(errno)); + return -1; + } + + ret = mknod(path, S_IFREG | 0000, 0); +- if (ret < 0 && errno != EEXIST) ++ if (ret < 0 && errno != EEXIST) { ++ lxc_write_error_message(rootfs->errfd, "%s:%d: open %s: %s.", ++ __FILE__, __LINE__, path, strerror(errno)); + return -errno; ++ } + + return 0; + } +@@ -2550,7 +2557,9 @@ static inline int mount_entry_on_generic(struct mntent *mntent, + if (rootfs_path) { + rpath = follow_symlink_in_scope(path, rootfs_path); + if (!rpath) { +- ERROR("Failed to get real path for '%s'", path); ++ ERROR("Failed to get real path of '%s' in scope '%s'.", path, rootfs_path); ++ lxc_write_error_message(rootfs->errfd, "%s:%d: failed to get real path of '%s' in scope '%s'.", ++ __FILE__, __LINE__, path, rootfs_path); + return -1; + } + dest = rpath; +@@ -2558,6 +2567,8 @@ static inline int mount_entry_on_generic(struct mntent *mntent, + ret = check_mount_destination(rootfs_path, dest); + if (ret) { + ERROR("Mount destination is invalid: '%s'", dest); ++ lxc_write_error_message(rootfs->errfd, "%s:%d: mount destination is invalid: '%s'.", ++ __FILE__, __LINE__, dest); + free(rpath); + return -1; + } +@@ -2587,6 +2598,10 @@ static inline int mount_entry_on_generic(struct mntent *mntent, + ret = mount_entry(mntent->mnt_fsname, dest, mntent->mnt_type, mntflags, + pflags, mntdata, optional, dev, relative, rootfs_path); + } ++ if (ret < 0) { ++ lxc_write_error_message(rootfs->errfd, "%s:%d: failed to mount %s as type %s.", ++ __FILE__, __LINE__, mntent->mnt_fsname, mntent->mnt_type); ++ } + + free(mntdata); + free(rpath); +@@ -2949,7 +2964,7 @@ static int parse_resource(const char *res) + return resid; + } + +-int setup_resource_limits(struct lxc_list *limits, pid_t pid) ++int setup_resource_limits(struct lxc_list *limits, pid_t pid, int errfd) + { + int resid; + struct lxc_list *it; +@@ -2966,7 +2981,10 @@ int setup_resource_limits(struct lxc_list *limits, pid_t pid) + + #if HAVE_PRLIMIT || HAVE_PRLIMIT64 + if (prlimit(pid, resid, &lim->limit, NULL) != 0) { +- SYSERROR("Failed to set limit %s", lim->resource); ++ SYSERROR("Failed to set limit %s %lu %lu.", lim->resource, lim->limit.rlim_cur, lim->limit.rlim_max); ++ lxc_write_error_message(errfd, "%s:%d: Failed to set limit %s %lu %lu: %s.", ++ __FILE__, __LINE__, lim->resource, ++ lim->limit.rlim_cur, lim->limit.rlim_max, strerror(errno)); + return -1; + } + +@@ -3989,6 +4007,8 @@ int lxc_setup(struct lxc_handler *handler) + ret = lxc_setup_rootfs_prepare_root(lxc_conf, name, lxcpath); + if (ret < 0) { + ERROR("Failed to setup rootfs"); ++ lxc_write_error_message(lxc_conf->errpipe[1], "%s:%d: failed to setup rootfs %s.", ++ __FILE__, __LINE__, lxc_conf->rootfs.path); + return -1; + } + +@@ -3996,31 +4016,31 @@ int lxc_setup(struct lxc_handler *handler) + ret = setup_utsname(lxc_conf->utsname); + if (ret < 0) { + ERROR("Failed to setup the utsname %s", name); +- return -1; ++ goto on_error; + } + } + + ret = lxc_setup_keyring(); + if (ret < 0) +- return -1; ++ goto on_error; + + ret = lxc_setup_network_in_child_namespaces(lxc_conf, &lxc_conf->network); + if (ret < 0) { + ERROR("Failed to setup network"); +- return -1; ++ goto on_error; + } + + ret = lxc_network_send_name_and_ifindex_to_parent(handler); + if (ret < 0) { + ERROR("Failed to send network device names and ifindices to parent"); +- return -1; ++ goto on_error; + } + + if (lxc_conf->autodev > 0) { + ret = mount_autodev(name, &lxc_conf->rootfs, lxcpath); + if (ret < 0) { + ERROR("Failed to mount \"/dev\""); +- return -1; ++ goto on_error; + } + } + +@@ -4030,13 +4050,14 @@ int lxc_setup(struct lxc_handler *handler) + ret = lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & ~LXC_AUTO_CGROUP_MASK, handler); + if (ret < 0) { + ERROR("Failed to setup first automatic mounts"); +- return -1; ++ goto on_error; + } + ++ lxc_conf->rootfs.errfd = lxc_conf->errpipe[1]; + ret = setup_mount(lxc_conf, &lxc_conf->rootfs, lxc_conf->fstab, name, lxcpath); + if (ret < 0) { + ERROR("Failed to setup mounts"); +- return -1; ++ goto on_error; + } + + if (lxc_conf->is_execute) { +@@ -4047,13 +4068,13 @@ int lxc_setup(struct lxc_handler *handler) + ret = snprintf(path, PATH_MAX, SBINDIR "/init.lxc.static"); + if (ret < 0 || ret >= PATH_MAX) { + ERROR("Path to init.lxc.static too long"); +- return -1; ++ goto on_error; + } + + fd = open(path, O_PATH | O_CLOEXEC); + if (fd < 0) { + SYSERROR("Unable to open lxc.init.static"); +- return -1; ++ goto on_error; + } + + ((struct execute_args *)handler->data)->init_fd = fd; +@@ -4062,7 +4083,7 @@ int lxc_setup(struct lxc_handler *handler) + ret = lxc_execute_bind_init(handler); + if (ret < 0) { + ERROR("Failed to bind-mount the lxc init system"); +- return -1; ++ goto on_error; + } + } + } +@@ -4074,7 +4095,7 @@ int lxc_setup(struct lxc_handler *handler) + ret = lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & LXC_AUTO_CGROUP_MASK, handler); + if (ret < 0) { + ERROR("Failed to setup remaining automatic mounts"); +- return -1; ++ goto on_error; + } + + /*isulad: move mount entries here, before we do lxc_fill_autodev and populate devices */ +@@ -4083,27 +4104,27 @@ int lxc_setup(struct lxc_handler *handler) + &lxc_conf->mount_list, name, lxcpath); + if (ret < 0) { + ERROR("Failed to setup mount entries"); +- return -1; ++ goto on_error; + } + } + + ret = run_lxc_hooks(name, "mount", lxc_conf, NULL); + if (ret < 0) { + ERROR("Failed to run mount hooks"); +- return -1; ++ goto on_error; + } + + if (lxc_conf->autodev > 0) { + ret = run_lxc_hooks(name, "autodev", lxc_conf, NULL); + if (ret < 0) { + ERROR("Failed to run autodev hooks"); +- return -1; ++ goto on_error; + } + + ret = lxc_fill_autodev(&lxc_conf->rootfs); + if (ret < 0) { + ERROR("Failed to populate \"/dev\""); +- return -1; ++ goto on_error; + } + } + +@@ -4111,64 +4132,64 @@ int lxc_setup(struct lxc_handler *handler) + if (!lxc_list_empty(&lxc_conf->populate_devs)) { + if (setup_populate_devs(&lxc_conf->rootfs, &lxc_conf->populate_devs)) { + ERROR("Failed to setup devices in the container"); +- return -1;; ++ goto on_error; + } + } + + /* Make sure any start hooks are in the container */ + if (!verify_start_hooks(lxc_conf)) { + ERROR("Failed to verify start hooks"); +- return -1; ++ goto on_error; + } + + ret = lxc_setup_console(&lxc_conf->rootfs, &lxc_conf->console, + lxc_conf->ttys.dir); + if (ret < 0) { + ERROR("Failed to setup console"); +- return -1; ++ goto on_error; + } + + ret = lxc_setup_dev_symlinks(&lxc_conf->rootfs); + if (ret < 0) { + ERROR("Failed to setup \"/dev\" symlinks"); +- return -1; ++ goto on_error; + } + + ret = lxc_create_tmp_proc_mount(lxc_conf); + if (ret < 0) { + ERROR("Failed to \"/proc\" LSMs"); +- return -1; ++ goto on_error; + } + + ret = lxc_setup_rootfs_switch_root(&lxc_conf->rootfs); + if (ret < 0) { + ERROR("Failed to pivot root into rootfs"); +- return -1; ++ goto on_error; + } + + /* isulad: remount rootfs readonly if necessary */ + if (setup_rootfs_mountopts(&lxc_conf->rootfs)) { + ERROR("failed to set rootfs for '%s'", name); +- return -1; ++ goto on_error; + } + + if (lxc_conf->rootfs.path) { + ret = lxc_setup_devpts(lxc_conf); + if (ret < 0) { + ERROR("Failed to setup new devpts instance"); +- return -1; ++ goto on_error; + } + } + + ret = lxc_create_ttys(handler); + if (ret < 0) +- return -1; ++ goto on_error; + + //isulad: setup rootfs masked paths + if (!lxc_list_empty(&lxc_conf->rootfs.maskedpaths)) { + if (setup_rootfs_maskedpaths(&lxc_conf->rootfs.maskedpaths)) { + ERROR("failed to setup maskedpaths"); +- return -1; ++ goto on_error; + } + } + +@@ -4176,7 +4197,7 @@ int lxc_setup(struct lxc_handler *handler) + if (!lxc_list_empty(&lxc_conf->rootfs.ropaths)) { + if (setup_rootfs_ropaths(&lxc_conf->rootfs.ropaths)) { + ERROR("failed to setup readonlypaths"); +- return -1; ++ goto on_error; + } + } + +@@ -4186,7 +4207,7 @@ int lxc_setup(struct lxc_handler *handler) + ret = setup_personality(lxc_conf->personality); + if (ret < 0) { + ERROR("Failed to set personality"); +- return -1; ++ goto on_error; + } + + /* Set sysctl value to a path under /proc/sys as determined from the +@@ -4197,7 +4218,7 @@ int lxc_setup(struct lxc_handler *handler) + ret = setup_sysctl_parameters(&lxc_conf->sysctls); + if (ret < 0) { + ERROR("Failed to setup sysctl parameters"); +- return -1; ++ goto on_error; + } + } + +@@ -4206,21 +4227,24 @@ int lxc_setup(struct lxc_handler *handler) + ERROR("Container requests lxc.cap.drop and " + "lxc.cap.keep: either use lxc.cap.drop or " + "lxc.cap.keep, not both"); +- return -1; ++ goto on_error; + } + + if (dropcaps_except(&lxc_conf->keepcaps)) { + ERROR("Failed to keep capabilities"); +- return -1; ++ goto on_error; + } + } else if (setup_caps(&lxc_conf->caps)) { + ERROR("Failed to drop capabilities"); +- return -1; ++ goto on_error; + } + + NOTICE("The container \"%s\" is set up", name); + + return 0; ++on_error: ++ lxc_write_error_message(lxc_conf->errpipe[1], "Failed to setup lxc, please check the config file."); ++ return -1; + } + + /* isulad drop caps for container*/ +@@ -4555,11 +4579,9 @@ void* wait_ocihook_timeout(void *arg) + __FILE__, __LINE__, lxchook_names[conf->which], + (double)conf->timeout); + +- if (conf->errfd >= 0) { +- lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"hook ran past specified timeout of %.1fs\"", +- __FILE__, __LINE__, lxchook_names[conf->which], +- (double)conf->timeout); +- } ++ lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"hook ran past specified timeout of %.1fs\".", ++ __FILE__, __LINE__, lxchook_names[conf->which], ++ (double)conf->timeout); + + if (kill(conf->pid, SIGKILL) && errno != ESRCH) { + ERROR("Send kill signal failed"); +@@ -4640,22 +4662,18 @@ static int run_ocihook_buffer(struct oci_hook_conf *oconf, char *inmsg) + goto print_hook; + } else if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) { + ERROR("Script exited with status %d. output:%s", WEXITSTATUS(ret), output); +- if (conf->errfd >= 0) { +- lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"error running hook: exit status %d, output:%s\"", +- __FILE__, __LINE__, +- (conf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[conf->which], +- WEXITSTATUS(ret), output); +- } ++ lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"error running hook: exit status %d, output:%s\".", ++ __FILE__, __LINE__, ++ (conf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[conf->which], ++ WEXITSTATUS(ret), output); + + goto print_hook; + } else if (WIFSIGNALED(ret)) { + ERROR("Script terminated by signal %d.", WTERMSIG(ret)); +- if (conf->errfd >= 0) { +- lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"error running hook: Script terminated by signal %d\"", +- __FILE__, __LINE__, +- (conf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[conf->which], +- WTERMSIG(ret)); +- } ++ lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"error running hook: Script terminated by signal %d\".", ++ __FILE__, __LINE__, ++ (conf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[conf->which], ++ WTERMSIG(ret)); + + goto print_hook; + } +diff --git a/src/lxc/conf.h b/src/lxc/conf.h +index b92c48e..88f5b41 100644 +--- a/src/lxc/conf.h ++++ b/src/lxc/conf.h +@@ -175,6 +175,8 @@ struct lxc_rootfs { + struct lxc_list maskedpaths; + /* isulad: ropaths */ + struct lxc_list ropaths; ++ /* isulad: errfd */ ++ int errfd; + }; + + /* +@@ -462,7 +464,7 @@ extern int lxc_setup_rootfs_prepare_root(struct lxc_conf *conf, + const char *name, const char *lxcpath); + extern int lxc_setup(struct lxc_handler *handler); + extern int lxc_setup_parent(struct lxc_handler *handler); +-extern int setup_resource_limits(struct lxc_list *limits, pid_t pid); ++extern int setup_resource_limits(struct lxc_list *limits, pid_t pid, int errfd); + extern int find_unmapped_nsid(struct lxc_conf *conf, enum idtype idtype); + extern int mapped_hostid(unsigned id, struct lxc_conf *conf, + enum idtype idtype); +@@ -499,6 +501,7 @@ int lxc_clear_populate_devices(struct lxc_conf *c); + int lxc_clear_rootfs_masked_paths(struct lxc_conf *c); + int lxc_clear_rootfs_ro_paths(struct lxc_conf *c); + int lxc_drop_caps(struct lxc_conf *conf); ++void lxc_close_error_pipe(int *errpipe); + + /* isulad add end */ + +diff --git a/src/lxc/execute.c b/src/lxc/execute.c +index d388e63..3fc46c6 100644 +--- a/src/lxc/execute.c ++++ b/src/lxc/execute.c +@@ -40,7 +40,7 @@ + + lxc_log_define(execute, start); + +-static int execute_start(struct lxc_handler *handler, void* data) ++static int execute_start(struct lxc_handler *handler, void* data, int fd) + { + int argc_add, j; + char **argv; +@@ -91,6 +91,7 @@ static int execute_start(struct lxc_handler *handler, void* data) + else + execvp(argv[0], argv); + SYSERROR("Failed to exec %s", argv[0]); ++ lxc_write_error_message(fd, "Failed to exec: \"%s\": %s.", argv[0], strerror(errno)); + + free(argv); + out1: +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index e99c41c..d641851 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -916,7 +916,9 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a + NULL, + }; + char **init_cmd = NULL; +- int keepfds[4] = {-1, -1, -1, -1}; ++ int keepfds[] = {-1, -1, -1, -1, -1}; ++ ssize_t size_read; ++ char errbuf[BUFSIZ + 1] = {0}; + + /* container does exist */ + if (!c) +@@ -962,7 +964,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a + argv = init_cmd = split_init_cmd(conf->init_cmd); + } + +- /* isulad: use init argv as init cmd */ ++ /* isulad: use init argv as init cmd */ + if (!argv) { + argv = init_cmd = use_init_args(conf->init_argv, conf->init_argc); + } +@@ -986,10 +988,19 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a + char title[2048]; + pid_t pid; + ++ //isulad: pipdfd for get error message of child or grandchild process. ++ if (pipe2(conf->errpipe, O_CLOEXEC) != 0) { ++ SYSERROR("Failed to init errpipe"); ++ free_init_cmd(init_cmd); ++ lxc_free_handler(handler); ++ return false; ++ } ++ + pid = fork(); + if (pid < 0) { + free_init_cmd(init_cmd); + lxc_free_handler(handler); ++ lxc_close_error_pipe(conf->errpipe); + return false; + } + +@@ -999,11 +1010,23 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a + * the PID file, child will do the free and unlink. + */ + c->pidfile = NULL; ++ close(conf->errpipe[1]); ++ conf->errpipe[1] = -1; + + /* Wait for container to tell us whether it started + * successfully. + */ + started = wait_on_daemonized_start(handler, pid); ++ if (!started) { ++ size_read = read(conf->errpipe[0], errbuf, BUFSIZ); ++ if (size_read > 0) { ++ conf->errmsg = strdup(errbuf); ++ if (!conf->errmsg) ++ ERROR("Out of memory"); ++ } ++ } ++ close(conf->errpipe[0]); ++ conf->errpipe[0] = -1; + + free_init_cmd(init_cmd); + lxc_free_handler(handler); +@@ -1039,6 +1062,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a + if (pid != 0) { + free_init_cmd(init_cmd); + lxc_free_handler(handler); ++ lxc_close_error_pipe(conf->errpipe); + _exit(EXIT_SUCCESS); + } + +@@ -1050,10 +1074,12 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a + SYSERROR("Failed to change to \"/\" directory"); + _exit(EXIT_FAILURE); + } +- ++ close(conf->errpipe[0]); ++ conf->errpipe[0] = -1; + keepfds[0] = handler->conf->maincmd_fd; + keepfds[1] = handler->state_socket_pair[0]; + keepfds[2] = handler->state_socket_pair[1]; ++ keepfds[4] = conf->errpipe[1]; + ret = lxc_check_inherited(conf, true, keepfds, + sizeof(keepfds) / sizeof(keepfds[0])); + if (ret < 0) +@@ -1088,6 +1114,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a + if (w < 0 || (size_t)w >= sizeof(pidstr)) { + free_init_cmd(init_cmd); + lxc_free_handler(handler); ++ lxc_close_error_pipe(conf->errpipe); + + SYSERROR("Failed to write monitor pid to \"%s\"", c->pidfile); + +@@ -1101,6 +1128,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a + if (ret < 0) { + free_init_cmd(init_cmd); + lxc_free_handler(handler); ++ lxc_close_error_pipe(conf->errpipe); + + SYSERROR("Failed to write monitor pid to \"%s\"", c->pidfile); + +@@ -1159,6 +1187,9 @@ reboot: + if (conf->exit_fd >= 0) { + keepfds[3] = conf->exit_fd; + } ++ /* isulad: keep errpipe fd */ ++ if (c->daemonize) ++ keepfds[4] = conf->errpipe[1]; + ret = lxc_check_inherited(conf, c->daemonize, keepfds, + sizeof(keepfds) / sizeof(keepfds[0])); + if (ret < 0) { +diff --git a/src/lxc/start.c b/src/lxc/start.c +index ec61b32..3e6854f 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -892,6 +892,7 @@ int lxc_init(const char *name, struct lxc_handler *handler) + ret = lxc_terminal_setup(conf); + if (ret < 0) { + ERROR("Failed to create console"); ++ lxc_write_error_message(conf->errpipe[1], "Failed to create console for container \"%s\".", name); + goto out_restore_sigmask; + } + TRACE("Created console"); +@@ -1390,6 +1391,8 @@ static int do_start(void *data) + struct stat st; + if (stat(handler->conf->init_cwd, &st) < 0 && mkdir_p(handler->conf->init_cwd, 0755) < 0) { + SYSERROR("Try to create directory \"%s\" as workdir failed", handler->conf->init_cwd); ++ lxc_write_error_message(handler->conf->errpipe[1], "%s:%d: Failed to create workdir: %s.", ++ __FILE__, __LINE__, strerror(errno)); + goto out_warn_father; + } + if (chdir(handler->conf->init_cwd)) { +@@ -1489,7 +1492,7 @@ static int do_start(void *data) + /* After this call, we are in error because this ops should not return + * as it execs. + */ +- handler->ops->start(handler, handler->data); ++ handler->ops->start(handler, handler->data, handler->daemonize ? handler->conf->errpipe[1] : -1); + + out_warn_father: + /* We want the parent to know something went wrong, so we return a +@@ -1898,7 +1901,7 @@ static int lxc_spawn(struct lxc_handler *handler) + goto out_delete_net; + + if (!lxc_list_empty(&conf->limits)) { +- ret = setup_resource_limits(&conf->limits, handler->pid); ++ ret = setup_resource_limits(&conf->limits, handler->pid, conf->errpipe[1]); + if (ret < 0) { + ERROR("Failed to setup resource limits"); + goto out_delete_net; +@@ -1960,7 +1963,7 @@ static int lxc_spawn(struct lxc_handler *handler) + } + + if (START_TIMEOUT == global_timeout_state) { +- //lxc_write_error_message(conf->errpipe[1], "Starting the container \"%s\" timeout.", name); ++ lxc_write_error_message(conf->errpipe[1], "Starting the container \"%s\" timeout.", name); + ERROR("Starting the container \"%s\" timeout.", name); + goto out_delete_net; + } +@@ -2008,7 +2011,7 @@ static int lxc_spawn(struct lxc_handler *handler) + } + + if (START_TIMEOUT == global_timeout_state) { +- //lxc_write_error_message(conf->errpipe[1], "Starting the container \"%s\" timeout.", name); ++ lxc_write_error_message(conf->errpipe[1], "Starting the container \"%s\" timeout.", name); + ERROR("Starting the container \"%s\" timeout.", name); + goto out_abort; + } +@@ -2232,7 +2235,7 @@ struct start_args { + char *const *argv; + }; + +-static int start(struct lxc_handler *handler, void* data) ++static int start(struct lxc_handler *handler, void* data, int fd) + { + struct start_args *arg = data; + +@@ -2240,6 +2243,7 @@ static int start(struct lxc_handler *handler, void* data) + + execvp(arg->argv[0], arg->argv); + SYSERROR("Failed to exec \"%s\"", arg->argv[0]); ++ lxc_write_error_message(fd, "exec: \"%s\": %s.", arg->argv[0], strerror(errno)); + return 0; + } + +diff --git a/src/lxc/start.h b/src/lxc/start.h +index 1d84325..ab72e6e 100644 +--- a/src/lxc/start.h ++++ b/src/lxc/start.h +@@ -145,7 +145,7 @@ struct execute_args { + }; + + struct lxc_operations { +- int (*start)(struct lxc_handler *, void *); ++ int (*start)(struct lxc_handler *, void *, int); + int (*post_start)(struct lxc_handler *, void *); + }; + +diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c +index f37f8a6..ec48701 100644 +--- a/src/lxc/tools/lxc_start.c ++++ b/src/lxc/tools/lxc_start.c +@@ -392,6 +392,9 @@ int main(int argc, char *argv[]) + else + err = c->start(c, 0, args) ? EXIT_SUCCESS : EXIT_FAILURE; + if (err) { ++ if (c->lxc_conf->errmsg) ++ fprintf(stderr, "%s:%s:%s:%d starting container process caused \"%s\"", c->name, ++ __FILE__, __func__, __LINE__, c->lxc_conf->errmsg); + ERROR("The container failed to start"); + + if (my_args.daemonize) +-- +1.8.3.1 + diff --git a/0040-add-timeout-200ms-for-cmds-send-to-lxc-monitor.patch b/0040-add-timeout-200ms-for-cmds-send-to-lxc-monitor.patch new file mode 100644 index 0000000..223472b --- /dev/null +++ b/0040-add-timeout-200ms-for-cmds-send-to-lxc-monitor.patch @@ -0,0 +1,107 @@ +From a03cf6d594d7b310138b898fd1c49ce031322e48 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Wed, 16 Jan 2019 02:22:13 -0500 +Subject: [PATCH 040/122] add timeout(200ms) for cmds send to [lxc monitor] + +Signed-off-by: LiFeng +--- + src/lxc/af_unix.c | 25 +++++++++++++++++++++++-- + src/lxc/af_unix.h | 2 ++ + src/lxc/commands.c | 7 +++++-- + 3 files changed, 30 insertions(+), 4 deletions(-) + +diff --git a/src/lxc/af_unix.c b/src/lxc/af_unix.c +index 02f32c4..24500a8 100644 +--- a/src/lxc/af_unix.c ++++ b/src/lxc/af_unix.c +@@ -194,8 +194,9 @@ int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds, + return ret; + } + +-int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds, +- void *data, size_t size) ++/* isulad: add wait timeout Microseconds*/ ++int lxc_abstract_unix_recv_fds_timeout(int fd, int *recvfds, int num_recvfds, ++ void *data, size_t size, unsigned int timeout) + { + int ret; + struct msghdr msg; +@@ -204,6 +205,7 @@ int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds, + char buf[1] = {0}; + char *cmsgbuf; + size_t cmsgbufsize = CMSG_SPACE(num_recvfds * sizeof(int)); ++ struct timeval out; + + memset(&msg, 0, sizeof(msg)); + memset(&iov, 0, sizeof(iov)); +@@ -222,6 +224,19 @@ int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds, + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + ++ if (timeout > 0) { ++ memset(&out, 0, sizeof(out)); ++ out.tv_sec = timeout / 1000000; ++ out.tv_usec = timeout % 1000000; ++ ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, ++ (const void *)&out, sizeof(out)); ++ if (ret < 0) { ++ ERROR("Failed to set %u timeout on containter " ++ "state socket", timeout); ++ goto out; ++ } ++ } ++ + ret = recvmsg(fd, &msg, 0); + if (ret <= 0) + goto out; +@@ -238,6 +253,12 @@ out: + return ret; + } + ++int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds, ++ void *data, size_t size) ++{ ++ return lxc_abstract_unix_recv_fds_timeout(fd, recvfds, num_recvfds, data, size, 0); ++} ++ + int lxc_abstract_unix_send_credential(int fd, void *data, size_t size) + { + struct msghdr msg = {0}; +diff --git a/src/lxc/af_unix.h b/src/lxc/af_unix.h +index f2c2fdc..74fd77f 100644 +--- a/src/lxc/af_unix.h ++++ b/src/lxc/af_unix.h +@@ -37,5 +37,7 @@ extern int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds, + void *data, size_t size); + extern int lxc_abstract_unix_send_credential(int fd, void *data, size_t size); + extern int lxc_abstract_unix_rcv_credential(int fd, void *data, size_t size); ++extern int lxc_abstract_unix_recv_fds_timeout(int fd, int *recvfds, int num_recvfds, ++ void *data, size_t size, unsigned int timeout); + + #endif /* __LXC_AF_UNIX_H */ +diff --git a/src/lxc/commands.c b/src/lxc/commands.c +index 133384d..47a824a 100644 +--- a/src/lxc/commands.c ++++ b/src/lxc/commands.c +@@ -126,13 +126,16 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd) + int ret, rspfd; + struct lxc_cmd_rsp *rsp = &cmd->rsp; + +- ret = lxc_abstract_unix_recv_fds(sock, &rspfd, 1, rsp, sizeof(*rsp)); ++ /*isulad: add timeout 200ms to avoid long block due to [lxc monitor] error*/ ++ ret = lxc_abstract_unix_recv_fds_timeout(sock, &rspfd, 1, rsp, sizeof(*rsp), 200 * 1000); + if (ret < 0) { + SYSWARN("Failed to receive response for command \"%s\"", + lxc_cmd_str(cmd->req.cmd)); + +- if (errno == ECONNRESET) ++ if (errno == ECONNRESET || errno == EAGAIN || errno == EWOULDBLOCK) { ++ errno = ECONNRESET; /*isulad set errno ECONNRESET when timeout */ + return -1; ++ } + + return -1; + } +-- +1.8.3.1 + diff --git a/0041-return-1-when-_lxc_start-fails.patch b/0041-return-1-when-_lxc_start-fails.patch new file mode 100644 index 0000000..ad6c1e0 --- /dev/null +++ b/0041-return-1-when-_lxc_start-fails.patch @@ -0,0 +1,25 @@ +From ea7fe5755309e9054ac06542b8fc0abb25039b7e Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Wed, 16 Jan 2019 05:53:36 -0500 +Subject: [PATCH 041/122] return -1 when _lxc_start fails + +Signed-off-by: LiFeng +--- + src/lxc/start.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 3e6854f..7bbcb00 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -2175,6 +2175,7 @@ int __lxc_start(const char *name, struct lxc_handler *handler, + + if (!handler->init_died && handler->pid > 0) { + ERROR("Child process is not killed"); ++ ret = -1; + goto out_abort; + } + +-- +1.8.3.1 + diff --git a/0042-lxc-seccomp-adopt-to-lxc3.0.patch b/0042-lxc-seccomp-adopt-to-lxc3.0.patch new file mode 100644 index 0000000..1f2989c --- /dev/null +++ b/0042-lxc-seccomp-adopt-to-lxc3.0.patch @@ -0,0 +1,169 @@ +From 6beb5e3a4afe7fede796fc547a29c6175512f024 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Thu, 17 Jan 2019 03:09:00 +0800 +Subject: [PATCH 042/122] lxc: seccomp adopt to lxc3.0 + +Signed-off-by: LiFeng +--- + src/lxc/seccomp.c | 127 ++++++++++++++++++++++++++++-------------------------- + 1 file changed, 65 insertions(+), 62 deletions(-) + +diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c +index 1e14be1..27bdc22 100644 +--- a/src/lxc/seccomp.c ++++ b/src/lxc/seccomp.c +@@ -936,86 +936,89 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c + SCMP_ARCH_NATIVE, line, rule.action, + get_action_name(rule.action)); + +- if (ctx.architectures[0] != SCMP_ARCH_NATIVE) { +- if (!do_resolve_add_rule(ctx.architectures[0], line, +- ctx.contexts[0], &rule)) +- goto bad_rule; +- +- INFO("Added compat rule for arch %d for %s action %d(%s)", +- ctx.architectures[0], line, rule.action, +- get_action_name(rule.action)); +- } ++ if (cur_rule_arch == lxc_seccomp_arch_all) { ++ if (ctx.architectures[0] != SCMP_ARCH_NATIVE) { ++ if (!do_resolve_add_rule(ctx.architectures[0], line, ++ ctx.contexts[0], &rule)) ++ goto bad_rule; ++ ++ INFO("Added compat rule for arch %d for %s action %d(%s)", ++ ctx.architectures[0], line, rule.action, ++ get_action_name(rule.action)); ++ } + +- if (ctx.architectures[1] != SCMP_ARCH_NATIVE) { +- if (!do_resolve_add_rule(ctx.architectures[1], line, +- ctx.contexts[1], &rule)) +- goto bad_rule; ++ if (ctx.architectures[1] != SCMP_ARCH_NATIVE) { ++ if (!do_resolve_add_rule(ctx.architectures[1], line, ++ ctx.contexts[1], &rule)) ++ goto bad_rule; + +- INFO("Added compat rule for arch %d for %s action %d(%s)", +- ctx.architectures[1], line, rule.action, +- get_action_name(rule.action)); +- } ++ INFO("Added compat rule for arch %d for %s action %d(%s)", ++ ctx.architectures[1], line, rule.action, ++ get_action_name(rule.action)); ++ } + +- if (ctx.architectures[2] != SCMP_ARCH_NATIVE) { +- if (!do_resolve_add_rule(ctx.architectures[2], line, ++ if (ctx.architectures[2] != SCMP_ARCH_NATIVE) { ++ if (!do_resolve_add_rule(ctx.architectures[2], line, + ctx.contexts[2], &rule)) +- goto bad_rule; ++ goto bad_rule; + +- INFO("Added native rule for arch %d for %s action %d(%s)", +- ctx.architectures[2], line, rule.action, +- get_action_name(rule.action)); ++ INFO("Added native rule for arch %d for %s action %d(%s)", ++ ctx.architectures[2], line, rule.action, ++ get_action_name(rule.action)); ++ } + } + } + +- INFO("Merging compat seccomp contexts into main context"); +- if (ctx.contexts[0]) { +- if (ctx.needs_merge[0]) { +- ret = seccomp_merge(conf->seccomp_ctx, ctx.contexts[0]); +- if (ret < 0) { +- ERROR("Failed to merge first compat seccomp " ++ if (cur_rule_arch == lxc_seccomp_arch_all) { ++ INFO("Merging compat seccomp contexts into main context"); ++ if (ctx.contexts[0]) { ++ if (ctx.needs_merge[0]) { ++ ret = seccomp_merge(conf->seccomp_ctx, ctx.contexts[0]); ++ if (ret < 0) { ++ ERROR("Failed to merge first compat seccomp " + "context into main context"); +- goto bad; +- } ++ goto bad; ++ } + +- TRACE("Merged first compat seccomp context into main context"); +- } else { +- seccomp_release(ctx.contexts[0]); +- ctx.contexts[0] = NULL; ++ TRACE("Merged first compat seccomp context into main context"); ++ } else { ++ seccomp_release(ctx.contexts[0]); ++ ctx.contexts[0] = NULL; ++ } + } +- } + +- if (ctx.contexts[1]) { +- if (ctx.needs_merge[1]) { +- ret = seccomp_merge(conf->seccomp_ctx, ctx.contexts[1]); +- if (ret < 0) { +- ERROR("Failed to merge first compat seccomp " +- "context into main context"); +- goto bad; +- } ++ if (ctx.contexts[1]) { ++ if (ctx.needs_merge[1]) { ++ ret = seccomp_merge(conf->seccomp_ctx, ctx.contexts[1]); ++ if (ret < 0) { ++ ERROR("Failed to merge first compat seccomp " ++ "context into main context"); ++ goto bad; ++ } + +- TRACE("Merged second compat seccomp context into main context"); +- } else { +- seccomp_release(ctx.contexts[1]); +- ctx.contexts[1] = NULL; ++ TRACE("Merged second compat seccomp context into main context"); ++ } else { ++ seccomp_release(ctx.contexts[1]); ++ ctx.contexts[1] = NULL; ++ } + } +- } + +- if (ctx.contexts[2]) { +- if (ctx.needs_merge[2]) { +- ret = seccomp_merge(conf->seccomp_ctx, ctx.contexts[2]); +- if (ret < 0) { +- ERROR("Failed to merge third compat seccomp " +- "context into main context"); +- goto bad; +- } ++ if (ctx.contexts[2]) { ++ if (ctx.needs_merge[2]) { ++ ret = seccomp_merge(conf->seccomp_ctx, ctx.contexts[2]); ++ if (ret < 0) { ++ ERROR("Failed to merge third compat seccomp " ++ "context into main context"); ++ goto bad; ++ } + +- TRACE("Merged third compat seccomp context into main context"); +- } else { +- seccomp_release(ctx.contexts[2]); +- ctx.contexts[2] = NULL; ++ TRACE("Merged third compat seccomp context into main context"); ++ } else { ++ seccomp_release(ctx.contexts[2]); ++ ctx.contexts[2] = NULL; ++ } + } + } +- + free(line); + return 0; + +-- +1.8.3.1 + diff --git a/0043-check-null-pointer-of-handler-to-fix-coredump-of-att.patch b/0043-check-null-pointer-of-handler-to-fix-coredump-of-att.patch new file mode 100644 index 0000000..e34ca7b --- /dev/null +++ b/0043-check-null-pointer-of-handler-to-fix-coredump-of-att.patch @@ -0,0 +1,28 @@ +From 7be24baf1379d45651d10f63cb7e1cb59bdc733c Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Thu, 17 Jan 2019 10:19:37 +0800 +Subject: [PATCH 043/122] check null pointer of handler to fix coredump of + attach + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/cgroups/cgroup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lxc/cgroups/cgroup.c b/src/lxc/cgroups/cgroup.c +index 7442c31..720a6c9 100644 +--- a/src/lxc/cgroups/cgroup.c ++++ b/src/lxc/cgroups/cgroup.c +@@ -44,7 +44,7 @@ struct cgroup_ops *cgroup_init(struct lxc_handler *handler) + { + struct cgroup_ops *cgroup_ops; + +- cgroup_ops = cgfsng_ops_init(handler->conf->errpipe[1]); ++ cgroup_ops = cgfsng_ops_init(handler ? handler->conf->errpipe[1] : -1); + if (!cgroup_ops) { + ERROR("Failed to initialize cgroup driver"); + return NULL; +-- +1.8.3.1 + diff --git a/0044-support-space-in-volume-mount-and-env.patch b/0044-support-space-in-volume-mount-and-env.patch new file mode 100644 index 0000000..7fe8a48 --- /dev/null +++ b/0044-support-space-in-volume-mount-and-env.patch @@ -0,0 +1,118 @@ +From baabb2596394fecf89c610e2473d8b930595f3aa Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Thu, 17 Jan 2019 10:18:23 +0800 +Subject: [PATCH 044/122] support space in --volume, --mount and --env + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 16 ++++++++++++++++ + src/lxc/confile.c | 9 ++++++++- + src/lxc/namespace.h | 1 + + src/lxc/utils.h | 3 +++ + 4 files changed, 28 insertions(+), 1 deletion(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 8fa63f7..48e31af 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -54,6 +54,7 @@ + #include + #include + #include ++#include + + #include "af_unix.h" + #include "caps.h" +@@ -2695,6 +2696,19 @@ static int mount_file_entries(const struct lxc_conf *conf, + int ret = -1; + + while (getmntent_r(file, &mntent, buf, sizeof(buf))) { ++ /* Note: Workaround for volume file path with space*/ ++ mntent.mnt_fsname = lxc_string_replace(SPACE_MAGIC_STR, " ", mntent.mnt_fsname); ++ if(!mntent.mnt_fsname) { ++ SYSERROR("memory allocation error"); ++ return -1; ++ } ++ mntent.mnt_dir = lxc_string_replace(SPACE_MAGIC_STR, " ", mntent.mnt_dir); ++ if(!mntent.mnt_dir) { ++ SYSERROR("memory allocation error"); ++ free(mntent.mnt_fsname); ++ return -1; ++ } ++ ERROR("mntent.mnt_fsname:%s, mntent.mnt_dir:%s", mntent.mnt_fsname, mntent.mnt_dir); + if (!rootfs->path) + ret = mount_entry_on_systemfs(&mntent); + else if (mntent.mnt_dir[0] != '/') +@@ -2703,6 +2717,8 @@ static int mount_file_entries(const struct lxc_conf *conf, + else + ret = mount_entry_on_absolute_rootfs(&mntent, rootfs, + lxc_name, lxc_path); ++ free(mntent.mnt_fsname); ++ free(mntent.mnt_dir); + if (ret < 0) + return -1; + } +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index db63b55..7e9d5c8 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -1036,6 +1036,7 @@ static int set_config_environment(const char *key, const char *value, + struct lxc_conf *lxc_conf, void *data) + { + struct lxc_list *list_item = NULL; ++ char *replaced; + + if (lxc_config_value_empty(value)) + return lxc_clear_environment(lxc_conf); +@@ -1044,7 +1045,12 @@ static int set_config_environment(const char *key, const char *value, + if (!list_item) + goto on_error; + +- list_item->elem = strdup(value); ++ /* isulad: recover space replaced by SPACE_MAGIC_STR */ ++ replaced = lxc_string_replace(SPACE_MAGIC_STR, " ", value); ++ if(!replaced) ++ goto on_error; ++ ++ list_item->elem = replaced; + + if (!list_item->elem) + goto on_error; +@@ -3661,6 +3667,7 @@ static int get_config_environment(const char *key, char *retv, int inlen, + memset(retv, 0, inlen); + + lxc_list_for_each(it, &c->environment) { ++ + strprint(retv, inlen, "%s\n", (char *)it->elem); + } + +diff --git a/src/lxc/namespace.h b/src/lxc/namespace.h +index ab583da..9caaf89 100644 +--- a/src/lxc/namespace.h ++++ b/src/lxc/namespace.h +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + #ifndef CLONE_PARENT_SETTID + #define CLONE_PARENT_SETTID 0x00100000 +diff --git a/src/lxc/utils.h b/src/lxc/utils.h +index 4313942..73ffdd9 100644 +--- a/src/lxc/utils.h ++++ b/src/lxc/utils.h +@@ -43,6 +43,9 @@ + #include "raw_syscalls.h" + #include "string_utils.h" + ++/* isulad: replace space with SPACE_MAGIC_STR */ ++#define SPACE_MAGIC_STR "[#)" ++ + /* returns 1 on success, 0 if there were any failures */ + extern int lxc_rmdir_onedev(const char *path, const char *exclude); + extern int get_u16(unsigned short *val, const char *arg, int base); +-- +1.8.3.1 + diff --git a/0045-add_terminal_fifos-Add-terminal-fifos-dynamically.patch b/0045-add_terminal_fifos-Add-terminal-fifos-dynamically.patch new file mode 100644 index 0000000..2cbfe24 --- /dev/null +++ b/0045-add_terminal_fifos-Add-terminal-fifos-dynamically.patch @@ -0,0 +1,254 @@ +From 698f04aa780eed16e70f96f3405596e98f3828a2 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Thu, 17 Jan 2019 02:18:14 -0500 +Subject: [PATCH 045/122] add_terminal_fifos: Add terminal fifos dynamically + +Signed-off-by: LiFeng +--- + src/lxc/commands.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ + src/lxc/commands.h | 4 ++++ + src/lxc/lxccontainer.c | 24 +++++++++++++++++++ + src/lxc/lxccontainer.h | 10 ++++++++ + src/lxc/terminal.c | 47 ++++++++++++++++++++++++++++++++++++++ + src/lxc/terminal.h | 1 + + 6 files changed, 148 insertions(+) + +diff --git a/src/lxc/commands.c b/src/lxc/commands.c +index 47a824a..46b2805 100644 +--- a/src/lxc/commands.c ++++ b/src/lxc/commands.c +@@ -96,6 +96,7 @@ static const char *lxc_cmd_str(lxc_cmd_t cmd) + [LXC_CMD_ADD_STATE_CLIENT] = "add_state_client", + [LXC_CMD_CONSOLE_LOG] = "console_log", + [LXC_CMD_SERVE_STATE_CLIENTS] = "serve_state_clients", ++ [LXC_CMD_SET_TERMINAL_FIFOS] = "set_terminal_fifos", + }; + + if (cmd >= LXC_CMD_MAX) +@@ -1056,6 +1057,66 @@ reap_client_fd: + return 1; + } + ++/* ++ * isulad: lxc_cmd_set_terminal_fifos: Set the fifos used for the container as terminal input/output ++ * ++ * @hashed_sock_name: hashed socket name ++ * ++ * Returns 0 when success, else when fail. ++ */ ++int lxc_cmd_set_terminal_fifos(const char *name, const char *lxcpath, const char *in_fifo, const char *out_fifo) ++{ ++ int ret = 0, stopped = 0; ++ int len = 0; ++ char *tmp = NULL; ++ ++ if (!in_fifo || !out_fifo) { ++ return -1; ++ } ++ ++ len = strlen(in_fifo) + strlen("&&&&") + strlen(out_fifo) + 1; ++ tmp = malloc(len); ++ if (!tmp) ++ return -1; ++ snprintf(tmp, len, "%s%s%s", in_fifo, "&&&&", out_fifo); ++ ++ struct lxc_cmd_rr cmd = { ++ .req = { ++ .cmd = LXC_CMD_SET_TERMINAL_FIFOS, ++ .datalen = strlen(tmp)+1, ++ .data = tmp, ++ }, ++ }; ++ ++ ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL); ++ if (ret < 0) { ++ ERROR("Failed to send command to container"); ++ free(tmp); ++ return -1; ++ } ++ ++ if (cmd.rsp.ret != 0) { ++ ERROR("Command response error:%d", cmd.rsp.ret); ++ free(tmp); ++ return -1; ++ } ++ ++ free(tmp); ++ return 0; ++} ++ ++static int lxc_cmd_set_terminal_fifos_callback(int fd, struct lxc_cmd_req *req, ++ struct lxc_handler *handler) ++{ ++ struct lxc_cmd_rsp rsp; ++ memset(&rsp, 0, sizeof(rsp)); ++ ++ rsp.ret = lxc_terminal_add_fifos(handler->conf, req->data);; ++ ++ return lxc_cmd_rsp_send(fd, &rsp); ++ ++} ++ + static int lxc_cmd_process(int fd, struct lxc_cmd_req *req, + struct lxc_handler *handler) + { +@@ -1075,6 +1136,7 @@ static int lxc_cmd_process(int fd, struct lxc_cmd_req *req, + [LXC_CMD_ADD_STATE_CLIENT] = lxc_cmd_add_state_client_callback, + [LXC_CMD_CONSOLE_LOG] = lxc_cmd_console_log_callback, + [LXC_CMD_SERVE_STATE_CLIENTS] = lxc_cmd_serve_state_clients_callback, ++ [LXC_CMD_SET_TERMINAL_FIFOS] = lxc_cmd_set_terminal_fifos_callback, + }; + + if (req->cmd >= LXC_CMD_MAX) { +diff --git a/src/lxc/commands.h b/src/lxc/commands.h +index 2c024b6..0c64544 100644 +--- a/src/lxc/commands.h ++++ b/src/lxc/commands.h +@@ -46,6 +46,7 @@ typedef enum { + LXC_CMD_ADD_STATE_CLIENT, + LXC_CMD_CONSOLE_LOG, + LXC_CMD_SERVE_STATE_CLIENTS, ++ LXC_CMD_SET_TERMINAL_FIFOS, + LXC_CMD_MAX, + } lxc_cmd_t; + +@@ -125,4 +126,7 @@ extern int lxc_try_cmd(const char *name, const char *lxcpath); + extern int lxc_cmd_console_log(const char *name, const char *lxcpath, + struct lxc_console_log *log); + ++extern int lxc_cmd_set_terminal_fifos(const char *name, const char *lxcpath, ++ const char *in_fifo, const char *out_fifo); ++ + #endif /* __commands_h */ +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index d641851..bfbf223 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -5164,6 +5164,29 @@ static bool do_lxcapi_clean_container_resource(struct lxc_container *c, pid_t pi + + WRAP_API_1(bool, lxcapi_clean_container_resource, pid_t) + ++/* isulad add clean resources */ ++static bool do_lxcapi_add_terminal_fifo(struct lxc_container *c, const char *in_fifo, const char *out_fifo) ++{ ++ bool ret = true; ++ ++ if (!c || !c->lxc_conf || !in_fifo || !out_fifo) ++ return false; ++ if (container_mem_lock(c)) { ++ ERROR("Error getting mem lock"); ++ return false; ++ } ++ ++ if (lxc_cmd_set_terminal_fifos(c->name, c->config_path, in_fifo, out_fifo)) { ++ ERROR("Error set console fifos"); ++ ret = false; ++ } ++ ++ container_mem_unlock(c); ++ return ret; ++} ++ ++WRAP_API_2(bool, lxcapi_add_terminal_fifo, const char *, const char *) ++ + static struct lxc_container *do_lxc_container_new(const char *name, const char *configpath, bool load_config) + { + struct lxc_container *c; +@@ -5299,6 +5322,7 @@ static struct lxc_container *do_lxc_container_new(const char *name, const char * + c->set_container_info_file = lxcapi_set_container_info_file; + c->set_start_timeout = lxcapi_set_start_timeout; + c->clean_container_resource = lxcapi_clean_container_resource; ++ c->add_terminal_fifos = lxcapi_add_terminal_fifo; + /* isulad add end */ + return c; + +diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h +index a00e0ec..c1d83ba 100644 +--- a/src/lxc/lxccontainer.h ++++ b/src/lxc/lxccontainer.h +@@ -878,6 +878,16 @@ struct lxc_container { + bool (*set_terminal_init_fifos)(struct lxc_container *c, const char *in, const char *out); + + /*! isulad add ++ * \brief An API call to add the path of terminal fifos ++ * ++ * \param c Container. ++ * \param path Value of the console path.. ++ * ++ * \return \c true on success, else \c false. ++ */ ++ bool (*add_terminal_fifos)(struct lxc_container *c, const char *in, const char *out); ++ ++ /*! isulad add + * \brief An API call to set the path of info file + * + * \param c Container. +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index ee3aef2..a33830d 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -1473,3 +1473,50 @@ int lxc_terminal_map_ids(struct lxc_conf *c, struct lxc_terminal *terminal) + + return 0; + } ++ ++/* isulad: add fifos dynamic*/ ++int lxc_terminal_add_fifos(struct lxc_conf *conf, const char *fifonames) ++{ ++ int ret = 0; ++ struct lxc_terminal *terminal = &conf->console; ++ int fifofd_in = -1; ++ char *tmp = NULL, *saveptr = NULL, *in = NULL, *out = NULL; ++ ++ tmp = strdup(fifonames); ++ if (!tmp) { ++ ret = -1; ++ goto free_out; ++ } ++ ++ in = strtok_r(tmp, "&&&&", &saveptr); ++ if (!in) { ++ ret = -1; ++ goto free_out; ++ } ++ out = strtok_r(NULL, "&&&&", &saveptr); ++ if (!out) { ++ ret = -1; ++ goto free_out; ++ } ++ ++ fifofd_in = lxc_terminal_set_fifo(terminal, in, out); ++ if (fifofd_in < 0) { ++ ERROR("Faild to set fifos to console config"); ++ ret = -1; ++ goto free_out; ++ } ++ ++ if (lxc_mainloop_add_handler(terminal->descr, fifofd_in, ++ lxc_terminal_io_cb, terminal)) { ++ ERROR("console fifo not added to mainloop"); ++ lxc_terminal_delete_fifo(fifofd_in, &terminal->fifos); ++ ret = -1; ++ goto free_out; ++ } ++ ++free_out: ++ if (tmp) ++ free(tmp); ++ return ret; ++} ++ +diff --git a/src/lxc/terminal.h b/src/lxc/terminal.h +index d25da65..d006b80 100644 +--- a/src/lxc/terminal.h ++++ b/src/lxc/terminal.h +@@ -310,5 +310,6 @@ extern int lxc_terminal_map_ids(struct lxc_conf *c, + static bool lxc_terminal_is_fifo(int fd, struct lxc_list *list); + /* isulad: if fd == -1, means delete all the fifos*/ + int lxc_terminal_delete_fifo(int fd, struct lxc_list *list); ++int lxc_terminal_add_fifos(struct lxc_conf *conf, const char *fifonames); + + #endif /* __LXC_TERMINAL_H */ +-- +1.8.3.1 + diff --git a/0046-Do-not-test-cgroup-writeable.patch b/0046-Do-not-test-cgroup-writeable.patch new file mode 100644 index 0000000..b2bb987 --- /dev/null +++ b/0046-Do-not-test-cgroup-writeable.patch @@ -0,0 +1,48 @@ +From 623f6fbd09a7694546ca7c57a564d984261c4f82 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Thu, 17 Jan 2019 03:49:16 -0500 +Subject: [PATCH 046/122] Do not test cgroup writeable + +If we run isulad in docker without cgroup namespace, the base_cgroup will be docker/XXX.., +mountpoint+base_cgroup may be not exist + +Signed-off-by: LiFeng +--- + src/lxc/cgroups/cgfsng.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index 47b12a6..6bfa693 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -581,7 +581,7 @@ static bool cg_legacy_handle_cpuset_hierarchy(struct hierarchy *h, char *cgname) + if (slash) + *slash = '/'; + +- ret = mkdir(cgpath, 0755); ++ ret = mkdir_p(cgpath, 0755); + if (ret < 0) { + if (errno != EEXIST) { + SYSERROR("Failed to create directory \"%s\"", cgpath); +@@ -2489,13 +2489,17 @@ static bool cg_hybrid_init(struct cgroup_ops *ops) + + trim(base_cgroup); + prune_init_scope(base_cgroup); ++ ++ /* isulad: ++ * do not test writeable, if we run isulad in docker without cgroup namespace. ++ * the base_cgroup will be docker/XXX.., mountpoint+base_cgroup may be not exist + if (type == CGROUP2_SUPER_MAGIC) + writeable = test_writeable_v2(mountpoint, base_cgroup); + else + writeable = test_writeable_v1(mountpoint, base_cgroup); + if (!writeable) + goto next; +- ++ */ + if (type == CGROUP2_SUPER_MAGIC) { + char *cgv2_ctrl_path; + +-- +1.8.3.1 + diff --git a/0047-Fix-memory-leak-in-lxc_global_config_value.patch b/0047-Fix-memory-leak-in-lxc_global_config_value.patch new file mode 100644 index 0000000..8d169c4 --- /dev/null +++ b/0047-Fix-memory-leak-in-lxc_global_config_value.patch @@ -0,0 +1,44 @@ +From ec20a5a0e68d0b70ec0014d3f34385cdd3c44370 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Thu, 17 Jan 2019 07:43:23 -0500 +Subject: [PATCH 047/122] Fix memory leak in lxc_global_config_value + +Signed-off-by: LiFeng +--- + src/lxc/cgroups/cgroup.c | 2 ++ + src/lxc/initutils.c | 5 ----- + 2 files changed, 2 insertions(+), 5 deletions(-) + +diff --git a/src/lxc/cgroups/cgroup.c b/src/lxc/cgroups/cgroup.c +index 720a6c9..8d559be 100644 +--- a/src/lxc/cgroups/cgroup.c ++++ b/src/lxc/cgroups/cgroup.c +@@ -95,6 +95,8 @@ void cgroup_exit(struct cgroup_ops *ops) + } + free(ops->hierarchies); + ++ free(ops); ++ + return; + } + +diff --git a/src/lxc/initutils.c b/src/lxc/initutils.c +index 09b521e..60147a5 100644 +--- a/src/lxc/initutils.c ++++ b/src/lxc/initutils.c +@@ -74,12 +74,7 @@ const char *lxc_global_config_value(const char *option_name) + { NULL, NULL }, + }; + +- /* placed in the thread local storage pool for non-bionic targets */ +-#ifdef HAVE_TLS +- static thread_local const char *values[sizeof(options) / sizeof(options[0])] = {0}; +-#else + static const char *values[sizeof(options) / sizeof(options[0])] = {0}; +-#endif + + /* user_config_path is freed as soon as it is used */ + char *user_config_path = NULL; +-- +1.8.3.1 + diff --git a/0048-clear-ONLCR-flag-from-master-of-terminal.patch b/0048-clear-ONLCR-flag-from-master-of-terminal.patch new file mode 100644 index 0000000..753971d --- /dev/null +++ b/0048-clear-ONLCR-flag-from-master-of-terminal.patch @@ -0,0 +1,59 @@ +From 26125894df9e3297f34c02d62ae5271b5ec88348 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Thu, 17 Jan 2019 20:46:33 +0800 +Subject: [PATCH 048/122] clear ONLCR flag from master of terminal + +clear ONLCR flag from master of terminal + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + src/lxc/terminal.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index a33830d..95140e0 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -1066,6 +1066,24 @@ static int lxc_terminal_fifo_default(struct lxc_terminal *terminal) + return lxc_terminal_set_fifo(terminal, terminal->init_fifo[0], terminal->init_fifo[1]); + } + ++/* ++ * isulad: disable (XSI) Map NL to CR-NL on output. ++ * */ ++static int use_unix_newline(int master_fd) ++{ ++ struct termios oldtios; ++ int ret; ++ ++ ret = tcgetattr(master_fd, &oldtios); ++ if (ret < 0) ++ return -1; ++ oldtios.c_oflag &= ~ONLCR; ++ ret = tcsetattr(master_fd, TCSAFLUSH, &oldtios); ++ if (ret < 0) ++ return -1; ++ return 0; ++} ++ + int lxc_terminal_create(struct lxc_terminal *terminal) + { + int ret; +@@ -1082,6 +1100,13 @@ int lxc_terminal_create(struct lxc_terminal *terminal) + goto err; + } + ++ /* isulad: clear ONLCR flag */ ++ ret = use_unix_newline(terminal->master); ++ if (ret < 0) { ++ SYSERROR("Failed to clear ONLCR flag on terminal master"); ++ goto err; ++ } ++ + ret = fd_cloexec(terminal->master, true); + if (ret < 0) { + SYSERROR("Failed to set FD_CLOEXEC flag on terminal master"); +-- +1.8.3.1 + diff --git a/0049-Add-100ms-timeout-for-console-epoll.patch b/0049-Add-100ms-timeout-for-console-epoll.patch new file mode 100644 index 0000000..74cd812 --- /dev/null +++ b/0049-Add-100ms-timeout-for-console-epoll.patch @@ -0,0 +1,28 @@ +From 81e84198f02323caabcab2200f2bedf9212a87d7 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Sat, 19 Jan 2019 02:05:17 -0500 +Subject: [PATCH 049/122] Add 100ms timeout for console epoll + +add 100ms timeout for console epoll to avoid lose console + +Signed-off-by: LiFeng +--- + src/lxc/start.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 7bbcb00..daf2af4 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -643,7 +643,7 @@ int lxc_poll(const char *name, struct lxc_handler *handler) + goto out_mainloop_console; + + if (has_console) +- ret = lxc_mainloop(&descr_console, 0); ++ ret = lxc_mainloop(&descr_console, 100); + + out_mainloop_console: + if (has_console) { +-- +1.8.3.1 + diff --git a/0050-seccomp-add-rules-for-specified-architecture-only.patch b/0050-seccomp-add-rules-for-specified-architecture-only.patch new file mode 100644 index 0000000..16e5eba --- /dev/null +++ b/0050-seccomp-add-rules-for-specified-architecture-only.patch @@ -0,0 +1,408 @@ +From 043d4a1b634a850a201bd835ee59061cbbdbd030 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Fri, 18 Jan 2019 02:11:11 -0500 +Subject: [PATCH 050/122] seccomp: add rules for specified architecture only + +LXC MR: https://github.com/lxc/lxc/pull/2786 + +Signed-off-by: LiFeng +--- + src/lxc/seccomp.c | 234 ++++++++++++++++++++++++++++++------------------------ + 1 file changed, 132 insertions(+), 102 deletions(-) + +diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c +index 27bdc22..4a9143b 100644 +--- a/src/lxc/seccomp.c ++++ b/src/lxc/seccomp.c +@@ -291,7 +291,7 @@ on_error: + #endif + + #if HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH +-enum lxc_hostarch_t { ++enum lxc_arch_t { + lxc_seccomp_arch_all = 0, + lxc_seccomp_arch_native, + lxc_seccomp_arch_i386, +@@ -345,8 +345,8 @@ int get_hostarch(void) + return lxc_seccomp_arch_unknown; + } + +-scmp_filter_ctx get_new_ctx(enum lxc_hostarch_t n_arch, +- uint32_t default_policy_action, bool *needs_merge) ++scmp_filter_ctx get_new_ctx(enum lxc_arch_t n_arch, ++ uint32_t default_policy_action) + { + int ret; + uint32_t arch; +@@ -464,10 +464,7 @@ scmp_filter_ctx get_new_ctx(enum lxc_hostarch_t n_arch, + return NULL; + } + TRACE("Removed native arch from main seccomp context"); +- +- *needs_merge = true; + } else { +- *needs_merge = false; + TRACE("Arch %d already present in main seccomp context", (int)n_arch); + } + +@@ -550,6 +547,27 @@ bool do_resolve_add_rule(uint32_t arch, char *line, scmp_filter_ctx ctx, + return true; + } + ++#define SCMP_ARCH_INDEX_MAX 3 ++ ++struct scmp_ctx_info { ++ uint32_t architectures[SCMP_ARCH_INDEX_MAX]; ++ enum lxc_arch_t lxc_arch[SCMP_ARCH_INDEX_MAX]; ++ scmp_filter_ctx contexts[SCMP_ARCH_INDEX_MAX]; ++ bool needs_merge[SCMP_ARCH_INDEX_MAX]; ++}; ++ ++static int get_arch_index(enum lxc_arch_t arch, struct scmp_ctx_info *ctx) ++{ ++ int i; ++ ++ for (i = 0; i < SCMP_ARCH_INDEX_MAX; i++) { ++ if (ctx->lxc_arch[i] == arch) ++ return i; ++ } ++ ++ return -1; ++} ++ + /* + * v2 consists of + * [x86] +@@ -568,15 +586,11 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c + { + int ret; + char *p; +- enum lxc_hostarch_t cur_rule_arch, native_arch; ++ enum lxc_arch_t cur_rule_arch, native_arch; + bool blacklist = false; + uint32_t default_policy_action = -1, default_rule_action = -1; + struct seccomp_v2_rule rule; +- struct scmp_ctx_info { +- uint32_t architectures[3]; +- scmp_filter_ctx contexts[3]; +- bool needs_merge[3]; +- } ctx; ++ struct scmp_ctx_info ctx; + + if (strncmp(line, "blacklist", 9) == 0) + blacklist = true; +@@ -617,23 +631,23 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c + cur_rule_arch = lxc_seccomp_arch_all; + + ctx.architectures[0] = SCMP_ARCH_X86; ++ ctx.lxc_arch[0] = lxc_seccomp_arch_i386; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_i386, +- default_policy_action, +- &ctx.needs_merge[0]); ++ default_policy_action); + if (!ctx.contexts[0]) + goto bad; + + ctx.architectures[1] = SCMP_ARCH_X32; ++ ctx.lxc_arch[1] = lxc_seccomp_arch_x32; + ctx.contexts[1] = get_new_ctx(lxc_seccomp_arch_x32, +- default_policy_action, +- &ctx.needs_merge[1]); ++ default_policy_action); + if (!ctx.contexts[1]) + goto bad; + + ctx.architectures[2] = SCMP_ARCH_X86_64; ++ ctx.lxc_arch[2] = lxc_seccomp_arch_amd64; + ctx.contexts[2] = get_new_ctx(lxc_seccomp_arch_amd64, +- default_policy_action, +- &ctx.needs_merge[2]); ++ default_policy_action); + if (!ctx.contexts[2]) + goto bad; + #ifdef SCMP_ARCH_PPC +@@ -641,17 +655,17 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c + cur_rule_arch = lxc_seccomp_arch_all; + + ctx.architectures[0] = SCMP_ARCH_PPC; ++ ctx.lxc_arch[0] = lxc_seccomp_arch_ppc; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_ppc, +- default_policy_action, +- &ctx.needs_merge[0]); ++ default_policy_action); + if (!ctx.contexts[0]) + goto bad; + +- ctx.architectures[2] = SCMP_ARCH_PPC64; +- ctx.contexts[2] = get_new_ctx(lxc_seccomp_arch_ppc64, +- default_policy_action, +- &ctx.needs_merge[2]); +- if (!ctx.contexts[2]) ++ ctx.architectures[1] = SCMP_ARCH_PPC64; ++ ctx.lxc_arch[1] = lxc_seccomp_arch_ppc64; ++ ctx.contexts[1] = get_new_ctx(lxc_seccomp_arch_ppc64, ++ default_policy_action); ++ if (!ctx.contexts[1]) + goto bad; + #endif + #ifdef SCMP_ARCH_ARM +@@ -659,18 +673,18 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c + cur_rule_arch = lxc_seccomp_arch_all; + + ctx.architectures[0] = SCMP_ARCH_ARM; ++ ctx.lxc_arch[0] = lxc_seccomp_arch_arm; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_arm, +- default_policy_action, +- &ctx.needs_merge[0]); ++ default_policy_action); + if (!ctx.contexts[0]) + goto bad; + + #ifdef SCMP_ARCH_AARCH64 +- ctx.architectures[2] = SCMP_ARCH_AARCH64; +- ctx.contexts[2] = get_new_ctx(lxc_seccomp_arch_arm64, +- default_policy_action, +- &ctx.needs_merge[2]); +- if (!ctx.contexts[2]) ++ ctx.architectures[1] = SCMP_ARCH_AARCH64; ++ ctx.lxc_arch[1] = lxc_seccomp_arch_arm64; ++ ctx.contexts[1] = get_new_ctx(lxc_seccomp_arch_arm64, ++ default_policy_action); ++ if (!ctx.contexts[1]) + goto bad; + #endif + #endif +@@ -679,46 +693,46 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c + cur_rule_arch = lxc_seccomp_arch_all; + + ctx.architectures[0] = SCMP_ARCH_MIPS; ++ ctx.lxc_arch[0] = lxc_seccomp_arch_mips; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_mips, +- default_policy_action, +- &ctx.needs_merge[0]); ++ default_policy_action); + if (!ctx.contexts[0]) + goto bad; + + ctx.architectures[1] = SCMP_ARCH_MIPS64N32; ++ ctx.lxc_arch[1] = lxc_seccomp_arch_mips64n32; + ctx.contexts[1] = get_new_ctx(lxc_seccomp_arch_mips64n32, +- default_policy_action, +- &ctx.needs_merge[1]); ++ default_policy_action); + if (!ctx.contexts[1]) + goto bad; + + ctx.architectures[2] = SCMP_ARCH_MIPS64; ++ ctx.lxc_arch[2] = lxc_seccomp_arch_mips64; + ctx.contexts[2] = get_new_ctx(lxc_seccomp_arch_mips64, +- default_policy_action, +- &ctx.needs_merge[2]); ++ default_policy_action); + if (!ctx.contexts[2]) + goto bad; + } else if (native_arch == lxc_seccomp_arch_mipsel64) { + cur_rule_arch = lxc_seccomp_arch_all; + + ctx.architectures[0] = SCMP_ARCH_MIPSEL; ++ ctx.lxc_arch[0] = lxc_seccomp_arch_mipsel; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_mipsel, +- default_policy_action, +- &ctx.needs_merge[0]); ++ default_policy_action); + if (!ctx.contexts[0]) + goto bad; + + ctx.architectures[1] = SCMP_ARCH_MIPSEL64N32; ++ ctx.lxc_arch[1] = lxc_seccomp_arch_mipsel64n32; + ctx.contexts[1] = get_new_ctx(lxc_seccomp_arch_mipsel64n32, +- default_policy_action, +- &ctx.needs_merge[1]); ++ default_policy_action); + if (!ctx.contexts[1]) + goto bad; + + ctx.architectures[2] = SCMP_ARCH_MIPSEL64; ++ ctx.lxc_arch[2] = lxc_seccomp_arch_mipsel64; + ctx.contexts[2] = get_new_ctx(lxc_seccomp_arch_mipsel64, +- default_policy_action, +- &ctx.needs_merge[2]); ++ default_policy_action); + if (!ctx.contexts[2]) + goto bad; + #endif +@@ -928,97 +942,113 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c + goto bad_rule; + } + +- if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, +- conf->seccomp_ctx, &rule)) +- goto bad_rule; ++ if (cur_rule_arch == native_arch) { ++ if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, ++ conf->seccomp_ctx, &rule)) ++ goto bad_rule; ++ ++ INFO("Added native rule for arch %d for %s action %d(%s)", ++ SCMP_ARCH_NATIVE, line, rule.action, ++ get_action_name(rule.action)); ++ } else if (cur_rule_arch != lxc_seccomp_arch_all) { ++ int arch_index = get_arch_index(cur_rule_arch, &ctx); ++ if (arch_index < 0) ++ goto bad_arch; + +- INFO("Added native rule for arch %d for %s action %d(%s)", +- SCMP_ARCH_NATIVE, line, rule.action, +- get_action_name(rule.action)); ++ if (!do_resolve_add_rule(ctx.architectures[arch_index], line, ++ ctx.contexts[arch_index], &rule)) ++ goto bad_rule; + +- if (cur_rule_arch == lxc_seccomp_arch_all) { ++ INFO("Added compat rule for arch %d for %s action %d(%s)", ++ ctx.architectures[arch_index], line, rule.action, ++ get_action_name(rule.action)); ++ ctx.needs_merge[arch_index] = true; ++ } else { + if (ctx.architectures[0] != SCMP_ARCH_NATIVE) { + if (!do_resolve_add_rule(ctx.architectures[0], line, +- ctx.contexts[0], &rule)) ++ ctx.contexts[0], &rule)) + goto bad_rule; + +- INFO("Added compat rule for arch %d for %s action %d(%s)", +- ctx.architectures[0], line, rule.action, +- get_action_name(rule.action)); ++ INFO("Added compat rule for arch %d for %s action %d(%s)", ++ ctx.architectures[0], line, rule.action, ++ get_action_name(rule.action)); ++ ctx.needs_merge[0] = true; + } + + if (ctx.architectures[1] != SCMP_ARCH_NATIVE) { + if (!do_resolve_add_rule(ctx.architectures[1], line, +- ctx.contexts[1], &rule)) ++ ctx.contexts[1], &rule)) + goto bad_rule; + + INFO("Added compat rule for arch %d for %s action %d(%s)", +- ctx.architectures[1], line, rule.action, +- get_action_name(rule.action)); ++ ctx.architectures[1], line, rule.action, ++ get_action_name(rule.action)); ++ ctx.needs_merge[1] = true; + } + + if (ctx.architectures[2] != SCMP_ARCH_NATIVE) { + if (!do_resolve_add_rule(ctx.architectures[2], line, +- ctx.contexts[2], &rule)) ++ ctx.contexts[2], &rule)) + goto bad_rule; + + INFO("Added native rule for arch %d for %s action %d(%s)", +- ctx.architectures[2], line, rule.action, +- get_action_name(rule.action)); ++ ctx.architectures[2], line, rule.action, ++ get_action_name(rule.action)); ++ ctx.needs_merge[2] = true; + } + } +- } + +- if (cur_rule_arch == lxc_seccomp_arch_all) { +- INFO("Merging compat seccomp contexts into main context"); +- if (ctx.contexts[0]) { +- if (ctx.needs_merge[0]) { +- ret = seccomp_merge(conf->seccomp_ctx, ctx.contexts[0]); +- if (ret < 0) { +- ERROR("Failed to merge first compat seccomp " +- "context into main context"); +- goto bad; +- } ++ } + +- TRACE("Merged first compat seccomp context into main context"); +- } else { +- seccomp_release(ctx.contexts[0]); +- ctx.contexts[0] = NULL; ++ INFO("Merging compat seccomp contexts into main context"); ++ if (ctx.contexts[0]) { ++ if (ctx.needs_merge[0]) { ++ ret = seccomp_merge(conf->seccomp_ctx, ctx.contexts[0]); ++ if (ret < 0) { ++ ERROR("%s - Failed to merge first compat seccomp " ++ "context into main context", strerror(-ret)); ++ goto bad; + } +- } + +- if (ctx.contexts[1]) { +- if (ctx.needs_merge[1]) { +- ret = seccomp_merge(conf->seccomp_ctx, ctx.contexts[1]); +- if (ret < 0) { +- ERROR("Failed to merge first compat seccomp " +- "context into main context"); +- goto bad; +- } ++ TRACE("Merged first compat seccomp context into main context"); ++ } else { ++ seccomp_release(ctx.contexts[0]); ++ ctx.contexts[0] = NULL; ++ } ++ } + +- TRACE("Merged second compat seccomp context into main context"); +- } else { +- seccomp_release(ctx.contexts[1]); +- ctx.contexts[1] = NULL; ++ if (ctx.contexts[1]) { ++ if (ctx.needs_merge[1]) { ++ ret = seccomp_merge(conf->seccomp_ctx, ctx.contexts[1]); ++ if (ret < 0) { ++ ERROR("%s - Failed to merge second compat seccomp " ++ "context into main context", strerror(-ret)); ++ goto bad; + } +- } + +- if (ctx.contexts[2]) { +- if (ctx.needs_merge[2]) { +- ret = seccomp_merge(conf->seccomp_ctx, ctx.contexts[2]); +- if (ret < 0) { +- ERROR("Failed to merge third compat seccomp " +- "context into main context"); +- goto bad; +- } ++ TRACE("Merged second compat seccomp context into main context"); ++ } else { ++ seccomp_release(ctx.contexts[1]); ++ ctx.contexts[1] = NULL; ++ } ++ } + +- TRACE("Merged third compat seccomp context into main context"); +- } else { +- seccomp_release(ctx.contexts[2]); +- ctx.contexts[2] = NULL; ++ if (ctx.contexts[2]) { ++ if (ctx.needs_merge[2]) { ++ ret = seccomp_merge(conf->seccomp_ctx, ctx.contexts[2]); ++ if (ret < 0) { ++ ERROR("%s - Failed to merge third compat seccomp " ++ "context into main context", strerror(-ret)); ++ goto bad; + } ++ ++ TRACE("Merged third compat seccomp context into main context"); ++ } else { ++ seccomp_release(ctx.contexts[2]); ++ ctx.contexts[2] = NULL; + } + } ++ + free(line); + return 0; + +-- +1.8.3.1 + diff --git a/0051-if-ocihook-is-empty.patch b/0051-if-ocihook-is-empty.patch new file mode 100644 index 0000000..5af0c61 --- /dev/null +++ b/0051-if-ocihook-is-empty.patch @@ -0,0 +1,34 @@ +From 4fc938241a649307d87700e90dc380651da4c550 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Tue, 22 Jan 2019 11:25:45 +0800 +Subject: [PATCH 051/122] if ocihook is empty + +return success + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 48e31af..6ea8f9c 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4782,9 +4782,12 @@ static int run_oci_hooks(const char *name, const char *lxcpath, struct lxc_conf + int ret = 0; + char *rootpath; + +- if (!lc || !lc->ocihooks) { ++ if (!lc) { + return -1; + } ++ if (!lc->ocihooks) { ++ return 0; ++ } + + rootpath = get_root_path(lc->rootfs.path, lc->rootfs.bdev_type); + if (!rootpath) { +-- +1.8.3.1 + diff --git a/0052-Fix-seccomp-fail-when-all-specified-in-config.patch b/0052-Fix-seccomp-fail-when-all-specified-in-config.patch new file mode 100644 index 0000000..d1b9753 --- /dev/null +++ b/0052-Fix-seccomp-fail-when-all-specified-in-config.patch @@ -0,0 +1,192 @@ +From bbefc33a969a7cf0d4f671d96030fb044593a71a Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Mon, 21 Jan 2019 23:28:43 -0500 +Subject: [PATCH 052/122] Fix seccomp fail when [all] specified in config + +Signed-off-by: LiFeng +--- + src/lxc/seccomp.c | 56 +++++++++++++++++++++++++++---------------------------- + 1 file changed, 28 insertions(+), 28 deletions(-) + +diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c +index 4a9143b..3218a60 100644 +--- a/src/lxc/seccomp.c ++++ b/src/lxc/seccomp.c +@@ -346,7 +346,7 @@ int get_hostarch(void) + } + + scmp_filter_ctx get_new_ctx(enum lxc_arch_t n_arch, +- uint32_t default_policy_action) ++ uint32_t default_policy_action, uint32_t *architectures) + { + int ret; + uint32_t arch; +@@ -464,8 +464,10 @@ scmp_filter_ctx get_new_ctx(enum lxc_arch_t n_arch, + return NULL; + } + TRACE("Removed native arch from main seccomp context"); ++ *architectures = arch; + } else { + TRACE("Arch %d already present in main seccomp context", (int)n_arch); ++ *architectures = SCMP_ARCH_NATIVE; + } + + return ctx; +@@ -630,41 +632,36 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c + if (native_arch == lxc_seccomp_arch_amd64) { + cur_rule_arch = lxc_seccomp_arch_all; + +- ctx.architectures[0] = SCMP_ARCH_X86; + ctx.lxc_arch[0] = lxc_seccomp_arch_i386; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_i386, +- default_policy_action); ++ default_policy_action, &ctx.architectures[0]); + if (!ctx.contexts[0]) + goto bad; + +- ctx.architectures[1] = SCMP_ARCH_X32; + ctx.lxc_arch[1] = lxc_seccomp_arch_x32; + ctx.contexts[1] = get_new_ctx(lxc_seccomp_arch_x32, +- default_policy_action); ++ default_policy_action, &ctx.architectures[1]); + if (!ctx.contexts[1]) + goto bad; + +- ctx.architectures[2] = SCMP_ARCH_X86_64; + ctx.lxc_arch[2] = lxc_seccomp_arch_amd64; + ctx.contexts[2] = get_new_ctx(lxc_seccomp_arch_amd64, +- default_policy_action); ++ default_policy_action, &ctx.architectures[2]); + if (!ctx.contexts[2]) + goto bad; + #ifdef SCMP_ARCH_PPC + } else if (native_arch == lxc_seccomp_arch_ppc64) { + cur_rule_arch = lxc_seccomp_arch_all; + +- ctx.architectures[0] = SCMP_ARCH_PPC; + ctx.lxc_arch[0] = lxc_seccomp_arch_ppc; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_ppc, +- default_policy_action); ++ default_policy_action, &ctx.architectures[0]); + if (!ctx.contexts[0]) + goto bad; + +- ctx.architectures[1] = SCMP_ARCH_PPC64; + ctx.lxc_arch[1] = lxc_seccomp_arch_ppc64; + ctx.contexts[1] = get_new_ctx(lxc_seccomp_arch_ppc64, +- default_policy_action); ++ default_policy_action, &ctx.architectures[1]); + if (!ctx.contexts[1]) + goto bad; + #endif +@@ -672,18 +669,16 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c + } else if (native_arch == lxc_seccomp_arch_arm64) { + cur_rule_arch = lxc_seccomp_arch_all; + +- ctx.architectures[0] = SCMP_ARCH_ARM; + ctx.lxc_arch[0] = lxc_seccomp_arch_arm; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_arm, +- default_policy_action); ++ default_policy_action, &ctx.architectures[0]); + if (!ctx.contexts[0]) + goto bad; + + #ifdef SCMP_ARCH_AARCH64 +- ctx.architectures[1] = SCMP_ARCH_AARCH64; + ctx.lxc_arch[1] = lxc_seccomp_arch_arm64; + ctx.contexts[1] = get_new_ctx(lxc_seccomp_arch_arm64, +- default_policy_action); ++ default_policy_action, &ctx.architectures[1]); + if (!ctx.contexts[1]) + goto bad; + #endif +@@ -692,47 +687,41 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c + } else if (native_arch == lxc_seccomp_arch_mips64) { + cur_rule_arch = lxc_seccomp_arch_all; + +- ctx.architectures[0] = SCMP_ARCH_MIPS; + ctx.lxc_arch[0] = lxc_seccomp_arch_mips; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_mips, +- default_policy_action); ++ default_policy_action, &ctx.architectures[0]); + if (!ctx.contexts[0]) + goto bad; + +- ctx.architectures[1] = SCMP_ARCH_MIPS64N32; + ctx.lxc_arch[1] = lxc_seccomp_arch_mips64n32; + ctx.contexts[1] = get_new_ctx(lxc_seccomp_arch_mips64n32, +- default_policy_action); ++ default_policy_action, &ctx.architectures[1]); + if (!ctx.contexts[1]) + goto bad; + +- ctx.architectures[2] = SCMP_ARCH_MIPS64; + ctx.lxc_arch[2] = lxc_seccomp_arch_mips64; + ctx.contexts[2] = get_new_ctx(lxc_seccomp_arch_mips64, +- default_policy_action); ++ default_policy_action, &ctx.architectures[2]); + if (!ctx.contexts[2]) + goto bad; + } else if (native_arch == lxc_seccomp_arch_mipsel64) { + cur_rule_arch = lxc_seccomp_arch_all; +- +- ctx.architectures[0] = SCMP_ARCH_MIPSEL; ++; + ctx.lxc_arch[0] = lxc_seccomp_arch_mipsel; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_mipsel, +- default_policy_action); ++ default_policy_action, &ctx.architectures[0]); + if (!ctx.contexts[0]) + goto bad; + +- ctx.architectures[1] = SCMP_ARCH_MIPSEL64N32; + ctx.lxc_arch[1] = lxc_seccomp_arch_mipsel64n32; + ctx.contexts[1] = get_new_ctx(lxc_seccomp_arch_mipsel64n32, +- default_policy_action); ++ default_policy_action, &ctx.architectures[1]); + if (!ctx.contexts[1]) + goto bad; + +- ctx.architectures[2] = SCMP_ARCH_MIPSEL64; + ctx.lxc_arch[2] = lxc_seccomp_arch_mipsel64; + ctx.contexts[2] = get_new_ctx(lxc_seccomp_arch_mipsel64, +- default_policy_action); ++ default_policy_action, &ctx.architectures[2]); + if (!ctx.contexts[2]) + goto bad; + #endif +@@ -943,6 +932,7 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c + } + + if (cur_rule_arch == native_arch) { ++ /* add for native arch */ + if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, + conf->seccomp_ctx, &rule)) + goto bad_rule; +@@ -951,6 +941,7 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c + SCMP_ARCH_NATIVE, line, rule.action, + get_action_name(rule.action)); + } else if (cur_rule_arch != lxc_seccomp_arch_all) { ++ /* add for compat specified arch */ + int arch_index = get_arch_index(cur_rule_arch, &ctx); + if (arch_index < 0) + goto bad_arch; +@@ -964,6 +955,15 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c + get_action_name(rule.action)); + ctx.needs_merge[arch_index] = true; + } else { ++ /* add for all compat archs */ ++ if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, ++ conf->seccomp_ctx, &rule)) ++ goto bad_rule; ++ ++ INFO("Added native rule for arch %d for %s action %d(%s)", ++ SCMP_ARCH_NATIVE, line, rule.action, ++ get_action_name(rule.action)); ++ + if (ctx.architectures[0] != SCMP_ARCH_NATIVE) { + if (!do_resolve_add_rule(ctx.architectures[0], line, + ctx.contexts[0], &rule)) +-- +1.8.3.1 + diff --git a/0053-destroy-empty-cgroup-path-return-ture.patch b/0053-destroy-empty-cgroup-path-return-ture.patch new file mode 100644 index 0000000..e54fe32 --- /dev/null +++ b/0053-destroy-empty-cgroup-path-return-ture.patch @@ -0,0 +1,31 @@ +From d1ae3bc538d21355947a1d1695c22690bb9a68ae Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Tue, 22 Jan 2019 14:45:54 +0800 +Subject: [PATCH 053/122] destroy empty cgroup path return ture + +destroy empty cgroup path return ture + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + src/lxc/utils.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index c8fb993..24e975b 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -1776,6 +1776,10 @@ int recursive_destroy(char *dirname) + + dir = opendir(dirname); + if (!dir) { ++ if (errno == ENOENT) { ++ WARN("Destroy path: %s do not exist"); ++ return 0; ++ } + SYSERROR("Failed to open dir \"%s\"", dirname); + return -1; + } +-- +1.8.3.1 + diff --git a/0054-fix-invalid-log-message.patch b/0054-fix-invalid-log-message.patch new file mode 100644 index 0000000..44d1fee --- /dev/null +++ b/0054-fix-invalid-log-message.patch @@ -0,0 +1,42 @@ +From d423289dd6f287b66d62538d9bdedd745a939c50 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Tue, 22 Jan 2019 20:14:53 +0800 +Subject: [PATCH 054/122] fix invalid log message + +fix invalid log message + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 1 - + src/lxc/utils.c | 2 +- + 2 files changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 6ea8f9c..1e403eb 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -2708,7 +2708,6 @@ static int mount_file_entries(const struct lxc_conf *conf, + free(mntent.mnt_fsname); + return -1; + } +- ERROR("mntent.mnt_fsname:%s, mntent.mnt_dir:%s", mntent.mnt_fsname, mntent.mnt_dir); + if (!rootfs->path) + ret = mount_entry_on_systemfs(&mntent); + else if (mntent.mnt_dir[0] != '/') +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index 24e975b..4db61c5 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -1777,7 +1777,7 @@ int recursive_destroy(char *dirname) + dir = opendir(dirname); + if (!dir) { + if (errno == ENOENT) { +- WARN("Destroy path: %s do not exist"); ++ WARN("Destroy path: \"%s\" do not exist", dirname); + return 0; + } + SYSERROR("Failed to open dir \"%s\"", dirname); +-- +1.8.3.1 + diff --git a/0055-Fix-compile-error.patch b/0055-Fix-compile-error.patch new file mode 100644 index 0000000..88d75de --- /dev/null +++ b/0055-Fix-compile-error.patch @@ -0,0 +1,229 @@ +From 9e3eb0c5c5258c6d8e658129ef87ae7ff3ffe64f Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Thu, 24 Jan 2019 05:14:24 -0500 +Subject: [PATCH 055/122] Fix compile error + +Signed-off-by: LiFeng +--- + src/lxc/cgroups/cgfsng.c | 13 ------------- + src/lxc/conf.c | 8 ++------ + src/lxc/confile.c | 1 - + src/lxc/start.c | 2 -- + src/lxc/terminal.c | 32 ++++++++++++++++---------------- + src/lxc/terminal.h | 3 --- + src/lxc/tools/lxc_attach.c | 2 -- + src/lxc/utils.c | 1 - + 8 files changed, 18 insertions(+), 44 deletions(-) + +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index 6bfa693..e513218 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -1263,18 +1263,6 @@ static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname, int err + return cg_unified_create_cgroup(h, cgname); + } + +-static void remove_path_for_hierarchy(struct hierarchy *h, char *cgname) +-{ +- int ret; +- +- ret = rmdir(h->container_full_path); +- if (ret < 0) +- SYSERROR("Failed to rmdir(\"%s\") from failed creation attempt", h->container_full_path); +- +- free(h->container_full_path); +- h->container_full_path = NULL; +-} +- + /* isulad: create hierarchies path, if fail, return the error */ + __cgfsng_ops static bool cgfsng_payload_create(struct cgroup_ops *ops, + struct lxc_handler *handler) +@@ -2439,7 +2427,6 @@ static bool cg_hybrid_init(struct cgroup_ops *ops) + + while (getline(&line, &len, f) != -1) { + int type; +- bool writeable; + struct hierarchy *new; + char *base_cgroup = NULL, *mountpoint = NULL; + char **controller_list = NULL; +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 1e403eb..4800943 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -1518,7 +1518,7 @@ error: + // remount_readonly will bind over the top of an existing path and ensure that it is read-only. + static bool remount_readonly(const char *path) + { +- int ret, savederrno, i; ++ int ret, i; + + if (!path) + return true; +@@ -4005,7 +4005,7 @@ static int setup_rootfs_mountopts(const struct lxc_rootfs *rootfs) + if (mntflags & MS_RDONLY) { + mflags = add_required_remount_flags("/", NULL, MS_BIND | MS_REC | mntflags | pflags | MS_REMOUNT); + DEBUG("remounting / as readonly"); +- if (mount("/", "/", NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, 0) < 0) { ++ if (mount("/", "/", NULL, mflags, 0) < 0) { + SYSERROR("Failed to make / readonly."); + return -1; + } +@@ -4776,7 +4776,6 @@ default_out: + static int run_oci_hooks(const char *name, const char *lxcpath, struct lxc_conf *lc, int which, int errfd) + { + struct oci_hook_conf work_conf = {0}; +- oci_runtime_spec_hooks *ocihooks = NULL; + size_t i; + int ret = 0; + char *rootpath; +@@ -4836,7 +4835,6 @@ int run_lxc_hooks(const char *name, char *hookname, struct lxc_conf *conf, + int which = -1; + + if (strcmp(hookname, "oci-prestart") == 0) { +- int ret; + which = OCI_HOOK_PRESTART; + if (!argv || !argv[0]) { + ERROR("oci hook require lxcpath"); +@@ -4844,7 +4842,6 @@ int run_lxc_hooks(const char *name, char *hookname, struct lxc_conf *conf, + } + return run_oci_hooks(name, argv[0], conf, which, conf->errpipe[1]); + } else if (strcmp(hookname, "oci-poststart") == 0) { +- int ret; + which = OCI_HOOK_POSTSTART; + if (!argv || !argv[0]) { + ERROR("oci hook require lxcpath"); +@@ -4852,7 +4849,6 @@ int run_lxc_hooks(const char *name, char *hookname, struct lxc_conf *conf, + } + return run_oci_hooks(name, argv[0], conf, which, conf->errpipe[1]); + } else if (strcmp(hookname, "oci-poststop") == 0) { +- int ret; + which = OCI_HOOK_POSTSTOP; + if (!argv || !argv[0]) { + ERROR("oci hook require lxcpath"); +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index 7e9d5c8..f66d01b 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -3909,7 +3909,6 @@ static int get_config_init_args(const char *key, char *retv, int inlen, + struct lxc_conf *c, void *data) + { + int i, len, fulllen = 0; +- struct lxc_list *it; + + if (!retv) + inlen = 0; +diff --git a/src/lxc/start.c b/src/lxc/start.c +index daf2af4..816b4a2 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -2470,8 +2470,6 @@ retry: + ret = -1; + } + +- +-out_fini_handler: + lxc_free_handler(handler); + out: + return ret; +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index 95140e0..252a644 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -418,6 +418,21 @@ static void lxc_forward_data_to_fifo(struct lxc_list *list, char *buf, int r) + return; + } + ++/* isulad: judge the fd whether is fifo */ ++static bool lxc_terminal_is_fifo(int fd, struct lxc_list *list) ++{ ++ struct lxc_list *it,*next; ++ struct lxc_fifos_fd *elem = NULL; ++ ++ lxc_list_for_each_safe(it, list, next) { ++ elem = it->elem; ++ if (elem->in_fd == fd) ++ return true; ++ } ++ ++ return false; ++} ++ + int lxc_terminal_io_cb(int fd, uint32_t events, void *data, + struct lxc_epoll_descr *descr) + { +@@ -1067,7 +1082,7 @@ static int lxc_terminal_fifo_default(struct lxc_terminal *terminal) + } + + /* +- * isulad: disable (XSI) Map NL to CR-NL on output. ++ * isulad: disable (XSI) Map NL to CR-NL on output. + * */ + static int use_unix_newline(int master_fd) + { +@@ -1427,21 +1442,6 @@ void lxc_terminal_init(struct lxc_terminal *terminal) + lxc_list_init(&terminal->fifos); + } + +-/* isulad: judge the fd whether is fifo */ +-static bool lxc_terminal_is_fifo(int fd, struct lxc_list *list) +-{ +- struct lxc_list *it,*next; +- struct lxc_fifos_fd *elem = NULL; +- +- lxc_list_for_each_safe(it, list, next) { +- elem = it->elem; +- if (elem->in_fd == fd) +- return true; +- } +- +- return false; +-} +- + /* isulad: if fd == -1, means delete all the fifos*/ + int lxc_terminal_delete_fifo(int fd, struct lxc_list *list) + { +diff --git a/src/lxc/terminal.h b/src/lxc/terminal.h +index d006b80..0c9653c 100644 +--- a/src/lxc/terminal.h ++++ b/src/lxc/terminal.h +@@ -305,9 +305,6 @@ extern void lxc_terminal_info_init(struct lxc_terminal_info *terminal); + extern void lxc_terminal_init(struct lxc_terminal *terminal); + extern int lxc_terminal_map_ids(struct lxc_conf *c, + struct lxc_terminal *terminal); +- +-/* isulad: judge the fd whether is fifo*/ +-static bool lxc_terminal_is_fifo(int fd, struct lxc_list *list); + /* isulad: if fd == -1, means delete all the fifos*/ + int lxc_terminal_delete_fifo(int fd, struct lxc_list *list); + int lxc_terminal_add_fifos(struct lxc_conf *conf, const char *fifonames); +diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c +index a590fd1..8856934 100644 +--- a/src/lxc/tools/lxc_attach.c ++++ b/src/lxc/tools/lxc_attach.c +@@ -398,11 +398,9 @@ out: + + int main(int argc, char *argv[]) + { +- int ret = -1; + int wexit = 0; + char *errmsg = NULL; + struct lxc_log log; +- pid_t pid; + lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT; + lxc_attach_command_t command = (lxc_attach_command_t){.program = NULL}; + +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index 4db61c5..9a50fce 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -2026,7 +2026,6 @@ void lxc_write_error_message(int errfd, const char *format, ...) + + bool lxc_process_alive(pid_t pid, unsigned long long start_time) + { +- int ret; + int sret = 0; + bool alive = true; + proc_t *pid_info = NULL; +-- +1.8.3.1 + diff --git a/0056-caps-use-_LINUX_CAPABILITY_VERSION_3-to-set-cap.patch b/0056-caps-use-_LINUX_CAPABILITY_VERSION_3-to-set-cap.patch new file mode 100644 index 0000000..41c5c40 --- /dev/null +++ b/0056-caps-use-_LINUX_CAPABILITY_VERSION_3-to-set-cap.patch @@ -0,0 +1,48 @@ +From 65b5764a98f751e885ba8596b2b92c4e7a3e0310 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Sat, 26 Jan 2019 02:22:48 -0500 +Subject: [PATCH 056/122] [caps]: use _LINUX_CAPABILITY_VERSION_3 to set cap + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 8 ++++---- + src/lxc/seccomp.c | 1 - + 2 files changed, 4 insertions(+), 5 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 4800943..0c6aa28 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4322,13 +4322,13 @@ int lxc_drop_caps(struct lxc_conf *conf) + memset(cap_data, 0, sizeof(struct __user_cap_data_struct) * 2); + + cap_header->pid = 0; +- cap_header->version = _LINUX_CAPABILITY_VERSION; ++ cap_header->version = _LINUX_CAPABILITY_VERSION_3; + + for (i = 0; i < numcaps; i++) { + if (caplist[i]) { +- cap_data[CAP_TO_INDEX(i)].effective = cap_data[CAP_TO_INDEX(i)].effective | __DEF_CAP_TO_MASK(i); +- cap_data[CAP_TO_INDEX(i)].permitted = cap_data[CAP_TO_INDEX(i)].permitted | __DEF_CAP_TO_MASK(i); +- cap_data[CAP_TO_INDEX(i)].inheritable = cap_data[CAP_TO_INDEX(i)].inheritable | __DEF_CAP_TO_MASK(i); ++ cap_data[CAP_TO_INDEX(i)].effective = cap_data[CAP_TO_INDEX(i)].effective | (i > 31 ? __DEF_CAP_TO_MASK(i % 32) : __DEF_CAP_TO_MASK(i)); ++ cap_data[CAP_TO_INDEX(i)].permitted = cap_data[CAP_TO_INDEX(i)].permitted | (i > 31 ? __DEF_CAP_TO_MASK(i % 32) : __DEF_CAP_TO_MASK(i)); ++ cap_data[CAP_TO_INDEX(i)].inheritable = cap_data[CAP_TO_INDEX(i)].inheritable | (i > 31 ? __DEF_CAP_TO_MASK(i % 32) : __DEF_CAP_TO_MASK(i)); + } + } + +diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c +index 3218a60..4a5b3d0 100644 +--- a/src/lxc/seccomp.c ++++ b/src/lxc/seccomp.c +@@ -706,7 +706,6 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c + goto bad; + } else if (native_arch == lxc_seccomp_arch_mipsel64) { + cur_rule_arch = lxc_seccomp_arch_all; +-; + ctx.lxc_arch[0] = lxc_seccomp_arch_mipsel; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_mipsel, + default_policy_action, &ctx.architectures[0]); +-- +1.8.3.1 + diff --git a/0057-confile-add-support-umask.patch b/0057-confile-add-support-umask.patch new file mode 100644 index 0000000..1c9b306 --- /dev/null +++ b/0057-confile-add-support-umask.patch @@ -0,0 +1,146 @@ +From b35461f2219dba74b2a51c576ec667f8912632d1 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Wed, 30 Jan 2019 03:39:42 -0500 +Subject: [PATCH 057/122] confile: add support umask + +lxc.isulad.umask=normal make the container umask to 0022 +lxc.isulad.umask=secure make the container umask to 0027 (default) + +Signed-off-by: LiFeng +--- + src/lxc/attach.c | 4 ++-- + src/lxc/conf.c | 5 +++-- + src/lxc/conf.h | 1 + + src/lxc/confile.c | 38 ++++++++++++++++++++++++++++++++++++++ + 4 files changed, 44 insertions(+), 4 deletions(-) + +diff --git a/src/lxc/attach.c b/src/lxc/attach.c +index b44ea74..9768897 100644 +--- a/src/lxc/attach.c ++++ b/src/lxc/attach.c +@@ -768,8 +768,8 @@ static int attach_child_main(struct attach_clone_payload *payload) + msg_fd = init_ctx->container->lxc_conf->errpipe[1]; + init_ctx->container->lxc_conf->errpipe[1] = -1; + +- /*isulad: set system umask 0027 for safe control */ +- umask(0027); ++ /*isulad: set system umask */ ++ umask(init_ctx->container->lxc_conf->umask); + + /*isulad: restore default signal handlers and unblock all signals*/ + for (i = 1; i < NSIG; i++) +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 0c6aa28..67beefe 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -3163,6 +3163,7 @@ struct lxc_conf *lxc_conf_init(void) + new->errmsg = NULL; + new->errpipe[0] = -1; + new->errpipe[1] = -1; ++ new->umask = 0027; /*default umask 0027*/ + /* isulad add end */ + + return new; +@@ -4216,8 +4217,8 @@ int lxc_setup(struct lxc_handler *handler) + } + } + +- /*isulad: set system umask 0027 for safe control*/ +- umask(0027); ++ /*isulad: set system umask */ ++ umask(lxc_conf->umask); + + ret = setup_personality(lxc_conf->personality); + if (ret < 0) { +diff --git a/src/lxc/conf.h b/src/lxc/conf.h +index 88f5b41..93cf15d 100644 +--- a/src/lxc/conf.h ++++ b/src/lxc/conf.h +@@ -427,6 +427,7 @@ struct lxc_conf { + + char *errmsg; /* record error messages */ + int errpipe[2];//pipdfd for get error message of child or grandchild process. ++ mode_t umask; //umask value + /* isulad add end */ + }; + +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index f66d01b..3940b32 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -155,6 +155,7 @@ lxc_config_define(proc); + /*isulad add begin*/ + lxc_config_define(init_args); + lxc_config_define(populate_device); ++lxc_config_define(umask); + /*isulad add end*/ + + +@@ -247,6 +248,7 @@ static struct lxc_config_t config_jump_table[] = { + { "lxc.isulad.populate.device", set_config_populate_device, get_config_populate_device, clr_config_populate_device, }, + { "lxc.isulad.rootfs.maskedpaths", set_config_rootfs_masked_paths, get_config_rootfs_masked_paths, clr_config_rootfs_masked_paths, }, + { "lxc.isulad.rootfs.ropaths", set_config_rootfs_ro_paths, get_config_rootfs_ro_paths, clr_config_rootfs_ro_paths, }, ++ { "lxc.isulad.umask", set_config_umask, get_config_umask, clr_config_umask, }, + /*isulad add end*/ + }; + +@@ -2371,6 +2373,27 @@ on_error: + + } + ++/* isulad: set config for umask */ ++static int set_config_umask(const char *key, const char *value, ++ struct lxc_conf *lxc_conf, void *data) ++{ ++ if (lxc_config_value_empty(value)) { ++ ERROR("Empty umask"); ++ return -1; ++ } ++ ++ if (strcmp(value, "normal") == 0) { ++ lxc_conf->umask = 0022; ++ return 0; ++ } else if (strcmp(value, "secure") == 0) { ++ lxc_conf->umask = 0027; ++ return 0; ++ } else { ++ ERROR("Invalid native umask: %s", value); ++ return -1; ++ } ++} ++ + struct parse_line_conf { + struct lxc_conf *conf; + bool from_include; +@@ -3141,6 +3164,13 @@ static int get_config_tty_max(const char *key, char *retv, int inlen, + return lxc_get_conf_size_t(c, retv, inlen, c->ttys.max); + } + ++/* isulad add: get umask value*/ ++static int get_config_umask(const char *key, char *retv, int inlen, ++ struct lxc_conf *c, void *data) ++{ ++ return lxc_get_conf_size_t(c, retv, inlen, c->umask); ++} ++ + static int get_config_tty_dir(const char *key, char *retv, int inlen, + struct lxc_conf *c, void *data) + { +@@ -4396,6 +4426,14 @@ static int clr_config_namespace_share(const char *key, + return 0; + } + ++/* isulad add: clear umask value */ ++static inline int clr_config_umask(const char *key, struct lxc_conf *c, ++ void *data) ++{ ++ c->umask = 0027; ++ return 0; ++} ++ + static int get_config_includefiles(const char *key, char *retv, int inlen, + struct lxc_conf *c, void *data) + { +-- +1.8.3.1 + diff --git a/0058-do-not-check-ppid-when-set-death-signal.patch b/0058-do-not-check-ppid-when-set-death-signal.patch new file mode 100644 index 0000000..e7fe48f --- /dev/null +++ b/0058-do-not-check-ppid-when-set-death-signal.patch @@ -0,0 +1,36 @@ +From 920c4a399b121ade499482cae1768f995576b547 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Tue, 12 Feb 2019 14:00:47 +0800 +Subject: [PATCH 058/122] do not check ppid when set death signal + +ppid will not be 0 if we shared host pid + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/utils.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index 9a50fce..0aa87aa 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -1722,12 +1722,13 @@ int lxc_set_death_signal(int signal, pid_t parent) + prctl_arg(0), prctl_arg(0)); + + /* Check whether we have been orphaned. */ +- ppid = (pid_t)syscall(SYS_getppid); ++ /* isulad: delete this check, ppid will not be 0 if we shared host pid */ ++ /*ppid = (pid_t)syscall(SYS_getppid); + if (ppid != parent) { + ret = raise(SIGKILL); + if (ret < 0) + return -1; +- } ++ }*/ + + if (ret < 0) + return -1; +-- +1.8.3.1 + diff --git a/0059-delete-unused-variable-ppid.patch b/0059-delete-unused-variable-ppid.patch new file mode 100644 index 0000000..2de91a0 --- /dev/null +++ b/0059-delete-unused-variable-ppid.patch @@ -0,0 +1,27 @@ +From 897a0999c48453547cd8631a622defe233804be1 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Tue, 12 Feb 2019 14:36:35 +0800 +Subject: [PATCH 059/122] delete unused variable ppid + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/utils.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index 0aa87aa..91ba493 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -1716,7 +1716,7 @@ uint64_t lxc_find_next_power2(uint64_t n) + int lxc_set_death_signal(int signal, pid_t parent) + { + int ret; +- pid_t ppid; ++ //pid_t ppid; + + ret = prctl(PR_SET_PDEATHSIG, prctl_arg(signal), prctl_arg(0), + prctl_arg(0), prctl_arg(0)); +-- +1.8.3.1 + diff --git a/0060-using-json-file-to-write-console-log-of-container.patch b/0060-using-json-file-to-write-console-log-of-container.patch new file mode 100644 index 0000000..00b6ecd --- /dev/null +++ b/0060-using-json-file-to-write-console-log-of-container.patch @@ -0,0 +1,610 @@ +From 1e1274c4202cb8aac8395586f163d6b27b31ff28 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Wed, 30 Jan 2019 17:44:19 +0800 +Subject: [PATCH 060/122] using json-file to write console log of container + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/Makefile.am | 2 + + src/lxc/json/json_common.c | 14 ++- + src/lxc/json/json_common.h | 2 + + src/lxc/json/logger_json_file.c | 243 ++++++++++++++++++++++++++++++++++++++++ + src/lxc/json/logger_json_file.h | 45 ++++++++ + src/lxc/terminal.c | 166 +++++++++++++++++++++++++-- + 6 files changed, 457 insertions(+), 15 deletions(-) + create mode 100644 src/lxc/json/logger_json_file.c + create mode 100644 src/lxc/json/logger_json_file.h + +diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am +index 260a7eb..698f8f9 100644 +--- a/src/lxc/Makefile.am ++++ b/src/lxc/Makefile.am +@@ -47,6 +47,7 @@ noinst_HEADERS = attach.h \ + json/json_common.h \ + json/oci_runtime_hooks.h \ + json/oci_runtime_spec.h \ ++ json/logger_json_file.h \ + json/read-file.h \ + utils.h + +@@ -149,6 +150,7 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \ + json/json_common.c json/json_common.h \ + json/defs.h json/defs.c \ + json/oci_runtime_hooks.c json/oci_runtime_hooks.h \ ++ json/logger_json_file.c json/logger_json_file.h \ + json/oci_runtime_spec.c json/oci_runtime_spec.h \ + json/read-file.c json/read-file.h \ + $(LSM_SOURCES) +diff --git a/src/lxc/json/json_common.c b/src/lxc/json/json_common.c +index 8b91844..e339ab3 100755 +--- a/src/lxc/json/json_common.c ++++ b/src/lxc/json/json_common.c +@@ -86,7 +86,7 @@ bool json_gen_init(yajl_gen *g, struct parser_context *ctx) { + + } + yajl_gen_config(*g, yajl_gen_beautify, !(ctx->options & GEN_OPTIONS_SIMPLIFY)); +- yajl_gen_config(*g, yajl_gen_validate_utf8, 1); ++ yajl_gen_config(*g, yajl_gen_validate_utf8, !(ctx->options & GEN_OPTIONS_NOT_VALIDATE_UTF8)); + return true; + } + +@@ -1156,7 +1156,7 @@ json_map_string_string *make_json_map_string_string(yajl_val src, struct parser_ + return ret; + } + int append_json_map_string_string(json_map_string_string *map, const char *key, const char *val) { +- size_t len; ++ size_t len, i; + char **keys; + char **vals; + +@@ -1164,6 +1164,14 @@ int append_json_map_string_string(json_map_string_string *map, const char *key, + return -1; + } + ++ for (i = 0; i < map->len; i++) { ++ if (strcmp(map->keys[i], key) == 0) { ++ free(map->values[i]); ++ map->values[i] = safe_strdup(val ? val : ""); ++ return 0; ++ } ++ } ++ + if ((SIZE_MAX / sizeof(char *) - 1) < map->len) { + return -1; + } +@@ -1193,4 +1201,4 @@ int append_json_map_string_string(json_map_string_string *map, const char *key, + + map->len++; + return 0; +-} ++} +\ No newline at end of file +diff --git a/src/lxc/json/json_common.h b/src/lxc/json/json_common.h +index 904fe3c..eb8281c 100755 +--- a/src/lxc/json/json_common.h ++++ b/src/lxc/json/json_common.h +@@ -23,6 +23,8 @@ extern "C" { + # define GEN_OPTIONS_ALLKEYVALUE 0x02 + //options to generate simplify(no indent) json string + # define GEN_OPTIONS_SIMPLIFY 0x04 ++//options not to validate utf8 data ++# define GEN_OPTIONS_NOT_VALIDATE_UTF8 0x08 + + #define GEN_SET_ERROR_AND_RETURN(stat, err) { \ + if (!*(err)) {\ +diff --git a/src/lxc/json/logger_json_file.c b/src/lxc/json/logger_json_file.c +new file mode 100644 +index 0000000..4d78103 +--- /dev/null ++++ b/src/lxc/json/logger_json_file.c +@@ -0,0 +1,243 @@ ++// Generated from json-file.json. Do not edit! ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE ++#endif ++#include ++#include ++#include "securec.h" ++#include "logger_json_file.h" ++ ++logger_json_file *make_logger_json_file(yajl_val tree, struct parser_context *ctx, parser_error *err) { ++ logger_json_file *ret = NULL; ++ *err = 0; ++ if (tree == NULL) ++ return ret; ++ ret = safe_malloc(sizeof(*ret)); ++ { ++ yajl_val tmp = get_val(tree, "log", yajl_t_string); ++ if (tmp) { ++ char *str = YAJL_GET_STRING(tmp); ++ ret->log = (uint8_t *)safe_strdup(str ? str : ""); ++ ret->log_len = str ? strlen(str) : 0; ++ } ++ } ++ { ++ yajl_val val = get_val(tree, "stream", yajl_t_string); ++ if (val) { ++ char *str = YAJL_GET_STRING(val); ++ ret->stream = safe_strdup(str ? str : ""); ++ } ++ } ++ { ++ yajl_val val = get_val(tree, "time", yajl_t_string); ++ if (val) { ++ char *str = YAJL_GET_STRING(val); ++ ret->time = safe_strdup(str ? str : ""); ++ } ++ } ++ { ++ yajl_val tmp = get_val(tree, "attrs", yajl_t_string); ++ if (tmp) { ++ char *str = YAJL_GET_STRING(tmp); ++ ret->attrs = (uint8_t *)safe_strdup(str ? str : ""); ++ ret->attrs_len = str ? strlen(str) : 0; ++ } ++ } ++ ++ if (tree->type == yajl_t_object && (ctx->options & PARSE_OPTIONS_STRICT)) { ++ int i; ++ for (i = 0; i < tree->u.object.len; i++) ++ if (strcmp(tree->u.object.keys[i], "log") && ++ strcmp(tree->u.object.keys[i], "stream") && ++ strcmp(tree->u.object.keys[i], "time") && ++ strcmp(tree->u.object.keys[i], "attrs")) { ++ if (ctx->stderr > 0) ++ fprintf(ctx->stderr, "WARNING: unknown key found: %s\n", tree->u.object.keys[i]); ++ } ++ } ++ return ret; ++} ++ ++void free_logger_json_file(logger_json_file *ptr) { ++ if (!ptr) ++ return; ++ free(ptr->log); ++ ptr->log = NULL; ++ free(ptr->stream); ++ ptr->stream = NULL; ++ free(ptr->time); ++ ptr->time = NULL; ++ free(ptr->attrs); ++ ptr->attrs = NULL; ++ free(ptr); ++} ++ ++yajl_gen_status gen_logger_json_file(yajl_gen g, logger_json_file *ptr, struct parser_context *ctx, parser_error *err) { ++ yajl_gen_status stat = yajl_gen_status_ok; ++ *err = 0; ++ stat = reformat_start_map(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) || (ptr && ptr->log && ptr->log_len)) { ++ const char *str = ""; ++ size_t len = 0; ++ stat = reformat_map_key(g, "log", strlen("log")); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (ptr && ptr->log) { ++ str = (const char *)ptr->log; ++ len = ptr->log_len; ++ } ++ stat = reformat_string(g, str, len); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr && ptr->stream)) { ++ char *str = ""; ++ stat = reformat_map_key(g, "stream", strlen("stream")); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (ptr && ptr->stream) { ++ str = ptr->stream; ++ } ++ stat = reformat_string(g, str, strlen(str)); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr && ptr->time)) { ++ char *str = ""; ++ stat = reformat_map_key(g, "time", strlen("time")); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (ptr && ptr->time) { ++ str = ptr->time; ++ } ++ stat = reformat_string(g, str, strlen(str)); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) || (ptr && ptr->attrs && ptr->attrs_len)) { ++ const char *str = ""; ++ size_t len = 0; ++ stat = reformat_map_key(g, "attrs", strlen("attrs")); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (ptr && ptr->attrs) { ++ str = (const char *)ptr->attrs; ++ len = ptr->attrs_len; ++ } ++ stat = reformat_string(g, str, len); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ stat = reformat_end_map(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ return yajl_gen_status_ok; ++} ++ ++ ++logger_json_file *logger_json_file_parse_file(const char *filename, struct parser_context *ctx, parser_error *err) { ++ logger_json_file *ptr; ++ size_t filesize; ++ char *content; ++ ++ if (!filename || !err) ++ return NULL; ++ ++ *err = NULL; ++ content = read_file(filename, &filesize); ++ if (content == NULL) { ++ if (asprintf(err, "cannot read the file: %s", filename) < 0) ++ *err = safe_strdup("error allocating memory"); ++ return NULL; ++ } ++ ptr = logger_json_file_parse_data(content, ctx, err); ++ free(content); ++ return ptr; ++} ++ ++logger_json_file *logger_json_file_parse_file_stream(FILE *stream, struct parser_context *ctx, parser_error *err) { ++ logger_json_file *ptr; ++ size_t filesize; ++ char *content ; ++ ++ if (!stream || !err) ++ return NULL; ++ ++ *err = NULL; ++ content = fread_file(stream, &filesize); ++ if (content == NULL) { ++ *err = safe_strdup("cannot read the file"); ++ return NULL; ++ } ++ ptr = logger_json_file_parse_data(content, ctx, err); ++ free(content); ++ return ptr; ++} ++ ++logger_json_file *logger_json_file_parse_data(const char *jsondata, struct parser_context *ctx, parser_error *err) { ++ logger_json_file *ptr; ++ yajl_val tree; ++ char errbuf[1024]; ++ struct parser_context tmp_ctx; ++ ++ if (!jsondata || !err) ++ return NULL; ++ ++ *err = NULL; ++ if (!ctx) { ++ ctx = &tmp_ctx; ++ memset(&tmp_ctx, 0, sizeof(tmp_ctx)); ++ } ++ tree = yajl_tree_parse(jsondata, errbuf, sizeof(errbuf)); ++ if (tree == NULL) { ++ if (asprintf(err, "cannot parse the data: %s", errbuf) < 0) ++ *err = safe_strdup("error allocating memory"); ++ return NULL; ++ } ++ ptr = make_logger_json_file(tree, ctx, err); ++ yajl_tree_free(tree); ++ return ptr; ++} ++char *logger_json_file_generate_json(logger_json_file *ptr, struct parser_context *ctx, parser_error *err) { ++ yajl_gen g = NULL; ++ struct parser_context tmp_ctx; ++ const unsigned char *gen_buf = NULL; ++ char *json_buf = NULL; ++ size_t gen_len = 0; ++ ++ if (!ptr || !err) ++ return NULL; ++ ++ *err = NULL; ++ if (!ctx) { ++ ctx = &tmp_ctx; ++ memset(&tmp_ctx, 0, sizeof(tmp_ctx)); ++ } ++ ++ if (!json_gen_init(&g, ctx)) { ++ *err = safe_strdup("Json_gen init failed"); ++ goto out; ++ } ++ if (yajl_gen_status_ok != gen_logger_json_file(g, ptr, ctx, err)) { ++ if (!*err) ++ *err = safe_strdup("Failed to generate json"); ++ goto free_out; ++ } ++ yajl_gen_get_buf(g, &gen_buf, &gen_len); ++ if (!gen_buf) { ++ *err = safe_strdup("Error to get generated json"); ++ goto free_out; ++ } ++ ++ json_buf = safe_malloc(gen_len + 1); ++ memcpy(json_buf, gen_buf, gen_len); ++ json_buf[gen_len] = '\0'; ++ ++free_out: ++ yajl_gen_clear(g); ++ yajl_gen_free(g); ++out: ++ return json_buf; ++} +diff --git a/src/lxc/json/logger_json_file.h b/src/lxc/json/logger_json_file.h +new file mode 100644 +index 0000000..ad5af7b +--- /dev/null ++++ b/src/lxc/json/logger_json_file.h +@@ -0,0 +1,45 @@ ++// Generated from json-file.json. Do not edit! ++#ifndef LOGGER_JSON_FILE_SCHEMA_H ++#define LOGGER_JSON_FILE_SCHEMA_H ++ ++#include ++#include ++#include "json_common.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef struct { ++ uint8_t *log; ++ size_t log_len; ++ ++ char *stream; ++ ++ char *time; ++ ++ uint8_t *attrs; ++ size_t attrs_len; ++ ++} ++logger_json_file; ++ ++void free_logger_json_file(logger_json_file *ptr); ++ ++logger_json_file *make_logger_json_file(yajl_val tree, struct parser_context *ctx, parser_error *err); ++ ++yajl_gen_status gen_logger_json_file(yajl_gen g, logger_json_file *ptr, struct parser_context *ctx, parser_error *err); ++ ++logger_json_file *logger_json_file_parse_file(const char *filename, struct parser_context *ctx, parser_error *err); ++ ++logger_json_file *logger_json_file_parse_file_stream(FILE *stream, struct parser_context *ctx, parser_error *err); ++ ++logger_json_file *logger_json_file_parse_data(const char *jsondata, struct parser_context *ctx, parser_error *err); ++ ++char *logger_json_file_generate_json(logger_json_file *ptr, struct parser_context *ctx, parser_error *err); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index 252a644..602d43d 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -47,6 +47,7 @@ + #include "start.h" + #include "syscall_wrappers.h" + #include "terminal.h" ++#include "logger_json_file.h" + #include "utils.h" + + #if HAVE_PTY_H +@@ -298,7 +299,7 @@ static int lxc_terminal_rotate_log_file(struct lxc_terminal *terminal) + return lxc_terminal_create_log_file(terminal); + } + +-static int lxc_terminal_write_log_file(struct lxc_terminal *terminal, char *buf, ++static int lxc_terminal_rotate_write_data(struct lxc_terminal *terminal, const char *buf, + int bytes_read) + { + int ret; +@@ -357,16 +358,6 @@ static int lxc_terminal_write_log_file(struct lxc_terminal *terminal, char *buf, + if (bytes_read <= space_left) + return lxc_write_nointr(terminal->log_fd, buf, bytes_read); + +- /* There's not enough space left but at least write as much as we can +- * into the old log file. +- */ +- ret = lxc_write_nointr(terminal->log_fd, buf, space_left); +- if (ret < 0) +- return -1; +- +- /* Calculate how many bytes we still need to write. */ +- bytes_read -= space_left; +- + /* There'd be more to write but we aren't instructed to rotate the log + * file so simply return. There's no error on our side here. + */ +@@ -404,6 +395,151 @@ static int lxc_terminal_write_log_file(struct lxc_terminal *terminal, char *buf, + return bytes_read; + } + ++/* get time buffer */ ++static bool get_time_buffer(struct timespec *timestamp, char *timebuffer, ++ size_t maxsize) ++{ ++ struct tm tm_utc = { 0 }; ++ int32_t nanos = 0; ++ time_t seconds; ++ ++ if (!timebuffer || !maxsize) { ++ return false; ++ } ++ ++ seconds = (time_t)timestamp->tv_sec; ++ gmtime_r(&seconds, &tm_utc); ++ strftime(timebuffer, maxsize, "%Y-%m-%dT%H:%M:%S", &tm_utc); ++ ++ nanos = (int32_t)timestamp->tv_nsec; ++ sprintf(timebuffer + strlen(timebuffer), ".%09dZ", nanos); ++ ++ return true; ++} ++ ++/* get now time buffer */ ++static bool get_now_time_buffer(char *timebuffer, size_t maxsize) ++{ ++ int err = 0; ++ struct timespec ts; ++ ++ err = clock_gettime(CLOCK_REALTIME, &ts); ++ if (err != 0) { ++ ERROR("failed to get time"); ++ return false; ++ } ++ ++ return get_time_buffer(&ts, timebuffer, maxsize); ++} ++ ++static ssize_t lxc_logger_write(struct lxc_terminal *terminal, const char *buf, ++ int bytes_read) ++{ ++ logger_json_file *msg = NULL; ++ ssize_t ret = -1; ++ size_t len; ++ char *json = NULL, timebuffer[64]; ++ parser_error err = NULL; ++ struct parser_context ctx = { GEN_OPTIONS_SIMPLIFY | GEN_OPTIONS_NOT_VALIDATE_UTF8, stderr }; ++ ++ msg = calloc(sizeof(logger_json_file), 1); ++ if (!msg) { ++ return -errno; ++ } ++ msg->log = calloc(bytes_read, 1); ++ if (!msg->log) { ++ goto cleanup; ++ } ++ memcpy(msg->log, buf, bytes_read); ++ msg->log_len = bytes_read; ++ msg->stream = strdup("stdout"); ++ ++ get_now_time_buffer(timebuffer, sizeof(timebuffer)); ++ msg->time = strdup(timebuffer); ++ ++ json = logger_json_file_generate_json(msg, &ctx, &err); ++ if (!json) { ++ ERROR("Failed to generate json: %s", err); ++ goto cleanup; ++ } ++ len = strlen(json); ++ json[len] = '\n'; ++ ret = lxc_terminal_rotate_write_data(terminal, json, len + 1); ++cleanup: ++ free(json); ++ free_logger_json_file(msg); ++ free(err); ++ return ret; ++} ++ ++static int lxc_terminal_write_log_file(struct lxc_terminal *terminal, char *buf, ++ int bytes_read) ++{ ++#define __BUF_CACHE_SIZE (16 * LXC_TERMINAL_BUFFER_SIZE) ++ static char cache[__BUF_CACHE_SIZE]; ++ static int size = 0; ++ int upto, index; ++ int begin = 0, buf_readed = 0, buf_left = 0; ++ int ret; ++ ++ if (buf != NULL && bytes_read > 0) { ++ /* Work out how much more data we are okay with reading this time. */ ++ upto = size + bytes_read; ++ if (upto > __BUF_CACHE_SIZE) { ++ upto = __BUF_CACHE_SIZE; ++ } ++ ++ if (upto > size) { ++ buf_readed = upto - size; ++ memcpy(cache + size, buf, buf_readed); ++ buf_left = bytes_read - buf_readed; ++ size += buf_readed; ++ } ++ } ++ ++ // If we have no data to log, and there's no more coming, we're done. ++ if (size == 0) ++ return 0; ++ ++ // Break up the data that we've buffered up into lines, and log each in turn. ++ for (index = 0; index < size; index++) { ++ if (cache[index] == '\n') { ++ ret = lxc_logger_write(terminal, cache + begin, index - begin + 1); ++ if (ret < 0) { ++ WARN("Failed to log msg"); ++ } ++ begin = index + 1; ++ } ++ } ++ /* If there's no more coming, or the buffer is full but ++ * has no newlines, log whatever we haven't logged yet, ++ * noting that it's a partial log line. */ ++ if (buf == NULL || (begin == 0 && size == __BUF_CACHE_SIZE)) { ++ if (begin < size) { ++ ret = lxc_logger_write(terminal, cache + begin, index - begin + 1); ++ if (ret < 0) { ++ WARN("Failed to log msg"); ++ } ++ begin = 0; ++ size = 0; ++ } ++ if (buf == NULL) { ++ return 0; ++ } ++ } ++ /* Move any unlogged data to the front of the buffer in preparation for another read. */ ++ if (begin > 0) { ++ memcpy(cache, cache + begin, size - begin); ++ size -= begin; ++ } ++ /* Move left data to cache buffer */ ++ if (buf_left > 0) { ++ memcpy(cache + size, buf + buf_readed, buf_left); ++ size += buf_left; ++ } ++ return 0; ++} ++ + /* isulad: forward data to all fifos */ + static void lxc_forward_data_to_fifo(struct lxc_list *list, char *buf, int r) + { +@@ -437,7 +573,7 @@ int lxc_terminal_io_cb(int fd, uint32_t events, void *data, + struct lxc_epoll_descr *descr) + { + struct lxc_terminal *terminal = data; +- char buf[LXC_TERMINAL_BUFFER_SIZE]; ++ char buf[2 * LXC_TERMINAL_BUFFER_SIZE]; + int r, w, w_log, w_rbuf; + + w = r = lxc_read_nointr(fd, buf, sizeof(buf)); +@@ -447,6 +583,12 @@ int lxc_terminal_io_cb(int fd, uint32_t events, void *data, + + if (fd == terminal->master) { + terminal->master = -EBADF; ++ /* write remained buffer to terminal log */ ++ if (terminal->log_fd >= 0) { ++ w_log = lxc_terminal_write_log_file(terminal, NULL, 0); ++ if (w_log < 0) ++ TRACE("Failed to write %d bytes to terminal log", r); ++ } + } else if (fd == terminal->peer) { + if (terminal->tty_state) { + lxc_terminal_signal_fini(terminal->tty_state); +-- +1.8.3.1 + diff --git a/0061-Fix-hook-use-the-path-args-envs-execvp-dirctory.patch b/0061-Fix-hook-use-the-path-args-envs-execvp-dirctory.patch new file mode 100644 index 0000000..4c73880 --- /dev/null +++ b/0061-Fix-hook-use-the-path-args-envs-execvp-dirctory.patch @@ -0,0 +1,50 @@ +From c9dc04b4237ac01155a8ce37beae9db4ea7c2b1a Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Thu, 21 Feb 2019 05:37:05 -0500 +Subject: [PATCH 061/122] Fix hook: use the path, args, envs execvp dirctory + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 17 ++--------------- + 1 file changed, 2 insertions(+), 15 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 67beefe..c2f3cf5 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4467,9 +4467,6 @@ static struct lxc_popen_FILE *lxc_popen_ocihook(char *commandpath, char **args, + + if (child_pid == 0) { + /* child */ +- size_t result_capacity; +- int r; +- char **real_args; + + close(pipe_msg[1]); + if (pipe_msg[0] != STDIN_FILENO) +@@ -4514,20 +4511,10 @@ static struct lxc_popen_FILE *lxc_popen_ocihook(char *commandpath, char **args, + sigprocmask(SIG_UNBLOCK, &mask, NULL); + } + +- result_capacity = args_len; +- real_args = malloc(sizeof(char *) * (result_capacity + 2 + 1)); +- if (!real_args) +- _exit(EXIT_FAILURE); +- memset(real_args, 0, sizeof(char *) * (result_capacity + 2 + 1)); +- real_args[0] = strdup("sh"); +- real_args[1] = strdup(commandpath); +- for(r = 2; r < (args_len + 1); r++) +- real_args[r] = strdup(args[r-1]); +- + if (env_len > 0) +- execvpe("/bin/sh", real_args, envs); ++ execvpe(commandpath, args, envs); + else +- execvp("/bin/sh", real_args); ++ execvp(commandpath, args); + exit(127); + } + +-- +1.8.3.1 + diff --git a/0062-setup-sysctls-before-set-read-only-path-and-masked-p.patch b/0062-setup-sysctls-before-set-read-only-path-and-masked-p.patch new file mode 100644 index 0000000..5449152 --- /dev/null +++ b/0062-setup-sysctls-before-set-read-only-path-and-masked-p.patch @@ -0,0 +1,74 @@ +From e0c8855867b71eb0106a312e84389389cee395d7 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Tue, 26 Feb 2019 17:21:18 +0800 +Subject: [PATCH 062/122] setup sysctls before set read-only path and masked + path + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 34 +++++++++++++++++----------------- + 1 file changed, 17 insertions(+), 17 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index c2f3cf5..e139dff 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -3039,7 +3039,7 @@ int setup_sysctl_parameters(struct lxc_list *sysctls) + ret = lxc_write_to_file(filename, elem->value, + strlen(elem->value), false, 0666); + if (ret < 0) { +- ERROR("Failed to setup sysctl parameters %s to %s", ++ SYSERROR("Failed to setup sysctl parameters %s to %s", + elem->key, elem->value); + return -1; + } +@@ -4201,22 +4201,6 @@ int lxc_setup(struct lxc_handler *handler) + if (ret < 0) + goto on_error; + +- //isulad: setup rootfs masked paths +- if (!lxc_list_empty(&lxc_conf->rootfs.maskedpaths)) { +- if (setup_rootfs_maskedpaths(&lxc_conf->rootfs.maskedpaths)) { +- ERROR("failed to setup maskedpaths"); +- goto on_error; +- } +- } +- +- // isulad: setup rootfs ro paths +- if (!lxc_list_empty(&lxc_conf->rootfs.ropaths)) { +- if (setup_rootfs_ropaths(&lxc_conf->rootfs.ropaths)) { +- ERROR("failed to setup readonlypaths"); +- goto on_error; +- } +- } +- + /*isulad: set system umask */ + umask(lxc_conf->umask); + +@@ -4238,6 +4222,22 @@ int lxc_setup(struct lxc_handler *handler) + } + } + ++ // isulad: setup rootfs masked paths ++ if (!lxc_list_empty(&lxc_conf->rootfs.maskedpaths)) { ++ if (setup_rootfs_maskedpaths(&lxc_conf->rootfs.maskedpaths)) { ++ ERROR("failed to setup maskedpaths"); ++ goto on_error; ++ } ++ } ++ ++ // isulad: setup rootfs ro paths ++ if (!lxc_list_empty(&lxc_conf->rootfs.ropaths)) { ++ if (setup_rootfs_ropaths(&lxc_conf->rootfs.ropaths)) { ++ ERROR("failed to setup readonlypaths"); ++ goto on_error; ++ } ++ } ++ + if (!lxc_list_empty(&lxc_conf->keepcaps)) { + if (!lxc_list_empty(&lxc_conf->caps)) { + ERROR("Container requests lxc.cap.drop and " +-- +1.8.3.1 + diff --git a/0063-lxc-ignore-systemcall-load-failure-error.patch b/0063-lxc-ignore-systemcall-load-failure-error.patch new file mode 100644 index 0000000..6403557 --- /dev/null +++ b/0063-lxc-ignore-systemcall-load-failure-error.patch @@ -0,0 +1,27 @@ +From aa6af28e14e024cfc31b8d77516df9899eb480c8 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Sat, 9 Mar 2019 03:10:06 +0800 +Subject: [PATCH 063/122] lxc: ignore systemcall load failure error + +Signed-off-by: wujing +Signed-off-by: LiFeng +--- + src/lxc/seccomp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c +index 4a5b3d0..26eac90 100644 +--- a/src/lxc/seccomp.c ++++ b/src/lxc/seccomp.c +@@ -543,7 +543,7 @@ bool do_resolve_add_rule(uint32_t arch, char *line, scmp_filter_ctx ctx, + errno = -ret; + SYSERROR("Failed loading rule for %s (nr %d action %d (%s))", + line, nr, rule->action, get_action_name(rule->action)); +- return false; ++ return true; + } + + return true; +-- +1.8.3.1 + diff --git a/0064-lxc-Reduce-seccomp-processing-log-level.patch b/0064-lxc-Reduce-seccomp-processing-log-level.patch new file mode 100644 index 0000000..3e297f7 --- /dev/null +++ b/0064-lxc-Reduce-seccomp-processing-log-level.patch @@ -0,0 +1,46 @@ +From ec896c711806cad0fa852ea1695361441e840132 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Sun, 10 Mar 2019 00:47:05 +0800 +Subject: [PATCH 064/122] lxc: Reduce seccomp processing log level + +Signed-off-by: wujing +Signed-off-by: LiFeng +--- + src/lxc/seccomp.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c +index 26eac90..7f10777 100644 +--- a/src/lxc/seccomp.c ++++ b/src/lxc/seccomp.c +@@ -507,14 +507,14 @@ bool do_resolve_add_rule(uint32_t arch, char *line, scmp_filter_ctx ctx, + + nr = seccomp_syscall_resolve_name(line); + if (nr == __NR_SCMP_ERROR) { +- WARN("Failed to resolve syscall \"%s\"", line); +- WARN("This syscall will NOT be handled by seccomp"); ++ DEBUG("Failed to resolve syscall \"%s\"", line); ++ DEBUG("This syscall will NOT be handled by seccomp"); + return true; + } + + if (nr < 0) { +- WARN("Got negative return value %d for syscall \"%s\"", nr, line); +- WARN("This syscall will NOT be handled by seccomp"); ++ DEBUG("Got negative return value %d for syscall \"%s\"", nr, line); ++ DEBUG("This syscall will NOT be handled by seccomp"); + return true; + } + +@@ -541,7 +541,7 @@ bool do_resolve_add_rule(uint32_t arch, char *line, scmp_filter_ctx ctx, + rule->args_num, arg_cmp); + if (ret < 0) { + errno = -ret; +- SYSERROR("Failed loading rule for %s (nr %d action %d (%s))", ++ DEBUG("Failed loading rule for %s (nr %d action %d (%s))", + line, nr, rule->action, get_action_name(rule->action)); + return true; + } +-- +1.8.3.1 + diff --git a/0065-Storage-return-true-if-storage_init-init-fail.patch b/0065-Storage-return-true-if-storage_init-init-fail.patch new file mode 100644 index 0000000..fec20d5 --- /dev/null +++ b/0065-Storage-return-true-if-storage_init-init-fail.patch @@ -0,0 +1,30 @@ +From d771f62e77e5d122178b171a06a821af4103e48d Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Mon, 11 Mar 2019 23:26:27 -0400 +Subject: [PATCH 065/122] Storage: return true if storage_init init fail + +Signed-off-by: LiFeng +--- + src/lxc/storage/storage.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/lxc/storage/storage.c b/src/lxc/storage/storage.c +index 18f754a..88ed788 100644 +--- a/src/lxc/storage/storage.c ++++ b/src/lxc/storage/storage.c +@@ -610,8 +610,11 @@ bool storage_destroy(struct lxc_conf *conf) + int destroy_rv = 0; + + r = storage_init(conf); +- if (!r) ++ if (r == NULL) { ++ ERROR("%s 's storage init failed, the storage may be deleted already", conf->name); ++ ret = true; + return ret; ++ } + + destroy_rv = r->ops->destroy(r); + if (destroy_rv == 0) +-- +1.8.3.1 + diff --git a/0066-lxc-Pids-limit-does-not-report-an-error-after-execut.patch b/0066-lxc-Pids-limit-does-not-report-an-error-after-execut.patch new file mode 100644 index 0000000..302e3cd --- /dev/null +++ b/0066-lxc-Pids-limit-does-not-report-an-error-after-execut.patch @@ -0,0 +1,28 @@ +From 5c96085ffd6f219f92bc210c057e9d964c75cd84 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Fri, 15 Mar 2019 10:11:10 +0800 +Subject: [PATCH 066/122] lxc: Pids limit does not report an error after + executing the limit in the background + +Signed-off-by: wujing +Signed-off-by: LiFeng +--- + src/lxc/tools/lxc_attach.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c +index 8856934..acdf8a0 100644 +--- a/src/lxc/tools/lxc_attach.c ++++ b/src/lxc/tools/lxc_attach.c +@@ -378,6 +378,8 @@ static int do_attach_background(struct lxc_container *c, lxc_attach_command_t *c + if (ret < 0) { + if (c->lxc_conf->errmsg) + lxc_write_error_message(msgpipe[1], "%s", c->lxc_conf->errmsg); ++ else ++ lxc_write_error_message(msgpipe[1], "Failed to attach container"); + close(msgpipe[1]); + msgpipe[1] = -1; + ret = -1; +-- +1.8.3.1 + diff --git a/0067-lxc-report-error-when-remove-directory-failed.patch b/0067-lxc-report-error-when-remove-directory-failed.patch new file mode 100644 index 0000000..723dc40 --- /dev/null +++ b/0067-lxc-report-error-when-remove-directory-failed.patch @@ -0,0 +1,72 @@ +From 6942bba7a61f9fe55d5d819ffd817ea4b028d040 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Sat, 16 Mar 2019 10:06:13 +0800 +Subject: [PATCH 067/122] lxc: report error when remove directory failed + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/lxccontainer.c | 3 +++ + src/lxc/utils.c | 9 ++++++++- + 2 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index bfbf223..3fd1a66 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -3148,8 +3148,11 @@ static bool container_destroy(struct lxc_container *c, + else + ret = lxc_rmdir_onedev(path, "snaps"); + if (ret < 0) { ++ char msg[BUFSIZ] = { 0 }; + ERROR("Failed to destroy directory \"%s\" for \"%s\"", path, + c->name); ++ sprintf(msg, "Failed to destroy directory \"%s\": %s", path, errno ? strerror(errno) : "error"); ++ c->error_string = strdup(msg); + goto out; + } + INFO("Destroyed directory \"%s\" for \"%s\"", path, c->name); +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index 91ba493..480e6d0 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -88,6 +88,7 @@ static int _recursive_rmdir(const char *dirname, dev_t pdev, + int ret, failed = 0; + char pathname[PATH_MAX]; + bool hadexclude = false; ++ int saved_errno = 0; + + dir = opendir(dirname); + if (!dir) { +@@ -153,6 +154,9 @@ static int _recursive_rmdir(const char *dirname, dev_t pdev, + failed=1; + } else { + if (unlink(pathname) < 0) { ++ if (saved_errno == 0) { ++ saved_errno = errno; ++ } + SYSERROR("Failed to delete \"%s\"", pathname); + failed=1; + } +@@ -160,6 +164,9 @@ static int _recursive_rmdir(const char *dirname, dev_t pdev, + } + + if (rmdir(dirname) < 0 && !btrfs_try_remove_subvol(dirname) && !hadexclude) { ++ if (saved_errno == 0) { ++ saved_errno = errno; ++ } + SYSERROR("Failed to delete \"%s\"", dirname); + failed=1; + } +@@ -169,7 +176,7 @@ static int _recursive_rmdir(const char *dirname, dev_t pdev, + SYSERROR("Failed to close directory \"%s\"", dirname); + failed=1; + } +- ++ errno = saved_errno; + return failed ? -1 : 0; + } + +-- +1.8.3.1 + diff --git a/0068-support-record-stdout-stderr-log-of-container-consol.patch b/0068-support-record-stdout-stderr-log-of-container-consol.patch new file mode 100644 index 0000000..3d90132 --- /dev/null +++ b/0068-support-record-stdout-stderr-log-of-container-consol.patch @@ -0,0 +1,1244 @@ +From a31be51b99331c80b66f587245cae0ca5d84d4fa Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Thu, 21 Feb 2019 20:27:47 +0800 +Subject: [PATCH 068/122] support record stdout, stderr log of container + console + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/attach.c | 15 +- + src/lxc/attach_options.h | 2 +- + src/lxc/commands.c | 15 +- + src/lxc/commands.h | 2 +- + src/lxc/conf.c | 33 +++-- + src/lxc/lxccontainer.c | 79 +++++++--- + src/lxc/lxccontainer.h | 35 ++++- + src/lxc/start.c | 67 ++++++++- + src/lxc/start.h | 5 + + src/lxc/terminal.c | 351 ++++++++++++++++++++++++++++++++------------- + src/lxc/terminal.h | 7 +- + src/lxc/tools/arguments.h | 14 +- + src/lxc/tools/lxc_attach.c | 7 +- + src/lxc/tools/lxc_start.c | 22 ++- + 14 files changed, 502 insertions(+), 152 deletions(-) + +diff --git a/src/lxc/attach.c b/src/lxc/attach.c +index 9768897..c979c85 100644 +--- a/src/lxc/attach.c ++++ b/src/lxc/attach.c +@@ -1052,15 +1052,18 @@ static int lxc_attach_terminal(struct lxc_conf *conf, + lxc_terminal_init(terminal); + + /* isulad: if we pass fifo in option, use them as init fifos */ +- if (options->init_fifo[0] && options->init_fifo[1]) { +- if (terminal->init_fifo[0]) +- free(terminal->init_fifo[0]); ++ if (options->init_fifo[0]) { ++ free(terminal->init_fifo[0]); + terminal->init_fifo[0] = strdup(options->init_fifo[0]); +- +- if (terminal->init_fifo[1]) +- free(terminal->init_fifo[1]); ++ } ++ if (options->init_fifo[1]) { ++ free(terminal->init_fifo[1]); + terminal->init_fifo[1] = strdup(options->init_fifo[1]); + } ++ if (options->init_fifo[2]) { ++ free(terminal->init_fifo[2]); ++ terminal->init_fifo[2] = strdup(options->init_fifo[2]); ++ } + + ret = lxc_terminal_create(terminal); + if (ret < 0) { +diff --git a/src/lxc/attach_options.h b/src/lxc/attach_options.h +index 7b0a8cb..71c1739 100644 +--- a/src/lxc/attach_options.h ++++ b/src/lxc/attach_options.h +@@ -136,7 +136,7 @@ typedef struct lxc_attach_options_t { + /*! File descriptor to log output. */ + int log_fd; + +- char *init_fifo[2]; /* isulad: default fifos for the start */ ++ char *init_fifo[3]; /* isulad: default fifos for the start */ + } lxc_attach_options_t; + + /*! Default attach options to use */ +diff --git a/src/lxc/commands.c b/src/lxc/commands.c +index 46b2805..f0c95df 100644 +--- a/src/lxc/commands.c ++++ b/src/lxc/commands.c +@@ -1064,21 +1064,22 @@ reap_client_fd: + * + * Returns 0 when success, else when fail. + */ +-int lxc_cmd_set_terminal_fifos(const char *name, const char *lxcpath, const char *in_fifo, const char *out_fifo) ++int lxc_cmd_set_terminal_fifos(const char *name, const char *lxcpath, const char *in_fifo, ++ const char *out_fifo, const char *err_fifo) + { + int ret = 0, stopped = 0; + int len = 0; + char *tmp = NULL; ++ const char *split = "&&&&", *none_fifo_name = "none"; ++ const char *cmd_in_fifo = in_fifo ? in_fifo : none_fifo_name; ++ const char *cmd_out_fifo = out_fifo ? out_fifo : none_fifo_name; ++ const char *cmd_err_fifo = err_fifo ? err_fifo : none_fifo_name; + +- if (!in_fifo || !out_fifo) { +- return -1; +- } +- +- len = strlen(in_fifo) + strlen("&&&&") + strlen(out_fifo) + 1; ++ len += strlen(cmd_in_fifo) + strlen(split) + strlen(cmd_out_fifo) + strlen(split) + strlen(cmd_err_fifo) + 1; + tmp = malloc(len); + if (!tmp) + return -1; +- snprintf(tmp, len, "%s%s%s", in_fifo, "&&&&", out_fifo); ++ snprintf(tmp, len, "%s%s%s%s%s", cmd_in_fifo, split, cmd_out_fifo, split, cmd_err_fifo); + + struct lxc_cmd_rr cmd = { + .req = { +diff --git a/src/lxc/commands.h b/src/lxc/commands.h +index 0c64544..6b64849 100644 +--- a/src/lxc/commands.h ++++ b/src/lxc/commands.h +@@ -127,6 +127,6 @@ extern int lxc_cmd_console_log(const char *name, const char *lxcpath, + struct lxc_console_log *log); + + extern int lxc_cmd_set_terminal_fifos(const char *name, const char *lxcpath, +- const char *in_fifo, const char *out_fifo); ++ const char *in_fifo, const char *out_fifo, const char *err_fifo); + + #endif /* __commands_h */ +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index e139dff..a6b9797 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -2067,20 +2067,22 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, + return -errno; + } + +- ret = fchmod(console->slave, S_IXUSR | S_IXGRP); +- if (ret < 0) { +- SYSERROR("Failed to set mode \"0%o\" to \"%s\"", +- S_IXUSR | S_IXGRP, console->name); +- return -errno; +- } ++ if (console->slave > 0) { ++ ret = fchmod(console->slave, S_IXUSR | S_IXGRP); ++ if (ret < 0) { ++ SYSERROR("Failed to set mode \"0%o\" to \"%s\"", ++ S_IXUSR | S_IXGRP, console->name); ++ return -errno; ++ } + +- /* bind mount console->name to '/dev//console' */ +- ret = safe_mount(console->name, lxcpath, "none", MS_BIND, 0, rootfs_path); +- if (ret < 0) { +- ERROR("Failed to mount \"%s\" on \"%s\"", console->name, lxcpath); +- return -1; ++ /* bind mount console->name to '/dev//console' */ ++ ret = safe_mount(console->name, lxcpath, "none", MS_BIND, 0, rootfs_path); ++ if (ret < 0) { ++ ERROR("Failed to mount \"%s\" on \"%s\"", console->name, lxcpath); ++ return -1; ++ } ++ DEBUG("Mounted \"%s\" onto \"%s\"", console->name, lxcpath); + } +- DEBUG("Mounted \"%s\" onto \"%s\"", console->name, lxcpath); + + /* bind mount '/dev//console' to '/dev/console' */ + ret = safe_mount(lxcpath, path, "none", MS_BIND, 0, rootfs_path); +@@ -3158,6 +3160,13 @@ struct lxc_conf *lxc_conf_init(void) + /* isulad init console fifos */ + new->console.init_fifo[0] = NULL; + new->console.init_fifo[1] = NULL; ++ new->console.init_fifo[2] = NULL; ++ new->console.pipes[0][0] = -1; ++ new->console.pipes[0][1] = -1; ++ new->console.pipes[1][0] = -1; ++ new->console.pipes[1][1] = -1; ++ new->console.pipes[2][0] = -1; ++ new->console.pipes[2][1] = -1; + lxc_list_init(&new->console.fifos); + + new->errmsg = NULL; +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index 3fd1a66..8a3724c 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -702,6 +702,40 @@ static bool do_lxcapi_want_daemonize(struct lxc_container *c, bool state) + + WRAP_API_1(bool, lxcapi_want_daemonize, bool) + ++static bool do_lxcapi_want_disable_pty(struct lxc_container *c, bool state) ++{ ++ if (!c || !c->lxc_conf) ++ return false; ++ ++ if (container_mem_lock(c)) ++ return false; ++ ++ c->disable_pty = state; ++ ++ container_mem_unlock(c); ++ ++ return true; ++} ++ ++WRAP_API_1(bool, lxcapi_want_disable_pty, bool) ++ ++static bool do_lxcapi_want_open_stdin(struct lxc_container *c, bool state) ++{ ++ if (!c || !c->lxc_conf) ++ return false; ++ ++ if (container_mem_lock(c)) ++ return false; ++ ++ c->open_stdin = state; ++ ++ container_mem_unlock(c); ++ ++ return true; ++} ++ ++WRAP_API_1(bool, lxcapi_want_open_stdin, bool) ++ + static bool do_lxcapi_want_close_all_fds(struct lxc_container *c, bool state) + { + if (!c || !c->lxc_conf) +@@ -1198,12 +1232,15 @@ reboot: + goto on_error; + } + +- if (useinit) ++ if (useinit) { + ret = lxc_execute(c->name, argv, 1, handler, c->config_path, + c->daemonize, &c->error_num, c->start_timeout); +- else ++ } else { ++ handler->disable_pty = c->disable_pty; ++ handler->open_stdin = c->open_stdin; + ret = lxc_start(c->name, argv, handler, c->config_path, + c->daemonize, &c->error_num, c->start_timeout); ++ } + + if (conf->reboot == REBOOT_REQ) { + INFO("Container requested reboot"); +@@ -5085,11 +5122,11 @@ out: + } + + /* isulad add set console fifos*/ +-static bool do_lxcapi_set_terminal_default_fifos(struct lxc_container *c, const char *in, const char *out) ++static bool do_lxcapi_set_terminal_default_fifos(struct lxc_container *c, const char *in, const char *out, const char *err) + { + struct lxc_conf *conf; + +- if (!c || !c->lxc_conf || !in || !out) ++ if (!c || !c->lxc_conf) + return false; + if (container_mem_lock(c)) { + ERROR("Error getting mem lock"); +@@ -5097,19 +5134,27 @@ static bool do_lxcapi_set_terminal_default_fifos(struct lxc_container *c, const + } + + conf = c->lxc_conf; +- if (conf->console.init_fifo[0]) +- free(conf->console.init_fifo[0]); +- conf->console.init_fifo[0] = strdup(in); +- +- if (conf->console.init_fifo[1]) +- free(conf->console.init_fifo[1]); +- conf->console.init_fifo[1] = strdup(out); ++ if (in) { ++ if (conf->console.init_fifo[0]) ++ free(conf->console.init_fifo[0]); ++ conf->console.init_fifo[0] = strdup(in); ++ } ++ if (out) { ++ if (conf->console.init_fifo[1]) ++ free(conf->console.init_fifo[1]); ++ conf->console.init_fifo[1] = strdup(out); ++ } ++ if (err) { ++ if (conf->console.init_fifo[2]) ++ free(conf->console.init_fifo[2]); ++ conf->console.init_fifo[2] = strdup(err); ++ } + + container_mem_unlock(c); + return true; + } + +-WRAP_API_2(bool, lxcapi_set_terminal_default_fifos, const char *, const char *) ++WRAP_API_3(bool, lxcapi_set_terminal_default_fifos, const char *, const char *, const char *) + + /* isulad add set info file path */ + static bool do_lxcapi_set_container_info_file(struct lxc_container *c, const char *info_file) +@@ -5168,18 +5213,18 @@ static bool do_lxcapi_clean_container_resource(struct lxc_container *c, pid_t pi + WRAP_API_1(bool, lxcapi_clean_container_resource, pid_t) + + /* isulad add clean resources */ +-static bool do_lxcapi_add_terminal_fifo(struct lxc_container *c, const char *in_fifo, const char *out_fifo) ++static bool do_lxcapi_add_terminal_fifo(struct lxc_container *c, const char *in_fifo, const char *out_fifo, const char *err_fifo) + { + bool ret = true; + +- if (!c || !c->lxc_conf || !in_fifo || !out_fifo) ++ if (!c || !c->lxc_conf) + return false; + if (container_mem_lock(c)) { + ERROR("Error getting mem lock"); + return false; + } + +- if (lxc_cmd_set_terminal_fifos(c->name, c->config_path, in_fifo, out_fifo)) { ++ if (lxc_cmd_set_terminal_fifos(c->name, c->config_path, in_fifo, out_fifo, err_fifo)) { + ERROR("Error set console fifos"); + ret = false; + } +@@ -5188,7 +5233,7 @@ static bool do_lxcapi_add_terminal_fifo(struct lxc_container *c, const char *in_ + return ret; + } + +-WRAP_API_2(bool, lxcapi_add_terminal_fifo, const char *, const char *) ++WRAP_API_3(bool, lxcapi_add_terminal_fifo, const char *, const char *, const char *) + + static struct lxc_container *do_lxc_container_new(const char *name, const char *configpath, bool load_config) + { +@@ -5274,6 +5319,8 @@ static struct lxc_container *do_lxc_container_new(const char *name, const char * + c->init_pid = lxcapi_init_pid; + c->load_config = lxcapi_load_config; + c->want_daemonize = lxcapi_want_daemonize; ++ c->want_disable_pty = lxcapi_want_disable_pty; ++ c->want_open_stdin = lxcapi_want_open_stdin; + c->want_close_all_fds = lxcapi_want_close_all_fds; + c->start = lxcapi_start; + c->startl = lxcapi_startl; +diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h +index c1d83ba..c3368e4 100644 +--- a/src/lxc/lxccontainer.h ++++ b/src/lxc/lxccontainer.h +@@ -137,6 +137,15 @@ struct lxc_container { + /*! Whether container wishes to be daemonized */ + bool daemonize; + ++ /*! Whether container wishes to create pty or pipes for console log */ ++ bool disable_pty; ++ ++ /*! Whether container wishes to keep stdin active */ ++ bool open_stdin; ++ ++ /*! Whether container wishes to detach from container stdio */ ++ bool detach; ++ + /*! Full path to configuration file */ + char *config_path; + +@@ -244,6 +253,28 @@ struct lxc_container { + bool (*stop)(struct lxc_container *c); + + /*! ++ * \brief Change whether the container wants to create pty or pipes ++ * from the console log. ++ * ++ * \param c Container. ++ * \param state Value for the disable pty bit (0 or 1). ++ * ++ * \return \c true on success, else \c false. ++ */ ++ bool (*want_disable_pty)(struct lxc_container *c, bool state); ++ ++ /*! ++ * \brief Change whether the container wants to keep stdin active ++ * for parent process of container ++ * ++ * \param c Container. ++ * \param state Value for the open_stdin bit (0 or 1). ++ * ++ * \return \c true on success, else \c false. ++ */ ++ bool (*want_open_stdin)(struct lxc_container *c, bool state); ++ ++ /*! + * \brief Change whether the container wants to run disconnected + * from the terminal. + * +@@ -875,7 +906,7 @@ struct lxc_container { + * + * \return \c true on success, else \c false. + */ +- bool (*set_terminal_init_fifos)(struct lxc_container *c, const char *in, const char *out); ++ bool (*set_terminal_init_fifos)(struct lxc_container *c, const char *in, const char *out, const char *err); + + /*! isulad add + * \brief An API call to add the path of terminal fifos +@@ -885,7 +916,7 @@ struct lxc_container { + * + * \return \c true on success, else \c false. + */ +- bool (*add_terminal_fifos)(struct lxc_container *c, const char *in, const char *out); ++ bool (*add_terminal_fifos)(struct lxc_container *c, const char *in, const char *out, const char *err); + + /*! isulad add + * \brief An API call to set the path of info file +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 816b4a2..cad0d76 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -635,6 +635,13 @@ int lxc_poll(const char *name, struct lxc_handler *handler) + } + + TRACE("Mainloop is ready"); ++ // iSulad: close stdin pipe if we do not want open_stdin with container stdin ++ if (!handler->conf->console.open_stdin) { ++ if (handler->conf->console.pipes[0][1] > 0) { ++ close(handler->conf->console.pipes[0][1]); ++ handler->conf->console.pipes[0][1] = -1; ++ } ++ } + + ret = lxc_mainloop(&descr, -1); + close(descr.epfd); +@@ -788,6 +795,8 @@ int lxc_init(const char *name, struct lxc_handler *handler) + int ret; + const char *loglevel; + struct lxc_conf *conf = handler->conf; ++ conf->console.disable_pty = handler->disable_pty; ++ conf->console.open_stdin = handler->open_stdin; + + lsm_init(); + TRACE("Initialized LSM"); +@@ -1244,7 +1253,7 @@ static int do_start(void *data) + * means that migration won't work, but at least we won't spew output + * where it isn't wanted. + */ +- if (handler->daemonize && !handler->conf->autodev) { ++ if (!handler->disable_pty && handler->daemonize && !handler->conf->autodev) { + ret = access(path, F_OK); + if (ret != 0) { + devnull_fd = open_devnull(); +@@ -1325,6 +1334,42 @@ static int do_start(void *data) + "privileges"); + } + ++ /* isulad: dup2 pipe[0][0] to container stdin, pipe[1][1] to container stdout, pipe[2][1] to container stderr */ ++ if (handler->disable_pty) { ++ if (handler->conf->console.pipes[0][1] >= 0) { ++ close(handler->conf->console.pipes[0][1]); ++ handler->conf->console.pipes[0][1] = -1; ++ } ++ ++ if (handler->conf->console.pipes[0][0] >= 0) { ++ ret = dup2(handler->conf->console.pipes[0][0], STDIN_FILENO); ++ if (ret < 0) ++ goto out_warn_father; ++ } ++ ++ if (handler->conf->console.pipes[1][0] >= 0) { ++ close(handler->conf->console.pipes[1][0]); ++ handler->conf->console.pipes[1][0] = -1; ++ } ++ ++ if (handler->conf->console.pipes[1][1] >= 0) { ++ ret = dup2(handler->conf->console.pipes[1][1], STDOUT_FILENO); ++ if (ret < 0) ++ goto out_warn_father; ++ } ++ if (handler->conf->console.pipes[2][0] >= 0) { ++ close(handler->conf->console.pipes[2][0]); ++ handler->conf->console.pipes[2][0] = -1; ++ } ++ ++ if (handler->conf->console.pipes[2][1] >= 0) { ++ ret = dup2(handler->conf->console.pipes[2][1], STDERR_FILENO); ++ if (ret < 0) ++ goto out_warn_father; ++ } ++ ++ } ++ + /* Some init's such as busybox will set sane tty settings on stdin, + * stdout, stderr which it thinks is the console. We already set them + * the way we wanted on the real terminal, and we want init to do its +@@ -1332,7 +1377,7 @@ static int do_start(void *data) + * make sure that that pty is stdin,stdout,stderr. + */ + setsid(); +- if (handler->conf->console.slave >= 0) { ++ if (!handler->disable_pty && handler->conf->console.slave >= 0) { + /* isulad:make the given terminal as controlling terminal to avoid warning + * sh: cannot set terminal process group (-1): Inappropriate ioctl for device + * sh: no job control in this shell */ +@@ -1367,7 +1412,7 @@ static int do_start(void *data) + + close(handler->sigfd); + +- if (handler->conf->console.slave < 0 && handler->daemonize) { ++ if (!handler->disable_pty && handler->conf->console.slave < 0 && handler->daemonize) { + if (devnull_fd < 0) { + devnull_fd = open_devnull(); + if (devnull_fd < 0) +@@ -1789,6 +1834,22 @@ static int lxc_spawn(struct lxc_handler *handler) + } + TRACE("Cloned child process %d", handler->pid); + ++ /* isulad: close pipe after clone */ ++ if (handler->conf->console.pipes[0][0] >= 0) { ++ close(handler->conf->console.pipes[0][0]); ++ handler->conf->console.pipes[0][0] = -1; ++ } ++ ++ if (handler->conf->console.pipes[1][1] >= 0) { ++ close(handler->conf->console.pipes[1][1]); ++ handler->conf->console.pipes[1][1] = -1; ++ } ++ ++ if (handler->conf->console.pipes[2][1] >= 0) { ++ close(handler->conf->console.pipes[2][1]); ++ handler->conf->console.pipes[2][1] = -1; ++ } ++ + /* isulad: save pid/ppid info into file*/ + if (handler->conf->container_info_file) { + if (lxc_save_container_info(handler->conf->container_info_file, handler->pid)) { +diff --git a/src/lxc/start.h b/src/lxc/start.h +index ab72e6e..0298991 100644 +--- a/src/lxc/start.h ++++ b/src/lxc/start.h +@@ -99,6 +99,11 @@ struct lxc_handler { + /* Indicates whether should we close std{in,out,err} on start. */ + bool daemonize; + ++ /* Indicates whether should we using pipes or pty dup to std{in,out,err} for console log. */ ++ bool disable_pty; ++ /* Indicates whether should we keep stdin active. */ ++ bool open_stdin; ++ + /* The child's pid. */ + pid_t pid; + +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index 602d43d..dfce92e 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -432,7 +432,7 @@ static bool get_now_time_buffer(char *timebuffer, size_t maxsize) + return get_time_buffer(&ts, timebuffer, maxsize); + } + +-static ssize_t lxc_logger_write(struct lxc_terminal *terminal, const char *buf, ++static ssize_t lxc_logger_write(struct lxc_terminal *terminal, const char *type, const char *buf, + int bytes_read) + { + logger_json_file *msg = NULL; +@@ -452,7 +452,7 @@ static ssize_t lxc_logger_write(struct lxc_terminal *terminal, const char *buf, + } + memcpy(msg->log, buf, bytes_read); + msg->log_len = bytes_read; +- msg->stream = strdup("stdout"); ++ msg->stream = type ? strdup(type) : strdup("stdout"); + + get_now_time_buffer(timebuffer, sizeof(timebuffer)); + msg->time = strdup(timebuffer); +@@ -472,7 +472,7 @@ cleanup: + return ret; + } + +-static int lxc_terminal_write_log_file(struct lxc_terminal *terminal, char *buf, ++static int lxc_terminal_write_log_file(struct lxc_terminal *terminal, const char *type, char *buf, + int bytes_read) + { + #define __BUF_CACHE_SIZE (16 * LXC_TERMINAL_BUFFER_SIZE) +@@ -504,7 +504,7 @@ static int lxc_terminal_write_log_file(struct lxc_terminal *terminal, char *buf, + // Break up the data that we've buffered up into lines, and log each in turn. + for (index = 0; index < size; index++) { + if (cache[index] == '\n') { +- ret = lxc_logger_write(terminal, cache + begin, index - begin + 1); ++ ret = lxc_logger_write(terminal, type, cache + begin, index - begin + 1); + if (ret < 0) { + WARN("Failed to log msg"); + } +@@ -516,7 +516,7 @@ static int lxc_terminal_write_log_file(struct lxc_terminal *terminal, char *buf, + * noting that it's a partial log line. */ + if (buf == NULL || (begin == 0 && size == __BUF_CACHE_SIZE)) { + if (begin < size) { +- ret = lxc_logger_write(terminal, cache + begin, index - begin + 1); ++ ret = lxc_logger_write(terminal, type, cache + begin, index - begin + 1); + if (ret < 0) { + WARN("Failed to log msg"); + } +@@ -541,14 +541,20 @@ static int lxc_terminal_write_log_file(struct lxc_terminal *terminal, char *buf, + } + + /* isulad: forward data to all fifos */ +-static void lxc_forward_data_to_fifo(struct lxc_list *list, char *buf, int r) ++static void lxc_forward_data_to_fifo(struct lxc_list *list, bool is_err, char *buf, int r) + { + struct lxc_list *it,*next; + struct lxc_fifos_fd *elem = NULL; + + lxc_list_for_each_safe(it, list, next) { + elem = it->elem; +- lxc_write_nointr(elem->out_fd, buf, r); ++ if (is_err) { ++ if (elem->err_fd >= 0) ++ lxc_write_nointr(elem->err_fd, buf, r); ++ } else { ++ if (elem->out_fd >= 0) ++ lxc_write_nointr(elem->out_fd, buf, r); ++ } + } + + return; +@@ -585,7 +591,7 @@ int lxc_terminal_io_cb(int fd, uint32_t events, void *data, + terminal->master = -EBADF; + /* write remained buffer to terminal log */ + if (terminal->log_fd >= 0) { +- w_log = lxc_terminal_write_log_file(terminal, NULL, 0); ++ w_log = lxc_terminal_write_log_file(terminal, "stdout", NULL, 0); + if (w_log < 0) + TRACE("Failed to write %d bytes to terminal log", r); + } +@@ -601,33 +607,57 @@ int lxc_terminal_io_cb(int fd, uint32_t events, void *data, + /* isulad: delete fifos when the client close */ + lxc_terminal_delete_fifo(fd, &terminal->fifos); + return LXC_MAINLOOP_CONTINUE; +- } else { ++ } else if (fd == terminal->pipes[1][0] || fd == terminal->pipes[2][0]) { ++ if (fd == terminal->pipes[1][0]) { ++ w_log = lxc_terminal_write_log_file(terminal, "stdout", NULL, 0); ++ terminal->pipes[1][0] = -EBADF; ++ } else if (fd == terminal->pipes[2][0]) { ++ w_log = lxc_terminal_write_log_file(terminal, "stderr", NULL, 0); ++ terminal->pipes[2][0] = -EBADF; ++ } ++ if (w_log < 0) ++ TRACE("Failed to write %d bytes to terminal log", r); ++ close(fd); ++ return LXC_MAINLOOP_CONTINUE; ++ } else if (fd == terminal->pipes[0][1]) { ++ TRACE("closed stdin pipe of container stdin"); ++ terminal->pipes[0][1] = -EBADF; ++ close(fd); ++ return LXC_MAINLOOP_CONTINUE; ++ } else { + ERROR("Handler received unexpected file descriptor"); + } + close(fd); +- + return LXC_MAINLOOP_CLOSE; + } + +- if (fd == terminal->peer || lxc_terminal_is_fifo(fd, &terminal->fifos)) +- w = lxc_write_nointr(terminal->master, buf, r); ++ if (fd == terminal->peer || lxc_terminal_is_fifo(fd, &terminal->fifos)) { ++ if (terminal->master > 0) ++ w = lxc_write_nointr(terminal->master, buf, r); ++ if (terminal->pipes[0][1] > 0) ++ w = lxc_write_nointr(terminal->pipes[0][1], buf, r); ++ } + + w_rbuf = w_log = 0; +- if (fd == terminal->master) { ++ if (fd == terminal->master || fd == terminal->pipes[1][0] || fd == terminal->pipes[2][0]) { + /* write to peer first */ + if (terminal->peer >= 0) + w = lxc_write_nointr(terminal->peer, buf, r); + + /* isulad: forward data to fifos */ +- lxc_forward_data_to_fifo(&terminal->fifos, buf, r); ++ lxc_forward_data_to_fifo(&terminal->fifos, fd == terminal->pipes[2][0], buf, r); + + /* write to terminal ringbuffer */ + if (terminal->buffer_size > 0) + w_rbuf = lxc_ringbuf_write(&terminal->ringbuf, buf, r); + + /* write to terminal log */ +- if (terminal->log_fd >= 0) +- w_log = lxc_terminal_write_log_file(terminal, buf, r); ++ if (terminal->log_fd >= 0) { ++ if (fd == terminal->master || fd == terminal->pipes[1][0]) ++ w_log = lxc_terminal_write_log_file(terminal, "stdout", buf, r); ++ else if (fd == terminal->pipes[2][0]) ++ w_log = lxc_terminal_write_log_file(terminal, "stderr", buf, r); ++ } + } + + if (w != r) +@@ -670,6 +700,41 @@ static int lxc_terminal_mainloop_add_peer(struct lxc_terminal *terminal) + return 0; + } + ++/* isulad add pipes to mainloop */ ++static int lxc_terminal_mainloop_add_pipes(struct lxc_terminal *terminal) ++{ ++ int ret = 0; ++ ++ // parent read data from fifo, and send to stdin of container ++ if (terminal->pipes[0][1] > 0) { ++ ret = lxc_mainloop_add_handler(terminal->descr, terminal->pipes[0][1], ++ lxc_terminal_io_cb, terminal); ++ if (ret) { ++ ERROR("pipe fd %d not added to mainloop", terminal->pipes[0][1]); ++ return -1; ++ } ++ } ++ // parent read data from stdout of container, and send to fifo ++ if (terminal->pipes[1][0] > 0) { ++ ret = lxc_mainloop_add_handler(terminal->descr, terminal->pipes[1][0], ++ lxc_terminal_io_cb, terminal); ++ if (ret) { ++ ERROR("pipe fd %d not added to mainloop", terminal->pipes[1][0]); ++ return -1; ++ } ++ } ++ // parent read data from stderr of container, and send to fifo ++ if (terminal->pipes[2][0] > 0) { ++ ret = lxc_mainloop_add_handler(terminal->descr, terminal->pipes[2][0], ++ lxc_terminal_io_cb, terminal); ++ if (ret) { ++ ERROR("pipe fd %d not added to mainloop", terminal->pipes[2][0]); ++ return -1; ++ } ++ } ++ return ret; ++} ++ + /* isulad add fifo to mainloop */ + static int lxc_terminal_mainloop_add_fifo(struct lxc_terminal *terminal) + { +@@ -696,19 +761,6 @@ int lxc_terminal_mainloop_add(struct lxc_epoll_descr *descr, + { + int ret; + +- if (terminal->master < 0) { +- INFO("Terminal is not initialized"); +- return 0; +- } +- +- ret = lxc_mainloop_add_handler(descr, terminal->master, +- lxc_terminal_io_cb, terminal); +- if (ret < 0) { +- ERROR("Failed to add handler for terminal master fd %d to " +- "mainloop", terminal->master); +- return -1; +- } +- + /* We cache the descr so that we can add an fd to it when someone + * does attach to it in lxc_terminal_allocate(). + */ +@@ -720,6 +772,13 @@ int lxc_terminal_mainloop_add(struct lxc_epoll_descr *descr, + return -1; + } + ++ /* isulad add pipes to mainloop */ ++ ret = lxc_terminal_mainloop_add_pipes(terminal); ++ if (ret < 0) { ++ ERROR("Failed to add handler for terminal fifos to mainloop"); ++ return -1; ++ } ++ + /* isulad add fifo to mainloop */ + ret = lxc_terminal_mainloop_add_fifo(terminal); + if (ret < 0) { +@@ -727,6 +786,19 @@ int lxc_terminal_mainloop_add(struct lxc_epoll_descr *descr, + return -1; + } + ++ if (terminal->master < 0) { ++ INFO("Terminal is not initialized"); ++ return 0; ++ } ++ ++ ret = lxc_mainloop_add_handler(descr, terminal->master, ++ lxc_terminal_io_cb, terminal); ++ if (ret < 0) { ++ ERROR("Failed to add handler for terminal master fd %d to " ++ "mainloop", terminal->master); ++ return -1; ++ } ++ + return 0; + } + +@@ -1082,6 +1154,26 @@ void lxc_terminal_delete(struct lxc_terminal *terminal) + close(terminal->log_fd); + terminal->log_fd = -1; + ++ /* isulad: close all pipes */ ++ if (terminal->pipes[0][0] >= 0) ++ close(terminal->pipes[0][0]); ++ terminal->pipes[0][0] = -1; ++ if (terminal->pipes[0][1] >= 0) ++ close(terminal->pipes[0][1]); ++ terminal->pipes[0][1] = -1; ++ if (terminal->pipes[1][0] >= 0) ++ close(terminal->pipes[1][0]); ++ terminal->pipes[1][0] = -1; ++ if (terminal->pipes[1][1] >= 0) ++ close(terminal->pipes[1][1]); ++ terminal->pipes[1][1] = -1; ++ if (terminal->pipes[2][0] >= 0) ++ close(terminal->pipes[2][0]); ++ terminal->pipes[2][0] = -1; ++ if (terminal->pipes[2][1] >= 0) ++ close(terminal->pipes[2][1]); ++ terminal->pipes[2][1] = -1; ++ + /* isulad: delete all fifos */ + lxc_terminal_delete_fifo(-1, &terminal->fifos); + } +@@ -1168,59 +1260,79 @@ static int terminal_fifo_open(const char *fifo_path, int flags) + } + + /* isulad: set terminal fifos */ +-static int lxc_terminal_set_fifo(struct lxc_terminal *console, const char *in, const char *out) ++static int lxc_terminal_set_fifo(struct lxc_terminal *console, const char *in, const char *out, const char *err, int *input_fd) + { +- int fifofd_in = -1, fifofd_out = -1; ++ int fifofd_in = -1, fifofd_out = -1, fifofd_err = -1; + struct lxc_fifos_fd *fifo_elem = NULL; + +- if (!in || !out) ++ if ((in && !fifo_exists(in)) || (out && !fifo_exists(out)) || (err && !fifo_exists(err))) { ++ ERROR("File %s or %s or %s does not refer to a FIFO", in, out, err); + return -1; ++ } + +- if (!fifo_exists(in) || !fifo_exists(out)) { +- ERROR("File %s or %s does not refer to a FIFO", in, out); +- return -1; ++ if (in) { ++ fifofd_in = terminal_fifo_open(in, O_RDONLY | O_NONBLOCK | O_CLOEXEC); ++ if (fifofd_in < 0) { ++ SYSERROR("Failed to open FIFO: %s", in); ++ return -1; ++ } + } + +- fifofd_in = terminal_fifo_open(in, O_RDONLY | O_NONBLOCK | O_CLOEXEC); +- if (fifofd_in < 0) { +- ERROR("Failed to open FIFO: %s", in); +- return -1; ++ if (out) { ++ fifofd_out = terminal_fifo_open(out, O_WRONLY | O_NONBLOCK | O_CLOEXEC); ++ if (fifofd_out < 0) { ++ SYSERROR("Failed to open FIFO: %s", out); ++ if (fifofd_in >= 0) ++ close(fifofd_in); ++ return -1; ++ } + } + +- fifofd_out = terminal_fifo_open(out, O_WRONLY | O_NONBLOCK | O_CLOEXEC); +- if (fifofd_out < 0) { +- ERROR("Failed to open FIFO: %s", out); +- close(fifofd_in); +- return -1; ++ if (err) { ++ fifofd_err = terminal_fifo_open(err, O_WRONLY | O_NONBLOCK | O_CLOEXEC); ++ if (fifofd_err < 0) { ++ SYSERROR("Failed to open FIFO: %s", err); ++ if (fifofd_in >= 0) ++ close(fifofd_in); ++ if (fifofd_out >= 0) ++ close(fifofd_out); ++ return -1; ++ } + } + + fifo_elem = malloc(sizeof(*fifo_elem)); + if (!fifo_elem) { +- close(fifofd_in); +- close(fifofd_out); ++ if (fifofd_in >= 0) ++ close(fifofd_in); ++ if (fifofd_out >= 0) ++ close(fifofd_out); ++ if (fifofd_err >= 0) ++ close(fifofd_err); + return -1; + } + memset(fifo_elem, 0, sizeof(*fifo_elem)); + +- fifo_elem->in_fifo = strdup(in); +- fifo_elem->out_fifo = strdup(out); ++ fifo_elem->in_fifo = strdup(in ? in : ""); ++ fifo_elem->out_fifo = strdup(out ? out : ""); ++ fifo_elem->err_fifo = strdup(err ? err : ""); + fifo_elem->in_fd = fifofd_in; + fifo_elem->out_fd = fifofd_out; ++ fifo_elem->err_fd = fifofd_err; + lxc_list_add_elem(&fifo_elem->node, fifo_elem); + lxc_list_add_tail(&console->fifos, &fifo_elem->node); + +- return fifofd_in; ++ if (input_fd) ++ *input_fd = fifofd_in; ++ ++ return 0; + } + + /* isulad: add default fifos */ + static int lxc_terminal_fifo_default(struct lxc_terminal *terminal) + { +- if (!terminal->init_fifo[0] || !terminal->init_fifo[1]) { +- DEBUG("Invalid default terminal fifos"); +- return 0; +- } +- +- return lxc_terminal_set_fifo(terminal, terminal->init_fifo[0], terminal->init_fifo[1]); ++ if (terminal->init_fifo[0] || terminal->init_fifo[1] || terminal->init_fifo[2]) ++ return lxc_terminal_set_fifo(terminal, terminal->init_fifo[0], terminal->init_fifo[1], terminal->init_fifo[2], NULL); ++ return 0; + } + + /* +@@ -1245,48 +1357,67 @@ int lxc_terminal_create(struct lxc_terminal *terminal) + { + int ret; + +- ret = openpty(&terminal->master, &terminal->slave, NULL, NULL, NULL); +- if (ret < 0) { +- SYSERROR("Failed to open terminal"); +- return -1; +- } ++ if (!terminal->disable_pty) { ++ ret = openpty(&terminal->master, &terminal->slave, NULL, NULL, NULL); ++ if (ret < 0) { ++ SYSERROR("Failed to open terminal"); ++ return -1; ++ } + +- ret = ttyname_r(terminal->slave, terminal->name, sizeof(terminal->name)); +- if (ret < 0) { +- SYSERROR("Failed to retrieve name of terminal slave"); +- goto err; +- } ++ ret = ttyname_r(terminal->slave, terminal->name, sizeof(terminal->name)); ++ if (ret < 0) { ++ SYSERROR("Failed to retrieve name of terminal slave"); ++ goto err; ++ } + +- /* isulad: clear ONLCR flag */ +- ret = use_unix_newline(terminal->master); +- if (ret < 0) { +- SYSERROR("Failed to clear ONLCR flag on terminal master"); +- goto err; +- } ++ /* isulad: clear ONLCR flag */ ++ ret = use_unix_newline(terminal->master); ++ if (ret < 0) { ++ SYSERROR("Failed to clear ONLCR flag on terminal master"); ++ goto err; ++ } + +- ret = fd_cloexec(terminal->master, true); +- if (ret < 0) { +- SYSERROR("Failed to set FD_CLOEXEC flag on terminal master"); +- goto err; +- } ++ ret = fd_cloexec(terminal->master, true); ++ if (ret < 0) { ++ SYSERROR("Failed to set FD_CLOEXEC flag on terminal master"); ++ goto err; ++ } + +- /* isulad: make master NONBLOCK */ +- ret = fd_nonblock(terminal->master); +- if (ret < 0) { +- SYSERROR("Failed to set O_NONBLOCK flag on terminal master"); +- goto err; +- } ++ /* isulad: make master NONBLOCK */ ++ ret = fd_nonblock(terminal->master); ++ if (ret < 0) { ++ SYSERROR("Failed to set O_NONBLOCK flag on terminal master"); ++ goto err; ++ } + +- ret = fd_cloexec(terminal->slave, true); +- if (ret < 0) { +- SYSERROR("Failed to set FD_CLOEXEC flag on terminal slave"); +- goto err; +- } ++ ret = fd_cloexec(terminal->slave, true); ++ if (ret < 0) { ++ SYSERROR("Failed to set FD_CLOEXEC flag on terminal slave"); ++ goto err; ++ } + +- ret = lxc_terminal_peer_default(terminal); +- if (ret < 0) { +- ERROR("Failed to allocate proxy terminal"); +- goto err; ++ ret = lxc_terminal_peer_default(terminal); ++ if (ret < 0) { ++ ERROR("Failed to allocate proxy terminal"); ++ goto err; ++ } ++ } else { ++ /* isulad: create 3 pipes */ ++ /* for stdin */ ++ if (pipe2(terminal->pipes[0], O_CLOEXEC)) { ++ ERROR("Failed to create stdin pipe"); ++ goto err; ++ } ++ /* for stdout */ ++ if (pipe2(terminal->pipes[1], O_NONBLOCK | O_CLOEXEC)) { ++ ERROR("Failed to create stdout pipe"); ++ goto err; ++ } ++ /* for stderr */ ++ if (pipe2(terminal->pipes[2], O_NONBLOCK | O_CLOEXEC)) { ++ ERROR("Failed to create stderr pipe"); ++ goto err; ++ } + } + + /* isulad: open fifos */ +@@ -1581,6 +1712,13 @@ void lxc_terminal_init(struct lxc_terminal *terminal) + /* isulad init console fifos */ + terminal->init_fifo[0] = NULL; + terminal->init_fifo[1] = NULL; ++ terminal->init_fifo[2] = NULL; ++ terminal->pipes[0][0] = -1; ++ terminal->pipes[0][1] = -1; ++ terminal->pipes[1][0] = -1; ++ terminal->pipes[1][1] = -1; ++ terminal->pipes[2][0] = -1; ++ terminal->pipes[2][1] = -1; + lxc_list_init(&terminal->fifos); + } + +@@ -1599,8 +1737,14 @@ int lxc_terminal_delete_fifo(int fd, struct lxc_list *list) + free(elem->in_fifo); + if (elem->out_fifo) + free(elem->out_fifo); +- close(elem->in_fd); +- close(elem->out_fd); ++ if (elem->err_fifo) ++ free(elem->err_fifo); ++ if (elem->in_fd >= 0) ++ close(elem->in_fd); ++ if (elem->out_fd >= 0) ++ close(elem->out_fd); ++ if (elem->err_fd >= 0) ++ close(elem->err_fd); + free(elem); + } + } +@@ -1617,6 +1761,7 @@ void lxc_terminal_conf_free(struct lxc_terminal *terminal) + /*isulad: free console fifos */ + free(terminal->init_fifo[0]); + free(terminal->init_fifo[1]); ++ free(terminal->init_fifo[2]); + lxc_terminal_delete_fifo(-1, &terminal->fifos); + } + +@@ -1647,7 +1792,8 @@ int lxc_terminal_add_fifos(struct lxc_conf *conf, const char *fifonames) + int ret = 0; + struct lxc_terminal *terminal = &conf->console; + int fifofd_in = -1; +- char *tmp = NULL, *saveptr = NULL, *in = NULL, *out = NULL; ++ char *tmp = NULL, *saveptr = NULL, *in = NULL, *out = NULL, *err = NULL; ++ const char *none_fifo_name = "none"; + + tmp = strdup(fifonames); + if (!tmp) { +@@ -1660,14 +1806,27 @@ int lxc_terminal_add_fifos(struct lxc_conf *conf, const char *fifonames) + ret = -1; + goto free_out; + } ++ if (strcmp(in, none_fifo_name) == 0) ++ in = NULL; ++ + out = strtok_r(NULL, "&&&&", &saveptr); + if (!out) { + ret = -1; + goto free_out; + } ++ if (strcmp(out, none_fifo_name) == 0) ++ out = NULL; + +- fifofd_in = lxc_terminal_set_fifo(terminal, in, out); +- if (fifofd_in < 0) { ++ err = strtok_r(NULL, "&&&&", &saveptr); ++ if (!err) { ++ ret = -1; ++ goto free_out; ++ } ++ if (strcmp(err, none_fifo_name) == 0) ++ err = NULL; ++ ++ ret = lxc_terminal_set_fifo(terminal, in, out, err, &fifofd_in); ++ if (ret < 0) { + ERROR("Faild to set fifos to console config"); + ret = -1; + goto free_out; +diff --git a/src/lxc/terminal.h b/src/lxc/terminal.h +index 0c9653c..9bb341f 100644 +--- a/src/lxc/terminal.h ++++ b/src/lxc/terminal.h +@@ -115,16 +115,21 @@ struct lxc_terminal { + /* the in-memory ringbuffer */ + struct lxc_ringbuf ringbuf; + }; +- char *init_fifo[2]; /* isulad: default fifos for the start */ ++ char *init_fifo[3]; /* isulad: default fifos for the start */ + struct lxc_list fifos; /* isulad: fifos used to forward teminal */ ++ bool disable_pty; ++ bool open_stdin; ++ int pipes[3][2]; /* isulad: pipes for dup to container fds of stdin,stdout,stderr on daemonize mode*/ + }; + + /* isulad: fifo struct */ + struct lxc_fifos_fd { + char *in_fifo; + char *out_fifo; ++ char *err_fifo; + int in_fd; + int out_fd; ++ int err_fd; + struct lxc_list node; + }; + +diff --git a/src/lxc/tools/arguments.h b/src/lxc/tools/arguments.h +index afab9f5..d03f8a4 100644 +--- a/src/lxc/tools/arguments.h ++++ b/src/lxc/tools/arguments.h +@@ -51,6 +51,8 @@ struct lxc_arguments { + char *log_priority; + int quiet; + int daemonize; ++ int disable_pty; ++ int open_stdin; + const char *rcfile; + const char *console; + const char *console_log; +@@ -62,7 +64,7 @@ struct lxc_arguments { + + /* for lxc-start */ + const char *share_ns[32]; /* size must be greater than LXC_NS_MAX */ +- char *terminal_fifos[2]; /* isulad add, fifos used to redirct stdin/out/err */ ++ char *terminal_fifos[3]; /* isulad add, fifos used to redirct stdin/out/err */ + const char *container_info; /* isulad: file used to store pid and ppid info of container */ + const char *exit_monitor_fifo; /* isulad: fifo used to monitor state of monitor process */ + unsigned int start_timeout; /* isulad: Seconds for waiting on a container to start before it is killed*/ +@@ -179,9 +181,13 @@ struct lxc_arguments { + /* isulad add begin */ + #define OPT_INPUT_FIFO OPT_USAGE - 7 + #define OPT_OUTPUT_FIFO OPT_USAGE - 8 +-#define OPT_CONTAINER_INFO OPT_USAGE - 9 +-#define OPT_EXIT_FIFO OPT_USAGE - 10 +-#define OPT_START_TIMEOUT OPT_USAGE - 11 ++#define OPT_STDERR_FIFO OPT_USAGE - 9 ++#define OPT_CONTAINER_INFO OPT_USAGE - 10 ++#define OPT_EXIT_FIFO OPT_USAGE - 11 ++#define OPT_START_TIMEOUT OPT_USAGE - 12 ++#define OPT_DISABLE_PTY OPT_USAGE - 13 ++#define OPT_OPEN_STDIN OPT_USAGE - 14 ++ + /* isulad add end*/ + + extern int lxc_arguments_parse(struct lxc_arguments *args, int argc, +diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c +index acdf8a0..674050d 100644 +--- a/src/lxc/tools/lxc_attach.c ++++ b/src/lxc/tools/lxc_attach.c +@@ -77,6 +77,7 @@ static const struct option my_longopts[] = { + {"rcfile", required_argument, 0, 'f'}, + {"in-fifo", required_argument, 0, OPT_INPUT_FIFO}, /* isulad add terminal fifos*/ + {"out-fifo", required_argument, 0, OPT_OUTPUT_FIFO}, ++ {"err-fifo", required_argument, 0, OPT_STDERR_FIFO}, + LXC_COMMON_OPTIONS + }; + +@@ -201,6 +202,9 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) + case OPT_OUTPUT_FIFO: + args->terminal_fifos[1] = arg; + break; ++ case OPT_STDERR_FIFO: ++ args->terminal_fifos[2] = arg; ++ break; + } + + return 0; +@@ -460,9 +464,10 @@ int main(int argc, char *argv[]) + if (elevated_privileges) + attach_options.attach_flags &= ~(elevated_privileges); + +- if (my_args.terminal_fifos[0] && my_args.terminal_fifos[1]) { ++ if (my_args.terminal_fifos[0] || my_args.terminal_fifos[1] || my_args.terminal_fifos[2]) { + attach_options.init_fifo[0] = my_args.terminal_fifos[0]; + attach_options.init_fifo[1] = my_args.terminal_fifos[1]; ++ attach_options.init_fifo[2] = my_args.terminal_fifos[2]; + attach_options.attach_flags |= LXC_ATTACH_TERMINAL; + } else if (stdfd_is_pty()) { + attach_options.attach_flags |= LXC_ATTACH_TERMINAL; +diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c +index ec48701..183fafc 100644 +--- a/src/lxc/tools/lxc_start.c ++++ b/src/lxc/tools/lxc_start.c +@@ -73,9 +73,12 @@ static const struct option my_longopts[] = { + /* isulad add begin */ + {"in-fifo", required_argument, 0, OPT_INPUT_FIFO}, + {"out-fifo", required_argument, 0, OPT_OUTPUT_FIFO}, ++ {"err-fifo", required_argument, 0, OPT_STDERR_FIFO}, + {"container-pidfile", required_argument, 0, OPT_CONTAINER_INFO}, + {"exit-fifo", required_argument, 0, OPT_EXIT_FIFO}, + {"start-timeout", required_argument, 0, OPT_START_TIMEOUT}, ++ {"disable-pty", no_argument, 0, OPT_DISABLE_PTY}, ++ {"open-stdin", no_argument, 0, OPT_OPEN_STDIN}, + /* isulad add end */ + LXC_COMMON_OPTIONS + }; +@@ -166,6 +169,9 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) + case OPT_OUTPUT_FIFO: + args->terminal_fifos[1] = arg; + break; ++ case OPT_STDERR_FIFO: ++ args->terminal_fifos[2] = arg; ++ break; + case OPT_CONTAINER_INFO: + args->container_info = arg; + break; +@@ -179,6 +185,12 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) + } + args->start_timeout = (unsigned int)atoi(arg); + break; ++ case OPT_DISABLE_PTY: ++ args->disable_pty = 1; ++ break; ++ case OPT_OPEN_STDIN: ++ args->open_stdin = 1; ++ break; + } + return 0; + } +@@ -381,11 +393,17 @@ int main(int argc, char *argv[]) + if (!my_args.daemonize) + c->want_daemonize(c, false); + ++ if (my_args.disable_pty) ++ c->want_disable_pty(c, true); ++ ++ if (my_args.open_stdin) ++ c->want_open_stdin(c, true); ++ + if (my_args.close_all_fds) + c->want_close_all_fds(c, true); + +- if (my_args.terminal_fifos[0] && my_args.terminal_fifos[1]) +- c->set_terminal_init_fifos(c, my_args.terminal_fifos[0], my_args.terminal_fifos[1]); ++ if (my_args.terminal_fifos[0] || my_args.terminal_fifos[1] || my_args.terminal_fifos[2]) ++ c->set_terminal_init_fifos(c, my_args.terminal_fifos[0], my_args.terminal_fifos[1], my_args.terminal_fifos[2]); + + if (args == default_args) + err = c->start(c, 0, NULL) ? EXIT_SUCCESS : EXIT_FAILURE; +-- +1.8.3.1 + diff --git a/0069-lxc-killall-processes-if-container-shared-pid-namesp.patch b/0069-lxc-killall-processes-if-container-shared-pid-namesp.patch new file mode 100644 index 0000000..4f99776 --- /dev/null +++ b/0069-lxc-killall-processes-if-container-shared-pid-namesp.patch @@ -0,0 +1,207 @@ +From f6877ff5a4ca2bb0e7556b0b17690290888021f5 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Thu, 21 Mar 2019 15:48:02 +0800 +Subject: [PATCH 069/122] lxc: killall processes if container shared pid + namespace + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/cgroups/cgfsng.c | 2 +- + src/lxc/start.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 161 insertions(+), 1 deletion(-) + +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index e513218..ab7ca35 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -1056,7 +1056,7 @@ static int cgroup_rmdir(struct hierarchy **hierarchies, + + ret = recursive_destroy(h->container_full_path); + if (ret < 0) { +- ERROR("Failed to destroy \"%s\"", h->container_full_path); ++ SYSERROR("Failed to destroy \"%s\"", h->container_full_path); + return -1; + } + +diff --git a/src/lxc/start.c b/src/lxc/start.c +index cad0d76..1c9eb0a 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -2494,6 +2494,162 @@ static void clean_resource_set_env(struct lxc_handler *handler) + /* End of environment variable setup for hooks. */ + } + ++void trim_line(char *s) ++{ ++ size_t len; ++ ++ len = strlen(s); ++ while ((len > 1) && (s[len - 1] == '\n')) ++ s[--len] = '\0'; ++} ++ ++static int _read_procs_file(const char *path, pid_t **pids, size_t *len) ++{ ++ FILE *f; ++ char *line = NULL; ++ size_t sz = 0; ++ ++ f = fopen_cloexec(path, "r"); ++ if (!f) ++ return -1; ++ ++ while (getline(&line, &sz, f) != -1) { ++ pid_t pid; ++ trim_line(line); ++ pid = (pid_t)atoll(line); ++ *pids = realloc(*pids, sizeof(pid_t) * (*len + 1)); ++ (*pids)[*len] = pid; ++ (*len)++; ++ } ++ ++ free(line); ++ fclose(f); ++ return 0; ++} ++ ++static int _recursive_read_cgroup_procs(const char *dirpath, pid_t **pids, size_t *len) ++{ ++ struct dirent *direntp; ++ DIR *dir; ++ int ret, failed = 0; ++ char pathname[PATH_MAX]; ++ ++ dir = opendir(dirpath); ++ if (!dir && errno != ENOENT) { ++ WARN("Failed to open \"%s\"", dirpath); ++ return 0; ++ } ++ ++ while ((direntp = readdir(dir))) { ++ struct stat mystat; ++ int rc; ++ ++ if (!strcmp(direntp->d_name, ".") || ++ !strcmp(direntp->d_name, "..")) ++ continue; ++ ++ rc = snprintf(pathname, PATH_MAX, "%s/%s", dirpath, direntp->d_name); ++ if (rc < 0 || rc >= PATH_MAX) { ++ failed = 1; ++ continue; ++ } ++ ++ if (strcmp(direntp->d_name, "cgroup.procs") == 0) { ++ if (_read_procs_file(pathname, pids, len)) { ++ failed = 1; ++ ++ } ++ continue; ++ } ++ ++ ret = lstat(pathname, &mystat); ++ if (ret) { ++ failed = 1; ++ continue; ++ } ++ ++ if (S_ISDIR(mystat.st_mode)) { ++ if (_recursive_read_cgroup_procs(pathname, pids, len) < 0) ++ failed = 1; ++ } ++ } ++ ++ ret = closedir(dir); ++ if (ret) { ++ WARN("Failed to close directory \"%s\"", dirpath); ++ failed = 1; ++ } ++ ++ return failed ? -1 : 0; ++} ++ ++int get_all_pids(struct cgroup_ops *cg_ops, pid_t **pids, size_t *len) ++{ ++ char *devices_path = NULL; ++ int ret; ++ ++ devices_path = must_make_path("/sys/fs/cgroup", "devices", cg_ops->container_cgroup, NULL); ++ if (!file_exists(devices_path)) { ++ free(devices_path); ++ return 0; ++ } ++ ++ ret = _recursive_read_cgroup_procs(devices_path, pids, len); ++ free(devices_path); ++ return ret; ++} ++ ++static int set_cgroup_freezer(struct cgroup_ops *cg_ops, const char *value) ++{ ++ char *fullpath; ++ int ret; ++ ++ fullpath = must_make_path("/sys/fs/cgroup", "freezer", cg_ops->container_cgroup, "freezer.state", NULL); ++ ret = lxc_write_to_file(fullpath, value, strlen(value), false, 0666); ++ free(fullpath); ++ return ret; ++} ++ ++/* isulad: kill all process in container cgroup path */ ++static void signal_all_processes(struct lxc_handler *handler) ++{ ++ int ret; ++ struct cgroup_ops *cg_ops = handler->cgroup_ops; ++ pid_t *pids = NULL; ++ size_t len = 0, i; ++ ++ ret = set_cgroup_freezer(cg_ops, "FROZEN"); ++ if (ret < 0 && errno != ENOENT) { ++ WARN("cgroup_set frozen failed"); ++ } ++ ++ ret = get_all_pids(cg_ops, &pids, &len); ++ if (ret < 0) { ++ WARN("failed to get all pids"); ++ } ++ ++ for (i = 0; i < len; i++) { ++ ret = kill(pids[i], SIGKILL); ++ if (ret < 0 && errno != ESRCH) { ++ WARN("Can not kill process (pid=%d) with SIGKILL for container %s", pids[i], handler->name); ++ } ++ } ++ ++ ret = set_cgroup_freezer(cg_ops, "THAWED"); ++ if (ret < 0 && errno != ENOENT) { ++ WARN("cgroup_set thawed failed"); ++ } ++ ++ for (i = 0; i < len; i++) { ++ ret = lxc_wait_for_pid_status(pids[i]); ++ if (ret < 0 && errno != ECHILD) { ++ WARN("Failed to wait pid %d for container %s: %s", pids[i], handler->name, strerror(errno)); ++ } ++ } ++ ++ free(pids); ++} ++ + /*isulad: do_lxcapi_clean_resource */ + int do_lxcapi_clean_resource(char *name, char *lxcpath, struct lxc_conf *conf, pid_t pid) + { +@@ -2510,6 +2666,10 @@ int do_lxcapi_clean_resource(char *name, char *lxcpath, struct lxc_conf *conf, p + } + + clean_resource_set_env(handler); ++ // if we shared pid namespace with others, should kill all processes within container cgroup ++ if (handler->conf->ns_share[LXC_NS_PID] != NULL) { ++ signal_all_processes(handler); ++ } + + char* oci_hook_args[1]; + oci_hook_args[0] = alloca(strlen(handler->lxcpath) + 1); +-- +1.8.3.1 + diff --git a/0070-lxc-signal-all-process-for-shared-container-when-con.patch b/0070-lxc-signal-all-process-for-shared-container-when-con.patch new file mode 100644 index 0000000..2944b4a --- /dev/null +++ b/0070-lxc-signal-all-process-for-shared-container-when-con.patch @@ -0,0 +1,400 @@ +From 44f3d99c562ab88670f1fe91a1d16474da8adb98 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Thu, 21 Mar 2019 17:21:44 +0800 +Subject: [PATCH 070/122] lxc: signal all process for shared container when + container init exited + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/cgroups/cgfsng.c | 2 +- + src/lxc/start.c | 332 +++++++++++++++++++++++++---------------------- + 2 files changed, 175 insertions(+), 159 deletions(-) + +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index ab7ca35..5ceb06b 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -1056,7 +1056,7 @@ static int cgroup_rmdir(struct hierarchy **hierarchies, + + ret = recursive_destroy(h->container_full_path); + if (ret < 0) { +- SYSERROR("Failed to destroy \"%s\"", h->container_full_path); ++ SYSWARN("Failed to destroy \"%s\"", h->container_full_path); + return -1; + } + +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 1c9eb0a..b14e46f 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -941,6 +941,162 @@ out_close_maincmd_fd: + return -1; + } + ++void trim_line(char *s) ++{ ++ size_t len; ++ ++ len = strlen(s); ++ while ((len > 1) && (s[len - 1] == '\n')) ++ s[--len] = '\0'; ++} ++ ++static int _read_procs_file(const char *path, pid_t **pids, size_t *len) ++{ ++ FILE *f; ++ char *line = NULL; ++ size_t sz = 0; ++ ++ f = fopen_cloexec(path, "r"); ++ if (!f) ++ return -1; ++ ++ while (getline(&line, &sz, f) != -1) { ++ pid_t pid; ++ trim_line(line); ++ pid = (pid_t)atoll(line); ++ *pids = realloc(*pids, sizeof(pid_t) * (*len + 1)); ++ (*pids)[*len] = pid; ++ (*len)++; ++ } ++ ++ free(line); ++ fclose(f); ++ return 0; ++} ++ ++static int _recursive_read_cgroup_procs(const char *dirpath, pid_t **pids, size_t *len) ++{ ++ struct dirent *direntp; ++ DIR *dir; ++ int ret, failed = 0; ++ char pathname[PATH_MAX]; ++ ++ dir = opendir(dirpath); ++ if (!dir && errno != ENOENT) { ++ WARN("Failed to open \"%s\"", dirpath); ++ return 0; ++ } ++ ++ while ((direntp = readdir(dir))) { ++ struct stat mystat; ++ int rc; ++ ++ if (!strcmp(direntp->d_name, ".") || ++ !strcmp(direntp->d_name, "..")) ++ continue; ++ ++ rc = snprintf(pathname, PATH_MAX, "%s/%s", dirpath, direntp->d_name); ++ if (rc < 0 || rc >= PATH_MAX) { ++ failed = 1; ++ continue; ++ } ++ ++ if (strcmp(direntp->d_name, "cgroup.procs") == 0) { ++ if (_read_procs_file(pathname, pids, len)) { ++ failed = 1; ++ ++ } ++ continue; ++ } ++ ++ ret = lstat(pathname, &mystat); ++ if (ret) { ++ failed = 1; ++ continue; ++ } ++ ++ if (S_ISDIR(mystat.st_mode)) { ++ if (_recursive_read_cgroup_procs(pathname, pids, len) < 0) ++ failed = 1; ++ } ++ } ++ ++ ret = closedir(dir); ++ if (ret) { ++ WARN("Failed to close directory \"%s\"", dirpath); ++ failed = 1; ++ } ++ ++ return failed ? -1 : 0; ++} ++ ++int get_all_pids(struct cgroup_ops *cg_ops, pid_t **pids, size_t *len) ++{ ++ char *devices_path = NULL; ++ int ret; ++ ++ devices_path = must_make_path("/sys/fs/cgroup", "devices", cg_ops->container_cgroup, NULL); ++ if (!file_exists(devices_path)) { ++ free(devices_path); ++ return 0; ++ } ++ ++ ret = _recursive_read_cgroup_procs(devices_path, pids, len); ++ free(devices_path); ++ return ret; ++} ++ ++static int set_cgroup_freezer(struct cgroup_ops *cg_ops, const char *value) ++{ ++ char *fullpath; ++ int ret; ++ ++ fullpath = must_make_path("/sys/fs/cgroup", "freezer", cg_ops->container_cgroup, "freezer.state", NULL); ++ ret = lxc_write_to_file(fullpath, value, strlen(value), false, 0666); ++ free(fullpath); ++ return ret; ++} ++ ++/* isulad: kill all process in container cgroup path */ ++static void signal_all_processes(struct lxc_handler *handler) ++{ ++ int ret; ++ struct cgroup_ops *cg_ops = handler->cgroup_ops; ++ pid_t *pids = NULL; ++ size_t len = 0, i; ++ ++ ret = set_cgroup_freezer(cg_ops, "FROZEN"); ++ if (ret < 0 && errno != ENOENT) { ++ WARN("cgroup_set frozen failed"); ++ } ++ ++ ret = get_all_pids(cg_ops, &pids, &len); ++ if (ret < 0) { ++ WARN("failed to get all pids"); ++ } ++ ++ for (i = 0; i < len; i++) { ++ ret = kill(pids[i], SIGKILL); ++ if (ret < 0 && errno != ESRCH) { ++ WARN("Can not kill process (pid=%d) with SIGKILL for container %s", pids[i], handler->name); ++ } ++ } ++ ++ ret = set_cgroup_freezer(cg_ops, "THAWED"); ++ if (ret < 0 && errno != ENOENT) { ++ WARN("cgroup_set thawed failed"); ++ } ++ ++ for (i = 0; i < len; i++) { ++ ret = lxc_wait_for_pid_status(pids[i]); ++ if (ret < 0 && errno != ECHILD) { ++ WARN("Failed to wait pid %d for container %s: %s", pids[i], handler->name, strerror(errno)); ++ } ++ } ++ ++ free(pids); ++} ++ + void lxc_fini(const char *name, struct lxc_handler *handler) + { + int i, ret; +@@ -949,6 +1105,8 @@ void lxc_fini(const char *name, struct lxc_handler *handler) + char *namespaces[LXC_NS_MAX + 1]; + size_t namespace_count = 0; + struct cgroup_ops *cgroup_ops = handler->cgroup_ops; ++ int retry_count = 0; ++ int max_retry = 10; + + /* The STOPPING state is there for future cleanup code which can take + * awhile. +@@ -1013,7 +1171,21 @@ void lxc_fini(const char *name, struct lxc_handler *handler) + while (namespace_count--) + free(namespaces[namespace_count]); + +- cgroup_ops->destroy(cgroup_ops, handler); ++ // if we shared pid namespace with others, should kill all processes within container cgroup ++ if (handler->conf->ns_share[LXC_NS_PID] != NULL) { ++ TRACE("Trying to kill all subprocess"); ++ signal_all_processes(handler); ++ TRACE("Finished kill all subprocess"); ++ } ++retry: ++ if (!cgroup_ops->destroy(cgroup_ops, handler)) { ++ if (retry_count < max_retry) { ++ usleep(100 * 1000); /* 100 millisecond */ ++ retry_count++; ++ goto retry; ++ } ++ SYSERROR("Failed to destroy cgroup path for container: \"%s\"", handler->name); ++ } + + if (handler->conf->reboot == REBOOT_NONE) { + /* For all new state clients simply close the command socket. +@@ -2494,162 +2666,6 @@ static void clean_resource_set_env(struct lxc_handler *handler) + /* End of environment variable setup for hooks. */ + } + +-void trim_line(char *s) +-{ +- size_t len; +- +- len = strlen(s); +- while ((len > 1) && (s[len - 1] == '\n')) +- s[--len] = '\0'; +-} +- +-static int _read_procs_file(const char *path, pid_t **pids, size_t *len) +-{ +- FILE *f; +- char *line = NULL; +- size_t sz = 0; +- +- f = fopen_cloexec(path, "r"); +- if (!f) +- return -1; +- +- while (getline(&line, &sz, f) != -1) { +- pid_t pid; +- trim_line(line); +- pid = (pid_t)atoll(line); +- *pids = realloc(*pids, sizeof(pid_t) * (*len + 1)); +- (*pids)[*len] = pid; +- (*len)++; +- } +- +- free(line); +- fclose(f); +- return 0; +-} +- +-static int _recursive_read_cgroup_procs(const char *dirpath, pid_t **pids, size_t *len) +-{ +- struct dirent *direntp; +- DIR *dir; +- int ret, failed = 0; +- char pathname[PATH_MAX]; +- +- dir = opendir(dirpath); +- if (!dir && errno != ENOENT) { +- WARN("Failed to open \"%s\"", dirpath); +- return 0; +- } +- +- while ((direntp = readdir(dir))) { +- struct stat mystat; +- int rc; +- +- if (!strcmp(direntp->d_name, ".") || +- !strcmp(direntp->d_name, "..")) +- continue; +- +- rc = snprintf(pathname, PATH_MAX, "%s/%s", dirpath, direntp->d_name); +- if (rc < 0 || rc >= PATH_MAX) { +- failed = 1; +- continue; +- } +- +- if (strcmp(direntp->d_name, "cgroup.procs") == 0) { +- if (_read_procs_file(pathname, pids, len)) { +- failed = 1; +- +- } +- continue; +- } +- +- ret = lstat(pathname, &mystat); +- if (ret) { +- failed = 1; +- continue; +- } +- +- if (S_ISDIR(mystat.st_mode)) { +- if (_recursive_read_cgroup_procs(pathname, pids, len) < 0) +- failed = 1; +- } +- } +- +- ret = closedir(dir); +- if (ret) { +- WARN("Failed to close directory \"%s\"", dirpath); +- failed = 1; +- } +- +- return failed ? -1 : 0; +-} +- +-int get_all_pids(struct cgroup_ops *cg_ops, pid_t **pids, size_t *len) +-{ +- char *devices_path = NULL; +- int ret; +- +- devices_path = must_make_path("/sys/fs/cgroup", "devices", cg_ops->container_cgroup, NULL); +- if (!file_exists(devices_path)) { +- free(devices_path); +- return 0; +- } +- +- ret = _recursive_read_cgroup_procs(devices_path, pids, len); +- free(devices_path); +- return ret; +-} +- +-static int set_cgroup_freezer(struct cgroup_ops *cg_ops, const char *value) +-{ +- char *fullpath; +- int ret; +- +- fullpath = must_make_path("/sys/fs/cgroup", "freezer", cg_ops->container_cgroup, "freezer.state", NULL); +- ret = lxc_write_to_file(fullpath, value, strlen(value), false, 0666); +- free(fullpath); +- return ret; +-} +- +-/* isulad: kill all process in container cgroup path */ +-static void signal_all_processes(struct lxc_handler *handler) +-{ +- int ret; +- struct cgroup_ops *cg_ops = handler->cgroup_ops; +- pid_t *pids = NULL; +- size_t len = 0, i; +- +- ret = set_cgroup_freezer(cg_ops, "FROZEN"); +- if (ret < 0 && errno != ENOENT) { +- WARN("cgroup_set frozen failed"); +- } +- +- ret = get_all_pids(cg_ops, &pids, &len); +- if (ret < 0) { +- WARN("failed to get all pids"); +- } +- +- for (i = 0; i < len; i++) { +- ret = kill(pids[i], SIGKILL); +- if (ret < 0 && errno != ESRCH) { +- WARN("Can not kill process (pid=%d) with SIGKILL for container %s", pids[i], handler->name); +- } +- } +- +- ret = set_cgroup_freezer(cg_ops, "THAWED"); +- if (ret < 0 && errno != ENOENT) { +- WARN("cgroup_set thawed failed"); +- } +- +- for (i = 0; i < len; i++) { +- ret = lxc_wait_for_pid_status(pids[i]); +- if (ret < 0 && errno != ECHILD) { +- WARN("Failed to wait pid %d for container %s: %s", pids[i], handler->name, strerror(errno)); +- } +- } +- +- free(pids); +-} +- + /*isulad: do_lxcapi_clean_resource */ + int do_lxcapi_clean_resource(char *name, char *lxcpath, struct lxc_conf *conf, pid_t pid) + { +@@ -2687,7 +2703,7 @@ retry: + retry_count++; + goto retry; + } +- ERROR("Failed to destroy cgroup for container \"%s\".", handler->name); ++ SYSERROR("Failed to destroy cgroup path for container: \"%s\"", handler->name); + ret = -1; + } + +-- +1.8.3.1 + diff --git a/0071-lxc-get-cgroup-path-according-to-cgroup-mountpoint.patch b/0071-lxc-get-cgroup-path-according-to-cgroup-mountpoint.patch new file mode 100644 index 0000000..febd361 --- /dev/null +++ b/0071-lxc-get-cgroup-path-according-to-cgroup-mountpoint.patch @@ -0,0 +1,126 @@ +From 5c369714d1a1d74606e6ee44a3df4e1d159ee702 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Thu, 21 Mar 2019 22:05:09 +0800 +Subject: [PATCH 071/122] lxc: get cgroup path according to cgroup mountpoint + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/cgroups/cgfsng.c | 6 ++++-- + src/lxc/cgroups/cgroup.h | 2 +- + src/lxc/commands.c | 6 +++--- + src/lxc/criu.c | 2 +- + src/lxc/start.c | 8 +++----- + 5 files changed, 12 insertions(+), 12 deletions(-) + +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index 5ceb06b..62d58f9 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -1852,7 +1852,7 @@ __cgfsng_ops static bool cgfsng_unfreeze(struct cgroup_ops *ops) + } + + __cgfsng_ops static const char *cgfsng_get_cgroup(struct cgroup_ops *ops, +- const char *controller) ++ const char *controller, bool skip_mount) + { + struct hierarchy *h; + +@@ -1863,7 +1863,9 @@ __cgfsng_ops static const char *cgfsng_get_cgroup(struct cgroup_ops *ops, + return NULL; + } + +- return h->container_full_path ? h->container_full_path + strlen(h->mountpoint) : NULL; ++ if (!h->container_full_path) ++ h->container_full_path = must_make_path(h->mountpoint, h->container_base_path, ops->container_cgroup, NULL); ++ return skip_mount ? h->container_full_path + strlen(h->mountpoint) : h->container_full_path; + } + + /* Given a cgroup path returned from lxc_cmd_get_cgroup_path, build a full path, +diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h +index b6116f6..edbb1e3 100644 +--- a/src/lxc/cgroups/cgroup.h ++++ b/src/lxc/cgroups/cgroup.h +@@ -129,7 +129,7 @@ struct cgroup_ops { + bool (*destroy)(struct cgroup_ops *ops, struct lxc_handler *handler); + bool (*payload_create)(struct cgroup_ops *ops, struct lxc_handler *handler); + bool (*payload_enter)(struct cgroup_ops *ops, pid_t pid); +- const char *(*get_cgroup)(struct cgroup_ops *ops, const char *controller); ++ const char *(*get_cgroup)(struct cgroup_ops *ops, const char *controller, bool skip_mount); + bool (*escape)(const struct cgroup_ops *ops); + int (*num_hierarchies)(struct cgroup_ops *ops); + bool (*get_hierarchies)(struct cgroup_ops *ops, int n, char ***out); +diff --git a/src/lxc/commands.c b/src/lxc/commands.c +index f0c95df..c74b8c1 100644 +--- a/src/lxc/commands.c ++++ b/src/lxc/commands.c +@@ -481,9 +481,9 @@ static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req, + struct cgroup_ops *cgroup_ops = handler->cgroup_ops; + + if (req->datalen > 0) +- path = cgroup_ops->get_cgroup(cgroup_ops, req->data); ++ path = cgroup_ops->get_cgroup(cgroup_ops, req->data, true); + else +- path = cgroup_ops->get_cgroup(cgroup_ops, NULL); ++ path = cgroup_ops->get_cgroup(cgroup_ops, NULL, true); + if (!path) + return -1; + +@@ -655,7 +655,7 @@ static int lxc_cmd_stop_callback(int fd, struct lxc_cmd_req *req, + * lxc_unfreeze() would do another cmd (GET_CGROUP) which would + * deadlock us. + */ +- if (!cgroup_ops->get_cgroup(cgroup_ops, "freezer")) ++ if (!cgroup_ops->get_cgroup(cgroup_ops, "freezer", true)) + return 0; + + if (cgroup_ops->unfreeze(cgroup_ops)) +diff --git a/src/lxc/criu.c b/src/lxc/criu.c +index bb97859..5c77979 100644 +--- a/src/lxc/criu.c ++++ b/src/lxc/criu.c +@@ -332,7 +332,7 @@ static void exec_criu(struct cgroup_ops *cgroup_ops, struct lxc_conf *conf, + } else { + const char *p; + +- p = cgroup_ops->get_cgroup(cgroup_ops, controllers[0]); ++ p = cgroup_ops->get_cgroup(cgroup_ops, controllers[0], true); + if (!p) { + ERROR("failed to get cgroup path for %s", controllers[0]); + goto err; +diff --git a/src/lxc/start.c b/src/lxc/start.c +index b14e46f..9243a6d 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -1032,17 +1032,15 @@ static int _recursive_read_cgroup_procs(const char *dirpath, pid_t **pids, size_ + + int get_all_pids(struct cgroup_ops *cg_ops, pid_t **pids, size_t *len) + { +- char *devices_path = NULL; ++ const char *devices_path = NULL; + int ret; + +- devices_path = must_make_path("/sys/fs/cgroup", "devices", cg_ops->container_cgroup, NULL); ++ devices_path = cg_ops->get_cgroup(cg_ops, "devices", false); + if (!file_exists(devices_path)) { +- free(devices_path); + return 0; + } + + ret = _recursive_read_cgroup_procs(devices_path, pids, len); +- free(devices_path); + return ret; + } + +@@ -1051,7 +1049,7 @@ static int set_cgroup_freezer(struct cgroup_ops *cg_ops, const char *value) + char *fullpath; + int ret; + +- fullpath = must_make_path("/sys/fs/cgroup", "freezer", cg_ops->container_cgroup, "freezer.state", NULL); ++ fullpath = must_make_path(cg_ops->get_cgroup(cg_ops, "freezer", false), "freezer.state", NULL); + ret = lxc_write_to_file(fullpath, value, strlen(value), false, 0666); + free(fullpath); + return ret; +-- +1.8.3.1 + diff --git a/0072-lxc-adapt-to-docker-18.09.patch b/0072-lxc-adapt-to-docker-18.09.patch new file mode 100644 index 0000000..7b72afa --- /dev/null +++ b/0072-lxc-adapt-to-docker-18.09.patch @@ -0,0 +1,66 @@ +From de35b7df30fbdbf10c0d55523b7fa3a15eb17623 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Mon, 25 Mar 2019 18:03:23 +0800 +Subject: [PATCH 072/122] lxc: adapt to docker-18.09 + +1. adapt to docker-18.09 +2. fix strlcpy bug + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 8 ++++---- + src/lxc/start.c | 4 ++-- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index a6b9797..abfba04 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4382,9 +4382,9 @@ static char* generate_json_str(const char *name, const char *lxcpath, const char + ERROR("Get container %s pid failed: %s", name, strerror(errno)); + cpid = "-1"; + } +- // {"ociVersion":"","id":"xxx","pid":777,"root":"xxx","bundlePath":"xxx"} +- size = 1 + 16 + 5 + strlen(name) + 3 + 6 + strlen(cpid) + 1 +- + 7 + strlen(rootfs) + 3 + 13 + strlen(lxcpath) + 1 + strlen(name) + 3 + 1; ++ // {"ociVersion":"","id":"xxx","pid":777,"root":"xxx","bundle":"xxx"} ++ size = strlen("{\"ociVersion\":\"\",\"id\":\"\",\"pid\":,\"root\":\"\",\"bundle\":\"\"}") + ++ strlen(name) + strlen(cpid) + strlen(rootfs) + strlen(lxcpath) + 1 + strlen(name) + 1; + inmsg = malloc(size); + if (!inmsg) { + ERROR("Out of memory"); +@@ -4392,7 +4392,7 @@ static char* generate_json_str(const char *name, const char *lxcpath, const char + goto out_free; + } + rc = snprintf(inmsg, size, +- "{\"ociVersion\":\"\",\"id\":\"%s\",\"pid\":%s,\"root\":\"%s\",\"bundlePath\":\"%s/%s\"}", ++ "{\"ociVersion\":\"\",\"id\":\"%s\",\"pid\":%s,\"root\":\"%s\",\"bundle\":\"%s/%s\"}", + name, cpid, rootfs, lxcpath, name); + if (rc < 0 || rc >= size) { + ERROR("Create json string failed"); +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 9243a6d..2fca4e1 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -2186,7 +2186,7 @@ static int lxc_spawn(struct lxc_handler *handler) + /* isulad: Run oci prestart hook at here */ + char* oci_hook_args[1]; + oci_hook_args[0] = alloca(strlen(lxcpath) + 1); +- (void)strlcpy(oci_hook_args[0], lxcpath, strlen(lxcpath)); ++ (void)strlcpy(oci_hook_args[0], lxcpath, strlen(lxcpath) + 1); + ret = run_lxc_hooks(name, "oci-prestart", conf, oci_hook_args); + if (ret < 0) { + ERROR("Failed to run oci prestart hooks"); +@@ -2687,7 +2687,7 @@ int do_lxcapi_clean_resource(char *name, char *lxcpath, struct lxc_conf *conf, p + + char* oci_hook_args[1]; + oci_hook_args[0] = alloca(strlen(handler->lxcpath) + 1); +- (void)strlcpy(oci_hook_args[0], handler->lxcpath, strlen(handler->lxcpath)); ++ (void)strlcpy(oci_hook_args[0], handler->lxcpath, strlen(handler->lxcpath) + 1); + + if (run_lxc_hooks(handler->name, "oci-poststop", handler->conf, oci_hook_args)) { + ERROR("Failed to run lxc.hook.post-stop for container \"%s\".", handler->name); +-- +1.8.3.1 + diff --git a/0073-lxc-support-set-additional-groups.patch b/0073-lxc-support-set-additional-groups.patch new file mode 100644 index 0000000..c5edff8 --- /dev/null +++ b/0073-lxc-support-set-additional-groups.patch @@ -0,0 +1,247 @@ +From 5c599c0a93b66eea1633f54ac61bcd99142758e3 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Mon, 25 Mar 2019 17:17:00 +0800 +Subject: [PATCH 073/122] lxc: support set additional groups + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/attach.c | 8 ++++--- + src/lxc/conf.c | 12 ++++++++++ + src/lxc/conf.h | 3 +++ + src/lxc/confile.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- + src/lxc/start.c | 25 ++++++++++++--------- + 5 files changed, 100 insertions(+), 14 deletions(-) + +diff --git a/src/lxc/attach.c b/src/lxc/attach.c +index c979c85..618f2f1 100644 +--- a/src/lxc/attach.c ++++ b/src/lxc/attach.c +@@ -903,9 +903,6 @@ static int attach_child_main(struct attach_clone_payload *payload) + goto on_error; + } + +- if (!lxc_setgroups(0, NULL) && errno != EPERM) +- goto on_error; +- + /* Set {u,g}id. */ + if (options->uid != LXC_INVALID_UID) + new_uid = options->uid; +@@ -1017,6 +1014,11 @@ static int attach_child_main(struct attach_clone_payload *payload) + goto on_error; + } + ++ if (init_ctx->container && init_ctx->container->lxc_conf && ++ !lxc_setgroups(init_ctx->container->lxc_conf->init_groups_len, ++ init_ctx->container->lxc_conf->init_groups)) ++ goto on_error; ++ + if (!lxc_switch_uid_gid(new_uid, new_gid)) + goto on_error; + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index abfba04..58fc059 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -5184,10 +5184,21 @@ int lxc_clear_init_args(struct lxc_conf *lxc_conf) + for (i = 0; i < lxc_conf->init_argc; i++) + free(lxc_conf->init_argv[i]); + free(lxc_conf->init_argv); ++ lxc_conf->init_argc = 0; + + return 0; + } + ++/*isulad clear init groups*/ ++int lxc_clear_init_groups(struct lxc_conf *lxc_conf) ++{ ++ free(lxc_conf->init_groups); ++ lxc_conf->init_groups_len = 0; ++ ++ return 0; ++} ++ ++ + /*isulad: clear populate devices*/ + int lxc_clear_populate_devices(struct lxc_conf *c) + { +@@ -5294,6 +5305,7 @@ void lxc_conf_free(struct lxc_conf *conf) + free(conf->cgroup_meta.controllers); + /* isulad add begin */ + lxc_clear_init_args(conf); ++ lxc_clear_init_groups(conf); + lxc_clear_populate_devices(conf); + lxc_clear_rootfs_masked_paths(conf); + lxc_clear_rootfs_ro_paths(conf); +diff --git a/src/lxc/conf.h b/src/lxc/conf.h +index 93cf15d..11cf596 100644 +--- a/src/lxc/conf.h ++++ b/src/lxc/conf.h +@@ -418,6 +418,8 @@ struct lxc_conf { + /* init args used to repalce init_cmd*/ + char **init_argv; + size_t init_argc; ++ gid_t *init_groups; ++ size_t init_groups_len; + /* populate devices*/ + struct lxc_list populate_devs; + +@@ -498,6 +500,7 @@ extern int lxc_clear_namespace(struct lxc_conf *c); + + /* isulad add begin */ + int lxc_clear_init_args(struct lxc_conf *lxc_conf); ++int lxc_clear_init_groups(struct lxc_conf *lxc_conf); + int lxc_clear_populate_devices(struct lxc_conf *c); + int lxc_clear_rootfs_masked_paths(struct lxc_conf *c); + int lxc_clear_rootfs_ro_paths(struct lxc_conf *c); +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index 3940b32..60e6c46 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -154,6 +154,7 @@ lxc_config_define(sysctl); + lxc_config_define(proc); + /*isulad add begin*/ + lxc_config_define(init_args); ++lxc_config_define(init_groups); + lxc_config_define(populate_device); + lxc_config_define(umask); + /*isulad add end*/ +@@ -245,6 +246,7 @@ static struct lxc_config_t config_jump_table[] = { + + /*isulad add begin*/ + { "lxc.isulad.init.args", set_config_init_args, get_config_init_args, clr_config_init_args, }, ++ { "lxc.isulad.init.groups", set_config_init_groups, get_config_init_groups, clr_config_init_groups, }, + { "lxc.isulad.populate.device", set_config_populate_device, get_config_populate_device, clr_config_populate_device, }, + { "lxc.isulad.rootfs.maskedpaths", set_config_rootfs_masked_paths, get_config_rootfs_masked_paths, clr_config_rootfs_masked_paths, }, + { "lxc.isulad.rootfs.ropaths", set_config_rootfs_ro_paths, get_config_rootfs_ro_paths, clr_config_rootfs_ro_paths, }, +@@ -2230,6 +2232,43 @@ static int set_config_init_args(const char *key, const char *value, + return 0; + } + ++/* isulad: set config for init groups */ ++static int set_config_init_groups(const char *key, const char *value, ++ struct lxc_conf *lxc_conf, void *data) ++{ ++ char *groups, *token; ++ int ret = -1; ++ ++ if (lxc_config_value_empty(value)) ++ return lxc_clear_init_groups(lxc_conf); ++ ++ groups = strdup(value); ++ if (!groups) ++ return -1; ++ ++ /* In case several capability keep is specified in a single line ++ * split these caps in a single element for the list. ++ */ ++ lxc_iterate_parts(token, groups, " \t") { ++ gid_t *tmp; ++ tmp = realloc(lxc_conf->init_groups, (lxc_conf->init_groups_len + 1) * sizeof(gid_t)); ++ if (!tmp) { ++ ERROR("Out of memory"); ++ goto on_error; ++ } ++ lxc_conf->init_groups = tmp; ++ tmp[lxc_conf->init_groups_len] = atoll(token); ++ lxc_conf->init_groups_len++; ++ } ++ ++ ret = 0; ++ ++on_error: ++ free(groups); ++ ++ return ret; ++} ++ + /* isulad: set config for populate device */ + static int set_config_populate_device(const char *key, const char *value, + struct lxc_conf *lxc_conf, void *data) +@@ -3947,7 +3986,25 @@ static int get_config_init_args(const char *key, char *retv, int inlen, + + for (i = 0; i < c->init_argc; i++) { + strprint(retv, inlen, "%s", c->init_argv[i]); +- } ++ } ++ ++ return fulllen; ++} ++ ++/* isulad: get config init groups */ ++static int get_config_init_groups(const char *key, char *retv, int inlen, ++ struct lxc_conf *c, void *data) ++{ ++ int i, len, fulllen = 0; ++ ++ if (!retv) ++ inlen = 0; ++ else ++ memset(retv, 0, inlen); ++ ++ for (i = 0; i < c->init_groups_len; i++) { ++ strprint(retv, inlen, "%u\n", c->init_groups[i]); ++ } + + return fulllen; + } +@@ -4836,6 +4893,13 @@ static inline int clr_config_init_args(const char *key, struct lxc_conf *c, + return lxc_clear_init_args(c); + } + ++/* isulad: clr config init args*/ ++static inline int clr_config_init_groups(const char *key, struct lxc_conf *c, ++ void *data) ++{ ++ return lxc_clear_init_groups(c); ++} ++ + /* isulad: clr config populate devices*/ + static inline int clr_config_populate_device(const char *key, struct lxc_conf *c, + void *data) +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 2fca4e1..ae92c13 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -1666,6 +1666,20 @@ static int do_start(void *data) + if (lxc_setup_env_home(new_uid) < 0) + goto out_warn_father; + ++ /* If we are in a new user namespace we already dropped all groups when ++ * we switched to root in the new user namespace further above. Only ++ * drop groups if we can, so ensure that we have necessary privilege. ++ */ ++ if (lxc_list_empty(&handler->conf->id_map)) ++ #if HAVE_LIBCAP ++ if (lxc_proc_cap_is_set(CAP_SETGID, CAP_EFFECTIVE)) ++ #endif ++ /* isulad: set groups for init process, and before we set uid and gid */ ++ if (!lxc_setgroups(handler->conf->init_groups_len, handler->conf->init_groups)) { ++ ERROR("Can not set groups"); ++ goto out_warn_father; ++ } ++ + /* Avoid unnecessary syscalls. */ + if (new_uid == nsuid) + new_uid = LXC_INVALID_UID; +@@ -1676,16 +1690,7 @@ static int do_start(void *data) + if (!lxc_switch_uid_gid(new_uid, new_gid)) + goto out_warn_father; + +- /* If we are in a new user namespace we already dropped all groups when +- * we switched to root in the new user namespace further above. Only +- * drop groups if we can, so ensure that we have necessary privilege. +- */ +- if (lxc_list_empty(&handler->conf->id_map)) +- #if HAVE_LIBCAP +- if (lxc_proc_cap_is_set(CAP_SETGID, CAP_EFFECTIVE)) +- #endif +- if (!lxc_setgroups(0, NULL)) +- goto out_warn_father; ++ + + ret = lxc_ambient_caps_down(); + if (ret < 0) { +-- +1.8.3.1 + diff --git a/0074-lxc-only-add-valid-fd-to-mainloop.patch b/0074-lxc-only-add-valid-fd-to-mainloop.patch new file mode 100644 index 0000000..2a0e250 --- /dev/null +++ b/0074-lxc-only-add-valid-fd-to-mainloop.patch @@ -0,0 +1,28 @@ +From df20c5c153b342c2aa49ebafbef8c1e334668e9a Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Tue, 26 Mar 2019 16:11:13 +0800 +Subject: [PATCH 074/122] lxc: only add valid fd to mainloop + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/mainloop.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/lxc/mainloop.c b/src/lxc/mainloop.c +index b169aa6..9603d1e 100644 +--- a/src/lxc/mainloop.c ++++ b/src/lxc/mainloop.c +@@ -85,6 +85,9 @@ int lxc_mainloop_add_handler(struct lxc_epoll_descr *descr, int fd, + struct mainloop_handler *handler; + struct lxc_list *item; + ++ if (fd < 0) ++ return 0; ++ + handler = malloc(sizeof(*handler)); + if (!handler) + return -1; +-- +1.8.3.1 + diff --git a/0075-lxc-add-timeout-for-attach.patch b/0075-lxc-add-timeout-for-attach.patch new file mode 100644 index 0000000..38dba02 --- /dev/null +++ b/0075-lxc-add-timeout-for-attach.patch @@ -0,0 +1,278 @@ +From d108c60ea9bf1c0a257659d07531e50d09897e48 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Wed, 3 Apr 2019 19:54:36 +0800 +Subject: [PATCH 075/122] lxc: add timeout for attach + +Signed-off-by: wujing +Signed-off-by: LiFeng +--- + src/lxc/attach.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++ + src/lxc/attach_options.h | 1 + + src/lxc/tools/arguments.h | 4 +++ + src/lxc/tools/lxc_attach.c | 11 +++++++ + src/lxc/tools/lxc_start.c | 13 +------- + src/lxc/utils.c | 13 ++++++++ + src/lxc/utils.h | 2 ++ + 7 files changed, 111 insertions(+), 12 deletions(-) + +diff --git a/src/lxc/attach.c b/src/lxc/attach.c +index 618f2f1..79049c3 100644 +--- a/src/lxc/attach.c ++++ b/src/lxc/attach.c +@@ -69,6 +69,20 @@ + #include + #endif + ++typedef enum { ++ ATTACH_INIT, ++ ATTACH_TIMEOUT, ++ ATTACH_MAX, ++} attach_timeout_t; ++ ++static volatile attach_timeout_t g_attach_timeout_state = ATTACH_INIT; ++ ++struct attach_timeout_conf { ++ unsigned int timeout; ++ unsigned long long start_time; ++ pid_t pid; ++}; ++ + lxc_log_define(attach, lxc); + + /* Define default options if no options are supplied by the user. */ +@@ -1145,6 +1159,59 @@ static inline void lxc_attach_terminal_close_log(struct lxc_terminal *terminal) + terminal->log_fd = -EBADF; + } + ++/* isulad: attach timeout thread function */ ++static void* wait_attach_timeout(void *arg) ++{ ++ struct attach_timeout_conf *conf = (struct attach_timeout_conf *)arg; ++ ++ if (!conf || conf->timeout < 1) ++ goto out; ++ sleep(conf->timeout); ++ if (lxc_process_alive(conf->pid, conf->start_time)) { ++ g_attach_timeout_state = ATTACH_TIMEOUT; ++ if (kill(conf->pid, SIGKILL) < 0) { ++ ERROR("Failed to send signal %d to pid %d", SIGKILL, conf->pid); ++ } ++ } ++ ++out: ++ free(conf); ++ return ((void *)0); ++} ++ ++/* isulad: create attach timeout thread */ ++static int create_attach_timeout_thread(unsigned int attach_timeout, pid_t pid) ++{ ++ int ret = 0; ++ pthread_t ptid; ++ pthread_attr_t attr; ++ struct attach_timeout_conf *timeout_conf = NULL; ++ ++ timeout_conf = malloc(sizeof(struct attach_timeout_conf)); ++ if (!timeout_conf) { ++ ERROR("Failed to malloc attach timeout conf"); ++ ret = -1; ++ goto out; ++ } ++ ++ memset(timeout_conf, 0, sizeof(struct attach_timeout_conf)); ++ timeout_conf->timeout = attach_timeout; ++ timeout_conf->pid = pid; ++ timeout_conf->start_time = lxc_get_process_startat(pid); ++ ++ pthread_attr_init(&attr); ++ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); ++ ret = pthread_create(&ptid, &attr, wait_attach_timeout, timeout_conf); ++ if (ret != 0) { ++ ERROR("Create attach wait timeout thread failed"); ++ free(timeout_conf); ++ goto out; ++ } ++ ++out: ++ return ret; ++} ++ + int lxc_attach(const char *name, const char *lxcpath, + lxc_attach_exec_t exec_function, void *exec_payload, + lxc_attach_options_t *options, pid_t *attached_process, char **err_msg) +@@ -1481,6 +1548,13 @@ int lxc_attach(const char *name, const char *lxcpath, + + *attached_process = attached_pid; + ++ if (options->timeout > 0) { ++ ret = create_attach_timeout_thread(options->timeout, *attached_process); ++ if (ret) { ++ ERROR("Failed to create attach timeout thread for container."); ++ goto close_mainloop; ++ } ++ } + /* isulad: read error msg from pipe */ + ssize_t size_read; + char errbuf[BUFSIZ + 1] = {0}; +@@ -1510,6 +1584,11 @@ int lxc_attach(const char *name, const char *lxcpath, + } + } + ++ if (g_attach_timeout_state == ATTACH_TIMEOUT && err_msg != NULL && *err_msg == NULL) { ++ *err_msg = strdup("Attach exceeded timeout"); ++ if (!(*err_msg)) ++ ERROR("Out of memory"); ++ } + close_mainloop: + if (options->attach_flags & LXC_ATTACH_TERMINAL) + lxc_mainloop_close(&descr); +diff --git a/src/lxc/attach_options.h b/src/lxc/attach_options.h +index 71c1739..5e279ba 100644 +--- a/src/lxc/attach_options.h ++++ b/src/lxc/attach_options.h +@@ -137,6 +137,7 @@ typedef struct lxc_attach_options_t { + int log_fd; + + char *init_fifo[3]; /* isulad: default fifos for the start */ ++ unsigned int timeout;/* isulad: Seconds for waiting on a container to attach/exec before it is killed*/ + } lxc_attach_options_t; + + /*! Default attach options to use */ +diff --git a/src/lxc/tools/arguments.h b/src/lxc/tools/arguments.h +index d03f8a4..2fc90ad 100644 +--- a/src/lxc/tools/arguments.h ++++ b/src/lxc/tools/arguments.h +@@ -69,6 +69,9 @@ struct lxc_arguments { + const char *exit_monitor_fifo; /* isulad: fifo used to monitor state of monitor process */ + unsigned int start_timeout; /* isulad: Seconds for waiting on a container to start before it is killed*/ + ++ /* for lxc-attach */ ++ unsigned int attach_timeout; ++ + /* for lxc-console */ + unsigned int ttynum; + char escape; +@@ -187,6 +190,7 @@ struct lxc_arguments { + #define OPT_START_TIMEOUT OPT_USAGE - 12 + #define OPT_DISABLE_PTY OPT_USAGE - 13 + #define OPT_OPEN_STDIN OPT_USAGE - 14 ++#define OPT_ATTACH_TIMEOUT OPT_USAGE - 15 + + /* isulad add end*/ + +diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c +index 674050d..2861ef4 100644 +--- a/src/lxc/tools/lxc_attach.c ++++ b/src/lxc/tools/lxc_attach.c +@@ -62,6 +62,7 @@ static char **extra_env; + static ssize_t extra_env_size; + static char **extra_keep; + static ssize_t extra_keep_size; ++static unsigned int timeout = 0; + + static const struct option my_longopts[] = { + {"elevated-privileges", optional_argument, 0, 'e'}, +@@ -78,6 +79,7 @@ static const struct option my_longopts[] = { + {"in-fifo", required_argument, 0, OPT_INPUT_FIFO}, /* isulad add terminal fifos*/ + {"out-fifo", required_argument, 0, OPT_OUTPUT_FIFO}, + {"err-fifo", required_argument, 0, OPT_STDERR_FIFO}, ++ {"timeout", required_argument, 0, OPT_ATTACH_TIMEOUT}, + LXC_COMMON_OPTIONS + }; + +@@ -128,6 +130,7 @@ Options :\n\ + multiple times.\n\ + -f, --rcfile=FILE\n\ + Load configuration file FILE\n\ ++ --timeout Timeout in seconds (default: 0)\n\ + ", + .options = my_longopts, + .parser = my_parser, +@@ -205,6 +208,13 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) + case OPT_STDERR_FIFO: + args->terminal_fifos[2] = arg; + break; ++ case OPT_ATTACH_TIMEOUT: ++ if(!is_non_negative_num(arg)) { ++ ERROR("Error attach timeout parameter:%s.\n", arg); ++ return -1; ++ } ++ args->attach_timeout = (unsigned int)atoi(arg); ++ break; + } + + return 0; +@@ -478,6 +488,7 @@ int main(int argc, char *argv[]) + attach_options.env_policy = env_policy; + attach_options.extra_env_vars = extra_env; + attach_options.extra_keep_env = extra_keep; ++ attach_options.timeout = my_args.attach_timeout; + + if (my_args.argc > 0) { + command.program = my_args.argv[0]; +diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c +index 183fafc..af63f58 100644 +--- a/src/lxc/tools/lxc_start.c ++++ b/src/lxc/tools/lxc_start.c +@@ -49,6 +49,7 @@ + #include "config.h" + #include "confile.h" + #include "log.h" ++#include "utils.h" + + lxc_log_define(lxc_start, lxc); + +@@ -113,18 +114,6 @@ Options :\n\ + .pidfile = NULL, + }; + +-static bool is_non_negative_num(const char *s) +-{ +- if (!s || !strcmp(s, "")) +- return false; +- while(*s != '\0') { +- if(!isdigit(*s)) +- return false; +- ++s; +- } +- return true; +-} +- + static int my_parser(struct lxc_arguments *args, int c, char *arg) + { + switch (c) { +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index 480e6d0..69eb3e5 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -2069,3 +2069,16 @@ out: + free(pid_info); + return alive; + } ++ ++bool is_non_negative_num(const char *s) ++{ ++ if (!s || !strcmp(s, "")) ++ return false; ++ while(*s != '\0') { ++ if(!isdigit(*s)) ++ return false; ++ ++s; ++ } ++ return true; ++} ++ +diff --git a/src/lxc/utils.h b/src/lxc/utils.h +index 73ffdd9..20407af 100644 +--- a/src/lxc/utils.h ++++ b/src/lxc/utils.h +@@ -322,4 +322,6 @@ extern void lxc_write_error_message(int errfd, const char *format, ...); + + extern bool lxc_process_alive(pid_t pid, unsigned long long start_time); + ++extern bool is_non_negative_num(const char *s); ++ + #endif /* __LXC_UTILS_H */ +-- +1.8.3.1 + diff --git a/0076-lxc-delete-unused-variable.patch b/0076-lxc-delete-unused-variable.patch new file mode 100644 index 0000000..96aaedc --- /dev/null +++ b/0076-lxc-delete-unused-variable.patch @@ -0,0 +1,26 @@ +From 5a3c172215974dccf41e456b39c8174aaa580cc8 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Thu, 4 Apr 2019 11:19:48 +0800 +Subject: [PATCH 076/122] lxc: delete unused variable + +Signed-off-by: wujing +Signed-off-by: LiFeng +--- + src/lxc/tools/lxc_attach.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c +index 2861ef4..440c0bc 100644 +--- a/src/lxc/tools/lxc_attach.c ++++ b/src/lxc/tools/lxc_attach.c +@@ -62,7 +62,6 @@ static char **extra_env; + static ssize_t extra_env_size; + static char **extra_keep; + static ssize_t extra_keep_size; +-static unsigned int timeout = 0; + + static const struct option my_longopts[] = { + {"elevated-privileges", optional_argument, 0, 'e'}, +-- +1.8.3.1 + diff --git a/0077-lxc-set-negative-files.limit-to-max-and-fix-bug-of-s.patch b/0077-lxc-set-negative-files.limit-to-max-and-fix-bug-of-s.patch new file mode 100644 index 0000000..103b251 --- /dev/null +++ b/0077-lxc-set-negative-files.limit-to-max-and-fix-bug-of-s.patch @@ -0,0 +1,117 @@ +From fe7032c4ed978c38beb00804abb46ad691c0a83c Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Tue, 2 Apr 2019 23:59:20 -0400 +Subject: [PATCH 077/122] lxc: set negative files.limit to max and fix bug of + setting homedir + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/cgroups/cgfsng.c | 19 +++++++++++++++---- + src/lxc/storage/storage.c | 5 ++--- + src/lxc/utils.c | 29 ++++++++++++++++++++--------- + 3 files changed, 37 insertions(+), 16 deletions(-) + +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index 62d58f9..cc08737 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -2259,19 +2259,30 @@ static bool __cg_legacy_setup_limits(struct cgroup_ops *ops, + cg = iterator->elem; + + if (do_devices == !strncmp("devices", cg->subsystem, 7)) { +- if (cg_legacy_set_data(ops, cg->subsystem, cg->value)) { ++ const char *cgvalue = cg->value; ++ if (strcmp(cg->subsystem, "files.limit") == 0) { ++ if (lxc_safe_long_long(cgvalue, &setvalue) != 0) { ++ SYSERROR("Invalid integer value %s", cgvalue); ++ goto out; ++ } ++ if (setvalue <= 0) { ++ cgvalue = "max"; ++ } ++ } ++ if (cg_legacy_set_data(ops, cg->subsystem, cgvalue)) { + if (do_devices && (errno == EACCES || errno == EPERM)) { + WARN("Failed to set \"%s\" to \"%s\"", +- cg->subsystem, cg->value); ++ cg->subsystem, cgvalue); + continue; + } + WARN("Failed to set \"%s\" to \"%s\"", +- cg->subsystem, cg->value); ++ cg->subsystem, cgvalue); + goto out; + } + DEBUG("Set controller \"%s\" set to \"%s\"", +- cg->subsystem, cg->value); ++ cg->subsystem, cgvalue); + } ++ + // isulad: check cpu shares + if (strcmp(cg->subsystem, "cpu.shares") == 0) { + if (cg_legacy_get_data(ops, cg->subsystem, value, sizeof(value)) < 0) { +diff --git a/src/lxc/storage/storage.c b/src/lxc/storage/storage.c +index 88ed788..fa79762 100644 +--- a/src/lxc/storage/storage.c ++++ b/src/lxc/storage/storage.c +@@ -611,9 +611,8 @@ bool storage_destroy(struct lxc_conf *conf) + + r = storage_init(conf); + if (r == NULL) { +- ERROR("%s 's storage init failed, the storage may be deleted already", conf->name); +- ret = true; +- return ret; ++ WARN("%s 's storage init failed, the storage may be deleted already", conf->name); ++ return true; + } + + destroy_rv = r->ops->destroy(r); +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index 69eb3e5..7b82d06 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -1873,20 +1873,31 @@ int lxc_setup_keyring(void) + // isulad: set env home in container + int lxc_setup_env_home(uid_t uid) + { +-#define __DEFAULT_HOMEDIR__ "/" ++#define __PASSWD_FILE__ "/etc/passwd" + int ret = 0; +- char *homedir; +- struct passwd pwd, *result = NULL; ++ char *homedir = "/"; // default home dir is / ++ FILE *stream = NULL; ++ struct passwd pw, *pwbufp = NULL; + char buf[BUFSIZ]; + +- ret = getpwuid_r(uid, &pwd, buf, BUFSIZ, &result); +- if (ret || !result || !result->pw_dir) { +- WARN("User invalid, can not find user '%u'", uid); +- homedir = __DEFAULT_HOMEDIR__; +- } else { +- homedir = result->pw_dir; ++ stream = fopen_cloexec(__PASSWD_FILE__, "r"); ++ if (stream == NULL) { ++ SYSWARN("Failed to open %s: %s", __PASSWD_FILE__); ++ goto set_env; + } + ++ while (fgetpwent_r(stream, &pw, buf, sizeof(buf), &pwbufp) == 0 && pwbufp != NULL) { ++ if (pwbufp->pw_uid == uid) { ++ homedir = pwbufp->pw_dir; ++ goto set_env; ++ } ++ } ++ WARN("User invalid, can not find user '%u'", uid); ++ ++set_env: ++ if (stream) ++ fclose(stream); ++ + // if we didn't configure HOME, set it based on uid + if (setenv("HOME", homedir, 0) < 0) { + SYSERROR("Unable to set env 'HOME'"); +-- +1.8.3.1 + diff --git a/0078-Run-pre-start-hook-before-chroot.patch b/0078-Run-pre-start-hook-before-chroot.patch new file mode 100644 index 0000000..809ef89 --- /dev/null +++ b/0078-Run-pre-start-hook-before-chroot.patch @@ -0,0 +1,70 @@ +From ca1c7f86ddadd194c2347e2ccd6b216f1403e273 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Wed, 3 Apr 2019 23:36:04 -0400 +Subject: [PATCH 078/122] Run pre-start hook before chroot + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 7 +++++++ + src/lxc/start.c | 6 ++++++ + src/lxc/sync.h | 2 ++ + 3 files changed, 15 insertions(+) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 58fc059..a9421c5 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -82,6 +82,7 @@ + #include "loop.h" + #include "path.h" + #include "utils.h" ++#include "sync.h" + + #ifdef MAJOR_IN_MKDEV + #include +@@ -4186,6 +4187,12 @@ int lxc_setup(struct lxc_handler *handler) + goto on_error; + } + ++ /* Ask father to run start host hooks and wait for him to finish. */ ++ if (lxc_sync_barrier_parent(handler, LXC_SYNC_START_HOST_HOOK)) { ++ ERROR("Failed to sync parent to start host hook"); ++ goto on_error; ++ } ++ + ret = lxc_setup_rootfs_switch_root(&lxc_conf->rootfs); + if (ret < 0) { + ERROR("Failed to pivot root into rootfs"); +diff --git a/src/lxc/start.c b/src/lxc/start.c +index ae92c13..10f922d 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -2204,6 +2204,12 @@ static int lxc_spawn(struct lxc_handler *handler) + goto out_delete_net; + } + ++ /* Tell the child to continue its initialization. We'll get ++ * LXC_SYNC_CGROUP when it is ready for us to setup cgroups. ++ */ ++ if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_START_HOST_HOOK)) ++ goto out_delete_net; ++ + /* Tell the child to complete its initialization and wait for it to exec + * or return an error. (The child will never return + * LXC_SYNC_READY_START+1. It will either close the sync pipe, causing +diff --git a/src/lxc/sync.h b/src/lxc/sync.h +index 5c0fb34..787911d 100644 +--- a/src/lxc/sync.h ++++ b/src/lxc/sync.h +@@ -31,6 +31,8 @@ enum { + LXC_SYNC_POST_CONFIGURE, + LXC_SYNC_CGROUP, + LXC_SYNC_CGROUP_UNSHARE, ++ LXC_SYNC_START_HOST_HOOK, ++ LXC_SYNC_POST_START_HOST_HOOK, + LXC_SYNC_CGROUP_LIMITS, + LXC_SYNC_READY_START, + LXC_SYNC_RESTART, +-- +1.8.3.1 + diff --git a/0079-inherid-env-from-parent-in-oci-hooks.patch b/0079-inherid-env-from-parent-in-oci-hooks.patch new file mode 100644 index 0000000..53a8040 --- /dev/null +++ b/0079-inherid-env-from-parent-in-oci-hooks.patch @@ -0,0 +1,29 @@ +From b19fca11de19c05c4035fd98842810dfb102aa7b Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Thu, 4 Apr 2019 17:21:56 +0800 +Subject: [PATCH 079/122] inherid env from parent in oci hooks + +env: LD_LIBRAY_PAHT and PATH + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index a9421c5..20eb840 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4420,7 +4420,7 @@ static char **merge_ocihook_env(char **oldenvs, size_t env_len, size_t *merge_en + size_t result_len = env_len; + size_t i, j; + char *tmpenv; +- char *lxc_envs[] = {"LXC_CGNS_AWARE", "LXC_PID", "LXC_ROOTFS_MOUNT", ++ char *lxc_envs[] = {"LD_LIBRARY_PATH", "PATH", "LXC_CGNS_AWARE", "LXC_PID", "LXC_ROOTFS_MOUNT", + "LXC_CONFIG_FILE", "LXC_CGROUP_PATH", "LXC_ROOTFS_PATH", "LXC_NAME"}; + char *lxcenv_buf; + +-- +1.8.3.1 + diff --git a/0080-lxc-fix-compile-error.patch b/0080-lxc-fix-compile-error.patch new file mode 100644 index 0000000..9a0787d --- /dev/null +++ b/0080-lxc-fix-compile-error.patch @@ -0,0 +1,35 @@ +From ff3a4e1e01afe4cabd6dfae8400b3bfa5803567d Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Mon, 8 Apr 2019 08:29:46 -0400 +Subject: [PATCH 080/122] lxc: fix compile error + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/utils.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index 7b82d06..fd6075f 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -1874,7 +1874,6 @@ int lxc_setup_keyring(void) + int lxc_setup_env_home(uid_t uid) + { + #define __PASSWD_FILE__ "/etc/passwd" +- int ret = 0; + char *homedir = "/"; // default home dir is / + FILE *stream = NULL; + struct passwd pw, *pwbufp = NULL; +@@ -1882,7 +1881,7 @@ int lxc_setup_env_home(uid_t uid) + + stream = fopen_cloexec(__PASSWD_FILE__, "r"); + if (stream == NULL) { +- SYSWARN("Failed to open %s: %s", __PASSWD_FILE__); ++ SYSWARN("Failed to open %s", __PASSWD_FILE__); + goto set_env; + } + +-- +1.8.3.1 + diff --git a/0081-lxc-Change-the-range-of-attach-timeout.patch b/0081-lxc-Change-the-range-of-attach-timeout.patch new file mode 100644 index 0000000..2ed2601 --- /dev/null +++ b/0081-lxc-Change-the-range-of-attach-timeout.patch @@ -0,0 +1,78 @@ +From d2711e184061fd4c03413667e4e9b44ae741d901 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Mon, 8 Apr 2019 16:42:43 +0800 +Subject: [PATCH 081/122] lxc: Change the range of attach timeout + +Signed-off-by: wujing +Signed-off-by: LiFeng +--- + src/lxc/attach.c | 4 ++-- + src/lxc/attach_options.h | 2 +- + src/lxc/tools/arguments.h | 2 +- + src/lxc/tools/lxc_attach.c | 2 +- + 4 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/lxc/attach.c b/src/lxc/attach.c +index 79049c3..6480eb9 100644 +--- a/src/lxc/attach.c ++++ b/src/lxc/attach.c +@@ -78,7 +78,7 @@ typedef enum { + static volatile attach_timeout_t g_attach_timeout_state = ATTACH_INIT; + + struct attach_timeout_conf { +- unsigned int timeout; ++ int64_t timeout; + unsigned long long start_time; + pid_t pid; + }; +@@ -1180,7 +1180,7 @@ out: + } + + /* isulad: create attach timeout thread */ +-static int create_attach_timeout_thread(unsigned int attach_timeout, pid_t pid) ++static int create_attach_timeout_thread(int64_t attach_timeout, pid_t pid) + { + int ret = 0; + pthread_t ptid; +diff --git a/src/lxc/attach_options.h b/src/lxc/attach_options.h +index 5e279ba..9744a2e 100644 +--- a/src/lxc/attach_options.h ++++ b/src/lxc/attach_options.h +@@ -137,7 +137,7 @@ typedef struct lxc_attach_options_t { + int log_fd; + + char *init_fifo[3]; /* isulad: default fifos for the start */ +- unsigned int timeout;/* isulad: Seconds for waiting on a container to attach/exec before it is killed*/ ++ int64_t timeout;/* isulad: Seconds for waiting on a container to attach/exec before it is killed*/ + } lxc_attach_options_t; + + /*! Default attach options to use */ +diff --git a/src/lxc/tools/arguments.h b/src/lxc/tools/arguments.h +index 2fc90ad..de02aeb 100644 +--- a/src/lxc/tools/arguments.h ++++ b/src/lxc/tools/arguments.h +@@ -70,7 +70,7 @@ struct lxc_arguments { + unsigned int start_timeout; /* isulad: Seconds for waiting on a container to start before it is killed*/ + + /* for lxc-attach */ +- unsigned int attach_timeout; ++ int64_t attach_timeout; + + /* for lxc-console */ + unsigned int ttynum; +diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c +index 440c0bc..854b3a2 100644 +--- a/src/lxc/tools/lxc_attach.c ++++ b/src/lxc/tools/lxc_attach.c +@@ -212,7 +212,7 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) + ERROR("Error attach timeout parameter:%s.\n", arg); + return -1; + } +- args->attach_timeout = (unsigned int)atoi(arg); ++ args->attach_timeout = (unsigned int)atoll(arg); + break; + } + +-- +1.8.3.1 + diff --git a/0082-lxc-fix-memory-leak-cause-by-setenv.patch b/0082-lxc-fix-memory-leak-cause-by-setenv.patch new file mode 100644 index 0000000..c626eb7 --- /dev/null +++ b/0082-lxc-fix-memory-leak-cause-by-setenv.patch @@ -0,0 +1,150 @@ +From 767d1b2f9bb323de16658a080b314c5f8feaec67 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Thu, 11 Apr 2019 15:27:31 +0800 +Subject: [PATCH 082/122] lxc: fix memory leak cause by setenv + +isulad will call do_lxcapi_clean_resource(), so setenv at here, will +change env of isulad. + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + src/lxc/start.c | 107 ++++++++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 76 insertions(+), 31 deletions(-) + +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 10f922d..87e07d3 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -2635,44 +2635,85 @@ on_error: + } + + /*isulad: set env for clean resources */ +-static void clean_resource_set_env(struct lxc_handler *handler) ++static int clean_resource_set_env(struct lxc_handler *handler) + { + const char *name = handler->name; + struct lxc_conf *conf = handler->conf; +- char pidstr[20]; +- +- /* Start of environment variable setup for hooks. */ +- if (name && setenv("LXC_NAME", name, 1)) +- SYSERROR("Failed to set environment variable: LXC_NAME=%s.", name); +- +- if (conf->rcfile && setenv("LXC_CONFIG_FILE", conf->rcfile, 1)) +- SYSERROR("Failed to set environment variable: LXC_CONFIG_FILE=%s.", conf->rcfile); +- +- if (conf->rootfs.mount && setenv("LXC_ROOTFS_MOUNT", conf->rootfs.mount, 1)) +- SYSERROR("Failed to set environment variable: LXC_ROOTFS_MOUNT=%s.", conf->rootfs.mount); ++ char bufstr[PATH_MAX + 1]; ++ int i = 0; ++ int j = 0; ++ int len = 2; //set "LXC_PID" and "LXC_CGNS_AWARE" + +- if (conf->rootfs.path && setenv("LXC_ROOTFS_PATH", conf->rootfs.path, 1)) +- SYSERROR("Failed to set environment variable: LXC_ROOTFS_PATH=%s.", conf->rootfs.path); +- +- if (conf->console.path && setenv("LXC_CONSOLE", conf->console.path, 1)) +- SYSERROR("Failed to set environment variable: LXC_CONSOLE=%s.", conf->console.path); +- +- if (conf->console.log_path && setenv("LXC_CONSOLE_LOGPATH", conf->console.log_path, 1)) +- SYSERROR("Failed to set environment variable: LXC_CONSOLE_LOGPATH=%s.", conf->console.log_path); +- +- if (setenv("LXC_CGNS_AWARE", "1", 1)) +- SYSERROR("Failed to set environment variable LXC_CGNS_AWARE=1."); ++ if (conf == NULL || conf->ocihooks == NULL || conf->ocihooks->poststop_len == 0) { ++ return 0; ++ } + ++ if (name) { ++ len++; ++ } ++ if (conf->rcfile) { ++ len++; ++ } ++ if (conf->rootfs.mount) { ++ len++; ++ } ++ if (conf->rootfs.path) { ++ len++; ++ } ++ if (conf->console.path) { ++ len++; ++ } ++ if (conf->console.log_path) { ++ len++; ++ } ++ if (handler->cgroup_ops->container_cgroup) { ++ len++; ++ } + +- snprintf(pidstr, 20, "%d", handler->pid); +- if (setenv("LXC_PID", pidstr, 1)) +- SYSERROR("Failed to set environment variable: LXC_PID=%s.", pidstr); ++ for (; i < conf->ocihooks->poststop_len; i++) { ++ size_t cap = conf->ocihooks->poststop[i]->env_len; ++ size_t newcap = cap + len + 1; ++ if (lxc_grow_array((void ***)&(conf->ocihooks->poststop[i]->env), &cap, newcap, 1) != 0) { ++ return -1; ++ } ++ j = conf->ocihooks->poststop[i]->env_len; ++ /* Start of environment variable setup for hooks. */ ++ if (name) { ++ snprintf(bufstr, PATH_MAX + 1, "LXC_NAME=%s", name); ++ conf->ocihooks->poststop[i]->env[j++] = strdup(bufstr); ++ } ++ if (conf->rcfile) { ++ snprintf(bufstr, PATH_MAX + 1, "LXC_CONFIG_FILE=%s", conf->rcfile); ++ conf->ocihooks->poststop[i]->env[j++] = strdup(bufstr); ++ } ++ if (conf->rootfs.mount) { ++ snprintf(bufstr, PATH_MAX + 1, "LXC_ROOTFS_MOUNT=%s", conf->rootfs.mount); ++ conf->ocihooks->poststop[i]->env[j++] = strdup(bufstr); ++ } ++ if (conf->rootfs.path) { ++ snprintf(bufstr, PATH_MAX + 1, "LXC_ROOTFS_PATH=%s", conf->rootfs.path); ++ conf->ocihooks->poststop[i]->env[j++] = strdup(bufstr); ++ } ++ if (conf->console.path) { ++ snprintf(bufstr, PATH_MAX + 1, "LXC_CONSOLE=%s", conf->console.path); ++ conf->ocihooks->poststop[i]->env[j++] = strdup(bufstr); ++ } ++ if (conf->console.log_path) { ++ snprintf(bufstr, PATH_MAX + 1, "LXC_CONSOLE_LOGPATH=%s", conf->console.log_path); ++ conf->ocihooks->poststop[i]->env[j++] = strdup(bufstr); ++ } ++ conf->ocihooks->poststop[i]->env[j++] = strdup("LXC_CGNS_AWARE=1"); + +- if (handler->cgroup_ops->container_cgroup) { +- if (setenv("LXC_CGROUP_PATH", handler->cgroup_ops->container_cgroup, 1)) +- SYSERROR("Failed to set environment variable: LXC_CGROUP_PATH=%s.", handler->cgroup_ops->container_cgroup); ++ snprintf(bufstr, PATH_MAX + 1, "LXC_PID=%d", handler->pid); ++ conf->ocihooks->poststop[i]->env[j++] = strdup(bufstr); ++ if (handler->cgroup_ops->container_cgroup) { ++ snprintf(bufstr, PATH_MAX + 1, "LXC_CGROUP_PATH=%s", handler->cgroup_ops->container_cgroup); ++ conf->ocihooks->poststop[i]->env[j++] = strdup(bufstr); ++ } ++ conf->ocihooks->poststop[i]->env_len = j; ++ /* End of environment variable setup for hooks. */ + } +- /* End of environment variable setup for hooks. */ ++ return 0; + } + + /*isulad: do_lxcapi_clean_resource */ +@@ -2690,7 +2731,11 @@ int do_lxcapi_clean_resource(char *name, char *lxcpath, struct lxc_conf *conf, p + goto out; + } + +- clean_resource_set_env(handler); ++ if (clean_resource_set_env(handler) != 0) { ++ ERROR("Failed to set env for poststop hooks"); ++ ret = -1; ++ goto out; ++ } + // if we shared pid namespace with others, should kill all processes within container cgroup + if (handler->conf->ns_share[LXC_NS_PID] != NULL) { + signal_all_processes(handler); +-- +1.8.3.1 + diff --git a/0083-lxc-free-lxc-handler.patch b/0083-lxc-free-lxc-handler.patch new file mode 100644 index 0000000..faf83b4 --- /dev/null +++ b/0083-lxc-free-lxc-handler.patch @@ -0,0 +1,41 @@ +From 6688394517b79adc2ea1b2d65c66cf9af29ba251 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Thu, 11 Apr 2019 20:34:51 +0800 +Subject: [PATCH 083/122] lxc: free lxc-handler + +free handler if failed + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + src/lxc/start.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 87e07d3..f1cd7fa 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -695,6 +695,10 @@ void lxc_zero_handler(struct lxc_handler *handler) + + void lxc_free_handler(struct lxc_handler *handler) + { ++ if (handler == NULL) { ++ return; ++ } ++ + if (handler->pinfd >= 0) + close(handler->pinfd); + +@@ -2761,8 +2765,8 @@ retry: + ret = -1; + } + +- lxc_free_handler(handler); + out: ++ lxc_free_handler(handler); + return ret; + } + +-- +1.8.3.1 + diff --git a/0084-lxc-memory-leak-of-lxc_grow_array.patch b/0084-lxc-memory-leak-of-lxc_grow_array.patch new file mode 100644 index 0000000..5d80c50 --- /dev/null +++ b/0084-lxc-memory-leak-of-lxc_grow_array.patch @@ -0,0 +1,28 @@ +From fd9efbdd077e8cc2a7b825e6f632b5bf4a3473e1 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Thu, 11 Apr 2019 22:36:42 +0800 +Subject: [PATCH 084/122] lxc: memory leak of lxc_grow_array + +fix memory leak of lxc_grow_array + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + src/lxc/string_utils.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/lxc/string_utils.c b/src/lxc/string_utils.c +index 0d7538c..31c4340 100644 +--- a/src/lxc/string_utils.c ++++ b/src/lxc/string_utils.c +@@ -523,6 +523,7 @@ int lxc_grow_array(void ***array, size_t *capacity, size_t new_size, size_t capa + /* first time around, catch some trivial mistakes of the user + * only initializing one of these */ + if (!*array || !*capacity) { ++ free(*array); + *array = NULL; + *capacity = 0; + } +-- +1.8.3.1 + diff --git a/0085-lxc-update-json-file-from-isulad.patch b/0085-lxc-update-json-file-from-isulad.patch new file mode 100644 index 0000000..75d6c2f --- /dev/null +++ b/0085-lxc-update-json-file-from-isulad.patch @@ -0,0 +1,1089 @@ +From c378f6d33dc28604b317eb93f040ce371ceb152c Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Fri, 12 Apr 2019 06:06:12 -0400 +Subject: [PATCH 085/122] lxc: update json file from isulad + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/json/defs.c | 38 +++++----- + src/lxc/json/json_common.c | 160 +++++++++++++++++++-------------------- + src/lxc/json/json_common.h | 2 +- + src/lxc/json/logger_json_file.c | 50 ++++++------ + src/lxc/json/oci_runtime_hooks.c | 3 +- + src/lxc/json/oci_runtime_spec.c | 32 ++++---- + 6 files changed, 142 insertions(+), 143 deletions(-) + +diff --git a/src/lxc/json/defs.c b/src/lxc/json/defs.c +index 38df2f7..e7d9a09 100644 +--- a/src/lxc/json/defs.c ++++ b/src/lxc/json/defs.c +@@ -15,20 +15,20 @@ defs_hook *make_defs_hook(yajl_val tree, struct parser_context *ctx, parser_erro + ret = safe_malloc(sizeof(*ret)); + { + yajl_val val = get_val(tree, "path", yajl_t_string); +- if (val) { ++ if (val != NULL) { + char *str = YAJL_GET_STRING(val); + ret->path = safe_strdup(str ? str : ""); + } + } + { + yajl_val tmp = get_val(tree, "args", yajl_t_array); +- if (tmp && YAJL_GET_ARRAY(tmp)) { ++ if (tmp != NULL && YAJL_GET_ARRAY(tmp) != NULL && YAJL_GET_ARRAY(tmp)->len > 0) { + size_t i; + ret->args_len = YAJL_GET_ARRAY(tmp)->len; + ret->args = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) * sizeof(*ret->args)); + for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) { + yajl_val val = YAJL_GET_ARRAY(tmp)->values[i]; +- if (val) { ++ if (val != NULL) { + char *str = YAJL_GET_STRING(val); + ret->args[i] = safe_strdup(str ? str : ""); + } +@@ -37,13 +37,13 @@ defs_hook *make_defs_hook(yajl_val tree, struct parser_context *ctx, parser_erro + } + { + yajl_val tmp = get_val(tree, "env", yajl_t_array); +- if (tmp && YAJL_GET_ARRAY(tmp)) { ++ if (tmp != NULL && YAJL_GET_ARRAY(tmp) != NULL && YAJL_GET_ARRAY(tmp)->len > 0) { + size_t i; + ret->env_len = YAJL_GET_ARRAY(tmp)->len; + ret->env = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) * sizeof(*ret->env)); + for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) { + yajl_val val = YAJL_GET_ARRAY(tmp)->values[i]; +- if (val) { ++ if (val != NULL) { + char *str = YAJL_GET_STRING(val); + ret->env[i] = safe_strdup(str ? str : ""); + } +@@ -52,7 +52,7 @@ defs_hook *make_defs_hook(yajl_val tree, struct parser_context *ctx, parser_erro + } + { + yajl_val val = get_val(tree, "timeout", yajl_t_number); +- if (val) { ++ if (val != NULL) { + int invalid = common_safe_int(YAJL_GET_NUMBER(val), (int *)&ret->timeout); + if (invalid) { + if (asprintf(err, "Invalid value '%s' with type 'integer' for key 'timeout': %s", YAJL_GET_NUMBER(val), strerror(-invalid)) < 0) +@@ -84,14 +84,14 @@ defs_hook *make_defs_hook(yajl_val tree, struct parser_context *ctx, parser_erro + } + + void free_defs_hook(defs_hook *ptr) { +- if (!ptr) ++ if (ptr == NULL) + return; + free(ptr->path); + ptr->path = NULL; +- if (ptr->args) { ++ if (ptr->args != NULL) { + size_t i; + for (i = 0; i < ptr->args_len; i++) { +- if (ptr->args[i]) { ++ if (ptr->args[i] != NULL) { + free(ptr->args[i]); + ptr->args[i] = NULL; + } +@@ -99,10 +99,10 @@ void free_defs_hook(defs_hook *ptr) { + free(ptr->args); + ptr->args = NULL; + } +- if (ptr->env) { ++ if (ptr->env != NULL) { + size_t i; + for (i = 0; i < ptr->env_len; i++) { +- if (ptr->env[i]) { ++ if (ptr->env[i] != NULL) { + free(ptr->env[i]); + ptr->env[i] = NULL; + } +@@ -119,24 +119,24 @@ yajl_gen_status gen_defs_hook(yajl_gen g, defs_hook *ptr, struct parser_context + stat = reformat_start_map(g); + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); +- if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr && ptr->path)) { ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr != NULL && ptr->path != NULL)) { + char *str = ""; + stat = reformat_map_key(g, "path", strlen("path")); + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); +- if (ptr && ptr->path) { ++ if (ptr != NULL && ptr->path != NULL) { + str = ptr->path; + } + stat = reformat_string(g, str, strlen(str)); + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); + } +- if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr && ptr->args)) { ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) || (ptr != NULL && ptr->args != NULL)) { + size_t len = 0, i; + stat = reformat_map_key(g, "args", strlen("args")); + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); +- if (ptr && ptr->args) { ++ if (ptr != NULL && ptr->args != NULL) { + len = ptr->args_len; + } + if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) +@@ -155,12 +155,12 @@ yajl_gen_status gen_defs_hook(yajl_gen g, defs_hook *ptr, struct parser_context + if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) + yajl_gen_config(g, yajl_gen_beautify, 1); + } +- if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr && ptr->env)) { ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) || (ptr != NULL && ptr->env != NULL)) { + size_t len = 0, i; + stat = reformat_map_key(g, "env", strlen("env")); + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); +- if (ptr && ptr->env) { ++ if (ptr != NULL && ptr->env != NULL) { + len = ptr->env_len; + } + if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) +@@ -179,12 +179,12 @@ yajl_gen_status gen_defs_hook(yajl_gen g, defs_hook *ptr, struct parser_context + if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) + yajl_gen_config(g, yajl_gen_beautify, 1); + } +- if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr && ptr->timeout)) { ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr != NULL && ptr->timeout)) { + long long int num = 0; + stat = reformat_map_key(g, "timeout", strlen("timeout")); + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); +- if (ptr && ptr->timeout) { ++ if (ptr != NULL && ptr->timeout) { + num = (long long int)ptr->timeout; + } + stat = reformat_int(g, num); +diff --git a/src/lxc/json/json_common.c b/src/lxc/json/json_common.c +index e339ab3..54b7b61 100755 +--- a/src/lxc/json/json_common.c ++++ b/src/lxc/json/json_common.c +@@ -111,7 +111,7 @@ int common_safe_double(const char *numstr, double *converted) { + char *err_str = NULL; + double d; + +- if (!numstr) { ++ if (numstr == NULL) { + return -EINVAL; + } + +@@ -121,7 +121,7 @@ int common_safe_double(const char *numstr, double *converted) { + return -errno; + } + +- if (!err_str || err_str == numstr || *err_str != '\0') { ++ if (err_str == NULL || err_str == numstr || *err_str != '\0') { + return -EINVAL; + } + +@@ -133,7 +133,7 @@ int common_safe_uint8(const char *numstr, uint8_t *converted) { + char *err = NULL; + unsigned long int uli; + +- if (!numstr) { ++ if (numstr == NULL) { + return -EINVAL; + } + +@@ -143,7 +143,7 @@ int common_safe_uint8(const char *numstr, uint8_t *converted) { + return -errno; + } + +- if (!err || err == numstr || *err != '\0') { ++ if (err == NULL || err == numstr || *err != '\0') { + return -EINVAL; + } + +@@ -159,7 +159,7 @@ int common_safe_uint16(const char *numstr, uint16_t *converted) { + char *err = NULL; + unsigned long int uli; + +- if (!numstr) { ++ if (numstr == NULL) { + return -EINVAL; + } + +@@ -169,7 +169,7 @@ int common_safe_uint16(const char *numstr, uint16_t *converted) { + return -errno; + } + +- if (!err || err == numstr || *err != '\0') { ++ if (err == NULL || err == numstr || *err != '\0') { + return -EINVAL; + } + +@@ -185,7 +185,7 @@ int common_safe_uint32(const char *numstr, uint32_t *converted) { + char *err = NULL; + unsigned long long int ull; + +- if (!numstr) { ++ if (numstr == NULL) { + return -EINVAL; + } + +@@ -195,7 +195,7 @@ int common_safe_uint32(const char *numstr, uint32_t *converted) { + return -errno; + } + +- if (!err || err == numstr || *err != '\0') { ++ if (err == NULL || err == numstr || *err != '\0') { + return -EINVAL; + } + +@@ -211,7 +211,7 @@ int common_safe_uint64(const char *numstr, uint64_t *converted) { + char *err = NULL; + unsigned long long int ull; + +- if (!numstr) { ++ if (numstr == NULL) { + return -EINVAL; + } + +@@ -221,7 +221,7 @@ int common_safe_uint64(const char *numstr, uint64_t *converted) { + return -errno; + } + +- if (!err || err == numstr || *err != '\0') { ++ if (err == NULL || err == numstr || *err != '\0') { + return -EINVAL; + } + +@@ -233,7 +233,7 @@ int common_safe_uint(const char *numstr, unsigned int *converted) { + char *err = NULL; + unsigned long long int ull; + +- if (!numstr) { ++ if (numstr == NULL) { + return -EINVAL; + } + +@@ -243,7 +243,7 @@ int common_safe_uint(const char *numstr, unsigned int *converted) { + return -errno; + } + +- if (!err || err == numstr || *err != '\0') { ++ if (err == NULL || err == numstr || *err != '\0') { + return -EINVAL; + } + +@@ -259,7 +259,7 @@ int common_safe_int8(const char *numstr, int8_t *converted) { + char *err = NULL; + long int li; + +- if (!numstr) { ++ if (numstr == NULL) { + return -EINVAL; + } + +@@ -269,7 +269,7 @@ int common_safe_int8(const char *numstr, int8_t *converted) { + return -errno; + } + +- if (!err || err == numstr || *err != '\0') { ++ if (err == NULL || err == numstr || *err != '\0') { + return -EINVAL; + } + +@@ -285,7 +285,7 @@ int common_safe_int16(const char *numstr, int16_t *converted) { + char *err = NULL; + long int li; + +- if (!numstr) { ++ if (numstr == NULL) { + return -EINVAL; + } + +@@ -295,7 +295,7 @@ int common_safe_int16(const char *numstr, int16_t *converted) { + return -errno; + } + +- if (!err || err == numstr || *err != '\0') { ++ if (err == NULL || err == numstr || *err != '\0') { + return -EINVAL; + } + +@@ -311,7 +311,7 @@ int common_safe_int32(const char *numstr, int32_t *converted) { + char *err = NULL; + long long int lli; + +- if (!numstr) { ++ if (numstr == NULL) { + return -EINVAL; + } + +@@ -321,7 +321,7 @@ int common_safe_int32(const char *numstr, int32_t *converted) { + return -errno; + } + +- if (!err || err == numstr || *err != '\0') { ++ if (err == NULL || err == numstr || *err != '\0') { + return -EINVAL; + } + +@@ -337,7 +337,7 @@ int common_safe_int64(const char *numstr, int64_t *converted) { + char *err = NULL; + long long int lli; + +- if (!numstr) { ++ if (numstr == NULL) { + return -EINVAL; + } + +@@ -347,7 +347,7 @@ int common_safe_int64(const char *numstr, int64_t *converted) { + return -errno; + } + +- if (!err || err == numstr || *err != '\0') { ++ if (err == NULL || err == numstr || *err != '\0') { + return -EINVAL; + } + +@@ -359,7 +359,7 @@ int common_safe_int(const char *numstr, int *converted) { + char *err = NULL; + long long int lli; + +- if (!numstr) { ++ if (numstr == NULL) { + return -EINVAL; + } + +@@ -369,7 +369,7 @@ int common_safe_int(const char *numstr, int *converted) { + return -errno; + } + +- if (!err || err == numstr || *err != '\0') { ++ if (err == NULL || err == numstr || *err != '\0') { + return -EINVAL; + } + +@@ -385,12 +385,12 @@ char *safe_strdup(const char *src) + { + char *dst = NULL; + +- if (!src) { ++ if (src == NULL) { + return NULL; + } + + dst = strdup(src); +- if (!dst) { ++ if (dst == NULL) { + abort(); + } + +@@ -402,7 +402,7 @@ yajl_gen_status gen_json_map_int_int(void *ctx, json_map_int_int *map, struct pa + yajl_gen_status stat = yajl_gen_status_ok; + yajl_gen g = (yajl_gen) ctx; + size_t len = 0, i = 0; +- if (map) { ++ if (map != NULL) { + len = map->len; + } + if (!len && !(ptx->options & GEN_OPTIONS_SIMPLIFY)) { +@@ -444,7 +444,7 @@ yajl_gen_status gen_json_map_int_int(void *ctx, json_map_int_int *map, struct pa + } + + void free_json_map_int_int(json_map_int_int *map) { +- if (map) { ++ if (map != NULL) { + size_t i; + for (i = 0; i < map->len; i++) { + // No need to free key for type int +@@ -459,7 +459,7 @@ void free_json_map_int_int(json_map_int_int *map) { + } + json_map_int_int *make_json_map_int_int(yajl_val src, struct parser_context *ctx, parser_error *err) { + json_map_int_int *ret = NULL; +- if (src && YAJL_GET_OBJECT(src)) { ++ if (src != NULL && YAJL_GET_OBJECT(src) != NULL) { + size_t i; + size_t len = YAJL_GET_OBJECT(src)->len; + ret = safe_malloc(sizeof(*ret)); +@@ -470,11 +470,11 @@ json_map_int_int *make_json_map_int_int(yajl_val src, struct parser_context *ctx + const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; + yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; + +- if (srckey) { ++ if (srckey != NULL) { + int invalid; + invalid = common_safe_int(srckey, &(ret->keys[i])); + if (invalid) { +- if (!*err && asprintf(err, "Invalid key '%s' with type 'int': %s", srckey, strerror(-invalid)) < 0) { ++ if (*err == NULL && asprintf(err, "Invalid key '%s' with type 'int': %s", srckey, strerror(-invalid)) < 0) { + *(err) = safe_strdup("error allocating memory"); + } + free_json_map_int_int(ret); +@@ -482,10 +482,10 @@ json_map_int_int *make_json_map_int_int(yajl_val src, struct parser_context *ctx + } + } + +- if (srcval) { ++ if (srcval != NULL) { + int invalid; + if (!YAJL_IS_NUMBER(srcval)) { +- if (!*err && asprintf(err, "Invalid value with type 'int' for key '%s'", srckey) < 0) { ++ if (*err == NULL && asprintf(err, "Invalid value with type 'int' for key '%s'", srckey) < 0) { + *(err) = safe_strdup("error allocating memory"); + } + free_json_map_int_int(ret); +@@ -493,7 +493,7 @@ json_map_int_int *make_json_map_int_int(yajl_val src, struct parser_context *ctx + } + invalid = common_safe_int(YAJL_GET_NUMBER(srcval), &(ret->values[i])); + if (invalid) { +- if (!*err && asprintf(err, "Invalid value with type 'int' for key '%s': %s", srckey, strerror(-invalid)) < 0) { ++ if (*err == NULL && asprintf(err, "Invalid value with type 'int' for key '%s': %s", srckey, strerror(-invalid)) < 0) { + *(err) = safe_strdup("error allocating memory"); + } + free_json_map_int_int(ret); +@@ -506,10 +506,10 @@ json_map_int_int *make_json_map_int_int(yajl_val src, struct parser_context *ctx + } + int append_json_map_int_int(json_map_int_int *map, int key, int val) { + size_t len; +- int *keys; +- int *vals; ++ int *keys = NULL; ++ int *vals = NULL; + +- if (!map) { ++ if (map == NULL) { + return -1; + } + +@@ -548,7 +548,7 @@ yajl_gen_status gen_json_map_int_bool(void *ctx, json_map_int_bool *map, struct + yajl_gen_status stat = yajl_gen_status_ok; + yajl_gen g = (yajl_gen) ctx; + size_t len = 0, i = 0; +- if (map) { ++ if (map != NULL) { + len = map->len; + } + if (!len && !(ptx->options & GEN_OPTIONS_SIMPLIFY)) { +@@ -590,7 +590,7 @@ yajl_gen_status gen_json_map_int_bool(void *ctx, json_map_int_bool *map, struct + } + + void free_json_map_int_bool(json_map_int_bool *map) { +- if (map) { ++ if (map != NULL) { + size_t i; + for (i = 0; i < map->len; i++) { + // No need to free key for type int +@@ -605,7 +605,7 @@ void free_json_map_int_bool(json_map_int_bool *map) { + } + json_map_int_bool *make_json_map_int_bool(yajl_val src, struct parser_context *ctx, parser_error *err) { + json_map_int_bool *ret = NULL; +- if (src && YAJL_GET_OBJECT(src)) { ++ if (src != NULL && YAJL_GET_OBJECT(src) != NULL) { + size_t i; + size_t len = YAJL_GET_OBJECT(src)->len; + ret = safe_malloc(sizeof(*ret)); +@@ -616,11 +616,11 @@ json_map_int_bool *make_json_map_int_bool(yajl_val src, struct parser_context *c + const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; + yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; + +- if (srckey) { ++ if (srckey != NULL) { + int invalid; + invalid = common_safe_int(srckey, &(ret->keys[i])); + if (invalid) { +- if (!*err && asprintf(err, "Invalid key '%s' with type 'int': %s", srckey, strerror(-invalid)) < 0) { ++ if (*err == NULL && asprintf(err, "Invalid key '%s' with type 'int': %s", srckey, strerror(-invalid)) < 0) { + *(err) = safe_strdup("error allocating memory"); + } + free_json_map_int_bool(ret); +@@ -628,13 +628,13 @@ json_map_int_bool *make_json_map_int_bool(yajl_val src, struct parser_context *c + } + } + +- if (srcval) { ++ if (srcval != NULL) { + if (YAJL_IS_TRUE(srcval)) { + ret->values[i] = true; + } else if (YAJL_IS_FALSE(srcval)) { + ret->values[i] = false; + } else { +- if (!*err && asprintf(err, "Invalid value with type 'bool' for key '%s'", srckey) < 0) { ++ if (*err == NULL && asprintf(err, "Invalid value with type 'bool' for key '%s'", srckey) < 0) { + *(err) = safe_strdup("error allocating memory"); + } + free_json_map_int_bool(ret); +@@ -647,10 +647,10 @@ json_map_int_bool *make_json_map_int_bool(yajl_val src, struct parser_context *c + } + int append_json_map_int_bool(json_map_int_bool *map, int key, bool val) { + size_t len; +- int *keys; +- bool *vals; ++ int *keys = NULL; ++ bool *vals = NULL; + +- if (!map) { ++ if (map == NULL) { + return -1; + } + +@@ -689,7 +689,7 @@ yajl_gen_status gen_json_map_int_string(void *ctx, json_map_int_string *map, str + yajl_gen_status stat = yajl_gen_status_ok; + yajl_gen g = (yajl_gen) ctx; + size_t len = 0, i = 0; +- if (map) { ++ if (map != NULL) { + len = map->len; + } + if (!len && !(ptx->options & GEN_OPTIONS_SIMPLIFY)) { +@@ -731,7 +731,7 @@ yajl_gen_status gen_json_map_int_string(void *ctx, json_map_int_string *map, str + } + + void free_json_map_int_string(json_map_int_string *map) { +- if (map) { ++ if (map != NULL) { + size_t i; + for (i = 0; i < map->len; i++) { + // No need to free key for type int +@@ -747,7 +747,7 @@ void free_json_map_int_string(json_map_int_string *map) { + } + json_map_int_string *make_json_map_int_string(yajl_val src, struct parser_context *ctx, parser_error *err) { + json_map_int_string *ret = NULL; +- if (src && YAJL_GET_OBJECT(src)) { ++ if (src != NULL && YAJL_GET_OBJECT(src) != NULL) { + size_t i; + size_t len = YAJL_GET_OBJECT(src)->len; + ret = safe_malloc(sizeof(*ret)); +@@ -758,11 +758,11 @@ json_map_int_string *make_json_map_int_string(yajl_val src, struct parser_contex + const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; + yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; + +- if (srckey) { ++ if (srckey != NULL) { + int invalid; + invalid = common_safe_int(srckey, &(ret->keys[i])); + if (invalid) { +- if (!*err && asprintf(err, "Invalid key '%s' with type 'int': %s", srckey, strerror(-invalid)) < 0) { ++ if (*err == NULL && asprintf(err, "Invalid key '%s' with type 'int': %s", srckey, strerror(-invalid)) < 0) { + *(err) = safe_strdup("error allocating memory"); + } + free_json_map_int_string(ret); +@@ -770,9 +770,9 @@ json_map_int_string *make_json_map_int_string(yajl_val src, struct parser_contex + } + } + +- if (srcval) { ++ if (srcval != NULL) { + if (!YAJL_IS_STRING(srcval)) { +- if (!*err && asprintf(err, "Invalid value with type 'string' for key '%s'", srckey) < 0) { ++ if (*err == NULL && asprintf(err, "Invalid value with type 'string' for key '%s'", srckey) < 0) { + *(err) = safe_strdup("error allocating memory"); + } + free_json_map_int_string(ret); +@@ -787,10 +787,10 @@ json_map_int_string *make_json_map_int_string(yajl_val src, struct parser_contex + } + int append_json_map_int_string(json_map_int_string *map, int key, const char *val) { + size_t len; +- int *keys; +- char **vals; ++ int *keys = NULL; ++ char **vals = NULL; + +- if (!map) { ++ if (map == NULL) { + return -1; + } + +@@ -829,7 +829,7 @@ yajl_gen_status gen_json_map_string_int(void *ctx, json_map_string_int *map, str + yajl_gen_status stat = yajl_gen_status_ok; + yajl_gen g = (yajl_gen) ctx; + size_t len = 0, i = 0; +- if (map) { ++ if (map != NULL) { + len = map->len; + } + if (!len && !(ptx->options & GEN_OPTIONS_SIMPLIFY)) { +@@ -862,7 +862,7 @@ yajl_gen_status gen_json_map_string_int(void *ctx, json_map_string_int *map, str + } + + void free_json_map_string_int(json_map_string_int *map) { +- if (map) { ++ if (map != NULL) { + size_t i; + for (i = 0; i < map->len; i++) { + free(map->keys[i]); +@@ -878,7 +878,7 @@ void free_json_map_string_int(json_map_string_int *map) { + } + json_map_string_int *make_json_map_string_int(yajl_val src, struct parser_context *ctx, parser_error *err) { + json_map_string_int *ret = NULL; +- if (src && YAJL_GET_OBJECT(src)) { ++ if (src != NULL && YAJL_GET_OBJECT(src) != NULL) { + size_t i; + size_t len = YAJL_GET_OBJECT(src)->len; + ret = safe_malloc(sizeof(*ret)); +@@ -890,10 +890,10 @@ json_map_string_int *make_json_map_string_int(yajl_val src, struct parser_contex + yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; + ret->keys[i] = safe_strdup(srckey ? srckey : ""); + +- if (srcval) { ++ if (srcval != NULL) { + int invalid; + if (!YAJL_IS_NUMBER(srcval)) { +- if (!*err && asprintf(err, "Invalid value with type 'int' for key '%s'", srckey) < 0) { ++ if (*err == NULL && asprintf(err, "Invalid value with type 'int' for key '%s'", srckey) < 0) { + *(err) = safe_strdup("error allocating memory"); + } + free_json_map_string_int(ret); +@@ -901,7 +901,7 @@ json_map_string_int *make_json_map_string_int(yajl_val src, struct parser_contex + } + invalid = common_safe_int(YAJL_GET_NUMBER(srcval), &(ret->values[i])); + if (invalid) { +- if (!*err && asprintf(err, "Invalid value with type 'int' for key '%s': %s", srckey, strerror(-invalid)) < 0) { ++ if (*err == NULL && asprintf(err, "Invalid value with type 'int' for key '%s': %s", srckey, strerror(-invalid)) < 0) { + *(err) = safe_strdup("error allocating memory"); + } + free_json_map_string_int(ret); +@@ -914,10 +914,10 @@ json_map_string_int *make_json_map_string_int(yajl_val src, struct parser_contex + } + int append_json_map_string_int(json_map_string_int *map, const char *key, int val) { + size_t len; +- char **keys; +- int *vals; ++ char **keys = NULL; ++ int *vals = NULL; + +- if (!map) { ++ if (map == NULL) { + return -1; + } + +@@ -956,7 +956,7 @@ yajl_gen_status gen_json_map_string_bool(void *ctx, json_map_string_bool *map, s + yajl_gen_status stat = yajl_gen_status_ok; + yajl_gen g = (yajl_gen) ctx; + size_t len = 0, i = 0; +- if (map) { ++ if (map != NULL) { + len = map->len; + } + if (!len && !(ptx->options & GEN_OPTIONS_SIMPLIFY)) { +@@ -989,7 +989,7 @@ yajl_gen_status gen_json_map_string_bool(void *ctx, json_map_string_bool *map, s + } + + void free_json_map_string_bool(json_map_string_bool *map) { +- if (map) { ++ if (map != NULL) { + size_t i; + for (i = 0; i < map->len; i++) { + free(map->keys[i]); +@@ -1005,7 +1005,7 @@ void free_json_map_string_bool(json_map_string_bool *map) { + } + json_map_string_bool *make_json_map_string_bool(yajl_val src, struct parser_context *ctx, parser_error *err) { + json_map_string_bool *ret = NULL; +- if (src && YAJL_GET_OBJECT(src)) { ++ if (src != NULL && YAJL_GET_OBJECT(src) != NULL) { + size_t i; + size_t len = YAJL_GET_OBJECT(src)->len; + ret = safe_malloc(sizeof(*ret)); +@@ -1017,13 +1017,13 @@ json_map_string_bool *make_json_map_string_bool(yajl_val src, struct parser_cont + yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; + ret->keys[i] = safe_strdup(srckey ? srckey : ""); + +- if (srcval) { ++ if (srcval != NULL) { + if (YAJL_IS_TRUE(srcval)) { + ret->values[i] = true; + } else if (YAJL_IS_FALSE(srcval)) { + ret->values[i] = false; + } else { +- if (!*err && asprintf(err, "Invalid value with type 'bool' for key '%s'", srckey) < 0) { ++ if (*err == NULL && asprintf(err, "Invalid value with type 'bool' for key '%s'", srckey) < 0) { + *(err) = safe_strdup("error allocating memory"); + } + free_json_map_string_bool(ret); +@@ -1036,10 +1036,10 @@ json_map_string_bool *make_json_map_string_bool(yajl_val src, struct parser_cont + } + int append_json_map_string_bool(json_map_string_bool *map, const char *key, bool val) { + size_t len; +- char **keys; +- bool *vals; ++ char **keys = NULL; ++ bool *vals = NULL; + +- if (!map) { ++ if (map == NULL) { + return -1; + } + +@@ -1078,7 +1078,7 @@ yajl_gen_status gen_json_map_string_string(void *ctx, json_map_string_string *ma + yajl_gen_status stat = yajl_gen_status_ok; + yajl_gen g = (yajl_gen) ctx; + size_t len = 0, i = 0; +- if (map) { ++ if (map != NULL) { + len = map->len; + } + if (!len && !(ptx->options & GEN_OPTIONS_SIMPLIFY)) { +@@ -1111,7 +1111,7 @@ yajl_gen_status gen_json_map_string_string(void *ctx, json_map_string_string *ma + } + + void free_json_map_string_string(json_map_string_string *map) { +- if (map) { ++ if (map != NULL) { + size_t i; + for (i = 0; i < map->len; i++) { + free(map->keys[i]); +@@ -1128,7 +1128,7 @@ void free_json_map_string_string(json_map_string_string *map) { + } + json_map_string_string *make_json_map_string_string(yajl_val src, struct parser_context *ctx, parser_error *err) { + json_map_string_string *ret = NULL; +- if (src && YAJL_GET_OBJECT(src)) { ++ if (src != NULL && YAJL_GET_OBJECT(src) != NULL) { + size_t i; + size_t len = YAJL_GET_OBJECT(src)->len; + ret = safe_malloc(sizeof(*ret)); +@@ -1140,9 +1140,9 @@ json_map_string_string *make_json_map_string_string(yajl_val src, struct parser_ + yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; + ret->keys[i] = safe_strdup(srckey ? srckey : ""); + +- if (srcval) { ++ if (srcval != NULL) { + if (!YAJL_IS_STRING(srcval)) { +- if (!*err && asprintf(err, "Invalid value with type 'string' for key '%s'", srckey) < 0) { ++ if (*err == NULL && asprintf(err, "Invalid value with type 'string' for key '%s'", srckey) < 0) { + *(err) = safe_strdup("error allocating memory"); + } + free_json_map_string_string(ret); +@@ -1157,10 +1157,10 @@ json_map_string_string *make_json_map_string_string(yajl_val src, struct parser_ + } + int append_json_map_string_string(json_map_string_string *map, const char *key, const char *val) { + size_t len, i; +- char **keys; +- char **vals; ++ char **keys = NULL; ++ char **vals = NULL; + +- if (!map) { ++ if (map == NULL) { + return -1; + } + +diff --git a/src/lxc/json/json_common.h b/src/lxc/json/json_common.h +index eb8281c..218a837 100755 +--- a/src/lxc/json/json_common.h ++++ b/src/lxc/json/json_common.h +@@ -27,7 +27,7 @@ extern "C" { + # define GEN_OPTIONS_NOT_VALIDATE_UTF8 0x08 + + #define GEN_SET_ERROR_AND_RETURN(stat, err) { \ +- if (!*(err)) {\ ++ if (*(err) == NULL) {\ + if (asprintf(err, "%s: %s: %d: error generating json, errcode: %d", __FILE__, __func__, __LINE__, stat) < 0) { \ + *(err) = safe_strdup("error allocating memory"); \ + } \ +diff --git a/src/lxc/json/logger_json_file.c b/src/lxc/json/logger_json_file.c +index 4d78103..6433b04 100644 +--- a/src/lxc/json/logger_json_file.c ++++ b/src/lxc/json/logger_json_file.c +@@ -15,32 +15,32 @@ logger_json_file *make_logger_json_file(yajl_val tree, struct parser_context *ct + ret = safe_malloc(sizeof(*ret)); + { + yajl_val tmp = get_val(tree, "log", yajl_t_string); +- if (tmp) { ++ if (tmp != NULL) { + char *str = YAJL_GET_STRING(tmp); + ret->log = (uint8_t *)safe_strdup(str ? str : ""); +- ret->log_len = str ? strlen(str) : 0; ++ ret->log_len = str != NULL ? strlen(str) : 0; + } + } + { + yajl_val val = get_val(tree, "stream", yajl_t_string); +- if (val) { ++ if (val != NULL) { + char *str = YAJL_GET_STRING(val); + ret->stream = safe_strdup(str ? str : ""); + } + } + { + yajl_val val = get_val(tree, "time", yajl_t_string); +- if (val) { ++ if (val != NULL) { + char *str = YAJL_GET_STRING(val); + ret->time = safe_strdup(str ? str : ""); + } + } + { + yajl_val tmp = get_val(tree, "attrs", yajl_t_string); +- if (tmp) { ++ if (tmp != NULL) { + char *str = YAJL_GET_STRING(tmp); + ret->attrs = (uint8_t *)safe_strdup(str ? str : ""); +- ret->attrs_len = str ? strlen(str) : 0; ++ ret->attrs_len = str != NULL ? strlen(str) : 0; + } + } + +@@ -59,7 +59,7 @@ logger_json_file *make_logger_json_file(yajl_val tree, struct parser_context *ct + } + + void free_logger_json_file(logger_json_file *ptr) { +- if (!ptr) ++ if (ptr == NULL) + return; + free(ptr->log); + ptr->log = NULL; +@@ -78,13 +78,13 @@ yajl_gen_status gen_logger_json_file(yajl_gen g, logger_json_file *ptr, struct p + stat = reformat_start_map(g); + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); +- if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) || (ptr && ptr->log && ptr->log_len)) { ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) || (ptr != NULL && ptr->log != NULL && ptr->log_len)) { + const char *str = ""; + size_t len = 0; + stat = reformat_map_key(g, "log", strlen("log")); + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); +- if (ptr && ptr->log) { ++ if (ptr != NULL && ptr->log != NULL) { + str = (const char *)ptr->log; + len = ptr->log_len; + } +@@ -92,37 +92,37 @@ yajl_gen_status gen_logger_json_file(yajl_gen g, logger_json_file *ptr, struct p + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); + } +- if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr && ptr->stream)) { ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr != NULL && ptr->stream != NULL)) { + char *str = ""; + stat = reformat_map_key(g, "stream", strlen("stream")); + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); +- if (ptr && ptr->stream) { ++ if (ptr != NULL && ptr->stream != NULL) { + str = ptr->stream; + } + stat = reformat_string(g, str, strlen(str)); + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); + } +- if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr && ptr->time)) { ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr != NULL && ptr->time != NULL)) { + char *str = ""; + stat = reformat_map_key(g, "time", strlen("time")); + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); +- if (ptr && ptr->time) { ++ if (ptr != NULL && ptr->time != NULL) { + str = ptr->time; + } + stat = reformat_string(g, str, strlen(str)); + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); + } +- if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) || (ptr && ptr->attrs && ptr->attrs_len)) { ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) || (ptr != NULL && ptr->attrs != NULL && ptr->attrs_len)) { + const char *str = ""; + size_t len = 0; + stat = reformat_map_key(g, "attrs", strlen("attrs")); + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); +- if (ptr && ptr->attrs) { ++ if (ptr != NULL && ptr->attrs != NULL) { + str = (const char *)ptr->attrs; + len = ptr->attrs_len; + } +@@ -140,9 +140,9 @@ yajl_gen_status gen_logger_json_file(yajl_gen g, logger_json_file *ptr, struct p + logger_json_file *logger_json_file_parse_file(const char *filename, struct parser_context *ctx, parser_error *err) { + logger_json_file *ptr; + size_t filesize; +- char *content; ++ char *content = NULL; + +- if (!filename || !err) ++ if (filename == NULL || err == NULL) + return NULL; + + *err = NULL; +@@ -160,9 +160,9 @@ logger_json_file *logger_json_file_parse_file(const char *filename, struct parse + logger_json_file *logger_json_file_parse_file_stream(FILE *stream, struct parser_context *ctx, parser_error *err) { + logger_json_file *ptr; + size_t filesize; +- char *content ; ++ char *content = NULL ; + +- if (!stream || !err) ++ if (stream == NULL || err == NULL) + return NULL; + + *err = NULL; +@@ -182,11 +182,11 @@ logger_json_file *logger_json_file_parse_data(const char *jsondata, struct parse + char errbuf[1024]; + struct parser_context tmp_ctx; + +- if (!jsondata || !err) ++ if (jsondata == NULL || err == NULL) + return NULL; + + *err = NULL; +- if (!ctx) { ++ if (ctx == NULL) { + ctx = &tmp_ctx; + memset(&tmp_ctx, 0, sizeof(tmp_ctx)); + } +@@ -207,11 +207,11 @@ char *logger_json_file_generate_json(logger_json_file *ptr, struct parser_contex + char *json_buf = NULL; + size_t gen_len = 0; + +- if (!ptr || !err) ++ if (ptr == NULL || err == NULL) + return NULL; + + *err = NULL; +- if (!ctx) { ++ if (ctx == NULL) { + ctx = &tmp_ctx; + memset(&tmp_ctx, 0, sizeof(tmp_ctx)); + } +@@ -221,12 +221,12 @@ char *logger_json_file_generate_json(logger_json_file *ptr, struct parser_contex + goto out; + } + if (yajl_gen_status_ok != gen_logger_json_file(g, ptr, ctx, err)) { +- if (!*err) ++ if (*err == NULL) + *err = safe_strdup("Failed to generate json"); + goto free_out; + } + yajl_gen_get_buf(g, &gen_buf, &gen_len); +- if (!gen_buf) { ++ if (gen_buf == NULL) { + *err = safe_strdup("Error to get generated json"); + goto free_out; + } +diff --git a/src/lxc/json/oci_runtime_hooks.c b/src/lxc/json/oci_runtime_hooks.c +index 3aa134e..43ff8d7 100644 +--- a/src/lxc/json/oci_runtime_hooks.c ++++ b/src/lxc/json/oci_runtime_hooks.c +@@ -46,8 +46,7 @@ oci_runtime_spec_hooks *oci_runtime_spec_hooks_parse_file(const char *filename, + } + return NULL; + } +- oci_runtime_spec_hooks *ptr = make_oci_runtime_spec_hooks(tree, ctx, +- err); ++ oci_runtime_spec_hooks *ptr = make_oci_runtime_spec_hooks(tree, ctx, err); + yajl_tree_free(tree); + return ptr; + } +diff --git a/src/lxc/json/oci_runtime_spec.c b/src/lxc/json/oci_runtime_spec.c +index 1f6073c..4ccb635 100644 +--- a/src/lxc/json/oci_runtime_spec.c ++++ b/src/lxc/json/oci_runtime_spec.c +@@ -15,7 +15,7 @@ oci_runtime_spec_hooks *make_oci_runtime_spec_hooks(yajl_val tree, struct parser + ret = safe_malloc(sizeof(*ret)); + { + yajl_val tmp = get_val(tree, "prestart", yajl_t_array); +- if (tmp && YAJL_GET_ARRAY(tmp)) { ++ if (tmp != NULL && YAJL_GET_ARRAY(tmp) != NULL && YAJL_GET_ARRAY(tmp)->len > 0) { + size_t i; + ret->prestart_len = YAJL_GET_ARRAY(tmp)->len; + ret->prestart = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) * sizeof(*ret->prestart)); +@@ -31,7 +31,7 @@ oci_runtime_spec_hooks *make_oci_runtime_spec_hooks(yajl_val tree, struct parser + } + { + yajl_val tmp = get_val(tree, "poststart", yajl_t_array); +- if (tmp && YAJL_GET_ARRAY(tmp)) { ++ if (tmp != NULL && YAJL_GET_ARRAY(tmp) != NULL && YAJL_GET_ARRAY(tmp)->len > 0) { + size_t i; + ret->poststart_len = YAJL_GET_ARRAY(tmp)->len; + ret->poststart = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) * sizeof(*ret->poststart)); +@@ -47,7 +47,7 @@ oci_runtime_spec_hooks *make_oci_runtime_spec_hooks(yajl_val tree, struct parser + } + { + yajl_val tmp = get_val(tree, "poststop", yajl_t_array); +- if (tmp && YAJL_GET_ARRAY(tmp)) { ++ if (tmp != NULL && YAJL_GET_ARRAY(tmp) != NULL && YAJL_GET_ARRAY(tmp)->len > 0) { + size_t i; + ret->poststop_len = YAJL_GET_ARRAY(tmp)->len; + ret->poststop = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) * sizeof(*ret->poststop)); +@@ -76,32 +76,32 @@ oci_runtime_spec_hooks *make_oci_runtime_spec_hooks(yajl_val tree, struct parser + } + + void free_oci_runtime_spec_hooks(oci_runtime_spec_hooks *ptr) { +- if (!ptr) ++ if (ptr == NULL) + return; +- if (ptr->prestart) { ++ if (ptr->prestart != NULL) { + size_t i; + for (i = 0; i < ptr->prestart_len; i++) +- if (ptr->prestart[i]) { ++ if (ptr->prestart[i] != NULL) { + free_defs_hook(ptr->prestart[i]); + ptr->prestart[i] = NULL; + } + free(ptr->prestart); + ptr->prestart = NULL; + } +- if (ptr->poststart) { ++ if (ptr->poststart != NULL) { + size_t i; + for (i = 0; i < ptr->poststart_len; i++) +- if (ptr->poststart[i]) { ++ if (ptr->poststart[i] != NULL) { + free_defs_hook(ptr->poststart[i]); + ptr->poststart[i] = NULL; + } + free(ptr->poststart); + ptr->poststart = NULL; + } +- if (ptr->poststop) { ++ if (ptr->poststop != NULL) { + size_t i; + for (i = 0; i < ptr->poststop_len; i++) +- if (ptr->poststop[i]) { ++ if (ptr->poststop[i] != NULL) { + free_defs_hook(ptr->poststop[i]); + ptr->poststop[i] = NULL; + } +@@ -117,12 +117,12 @@ yajl_gen_status gen_oci_runtime_spec_hooks(yajl_gen g, oci_runtime_spec_hooks *p + stat = reformat_start_map(g); + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); +- if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr && ptr->prestart)) { ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr != NULL && ptr->prestart != NULL)) { + size_t len = 0, i; + stat = reformat_map_key(g, "prestart", strlen("prestart")); + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); +- if (ptr && ptr->prestart) { ++ if (ptr != NULL && ptr->prestart != NULL) { + len = ptr->prestart_len; + } + if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) +@@ -141,12 +141,12 @@ yajl_gen_status gen_oci_runtime_spec_hooks(yajl_gen g, oci_runtime_spec_hooks *p + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); + } +- if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr && ptr->poststart)) { ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr != NULL && ptr->poststart != NULL)) { + size_t len = 0, i; + stat = reformat_map_key(g, "poststart", strlen("poststart")); + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); +- if (ptr && ptr->poststart) { ++ if (ptr != NULL && ptr->poststart != NULL) { + len = ptr->poststart_len; + } + if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) +@@ -165,12 +165,12 @@ yajl_gen_status gen_oci_runtime_spec_hooks(yajl_gen g, oci_runtime_spec_hooks *p + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); + } +- if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr && ptr->poststop)) { ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr != NULL && ptr->poststop != NULL)) { + size_t len = 0, i; + stat = reformat_map_key(g, "poststop", strlen("poststop")); + if (yajl_gen_status_ok != stat) + GEN_SET_ERROR_AND_RETURN(stat, err); +- if (ptr && ptr->poststop) { ++ if (ptr != NULL && ptr->poststop != NULL) { + len = ptr->poststop_len; + } + if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) +-- +1.8.3.1 + diff --git a/0086-confile-add-support-systemd.patch b/0086-confile-add-support-systemd.patch new file mode 100644 index 0000000..9bb4620 --- /dev/null +++ b/0086-confile-add-support-systemd.patch @@ -0,0 +1,150 @@ +From 196510dd784d195dfc131b56249a5aac0b9eab54 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Sat, 20 Apr 2019 22:40:18 +0800 +Subject: [PATCH 086/122] confile: add support systemd + +lxc.isulad.systemd=true remount systemd cgroup path to rw + +Signed-off-by: zhangsong +Signed-off-by: LiFeng +--- + src/lxc/cgroups/cgfsng.c | 16 ++++++++++++++++ + src/lxc/conf.c | 1 + + src/lxc/conf.h | 1 + + src/lxc/confile.c | 30 ++++++++++++++++++++++++++++++ + 4 files changed, 48 insertions(+) + +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index cc08737..b1f56b0 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -1567,6 +1567,7 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, + { + int i, ret; + char *tmpfspath = NULL; ++ char *systemdpath = NULL; + bool has_cgns = false, retval = false, wants_force_mount = false; + char **merged = NULL; + +@@ -1711,10 +1712,25 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, + goto on_error; + } + } ++ ++ // isulad: remount /sys/fs/cgroup/systemd to readwrite for system container ++ if (handler->conf->systemd != NULL && strcmp(handler->conf->systemd, "true") == 0) { ++ systemdpath = must_make_path(root, "/sys/fs/cgroup/systemd", NULL); ++ ret = mount(systemdpath, systemdpath, "bind", ++ MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_RELATIME|MS_BIND|MS_REMOUNT, NULL); ++ if (ret < 0) { ++ SYSERROR("Failed to remount /sys/fs/cgroup/systemd."); ++ goto on_error; ++ } ++ } ++ + retval = true; + + on_error: + free(tmpfspath); ++ if (systemdpath != NULL) { ++ free(systemdpath); ++ } + lxc_free_array((void **)merged, free); + return retval; + } +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 20eb840..8cdccf1 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -5320,6 +5320,7 @@ void lxc_conf_free(struct lxc_conf *conf) + if (conf->exit_fd != -1) + close(conf->exit_fd); + free(conf->errmsg); ++ free(conf->systemd); + lxc_close_error_pipe(conf->errpipe); + /* isulad add end */ + free(conf); +diff --git a/src/lxc/conf.h b/src/lxc/conf.h +index 11cf596..fb3c156 100644 +--- a/src/lxc/conf.h ++++ b/src/lxc/conf.h +@@ -430,6 +430,7 @@ struct lxc_conf { + char *errmsg; /* record error messages */ + int errpipe[2];//pipdfd for get error message of child or grandchild process. + mode_t umask; //umask value ++ char *systemd; //systemd value + /* isulad add end */ + }; + +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index 60e6c46..93936cc 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -157,6 +157,7 @@ lxc_config_define(init_args); + lxc_config_define(init_groups); + lxc_config_define(populate_device); + lxc_config_define(umask); ++lxc_config_define(systemd); + /*isulad add end*/ + + +@@ -251,6 +252,7 @@ static struct lxc_config_t config_jump_table[] = { + { "lxc.isulad.rootfs.maskedpaths", set_config_rootfs_masked_paths, get_config_rootfs_masked_paths, clr_config_rootfs_masked_paths, }, + { "lxc.isulad.rootfs.ropaths", set_config_rootfs_ro_paths, get_config_rootfs_ro_paths, clr_config_rootfs_ro_paths, }, + { "lxc.isulad.umask", set_config_umask, get_config_umask, clr_config_umask, }, ++ { "lxc.isulad.systemd", set_config_systemd, get_config_systemd, clr_config_systemd, }, + /*isulad add end*/ + }; + +@@ -2433,6 +2435,18 @@ static int set_config_umask(const char *key, const char *value, + } + } + ++/* isulad: set config for systemd */ ++static int set_config_systemd(const char *key, const char *value, ++ struct lxc_conf *lxc_conf, void *data) ++{ ++ if (lxc_config_value_empty(value)) { ++ ERROR("Empty umask"); ++ return -1; ++ } ++ lxc_conf->systemd = strdup(value); ++ return 0; ++} ++ + struct parse_line_conf { + struct lxc_conf *conf; + bool from_include; +@@ -3210,6 +3224,13 @@ static int get_config_umask(const char *key, char *retv, int inlen, + return lxc_get_conf_size_t(c, retv, inlen, c->umask); + } + ++/* isulad add: get systemd value*/ ++static int get_config_systemd(const char *key, char *retv, int inlen, ++ struct lxc_conf *c, void *data) ++{ ++ return lxc_get_conf_str(retv, inlen, c->systemd); ++} ++ + static int get_config_tty_dir(const char *key, char *retv, int inlen, + struct lxc_conf *c, void *data) + { +@@ -4491,6 +4512,15 @@ static inline int clr_config_umask(const char *key, struct lxc_conf *c, + return 0; + } + ++/* isulad add: clear systemd value */ ++static inline int clr_config_systemd(const char *key, struct lxc_conf *c, ++ void *data) ++{ ++ free(c->systemd); ++ c->systemd = NULL; ++ return 0; ++} ++ + static int get_config_includefiles(const char *key, char *retv, int inlen, + struct lxc_conf *c, void *data) + { +-- +1.8.3.1 + diff --git a/0087-lxc-adapt-to-spec-of-oci-hook.patch b/0087-lxc-adapt-to-spec-of-oci-hook.patch new file mode 100644 index 0000000..bcf1ab8 --- /dev/null +++ b/0087-lxc-adapt-to-spec-of-oci-hook.patch @@ -0,0 +1,41 @@ +From 917a306cfab2e0cef3a666b23bf7c788bcf466d3 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Wed, 24 Apr 2019 22:22:55 +0800 +Subject: [PATCH 087/122] lxc: adapt to spec of oci hook + +poststart failed do not cause run failed + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 8cdccf1..a1d77eb 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4782,6 +4782,7 @@ static int run_oci_hooks(const char *name, const char *lxcpath, struct lxc_conf + struct oci_hook_conf work_conf = {0}; + size_t i; + int ret = 0; ++ int nret = 0; + char *rootpath; + + if (!lc) { +@@ -4811,9 +4812,9 @@ static int run_oci_hooks(const char *name, const char *lxcpath, struct lxc_conf + case OCI_HOOK_POSTSTART: + for (i = 0; i < lc->ocihooks->poststart_len; i++) { + work_conf.ocihook = lc->ocihooks->poststart[i]; +- ret = run_ocihook_script_argv(name, "lxc", &work_conf, lxcpath, rootpath); +- if (ret != 0) +- break; ++ nret = run_ocihook_script_argv(name, "lxc", &work_conf, lxcpath, rootpath); ++ if (nret != 0) ++ WARN("running poststart hook %d failed, ContainerId: %s", i, name); + } + break; + case OCI_HOOK_POSTSTOP: +-- +1.8.3.1 + diff --git a/0088-fix-lxc-build-error.patch b/0088-fix-lxc-build-error.patch new file mode 100644 index 0000000..57b617f --- /dev/null +++ b/0088-fix-lxc-build-error.patch @@ -0,0 +1,29 @@ +From f6ddc6eb341b7eca5616be1ffd6b403db1b83b11 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Thu, 25 Apr 2019 10:12:16 +0800 +Subject: [PATCH 088/122] fix lxc build error + +cause by invalid print format + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index a1d77eb..14d5d80 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4814,7 +4814,7 @@ static int run_oci_hooks(const char *name, const char *lxcpath, struct lxc_conf + work_conf.ocihook = lc->ocihooks->poststart[i]; + nret = run_ocihook_script_argv(name, "lxc", &work_conf, lxcpath, rootpath); + if (nret != 0) +- WARN("running poststart hook %d failed, ContainerId: %s", i, name); ++ WARN("running poststart hook %ld failed, ContainerId: %s", i, name); + } + break; + case OCI_HOOK_POSTSTOP: +-- +1.8.3.1 + diff --git a/0089-lxc-add-get-container-processes-pids-func.patch b/0089-lxc-add-get-container-processes-pids-func.patch new file mode 100644 index 0000000..db70b9b --- /dev/null +++ b/0089-lxc-add-get-container-processes-pids-func.patch @@ -0,0 +1,177 @@ +From 4241f51abad788017ca5a0da5946ccc2672bdc3b Mon Sep 17 00:00:00 2001 +From: maoweiyong +Date: Tue, 23 Apr 2019 12:12:55 +0800 +Subject: [PATCH 089/122] lxc:add get container processes pids func + +Signed-off-by: maoweiyong +--- + src/lxc/lxccontainer.c | 18 ++++++++++++ + src/lxc/lxccontainer.h | 11 ++++++++ + src/lxc/start.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++ + src/lxc/start.h | 2 ++ + 4 files changed, 107 insertions(+) + +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index 8a3724c..fa13e52 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -5212,6 +5212,23 @@ static bool do_lxcapi_clean_container_resource(struct lxc_container *c, pid_t pi + + WRAP_API_1(bool, lxcapi_clean_container_resource, pid_t) + ++/* isulad get coantainer pids */ ++static bool do_lxcapi_get_container_pids(struct lxc_container *c, pid_t **pids,size_t *pids_len) ++{ ++ int ret; ++ ++ if (!c) ++ return false; ++ ++ ret = do_lxcapi_get_pids(c->name, c->config_path, c->lxc_conf, pids,pids_len); ++ if (ret) ++ ERROR("Failed to get container %s pids", c->name); ++ return ret == 0; ++ ++} ++ ++WRAP_API_2(bool, lxcapi_get_container_pids, pid_t **,size_t *) ++ + /* isulad add clean resources */ + static bool do_lxcapi_add_terminal_fifo(struct lxc_container *c, const char *in_fifo, const char *out_fifo, const char *err_fifo) + { +@@ -5373,6 +5390,7 @@ static struct lxc_container *do_lxc_container_new(const char *name, const char * + c->set_start_timeout = lxcapi_set_start_timeout; + c->clean_container_resource = lxcapi_clean_container_resource; + c->add_terminal_fifos = lxcapi_add_terminal_fifo; ++ c->get_container_pids = lxcapi_get_container_pids; + /* isulad add end */ + return c; + +diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h +index c3368e4..608f815 100644 +--- a/src/lxc/lxccontainer.h ++++ b/src/lxc/lxccontainer.h +@@ -947,6 +947,17 @@ struct lxc_container { + * \return \c true on success, else \c false. + */ + bool (*clean_container_resource) (struct lxc_container *c, pid_t pid); ++ ++ /*! isulad add ++ * \brief An API call to get container pids ++ * ++ * \param c Container. ++ * \param pids Value of container pids. ++ * \param pids_len Value of container pids len. ++ * \param pid Value of container pid. ++ * \return \c true on success, else \c false. ++ */ ++ bool (*get_container_pids)(struct lxc_container *c,pid_t **pids,size_t *pids_len); + }; + + /*! +diff --git a/src/lxc/start.c b/src/lxc/start.c +index f1cd7fa..2b0d43e 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -2638,6 +2638,55 @@ on_error: + return NULL; + } + ++/*isulad: init handler for clean */ ++static struct lxc_handler *lxc_init_pids_handler(char *name, char *lxcpath, struct lxc_conf *conf) ++{ ++ int i; ++ struct lxc_handler *handler; ++ ++ handler = malloc(sizeof(*handler)); ++ if (!handler) ++ return NULL; ++ ++ memset(handler, 0, sizeof(*handler)); ++ ++ /* Note that am_guest_unpriv() checks the effective uid. We ++ * probably don't care if we are real root only if we are running ++ * as root so this should be fine. ++ */ ++ handler->am_root = !am_guest_unpriv(); ++ handler->data_sock[0] = handler->data_sock[1] = -1; ++ handler->conf = conf; ++ handler->lxcpath = lxcpath; ++ handler->pinfd = -1; ++ handler->sigfd = -EBADF; ++ handler->init_died = false; ++ handler->state_socket_pair[0] = handler->state_socket_pair[1] = -1; ++ if (handler->conf->reboot == REBOOT_NONE) ++ lxc_list_init(&handler->conf->state_clients); ++ ++ for (i = 0; i < LXC_NS_MAX; i++) ++ handler->nsfd[i] = -1; ++ ++ handler->name = name; ++ handler->exit_code = -1; /* isulad: record exit code of container */ ++ ++ handler->cgroup_ops = cgroup_init(handler); ++ if (!handler->cgroup_ops) { ++ ERROR("Failed to initialize cgroup driver"); ++ goto on_error; ++ } ++ ++ INFO("Container \"%s\" 's clean handler is initialized.", name); ++ ++ return handler; ++ ++on_error: ++ lxc_free_handler(handler); ++ ++ return NULL; ++} ++ + /*isulad: set env for clean resources */ + static int clean_resource_set_env(struct lxc_handler *handler) + { +@@ -2770,3 +2819,30 @@ out: + return ret; + } + ++/*isulad: do_lxcapi_get_pids */ ++int do_lxcapi_get_pids(char *name, char *lxcpath, struct lxc_conf *conf, pid_t **pids,size_t *pids_len) ++{ ++ int ret = 0; ++ struct lxc_handler *handler = NULL; ++ int retry_count = 0; ++ int max_retry = 10; ++ struct cgroup_ops *cg_ops = NULL; ++ ++ handler = lxc_init_pids_handler(name, lxcpath, conf); ++ if (!handler) { ++ ERROR("Failed to init container %s clean handler", name); ++ ret = -1; ++ goto out; ++ } ++ ++ cg_ops = handler->cgroup_ops; ++ ret = get_all_pids(cg_ops, pids, pids_len); ++ if (ret < 0) { ++ WARN("failed to get all pids"); ++ } ++ ++out: ++ lxc_free_handler(handler); ++ return ret; ++} ++ +diff --git a/src/lxc/start.h b/src/lxc/start.h +index 0298991..20e667c 100644 +--- a/src/lxc/start.h ++++ b/src/lxc/start.h +@@ -188,5 +188,7 @@ extern int resolve_clone_flags(struct lxc_handler *handler); + /*isulad: do_lxcapi_clean_resource */ + extern int do_lxcapi_clean_resource(char *name, char *lxcpath, struct lxc_conf *conf, pid_t pid); + ++/*isulad: do_lxcapi_get_pids */ ++extern int do_lxcapi_get_pids(char *name, char *lxcpath, struct lxc_conf *conf, pid_t **pids,size_t *pids_len); + + #endif +-- +1.8.3.1 + diff --git a/0090-lxc-remove-unused-variable.patch b/0090-lxc-remove-unused-variable.patch new file mode 100644 index 0000000..6213607 --- /dev/null +++ b/0090-lxc-remove-unused-variable.patch @@ -0,0 +1,26 @@ +From 83136d88470202915844a0bb0413af70fcd18efc Mon Sep 17 00:00:00 2001 +From: maoweiyong +Date: Thu, 25 Apr 2019 21:21:12 +0800 +Subject: [PATCH 090/122] lxc: remove unused variable + +Signed-off-by: maoweiyong +--- + src/lxc/start.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 2b0d43e..3657d4e 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -2824,8 +2824,6 @@ int do_lxcapi_get_pids(char *name, char *lxcpath, struct lxc_conf *conf, pid_t * + { + int ret = 0; + struct lxc_handler *handler = NULL; +- int retry_count = 0; +- int max_retry = 10; + struct cgroup_ops *cg_ops = NULL; + + handler = lxc_init_pids_handler(name, lxcpath, conf); +-- +1.8.3.1 + diff --git a/0091-lxc-support-namespaced-kernel-params-can-be-changed-.patch b/0091-lxc-support-namespaced-kernel-params-can-be-changed-.patch new file mode 100644 index 0000000..7536a3c --- /dev/null +++ b/0091-lxc-support-namespaced-kernel-params-can-be-changed-.patch @@ -0,0 +1,118 @@ +From 639248d8b9bcbaabe789f7d12f28191a4e65752f Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Fri, 26 Apr 2019 07:13:53 +0800 +Subject: [PATCH 091/122] lxc: support namespaced kernel params can be changed + in system container + +support namespaced kernel params can be changed in system container + +Signed-off-by: yangchenliang +--- + src/lxc/conf.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 77 insertions(+) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 14d5d80..0f227aa 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -1516,6 +1516,66 @@ error: + return false; + } + ++static bool remount_readwrite(const char *path) ++{ ++ int ret, i; ++ ++ if (!path) ++ return true; ++ ++ for (i = 0; i < 5; i++) { ++ ret = mount("", path, "", MS_REMOUNT, ""); ++ if (ret < 0 && errno != ENOENT) { ++ if (errno == EINVAL) { ++ // Probably not a mountpoint, use bind-mount ++ ret = mount(path, path, "", MS_BIND, ""); ++ if (ret < 0) ++ goto on_error; ++ ret = mount(path, path, "", MS_BIND | MS_REMOUNT | MS_REC | \ ++ MS_NOEXEC | MS_NOSUID | MS_NODEV, ""); ++ if (ret < 0) ++ goto on_error; ++ } else if (errno == EBUSY) { ++ DEBUG("Try to mount \"%s\" to readonly after 100ms.", path); ++ usleep(100 * 1000); ++ continue; ++ } else { ++ goto on_error; ++ } ++ } ++ return true; ++ } ++ ++on_error: ++ SYSERROR("Unable to mount \"%s\" to readwrite", path); ++ return false; ++} ++ ++static int remount_proc_sys_mount_entries(struct lxc_list *mount_list) ++{ ++ char buf[4096]; ++ FILE *file; ++ struct mntent mntent; ++ ++ file = make_anonymous_mount_file(mount_list); ++ if (!file) ++ return -1; ++ ++ while (getmntent_r(file, &mntent, buf, sizeof(buf))) { ++ if (strstr(mntent.mnt_dir, "proc/sys") == NULL) { ++ continue; ++ } ++ ++ if (!remount_readwrite((const char*)mntent.mnt_dir)) { ++ fclose(file); ++ return -1; ++ } ++ } ++ ++ fclose(file); ++ return 0; ++} ++ + // remount_readonly will bind over the top of an existing path and ensure that it is read-only. + static bool remount_readonly(const char *path) + { +@@ -2699,6 +2759,13 @@ static int mount_file_entries(const struct lxc_conf *conf, + int ret = -1; + + while (getmntent_r(file, &mntent, buf, sizeof(buf))) { ++ //isulad, system contaienr, skip "proc/sys/xxx" path ++ if (conf->systemd != NULL && strcmp(conf->systemd, "true") == 0) { ++ if (strstr(mntent.mnt_dir, "proc/sys") != NULL) { ++ continue; ++ } ++ } ++ + /* Note: Workaround for volume file path with space*/ + mntent.mnt_fsname = lxc_string_replace(SPACE_MAGIC_STR, " ", mntent.mnt_fsname); + if(!mntent.mnt_fsname) { +@@ -4254,6 +4321,16 @@ int lxc_setup(struct lxc_handler *handler) + } + } + ++ //isulad: system container, remount /proc/sys/xxx by mount_list ++ if (lxc_conf->systemd != NULL && strcmp(lxc_conf->systemd, "true") == 0) { ++ if (!lxc_list_empty(&lxc_conf->mount_list)) { ++ if (remount_proc_sys_mount_entries(&lxc_conf->mount_list)) { ++ ERROR("failed to remount /proc/sys"); ++ goto on_error; ++ } ++ } ++ } ++ + if (!lxc_list_empty(&lxc_conf->keepcaps)) { + if (!lxc_list_empty(&lxc_conf->caps)) { + ERROR("Container requests lxc.cap.drop and " +-- +1.8.3.1 + diff --git a/0092-lxc-add-output-error-when-create-unified-cgroup.patch b/0092-lxc-add-output-error-when-create-unified-cgroup.patch new file mode 100644 index 0000000..1787d8b --- /dev/null +++ b/0092-lxc-add-output-error-when-create-unified-cgroup.patch @@ -0,0 +1,45 @@ +From 548054179d5e5b43368491822ebed803c9a03a36 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Mon, 29 Apr 2019 04:13:52 -0400 +Subject: [PATCH 092/122] lxc: add output error when create unified cgroup + +Signed-off-by: LiFeng +--- + src/lxc/cgroups/cgfsng.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index b1f56b0..2bf142f 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -1132,7 +1132,7 @@ __cgfsng_ops static bool cgfsng_payload_destroy(struct cgroup_ops *ops, + return true; + } + +-static bool cg_unified_create_cgroup(struct hierarchy *h, char *cgname) ++static bool cg_unified_create_cgroup(struct hierarchy *h, char *cgname, int errfd) + { + size_t i, parts_len; + char **it; +@@ -1187,6 +1187,9 @@ static bool cg_unified_create_cgroup(struct hierarchy *h, char *cgname) + if (ret < 0) { + SYSERROR("Could not enable \"%s\" controllers in the " + "unified cgroup \"%s\"", add_controllers, cgroup); ++ lxc_write_error_message(errfd, "%s:%d: Could not enable \"%s\" controllers in the " ++ "unified cgroup: \"%s\"", ++ __FILE__, __LINE__, add_controllers, strerror(errno)); + goto on_error; + } + } +@@ -1260,7 +1263,7 @@ static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname, int err + return false; + } + +- return cg_unified_create_cgroup(h, cgname); ++ return cg_unified_create_cgroup(h, cgname, errfd); + } + + /* isulad: create hierarchies path, if fail, return the error */ +-- +1.8.3.1 + diff --git a/0093-optimize-isulad_kit-operator.patch b/0093-optimize-isulad_kit-operator.patch new file mode 100644 index 0000000..eded542 --- /dev/null +++ b/0093-optimize-isulad_kit-operator.patch @@ -0,0 +1,424 @@ +From d37fe422dc56c4904c138fdcb2c721a3cca2f0a8 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Thu, 2 May 2019 11:23:50 +0800 +Subject: [PATCH 093/122] optimize isulad_kit operator + +parse group add start container + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + src/lxc/Makefile.am | 2 + + src/lxc/json/container_start_generate_config.c | 245 +++++++++++++++++++++++++ + src/lxc/json/container_start_generate_config.h | 43 +++++ + src/lxc/tools/lxc_start.c | 58 ++++++ + 4 files changed, 348 insertions(+) + create mode 100644 src/lxc/json/container_start_generate_config.c + create mode 100644 src/lxc/json/container_start_generate_config.h + +diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am +index 698f8f9..4ec2081 100644 +--- a/src/lxc/Makefile.am ++++ b/src/lxc/Makefile.am +@@ -45,6 +45,7 @@ noinst_HEADERS = attach.h \ + storage/storage_utils.h \ + json/defs.h \ + json/json_common.h \ ++ json/container_start_generate_config.h \ + json/oci_runtime_hooks.h \ + json/oci_runtime_spec.h \ + json/logger_json_file.h \ +@@ -152,6 +153,7 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \ + json/oci_runtime_hooks.c json/oci_runtime_hooks.h \ + json/logger_json_file.c json/logger_json_file.h \ + json/oci_runtime_spec.c json/oci_runtime_spec.h \ ++ json/container_start_generate_config.c json/container_start_generate_config.h \ + json/read-file.c json/read-file.h \ + $(LSM_SOURCES) + +diff --git a/src/lxc/json/container_start_generate_config.c b/src/lxc/json/container_start_generate_config.c +new file mode 100644 +index 0000000..5ec8311 +--- /dev/null ++++ b/src/lxc/json/container_start_generate_config.c +@@ -0,0 +1,245 @@ ++// Generated from start-generate-config.json. Do not edit! ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE ++#endif ++#include ++#include "read-file.h" ++#include "container_start_generate_config.h" ++ ++container_start_generate_config *make_container_start_generate_config(yajl_val tree, struct parser_context *ctx, parser_error *err) { ++ container_start_generate_config *ret = NULL; ++ *err = 0; ++ if (tree == NULL) ++ return ret; ++ ret = safe_malloc(sizeof(*ret)); ++ { ++ yajl_val val = get_val(tree, "uid", yajl_t_number); ++ if (val != NULL) { ++ int invalid = common_safe_uint(YAJL_GET_NUMBER(val), (unsigned int *)&ret->uid); ++ if (invalid) { ++ if (asprintf(err, "Invalid value '%s' with type 'UID' for key 'uid': %s", YAJL_GET_NUMBER(val), strerror(-invalid)) < 0) ++ *err = safe_strdup("error allocating memory"); ++ free_container_start_generate_config(ret); ++ return NULL; ++ } ++ } ++ } ++ { ++ yajl_val val = get_val(tree, "gid", yajl_t_number); ++ if (val != NULL) { ++ int invalid = common_safe_uint(YAJL_GET_NUMBER(val), (unsigned int *)&ret->gid); ++ if (invalid) { ++ if (asprintf(err, "Invalid value '%s' with type 'GID' for key 'gid': %s", YAJL_GET_NUMBER(val), strerror(-invalid)) < 0) ++ *err = safe_strdup("error allocating memory"); ++ free_container_start_generate_config(ret); ++ return NULL; ++ } ++ } ++ } ++ { ++ yajl_val tmp = get_val(tree, "additionalGids", yajl_t_array); ++ if (tmp != NULL && YAJL_GET_ARRAY(tmp) != NULL && YAJL_GET_ARRAY(tmp)->len > 0) { ++ size_t i; ++ ret->additional_gids_len = YAJL_GET_ARRAY(tmp)->len; ++ ret->additional_gids = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) * sizeof(*ret->additional_gids)); ++ for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) { ++ yajl_val val = YAJL_GET_ARRAY(tmp)->values[i]; ++ if (val != NULL) { ++ int invalid = common_safe_uint(YAJL_GET_NUMBER(val), (unsigned int *)&ret->additional_gids[i]); ++ if (invalid) { ++ if (asprintf(err, "Invalid value '%s' with type 'GID' for key 'additionalGids': %s", YAJL_GET_NUMBER(val), strerror(-invalid)) < 0) ++ *err = safe_strdup("error allocating memory"); ++ free_container_start_generate_config(ret); ++ return NULL; ++ } ++ } ++ } ++ } ++ } ++ ++ if (tree->type == yajl_t_object && (ctx->options & PARSE_OPTIONS_STRICT)) { ++ int i; ++ for (i = 0; i < tree->u.object.len; i++) ++ if (strcmp(tree->u.object.keys[i], "uid") && ++ strcmp(tree->u.object.keys[i], "gid") && ++ strcmp(tree->u.object.keys[i], "additionalGids")) { ++ if (ctx->stderr > 0) ++ fprintf(ctx->stderr, "WARNING: unknown key found: %s\n", tree->u.object.keys[i]); ++ } ++ } ++ return ret; ++} ++ ++void free_container_start_generate_config(container_start_generate_config *ptr) { ++ if (ptr == NULL) ++ return; ++ free(ptr->additional_gids); ++ ptr->additional_gids = NULL; ++ free(ptr); ++} ++ ++yajl_gen_status gen_container_start_generate_config(yajl_gen g, container_start_generate_config *ptr, struct parser_context *ctx, parser_error *err) { ++ yajl_gen_status stat = yajl_gen_status_ok; ++ *err = 0; ++ stat = reformat_start_map(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr != NULL && ptr->uid)) { ++ long long unsigned int num = 0; ++ stat = reformat_map_key(g, "uid", strlen("uid")); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (ptr != NULL && ptr->uid) { ++ num = (long long unsigned int)ptr->uid; ++ } ++ stat = reformat_uint(g, num); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr != NULL && ptr->gid)) { ++ long long unsigned int num = 0; ++ stat = reformat_map_key(g, "gid", strlen("gid")); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (ptr != NULL && ptr->gid) { ++ num = (long long unsigned int)ptr->gid; ++ } ++ stat = reformat_uint(g, num); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) || (ptr != NULL && ptr->additional_gids != NULL)) { ++ size_t len = 0, i; ++ stat = reformat_map_key(g, "additionalGids", strlen("additionalGids")); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (ptr != NULL && ptr->additional_gids != NULL) { ++ len = ptr->additional_gids_len; ++ } ++ if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) ++ yajl_gen_config(g, yajl_gen_beautify, 0); ++ stat = reformat_start_array(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ for (i = 0; i < len; i++) { ++ stat = reformat_uint(g, ptr->additional_gids[i]); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ stat = reformat_end_array(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY)) ++ yajl_gen_config(g, yajl_gen_beautify, 1); ++ } ++ stat = reformat_end_map(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ return yajl_gen_status_ok; ++} ++ ++ ++container_start_generate_config *container_start_generate_config_parse_file(const char *filename, struct parser_context *ctx, parser_error *err) { ++ container_start_generate_config *ptr = NULL; ++ size_t filesize; ++ char *content = NULL; ++ ++ if (filename == NULL || err == NULL) ++ return NULL; ++ ++ *err = NULL; ++ content = read_file(filename, &filesize); ++ if (content == NULL) { ++ if (asprintf(err, "cannot read the file: %s", filename) < 0) ++ *err = safe_strdup("error allocating memory"); ++ return NULL; ++ } ++ ptr = container_start_generate_config_parse_data(content, ctx, err); ++ free(content); ++ return ptr; ++} ++ ++container_start_generate_config *container_start_generate_config_parse_file_stream(FILE *stream, struct parser_context *ctx, parser_error *err) { ++ container_start_generate_config *ptr = NULL; ++ size_t filesize; ++ char *content = NULL ; ++ ++ if (stream == NULL || err == NULL) ++ return NULL; ++ ++ *err = NULL; ++ content = fread_file(stream, &filesize); ++ if (content == NULL) { ++ *err = safe_strdup("cannot read the file"); ++ return NULL; ++ } ++ ptr = container_start_generate_config_parse_data(content, ctx, err); ++ free(content); ++ return ptr; ++} ++ ++container_start_generate_config *container_start_generate_config_parse_data(const char *jsondata, struct parser_context *ctx, parser_error *err) { ++ container_start_generate_config *ptr = NULL; ++ yajl_val tree; ++ char errbuf[1024]; ++ struct parser_context tmp_ctx; ++ ++ if (jsondata == NULL || err == NULL) ++ return NULL; ++ ++ *err = NULL; ++ if (ctx == NULL) { ++ ctx = &tmp_ctx; ++ (void)memset(&tmp_ctx, 0, sizeof(tmp_ctx)); ++ } ++ tree = yajl_tree_parse(jsondata, errbuf, sizeof(errbuf)); ++ if (tree == NULL) { ++ if (asprintf(err, "cannot parse the data: %s", errbuf) < 0) ++ *err = safe_strdup("error allocating memory"); ++ return NULL; ++ } ++ ptr = make_container_start_generate_config(tree, ctx, err); ++ yajl_tree_free(tree); ++ return ptr; ++} ++char *container_start_generate_config_generate_json(container_start_generate_config *ptr, struct parser_context *ctx, parser_error *err) { ++ yajl_gen g = NULL; ++ struct parser_context tmp_ctx; ++ const unsigned char *gen_buf = NULL; ++ char *json_buf = NULL; ++ size_t gen_len = 0; ++ ++ if (ptr == NULL || err == NULL) ++ return NULL; ++ ++ *err = NULL; ++ if (ctx == NULL) { ++ ctx = &tmp_ctx; ++ (void)memset(&tmp_ctx, 0, sizeof(tmp_ctx)); ++ } ++ ++ if (!json_gen_init(&g, ctx)) { ++ *err = safe_strdup("Json_gen init failed"); ++ goto out; ++ } ++ if (yajl_gen_status_ok != gen_container_start_generate_config(g, ptr, ctx, err)) { ++ if (*err == NULL) ++ *err = safe_strdup("Failed to generate json"); ++ goto free_out; ++ } ++ yajl_gen_get_buf(g, &gen_buf, &gen_len); ++ if (gen_buf == NULL) { ++ *err = safe_strdup("Error to get generated json"); ++ goto free_out; ++ } ++ ++ json_buf = safe_malloc(gen_len + 1); ++ (void)memcpy(json_buf, gen_buf, gen_len); ++ json_buf[gen_len] = '\0'; ++ ++free_out: ++ yajl_gen_clear(g); ++ yajl_gen_free(g); ++out: ++ return json_buf; ++} +diff --git a/src/lxc/json/container_start_generate_config.h b/src/lxc/json/container_start_generate_config.h +new file mode 100644 +index 0000000..e1dcf56 +--- /dev/null ++++ b/src/lxc/json/container_start_generate_config.h +@@ -0,0 +1,43 @@ ++// Generated from start-generate-config.json. Do not edit! ++#ifndef CONTAINER_START_GENERATE_CONFIG_SCHEMA_H ++#define CONTAINER_START_GENERATE_CONFIG_SCHEMA_H ++ ++#include ++#include ++#include "json_common.h" ++#include "defs.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef struct { ++ uid_t uid; ++ ++ gid_t gid; ++ ++ gid_t *additional_gids; ++ size_t additional_gids_len; ++ ++} ++container_start_generate_config; ++ ++void free_container_start_generate_config(container_start_generate_config *ptr); ++ ++container_start_generate_config *make_container_start_generate_config(yajl_val tree, struct parser_context *ctx, parser_error *err); ++ ++yajl_gen_status gen_container_start_generate_config(yajl_gen g, container_start_generate_config *ptr, struct parser_context *ctx, parser_error *err); ++ ++container_start_generate_config *container_start_generate_config_parse_file(const char *filename, struct parser_context *ctx, parser_error *err); ++ ++container_start_generate_config *container_start_generate_config_parse_file_stream(FILE *stream, struct parser_context *ctx, parser_error *err); ++ ++container_start_generate_config *container_start_generate_config_parse_data(const char *jsondata, struct parser_context *ctx, parser_error *err); ++ ++char *container_start_generate_config_generate_json(container_start_generate_config *ptr, struct parser_context *ctx, parser_error *err); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c +index af63f58..4069204 100644 +--- a/src/lxc/tools/lxc_start.c ++++ b/src/lxc/tools/lxc_start.c +@@ -50,6 +50,7 @@ + #include "confile.h" + #include "log.h" + #include "utils.h" ++#include "container_start_generate_config.h" + + lxc_log_define(lxc_start, lxc); + +@@ -213,6 +214,57 @@ static int ensure_path(char **confpath, const char *path) + return 0; + } + ++static int set_start_extral_configs(const char *lxcpath, const char *name, struct lxc_container *c) ++{ ++#define START_GENERATE_CONFIG "start_generate_config.json" ++ char fpath[PATH_MAX] = {0}; ++ parser_error jerr = NULL; ++ int ret = -1; ++ container_start_generate_config *start_conf = NULL; ++ struct lxc_conf *lconf = c->lxc_conf; ++ size_t i = 0; ++ ++ if (sprintf(fpath, "%s/%s/%s", lxcpath, name, START_GENERATE_CONFIG) < 0) { ++ ERROR("Sprintf config path failed"); ++ return -1; ++ } ++ if (!file_exists(fpath)) { ++ return 0; ++ } ++ start_conf = container_start_generate_config_parse_file(fpath, NULL, &jerr); ++ if (start_conf == NULL) { ++ ERROR("Parse start generate config file: %s failed", fpath); ++ goto out; ++ } ++ if (start_conf->uid != 0) { ++ lconf->init_uid = start_conf->uid; ++ } ++ if (start_conf->gid != 0) { ++ lconf->init_gid = start_conf->gid; ++ } ++ if (start_conf->additional_gids != NULL && start_conf->additional_gids_len > 0) { ++ gid_t *tmp; ++ tmp = realloc(lconf->init_groups, (lconf->init_groups_len + start_conf->additional_gids_len) * sizeof(gid_t)); ++ if (tmp == NULL) { ++ ERROR("Out of memory"); ++ goto out; ++ } ++ lconf->init_groups = tmp; ++ for (; i < start_conf->additional_gids_len; i++) { ++ tmp[lconf->init_groups_len] = start_conf->additional_gids[i]; ++ lconf->init_groups_len++; ++ } ++ } ++ ++ ret = 0; ++out: ++ free(jerr); ++ if (start_conf != NULL) { ++ free_container_start_generate_config(start_conf); ++ } ++ return ret; ++} ++ + int main(int argc, char *argv[]) + { + const char *lxcpath; +@@ -358,6 +410,12 @@ int main(int argc, char *argv[]) + } + } + ++ /* isulad: load extral config for start container */ ++ if (set_start_extral_configs(lxcpath, my_args.name, c) != 0) { ++ ERROR("Failed to load extral config for container"); ++ goto out; ++ } ++ + /* isulad: fifo used to monitor state of monitor process */ + if (my_args.exit_monitor_fifo != NULL) { + c->exit_fifo = strdup(my_args.exit_monitor_fifo); +-- +1.8.3.1 + diff --git a/0094-exec-load-uid-gid-and-groups.patch b/0094-exec-load-uid-gid-and-groups.patch new file mode 100644 index 0000000..a2acb22 --- /dev/null +++ b/0094-exec-load-uid-gid-and-groups.patch @@ -0,0 +1,197 @@ +From 900c2f8fe30d4ffdaef93f2c01d711705ab8cff9 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Tue, 7 May 2019 12:55:03 +0800 +Subject: [PATCH 094/122] exec load uid gid and groups + +exec load uid gid and groups + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + src/lxc/lxccontainer.c | 69 +++++++++++++++++++++++++++++++++++++++++++++-- + src/lxc/tools/lxc_start.c | 58 --------------------------------------- + 2 files changed, 67 insertions(+), 60 deletions(-) + +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index fa13e52..e0c4de3 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -74,6 +74,7 @@ + #include "terminal.h" + #include "utils.h" + #include "version.h" ++#include "container_start_generate_config.h" + + /* major()/minor() */ + #ifdef MAJOR_IN_MKDEV +@@ -5252,6 +5253,65 @@ static bool do_lxcapi_add_terminal_fifo(struct lxc_container *c, const char *in_ + + WRAP_API_3(bool, lxcapi_add_terminal_fifo, const char *, const char *, const char *) + ++static int set_start_extral_configs(struct lxc_container *c) ++{ ++#define START_GENERATE_CONFIG "start_generate_config.json" ++ char fpath[PATH_MAX] = {0}; ++ parser_error jerr = NULL; ++ int ret = -1; ++ container_start_generate_config *start_conf = NULL; ++ struct lxc_conf *lconf = c->lxc_conf; ++ size_t i = 0; ++ ++ if (lconf == NULL) { ++ c->lxc_conf = malloc(sizeof(struct lxc_conf)); ++ lconf = c->lxc_conf; ++ if (lconf == NULL) { ++ fprintf(stderr, "Out of memory\n"); ++ return -1; ++ } ++ } ++ if (sprintf(fpath, "%s/%s/%s", c->config_path, c->name, START_GENERATE_CONFIG) < 0) { ++ fprintf(stderr, "Sprintf config path failed\n"); ++ return -1; ++ } ++ if (!file_exists(fpath)) { ++ return 0; ++ } ++ start_conf = container_start_generate_config_parse_file(fpath, NULL, &jerr); ++ if (start_conf == NULL) { ++ fprintf(stderr, "Parse start generate config file: %s failed", fpath); ++ goto out; ++ } ++ if (start_conf->uid != 0) { ++ lconf->init_uid = start_conf->uid; ++ } ++ if (start_conf->gid != 0) { ++ lconf->init_gid = start_conf->gid; ++ } ++ if (start_conf->additional_gids != NULL && start_conf->additional_gids_len > 0) { ++ gid_t *tmp; ++ tmp = realloc(lconf->init_groups, (lconf->init_groups_len + start_conf->additional_gids_len) * sizeof(gid_t)); ++ if (tmp == NULL) { ++ fprintf(stderr, "Out of memory"); ++ goto out; ++ } ++ lconf->init_groups = tmp; ++ for (; i < start_conf->additional_gids_len; i++) { ++ tmp[lconf->init_groups_len] = start_conf->additional_gids[i]; ++ lconf->init_groups_len++; ++ } ++ } ++ ++ ret = 0; ++out: ++ free(jerr); ++ if (start_conf != NULL) { ++ free_container_start_generate_config(start_conf); ++ } ++ return ret; ++} ++ + static struct lxc_container *do_lxc_container_new(const char *name, const char *configpath, bool load_config) + { + struct lxc_container *c; +@@ -5309,11 +5369,16 @@ static struct lxc_container *do_lxc_container_new(const char *name, const char * + goto err; + } + +- if (load_config) { +- if (file_exists(c->configfile) && !lxcapi_load_config(c, NULL)) { ++ if (load_config && file_exists(c->configfile)) { ++ if (!lxcapi_load_config(c, NULL)) { + fprintf(stderr, "Failed to load config for %s\n", name); + goto err; + } ++ /* isulad: load extral config for start container */ ++ if (set_start_extral_configs(c) != 0) { ++ fprintf(stderr, "Failed to load extral config for container: %s\n", name); ++ goto err; ++ } + } + + if (ongoing_create(c) == 2) { +diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c +index 4069204..af63f58 100644 +--- a/src/lxc/tools/lxc_start.c ++++ b/src/lxc/tools/lxc_start.c +@@ -50,7 +50,6 @@ + #include "confile.h" + #include "log.h" + #include "utils.h" +-#include "container_start_generate_config.h" + + lxc_log_define(lxc_start, lxc); + +@@ -214,57 +213,6 @@ static int ensure_path(char **confpath, const char *path) + return 0; + } + +-static int set_start_extral_configs(const char *lxcpath, const char *name, struct lxc_container *c) +-{ +-#define START_GENERATE_CONFIG "start_generate_config.json" +- char fpath[PATH_MAX] = {0}; +- parser_error jerr = NULL; +- int ret = -1; +- container_start_generate_config *start_conf = NULL; +- struct lxc_conf *lconf = c->lxc_conf; +- size_t i = 0; +- +- if (sprintf(fpath, "%s/%s/%s", lxcpath, name, START_GENERATE_CONFIG) < 0) { +- ERROR("Sprintf config path failed"); +- return -1; +- } +- if (!file_exists(fpath)) { +- return 0; +- } +- start_conf = container_start_generate_config_parse_file(fpath, NULL, &jerr); +- if (start_conf == NULL) { +- ERROR("Parse start generate config file: %s failed", fpath); +- goto out; +- } +- if (start_conf->uid != 0) { +- lconf->init_uid = start_conf->uid; +- } +- if (start_conf->gid != 0) { +- lconf->init_gid = start_conf->gid; +- } +- if (start_conf->additional_gids != NULL && start_conf->additional_gids_len > 0) { +- gid_t *tmp; +- tmp = realloc(lconf->init_groups, (lconf->init_groups_len + start_conf->additional_gids_len) * sizeof(gid_t)); +- if (tmp == NULL) { +- ERROR("Out of memory"); +- goto out; +- } +- lconf->init_groups = tmp; +- for (; i < start_conf->additional_gids_len; i++) { +- tmp[lconf->init_groups_len] = start_conf->additional_gids[i]; +- lconf->init_groups_len++; +- } +- } +- +- ret = 0; +-out: +- free(jerr); +- if (start_conf != NULL) { +- free_container_start_generate_config(start_conf); +- } +- return ret; +-} +- + int main(int argc, char *argv[]) + { + const char *lxcpath; +@@ -410,12 +358,6 @@ int main(int argc, char *argv[]) + } + } + +- /* isulad: load extral config for start container */ +- if (set_start_extral_configs(lxcpath, my_args.name, c) != 0) { +- ERROR("Failed to load extral config for container"); +- goto out; +- } +- + /* isulad: fifo used to monitor state of monitor process */ + if (my_args.exit_monitor_fifo != NULL) { + c->exit_fifo = strdup(my_args.exit_monitor_fifo); +-- +1.8.3.1 + diff --git a/0095-lxc-don-t-use-the-unified-hierarchy-for-the-systemd-.patch b/0095-lxc-don-t-use-the-unified-hierarchy-for-the-systemd-.patch new file mode 100644 index 0000000..4fa4a52 --- /dev/null +++ b/0095-lxc-don-t-use-the-unified-hierarchy-for-the-systemd-.patch @@ -0,0 +1,56 @@ +From 92dfbde544492386418f02469af5380d7d5e7c00 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Fri, 10 May 2019 11:05:42 +0800 +Subject: [PATCH 095/122] lxc: don't use the unified hierarchy for the systemd + cgroup + +reason:don't use the unified hierarchy for the systemd cgroup + +Signed-off-by: zhangsong +Signed-off-by: LiFeng +--- + src/lxc/cgroups/cgfsng.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index 2bf142f..eee7ed6 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -1571,6 +1571,7 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, + int i, ret; + char *tmpfspath = NULL; + char *systemdpath = NULL; ++ char *unifiedpath = NULL; + bool has_cgns = false, retval = false, wants_force_mount = false; + char **merged = NULL; + +@@ -1718,6 +1719,16 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, + + // isulad: remount /sys/fs/cgroup/systemd to readwrite for system container + if (handler->conf->systemd != NULL && strcmp(handler->conf->systemd, "true") == 0) { ++ // isulad: don't use the unified hierarchy for the systemd cgroup ++ unifiedpath = must_make_path(root, "/sys/fs/cgroup/unified", NULL); ++ if (dir_exists(unifiedpath)) { ++ ret = umount2(unifiedpath, MNT_DETACH); ++ if (ret < 0) { ++ SYSERROR("Failed to umount /sys/fs/cgroup/unified."); ++ goto on_error; ++ } ++ } ++ + systemdpath = must_make_path(root, "/sys/fs/cgroup/systemd", NULL); + ret = mount(systemdpath, systemdpath, "bind", + MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_RELATIME|MS_BIND|MS_REMOUNT, NULL); +@@ -1734,6 +1745,9 @@ on_error: + if (systemdpath != NULL) { + free(systemdpath); + } ++ if (unifiedpath != NULL) { ++ free(unifiedpath); ++ } + lxc_free_array((void **)merged, free); + return retval; + } +-- +1.8.3.1 + diff --git a/0096-close-inherited-fd-in-hook-process.patch b/0096-close-inherited-fd-in-hook-process.patch new file mode 100644 index 0000000..dec0378 --- /dev/null +++ b/0096-close-inherited-fd-in-hook-process.patch @@ -0,0 +1,34 @@ +From 7f4352c61de6732d41285f6f949199708e459ac0 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Mon, 13 May 2019 16:45:50 +0800 +Subject: [PATCH 096/122] close inherited fd in hook process + +close inherited fd in hook process + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 0f227aa..6cf86a4 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4560,6 +4560,13 @@ static struct lxc_popen_FILE *lxc_popen_ocihook(char *commandpath, char **args, + + if (child_pid == 0) { + /* child */ ++ int inherit_fds[2] = { ++ pipe_msg[0], pipe_fds[1] ++ }; ++ if (lxc_check_inherited(NULL, true, inherit_fds, 2) != 0) { ++ SYSERROR("check inherited fd failed"); ++ exit(127); ++ } + + close(pipe_msg[1]); + if (pipe_msg[0] != STDIN_FILENO) +-- +1.8.3.1 + diff --git a/0097-lxc-report-error-when-fork-exec-error-for-hooks.patch b/0097-lxc-report-error-when-fork-exec-error-for-hooks.patch new file mode 100644 index 0000000..f3e40c5 --- /dev/null +++ b/0097-lxc-report-error-when-fork-exec-error-for-hooks.patch @@ -0,0 +1,72 @@ +From 474a63f9c72ace7d1d49d58f6b844dc18f2b6456 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Wed, 15 May 2019 00:53:49 -0400 +Subject: [PATCH 097/122] lxc: report error when fork/exec error for hooks + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 21 +++++++++------------ + 1 file changed, 9 insertions(+), 12 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 6cf86a4..341fdab 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4559,21 +4559,12 @@ static struct lxc_popen_FILE *lxc_popen_ocihook(char *commandpath, char **args, + goto on_error; + + if (child_pid == 0) { +- /* child */ +- int inherit_fds[2] = { +- pipe_msg[0], pipe_fds[1] +- }; +- if (lxc_check_inherited(NULL, true, inherit_fds, 2) != 0) { +- SYSERROR("check inherited fd failed"); +- exit(127); +- } +- + close(pipe_msg[1]); + if (pipe_msg[0] != STDIN_FILENO) + dup2(pipe_msg[0], STDIN_FILENO); + else { + if (fcntl(pipe_msg[0], F_SETFD, 0) != 0) { +- SYSERROR("Failed to remove FD_CLOEXEC from fd."); ++ fprintf(stderr, "Failed to remove FD_CLOEXEC from fd."); + exit(127); + } + } +@@ -4600,6 +4591,11 @@ static struct lxc_popen_FILE *lxc_popen_ocihook(char *commandpath, char **args, + if (ret < 0) + _exit(EXIT_FAILURE); + ++ if (lxc_check_inherited(NULL, true, NULL, 0) != 0) { ++ fprintf(stderr, "check inherited fd failed"); ++ exit(127); ++ } ++ + /* + * Unblock signals. + * This is the main/only reason +@@ -4615,6 +4611,7 @@ static struct lxc_popen_FILE *lxc_popen_ocihook(char *commandpath, char **args, + execvpe(commandpath, args, envs); + else + execvp(commandpath, args); ++ fprintf(stderr, "fork/exec %s: %s", commandpath, strerror(errno)); + exit(127); + } + +@@ -4764,8 +4761,8 @@ static int run_ocihook_buffer(struct oci_hook_conf *oconf, char *inmsg) + SYSERROR("Script exited with error."); + goto print_hook; + } else if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) { +- ERROR("Script exited with status %d. output:%s", WEXITSTATUS(ret), output); +- lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"error running hook: exit status %d, output:%s\".", ++ ERROR("Script exited with status %d. output: %s", WEXITSTATUS(ret), output); ++ lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"error running hook: exit status %d, output: %s\".", + __FILE__, __LINE__, + (conf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[conf->which], + WEXITSTATUS(ret), output); +-- +1.8.3.1 + diff --git a/0098-lxc-make-dev-bind-mount-from-host-tmpfs-for-system-c.patch b/0098-lxc-make-dev-bind-mount-from-host-tmpfs-for-system-c.patch new file mode 100644 index 0000000..c812c87 --- /dev/null +++ b/0098-lxc-make-dev-bind-mount-from-host-tmpfs-for-system-c.patch @@ -0,0 +1,67 @@ +From 94b3ad110dc17ecad2f86ef166065293cb278295 Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Wed, 15 May 2019 12:42:08 +0800 +Subject: [PATCH 098/122] lxc: make /dev bind mount from host tmpfs for system + container + +reason:make /dev bind mount from host tmpfs for system container + +Signed-off-by: zhangsong +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 24 ++++++++++++++++-------- + 1 file changed, 16 insertions(+), 8 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 341fdab..3780966 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -1122,7 +1122,7 @@ on_error: + * error, log it but don't fail yet. + */ + static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs, +- const char *lxcpath) ++ const char *lxcpath, char *systemd) + { + int ret; + size_t clen; +@@ -1147,13 +1147,21 @@ static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs, + goto reset_umask; + } + +- ret = safe_mount("none", path, "tmpfs", 0, "size=500000,mode=755", ++ if (systemd != NULL && !strcmp(systemd, "true")) { ++ ret = mount(path, path, "", MS_BIND, NULL); ++ if (ret < 0) { ++ SYSERROR("Failed to bind mount path \"%s\"", path); ++ goto reset_umask; ++ } ++ } else { ++ ret = safe_mount("none", path, "tmpfs", 0, "size=500000,mode=755", + rootfs->path ? rootfs->mount : NULL); +- if (ret < 0) { +- SYSERROR("Failed to mount tmpfs on \"%s\"", path); +- goto reset_umask; +- } +- TRACE("Mounted tmpfs on \"%s\"", path); ++ if (ret < 0) { ++ SYSERROR("Failed to mount tmpfs on \"%s\"", path); ++ goto reset_umask; ++ } ++ TRACE("Mounted tmpfs on \"%s\"", path); ++ } + + ret = snprintf(path, clen, "%s/dev/pts", rootfs->path ? rootfs->mount : ""); + if (ret < 0 || (size_t)ret >= clen) { +@@ -4130,7 +4138,7 @@ int lxc_setup(struct lxc_handler *handler) + } + + if (lxc_conf->autodev > 0) { +- ret = mount_autodev(name, &lxc_conf->rootfs, lxcpath); ++ ret = mount_autodev(name, &lxc_conf->rootfs, lxcpath, lxc_conf->systemd); + if (ret < 0) { + ERROR("Failed to mount \"/dev\""); + goto on_error; +-- +1.8.3.1 + diff --git a/0099-terminal-do-not-close-the-master-fd-of-pty.patch b/0099-terminal-do-not-close-the-master-fd-of-pty.patch new file mode 100644 index 0000000..2246157 --- /dev/null +++ b/0099-terminal-do-not-close-the-master-fd-of-pty.patch @@ -0,0 +1,28 @@ +From d5d48aa449d782dce754ee87c6a3ee1706c1f967 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Tue, 21 May 2019 04:53:16 -0400 +Subject: [PATCH 099/122] terminal: do not close the master fd of pty + +Signed-off-by: LiFeng +--- + src/lxc/terminal.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index dfce92e..88653b4 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -595,6 +595,10 @@ int lxc_terminal_io_cb(int fd, uint32_t events, void *data, + if (w_log < 0) + TRACE("Failed to write %d bytes to terminal log", r); + } ++ /* notes: do not close the master fd due to if we close the fd, the process may ++ * recive SIGHUP and the exit code will be 129 (128 + 1) ++ */ ++ return LXC_MAINLOOP_CLOSE; + } else if (fd == terminal->peer) { + if (terminal->tty_state) { + lxc_terminal_signal_fini(terminal->tty_state); +-- +1.8.3.1 + diff --git a/0100-start-add-check-save-pid-info-file.patch b/0100-start-add-check-save-pid-info-file.patch new file mode 100644 index 0000000..155b02d --- /dev/null +++ b/0100-start-add-check-save-pid-info-file.patch @@ -0,0 +1,139 @@ +From 5f9953ea9fffa99ca3838e3b59ab3ee170e62795 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Wed, 22 May 2019 23:00:17 -0400 +Subject: [PATCH 100/122] start: add check save pid info file + +Signed-off-by: LiFeng +--- + src/lxc/start.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++-------- + src/lxc/utils.c | 2 +- + src/lxc/utils.h | 1 + + 3 files changed, 64 insertions(+), 11 deletions(-) + +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 3657d4e..4541793 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -1850,14 +1850,10 @@ static inline int do_share_ns(void *arg) + return 0; + } + +-/* isuald: save pid/ppid info */ +-static int lxc_save_container_info(char *filename, pid_t pid) ++static int lxc_write_container_info(char *filename, pid_t pid, pid_t p_pid, unsigned long long start_at, unsigned long long p_start_at) + { + FILE *pid_fp = NULL; + int ret = 0; +- pid_t p_pid = 0; +- unsigned long long start_at = 0; +- unsigned long long p_start_at = 0; + + pid_fp = fopen(filename, "w"); + if (pid_fp == NULL) { +@@ -1866,11 +1862,6 @@ static int lxc_save_container_info(char *filename, pid_t pid) + goto out; + } + +- start_at = lxc_get_process_startat(pid); +- +- p_pid = getpid(); +- p_start_at = lxc_get_process_startat(p_pid); +- + if (fprintf(pid_fp, "%d %llu %d %llu\n", pid, start_at, p_pid, p_start_at) < 0) { + SYSERROR("Failed to write '%s'", filename); + ret = -1; +@@ -1883,6 +1874,67 @@ out: + return ret; + } + ++static int lxc_check_container_info(char *filename, pid_t pid, pid_t p_pid, unsigned long long start_at, unsigned long long p_start_at) ++{ ++ int ret = 0; ++ int num; ++ char sbuf[1024] = {0}; /* bufs for stat */ ++ int saved_pid; /* process id */ ++ int saved_ppid; /* pid of parent process */ ++ unsigned long long saved_start_time; /* start time of process -- seconds since 1-1-70 */ ++ unsigned long long saved_pstart_time; /* start time of parent process -- seconds since 1-1-70 */ ++ ++ if ((lxc_file2str(filename, sbuf, sizeof(sbuf))) == -1) { ++ SYSERROR("Failed to read pidfile %s", filename); ++ ret = -1; ++ goto out; ++ } ++ ++ num = sscanf(sbuf, "%d %Lu %d %Lu", &saved_pid, &saved_start_time, &saved_ppid, &saved_pstart_time); ++ if (num < 0) { ++ SYSERROR("Call sscanf error"); ++ ret = -1; ++ goto out; ++ } ++ ++ if (pid != saved_pid || p_pid != saved_ppid ++ || start_at != saved_start_time || p_start_at != saved_pstart_time) { ++ ERROR("Check container info failed"); ++ ret = -1; ++ goto out; ++ } ++ ++out: ++ return ret; ++} ++ ++ ++/* isuald: save pid/ppid info */ ++static int lxc_save_container_info(char *filename, pid_t pid) ++{ ++ int ret = 0; ++ pid_t p_pid = 0; ++ unsigned long long start_at = 0; ++ unsigned long long p_start_at = 0; ++ ++ start_at = lxc_get_process_startat(pid); ++ p_pid = getpid(); ++ p_start_at = lxc_get_process_startat(p_pid); ++ ++ ret = lxc_write_container_info(filename, pid, p_pid, start_at, p_start_at); ++ if (ret != 0) { ++ goto out; ++ } ++ ++ ret = lxc_check_container_info(filename, pid, p_pid, start_at, p_start_at); ++ if (ret != 0) { ++ goto out; ++ } ++ ++out: ++ return ret; ++} ++ + /* lxc_spawn() performs crucial setup tasks and clone()s the new process which + * exec()s the requested container binary. + * Note that lxc_spawn() runs in the parent namespaces. Any operations performed +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index fd6075f..dc0e6c5 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -1909,7 +1909,7 @@ set_env: + + + /* isulad: read file to buffer */ +-static int lxc_file2str(const char *filename, char ret[], int cap) ++int lxc_file2str(const char *filename, char ret[], int cap) + { + int fd, num_read; + +diff --git a/src/lxc/utils.h b/src/lxc/utils.h +index 20407af..4410ff2 100644 +--- a/src/lxc/utils.h ++++ b/src/lxc/utils.h +@@ -323,5 +323,6 @@ extern void lxc_write_error_message(int errfd, const char *format, ...); + extern bool lxc_process_alive(pid_t pid, unsigned long long start_time); + + extern bool is_non_negative_num(const char *s); ++extern int lxc_file2str(const char *filename, char ret[], int cap); + + #endif /* __LXC_UTILS_H */ +-- +1.8.3.1 + diff --git a/0101-lxc-fix-code-error.patch b/0101-lxc-fix-code-error.patch new file mode 100644 index 0000000..ad97aa3 --- /dev/null +++ b/0101-lxc-fix-code-error.patch @@ -0,0 +1,8983 @@ +From ed19b6f4c950fc20be79f630812a3a8cfec847bd Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Mon, 3 Jun 2019 05:14:46 -0400 +Subject: [PATCH 101/122] lxc: fix code error + +Signed-off-by: LiFeng +--- + src/lxc/af_unix.c | 28 +- + src/lxc/cgroups/cgfsng.c | 263 ++++++------ + src/lxc/conf.c | 575 ++++++++++++++------------ + src/lxc/conf.h | 28 +- + src/lxc/confile.c | 897 ++++++++++++++++++++-------------------- + src/lxc/confile_utils.c | 42 +- + src/lxc/json/logger_json_file.c | 422 +++++++++---------- + src/lxc/json/read-file.c | 139 +++---- + src/lxc/log.c | 48 +-- + src/lxc/lxccontainer.c | 239 ++++++----- + src/lxc/mainloop.c | 8 +- + src/lxc/path.c | 584 +++++++++++++++----------- + src/lxc/path.h | 18 +- + src/lxc/start.c | 194 ++++----- + src/lxc/storage/block.c | 3 +- + src/lxc/terminal.c | 129 +++--- + src/lxc/utils.c | 159 ++++--- + src/lxc/utils.h | 11 +- + 18 files changed, 2019 insertions(+), 1768 deletions(-) + +diff --git a/src/lxc/af_unix.c b/src/lxc/af_unix.c +index 24500a8..4c45946 100644 +--- a/src/lxc/af_unix.c ++++ b/src/lxc/af_unix.c +@@ -47,7 +47,7 @@ + lxc_log_define(af_unix, lxc); + + static ssize_t lxc_abstract_unix_set_sockaddr(struct sockaddr_un *addr, +- const char *path) ++ const char *path) + { + size_t len; + +@@ -96,7 +96,7 @@ int lxc_abstract_unix_open(const char *path, int type, int flags) + } + + ret = bind(fd, (struct sockaddr *)&addr, +- offsetof(struct sockaddr_un, sun_path) + len + 1); ++ offsetof(struct sockaddr_un, sun_path) + len + 1); + if (ret < 0) { + int saved_errno = errno; + close(fd); +@@ -141,7 +141,7 @@ int lxc_abstract_unix_connect(const char *path) + } + + ret = connect(fd, (struct sockaddr *)&addr, +- offsetof(struct sockaddr_un, sun_path) + len + 1); ++ offsetof(struct sockaddr_un, sun_path) + len + 1); + if (ret < 0) { + int saved_errno = errno; + close(fd); +@@ -153,7 +153,7 @@ int lxc_abstract_unix_connect(const char *path) + } + + int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds, +- void *data, size_t size) ++ void *data, size_t size) + { + int ret; + struct msghdr msg; +@@ -196,14 +196,14 @@ int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds, + + /* isulad: add wait timeout Microseconds*/ + int lxc_abstract_unix_recv_fds_timeout(int fd, int *recvfds, int num_recvfds, +- void *data, size_t size, unsigned int timeout) ++ void *data, size_t size, unsigned int timeout) + { + int ret; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsg = NULL; + char buf[1] = {0}; +- char *cmsgbuf; ++ char *cmsgbuf = NULL; + size_t cmsgbufsize = CMSG_SPACE(num_recvfds * sizeof(int)); + struct timeval out; + +@@ -229,10 +229,10 @@ int lxc_abstract_unix_recv_fds_timeout(int fd, int *recvfds, int num_recvfds, + out.tv_sec = timeout / 1000000; + out.tv_usec = timeout % 1000000; + ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, +- (const void *)&out, sizeof(out)); ++ (const void *)&out, sizeof(out)); + if (ret < 0) { + ERROR("Failed to set %u timeout on containter " +- "state socket", timeout); ++ "state socket", timeout); + goto out; + } + } +@@ -245,7 +245,7 @@ int lxc_abstract_unix_recv_fds_timeout(int fd, int *recvfds, int num_recvfds, + + memset(recvfds, -1, num_recvfds * sizeof(int)); + if (cmsg && cmsg->cmsg_len == CMSG_LEN(num_recvfds * sizeof(int)) && +- cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) ++ cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) + memcpy(recvfds, CMSG_DATA(cmsg), num_recvfds * sizeof(int)); + + out: +@@ -254,7 +254,7 @@ out: + } + + int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds, +- void *data, size_t size) ++ void *data, size_t size) + { + return lxc_abstract_unix_recv_fds_timeout(fd, recvfds, num_recvfds, data, size, 0); + } +@@ -265,7 +265,7 @@ int lxc_abstract_unix_send_credential(int fd, void *data, size_t size) + struct iovec iov; + struct cmsghdr *cmsg; + struct ucred cred = { +- .pid = lxc_raw_getpid(), .uid = getuid(), .gid = getgid(), ++ .pid = lxc_raw_getpid(), .uid = getuid(), .gid = getgid(), + }; + char cmsgbuf[CMSG_SPACE(sizeof(cred))] = {0}; + char buf[1] = {0}; +@@ -317,11 +317,11 @@ int lxc_abstract_unix_rcv_credential(int fd, void *data, size_t size) + cmsg = CMSG_FIRSTHDR(&msg); + + if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)) && +- cmsg->cmsg_level == SOL_SOCKET && +- cmsg->cmsg_type == SCM_CREDENTIALS) { ++ cmsg->cmsg_level == SOL_SOCKET && ++ cmsg->cmsg_type == SCM_CREDENTIALS) { + memcpy(&cred, CMSG_DATA(cmsg), sizeof(cred)); + if (cred.uid && +- (cred.uid != getuid() || cred.gid != getgid())) { ++ (cred.uid != getuid() || cred.gid != getgid())) { + INFO("Message denied for '%d/%d'", cred.uid, cred.gid); + errno = EACCES; + return -1; +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index eee7ed6..67c7a0e 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -149,7 +149,7 @@ static char *cg_legacy_must_prefix_named(char *entry) + * The last entry will always be NULL. + */ + static void must_append_controller(char **klist, char **nlist, char ***clist, +- char *entry) ++ char *entry) + { + int newentry; + char *copy; +@@ -190,7 +190,7 @@ struct hierarchy *get_hierarchy(struct cgroup_ops *ops, const char *controller) + if (!controller) { + /* This is the empty unified hierarchy. */ + if (ops->hierarchies[i]->controllers && +- !ops->hierarchies[i]->controllers[0]) ++ !ops->hierarchies[i]->controllers[0]) + return ops->hierarchies[i]; + + continue; +@@ -591,7 +591,7 @@ static bool cg_legacy_handle_cpuset_hierarchy(struct hierarchy *h, char *cgname) + } + + clonechildrenpath = +- must_make_path(cgpath, "cgroup.clone_children", NULL); ++ must_make_path(cgpath, "cgroup.clone_children", NULL); + /* unified hierarchy doesn't have clone_children */ + if (!file_exists(clonechildrenpath)) { + free(clonechildrenpath); +@@ -722,7 +722,7 @@ static bool all_controllers_found(struct cgroup_ops *ops) + * be /sys/fs/cgroup/controller-list + */ + static char **cg_hybrid_get_controllers(char **klist, char **nlist, char *line, +- int type) ++ int type) + { + /* The fourth field is /sys/fs/cgroup/comma-delimited-controller-list + * for legacy hierarchies. +@@ -809,7 +809,7 @@ static char **cg_unified_get_controllers(const char *file) + } + + static struct hierarchy *add_hierarchy(struct hierarchy ***h, char **clist, char *mountpoint, +- char *container_base_path, int type) ++ char *container_base_path, int type) + { + struct hierarchy *new; + int newentry; +@@ -903,7 +903,7 @@ static bool controller_in_clist(char *cgline, char *c) + * @controller. + */ + static char *cg_hybrid_get_current_cgroup(char *basecginfo, char *controller, +- int type) ++ int type) + { + char *p = basecginfo; + +@@ -1023,7 +1023,7 @@ static void lxc_cgfsng_print_hierarchies(struct cgroup_ops *ops) + } + + static void lxc_cgfsng_print_basecg_debuginfo(char *basecginfo, char **klist, +- char **nlist) ++ char **nlist) + { + int k; + char **it; +@@ -1039,7 +1039,7 @@ static void lxc_cgfsng_print_basecg_debuginfo(char *basecginfo, char **klist, + } + + static int cgroup_rmdir(struct hierarchy **hierarchies, +- const char *container_cgroup) ++ const char *container_cgroup) + { + int i; + +@@ -1085,14 +1085,14 @@ static int cgroup_rmdir_wrapper(void *data) + ret = setresgid(nsgid, nsgid, nsgid); + if (ret < 0) { + SYSERROR("Failed to setresgid(%d, %d, %d)", (int)nsgid, +- (int)nsgid, (int)nsgid); ++ (int)nsgid, (int)nsgid); + return -1; + } + + ret = setresuid(nsuid, nsuid, nsuid); + if (ret < 0) { + SYSERROR("Failed to setresuid(%d, %d, %d)", (int)nsuid, +- (int)nsuid, (int)nsuid); ++ (int)nsuid, (int)nsuid); + return -1; + } + +@@ -1107,7 +1107,7 @@ static int cgroup_rmdir_wrapper(void *data) + + /* isulad: fix return bool instead of void*/ + __cgfsng_ops static bool cgfsng_payload_destroy(struct cgroup_ops *ops, +- struct lxc_handler *handler) ++ struct lxc_handler *handler) + { + int ret; + struct generic_userns_exec_data wrap; +@@ -1121,7 +1121,7 @@ __cgfsng_ops static bool cgfsng_payload_destroy(struct cgroup_ops *ops, + + if (handler->conf && !lxc_list_empty(&handler->conf->id_map)) + ret = userns_exec_1(handler->conf, cgroup_rmdir_wrapper, &wrap, +- "cgroup_rmdir_wrapper"); ++ "cgroup_rmdir_wrapper"); + else + ret = cgroup_rmdir(ops->hierarchies, ops->container_cgroup); + if (ret < 0) { +@@ -1186,10 +1186,10 @@ static bool cg_unified_create_cgroup(struct hierarchy *h, char *cgname, int errf + free(target); + if (ret < 0) { + SYSERROR("Could not enable \"%s\" controllers in the " +- "unified cgroup \"%s\"", add_controllers, cgroup); ++ "unified cgroup \"%s\"", add_controllers, cgroup); + lxc_write_error_message(errfd, "%s:%d: Could not enable \"%s\" controllers in the " +- "unified cgroup: \"%s\"", +- __FILE__, __LINE__, add_controllers, strerror(errno)); ++ "unified cgroup: \"%s\"", ++ __FILE__, __LINE__, add_controllers, strerror(errno)); + goto on_error; + } + } +@@ -1248,7 +1248,7 @@ static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname, int err + if (file_exists(h->container_full_path)) { // it must not already exist + ERROR("Cgroup path \"%s\" already exist.", h->container_full_path); + lxc_write_error_message(errfd, "%s:%d: Cgroup path \"%s\" already exist.", +- __FILE__, __LINE__, h->container_full_path); ++ __FILE__, __LINE__, h->container_full_path); + return false; + } + +@@ -1268,7 +1268,7 @@ static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname, int err + + /* isulad: create hierarchies path, if fail, return the error */ + __cgfsng_ops static bool cgfsng_payload_create(struct cgroup_ops *ops, +- struct lxc_handler *handler) ++ struct lxc_handler *handler) + { + int i; + char *container_cgroup = ops->container_cgroup; +@@ -1302,7 +1302,7 @@ __cgfsng_ops static bool cgfsng_payload_enter(struct cgroup_ops *ops, pid_t pid) + char *fullpath; + + fullpath = must_make_path(ops->hierarchies[i]->container_full_path, +- "cgroup.procs", NULL); ++ "cgroup.procs", NULL); + ret = lxc_write_to_file(fullpath, pidstr, len, false, 0666); + if (ret != 0) { + SYSERROR("Failed to enter cgroup \"%s\"", fullpath); +@@ -1316,7 +1316,7 @@ __cgfsng_ops static bool cgfsng_payload_enter(struct cgroup_ops *ops, pid_t pid) + } + + static int chowmod(char *path, uid_t chown_uid, gid_t chown_gid, +- mode_t chmod_mode) ++ mode_t chmod_mode) + { + int ret; + +@@ -1353,14 +1353,14 @@ static int chown_cgroup_wrapper(void *data) + ret = setresgid(nsgid, nsgid, nsgid); + if (ret < 0) { + SYSERROR("Failed to setresgid(%d, %d, %d)", +- (int)nsgid, (int)nsgid, (int)nsgid); ++ (int)nsgid, (int)nsgid, (int)nsgid); + return -1; + } + + ret = setresuid(nsuid, nsuid, nsuid); + if (ret < 0) { + SYSERROR("Failed to setresuid(%d, %d, %d)", +- (int)nsuid, (int)nsuid, (int)nsuid); ++ (int)nsuid, (int)nsuid, (int)nsuid); + return -1; + } + +@@ -1415,7 +1415,7 @@ static int chown_cgroup_wrapper(void *data) + } + + __cgfsng_ops static bool cgfsng_chown(struct cgroup_ops *ops, +- struct lxc_conf *conf) ++ struct lxc_conf *conf) + { + struct generic_userns_exec_data wrap; + +@@ -1428,7 +1428,7 @@ __cgfsng_ops static bool cgfsng_chown(struct cgroup_ops *ops, + wrap.conf = conf; + + if (userns_exec_1(conf, chown_cgroup_wrapper, &wrap, +- "chown_cgroup_wrapper") < 0) { ++ "chown_cgroup_wrapper") < 0) { + ERROR("Error requesting cgroup chown in new user namespace"); + return false; + } +@@ -1450,8 +1450,8 @@ static bool cg_mount_needs_subdirs(int type) + * control/the/cg/path. + */ + static int cg_legacy_mount_controllers(int type, struct hierarchy *h, +- char *controllerpath, char *cgpath, +- const char *container_cgroup) ++ char *controllerpath, char *cgpath, ++ const char *container_cgroup) + { + int ret, remount_flags; + char *sourcepath; +@@ -1461,16 +1461,16 @@ static int cg_legacy_mount_controllers(int type, struct hierarchy *h, + ret = mount(controllerpath, controllerpath, "cgroup", MS_BIND, NULL); + if (ret < 0) { + SYSERROR("Failed to bind mount \"%s\" onto \"%s\"", +- controllerpath, controllerpath); ++ controllerpath, controllerpath); + return -1; + } + + remount_flags = add_required_remount_flags(controllerpath, +- controllerpath, +- flags | MS_REMOUNT); ++ controllerpath, ++ flags | MS_REMOUNT); + ret = mount(controllerpath, controllerpath, "cgroup", +- remount_flags | MS_REMOUNT | MS_BIND | MS_RDONLY, +- NULL); ++ remount_flags | MS_REMOUNT | MS_BIND | MS_RDONLY, ++ NULL); + if (ret < 0) { + SYSERROR("Failed to remount \"%s\" ro", controllerpath); + return -1; +@@ -1480,7 +1480,7 @@ static int cg_legacy_mount_controllers(int type, struct hierarchy *h, + } + + sourcepath = must_make_path(h->mountpoint, h->container_base_path, +- container_cgroup, NULL); ++ container_cgroup, NULL); + if (type == LXC_AUTO_CGROUP_RO) + flags |= MS_RDONLY; + +@@ -1494,7 +1494,7 @@ static int cg_legacy_mount_controllers(int type, struct hierarchy *h, + + if (flags & MS_RDONLY) { + remount_flags = add_required_remount_flags(sourcepath, cgpath, +- flags | MS_REMOUNT); ++ flags | MS_REMOUNT); + ret = mount(sourcepath, cgpath, "cgroup", remount_flags, NULL); + if (ret < 0) { + SYSERROR("Failed to remount \"%s\" ro", cgpath); +@@ -1516,26 +1516,26 @@ static int cg_legacy_mount_controllers(int type, struct hierarchy *h, + * cgroups for the LXC_AUTO_CGROUP_FULL option. + */ + static int __cg_mount_direct(int type, struct hierarchy *h, +- const char *controllerpath) ++ const char *controllerpath) + { +- int ret; +- char *controllers = NULL; +- char *fstype = "cgroup2"; +- unsigned long flags = 0; ++ int ret; ++ char *controllers = NULL; ++ char *fstype = "cgroup2"; ++ unsigned long flags = 0; + +- flags |= MS_NOSUID; +- flags |= MS_NOEXEC; +- flags |= MS_NODEV; +- flags |= MS_RELATIME; ++ flags |= MS_NOSUID; ++ flags |= MS_NOEXEC; ++ flags |= MS_NODEV; ++ flags |= MS_RELATIME; + +- if (type == LXC_AUTO_CGROUP_RO || type == LXC_AUTO_CGROUP_FULL_RO) +- flags |= MS_RDONLY; ++ if (type == LXC_AUTO_CGROUP_RO || type == LXC_AUTO_CGROUP_FULL_RO) ++ flags |= MS_RDONLY; + +- if (h->version != CGROUP2_SUPER_MAGIC) { +- controllers = lxc_string_join(",", (const char **)h->controllers, false); +- if (!controllers) +- return -ENOMEM; +- fstype = "cgroup"; ++ if (h->version != CGROUP2_SUPER_MAGIC) { ++ controllers = lxc_string_join(",", (const char **)h->controllers, false); ++ if (!controllers) ++ return -ENOMEM; ++ fstype = "cgroup"; + } + + ret = mount("cgroup", controllerpath, fstype, flags, controllers); +@@ -1550,13 +1550,13 @@ static int __cg_mount_direct(int type, struct hierarchy *h, + } + + static inline int cg_mount_in_cgroup_namespace(int type, struct hierarchy *h, +- const char *controllerpath) ++ const char *controllerpath) + { + return __cg_mount_direct(type, h, controllerpath); + } + + static inline int cg_mount_cgroup_full(int type, struct hierarchy *h, +- const char *controllerpath) ++ const char *controllerpath) + { + if (type < LXC_AUTO_CGROUP_FULL_RO || type > LXC_AUTO_CGROUP_FULL_MIXED) + return 0; +@@ -1565,8 +1565,8 @@ static inline int cg_mount_cgroup_full(int type, struct hierarchy *h, + } + + __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, +- struct lxc_handler *handler, +- const char *root, int type) ++ struct lxc_handler *handler, ++ const char *root, int type) + { + int i, ret; + char *tmpfspath = NULL; +@@ -1583,7 +1583,7 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, + wants_force_mount = true; + } + +- if (!wants_force_mount){ ++ if (!wants_force_mount) { + if (!lxc_list_empty(&handler->conf->keepcaps)) + wants_force_mount = !in_caplist(CAP_SYS_ADMIN, &handler->conf->keepcaps); + else +@@ -1606,13 +1606,14 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, + goto on_error; + } + ret = safe_mount(NULL, tmpfspath, "tmpfs", +- MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME, +- "size=10240k,mode=755", root); ++ MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME, ++ "size=10240k,mode=755", root); + if (ret < 0) + goto on_error; + + for (i = 0; ops->hierarchies[i]; i++) { +- char *controllerpath, *path2; ++ char *controllerpath = NULL; ++ char *path2 = NULL; + struct hierarchy *h = ops->hierarchies[i]; + char *controller = strrchr(h->mountpoint, '/'); + +@@ -1676,7 +1677,7 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, + } + + ret = cg_legacy_mount_controllers(type, h, controllerpath, +- path2, ops->container_cgroup); ++ path2, ops->container_cgroup); + free(controllerpath); + free(path2); + if (ret < 0) +@@ -1685,7 +1686,7 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, + + // isulad: symlink subcgroup + if (merged) { +- char **mc; ++ char **mc = NULL; + for (mc = merged; *mc; mc++) { + char *token; + char *copy = must_copy_string(*mc); +@@ -1710,44 +1711,44 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, + // isulad: remount /sys/fs/cgroup to readonly + if (type == LXC_AUTO_CGROUP_FULL_RO || type == LXC_AUTO_CGROUP_RO) { + ret = mount(tmpfspath, tmpfspath, "bind", +- MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_RELATIME|MS_RDONLY|MS_BIND|MS_REMOUNT, NULL); ++ MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_RELATIME|MS_RDONLY|MS_BIND|MS_REMOUNT, NULL); + if (ret < 0) { + SYSERROR("Failed to remount /sys/fs/cgroup."); + goto on_error; + } + } + +- // isulad: remount /sys/fs/cgroup/systemd to readwrite for system container +- if (handler->conf->systemd != NULL && strcmp(handler->conf->systemd, "true") == 0) { +- // isulad: don't use the unified hierarchy for the systemd cgroup +- unifiedpath = must_make_path(root, "/sys/fs/cgroup/unified", NULL); +- if (dir_exists(unifiedpath)) { +- ret = umount2(unifiedpath, MNT_DETACH); +- if (ret < 0) { +- SYSERROR("Failed to umount /sys/fs/cgroup/unified."); +- goto on_error; +- } +- } +- +- systemdpath = must_make_path(root, "/sys/fs/cgroup/systemd", NULL); +- ret = mount(systemdpath, systemdpath, "bind", +- MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_RELATIME|MS_BIND|MS_REMOUNT, NULL); +- if (ret < 0) { +- SYSERROR("Failed to remount /sys/fs/cgroup/systemd."); +- goto on_error; +- } +- } ++ // isulad: remount /sys/fs/cgroup/systemd to readwrite for system container ++ if (handler->conf->systemd != NULL && strcmp(handler->conf->systemd, "true") == 0) { ++ // isulad: don't use the unified hierarchy for the systemd cgroup ++ unifiedpath = must_make_path(root, "/sys/fs/cgroup/unified", NULL); ++ if (dir_exists(unifiedpath)) { ++ ret = umount2(unifiedpath, MNT_DETACH); ++ if (ret < 0) { ++ SYSERROR("Failed to umount /sys/fs/cgroup/unified."); ++ goto on_error; ++ } ++ } ++ ++ systemdpath = must_make_path(root, "/sys/fs/cgroup/systemd", NULL); ++ ret = mount(systemdpath, systemdpath, "bind", ++ MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_RELATIME|MS_BIND|MS_REMOUNT, NULL); ++ if (ret < 0) { ++ SYSERROR("Failed to remount /sys/fs/cgroup/systemd."); ++ goto on_error; ++ } ++ } + + retval = true; + + on_error: + free(tmpfspath); +- if (systemdpath != NULL) { +- free(systemdpath); +- } +- if (unifiedpath != NULL) { +- free(unifiedpath); +- } ++ if (systemdpath != NULL) { ++ free(systemdpath); ++ } ++ if (unifiedpath != NULL) { ++ free(unifiedpath); ++ } + lxc_free_array((void **)merged, free); + return retval; + } +@@ -1767,7 +1768,7 @@ static int recursive_count_nrtasks(char *dirname) + struct stat mystat; + + if (!strcmp(direntp->d_name, ".") || +- !strcmp(direntp->d_name, "..")) ++ !strcmp(direntp->d_name, "..")) + continue; + + path = must_make_path(dirname, direntp->d_name, NULL); +@@ -1779,7 +1780,7 @@ static int recursive_count_nrtasks(char *dirname) + goto next; + + count += recursive_count_nrtasks(path); +- next: ++next: + free(path); + } + +@@ -1821,8 +1822,8 @@ __cgfsng_ops static bool cgfsng_escape(const struct cgroup_ops *ops) + char *fullpath; + + fullpath = must_make_path(ops->hierarchies[i]->mountpoint, +- ops->hierarchies[i]->container_base_path, +- "cgroup.procs", NULL); ++ ops->hierarchies[i]->container_base_path, ++ "cgroup.procs", NULL); + ret = lxc_write_to_file(fullpath, "0", 2, false, 0666); + if (ret != 0) { + SYSERROR("Failed to escape to cgroup \"%s\"", fullpath); +@@ -1885,7 +1886,7 @@ __cgfsng_ops static bool cgfsng_unfreeze(struct cgroup_ops *ops) + } + + __cgfsng_ops static const char *cgfsng_get_cgroup(struct cgroup_ops *ops, +- const char *controller, bool skip_mount) ++ const char *controller, bool skip_mount) + { + struct hierarchy *h; + +@@ -1905,8 +1906,8 @@ __cgfsng_ops static const char *cgfsng_get_cgroup(struct cgroup_ops *ops, + * which must be freed by the caller. + */ + static inline char *build_full_cgpath_from_monitorpath(struct hierarchy *h, +- const char *inpath, +- const char *filename) ++ const char *inpath, ++ const char *filename) + { + return must_make_path(h->mountpoint, inpath, filename, NULL); + } +@@ -1921,8 +1922,8 @@ static inline char *build_full_cgpath_from_monitorpath(struct hierarchy *h, + * cgroup for the attaching process. + */ + static int __cg_unified_attach(const struct hierarchy *h, const char *name, +- const char *lxcpath, const char *pidstr, +- size_t pidstr_len, const char *controller) ++ const char *lxcpath, const char *pidstr, ++ size_t pidstr_len, const char *controller) + { + int ret; + size_t len; +@@ -1952,7 +1953,7 @@ static int __cg_unified_attach(const struct hierarchy *h, const char *name, + do { + if (idx) + ret = snprintf(full_path, len + 1, "%s/lxc-%d", +- base_path, idx); ++ base_path, idx); + else + ret = snprintf(full_path, len + 1, "%s/lxc", base_path); + if (ret < 0 || (size_t)ret >= len + 1) +@@ -1987,7 +1988,7 @@ on_error: + } + + __cgfsng_ops static bool cgfsng_attach(struct cgroup_ops *ops, const char *name, +- const char *lxcpath, pid_t pid) ++ const char *lxcpath, pid_t pid) + { + int i, len, ret; + char pidstr[INTTYPE_TO_STRLEN(pid_t)]; +@@ -2003,7 +2004,7 @@ __cgfsng_ops static bool cgfsng_attach(struct cgroup_ops *ops, const char *name, + + if (h->version == CGROUP2_SUPER_MAGIC) { + ret = __cg_unified_attach(h, name, lxcpath, pidstr, len, +- h->controllers[0]); ++ h->controllers[0]); + if (ret < 0) + return false; + +@@ -2034,8 +2035,8 @@ __cgfsng_ops static bool cgfsng_attach(struct cgroup_ops *ops, const char *name, + * commands API for the cgroup path. + */ + __cgfsng_ops static int cgfsng_get(struct cgroup_ops *ops, const char *filename, +- char *value, size_t len, const char *name, +- const char *lxcpath) ++ char *value, size_t len, const char *name, ++ const char *lxcpath) + { + int ret = -1; + size_t controller_len; +@@ -2073,8 +2074,8 @@ __cgfsng_ops static int cgfsng_get(struct cgroup_ops *ops, const char *filename, + * commands API for the cgroup path. + */ + __cgfsng_ops static int cgfsng_set(struct cgroup_ops *ops, +- const char *filename, const char *value, +- const char *name, const char *lxcpath) ++ const char *filename, const char *value, ++ const char *name, const char *lxcpath) + { + int ret = -1; + size_t controller_len; +@@ -2189,7 +2190,7 @@ out: + * we created the cgroups. + */ + static int cg_legacy_set_data(struct cgroup_ops *ops, const char *filename, +- const char *value) ++ const char *value) + { + size_t len; + char *fullpath, *p; +@@ -2228,8 +2229,8 @@ static int cg_legacy_set_data(struct cgroup_ops *ops, const char *filename, + ret = lxc_write_to_file(fullpath, value, strlen(value), false, 0666); + if (ret) { + lxc_write_error_message(ops->errfd, +- "%s:%d: setting cgroup config for ready process caused \"failed to write %s to %s: %s\".", +- __FILE__, __LINE__, value, fullpath, strerror(errno)); ++ "%s:%d: setting cgroup config for ready process caused \"failed to write %s to %s: %s\".", ++ __FILE__, __LINE__, value, fullpath, strerror(errno)); + } + free(fullpath); + return ret; +@@ -2239,15 +2240,16 @@ static int cg_legacy_set_data(struct cgroup_ops *ops, const char *filename, + * we created the cgroups. + */ + static int cg_legacy_get_data(struct cgroup_ops *ops, const char *filename, +- char *value, size_t len) ++ char *value, size_t len) + { +- char *fullpath, *p; +- struct hierarchy *h; ++ char *fullpath = NULL; ++ char *p = NULL; ++ struct hierarchy *h = NULL; + int ret = 0; + char *controller = NULL; + + len = strlen(filename); +- controller = alloca(len + 1); ++ controller = calloc(1, len + 1); + (void)strlcpy(controller, filename, len + 1); + + p = strchr(controller, '.'); +@@ -2262,23 +2264,25 @@ static int cg_legacy_get_data(struct cgroup_ops *ops, const char *filename, + "driver or not enabled on the cgroup hierarchy", + controller); + errno = ENOENT; ++ free(controller); + return -ENOENT; + } + + fullpath = must_make_path(h->container_full_path, filename, NULL); + ret = lxc_read_from_file(fullpath, value, len); + free(fullpath); ++ free(controller); + return ret; + } + + static bool __cg_legacy_setup_limits(struct cgroup_ops *ops, +- struct lxc_list *cgroup_settings, +- bool do_devices) ++ struct lxc_list *cgroup_settings, ++ bool do_devices) + { + struct lxc_list *iterator, *next, *sorted_cgroup_settings; + struct lxc_cgroup *cg; + bool ret = false; +- char value[21]; ++ char value[21 + 1] = { 0 }; + long long int readvalue, setvalue; + + if (lxc_list_empty(cgroup_settings)) +@@ -2318,7 +2322,7 @@ static bool __cg_legacy_setup_limits(struct cgroup_ops *ops, + + // isulad: check cpu shares + if (strcmp(cg->subsystem, "cpu.shares") == 0) { +- if (cg_legacy_get_data(ops, cg->subsystem, value, sizeof(value)) < 0) { ++ if (cg_legacy_get_data(ops, cg->subsystem, value, sizeof(value) - 1) < 0) { + SYSERROR("Error get %s", cg->subsystem); + goto out; + } +@@ -2334,14 +2338,14 @@ static bool __cg_legacy_setup_limits(struct cgroup_ops *ops, + if (setvalue > readvalue) { + ERROR("The maximum allowed cpu-shares is %s", value); + lxc_write_error_message(ops->errfd, +- "%s:%d: setting cgroup config for ready process caused \"The maximum allowed cpu-shares is %s\".", +- __FILE__, __LINE__, value); ++ "%s:%d: setting cgroup config for ready process caused \"The maximum allowed cpu-shares is %s\".", ++ __FILE__, __LINE__, value); + goto out; + } else if (setvalue < readvalue) { + ERROR("The minimum allowed cpu-shares is %s", value); + lxc_write_error_message(ops->errfd, +- "%s:%d: setting cgroup config for ready process caused \"The minimum allowed cpu-shares is %s\".", +- __FILE__, __LINE__, value); ++ "%s:%d: setting cgroup config for ready process caused \"The minimum allowed cpu-shares is %s\".", ++ __FILE__, __LINE__, value); + goto out; + } + } +@@ -2359,7 +2363,7 @@ out: + } + + static bool __cg_unified_setup_limits(struct cgroup_ops *ops, +- struct lxc_list *cgroup_settings) ++ struct lxc_list *cgroup_settings) + { + struct lxc_list *iterator; + struct hierarchy *h = ops->unified; +@@ -2380,7 +2384,7 @@ static bool __cg_unified_setup_limits(struct cgroup_ops *ops, + free(fullpath); + if (ret < 0) { + SYSERROR("Failed to set \"%s\" to \"%s\"", +- cg->subsystem, cg->value); ++ cg->subsystem, cg->value); + return false; + } + TRACE("Set \"%s\" to \"%s\"", cg->subsystem, cg->value); +@@ -2391,8 +2395,8 @@ static bool __cg_unified_setup_limits(struct cgroup_ops *ops, + } + + __cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops, +- struct lxc_conf *conf, +- bool do_devices) ++ struct lxc_conf *conf, ++ bool do_devices) + { + bool bret; + +@@ -2404,7 +2408,7 @@ __cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops, + } + + static bool cgroup_use_wants_controllers(const struct cgroup_ops *ops, +- char **controllers) ++ char **controllers) + { + char **cur_ctrl, **cur_use; + +@@ -2537,8 +2541,8 @@ static bool cg_hybrid_init(struct cgroup_ops *ops) + char *cgv2_ctrl_path; + + cgv2_ctrl_path = must_make_path(mountpoint, base_cgroup, +- "cgroup.controllers", +- NULL); ++ "cgroup.controllers", ++ NULL); + + controller_list = cg_unified_get_controllers(cgv2_ctrl_path); + free(cgv2_ctrl_path); +@@ -2559,7 +2563,7 @@ static bool cg_hybrid_init(struct cgroup_ops *ops) + + continue; + +- next: ++next: + free_string_list(controller_list); + free(mountpoint); + free(base_cgroup); +@@ -2658,7 +2662,7 @@ static int cg_unified_init(struct cgroup_ops *ops) + */ + mountpoint = must_copy_string("/sys/fs/cgroup"); + subtree_path = must_make_path(mountpoint, base_cgroup, +- "cgroup.subtree_control", NULL); ++ "cgroup.subtree_control", NULL); + delegatable = cg_unified_get_controllers(subtree_path); + free(subtree_path); + if (!delegatable) +@@ -2710,8 +2714,9 @@ static bool cg_init(struct cgroup_ops *ops) + + __cgfsng_ops static bool cgfsng_data_init(struct cgroup_ops *ops, struct lxc_handler *handler) + { +- const char *cgroup_pattern; +- char *container_cgroup, *tmp; ++ const char *cgroup_pattern = NULL; ++ char *container_cgroup = NULL; ++ char *tmp = NULL; + struct lxc_conf *conf = NULL; + size_t len; + +@@ -2730,7 +2735,9 @@ __cgfsng_ops static bool cgfsng_data_init(struct cgroup_ops *ops, struct lxc_han + /* isulad: init ops->container_cgroup here instead of in cgfsng_payload_create*/ + if (conf) { + if (conf->cgroup_meta.dir) +- tmp = lxc_string_join("/", (const char *[]){conf->cgroup_meta.dir, handler->name, NULL}, false); ++ tmp = lxc_string_join("/", (const char *[]) { ++ conf->cgroup_meta.dir, handler->name, NULL ++ }, false); + else + tmp = lxc_string_replace("%n", handler->name, ops->cgroup_pattern); + if (!tmp) { +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 3780966..ec1667d 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -351,8 +351,8 @@ static int run_buffer(char *buffer) + } + + int run_script_argv(const char *name, unsigned int hook_version, +- const char *section, const char *script, +- const char *hookname, char **argv) ++ const char *section, const char *script, ++ const char *hookname, char **argv) + { + int buf_pos, i, ret; + char *buffer; +@@ -407,7 +407,7 @@ int run_script_argv(const char *name, unsigned int hook_version, + ret = setenv("LXC_HOOK_TYPE", hookname, 1); + if (ret < 0) { + SYSERROR("Failed to set environment variable: " +- "LXC_HOOK_TYPE=%s", hookname); ++ "LXC_HOOK_TYPE=%s", hookname); + goto on_error; + } + TRACE("Set environment variable: LXC_HOOK_TYPE=%s", hookname); +@@ -415,7 +415,7 @@ int run_script_argv(const char *name, unsigned int hook_version, + ret = setenv("LXC_HOOK_SECTION", section, 1); + if (ret < 0) { + SYSERROR("Failed to set environment variable: " +- "LXC_HOOK_SECTION=%s", section); ++ "LXC_HOOK_SECTION=%s", section); + goto on_error; + } + TRACE("Set environment variable: LXC_HOOK_SECTION=%s", section); +@@ -429,7 +429,7 @@ int run_script_argv(const char *name, unsigned int hook_version, + ret = setenv("LXC_NET_TYPE", argv[0], 1); + if (ret < 0) { + SYSERROR("Failed to set environment variable: " +- "LXC_NET_TYPE=%s", argv[0]); ++ "LXC_NET_TYPE=%s", argv[0]); + goto on_error; + } + TRACE("Set environment variable: LXC_NET_TYPE=%s", argv[0]); +@@ -440,7 +440,7 @@ int run_script_argv(const char *name, unsigned int hook_version, + ret = setenv("LXC_NET_PARENT", parent, 1); + if (ret < 0) { + SYSERROR("Failed to set environment " +- "variable: LXC_NET_PARENT=%s", parent); ++ "variable: LXC_NET_PARENT=%s", parent); + goto on_error; + } + TRACE("Set environment variable: LXC_NET_PARENT=%s", parent); +@@ -448,7 +448,7 @@ int run_script_argv(const char *name, unsigned int hook_version, + ret = setenv("LXC_NET_PARENT", parent, 1); + if (ret < 0) { + SYSERROR("Failed to set environment " +- "variable: LXC_NET_PARENT=%s", parent); ++ "variable: LXC_NET_PARENT=%s", parent); + goto on_error; + } + TRACE("Set environment variable: LXC_NET_PARENT=%s", parent); +@@ -458,7 +458,7 @@ int run_script_argv(const char *name, unsigned int hook_version, + ret = setenv("LXC_NET_PEER", peer, 1); + if (ret < 0) { + SYSERROR("Failed to set environment " +- "variable: LXC_NET_PEER=%s", peer); ++ "variable: LXC_NET_PEER=%s", peer); + goto on_error; + } + TRACE("Set environment variable: LXC_NET_PEER=%s", peer); +@@ -466,7 +466,7 @@ int run_script_argv(const char *name, unsigned int hook_version, + ret = setenv("LXC_NET_PARENT", parent, 1); + if (ret < 0) { + SYSERROR("Failed to set environment " +- "variable: LXC_NET_PARENT=%s", parent); ++ "variable: LXC_NET_PARENT=%s", parent); + goto on_error; + } + TRACE("Set environment variable: LXC_NET_PARENT=%s", parent); +@@ -600,7 +600,7 @@ int pin_rootfs(const char *rootfs) + * honored. + */ + unsigned long add_required_remount_flags(const char *s, const char *d, +- unsigned long flags) ++ unsigned long flags) + { + #ifdef HAVE_STATVFS + int ret; +@@ -728,10 +728,10 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha + } + + mflags = add_required_remount_flags(source, destination, +- default_mounts[i].flags); ++ default_mounts[i].flags); + r = safe_mount(source, destination, default_mounts[i].fstype, +- mflags, default_mounts[i].options, +- conf->rootfs.path ? conf->rootfs.mount : NULL); ++ mflags, default_mounts[i].options, ++ conf->rootfs.path ? conf->rootfs.mount : NULL); + saved_errno = errno; + if (r < 0 && errno == ENOENT) { + INFO("Mount source for \"%s\" on \"%s\" does " +@@ -781,9 +781,9 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha + cg_flags |= LXC_AUTO_CGROUP_FORCE; + + if (!handler->cgroup_ops->mount(handler->cgroup_ops, +- handler, +- conf->rootfs.path ? conf->rootfs.mount : "", +- cg_flags)) { ++ handler, ++ conf->rootfs.path ? conf->rootfs.mount : "", ++ cg_flags)) { + SYSERROR("Failed to mount \"/sys/fs/cgroup\""); + return -1; + } +@@ -832,7 +832,7 @@ static int lxc_setup_dev_symlinks(const struct lxc_rootfs *rootfs) + const struct dev_symlinks *d = &dev_symlinks[i]; + + ret = snprintf(path, sizeof(path), "%s/dev/%s", +- rootfs->path ? rootfs->mount : "", d->name); ++ rootfs->path ? rootfs->mount : "", d->name); + if (ret < 0 || ret >= PATH_MAX) + return -1; + +@@ -901,7 +901,7 @@ static int lxc_setup_ttys(struct lxc_conf *conf) + if (ttydir) { + /* create dev/lxc/tty%d" */ + ret = snprintf(lxcpath, sizeof(lxcpath), +- "/dev/%s/tty%d", ttydir, i + 1); ++ "/dev/%s/tty%d", ttydir, i + 1); + if (ret < 0 || (size_t)ret >= sizeof(lxcpath)) + return -1; + +@@ -920,14 +920,14 @@ static int lxc_setup_ttys(struct lxc_conf *conf) + ret = mount(tty->name, lxcpath, "none", MS_BIND, 0); + if (ret < 0) { + SYSWARN("Failed to bind mount \"%s\" onto \"%s\"", +- tty->name, lxcpath); ++ tty->name, lxcpath); + continue; + } + DEBUG("Bind mounted \"%s\" onto \"%s\"", tty->name, + lxcpath); + + ret = snprintf(lxcpath, sizeof(lxcpath), "%s/tty%d", +- ttydir, i + 1); ++ ttydir, i + 1); + if (ret < 0 || (size_t)ret >= sizeof(lxcpath)) + return -1; + +@@ -1122,7 +1122,7 @@ on_error: + * error, log it but don't fail yet. + */ + static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs, +- const char *lxcpath, char *systemd) ++ const char *lxcpath, const char *systemd) + { + int ret; + size_t clen; +@@ -1147,21 +1147,21 @@ static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs, + goto reset_umask; + } + +- if (systemd != NULL && !strcmp(systemd, "true")) { +- ret = mount(path, path, "", MS_BIND, NULL); +- if (ret < 0) { +- SYSERROR("Failed to bind mount path \"%s\"", path); +- goto reset_umask; +- } +- } else { +- ret = safe_mount("none", path, "tmpfs", 0, "size=500000,mode=755", +- rootfs->path ? rootfs->mount : NULL); +- if (ret < 0) { +- SYSERROR("Failed to mount tmpfs on \"%s\"", path); +- goto reset_umask; +- } +- TRACE("Mounted tmpfs on \"%s\"", path); +- } ++ if (systemd != NULL && !strcmp(systemd, "true")) { ++ ret = mount(path, path, "", MS_BIND, NULL); ++ if (ret < 0) { ++ SYSERROR("Failed to bind mount path \"%s\"", path); ++ goto reset_umask; ++ } ++ } else { ++ ret = safe_mount("none", path, "tmpfs", 0, "size=500000,mode=755", ++ rootfs->path ? rootfs->mount : NULL); ++ if (ret < 0) { ++ SYSERROR("Failed to mount tmpfs on \"%s\"", path); ++ goto reset_umask; ++ } ++ TRACE("Mounted tmpfs on \"%s\"", path); ++ } + + ret = snprintf(path, clen, "%s/dev/pts", rootfs->path ? rootfs->mount : ""); + if (ret < 0 || (size_t)ret >= clen) { +@@ -1220,7 +1220,7 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) + int use_mknod = LXC_DEVNODE_MKNOD; + + ret = snprintf(path, PATH_MAX, "%s/dev", +- rootfs->path ? rootfs->mount : ""); ++ rootfs->path ? rootfs->mount : ""); + if (ret < 0 || ret >= PATH_MAX) + return -1; + +@@ -1236,7 +1236,7 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) + const struct lxc_device_node *device = &lxc_devices[i]; + + ret = snprintf(path, PATH_MAX, "%s/dev/%s", +- rootfs->path ? rootfs->mount : "", device->name); ++ rootfs->path ? rootfs->mount : "", device->name); + if (ret < 0 || ret >= PATH_MAX) + return -1; + +@@ -1294,10 +1294,10 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) + return -1; + + ret = safe_mount(hostpath, path, 0, MS_BIND, NULL, +- rootfs->path ? rootfs->mount : NULL); ++ rootfs->path ? rootfs->mount : NULL); + if (ret < 0) { + SYSERROR("Failed to bind mount host device node \"%s\" " +- "onto \"%s\"", hostpath, path); ++ "onto \"%s\"", hostpath, path); + return -1; + } + DEBUG("Bind mounted host device node \"%s\" onto \"%s\"", +@@ -1350,7 +1350,9 @@ static int rootfs_parent_mount_private(char *rootfs) + } + + while (getline(&line, &len, f) != -1) { +- char *target, *opts, *tmptarget; ++ char *target = NULL; ++ char *opts = NULL; ++ char *tmptarget = NULL; + target = get_field(line, 4); + if (!target) + continue; +@@ -1401,10 +1403,10 @@ static int rootfs_parent_mount_private(char *rootfs) + static int lxc_mount_rootfs(struct lxc_conf *conf) + { + int ret; +- struct lxc_storage *bdev; ++ struct lxc_storage *bdev = NULL; + struct lxc_rootfs *rootfs = &conf->rootfs; + unsigned long flags, mntflags, pflags; +- char *mntdata; ++ char *mntdata = NULL; + + if (!rootfs->path) { + ret = mount("", "/", NULL, MS_SLAVE | MS_REC, 0); +@@ -1430,7 +1432,7 @@ static int lxc_mount_rootfs(struct lxc_conf *conf) + ret = access(rootfs->mount, F_OK); + if (ret != 0) { + SYSERROR("Failed to access to \"%s\". Check it is present", +- rootfs->mount); ++ rootfs->mount); + return -1; + } + +@@ -1540,7 +1542,7 @@ static bool remount_readwrite(const char *path) + if (ret < 0) + goto on_error; + ret = mount(path, path, "", MS_BIND | MS_REMOUNT | MS_REC | \ +- MS_NOEXEC | MS_NOSUID | MS_NODEV, ""); ++ MS_NOEXEC | MS_NOSUID | MS_NODEV, ""); + if (ret < 0) + goto on_error; + } else if (errno == EBUSY) { +@@ -1601,7 +1603,7 @@ static bool remount_readonly(const char *path) + if (ret < 0) + goto on_error; + ret = mount(path, path, "", MS_BIND | MS_REMOUNT | MS_RDONLY | MS_REC | \ +- MS_NOEXEC | MS_NOSUID | MS_NODEV, ""); ++ MS_NOEXEC | MS_NOSUID | MS_NODEV, ""); + if (ret < 0) + goto on_error; + } else if (errno == EBUSY) { +@@ -1626,8 +1628,8 @@ static int setup_rootfs_maskedpaths(struct lxc_list *maskedpaths) + struct lxc_list *it; + + lxc_list_for_each(it, maskedpaths) { +- if (!mask_path((char *)it->elem)) +- return -1; ++ if (!mask_path((char *)it->elem)) ++ return -1; + } + + return 0; +@@ -1638,8 +1640,8 @@ static int setup_rootfs_ropaths(struct lxc_list *ropaths) + struct lxc_list *it; + + lxc_list_for_each(it, ropaths) { +- if (!remount_readonly((char *)it->elem)) +- return -1; ++ if (!remount_readonly((char *)it->elem)) ++ return -1; + } + + return 0; +@@ -1873,8 +1875,8 @@ static int lxc_setup_rootfs_switch_root(const struct lxc_rootfs *rootfs) + } + + static const struct id_map *find_mapped_nsid_entry(struct lxc_conf *conf, +- unsigned id, +- enum idtype idtype) ++ unsigned id, ++ enum idtype idtype) + { + struct lxc_list *it; + struct id_map *map; +@@ -1918,7 +1920,7 @@ static int lxc_setup_devpts(struct lxc_conf *conf) + } + + ret = snprintf(devpts_mntopts, sizeof(devpts_mntopts), "%s,max=%zu", +- default_devpts_mntopts, conf->pty_max); ++ default_devpts_mntopts, conf->pty_max); + if (ret < 0 || (size_t)ret >= sizeof(devpts_mntopts)) + return -1; + +@@ -2031,7 +2033,7 @@ static int setup_personality(int persona) + } + + static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs, +- const struct lxc_terminal *console) ++ const struct lxc_terminal *console) + { + int ret; + char path[PATH_MAX]; +@@ -2069,7 +2071,7 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs, + ret = fchmod(console->slave, S_IXUSR | S_IXGRP); + if (ret < 0) { + SYSERROR("Failed to set mode \"0%o\" to \"%s\"", +- S_IXUSR | S_IXGRP, console->name); ++ S_IXUSR | S_IXGRP, console->name); + return -errno; + } + +@@ -2084,8 +2086,8 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs, + } + + static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, +- const struct lxc_terminal *console, +- char *ttydir) ++ const struct lxc_terminal *console, ++ char *ttydir) + { + int ret; + char path[PATH_MAX], lxcpath[PATH_MAX]; +@@ -2104,7 +2106,7 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, + SYSERROR("Failed to create \"%s\"", path); + return -errno; + } +- DEBUG("Created directory for console and tty devices at \"%s\"", path); ++ DEBUG("Created directory for console and tty devices at \"%s\"", path); + + ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/console", rootfs_path, ttydir); + if (ret < 0 || (size_t)ret >= sizeof(lxcpath)) +@@ -2140,7 +2142,7 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, + ret = fchmod(console->slave, S_IXUSR | S_IXGRP); + if (ret < 0) { + SYSERROR("Failed to set mode \"0%o\" to \"%s\"", +- S_IXUSR | S_IXGRP, console->name); ++ S_IXUSR | S_IXGRP, console->name); + return -errno; + } + +@@ -2166,7 +2168,7 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, + } + + static int lxc_setup_console(const struct lxc_rootfs *rootfs, +- const struct lxc_terminal *console, char *ttydir) ++ const struct lxc_terminal *console, char *ttydir) + { + + if (!ttydir) +@@ -2236,7 +2238,7 @@ int parse_mntopts(const char *mntopts, unsigned long *mntflags, unsigned long *p + *data = 0; + + lxc_iterate_parts(p, s, ",") +- parse_mntopt(p, mntflags, pflags, &data, size); ++ parse_mntopt(p, mntflags, pflags, &data, size); + + if (*data) + *mntdata = data; +@@ -2248,9 +2250,9 @@ int parse_mntopts(const char *mntopts, unsigned long *mntflags, unsigned long *p + } + + static int mount_entry(const char *fsname, const char *target, +- const char *fstype, unsigned long mountflags, +- unsigned long pflags, const char *data, bool optional, +- bool dev, bool relative, const char *rootfs) ++ const char *fstype, unsigned long mountflags, ++ unsigned long pflags, const char *data, bool optional, ++ bool dev, bool relative, const char *rootfs) + { + int ret; + char srcbuf[PATH_MAX]; +@@ -2269,7 +2271,7 @@ static int mount_entry(const char *fsname, const char *target, + } + + ret = safe_mount(srcpath, target, fstype, mountflags & ~MS_REMOUNT, data, +- rootfs); ++ rootfs); + if (ret < 0) { + if (optional) { + SYSINFO("Failed to mount \"%s\" on \"%s\" (optional)", +@@ -2278,7 +2280,7 @@ static int mount_entry(const char *fsname, const char *target, + } + + SYSERROR("Failed to mount \"%s\" on \"%s\"", +- srcpath ? srcpath : "(null)", target); ++ srcpath ? srcpath : "(null)", target); + return -1; + } + +@@ -2315,7 +2317,7 @@ static int mount_entry(const char *fsname, const char *target, + */ + if (!(mountflags & MS_REMOUNT)) { + if (!(required_flags & ~mountflags) && +- rqd_flags == 0) { ++ rqd_flags == 0) { + DEBUG("Mountflags already were %lu, " + "skipping remount", mountflags); + goto skipremount; +@@ -2335,13 +2337,13 @@ static int mount_entry(const char *fsname, const char *target, + } + + SYSERROR("Failed to mount \"%s\" on \"%s\"", +- srcpath ? srcpath : "(null)", target); ++ srcpath ? srcpath : "(null)", target); + return -1; + } + } + + #ifdef HAVE_STATVFS +- skipremount: ++skipremount: + #endif + if (pflags) { + ret = mount(NULL, target, NULL, pflags, NULL); +@@ -2352,7 +2354,7 @@ static int mount_entry(const char *fsname, const char *target, + return 0; + } else { + SYSERROR("Failed to change mount propagation " +- "for \"%s\" (optional)", target); ++ "for \"%s\" (optional)", target); + return -1; + } + } +@@ -2416,10 +2418,12 @@ static int check_mount_destination(const char *rootfs, const char *dest) + "/proc/net/dev", + NULL + }; +- const char **valid, **invalid; ++ const char **valid = NULL; ++ const char **invalid = NULL; + + for(valid = valid_destinations; *valid != NULL; valid++) { +- char *fullpath, *relpath; ++ char *fullpath = NULL; ++ char *relpath = NULL; + const char *parts[3] = { + rootfs, + *valid, +@@ -2469,9 +2473,9 @@ static int check_mount_destination(const char *rootfs, const char *dest) + } + + static int mount_entry_create_dir_file(const struct mntent *mntent, +- const char *path, +- const struct lxc_rootfs *rootfs, +- const char *lxc_name, const char *lxc_path) ++ const char *path, ++ const struct lxc_rootfs *rootfs, ++ const char *lxc_name, const char *lxc_path) + { + int ret; + char *p1, *p2; +@@ -2487,7 +2491,7 @@ static int mount_entry_create_dir_file(const struct mntent *mntent, + if (ret < 0 && errno != EEXIST) { + SYSERROR("Failed to create directory \"%s\"", path); + lxc_write_error_message(rootfs->errfd, "%s:%d: mkdir %s: %s.", +- __FILE__, __LINE__, path, strerror(errno)); ++ __FILE__, __LINE__, path, strerror(errno)); + return -1; + } + } +@@ -2510,14 +2514,14 @@ static int mount_entry_create_dir_file(const struct mntent *mntent, + if (ret < 0 && errno != EEXIST) { + SYSERROR("Failed to create directory \"%s\"", path); + lxc_write_error_message(rootfs->errfd, "%s:%d: mkdir %s: %s.", +- __FILE__, __LINE__, p2, strerror(errno)); ++ __FILE__, __LINE__, p2, strerror(errno)); + return -1; + } + + ret = mknod(path, S_IFREG | 0000, 0); + if (ret < 0 && errno != EEXIST) { + lxc_write_error_message(rootfs->errfd, "%s:%d: open %s: %s.", +- __FILE__, __LINE__, path, strerror(errno)); ++ __FILE__, __LINE__, path, strerror(errno)); + return -errno; + } + +@@ -2525,7 +2529,7 @@ static int mount_entry_create_dir_file(const struct mntent *mntent, + } + + static int mount_entry_with_loop_dev(const char *src, const char *dest, const char *fstype, +- char *mnt_opts, const char *rootfs) ++ char *mnt_opts, const char *rootfs) + { + int srcfd = -1, destfd, ret, saved_errno; + char srcbuf[50], destbuf[50]; // only needs enough for /proc/self/fd/ +@@ -2603,10 +2607,10 @@ retry: + /* rootfs, lxc_name, and lxc_path can be NULL when the container is created + * without a rootfs. */ + static inline int mount_entry_on_generic(struct mntent *mntent, +- const char *path, +- const struct lxc_rootfs *rootfs, +- const char *lxc_name, +- const char *lxc_path) ++ const char *path, ++ const struct lxc_rootfs *rootfs, ++ const char *lxc_name, ++ const char *lxc_path) + { + int ret; + unsigned long mntflags, pflags; +@@ -2631,7 +2635,7 @@ static inline int mount_entry_on_generic(struct mntent *mntent, + if (!rpath) { + ERROR("Failed to get real path of '%s' in scope '%s'.", path, rootfs_path); + lxc_write_error_message(rootfs->errfd, "%s:%d: failed to get real path of '%s' in scope '%s'.", +- __FILE__, __LINE__, path, rootfs_path); ++ __FILE__, __LINE__, path, rootfs_path); + return -1; + } + dest = rpath; +@@ -2640,7 +2644,7 @@ static inline int mount_entry_on_generic(struct mntent *mntent, + if (ret) { + ERROR("Mount destination is invalid: '%s'", dest); + lxc_write_error_message(rootfs->errfd, "%s:%d: mount destination is invalid: '%s'.", +- __FILE__, __LINE__, dest); ++ __FILE__, __LINE__, dest); + free(rpath); + return -1; + } +@@ -2665,14 +2669,14 @@ static inline int mount_entry_on_generic(struct mntent *mntent, + // isulad: support squashfs + if (strcmp(mntent->mnt_type, "squashfs") == 0) { + ret = mount_entry_with_loop_dev(mntent->mnt_fsname, dest, mntent->mnt_type, +- mntent->mnt_opts, rootfs_path); ++ mntent->mnt_opts, rootfs_path); + } else { + ret = mount_entry(mntent->mnt_fsname, dest, mntent->mnt_type, mntflags, +- pflags, mntdata, optional, dev, relative, rootfs_path); ++ pflags, mntdata, optional, dev, relative, rootfs_path); + } + if (ret < 0) { + lxc_write_error_message(rootfs->errfd, "%s:%d: failed to mount %s as type %s.", +- __FILE__, __LINE__, mntent->mnt_fsname, mntent->mnt_type); ++ __FILE__, __LINE__, mntent->mnt_fsname, mntent->mnt_type); + } + + free(mntdata); +@@ -2699,9 +2703,9 @@ static inline int mount_entry_on_systemfs(struct mntent *mntent) + } + + static int mount_entry_on_absolute_rootfs(struct mntent *mntent, +- const struct lxc_rootfs *rootfs, +- const char *lxc_name, +- const char *lxc_path) ++ const struct lxc_rootfs *rootfs, ++ const char *lxc_name, ++ const char *lxc_path) + { + int offset; + char *aux; +@@ -2743,9 +2747,9 @@ skipabs: + } + + static int mount_entry_on_relative_rootfs(struct mntent *mntent, +- const struct lxc_rootfs *rootfs, +- const char *lxc_name, +- const char *lxc_path) ++ const struct lxc_rootfs *rootfs, ++ const char *lxc_name, ++ const char *lxc_path) + { + int ret; + char path[PATH_MAX]; +@@ -2759,8 +2763,8 @@ static int mount_entry_on_relative_rootfs(struct mntent *mntent, + } + + static int mount_file_entries(const struct lxc_conf *conf, +- const struct lxc_rootfs *rootfs, FILE *file, +- const char *lxc_name, const char *lxc_path) ++ const struct lxc_rootfs *rootfs, FILE *file, ++ const char *lxc_name, const char *lxc_path) + { + char buf[4096]; + struct mntent mntent; +@@ -2790,10 +2794,10 @@ static int mount_file_entries(const struct lxc_conf *conf, + ret = mount_entry_on_systemfs(&mntent); + else if (mntent.mnt_dir[0] != '/') + ret = mount_entry_on_relative_rootfs(&mntent, rootfs, +- lxc_name, lxc_path); ++ lxc_name, lxc_path); + else + ret = mount_entry_on_absolute_rootfs(&mntent, rootfs, +- lxc_name, lxc_path); ++ lxc_name, lxc_path); + free(mntent.mnt_fsname); + free(mntent.mnt_dir); + if (ret < 0) +@@ -2806,8 +2810,8 @@ static int mount_file_entries(const struct lxc_conf *conf, + } + + static int setup_mount(const struct lxc_conf *conf, +- const struct lxc_rootfs *rootfs, const char *fstab, +- const char *lxc_name, const char *lxc_path) ++ const struct lxc_rootfs *rootfs, const char *fstab, ++ const char *lxc_name, const char *lxc_path) + { + FILE *f; + int ret; +@@ -2880,9 +2884,9 @@ on_error: + } + + static int setup_mount_entries(const struct lxc_conf *conf, +- const struct lxc_rootfs *rootfs, +- struct lxc_list *mount, const char *lxc_name, +- const char *lxc_path) ++ const struct lxc_rootfs *rootfs, ++ struct lxc_list *mount, const char *lxc_name, ++ const char *lxc_path) + { + int ret; + FILE *f; +@@ -2966,7 +2970,7 @@ static int setup_caps(struct lxc_list *caps) + } + + ret = prctl(PR_CAPBSET_DROP, prctl_arg(capid), prctl_arg(0), +- prctl_arg(0), prctl_arg(0)); ++ prctl_arg(0), prctl_arg(0)); + if (ret < 0) { + SYSERROR("Failed to remove %s capability", drop_entry); + return -1; +@@ -3025,7 +3029,7 @@ static int dropcaps_except(struct lxc_list *caps) + continue; + + ret = prctl(PR_CAPBSET_DROP, prctl_arg(i), prctl_arg(0), +- prctl_arg(0), prctl_arg(0)); ++ prctl_arg(0), prctl_arg(0)); + if (ret < 0) { + SYSERROR("Failed to remove capability %d", i); + return -1; +@@ -3076,8 +3080,8 @@ int setup_resource_limits(struct lxc_list *limits, pid_t pid, int errfd) + if (prlimit(pid, resid, &lim->limit, NULL) != 0) { + SYSERROR("Failed to set limit %s %lu %lu.", lim->resource, lim->limit.rlim_cur, lim->limit.rlim_max); + lxc_write_error_message(errfd, "%s:%d: Failed to set limit %s %lu %lu: %s.", +- __FILE__, __LINE__, lim->resource, +- lim->limit.rlim_cur, lim->limit.rlim_max, strerror(errno)); ++ __FILE__, __LINE__, lim->resource, ++ lim->limit.rlim_cur, lim->limit.rlim_max, strerror(errno)); + return -1; + } + +@@ -3115,10 +3119,10 @@ int setup_sysctl_parameters(struct lxc_list *sysctls) + } + + ret = lxc_write_to_file(filename, elem->value, +- strlen(elem->value), false, 0666); ++ strlen(elem->value), false, 0666); + if (ret < 0) { + SYSERROR("Failed to setup sysctl parameters %s to %s", +- elem->key, elem->value); ++ elem->key, elem->value); + return -1; + } + } +@@ -3150,7 +3154,7 @@ int setup_proc_filesystem(struct lxc_list *procs, pid_t pid) + } + + ret = lxc_write_to_file(filename, elem->value, +- strlen(elem->value), false, 0666); ++ strlen(elem->value), false, 0666); + if (ret < 0) { + ERROR("Failed to setup proc filesystem %s to %s", + elem->filename, elem->value); +@@ -3255,7 +3259,7 @@ struct lxc_conf *lxc_conf_init(void) + } + + int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, +- size_t buf_size) ++ size_t buf_size) + { + int fd, ret; + char path[PATH_MAX]; +@@ -3280,7 +3284,7 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, + close(fd); + if (ret != buflen) { + SYSERROR("Failed to write \"deny\" to " +- "\"/proc/%d/setgroups\"", pid); ++ "\"/proc/%d/setgroups\"", pid); + return -1; + } + TRACE("Wrote \"deny\" to \"/proc/%d/setgroups\"", pid); +@@ -3288,7 +3292,7 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, + } + + ret = snprintf(path, PATH_MAX, "/proc/%d/%cid_map", pid, +- idtype == ID_TYPE_UID ? 'u' : 'g'); ++ idtype == ID_TYPE_UID ? 'u' : 'g'); + if (ret < 0 || ret >= PATH_MAX) + return -E2BIG; + +@@ -3303,7 +3307,7 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, + close(fd); + if (ret != buf_size) { + SYSERROR("Failed to write %cid mapping to \"%s\"", +- idtype == ID_TYPE_UID ? 'u' : 'g', path); ++ idtype == ID_TYPE_UID ? 'u' : 'g', path); + return -1; + } + +@@ -3347,8 +3351,8 @@ static int idmaptool_on_path_and_privileged(const char *binary, cap_value_t cap) + #if HAVE_LIBCAP && LIBCAP_SUPPORTS_FILE_CAPABILITIES + /* Check if it has the CAP_SETUID capability. */ + if ((cap & CAP_SETUID) && +- lxc_file_cap_is_set(path, CAP_SETUID, CAP_EFFECTIVE) && +- lxc_file_cap_is_set(path, CAP_SETUID, CAP_PERMITTED)) { ++ lxc_file_cap_is_set(path, CAP_SETUID, CAP_EFFECTIVE) && ++ lxc_file_cap_is_set(path, CAP_SETUID, CAP_PERMITTED)) { + DEBUG("The binary \"%s\" has CAP_SETUID in its CAP_EFFECTIVE " + "and CAP_PERMITTED sets", path); + fret = 1; +@@ -3357,8 +3361,8 @@ static int idmaptool_on_path_and_privileged(const char *binary, cap_value_t cap) + + /* Check if it has the CAP_SETGID capability. */ + if ((cap & CAP_SETGID) && +- lxc_file_cap_is_set(path, CAP_SETGID, CAP_EFFECTIVE) && +- lxc_file_cap_is_set(path, CAP_SETGID, CAP_PERMITTED)) { ++ lxc_file_cap_is_set(path, CAP_SETGID, CAP_EFFECTIVE) && ++ lxc_file_cap_is_set(path, CAP_SETGID, CAP_PERMITTED)) { + DEBUG("The binary \"%s\" has CAP_SETGID in its CAP_EFFECTIVE " + "and CAP_PERMITTED sets", path); + fret = 1; +@@ -3451,10 +3455,10 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid) + lxc_list_for_each(iterator, idmap) { + map = iterator->elem; + if (map->idtype == ID_TYPE_UID && map->range == 1 && +- map->nsid == hostuid && map->hostid == hostuid) ++ map->nsid == hostuid && map->hostid == hostuid) + continue; + if (map->idtype == ID_TYPE_GID && map->range == 1 && +- map->nsid == hostgid && map->hostid == hostgid) ++ map->nsid == hostgid && map->hostid == hostgid) + continue; + use_shadow = true; + break; +@@ -3462,7 +3466,7 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid) + } + + for (type = ID_TYPE_UID, u_or_g = 'u'; type <= ID_TYPE_GID; +- type++, u_or_g = 'g') { ++ type++, u_or_g = 'g') { + pos = mapbuf; + + if (use_shadow) +@@ -3477,9 +3481,9 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid) + + left = LXC_IDMAPLEN - (pos - mapbuf); + fill = snprintf(pos, left, "%s%lu %lu %lu%s", +- use_shadow ? " " : "", map->nsid, +- map->hostid, map->range, +- use_shadow ? "" : "\n"); ++ use_shadow ? " " : "", map->nsid, ++ map->hostid, map->range, ++ use_shadow ? "" : "\n"); + if (fill <= 0 || fill >= left) { + /* The kernel only takes <= 4k for writes to + * /proc//{g,u}id_map +@@ -3498,8 +3502,8 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid) + */ + if (use_shadow) { + ret = run_command(cmd_output, sizeof(cmd_output), +- lxc_map_ids_exec_wrapper, +- (void *)mapbuf); ++ lxc_map_ids_exec_wrapper, ++ (void *)mapbuf); + if (ret < 0) { + ERROR("new%cidmap failed to write mapping \"%s\": %s", + u_or_g, cmd_output, mapbuf); +@@ -3525,7 +3529,7 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid) + * Return true if id was found, false otherwise. + */ + bool get_mapped_rootid(struct lxc_conf *conf, enum idtype idtype, +- unsigned long *val) ++ unsigned long *val) + { + unsigned nsid; + struct id_map *map; +@@ -3609,20 +3613,22 @@ int chown_mapped_root(const char *path, struct lxc_conf *conf) + char map1[100], map2[100], map3[100], map4[100], map5[100]; + char ugid[100]; + const char *args1[] = {"lxc-usernsexec", +- "-m", map1, +- "-m", map2, +- "-m", map3, +- "-m", map5, +- "--", "chown", ugid, path, +- NULL}; ++ "-m", map1, ++ "-m", map2, ++ "-m", map3, ++ "-m", map5, ++ "--", "chown", ugid, path, ++ NULL ++ }; + const char *args2[] = {"lxc-usernsexec", +- "-m", map1, +- "-m", map2, +- "-m", map3, +- "-m", map4, +- "-m", map5, +- "--", "chown", ugid, path, +- NULL}; ++ "-m", map1, ++ "-m", map2, ++ "-m", map3, ++ "-m", map4, ++ "-m", map5, ++ "--", "chown", ugid, path, ++ NULL ++ }; + char cmd_output[PATH_MAX]; + + hostuid = geteuid(); +@@ -3671,8 +3677,8 @@ int chown_mapped_root(const char *path, struct lxc_conf *conf) + */ + DEBUG("trying to chown \"%s\" to %d", path, hostgid); + if (sb.st_uid == hostuid && +- mapped_hostid(sb.st_gid, conf, ID_TYPE_GID) < 0 && +- chown(path, -1, hostgid) < 0) { ++ mapped_hostid(sb.st_gid, conf, ID_TYPE_GID) < 0 && ++ chown(path, -1, hostgid) < 0) { + ERROR("Failed chgrping %s", path); + return -1; + } +@@ -3700,7 +3706,7 @@ int chown_mapped_root(const char *path, struct lxc_conf *conf) + + /* "g:pathgid:rootgid+pathgid:1" */ + ret = snprintf(map4, 100, "g:%d:%d:1", (gid_t)sb.st_gid, +- rootgid + (gid_t)sb.st_gid); ++ rootgid + (gid_t)sb.st_gid); + if (ret < 0 || ret >= 100) { + ERROR("Error gid printing map string"); + return -1; +@@ -3722,12 +3728,12 @@ int chown_mapped_root(const char *path, struct lxc_conf *conf) + + if (hostgid == sb.st_gid) + ret = run_command(cmd_output, sizeof(cmd_output), +- chown_mapped_root_exec_wrapper, +- (void *)args1); ++ chown_mapped_root_exec_wrapper, ++ (void *)args1); + else + ret = run_command(cmd_output, sizeof(cmd_output), +- chown_mapped_root_exec_wrapper, +- (void *)args2); ++ chown_mapped_root_exec_wrapper, ++ (void *)args2); + if (ret < 0) + ERROR("lxc-usernsexec failed: %s", cmd_output); + +@@ -3820,7 +3826,7 @@ again: + f = fdopen(memfd, "r"); + if (!f) { + SYSERROR("Failed to open copy of \"/proc/self/mountinfo\" to mark " +- "all shared. Continuing"); ++ "all shared. Continuing"); + close(memfd); + return; + } +@@ -3918,7 +3924,7 @@ out: + * pre-mount hooks, and mounting the rootfs. + */ + int lxc_setup_rootfs_prepare_root(struct lxc_conf *conf, const char *name, +- const char *lxcpath) ++ const char *lxcpath) + { + int ret; + +@@ -3967,15 +3973,15 @@ static bool verify_start_hooks(struct lxc_conf *conf) + char *hookname = it->elem; + + ret = snprintf(path, PATH_MAX, "%s%s", +- conf->rootfs.path ? conf->rootfs.mount : "", +- hookname); ++ conf->rootfs.path ? conf->rootfs.mount : "", ++ hookname); + if (ret < 0 || ret >= PATH_MAX) + return false; + + ret = access(path, X_OK); + if (ret < 0) { + SYSERROR("Start hook \"%s\" not found in container", +- hookname); ++ hookname); + return false; + } + +@@ -3997,13 +4003,13 @@ static bool execveat_supported(void) + /* isulad: setup devices which will be populated in the container.*/ + static int setup_populate_devs(const struct lxc_rootfs *rootfs, struct lxc_list *devs) + { +- int ret; +- char *pathdirname; ++ int ret = 0; ++ char *pathdirname = NULL; + char path[MAXPATHLEN]; + mode_t cmask; + mode_t file_mode = 0; +- struct lxc_populate_devs *dev_elem; +- struct lxc_list *it; ++ struct lxc_populate_devs *dev_elem = NULL; ++ struct lxc_list *it = NULL; + + INFO("Populating devices into container"); + cmask = umask(S_IXUSR | S_IXGRP | S_IXOTH); +@@ -4034,12 +4040,12 @@ static int setup_populate_devs(const struct lxc_rootfs *rootfs, struct lxc_list + } + + DEBUG("Try to mknod '%s':'%d':'%d':'%d'\n", path, +- file_mode, dev_elem->maj, dev_elem->min); ++ file_mode, dev_elem->maj, dev_elem->min); + + ret = mknod(path, file_mode, makedev(dev_elem->maj, dev_elem->min)); + if (ret && errno != EEXIST) { + SYSERROR("Failed to mknod '%s':'%d':'%d':'%d'", dev_elem->name, +- file_mode, dev_elem->maj, dev_elem->min); ++ file_mode, dev_elem->maj, dev_elem->min); + + char hostpath[MAXPATHLEN]; + FILE *pathfile; +@@ -4049,16 +4055,16 @@ static int setup_populate_devs(const struct lxc_rootfs *rootfs, struct lxc_list + ret = snprintf(hostpath, MAXPATHLEN, "/dev/%s", dev_elem->name); + if (ret < 0 || ret >= MAXPATHLEN) + return -1; +- pathfile = fopen(path, "wb"); ++ pathfile = lxc_fopen(path, "wb"); + if (!pathfile) { + SYSERROR("Failed to create device mount target '%s'", path); + return -1; + } + fclose(pathfile); + if (safe_mount(hostpath, path, 0, MS_BIND, NULL, +- rootfs->path ? rootfs->mount : NULL) != 0) { ++ rootfs->path ? rootfs->mount : NULL) != 0) { + SYSERROR("Failed bind mounting device %s from host into container", +- dev_elem->name); ++ dev_elem->name); + return -1; + } + } +@@ -4077,7 +4083,7 @@ static int setup_populate_devs(const struct lxc_rootfs *rootfs, struct lxc_list + static int setup_rootfs_mountopts(const struct lxc_rootfs *rootfs) + { + unsigned long mflags, mntflags, pflags; +- char *mntdata; ++ char *mntdata = NULL; + + if(!rootfs || !rootfs->options) + return 0; +@@ -4109,7 +4115,7 @@ int lxc_setup(struct lxc_handler *handler) + if (ret < 0) { + ERROR("Failed to setup rootfs"); + lxc_write_error_message(lxc_conf->errpipe[1], "%s:%d: failed to setup rootfs %s.", +- __FILE__, __LINE__, lxc_conf->rootfs.path); ++ __FILE__, __LINE__, lxc_conf->rootfs.path); + return -1; + } + +@@ -4202,7 +4208,7 @@ int lxc_setup(struct lxc_handler *handler) + /*isulad: move mount entries here, before we do lxc_fill_autodev and populate devices */ + if (!lxc_list_empty(&lxc_conf->mount_list)) { + ret = setup_mount_entries(lxc_conf, &lxc_conf->rootfs, +- &lxc_conf->mount_list, name, lxcpath); ++ &lxc_conf->mount_list, name, lxcpath); + if (ret < 0) { + ERROR("Failed to setup mount entries"); + goto on_error; +@@ -4244,7 +4250,7 @@ int lxc_setup(struct lxc_handler *handler) + } + + ret = lxc_setup_console(&lxc_conf->rootfs, &lxc_conf->console, +- lxc_conf->ttys.dir); ++ lxc_conf->ttys.dir); + if (ret < 0) { + ERROR("Failed to setup console"); + goto on_error; +@@ -4369,11 +4375,13 @@ int lxc_drop_caps(struct lxc_conf *conf) + { + #define __DEF_CAP_TO_MASK(x) (1U << ((x) & 31)) + #if HAVE_LIBCAP +- struct lxc_list *iterator; +- char *keep_entry; ++ int ret = 0; ++ struct lxc_list *iterator = NULL; ++ char *keep_entry = NULL; + int i, capid; + int numcaps = lxc_caps_last_cap() + 1; + struct lxc_list *caps = NULL; ++ int *caplist = NULL; + + if (lxc_list_empty(&conf->keepcaps)) + return 0; +@@ -4384,7 +4392,7 @@ int lxc_drop_caps(struct lxc_conf *conf) + return -1; + + // caplist[i] is 1 if we keep capability i +- int *caplist = alloca(numcaps * sizeof(int)); ++ caplist = malloc(numcaps * sizeof(int)); + memset(caplist, 0, numcaps * sizeof(int)); + + lxc_list_for_each(iterator, caps) { +@@ -4404,9 +4412,10 @@ int lxc_drop_caps(struct lxc_conf *conf) + if (capid == -2) + continue; + +- if (capid < 0) { ++ if (capid < 0) { + ERROR("unknown capability %s", keep_entry); +- return -1; ++ ret = -1; ++ goto out; + } + + DEBUG("keep capability '%s' (%d)", keep_entry, capid); +@@ -4420,7 +4429,7 @@ int lxc_drop_caps(struct lxc_conf *conf) + cap_user_header_t cap_header = &cap_header_data; + cap_user_data_t cap_data = &cap_data_data[0]; + +- memset(cap_header, 0 ,sizeof(struct __user_cap_header_struct)); ++ memset(cap_header, 0,sizeof(struct __user_cap_header_struct)); + memset(cap_data, 0, sizeof(struct __user_cap_data_struct) * 2); + + cap_header->pid = 0; +@@ -4435,12 +4444,16 @@ int lxc_drop_caps(struct lxc_conf *conf) + } + + if (capset(cap_header, cap_data)) { +- SYSERROR("Failed to set capabilitys"); +- return -1; ++ SYSERROR("Failed to set capabilitys"); ++ ret = -1; ++ goto out; + } + + #endif +- return 0; ++ ++out: ++ free(caplist); ++ return ret; + } + + struct oci_hook_conf { +@@ -4474,9 +4487,17 @@ static char* generate_json_str(const char *name, const char *lxcpath, const char + ERROR("Get container %s pid failed: %s", name, strerror(errno)); + cpid = "-1"; + } ++ ++ if ((SIZE_MAX - strlen(name) - strlen(cpid) - strlen(rootfs) - strlen(lxcpath) - strlen(name)) < ++ (strlen("{\"ociVersion\":\"\",\"id\":\"\",\"pid\":,\"root\":\"\",\"bundle\":\"\"}") + 1 + 1)) { ++ ERROR("Out of memory"); ++ ret = -1; ++ goto out_free; ++ } ++ + // {"ociVersion":"","id":"xxx","pid":777,"root":"xxx","bundle":"xxx"} + size = strlen("{\"ociVersion\":\"\",\"id\":\"\",\"pid\":,\"root\":\"\",\"bundle\":\"\"}") + +- strlen(name) + strlen(cpid) + strlen(rootfs) + strlen(lxcpath) + 1 + strlen(name) + 1; ++ strlen(name) + strlen(cpid) + strlen(rootfs) + strlen(lxcpath) + 1 + strlen(name) + 1; + inmsg = malloc(size); + if (!inmsg) { + ERROR("Out of memory"); +@@ -4484,8 +4505,8 @@ static char* generate_json_str(const char *name, const char *lxcpath, const char + goto out_free; + } + rc = snprintf(inmsg, size, +- "{\"ociVersion\":\"\",\"id\":\"%s\",\"pid\":%s,\"root\":\"%s\",\"bundle\":\"%s/%s\"}", +- name, cpid, rootfs, lxcpath, name); ++ "{\"ociVersion\":\"\",\"id\":\"%s\",\"pid\":%s,\"root\":\"%s\",\"bundle\":\"%s/%s\"}", ++ name, cpid, rootfs, lxcpath, name); + if (rc < 0 || rc >= size) { + ERROR("Create json string failed"); + ret = -1; +@@ -4501,13 +4522,14 @@ out_free: + + static char **merge_ocihook_env(char **oldenvs, size_t env_len, size_t *merge_env_len) + { +- char **result; ++ char **result = NULL; + size_t result_len = env_len; + size_t i, j; +- char *tmpenv; ++ char *tmpenv = NULL; + char *lxc_envs[] = {"LD_LIBRARY_PATH", "PATH", "LXC_CGNS_AWARE", "LXC_PID", "LXC_ROOTFS_MOUNT", +- "LXC_CONFIG_FILE", "LXC_CGROUP_PATH", "LXC_ROOTFS_PATH", "LXC_NAME"}; +- char *lxcenv_buf; ++ "LXC_CONFIG_FILE", "LXC_CGROUP_PATH", "LXC_ROOTFS_PATH", "LXC_NAME" ++ }; ++ char *lxcenv_buf = NULL; + + result_len += (sizeof(lxc_envs) / sizeof(char *)) + 1; + result = malloc(sizeof(char *) * result_len); +@@ -4541,8 +4563,8 @@ static char **merge_ocihook_env(char **oldenvs, size_t env_len, size_t *merge_en + return result; + } + +-static struct lxc_popen_FILE *lxc_popen_ocihook(char *commandpath, char **args, int args_len, +- char **envs, int env_len, const char *instr) ++static struct lxc_popen_FILE *lxc_popen_ocihook(const char *commandpath, char **args, int args_len, ++ char **envs, int env_len, const char *instr) + { + int ret; + struct lxc_popen_FILE *fp = NULL; +@@ -4684,12 +4706,12 @@ void* wait_ocihook_timeout(void *arg) + + if (alive) { + ERROR("%s:%d: running %s hook caused \"hook ran past specified timeout of %.1fs\"", +- __FILE__, __LINE__, lxchook_names[conf->which], +- (double)conf->timeout); ++ __FILE__, __LINE__, lxchook_names[conf->which], ++ (double)conf->timeout); + + lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"hook ran past specified timeout of %.1fs\".", +- __FILE__, __LINE__, lxchook_names[conf->which], +- (double)conf->timeout); ++ __FILE__, __LINE__, lxchook_names[conf->which], ++ (double)conf->timeout); + + if (kill(conf->pid, SIGKILL) && errno != ESRCH) { + ERROR("Send kill signal failed"); +@@ -4702,7 +4724,7 @@ out: + return ((void *)0); + } + +-static int run_ocihook_buffer(struct oci_hook_conf *oconf, char *inmsg) ++static int run_ocihook_buffer(struct oci_hook_conf *oconf, const char *inmsg) + { + struct lxc_popen_FILE *f; + char output[LXC_LOG_BUFFER_SIZE] = {0}; +@@ -4771,17 +4793,17 @@ static int run_ocihook_buffer(struct oci_hook_conf *oconf, char *inmsg) + } else if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) { + ERROR("Script exited with status %d. output: %s", WEXITSTATUS(ret), output); + lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"error running hook: exit status %d, output: %s\".", +- __FILE__, __LINE__, +- (conf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[conf->which], +- WEXITSTATUS(ret), output); ++ __FILE__, __LINE__, ++ (conf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[conf->which], ++ WEXITSTATUS(ret), output); + + goto print_hook; + } else if (WIFSIGNALED(ret)) { + ERROR("Script terminated by signal %d.", WTERMSIG(ret)); + lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"error running hook: Script terminated by signal %d\".", +- __FILE__, __LINE__, +- (conf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[conf->which], +- WTERMSIG(ret)); ++ __FILE__, __LINE__, ++ (conf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[conf->which], ++ WTERMSIG(ret)); + + goto print_hook; + } +@@ -4801,8 +4823,8 @@ print_hook: + if (oconf->ocihook->env) + err_envs_msg = lxc_string_join(" ", (const char **)oconf->ocihook->env, false); + ERROR("Hook script command: \"%s\", args: \"%s\", envs: \"%s\", timeout: %d.", +- buffer, err_args_msg ? err_args_msg : "", +- err_envs_msg ? err_envs_msg : "", conf->timeout); ++ buffer, err_args_msg ? err_args_msg : "", ++ err_envs_msg ? err_envs_msg : "", conf->timeout); + + free(err_args_msg); + free(err_envs_msg); +@@ -4810,8 +4832,8 @@ print_hook: + } + + static int run_ocihook_script_argv(const char *name, const char *section, +- struct oci_hook_conf *oconf, +- const char *lxcpath, const char *rootfs) ++ struct oci_hook_conf *oconf, ++ const char *lxcpath, const char *rootfs) + { + int ret; + const char *script = oconf->ocihook->path; +@@ -4845,9 +4867,13 @@ static char *get_root_path(const char *path, const char *backend) + } + + if (strcmp(backend, "aufs") == 0 || +- strcmp(backend, "overlayfs") == 0 || +- strcmp(backend, "loop") == 0) { ++ strcmp(backend, "overlayfs") == 0 || ++ strcmp(backend, "loop") == 0) { + tmp = strrchr(path, ':'); ++ if (tmp == NULL) { ++ ERROR("Out of memory"); ++ return NULL; ++ } + tmp++; + ret = strdup(tmp); + if (!ret) { +@@ -4866,13 +4892,13 @@ default_out: + return ret; + } + +-static int run_oci_hooks(const char *name, const char *lxcpath, struct lxc_conf *lc, int which, int errfd) ++static int do_run_oci_hooks(const char *name, const char *lxcpath, struct lxc_conf *lc, int which, int errfd) + { + struct oci_hook_conf work_conf = {0}; + size_t i; + int ret = 0; + int nret = 0; +- char *rootpath; ++ char *rootpath = NULL; + + if (!lc) { + return -1; +@@ -4890,32 +4916,32 @@ static int run_oci_hooks(const char *name, const char *lxcpath, struct lxc_conf + work_conf.errfd = errfd; + work_conf.which = which; + switch (which) { +- case OCI_HOOK_PRESTART: +- for (i = 0; i < lc->ocihooks->prestart_len; i++) { +- work_conf.ocihook = lc->ocihooks->prestart[i]; +- ret = run_ocihook_script_argv(name, "lxc", &work_conf, lxcpath, rootpath); +- if (ret != 0) +- break; +- } +- break; +- case OCI_HOOK_POSTSTART: +- for (i = 0; i < lc->ocihooks->poststart_len; i++) { +- work_conf.ocihook = lc->ocihooks->poststart[i]; +- nret = run_ocihook_script_argv(name, "lxc", &work_conf, lxcpath, rootpath); +- if (nret != 0) +- WARN("running poststart hook %ld failed, ContainerId: %s", i, name); +- } +- break; +- case OCI_HOOK_POSTSTOP: +- for (i = 0; i < lc->ocihooks->poststop_len; i++) { +- work_conf.ocihook = lc->ocihooks->poststop[i]; +- ret = run_ocihook_script_argv(name, "lxc", &work_conf, lxcpath, rootpath); +- if (ret != 0) +- break; +- } +- break; +- default: +- ret = -1; ++ case OCI_HOOK_PRESTART: ++ for (i = 0; i < lc->ocihooks->prestart_len; i++) { ++ work_conf.ocihook = lc->ocihooks->prestart[i]; ++ ret = run_ocihook_script_argv(name, "lxc", &work_conf, lxcpath, rootpath); ++ if (ret != 0) ++ break; ++ } ++ break; ++ case OCI_HOOK_POSTSTART: ++ for (i = 0; i < lc->ocihooks->poststart_len; i++) { ++ work_conf.ocihook = lc->ocihooks->poststart[i]; ++ nret = run_ocihook_script_argv(name, "lxc", &work_conf, lxcpath, rootpath); ++ if (nret != 0) ++ WARN("running poststart hook %ld failed, ContainerId: %s", i, name); ++ } ++ break; ++ case OCI_HOOK_POSTSTOP: ++ for (i = 0; i < lc->ocihooks->poststop_len; i++) { ++ work_conf.ocihook = lc->ocihooks->poststop[i]; ++ ret = run_ocihook_script_argv(name, "lxc", &work_conf, lxcpath, rootpath); ++ if (ret != 0) ++ break; ++ } ++ break; ++ default: ++ ret = -1; + } + if (rootpath) + free(rootpath); +@@ -4923,33 +4949,12 @@ static int run_oci_hooks(const char *name, const char *lxcpath, struct lxc_conf + } + + int run_lxc_hooks(const char *name, char *hookname, struct lxc_conf *conf, +- char *argv[]) ++ char *argv[]) + { + struct lxc_list *it; + int which = -1; + +- if (strcmp(hookname, "oci-prestart") == 0) { +- which = OCI_HOOK_PRESTART; +- if (!argv || !argv[0]) { +- ERROR("oci hook require lxcpath"); +- return -1; +- } +- return run_oci_hooks(name, argv[0], conf, which, conf->errpipe[1]); +- } else if (strcmp(hookname, "oci-poststart") == 0) { +- which = OCI_HOOK_POSTSTART; +- if (!argv || !argv[0]) { +- ERROR("oci hook require lxcpath"); +- return -1; +- } +- return run_oci_hooks(name, argv[0], conf, which, conf->errpipe[1]); +- } else if (strcmp(hookname, "oci-poststop") == 0) { +- which = OCI_HOOK_POSTSTOP; +- if (!argv || !argv[0]) { +- ERROR("oci hook require lxcpath"); +- return -1; +- } +- return run_oci_hooks(name, argv[0], conf, which, conf->errpipe[1]); +- } else if (strcmp(hookname, "pre-start") == 0) ++ if (strcmp(hookname, "pre-start") == 0) + which = LXCHOOK_PRESTART; + else if (strcmp(hookname, "start-host") == 0) + which = LXCHOOK_START_HOST; +@@ -4977,7 +4982,7 @@ int run_lxc_hooks(const char *name, char *hookname, struct lxc_conf *conf, + char *hook = it->elem; + + ret = run_script_argv(name, conf->hooks_version, "lxc", hook, +- hookname, argv); ++ hookname, argv); + if (ret < 0) + return -1; + } +@@ -4985,6 +4990,39 @@ int run_lxc_hooks(const char *name, char *hookname, struct lxc_conf *conf, + return 0; + } + ++int run_oci_hooks(const char *name, char *hookname, struct lxc_conf *conf, const char *lxcpath) ++{ ++ struct lxc_list *it; ++ int which = -1; ++ ++ if (strcmp(hookname, "oci-prestart") == 0) { ++ which = OCI_HOOK_PRESTART; ++ if (!lxcpath) { ++ ERROR("oci hook require lxcpath"); ++ return -1; ++ } ++ return do_run_oci_hooks(name, lxcpath, conf, which, conf->errpipe[1]); ++ } else if (strcmp(hookname, "oci-poststart") == 0) { ++ which = OCI_HOOK_POSTSTART; ++ if (!lxcpath) { ++ ERROR("oci hook require lxcpath"); ++ return -1; ++ } ++ return do_run_oci_hooks(name, lxcpath, conf, which, conf->errpipe[1]); ++ } else if (strcmp(hookname, "oci-poststop") == 0) { ++ which = OCI_HOOK_POSTSTOP; ++ if (!lxcpath) { ++ ERROR("oci hook require lxcpath"); ++ return -1; ++ } ++ return do_run_oci_hooks(name, lxcpath, conf, which, conf->errpipe[1]); ++ } else ++ return -1; ++ ++ return 0; ++} ++ ++ + int lxc_clear_config_caps(struct lxc_conf *c) + { + struct lxc_list *it, *next; +@@ -5299,7 +5337,8 @@ int lxc_clear_init_groups(struct lxc_conf *lxc_conf) + /*isulad: clear populate devices*/ + int lxc_clear_populate_devices(struct lxc_conf *c) + { +- struct lxc_list *it,*next; ++ struct lxc_list *it = NULL; ++ struct lxc_list *next = NULL; + + lxc_list_for_each_safe(it, &c->populate_devs, next) { + struct lxc_populate_devs *dev_elem = it->elem; +@@ -5315,7 +5354,8 @@ int lxc_clear_populate_devices(struct lxc_conf *c) + /*isulad: clear rootfs masked paths*/ + int lxc_clear_rootfs_masked_paths(struct lxc_conf *c) + { +- struct lxc_list *it,*next; ++ struct lxc_list *it = NULL; ++ struct lxc_list *next = NULL; + + lxc_list_for_each_safe(it, &c->rootfs.maskedpaths, next) { + lxc_list_del(it); +@@ -5328,7 +5368,8 @@ int lxc_clear_rootfs_masked_paths(struct lxc_conf *c) + /*isulad: clear rootfs ro paths*/ + int lxc_clear_rootfs_ro_paths(struct lxc_conf *c) + { +- struct lxc_list *it,*next; ++ struct lxc_list *it = NULL; ++ struct lxc_list *next = NULL; + + lxc_list_for_each_safe(it, &c->rootfs.ropaths, next) { + lxc_list_del(it); +@@ -5449,7 +5490,7 @@ static int run_userns_fn(void *data) + } + + static struct id_map *mapped_nsid_add(struct lxc_conf *conf, unsigned id, +- enum idtype idtype) ++ enum idtype idtype) + { + const struct id_map *map; + struct id_map *retmap; +@@ -5467,7 +5508,7 @@ static struct id_map *mapped_nsid_add(struct lxc_conf *conf, unsigned id, + } + + static struct id_map *find_mapped_hostid_entry(struct lxc_conf *conf, +- unsigned id, enum idtype idtype) ++ unsigned id, enum idtype idtype) + { + struct id_map *map; + struct lxc_list *it; +@@ -5491,7 +5532,7 @@ static struct id_map *find_mapped_hostid_entry(struct lxc_conf *conf, + * existing one or establish a new one. + */ + static struct id_map *mapped_hostid_add(struct lxc_conf *conf, uid_t id, +- enum idtype type) ++ enum idtype type) + { + int hostid_mapped; + struct id_map *entry = NULL, *tmp = NULL; +@@ -5528,7 +5569,7 @@ struct lxc_list *get_minimal_idmap(struct lxc_conf *conf) + gid_t nsgid = (conf->root_nsgid_map != NULL) ? 0 : conf->init_gid; + struct lxc_list *idmap = NULL, *tmplist = NULL; + struct id_map *container_root_uid = NULL, *container_root_gid = NULL, +- *host_uid_map = NULL, *host_gid_map = NULL; ++ *host_uid_map = NULL, *host_gid_map = NULL; + + /* Find container root mappings. */ + container_root_uid = mapped_nsid_add(conf, nsuid, ID_TYPE_UID); +@@ -5538,7 +5579,7 @@ struct lxc_list *get_minimal_idmap(struct lxc_conf *conf) + } + euid = geteuid(); + if (euid >= container_root_uid->hostid && +- euid < (container_root_uid->hostid + container_root_uid->range)) ++ euid < (container_root_uid->hostid + container_root_uid->range)) + host_uid_map = container_root_uid; + + container_root_gid = mapped_nsid_add(conf, nsgid, ID_TYPE_GID); +@@ -5548,7 +5589,7 @@ struct lxc_list *get_minimal_idmap(struct lxc_conf *conf) + } + egid = getegid(); + if (egid >= container_root_gid->hostid && +- egid < (container_root_gid->hostid + container_root_gid->range)) ++ egid < (container_root_gid->hostid + container_root_gid->range)) + host_gid_map = container_root_gid; + + /* Check whether the {g,u}id of the user has a mapping. */ +@@ -5648,7 +5689,7 @@ on_error: + * there to start the container in the first place. + */ + int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, +- const char *fn_name) ++ const char *fn_name) + { + pid_t pid; + int p[2]; +@@ -5686,7 +5727,7 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, + p[0] = -1; + + if (lxc_log_get_level() == LXC_LOG_LEVEL_TRACE || +- conf->loglevel == LXC_LOG_LEVEL_TRACE) { ++ conf->loglevel == LXC_LOG_LEVEL_TRACE) { + struct id_map *map; + struct lxc_list *it; + +@@ -5729,7 +5770,7 @@ on_error: + } + + int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data, +- const char *fn_name) ++ const char *fn_name) + { + pid_t pid; + uid_t euid, egid; +@@ -5741,7 +5782,7 @@ int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data, + char c = '1'; + struct lxc_list *idmap = NULL, *tmplist = NULL; + struct id_map *container_root_uid = NULL, *container_root_gid = NULL, +- *host_uid_map = NULL, *host_gid_map = NULL; ++ *host_uid_map = NULL, *host_gid_map = NULL; + + if (!conf) + return -EINVAL; +@@ -5866,7 +5907,7 @@ int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data, + host_gid_map = NULL; + + if (lxc_log_get_level() == LXC_LOG_LEVEL_TRACE || +- conf->loglevel == LXC_LOG_LEVEL_TRACE) { ++ conf->loglevel == LXC_LOG_LEVEL_TRACE) { + lxc_list_for_each (cur, idmap) { + map = cur->elem; + TRACE("establishing %cid mapping for \"%d\" in new " +@@ -6139,7 +6180,7 @@ struct lxc_list *sort_cgroup_settings(struct lxc_list *cgroup_settings) + /* Store the memsw_limit location */ + memsw_limit = item; + } else if (strcmp(cg->subsystem, "memory.limit_in_bytes") == 0 && +- memsw_limit != NULL) { ++ memsw_limit != NULL) { + /* lxc.cgroup.memory.memsw.limit_in_bytes is found + * before lxc.cgroup.memory.limit_in_bytes, swap these + * two items */ +diff --git a/src/lxc/conf.h b/src/lxc/conf.h +index fb3c156..26bb70f 100644 +--- a/src/lxc/conf.h ++++ b/src/lxc/conf.h +@@ -70,14 +70,14 @@ typedef void * scmp_filter_ctx; + struct lxc_cgroup { + union { + /* information about a specific controller */ +- struct /* controller */ { ++ struct { /* controller */ + int version; + char *subsystem; + char *value; + }; + + /* meta information about cgroup configuration */ +- struct /* meta */ { ++ struct { /* meta */ + char *controllers; + char *dir; + }; +@@ -435,7 +435,7 @@ struct lxc_conf { + }; + + extern int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, +- size_t buf_size); ++ size_t buf_size); + + #ifdef HAVE_TLS + extern thread_local struct lxc_conf *current_config; +@@ -444,7 +444,9 @@ extern struct lxc_conf *current_config; + #endif + + extern int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf, +- char *argv[]); ++ char *argv[]); ++extern int run_oci_hooks(const char *name, char *hookname, struct lxc_conf *conf, const char *lxcpath); ++ + extern int detect_shared_rootfs(void); + extern struct lxc_conf *lxc_conf_init(void); + extern void lxc_conf_free(struct lxc_conf *conf); +@@ -465,20 +467,20 @@ extern int lxc_clear_limits(struct lxc_conf *c, const char *key); + extern int lxc_delete_autodev(struct lxc_handler *handler); + extern void lxc_clear_includes(struct lxc_conf *conf); + extern int lxc_setup_rootfs_prepare_root(struct lxc_conf *conf, +- const char *name, const char *lxcpath); ++ const char *name, const char *lxcpath); + extern int lxc_setup(struct lxc_handler *handler); + extern int lxc_setup_parent(struct lxc_handler *handler); + extern int setup_resource_limits(struct lxc_list *limits, pid_t pid, int errfd); + extern int find_unmapped_nsid(struct lxc_conf *conf, enum idtype idtype); + extern int mapped_hostid(unsigned id, struct lxc_conf *conf, +- enum idtype idtype); ++ enum idtype idtype); + extern int chown_mapped_root(const char *path, struct lxc_conf *conf); + extern int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, +- const char *fn_name); ++ const char *fn_name); + extern int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), +- void *data, const char *fn_name); ++ void *data, const char *fn_name); + extern int parse_mntopts(const char *mntopts, unsigned long *mntflags, +- unsigned long *pflags, char **mntdata); ++ unsigned long *pflags, char **mntdata); + extern int parse_propagationopts(const char *mntopts, unsigned long *pflags); + extern void tmp_proc_unmount(struct lxc_conf *lxc_conf); + extern void remount_all_slave(void); +@@ -486,12 +488,12 @@ extern void suggest_default_idmap(void); + extern FILE *make_anonymous_mount_file(struct lxc_list *mount); + extern struct lxc_list *sort_cgroup_settings(struct lxc_list *cgroup_settings); + extern unsigned long add_required_remount_flags(const char *s, const char *d, +- unsigned long flags); ++ unsigned long flags); + extern int run_script(const char *name, const char *section, const char *script, +- ...); ++ ...); + extern int run_script_argv(const char *name, unsigned int hook_version, +- const char *section, const char *script, +- const char *hookname, char **argsin); ++ const char *section, const char *script, ++ const char *hookname, char **argsin); + extern int in_caplist(int cap, struct lxc_list *caps); + extern int setup_sysctl_parameters(struct lxc_list *sysctls); + extern int lxc_clear_sysctls(struct lxc_conf *c, const char *key); +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index 93936cc..216a688 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -270,7 +270,7 @@ struct lxc_config_t *lxc_get_config(const char *key) + } + + static int set_config_net(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + if (!lxc_config_value_empty(value)) { + ERROR("lxc.net must not have a value"); +@@ -281,7 +281,7 @@ static int set_config_net(const char *key, const char *value, + } + + static int set_config_net_type(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_netdev *netdev = data; + +@@ -296,7 +296,7 @@ static int set_config_net_type(const char *key, const char *value, + } else if (!strcmp(value, "macvlan")) { + netdev->type = LXC_NET_MACVLAN; + lxc_macvlan_mode_to_flag(&netdev->priv.macvlan_attr.mode, +- "private"); ++ "private"); + } else if (!strcmp(value, "vlan")) { + netdev->type = LXC_NET_VLAN; + } else if (!strcmp(value, "phys")) { +@@ -314,7 +314,7 @@ static int set_config_net_type(const char *key, const char *value, + } + + static int set_config_net_flags(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_netdev *netdev = data; + +@@ -330,7 +330,7 @@ static int set_config_net_flags(const char *key, const char *value, + } + + static int create_matched_ifnames(const char *value, struct lxc_conf *lxc_conf, +- struct lxc_netdev *netdev) ++ struct lxc_netdev *netdev) + { + struct netns_ifaddrs *ifaddr, *ifa; + int n; +@@ -339,7 +339,9 @@ static int create_matched_ifnames(const char *value, struct lxc_conf *lxc_conf, + const char *link_key = "lxc.net.link"; + const char *tmpvalue = "phys"; + +- if (netns_getifaddrs(&ifaddr, -1, &(bool){false}) < 0) { ++ if (netns_getifaddrs(&ifaddr, -1, &(bool) { ++ false ++}) < 0) { + SYSERROR("Failed to get network interfaces"); + return -1; + } +@@ -353,10 +355,10 @@ static int create_matched_ifnames(const char *value, struct lxc_conf *lxc_conf, + + if (!strncmp(value, ifa->ifa_name, strlen(value) - 1)) { + ret = set_config_net_type(type_key, tmpvalue, lxc_conf, +- netdev); ++ netdev); + if (!ret) { + ret = set_config_net_link( +- link_key, ifa->ifa_name, lxc_conf, netdev); ++ link_key, ifa->ifa_name, lxc_conf, netdev); + if (ret) { + ERROR("Failed to create matched ifnames"); + break; +@@ -375,7 +377,7 @@ static int create_matched_ifnames(const char *value, struct lxc_conf *lxc_conf, + } + + static int set_config_net_link(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_netdev *netdev = data; + int ret = 0; +@@ -395,7 +397,7 @@ static int set_config_net_link(const char *key, const char *value, + } + + static int set_config_net_name(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_netdev *netdev = data; + +@@ -409,7 +411,7 @@ static int set_config_net_name(const char *key, const char *value, + } + + static int set_config_net_veth_pair(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_netdev *netdev = data; + +@@ -423,7 +425,7 @@ static int set_config_net_veth_pair(const char *key, const char *value, + } + + static int set_config_net_macvlan_mode(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_netdev *netdev = data; + +@@ -437,7 +439,7 @@ static int set_config_net_macvlan_mode(const char *key, const char *value, + } + + static int set_config_net_hwaddr(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_netdev *netdev = data; + char *new_value; +@@ -466,7 +468,7 @@ static int set_config_net_hwaddr(const char *key, const char *value, + } + + static int set_config_net_vlan_id(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int ret; + struct lxc_netdev *netdev = data; +@@ -485,7 +487,7 @@ static int set_config_net_vlan_id(const char *key, const char *value, + } + + static int set_config_net_mtu(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_netdev *netdev = data; + +@@ -499,7 +501,7 @@ static int set_config_net_mtu(const char *key, const char *value, + } + + static int set_config_net_ipv4_address(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int ret; + struct lxc_netdev *netdev = data; +@@ -596,7 +598,7 @@ static int set_config_net_ipv4_address(const char *key, const char *value, + } + + static int set_config_net_ipv4_gateway(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_netdev *netdev = data; + +@@ -634,7 +636,7 @@ static int set_config_net_ipv4_gateway(const char *key, const char *value, + } + + static int set_config_net_ipv6_address(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int ret; + struct lxc_netdev *netdev = data; +@@ -700,7 +702,7 @@ static int set_config_net_ipv6_address(const char *key, const char *value, + } + + static int set_config_net_ipv6_gateway(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_netdev *netdev = data; + +@@ -738,7 +740,7 @@ static int set_config_net_ipv6_gateway(const char *key, const char *value, + } + + static int set_config_net_script_up(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_netdev *netdev = data; + +@@ -752,7 +754,7 @@ static int set_config_net_script_up(const char *key, const char *value, + } + + static int set_config_net_script_down(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_netdev *netdev = data; + +@@ -782,31 +784,31 @@ static int add_hook(struct lxc_conf *lxc_conf, int which, char *hook) + } + + static int set_config_seccomp_profile(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + return set_config_path_item(&lxc_conf->seccomp, value); + } + + static int set_config_execute_cmd(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + return set_config_path_item(&lxc_conf->execute_cmd, value); + } + + static int set_config_init_cmd(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + return set_config_path_item(&lxc_conf->init_cmd, value); + } + + static int set_config_init_cwd(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + return set_config_path_item(&lxc_conf->init_cwd, value); + } + + static int set_config_init_uid(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + unsigned int init_uid; + +@@ -824,7 +826,7 @@ static int set_config_init_uid(const char *key, const char *value, + } + + static int set_config_init_gid(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + unsigned int init_gid; + +@@ -842,7 +844,7 @@ static int set_config_init_gid(const char *key, const char *value, + } + + static int set_config_hooks(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + char *copy; + +@@ -885,7 +887,7 @@ static int set_config_hooks(const char *key, const char *value, + } + + static int set_config_hooks_version(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int ret; + unsigned int tmp; +@@ -909,7 +911,7 @@ static int set_config_hooks_version(const char *key, const char *value, + } + + static int set_config_personality(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + signed long personality = lxc_config_parse_arch(value); + +@@ -922,7 +924,7 @@ static int set_config_personality(const char *key, const char *value, + } + + static int set_config_pty_max(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int ret; + unsigned int max = 0; +@@ -947,7 +949,7 @@ static int set_config_pty_max(const char *key, const char *value, + * noticed when the callback was called. + */ + static int set_config_start(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + bool is_empty; + +@@ -986,7 +988,7 @@ static int set_config_start(const char *key, const char *value, + } + + static int set_config_monitor(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + if (lxc_config_value_empty(value)) { + lxc_conf->monitor_unshare = 0; +@@ -1000,7 +1002,7 @@ static int set_config_monitor(const char *key, const char *value, + } + + static int set_config_group(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + char *groups, *token; + struct lxc_list *grouplist; +@@ -1039,10 +1041,10 @@ static int set_config_group(const char *key, const char *value, + } + + static int set_config_environment(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_list *list_item = NULL; +- char *replaced; ++ char *replaced = NULL; + + if (lxc_config_value_empty(value)) + return lxc_clear_environment(lxc_conf); +@@ -1072,7 +1074,7 @@ on_error: + } + + static int set_config_tty_max(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int ret; + unsigned int nbtty = 0; +@@ -1092,22 +1094,22 @@ static int set_config_tty_max(const char *key, const char *value, + } + + static int set_config_tty_dir(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + return set_config_string_item_max(&lxc_conf->ttys.dir, value, +- NAME_MAX + 1); ++ NAME_MAX + 1); + } + + static int set_config_apparmor_profile(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + return set_config_string_item(&lxc_conf->lsm_aa_profile, value); + } + + static int set_config_apparmor_allow_incomplete(const char *key, +- const char *value, +- struct lxc_conf *lxc_conf, +- void *data) ++ const char *value, ++ struct lxc_conf *lxc_conf, ++ void *data) + { + if (lxc_config_value_empty(value)) { + lxc_conf->lsm_aa_allow_incomplete = 0; +@@ -1124,13 +1126,13 @@ static int set_config_apparmor_allow_incomplete(const char *key, + } + + static int set_config_selinux_context(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + return set_config_string_item(&lxc_conf->lsm_se_context, value); + } + + static int set_config_log_file(const char *key, const char *value, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int ret; + +@@ -1151,7 +1153,7 @@ static int set_config_log_file(const char *key, const char *value, + } + + static int set_config_log_level(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int newlevel; + +@@ -1176,7 +1178,7 @@ static int set_config_log_level(const char *key, const char *value, + } + + static int set_config_autodev(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + if (lxc_config_value_empty(value)) { + lxc_conf->autodev = 0; +@@ -1193,7 +1195,7 @@ static int set_config_autodev(const char *key, const char *value, + } + + static int set_config_signal_halt(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int sig_n; + +@@ -1212,7 +1214,7 @@ static int set_config_signal_halt(const char *key, const char *value, + } + + static int set_config_signal_reboot(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int sig_n; + +@@ -1231,7 +1233,7 @@ static int set_config_signal_reboot(const char *key, const char *value, + } + + static int set_config_signal_stop(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int sig_n; + +@@ -1250,7 +1252,7 @@ static int set_config_signal_stop(const char *key, const char *value, + } + + static int __set_config_cgroup_controller(const char *key, const char *value, +- struct lxc_conf *lxc_conf, int version) ++ struct lxc_conf *lxc_conf, int version) + { + const char *subkey, *token; + size_t token_len; +@@ -1317,22 +1319,22 @@ out: + } + + static int set_config_cgroup_controller(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + return __set_config_cgroup_controller(key, value, lxc_conf, +- CGROUP_SUPER_MAGIC); ++ CGROUP_SUPER_MAGIC); + } + + static int set_config_cgroup2_controller(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + return __set_config_cgroup_controller(key, value, lxc_conf, +- CGROUP2_SUPER_MAGIC); ++ CGROUP2_SUPER_MAGIC); + } + + + static int set_config_cgroup_dir(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + if (lxc_config_value_empty(value)) + return clr_config_cgroup_dir(key, lxc_conf, NULL); +@@ -1341,7 +1343,7 @@ static int set_config_cgroup_dir(const char *key, const char *value, + } + + static int set_config_prlimit(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_list *iter; + struct rlimit limit; +@@ -1434,7 +1436,7 @@ on_error: + } + + static int set_config_sysctl(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_list *iter; + char *replace_value = NULL; +@@ -1502,7 +1504,7 @@ on_error: + } + + static int set_config_proc(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + const char *subkey; + struct lxc_list *proclist = NULL; +@@ -1552,7 +1554,7 @@ on_error: + } + + static int set_config_idmaps(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + unsigned long hostid, nsid, range; + char type; +@@ -1612,7 +1614,7 @@ on_error: + } + + static int set_config_mount_fstab(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + if (lxc_config_value_empty(value)) { + clr_config_mount_fstab(key, lxc_conf, NULL); +@@ -1623,7 +1625,7 @@ static int set_config_mount_fstab(const char *key, const char *value, + } + + static int set_config_mount_auto(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + char *autos, *token; + int i; +@@ -1633,34 +1635,34 @@ static int set_config_mount_auto(const char *key, const char *value, + int mask; + int flag; + } allowed_auto_mounts[] = { +- { "proc", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED }, +- { "proc:mixed", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED }, +- { "proc:rw", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW }, +- { "sys", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED }, +- { "sys:ro", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO }, +- { "sys:mixed", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED }, +- { "sys:rw", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW }, +- { "cgroup", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC }, +- { "cgroup:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED }, +- { "cgroup:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO }, +- { "cgroup:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW }, +- { "cgroup:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC | LXC_AUTO_CGROUP_FORCE }, +- { "cgroup:mixed:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED | LXC_AUTO_CGROUP_FORCE }, +- { "cgroup:ro:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO | LXC_AUTO_CGROUP_FORCE }, +- { "cgroup:rw:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW | LXC_AUTO_CGROUP_FORCE }, +- { "cgroup-full", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC }, +- { "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED }, +- { "cgroup-full:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO }, +- { "cgroup-full:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW }, +- { "cgroup-full:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC | LXC_AUTO_CGROUP_FORCE }, +- { "cgroup-full:mixed:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED | LXC_AUTO_CGROUP_FORCE }, +- { "cgroup-full:ro:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO | LXC_AUTO_CGROUP_FORCE }, +- { "cgroup-full:rw:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW | LXC_AUTO_CGROUP_FORCE }, +- /* For adding anything that is just a single on/off, but has no +- * options: keep mask and flag identical and just define the enum +- * value as an unused bit so far +- */ +- { NULL, 0, 0 } ++ { "proc", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED }, ++ { "proc:mixed", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED }, ++ { "proc:rw", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW }, ++ { "sys", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED }, ++ { "sys:ro", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO }, ++ { "sys:mixed", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED }, ++ { "sys:rw", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW }, ++ { "cgroup", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC }, ++ { "cgroup:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED }, ++ { "cgroup:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO }, ++ { "cgroup:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW }, ++ { "cgroup:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC | LXC_AUTO_CGROUP_FORCE }, ++ { "cgroup:mixed:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED | LXC_AUTO_CGROUP_FORCE }, ++ { "cgroup:ro:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO | LXC_AUTO_CGROUP_FORCE }, ++ { "cgroup:rw:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW | LXC_AUTO_CGROUP_FORCE }, ++ { "cgroup-full", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC }, ++ { "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED }, ++ { "cgroup-full:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO }, ++ { "cgroup-full:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW }, ++ { "cgroup-full:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC | LXC_AUTO_CGROUP_FORCE }, ++ { "cgroup-full:mixed:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED | LXC_AUTO_CGROUP_FORCE }, ++ { "cgroup-full:ro:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO | LXC_AUTO_CGROUP_FORCE }, ++ { "cgroup-full:rw:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW | LXC_AUTO_CGROUP_FORCE }, ++ /* For adding anything that is just a single on/off, but has no ++ * options: keep mask and flag identical and just define the enum ++ * value as an unused bit so far ++ */ ++ { NULL, 0, 0 } + }; + + if (lxc_config_value_empty(value)) { +@@ -1696,7 +1698,7 @@ on_error: + } + + static int set_config_mount(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + char *mntelem; + struct lxc_list *mntlist; +@@ -1721,7 +1723,7 @@ static int set_config_mount(const char *key, const char *value, + } + + static int set_config_cap_keep(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + char *keepcaps, *token; + struct lxc_list *keeplist; +@@ -1763,7 +1765,7 @@ on_error: + } + + static int set_config_cap_drop(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + char *dropcaps, *token; + struct lxc_list *droplist; +@@ -1793,7 +1795,7 @@ static int set_config_cap_drop(const char *key, const char *value, + lxc_list_add_tail(&lxc_conf->caps, droplist); + } + +- ret = 0; ++ ret = 0; + + on_error: + free(dropcaps); +@@ -1802,13 +1804,13 @@ on_error: + } + + static int set_config_console_path(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + return set_config_path_item(&lxc_conf->console.path, value); + } + + static int set_config_console_rotate(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + if (lxc_config_value_empty(value)) { + lxc_conf->console.log_rotate = 0; +@@ -1831,13 +1833,13 @@ static int set_config_console_rotate(const char *key, const char *value, + } + + static int set_config_console_logfile(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + return set_config_path_item(&lxc_conf->console.log_path, value); + } + + static int set_config_console_buffer_size(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int ret; + int64_t size; +@@ -1885,7 +1887,7 @@ static int set_config_console_buffer_size(const char *key, const char *value, + } + + static int set_config_console_size(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int ret; + int64_t size; +@@ -1942,7 +1944,7 @@ int append_unexp_config_line(const char *line, struct lxc_conf *conf) + linelen = strlen(line); + while (conf->unexpanded_alloced <= len + linelen + 2) { + char *tmp = realloc(conf->unexpanded_config, +- conf->unexpanded_alloced + 1024); ++ conf->unexpanded_alloced + 1024); + if (!tmp) + return -1; + +@@ -2007,7 +2009,7 @@ out: + } + + static int set_config_includefiles(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + if (lxc_config_value_empty(value)) { + clr_config_includefiles(key, lxc_conf, NULL); +@@ -2021,7 +2023,7 @@ static int set_config_includefiles(const char *key, const char *value, + } + + static int set_config_rootfs_path(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int ret; + char *dup, *tmp; +@@ -2064,13 +2066,13 @@ static int set_config_rootfs_path(const char *key, const char *value, + } + + static int set_config_rootfs_mount(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + return set_config_path_item(&lxc_conf->rootfs.mount, value); + } + + static int set_config_rootfs_options(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int ret; + unsigned long mflags = 0, pflags = 0; +@@ -2095,7 +2097,7 @@ static int set_config_rootfs_options(const char *key, const char *value, + } + + static int set_config_uts_name(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct utsname *utsname; + +@@ -2121,7 +2123,7 @@ static int set_config_uts_name(const char *key, const char *value, + } + + static int set_config_namespace_clone(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + char *ns, *token; + int cloneflag = 0; +@@ -2156,7 +2158,7 @@ static int set_config_namespace_clone(const char *key, const char *value, + } + + static int set_config_namespace_keep(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + char *ns, *token; + int cloneflag = 0; +@@ -2191,7 +2193,7 @@ static int set_config_namespace_keep(const char *key, const char *value, + } + + static int set_config_namespace_share(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int ns_idx; + const char *namespace; +@@ -2209,7 +2211,7 @@ static int set_config_namespace_share(const char *key, const char *value, + + /* isulad: set config for init args */ + static int set_config_init_args(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int ret = 0; + char *tmp = NULL; +@@ -2219,8 +2221,8 @@ static int set_config_init_args(const char *key, const char *value, + if (ret || !new_value) + return ret; + +- tmp = realloc(lxc_conf->init_argv, (lxc_conf->init_argc + 1) * sizeof(char *)); +- if (!tmp) { ++ if (lxc_mem_realloc((void **)&tmp, (lxc_conf->init_argc + 1) * sizeof(char *), lxc_conf->init_argv, ++ (lxc_conf->init_argc) * sizeof(char *)) != 0) { + ERROR("Out of memory"); + free(new_value); + return -1; +@@ -2236,9 +2238,10 @@ static int set_config_init_args(const char *key, const char *value, + + /* isulad: set config for init groups */ + static int set_config_init_groups(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { +- char *groups, *token; ++ char *groups = NULL; ++ char *token = NULL; + int ret = -1; + + if (lxc_config_value_empty(value)) +@@ -2252,9 +2255,9 @@ static int set_config_init_groups(const char *key, const char *value, + * split these caps in a single element for the list. + */ + lxc_iterate_parts(token, groups, " \t") { +- gid_t *tmp; +- tmp = realloc(lxc_conf->init_groups, (lxc_conf->init_groups_len + 1) * sizeof(gid_t)); +- if (!tmp) { ++ gid_t *tmp = NULL; ++ if (lxc_mem_realloc((void **)&tmp, (lxc_conf->init_groups_len + 1) * sizeof(gid_t), lxc_conf->init_groups, ++ (lxc_conf->init_groups_len) * sizeof(gid_t)) != 0) { + ERROR("Out of memory"); + goto on_error; + } +@@ -2273,93 +2276,93 @@ on_error: + + /* isulad: set config for populate device */ + static int set_config_populate_device(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) +-{ +- int ret = 0, major = 0, minor = 0; +- uid_t uid = (uid_t)-1; +- gid_t gid = (gid_t)-1; +- char name[PATH_MAX] = {0}; +- char type[3] = {0}; +- char *replace_value = NULL; +- mode_t filemode = 0; +- struct lxc_list *iter; +- struct lxc_list *dev_list = NULL; +- struct lxc_populate_devs *dev_elem = NULL; +- +- if (lxc_config_value_empty(value)) +- return lxc_clear_populate_devices(lxc_conf); +- +- /* lxc.populate.device = PATH_IN_CONTAINER:DEVICETYPE:MAJOR:MINOR:MODE:UID:GID +- * For e.g. lxc.populate.device = /dev/sda:b:8:0:0666:0:0 +- */ +- ret = sscanf(value, "%[^:]:%2[^:]:%i:%i:%i:%u:%u", name, type, &major, &minor, &filemode, &uid, &gid); +- if (ret != 7) +- return -1; +- +- /* find existing list element */ +- lxc_list_for_each(iter, &lxc_conf->populate_devs) { +- dev_elem = iter->elem; +- +- if (strcmp(name, dev_elem->name) != 0) +- continue; +- +- replace_value = strdup(type); +- if (!replace_value) +- return -1; +- +- free(dev_elem->type); +- dev_elem->type = replace_value; +- dev_elem->file_mode = filemode; +- dev_elem->maj = major; +- dev_elem->min = minor; +- dev_elem->uid = (uid_t)uid; +- dev_elem->gid = (gid_t)gid; +- return 0; +- } +- +- /* allocate list element */ +- dev_list = malloc(sizeof(*dev_list)); +- if (!dev_list) +- goto on_error; +- +- lxc_list_init(dev_list); +- +- dev_elem = malloc(sizeof(*dev_elem)); +- if (!dev_elem) +- goto on_error; +- memset(dev_elem, 0, sizeof(*dev_elem)); +- +- dev_elem->name = strdup(name); +- if (!dev_elem->name) +- goto on_error; +- +- dev_elem->type = strdup(type); +- if (!dev_elem->type) +- goto on_error; +- +- dev_elem->file_mode = filemode; +- dev_elem->maj = major; +- dev_elem->min = minor; +- +- lxc_list_add_elem(dev_list, dev_elem); +- +- lxc_list_add_tail(&lxc_conf->populate_devs, dev_list); +- +- return 0; ++ struct lxc_conf *lxc_conf, void *data) ++{ ++ int ret = 0, major = 0, minor = 0; ++ uid_t uid = (uid_t)-1; ++ gid_t gid = (gid_t)-1; ++ char name[PATH_MAX] = {0}; ++ char type[3] = {0}; ++ char *replace_value = NULL; ++ mode_t filemode = 0; ++ struct lxc_list *iter = NULL; ++ struct lxc_list *dev_list = NULL; ++ struct lxc_populate_devs *dev_elem = NULL; ++ ++ if (lxc_config_value_empty(value)) ++ return lxc_clear_populate_devices(lxc_conf); ++ ++ /* lxc.populate.device = PATH_IN_CONTAINER:DEVICETYPE:MAJOR:MINOR:MODE:UID:GID ++ * For e.g. lxc.populate.device = /dev/sda:b:8:0:0666:0:0 ++ */ ++ ret = sscanf(value, "%[^:]:%2[^:]:%i:%i:%i:%u:%u", name, type, &major, &minor, &filemode, &uid, &gid); ++ if (ret != 7) ++ return -1; ++ ++ /* find existing list element */ ++ lxc_list_for_each(iter, &lxc_conf->populate_devs) { ++ dev_elem = iter->elem; ++ ++ if (strcmp(name, dev_elem->name) != 0) ++ continue; ++ ++ replace_value = strdup(type); ++ if (!replace_value) ++ return -1; ++ ++ free(dev_elem->type); ++ dev_elem->type = replace_value; ++ dev_elem->file_mode = filemode; ++ dev_elem->maj = major; ++ dev_elem->min = minor; ++ dev_elem->uid = (uid_t)uid; ++ dev_elem->gid = (gid_t)gid; ++ return 0; ++ } ++ ++ /* allocate list element */ ++ dev_list = malloc(sizeof(*dev_list)); ++ if (!dev_list) ++ goto on_error; ++ ++ lxc_list_init(dev_list); ++ ++ dev_elem = malloc(sizeof(*dev_elem)); ++ if (!dev_elem) ++ goto on_error; ++ memset(dev_elem, 0, sizeof(*dev_elem)); ++ ++ dev_elem->name = strdup(name); ++ if (!dev_elem->name) ++ goto on_error; ++ ++ dev_elem->type = strdup(type); ++ if (!dev_elem->type) ++ goto on_error; ++ ++ dev_elem->file_mode = filemode; ++ dev_elem->maj = major; ++ dev_elem->min = minor; ++ ++ lxc_list_add_elem(dev_list, dev_elem); ++ ++ lxc_list_add_tail(&lxc_conf->populate_devs, dev_list); ++ ++ return 0; + + on_error: +- free(dev_list); +- if (dev_elem) { +- free(dev_elem->name); +- free(dev_elem->type); +- free(dev_elem); +- } +- return -1; ++ free(dev_list); ++ if (dev_elem) { ++ free(dev_elem->name); ++ free(dev_elem->type); ++ free(dev_elem); ++ } ++ return -1; + } + + /* isulad: set config for rootfs masked paths */ + static int set_config_rootfs_masked_paths(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_list *list_item = NULL; + +@@ -2387,7 +2390,7 @@ on_error: + + /* isulad: set config for rootfs ro paths */ + static int set_config_rootfs_ro_paths(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_list *list_item = NULL; + +@@ -2416,7 +2419,7 @@ on_error: + + /* isulad: set config for umask */ + static int set_config_umask(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + if (lxc_config_value_empty(value)) { + ERROR("Empty umask"); +@@ -2437,7 +2440,7 @@ static int set_config_umask(const char *key, const char *value, + + /* isulad: set config for systemd */ + static int set_config_systemd(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + if (lxc_config_value_empty(value)) { + ERROR("Empty umask"); +@@ -2673,32 +2676,32 @@ signed long lxc_config_parse_arch(const char *arch) + char *name; + unsigned long per; + } pername[] = { +- { "arm", PER_LINUX32 }, +- { "armel", PER_LINUX32 }, +- { "armhf", PER_LINUX32 }, +- { "armv7l", PER_LINUX32 }, +- { "athlon", PER_LINUX32 }, +- { "i386", PER_LINUX32 }, +- { "i486", PER_LINUX32 }, +- { "i586", PER_LINUX32 }, +- { "i686", PER_LINUX32 }, +- { "linux32", PER_LINUX32 }, +- { "mips", PER_LINUX32 }, +- { "mipsel", PER_LINUX32 }, +- { "ppc", PER_LINUX32 }, +- { "powerpc", PER_LINUX32 }, +- { "x86", PER_LINUX32 }, +- { "amd64", PER_LINUX }, +- { "arm64", PER_LINUX }, +- { "linux64", PER_LINUX }, +- { "mips64", PER_LINUX }, +- { "mips64el", PER_LINUX }, +- { "ppc64", PER_LINUX }, +- { "ppc64el", PER_LINUX }, +- { "ppc64le", PER_LINUX }, +- { "powerpc64", PER_LINUX }, +- { "s390x", PER_LINUX }, +- { "x86_64", PER_LINUX }, ++ { "arm", PER_LINUX32 }, ++ { "armel", PER_LINUX32 }, ++ { "armhf", PER_LINUX32 }, ++ { "armv7l", PER_LINUX32 }, ++ { "athlon", PER_LINUX32 }, ++ { "i386", PER_LINUX32 }, ++ { "i486", PER_LINUX32 }, ++ { "i586", PER_LINUX32 }, ++ { "i686", PER_LINUX32 }, ++ { "linux32", PER_LINUX32 }, ++ { "mips", PER_LINUX32 }, ++ { "mipsel", PER_LINUX32 }, ++ { "ppc", PER_LINUX32 }, ++ { "powerpc", PER_LINUX32 }, ++ { "x86", PER_LINUX32 }, ++ { "amd64", PER_LINUX }, ++ { "arm64", PER_LINUX }, ++ { "linux64", PER_LINUX }, ++ { "mips64", PER_LINUX }, ++ { "mips64el", PER_LINUX }, ++ { "ppc64", PER_LINUX }, ++ { "ppc64el", PER_LINUX }, ++ { "ppc64le", PER_LINUX }, ++ { "powerpc64", PER_LINUX }, ++ { "s390x", PER_LINUX }, ++ { "x86_64", PER_LINUX }, + }; + size_t len = sizeof(pername) / sizeof(pername[0]); + +@@ -2769,7 +2772,7 @@ int write_config(int fd, const struct lxc_conf *conf) + } + + bool do_append_unexp_config_line(struct lxc_conf *conf, const char *key, +- const char *v) ++ const char *v) + { + int ret; + size_t len; +@@ -2793,7 +2796,7 @@ bool do_append_unexp_config_line(struct lxc_conf *conf, const char *key, + } + + void clear_unexp_config_line(struct lxc_conf *conf, const char *key, +- bool rm_subkeys) ++ bool rm_subkeys) + { + char *lend; + char *lstart = conf->unexpanded_config; +@@ -2835,8 +2838,8 @@ void clear_unexp_config_line(struct lxc_conf *conf, const char *key, + } + + bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath, +- const char *newpath, const char *oldname, +- const char *newname, const char *ovldir) ++ const char *newpath, const char *oldname, ++ const char *newname, const char *ovldir) + { + int ret; + char *lend, *newdir, *olddir, *p, *q; +@@ -2847,14 +2850,14 @@ bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath, + olddirlen = strlen(ovldir) + strlen(oldpath) + strlen(oldname) + 2; + olddir = alloca(olddirlen + 1); + ret = snprintf(olddir, olddirlen + 1, "%s=%s/%s", ovldir, oldpath, +- oldname); ++ oldname); + if (ret < 0 || ret >= olddirlen + 1) + return false; + + newdirlen = strlen(ovldir) + strlen(newpath) + strlen(newname) + 2; + newdir = alloca(newdirlen + 1); + ret = snprintf(newdir, newdirlen + 1, "%s=%s/%s", ovldir, newpath, +- newname); ++ newname); + if (ret < 0 || ret >= newdirlen + 1) + return false; + +@@ -2935,7 +2938,7 @@ bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath, + lend += diff; + } + +- next: ++next: + lstart = lend; + } + +@@ -2943,8 +2946,8 @@ bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath, + } + + bool clone_update_unexp_hooks(struct lxc_conf *conf, const char *oldpath, +- const char *newpath, const char *oldname, +- const char *newname) ++ const char *newpath, const char *oldname, ++ const char *newname) + { + int ret; + char *lend, *newdir, *olddir, *p; +@@ -3029,7 +3032,7 @@ bool clone_update_unexp_hooks(struct lxc_conf *conf, const char *oldpath, + lend += diff; + } + +- next: ++next: + lstart = lend; + } + +@@ -3117,7 +3120,7 @@ bool network_new_hwaddrs(struct lxc_conf *conf) + } + + static int set_config_ephemeral(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + if (lxc_config_value_empty(value)) { + lxc_conf->ephemeral = 0; +@@ -3134,7 +3137,7 @@ static int set_config_ephemeral(const char *key, const char *value, + } + + static int set_config_log_syslog(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int facility; + +@@ -3156,7 +3159,7 @@ static int set_config_log_syslog(const char *key, const char *value, + } + + static int set_config_no_new_privs(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + unsigned int v; + +@@ -3178,7 +3181,7 @@ static int set_config_no_new_privs(const char *key, const char *value, + + /* Callbacks to get configuration items. */ + static int get_config_personality(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int fulllen = 0; + +@@ -3206,53 +3209,53 @@ static int get_config_personality(const char *key, char *retv, int inlen, + } + + static int get_config_pty_max(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_size_t(c, retv, inlen, c->pty_max); + } + + static int get_config_tty_max(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_size_t(c, retv, inlen, c->ttys.max); + } + + /* isulad add: get umask value*/ + static int get_config_umask(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_size_t(c, retv, inlen, c->umask); + } + + /* isulad add: get systemd value*/ + static int get_config_systemd(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_str(retv, inlen, c->systemd); + } + + static int get_config_tty_dir(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_str(retv, inlen, c->ttys.dir); + } + + static int get_config_apparmor_profile(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_str(retv, inlen, c->lsm_aa_profile); + } + + static int get_config_apparmor_allow_incomplete(const char *key, char *retv, +- int inlen, struct lxc_conf *c, +- void *data) ++ int inlen, struct lxc_conf *c, ++ void *data) + { + return lxc_get_conf_int(c, retv, inlen, +- c->lsm_aa_allow_incomplete); ++ c->lsm_aa_allow_incomplete); + } + + static int get_config_selinux_context(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_str(retv, inlen, c->lsm_se_context); + } +@@ -3266,8 +3269,8 @@ static int get_config_selinux_context(const char *key, char *retv, int inlen, + * 'lxc.cgroup.subsystem.key = value' format. + */ + static int __get_config_cgroup_controller(const char *key, char *retv, +- int inlen, struct lxc_conf *c, +- int version) ++ int inlen, struct lxc_conf *c, ++ int version) + { + int len; + size_t namespaced_token_len; +@@ -3308,7 +3311,7 @@ static int __get_config_cgroup_controller(const char *key, char *retv, + continue; + + strprint(retv, inlen, "%s.%s = %s\n", global_token, +- cg->subsystem, cg->value); ++ cg->subsystem, cg->value); + } else if (strcmp(cg->subsystem, key) == 0) { + strprint(retv, inlen, "%s\n", cg->value); + } +@@ -3318,21 +3321,21 @@ static int __get_config_cgroup_controller(const char *key, char *retv, + } + + static int get_config_cgroup_controller(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return __get_config_cgroup_controller(key, retv, inlen, c, +- CGROUP_SUPER_MAGIC); ++ CGROUP_SUPER_MAGIC); + } + + static int get_config_cgroup2_controller(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return __get_config_cgroup_controller(key, retv, inlen, c, +- CGROUP2_SUPER_MAGIC); ++ CGROUP2_SUPER_MAGIC); + } + + static int get_config_cgroup_dir(const char *key, char *retv, int inlen, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int len; + int fulllen = 0; +@@ -3348,31 +3351,31 @@ static int get_config_cgroup_dir(const char *key, char *retv, int inlen, + } + + static int get_config_idmaps(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + struct lxc_list *it; + int len, listlen, ret; + int fulllen = 0; +-/* "u 1000 1000000 65536" +- * +- * let's render this as +- * +- * sizeof(char) +- * + +- * sizeof(" ") +- * + +- * sizeof(uint32_t) +- * + +- * sizeof(" ") +- * + +- * sizeof(uint32_t) +- * + +- * sizeof(" ") +- * + +- * sizeof(uint32_t) +- * + +- * \0 +- */ ++ /* "u 1000 1000000 65536" ++ * ++ * let's render this as ++ * ++ * sizeof(char) ++ * + ++ * sizeof(" ") ++ * + ++ * sizeof(uint32_t) ++ * + ++ * sizeof(" ") ++ * + ++ * sizeof(uint32_t) ++ * + ++ * sizeof(" ") ++ * + ++ * sizeof(uint32_t) ++ * + ++ * \0 ++ */ + #define __LXC_IDMAP_STR_BUF (3 * INTTYPE_TO_STRLEN(uint32_t) + 3 + 1 + 1) + char buf[__LXC_IDMAP_STR_BUF]; + +@@ -3385,8 +3388,8 @@ static int get_config_idmaps(const char *key, char *retv, int inlen, + lxc_list_for_each(it, &c->id_map) { + struct id_map *map = it->elem; + ret = snprintf(buf, __LXC_IDMAP_STR_BUF, "%c %lu %lu %lu", +- (map->idtype == ID_TYPE_UID) ? 'u' : 'g', +- map->nsid, map->hostid, map->range); ++ (map->idtype == ID_TYPE_UID) ? 'u' : 'g', ++ map->nsid, map->hostid, map->range); + if (ret < 0 || ret >= __LXC_IDMAP_STR_BUF) + return -1; + +@@ -3397,7 +3400,7 @@ static int get_config_idmaps(const char *key, char *retv, int inlen, + } + + static int get_config_log_level(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + const char *v; + v = lxc_log_priority_to_string(c->loglevel); +@@ -3405,19 +3408,19 @@ static int get_config_log_level(const char *key, char *retv, int inlen, + } + + static int get_config_log_file(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_str(retv, inlen, c->logfile); + } + + static int get_config_mount_fstab(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_str(retv, inlen, c->fstab); + } + + static int get_config_mount_auto(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len, fulllen = 0; + const char *sep = ""; +@@ -3493,7 +3496,7 @@ static int get_config_mount_auto(const char *key, char *retv, int inlen, + } + + static int get_config_mount(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len, fulllen = 0; + struct lxc_list *it; +@@ -3511,33 +3514,33 @@ static int get_config_mount(const char *key, char *retv, int inlen, + } + + static int get_config_rootfs_path(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_str(retv, inlen, c->rootfs.path); + } + + static int get_config_rootfs_mount(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_str(retv, inlen, c->rootfs.mount); + } + + static int get_config_rootfs_options(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_str(retv, inlen, c->rootfs.options); + } + + static int get_config_uts_name(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_str( +- retv, inlen, +- c->utsname ? c->utsname->nodename : NULL); ++ retv, inlen, ++ c->utsname ? c->utsname->nodename : NULL); + } + + static int get_config_hooks(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + char *subkey; + int len, fulllen = 0, found = -1; +@@ -3578,13 +3581,13 @@ static int get_config_hooks(const char *key, char *retv, int inlen, + } + + static int get_config_hooks_version(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_int(c, retv, inlen, c->hooks_version); + } + + static int get_config_net(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len, fulllen = 0; + struct lxc_list *it; +@@ -3604,7 +3607,7 @@ static int get_config_net(const char *key, char *retv, int inlen, + } + + static int get_config_cap_drop(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len, fulllen = 0; + struct lxc_list *it; +@@ -3622,7 +3625,7 @@ static int get_config_cap_drop(const char *key, char *retv, int inlen, + } + + static int get_config_cap_keep(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len, fulllen = 0; + struct lxc_list *it; +@@ -3640,70 +3643,70 @@ static int get_config_cap_keep(const char *key, char *retv, int inlen, + } + + static int get_config_console_path(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_str(retv, inlen, c->console.path); + } + + static int get_config_console_logfile(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_str(retv, inlen, c->console.log_path); + } + + static int get_config_console_rotate(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_int(c, retv, inlen, c->console.log_rotate); + } + + + static int get_config_console_buffer_size(const char *key, char *retv, +- int inlen, struct lxc_conf *c, +- void *data) ++ int inlen, struct lxc_conf *c, ++ void *data) + { + return lxc_get_conf_uint64(c, retv, inlen, c->console.buffer_size); + } + + static int get_config_console_size(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_uint64(c, retv, inlen, c->console.log_size); + } + + + static int get_config_seccomp_profile(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_str(retv, inlen, c->seccomp); + } + + static int get_config_autodev(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_int(c, retv, inlen, c->autodev); + } + + static int get_config_signal_halt(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_int(c, retv, inlen, c->haltsignal); + } + + static int get_config_signal_reboot(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_int(c, retv, inlen, c->rebootsignal); + } + + static int get_config_signal_stop(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_int(c, retv, inlen, c->stopsignal); + } + + static int get_config_start(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + if (strcmp(key + 10, "auto") == 0) + return lxc_get_conf_int(c, retv, inlen, c->start_auto); +@@ -3716,19 +3719,19 @@ static int get_config_start(const char *key, char *retv, int inlen, + } + + static int get_config_log_syslog(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_str(retv, inlen, c->syslog); + } + + static int get_config_monitor(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_int(c, retv, inlen, c->monitor_unshare); + } + + static int get_config_group(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len, fulllen = 0; + struct lxc_list *it; +@@ -3746,7 +3749,7 @@ static int get_config_group(const char *key, char *retv, int inlen, + } + + static int get_config_environment(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len, fulllen = 0; + struct lxc_list *it; +@@ -3765,43 +3768,43 @@ static int get_config_environment(const char *key, char *retv, int inlen, + } + + static int get_config_execute_cmd(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_str(retv, inlen, c->execute_cmd); + } + + static int get_config_init_cmd(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_str(retv, inlen, c->init_cmd); + } + + static int get_config_init_cwd(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_str(retv, inlen, c->init_cwd); + } + + static int get_config_init_uid(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_int(c, retv, inlen, c->init_uid); + } + + static int get_config_init_gid(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_int(c, retv, inlen, c->init_gid); + } + + static int get_config_ephemeral(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_int(c, retv, inlen, c->ephemeral); + } + + static int get_config_no_new_privs(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_get_conf_int(c, retv, inlen, c->no_new_privs); + } +@@ -3811,7 +3814,7 @@ static int get_config_no_new_privs(const char *key, char *retv, int inlen, + * printed, in 'lxc.prlimit.resource = value' format. + */ + static int get_config_prlimit(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int fulllen = 0, len; + bool get_all = false; +@@ -3840,7 +3843,7 @@ static int get_config_prlimit(const char *key, char *retv, int inlen, + partlen = STRLITERALLEN("unlimited"); + } else { + partlen = sprintf(buf, "%" PRIu64, +- (uint64_t)lim->limit.rlim_cur); ++ (uint64_t)lim->limit.rlim_cur); + } + + if (lim->limit.rlim_cur != lim->limit.rlim_max) { +@@ -3849,12 +3852,12 @@ static int get_config_prlimit(const char *key, char *retv, int inlen, + STRLITERALLEN(":unlimited") + 1); + else + sprintf(buf + partlen, ":%" PRIu64, +- (uint64_t)lim->limit.rlim_max); ++ (uint64_t)lim->limit.rlim_max); + } + + if (get_all) { + strprint(retv, inlen, "lxc.prlimit.%s = %s\n", +- lim->resource, buf); ++ lim->resource, buf); + } else if (strcmp(lim->resource, key) == 0) { + strprint(retv, inlen, "%s", buf); + } +@@ -3868,7 +3871,7 @@ static int get_config_prlimit(const char *key, char *retv, int inlen, + * entries will be printed, in 'lxc.sysctl.key = value' format. + */ + static int get_config_sysctl(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len; + struct lxc_list *it; +@@ -3891,7 +3894,7 @@ static int get_config_sysctl(const char *key, char *retv, int inlen, + struct lxc_sysctl *elem = it->elem; + if (get_all) { + strprint(retv, inlen, "lxc.sysctl.%s = %s\n", elem->key, +- elem->value); ++ elem->value); + } else if (strcmp(elem->key, key) == 0) { + strprint(retv, inlen, "%s", elem->value); + } +@@ -3901,7 +3904,7 @@ static int get_config_sysctl(const char *key, char *retv, int inlen, + } + + static int get_config_proc(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + struct lxc_list *it; + int len; +@@ -3935,7 +3938,7 @@ static int get_config_proc(const char *key, char *retv, int inlen, + } + + static int get_config_namespace_clone(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int i, len; + int fulllen = 0; +@@ -3954,7 +3957,7 @@ static int get_config_namespace_clone(const char *key, char *retv, int inlen, + } + + static int get_config_namespace_keep(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int i, len; + int fulllen = 0; +@@ -3973,7 +3976,7 @@ static int get_config_namespace_keep(const char *key, char *retv, int inlen, + } + + static int get_config_namespace_share(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len, ns_idx; + const char *namespace; +@@ -3996,7 +3999,7 @@ static int get_config_namespace_share(const char *key, char *retv, int inlen, + + /* isulad: get config init args */ + static int get_config_init_args(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int i, len, fulllen = 0; + +@@ -4006,7 +4009,7 @@ static int get_config_init_args(const char *key, char *retv, int inlen, + memset(retv, 0, inlen); + + for (i = 0; i < c->init_argc; i++) { +- strprint(retv, inlen, "%s", c->init_argv[i]); ++ strprint(retv, inlen, "%s", c->init_argv[i]); + } + + return fulllen; +@@ -4014,7 +4017,7 @@ static int get_config_init_args(const char *key, char *retv, int inlen, + + /* isulad: get config init groups */ + static int get_config_init_groups(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int i, len, fulllen = 0; + +@@ -4024,7 +4027,7 @@ static int get_config_init_groups(const char *key, char *retv, int inlen, + memset(retv, 0, inlen); + + for (i = 0; i < c->init_groups_len; i++) { +- strprint(retv, inlen, "%u\n", c->init_groups[i]); ++ strprint(retv, inlen, "%u\n", c->init_groups[i]); + } + + return fulllen; +@@ -4036,10 +4039,10 @@ static int get_config_init_groups(const char *key, char *retv, int inlen, + * For e.g. lxc.populate.device = /dev/sda:b:8:0:0666:0:0 + */ + static int get_config_populate_device(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len; +- struct lxc_list *it; ++ struct lxc_list *it = NULL; + int fulllen = 0; + + if (!retv) +@@ -4050,8 +4053,8 @@ static int get_config_populate_device(const char *key, char *retv, int inlen, + lxc_list_for_each(it, &c->populate_devs) { + struct lxc_populate_devs *elem = it->elem; + strprint(retv, inlen, "lxc.populate.device = %s:%s:%d:%d:%o:%u:%u\n", +- elem->name, elem->type, elem->maj, +- elem->min, elem->file_mode, elem->uid, elem->gid); ++ elem->name, elem->type, elem->maj, ++ elem->min, elem->file_mode, elem->uid, elem->gid); + } + + return fulllen; +@@ -4059,10 +4062,10 @@ static int get_config_populate_device(const char *key, char *retv, int inlen, + + // isulad: get config rootfs masked paths + static int get_config_rootfs_masked_paths(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len, fulllen = 0; +- struct lxc_list *it; ++ struct lxc_list *it = NULL; + + if (!retv) + inlen = 0; +@@ -4078,10 +4081,10 @@ static int get_config_rootfs_masked_paths(const char *key, char *retv, int inlen + + // isulad: get config rootfs ro paths + static int get_config_rootfs_ro_paths(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len, fulllen = 0; +- struct lxc_list *it; ++ struct lxc_list *it = NULL; + + if (!retv) + inlen = 0; +@@ -4097,28 +4100,28 @@ static int get_config_rootfs_ro_paths(const char *key, char *retv, int inlen, + + /* Callbacks to clear config items. */ + static inline int clr_config_personality(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + c->personality = -1; + return 0; + } + + static inline int clr_config_pty_max(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + c->pty_max = 0; + return 0; + } + + static inline int clr_config_tty_max(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + c->ttys.tty = 0; + return 0; + } + + static inline int clr_config_tty_dir(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + free(c->ttys.dir); + c->ttys.dir = NULL; +@@ -4126,7 +4129,7 @@ static inline int clr_config_tty_dir(const char *key, struct lxc_conf *c, + } + + static inline int clr_config_apparmor_profile(const char *key, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + free(c->lsm_aa_profile); + c->lsm_aa_profile = NULL; +@@ -4134,15 +4137,15 @@ static inline int clr_config_apparmor_profile(const char *key, + } + + static inline int clr_config_apparmor_allow_incomplete(const char *key, +- struct lxc_conf *c, +- void *data) ++ struct lxc_conf *c, ++ void *data) + { + c->lsm_aa_allow_incomplete = 0; + return 0; + } + + static inline int clr_config_selinux_context(const char *key, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + free(c->lsm_se_context); + c->lsm_se_context = NULL; +@@ -4150,19 +4153,19 @@ static inline int clr_config_selinux_context(const char *key, + } + + static inline int clr_config_cgroup_controller(const char *key, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_clear_cgroups(c, key, CGROUP_SUPER_MAGIC); + } + + static inline int clr_config_cgroup2_controller(const char *key, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return lxc_clear_cgroups(c, key, CGROUP2_SUPER_MAGIC); + } + + static int clr_config_cgroup_dir(const char *key, struct lxc_conf *lxc_conf, +- void *data) ++ void *data) + { + if (lxc_conf->cgroup_meta.dir) { + free(lxc_conf->cgroup_meta.dir); +@@ -4173,20 +4176,20 @@ static int clr_config_cgroup_dir(const char *key, struct lxc_conf *lxc_conf, + } + + static inline int clr_config_idmaps(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + return lxc_clear_idmaps(c); + } + + static inline int clr_config_log_level(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + c->loglevel = LXC_LOG_LEVEL_NOTSET; + return 0; + } + + static inline int clr_config_log_file(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + free(c->logfile); + c->logfile = NULL; +@@ -4194,19 +4197,19 @@ static inline int clr_config_log_file(const char *key, struct lxc_conf *c, + } + + static inline int clr_config_mount(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + return lxc_clear_mount_entries(c); + } + + static inline int clr_config_mount_auto(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + return lxc_clear_automounts(c); + } + + static inline int clr_config_mount_fstab(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + free(c->fstab); + c->fstab = NULL; +@@ -4214,7 +4217,7 @@ static inline int clr_config_mount_fstab(const char *key, struct lxc_conf *c, + } + + static inline int clr_config_rootfs_path(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + free(c->rootfs.path); + c->rootfs.path = NULL; +@@ -4222,7 +4225,7 @@ static inline int clr_config_rootfs_path(const char *key, struct lxc_conf *c, + } + + static inline int clr_config_rootfs_mount(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + free(c->rootfs.mount); + c->rootfs.mount = NULL; +@@ -4230,7 +4233,7 @@ static inline int clr_config_rootfs_mount(const char *key, struct lxc_conf *c, + } + + static inline int clr_config_rootfs_options(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + free(c->rootfs.options); + c->rootfs.options = NULL; +@@ -4242,7 +4245,7 @@ static inline int clr_config_rootfs_options(const char *key, struct lxc_conf *c, + } + + static inline int clr_config_uts_name(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + free(c->utsname); + c->utsname = NULL; +@@ -4250,13 +4253,13 @@ static inline int clr_config_uts_name(const char *key, struct lxc_conf *c, + } + + static inline int clr_config_hooks(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + return lxc_clear_hooks(c, key); + } + + static inline int clr_config_hooks_version(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + /* default to legacy hooks version */ + c->hooks_version = 0; +@@ -4264,7 +4267,7 @@ static inline int clr_config_hooks_version(const char *key, struct lxc_conf *c, + } + + static inline int clr_config_net(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + lxc_free_networks(&c->network); + +@@ -4272,19 +4275,19 @@ static inline int clr_config_net(const char *key, struct lxc_conf *c, + } + + static inline int clr_config_cap_drop(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + return lxc_clear_config_caps(c); + } + + static inline int clr_config_cap_keep(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + return lxc_clear_config_keepcaps(c); + } + + static inline int clr_config_console_path(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + free(c->console.path); + c->console.path = NULL; +@@ -4292,7 +4295,7 @@ static inline int clr_config_console_path(const char *key, struct lxc_conf *c, + } + + static inline int clr_config_console_logfile(const char *key, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + free(c->console.log_path); + c->console.log_path = NULL; +@@ -4300,28 +4303,28 @@ static inline int clr_config_console_logfile(const char *key, + } + + static inline int clr_config_console_rotate(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + c->console.log_rotate = 0; + return 0; + } + + static inline int clr_config_console_buffer_size(const char *key, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + c->console.buffer_size = 0; + return 0; + } + + static inline int clr_config_console_size(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + c->console.log_size = 0; + return 0; + } + + static inline int clr_config_seccomp_profile(const char *key, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + free(c->seccomp); + c->seccomp = NULL; +@@ -4329,35 +4332,35 @@ static inline int clr_config_seccomp_profile(const char *key, + } + + static inline int clr_config_autodev(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + c->autodev = 1; + return 0; + } + + static inline int clr_config_signal_halt(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + c->haltsignal = 0; + return 0; + } + + static inline int clr_config_signal_reboot(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + c->rebootsignal = 0; + return 0; + } + + static inline int clr_config_signal_stop(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + c->stopsignal = 0; + return 0; + } + + static inline int clr_config_start(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + if (strcmp(key + 10, "auto") == 0) + c->start_auto = 0; +@@ -4370,7 +4373,7 @@ static inline int clr_config_start(const char *key, struct lxc_conf *c, + } + + static inline int clr_config_log_syslog(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + free(c->syslog); + c->syslog = NULL; +@@ -4378,26 +4381,26 @@ static inline int clr_config_log_syslog(const char *key, struct lxc_conf *c, + } + + static inline int clr_config_monitor(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + c->monitor_unshare = 0; + return 0; + } + + static inline int clr_config_group(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + return lxc_clear_groups(c); + } + + static inline int clr_config_environment(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + return lxc_clear_environment(c); + } + + static inline int clr_config_execute_cmd(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + free(c->execute_cmd); + c->execute_cmd = NULL; +@@ -4405,7 +4408,7 @@ static inline int clr_config_execute_cmd(const char *key, struct lxc_conf *c, + } + + static inline int clr_config_init_cmd(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + free(c->init_cmd); + c->init_cmd = NULL; +@@ -4413,7 +4416,7 @@ static inline int clr_config_init_cmd(const char *key, struct lxc_conf *c, + } + + static inline int clr_config_init_cwd(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + free(c->init_cwd); + c->init_cwd = NULL; +@@ -4421,74 +4424,74 @@ static inline int clr_config_init_cwd(const char *key, struct lxc_conf *c, + } + + static inline int clr_config_init_uid(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + c->init_uid = 0; + return 0; + } + + static inline int clr_config_init_gid(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + c->init_gid = 0; + return 0; + } + + static inline int clr_config_ephemeral(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + c->ephemeral = 0; + return 0; + } + + static inline int clr_config_no_new_privs(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + c->no_new_privs = false; + return 0; + } + + static inline int clr_config_prlimit(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + return lxc_clear_limits(c, key); + } + + static inline int clr_config_sysctl(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + return lxc_clear_sysctls(c, key); + } + + static inline int clr_config_proc(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + return lxc_clear_procs(c, key); + } + + static inline int clr_config_includefiles(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + lxc_clear_includes(c); + return 0; + } + + static int clr_config_namespace_clone(const char *key, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + lxc_conf->ns_clone = 0; + return 0; + } + + static int clr_config_namespace_keep(const char *key, struct lxc_conf *lxc_conf, +- void *data) ++ void *data) + { + lxc_conf->ns_keep = 0; + return 0; + } + + static int clr_config_namespace_share(const char *key, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int ns_idx; + const char *namespace; +@@ -4506,7 +4509,7 @@ static int clr_config_namespace_share(const char *key, + + /* isulad add: clear umask value */ + static inline int clr_config_umask(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + c->umask = 0027; + return 0; +@@ -4514,7 +4517,7 @@ static inline int clr_config_umask(const char *key, struct lxc_conf *c, + + /* isulad add: clear systemd value */ + static inline int clr_config_systemd(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + free(c->systemd); + c->systemd = NULL; +@@ -4522,15 +4525,15 @@ static inline int clr_config_systemd(const char *key, struct lxc_conf *c, + } + + static int get_config_includefiles(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + return -ENOSYS; + } + + static struct lxc_config_t *get_network_config_ops(const char *key, +- struct lxc_conf *lxc_conf, +- ssize_t *idx, +- char **deindexed_key) ++ struct lxc_conf *lxc_conf, ++ ssize_t *idx, ++ char **deindexed_key) + { + int ret; + unsigned int tmpidx; +@@ -4624,7 +4627,7 @@ on_error: + * rewriting the key), and call it. + */ + static int set_config_net_nic(const char *key, const char *value, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + int ret; + const char *idxstring; +@@ -4657,7 +4660,7 @@ static int set_config_net_nic(const char *key, const char *value, + } + + static int clr_config_net_nic(const char *key, struct lxc_conf *lxc_conf, +- void *data) ++ void *data) + { + int ret; + const char *idxstring; +@@ -4703,7 +4706,7 @@ static int clr_config_net_nic(const char *key, struct lxc_conf *lxc_conf, + } + + static int clr_config_net_type(const char *key, struct lxc_conf *lxc_conf, +- void *data) ++ void *data) + { + struct lxc_netdev *netdev = data; + +@@ -4716,7 +4719,7 @@ static int clr_config_net_type(const char *key, struct lxc_conf *lxc_conf, + } + + static int clr_config_net_name(const char *key, struct lxc_conf *lxc_conf, +- void *data) ++ void *data) + { + struct lxc_netdev *netdev = data; + +@@ -4729,7 +4732,7 @@ static int clr_config_net_name(const char *key, struct lxc_conf *lxc_conf, + } + + static int clr_config_net_flags(const char *key, struct lxc_conf *lxc_conf, +- void *data) ++ void *data) + { + struct lxc_netdev *netdev = data; + +@@ -4742,7 +4745,7 @@ static int clr_config_net_flags(const char *key, struct lxc_conf *lxc_conf, + } + + static int clr_config_net_link(const char *key, struct lxc_conf *lxc_conf, +- void *data) ++ void *data) + { + struct lxc_netdev *netdev = data; + +@@ -4755,7 +4758,7 @@ static int clr_config_net_link(const char *key, struct lxc_conf *lxc_conf, + } + + static int clr_config_net_macvlan_mode(const char *key, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_netdev *netdev = data; + +@@ -4771,7 +4774,7 @@ static int clr_config_net_macvlan_mode(const char *key, + } + + static int clr_config_net_veth_pair(const char *key, struct lxc_conf *lxc_conf, +- void *data) ++ void *data) + { + struct lxc_netdev *netdev = data; + +@@ -4784,7 +4787,7 @@ static int clr_config_net_veth_pair(const char *key, struct lxc_conf *lxc_conf, + } + + static int clr_config_net_script_up(const char *key, struct lxc_conf *lxc_conf, +- void *data) ++ void *data) + { + struct lxc_netdev *netdev = data; + +@@ -4798,7 +4801,7 @@ static int clr_config_net_script_up(const char *key, struct lxc_conf *lxc_conf, + } + + static int clr_config_net_script_down(const char *key, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_netdev *netdev = data; + +@@ -4812,7 +4815,7 @@ static int clr_config_net_script_down(const char *key, + } + + static int clr_config_net_hwaddr(const char *key, struct lxc_conf *lxc_conf, +- void *data) ++ void *data) + { + struct lxc_netdev *netdev = data; + +@@ -4826,7 +4829,7 @@ static int clr_config_net_hwaddr(const char *key, struct lxc_conf *lxc_conf, + } + + static int clr_config_net_mtu(const char *key, struct lxc_conf *lxc_conf, +- void *data) ++ void *data) + { + struct lxc_netdev *netdev = data; + +@@ -4840,7 +4843,7 @@ static int clr_config_net_mtu(const char *key, struct lxc_conf *lxc_conf, + } + + static int clr_config_net_vlan_id(const char *key, struct lxc_conf *lxc_conf, +- void *data) ++ void *data) + { + struct lxc_netdev *netdev = data; + +@@ -4853,7 +4856,7 @@ static int clr_config_net_vlan_id(const char *key, struct lxc_conf *lxc_conf, + } + + static int clr_config_net_ipv4_gateway(const char *key, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_netdev *netdev = data; + +@@ -4867,7 +4870,7 @@ static int clr_config_net_ipv4_gateway(const char *key, + } + + static int clr_config_net_ipv4_address(const char *key, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_netdev *netdev = data; + struct lxc_list *cur, *next; +@@ -4885,7 +4888,7 @@ static int clr_config_net_ipv4_address(const char *key, + } + + static int clr_config_net_ipv6_gateway(const char *key, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_netdev *netdev = data; + +@@ -4899,7 +4902,7 @@ static int clr_config_net_ipv6_gateway(const char *key, + } + + static int clr_config_net_ipv6_address(const char *key, +- struct lxc_conf *lxc_conf, void *data) ++ struct lxc_conf *lxc_conf, void *data) + { + struct lxc_netdev *netdev = data; + struct lxc_list *cur, *next; +@@ -4918,41 +4921,41 @@ static int clr_config_net_ipv6_address(const char *key, + + /* isulad: clr config init args*/ + static inline int clr_config_init_args(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + return lxc_clear_init_args(c); + } + + /* isulad: clr config init args*/ + static inline int clr_config_init_groups(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + return lxc_clear_init_groups(c); + } + + /* isulad: clr config populate devices*/ + static inline int clr_config_populate_device(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + return lxc_clear_populate_devices(c); + } + + /* isulad: clr config rootfs masked paths */ + static inline int clr_config_rootfs_masked_paths(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + return lxc_clear_rootfs_masked_paths(c); + } + + /* isulad: clr config rootfs ro paths */ + static inline int clr_config_rootfs_ro_paths(const char *key, struct lxc_conf *c, +- void *data) ++ void *data) + { + return lxc_clear_rootfs_ro_paths(c); + } + + static int get_config_net_nic(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int ret; + const char *idxstring; +@@ -4982,7 +4985,7 @@ static int get_config_net_nic(const char *key, char *retv, int inlen, + } + + static int get_config_net_type(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len; + int fulllen = 0; +@@ -5002,7 +5005,7 @@ static int get_config_net_type(const char *key, char *retv, int inlen, + } + + static int get_config_net_flags(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len; + int fulllen = 0; +@@ -5023,7 +5026,7 @@ static int get_config_net_flags(const char *key, char *retv, int inlen, + } + + static int get_config_net_link(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len; + int fulllen = 0; +@@ -5044,7 +5047,7 @@ static int get_config_net_link(const char *key, char *retv, int inlen, + } + + static int get_config_net_name(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len; + int fulllen = 0; +@@ -5065,7 +5068,7 @@ static int get_config_net_name(const char *key, char *retv, int inlen, + } + + static int get_config_net_macvlan_mode(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len; + int fulllen = 0; +@@ -5107,7 +5110,7 @@ static int get_config_net_macvlan_mode(const char *key, char *retv, int inlen, + } + + static int get_config_net_veth_pair(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len; + int fulllen = 0; +@@ -5125,15 +5128,15 @@ static int get_config_net_veth_pair(const char *key, char *retv, int inlen, + return 0; + + strprint(retv, inlen, "%s", +- netdev->priv.veth_attr.pair[0] != '\0' +- ? netdev->priv.veth_attr.pair +- : netdev->priv.veth_attr.veth1); ++ netdev->priv.veth_attr.pair[0] != '\0' ++ ? netdev->priv.veth_attr.pair ++ : netdev->priv.veth_attr.veth1); + + return fulllen; + } + + static int get_config_net_script_up(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len; + int fulllen = 0; +@@ -5154,7 +5157,7 @@ static int get_config_net_script_up(const char *key, char *retv, int inlen, + } + + static int get_config_net_script_down(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len; + int fulllen = 0; +@@ -5175,7 +5178,7 @@ static int get_config_net_script_down(const char *key, char *retv, int inlen, + } + + static int get_config_net_hwaddr(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len; + int fulllen = 0; +@@ -5196,7 +5199,7 @@ static int get_config_net_hwaddr(const char *key, char *retv, int inlen, + } + + static int get_config_net_mtu(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len; + int fulllen = 0; +@@ -5217,7 +5220,7 @@ static int get_config_net_mtu(const char *key, char *retv, int inlen, + } + + static int get_config_net_vlan_id(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len; + int fulllen = 0; +@@ -5240,7 +5243,7 @@ static int get_config_net_vlan_id(const char *key, char *retv, int inlen, + } + + static int get_config_net_ipv4_gateway(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len; + char buf[INET_ADDRSTRLEN]; +@@ -5266,7 +5269,7 @@ static int get_config_net_ipv4_gateway(const char *key, char *retv, int inlen, + } + + static int get_config_net_ipv4_address(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len; + size_t listlen; +@@ -5289,14 +5292,14 @@ static int get_config_net_ipv4_address(const char *key, char *retv, int inlen, + struct lxc_inetdev *i = it->elem; + inet_ntop(AF_INET, &i->addr, buf, sizeof(buf)); + strprint(retv, inlen, "%s/%u%s", buf, i->prefix, +- (listlen-- > 1) ? "\n" : ""); ++ (listlen-- > 1) ? "\n" : ""); + } + + return fulllen; + } + + static int get_config_net_ipv6_gateway(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len; + char buf[INET6_ADDRSTRLEN]; +@@ -5322,7 +5325,7 @@ static int get_config_net_ipv6_gateway(const char *key, char *retv, int inlen, + } + + static int get_config_net_ipv6_address(const char *key, char *retv, int inlen, +- struct lxc_conf *c, void *data) ++ struct lxc_conf *c, void *data) + { + int len; + size_t listlen; +@@ -5345,7 +5348,7 @@ static int get_config_net_ipv6_address(const char *key, char *retv, int inlen, + struct lxc_inet6dev *i = it->elem; + inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf)); + strprint(retv, inlen, "%s/%u%s", buf, i->prefix, +- (listlen-- > 1) ? "\n" : ""); ++ (listlen-- > 1) ? "\n" : ""); + } + + return fulllen; +@@ -5375,7 +5378,7 @@ int lxc_list_config_items(char *retv, int inlen) + } + + int lxc_list_subkeys(struct lxc_conf *conf, const char *key, char *retv, +- int inlen) ++ int inlen) + { + int len; + int fulllen = 0; +diff --git a/src/lxc/confile_utils.c b/src/lxc/confile_utils.c +index 9049ce8..8c5208f 100644 +--- a/src/lxc/confile_utils.c ++++ b/src/lxc/confile_utils.c +@@ -46,7 +46,7 @@ + lxc_log_define(confile_utils, lxc); + + int parse_idmaps(const char *idmap, char *type, unsigned long *nsid, +- unsigned long *hostid, unsigned long *range) ++ unsigned long *hostid, unsigned long *range) + { + int ret = -1; + unsigned long tmp_hostid, tmp_nsid, tmp_range; +@@ -223,7 +223,7 @@ struct lxc_netdev *lxc_network_add(struct lxc_list *networks, int idx, bool tail + * allocates a new one if it couldn't be found. + */ + struct lxc_netdev *lxc_get_netdev_by_idx(struct lxc_conf *conf, +- unsigned int idx, bool allocate) ++ unsigned int idx, bool allocate) + { + struct lxc_netdev *netdev = NULL; + struct lxc_list *networks = &conf->network; +@@ -252,7 +252,7 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf) + struct lxc_list *it = (struct lxc_list *)&conf->network;; + + if ((conf->loglevel != LXC_LOG_LEVEL_TRACE) && +- (lxc_log_get_level() != LXC_LOG_LEVEL_TRACE)) ++ (lxc_log_get_level() != LXC_LOG_LEVEL_TRACE)) + return; + + if (lxc_list_empty(it)) { +@@ -294,7 +294,7 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf) + char *mode; + + mode = lxc_macvlan_flag_to_mode( +- netdev->priv.macvlan_attr.mode); ++ netdev->priv.macvlan_attr.mode); + TRACE("macvlan mode: %s", + mode ? mode : "(invalid mode)"); + } +@@ -348,14 +348,14 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf) + + if (netdev->ipv4_gateway) { + inet_ntop(AF_INET, netdev->ipv4_gateway, +- bufinet4, sizeof(bufinet4)); ++ bufinet4, sizeof(bufinet4)); + TRACE("ipv4 gateway: %s", bufinet4); + } + + lxc_list_for_each_safe(cur, &netdev->ipv4, next) { + inet4dev = cur->elem; + inet_ntop(AF_INET, &inet4dev->addr, bufinet4, +- sizeof(bufinet4)); ++ sizeof(bufinet4)); + TRACE("ipv4 addr: %s", bufinet4); + } + +@@ -364,14 +364,14 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf) + + if (netdev->ipv6_gateway) { + inet_ntop(AF_INET6, netdev->ipv6_gateway, +- bufinet6, sizeof(bufinet6)); ++ bufinet6, sizeof(bufinet6)); + TRACE("ipv6 gateway: %s", bufinet6); + } + + lxc_list_for_each_safe(cur, &netdev->ipv6, next) { + inet6dev = cur->elem; + inet_ntop(AF_INET6, &inet6dev->addr, bufinet6, +- sizeof(bufinet6)); ++ sizeof(bufinet6)); + TRACE("ipv6 addr: %s", bufinet6); + } + } +@@ -448,10 +448,10 @@ static struct lxc_macvlan_mode { + char *name; + int mode; + } macvlan_mode[] = { +- { "private", MACVLAN_MODE_PRIVATE }, +- { "vepa", MACVLAN_MODE_VEPA }, +- { "bridge", MACVLAN_MODE_BRIDGE }, +- { "passthru", MACVLAN_MODE_PASSTHRU }, ++ { "private", MACVLAN_MODE_PRIVATE }, ++ { "vepa", MACVLAN_MODE_VEPA }, ++ { "bridge", MACVLAN_MODE_BRIDGE }, ++ { "passthru", MACVLAN_MODE_PASSTHRU }, + }; + + int lxc_macvlan_mode_to_flag(int *mode, const char *value) +@@ -595,7 +595,7 @@ bool lxc_config_net_hwaddr(const char *line) + return true; + + if (sscanf(line, "lxc.net.%u.%6s", &index, tmp) == 2 || +- sscanf(line, "lxc.network.%u.%6s", &index, tmp) == 2) ++ sscanf(line, "lxc.network.%u.%6s", &index, tmp) == 2) + return strncmp(tmp, "hwaddr", 6) == 0; + + return false; +@@ -644,13 +644,13 @@ bool new_hwaddr(char *hwaddr) + seed = randseed(false); + + ret = snprintf(hwaddr, 18, "00:16:3e:%02x:%02x:%02x", rand_r(&seed) % 255, +- rand_r(&seed) % 255, rand_r(&seed) % 255); ++ rand_r(&seed) % 255, rand_r(&seed) % 255); + #else + + (void)randseed(true); + + ret = snprintf(hwaddr, 18, "00:16:3e:%02x:%02x:%02x", rand() % 255, +- rand() % 255, rand() % 255); ++ rand() % 255, rand() % 255); + #endif + if (ret < 0 || ret >= 18) { + SYSERROR("Failed to call snprintf()"); +@@ -740,7 +740,7 @@ bool parse_limit_value(const char **value, rlim_t *res) + } + + static int lxc_container_name_to_pid(const char *lxcname_or_pid, +- const char *lxcpath) ++ const char *lxcpath) + { + int ret; + signed long int pid; +@@ -784,16 +784,18 @@ static int lxc_container_name_to_pid(const char *lxcname_or_pid, + } + + int lxc_inherit_namespace(const char *lxcname_or_pid, const char *lxcpath, +- const char *namespace) ++ const char *namespace) + { +- int fd, pid; +- char *dup, *lastslash; ++ int fd = -1; ++ int pid = -1; ++ char *dup = NULL; ++ char *lastslash = NULL; + + /* isulad: add support share namespace by path. + * e.g. "lxc.namespace.share.net = /proc/PID/ns/net or /var/run/netns/net" + */ + if (file_exists(lxcname_or_pid) && !dir_exists(lxcname_or_pid)) { +- fd = open(lxcname_or_pid, O_RDONLY | O_CLOEXEC); ++ fd = lxc_open(lxcname_or_pid, O_RDONLY | O_CLOEXEC, 0); + if (fd < 0) + return -EINVAL; + +diff --git a/src/lxc/json/logger_json_file.c b/src/lxc/json/logger_json_file.c +index 6433b04..409ea11 100644 +--- a/src/lxc/json/logger_json_file.c ++++ b/src/lxc/json/logger_json_file.c +@@ -8,236 +8,236 @@ + #include "logger_json_file.h" + + logger_json_file *make_logger_json_file(yajl_val tree, struct parser_context *ctx, parser_error *err) { +- logger_json_file *ret = NULL; +- *err = 0; +- if (tree == NULL) +- return ret; +- ret = safe_malloc(sizeof(*ret)); +- { +- yajl_val tmp = get_val(tree, "log", yajl_t_string); +- if (tmp != NULL) { +- char *str = YAJL_GET_STRING(tmp); +- ret->log = (uint8_t *)safe_strdup(str ? str : ""); +- ret->log_len = str != NULL ? strlen(str) : 0; +- } +- } +- { +- yajl_val val = get_val(tree, "stream", yajl_t_string); +- if (val != NULL) { +- char *str = YAJL_GET_STRING(val); +- ret->stream = safe_strdup(str ? str : ""); +- } +- } +- { +- yajl_val val = get_val(tree, "time", yajl_t_string); +- if (val != NULL) { +- char *str = YAJL_GET_STRING(val); +- ret->time = safe_strdup(str ? str : ""); +- } +- } +- { +- yajl_val tmp = get_val(tree, "attrs", yajl_t_string); +- if (tmp != NULL) { +- char *str = YAJL_GET_STRING(tmp); +- ret->attrs = (uint8_t *)safe_strdup(str ? str : ""); +- ret->attrs_len = str != NULL ? strlen(str) : 0; +- } +- } +- +- if (tree->type == yajl_t_object && (ctx->options & PARSE_OPTIONS_STRICT)) { +- int i; +- for (i = 0; i < tree->u.object.len; i++) +- if (strcmp(tree->u.object.keys[i], "log") && +- strcmp(tree->u.object.keys[i], "stream") && +- strcmp(tree->u.object.keys[i], "time") && +- strcmp(tree->u.object.keys[i], "attrs")) { +- if (ctx->stderr > 0) +- fprintf(ctx->stderr, "WARNING: unknown key found: %s\n", tree->u.object.keys[i]); +- } +- } +- return ret; ++ logger_json_file *ret = NULL; ++ *err = 0; ++ if (tree == NULL) ++ return ret; ++ ret = safe_malloc(sizeof(*ret)); ++ { ++ yajl_val tmp = get_val(tree, "log", yajl_t_string); ++ if (tmp != NULL) { ++ char *str = YAJL_GET_STRING(tmp); ++ ret->log = (uint8_t *)safe_strdup(str ? str : ""); ++ ret->log_len = str != NULL ? strlen(str) : 0; ++ } ++ } ++ { ++ yajl_val val = get_val(tree, "stream", yajl_t_string); ++ if (val != NULL) { ++ char *str = YAJL_GET_STRING(val); ++ ret->stream = safe_strdup(str ? str : ""); ++ } ++ } ++ { ++ yajl_val val = get_val(tree, "time", yajl_t_string); ++ if (val != NULL) { ++ char *str = YAJL_GET_STRING(val); ++ ret->time = safe_strdup(str ? str : ""); ++ } ++ } ++ { ++ yajl_val tmp = get_val(tree, "attrs", yajl_t_string); ++ if (tmp != NULL) { ++ char *str = YAJL_GET_STRING(tmp); ++ ret->attrs = (uint8_t *)safe_strdup(str ? str : ""); ++ ret->attrs_len = str != NULL ? strlen(str) : 0; ++ } ++ } ++ ++ if (tree->type == yajl_t_object && (ctx->options & PARSE_OPTIONS_STRICT)) { ++ int i; ++ for (i = 0; i < tree->u.object.len; i++) ++ if (strcmp(tree->u.object.keys[i], "log") && ++ strcmp(tree->u.object.keys[i], "stream") && ++ strcmp(tree->u.object.keys[i], "time") && ++ strcmp(tree->u.object.keys[i], "attrs")) { ++ if (ctx->stderr > 0) ++ fprintf(ctx->stderr, "WARNING: unknown key found: %s\n", tree->u.object.keys[i]); ++ } ++ } ++ return ret; + } + + void free_logger_json_file(logger_json_file *ptr) { +- if (ptr == NULL) +- return; +- free(ptr->log); +- ptr->log = NULL; +- free(ptr->stream); +- ptr->stream = NULL; +- free(ptr->time); +- ptr->time = NULL; +- free(ptr->attrs); +- ptr->attrs = NULL; +- free(ptr); ++ if (ptr == NULL) ++ return; ++ free(ptr->log); ++ ptr->log = NULL; ++ free(ptr->stream); ++ ptr->stream = NULL; ++ free(ptr->time); ++ ptr->time = NULL; ++ free(ptr->attrs); ++ ptr->attrs = NULL; ++ free(ptr); + } + + yajl_gen_status gen_logger_json_file(yajl_gen g, logger_json_file *ptr, struct parser_context *ctx, parser_error *err) { +- yajl_gen_status stat = yajl_gen_status_ok; +- *err = 0; +- stat = reformat_start_map(g); +- if (yajl_gen_status_ok != stat) +- GEN_SET_ERROR_AND_RETURN(stat, err); +- if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) || (ptr != NULL && ptr->log != NULL && ptr->log_len)) { +- const char *str = ""; +- size_t len = 0; +- stat = reformat_map_key(g, "log", strlen("log")); +- if (yajl_gen_status_ok != stat) +- GEN_SET_ERROR_AND_RETURN(stat, err); +- if (ptr != NULL && ptr->log != NULL) { +- str = (const char *)ptr->log; +- len = ptr->log_len; +- } +- stat = reformat_string(g, str, len); +- if (yajl_gen_status_ok != stat) +- GEN_SET_ERROR_AND_RETURN(stat, err); +- } +- if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr != NULL && ptr->stream != NULL)) { +- char *str = ""; +- stat = reformat_map_key(g, "stream", strlen("stream")); +- if (yajl_gen_status_ok != stat) +- GEN_SET_ERROR_AND_RETURN(stat, err); +- if (ptr != NULL && ptr->stream != NULL) { +- str = ptr->stream; +- } +- stat = reformat_string(g, str, strlen(str)); +- if (yajl_gen_status_ok != stat) +- GEN_SET_ERROR_AND_RETURN(stat, err); +- } +- if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr != NULL && ptr->time != NULL)) { +- char *str = ""; +- stat = reformat_map_key(g, "time", strlen("time")); +- if (yajl_gen_status_ok != stat) +- GEN_SET_ERROR_AND_RETURN(stat, err); +- if (ptr != NULL && ptr->time != NULL) { +- str = ptr->time; +- } +- stat = reformat_string(g, str, strlen(str)); +- if (yajl_gen_status_ok != stat) +- GEN_SET_ERROR_AND_RETURN(stat, err); +- } +- if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) || (ptr != NULL && ptr->attrs != NULL && ptr->attrs_len)) { +- const char *str = ""; +- size_t len = 0; +- stat = reformat_map_key(g, "attrs", strlen("attrs")); +- if (yajl_gen_status_ok != stat) +- GEN_SET_ERROR_AND_RETURN(stat, err); +- if (ptr != NULL && ptr->attrs != NULL) { +- str = (const char *)ptr->attrs; +- len = ptr->attrs_len; +- } +- stat = reformat_string(g, str, len); +- if (yajl_gen_status_ok != stat) +- GEN_SET_ERROR_AND_RETURN(stat, err); +- } +- stat = reformat_end_map(g); +- if (yajl_gen_status_ok != stat) +- GEN_SET_ERROR_AND_RETURN(stat, err); +- return yajl_gen_status_ok; ++ yajl_gen_status stat = yajl_gen_status_ok; ++ *err = 0; ++ stat = reformat_start_map(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) || (ptr != NULL && ptr->log != NULL && ptr->log_len)) { ++ const char *str = ""; ++ size_t len = 0; ++ stat = reformat_map_key(g, "log", strlen("log")); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (ptr != NULL && ptr->log != NULL) { ++ str = (const char *)ptr->log; ++ len = ptr->log_len; ++ } ++ stat = reformat_string(g, str, len); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr != NULL && ptr->stream != NULL)) { ++ char *str = ""; ++ stat = reformat_map_key(g, "stream", strlen("stream")); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (ptr != NULL && ptr->stream != NULL) { ++ str = ptr->stream; ++ } ++ stat = reformat_string(g, str, strlen(str)); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr != NULL && ptr->time != NULL)) { ++ char *str = ""; ++ stat = reformat_map_key(g, "time", strlen("time")); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (ptr != NULL && ptr->time != NULL) { ++ str = ptr->time; ++ } ++ stat = reformat_string(g, str, strlen(str)); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) || (ptr != NULL && ptr->attrs != NULL && ptr->attrs_len)) { ++ const char *str = ""; ++ size_t len = 0; ++ stat = reformat_map_key(g, "attrs", strlen("attrs")); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ if (ptr != NULL && ptr->attrs != NULL) { ++ str = (const char *)ptr->attrs; ++ len = ptr->attrs_len; ++ } ++ stat = reformat_string(g, str, len); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ } ++ stat = reformat_end_map(g); ++ if (yajl_gen_status_ok != stat) ++ GEN_SET_ERROR_AND_RETURN(stat, err); ++ return yajl_gen_status_ok; + } + + + logger_json_file *logger_json_file_parse_file(const char *filename, struct parser_context *ctx, parser_error *err) { +- logger_json_file *ptr; +- size_t filesize; +- char *content = NULL; +- +- if (filename == NULL || err == NULL) +- return NULL; +- +- *err = NULL; +- content = read_file(filename, &filesize); +- if (content == NULL) { +- if (asprintf(err, "cannot read the file: %s", filename) < 0) +- *err = safe_strdup("error allocating memory"); +- return NULL; +- } +- ptr = logger_json_file_parse_data(content, ctx, err); +- free(content); +- return ptr; ++ logger_json_file *ptr = NULL; ++ size_t filesize; ++ char *content = NULL; ++ ++ if (filename == NULL || err == NULL) ++ return NULL; ++ ++ *err = NULL; ++ content = read_file(filename, &filesize); ++ if (content == NULL) { ++ if (asprintf(err, "cannot read the file: %s", filename) < 0) ++ *err = safe_strdup("error allocating memory"); ++ return NULL; ++ } ++ ptr = logger_json_file_parse_data(content, ctx, err); ++ free(content); ++ return ptr; + } + + logger_json_file *logger_json_file_parse_file_stream(FILE *stream, struct parser_context *ctx, parser_error *err) { +- logger_json_file *ptr; +- size_t filesize; +- char *content = NULL ; +- +- if (stream == NULL || err == NULL) +- return NULL; +- +- *err = NULL; +- content = fread_file(stream, &filesize); +- if (content == NULL) { +- *err = safe_strdup("cannot read the file"); +- return NULL; +- } +- ptr = logger_json_file_parse_data(content, ctx, err); +- free(content); +- return ptr; ++ logger_json_file *ptr = NULL; ++ size_t filesize; ++ char *content = NULL ; ++ ++ if (stream == NULL || err == NULL) ++ return NULL; ++ ++ *err = NULL; ++ content = fread_file(stream, &filesize); ++ if (content == NULL) { ++ *err = safe_strdup("cannot read the file"); ++ return NULL; ++ } ++ ptr = logger_json_file_parse_data(content, ctx, err); ++ free(content); ++ return ptr; + } + + logger_json_file *logger_json_file_parse_data(const char *jsondata, struct parser_context *ctx, parser_error *err) { +- logger_json_file *ptr; +- yajl_val tree; +- char errbuf[1024]; +- struct parser_context tmp_ctx; +- +- if (jsondata == NULL || err == NULL) +- return NULL; +- +- *err = NULL; +- if (ctx == NULL) { +- ctx = &tmp_ctx; +- memset(&tmp_ctx, 0, sizeof(tmp_ctx)); +- } +- tree = yajl_tree_parse(jsondata, errbuf, sizeof(errbuf)); +- if (tree == NULL) { +- if (asprintf(err, "cannot parse the data: %s", errbuf) < 0) +- *err = safe_strdup("error allocating memory"); +- return NULL; +- } +- ptr = make_logger_json_file(tree, ctx, err); +- yajl_tree_free(tree); +- return ptr; ++ logger_json_file *ptr = NULL; ++ yajl_val tree; ++ char errbuf[1024]; ++ struct parser_context tmp_ctx; ++ ++ if (jsondata == NULL || err == NULL) ++ return NULL; ++ ++ *err = NULL; ++ if (ctx == NULL) { ++ ctx = &tmp_ctx; ++ memset(&tmp_ctx, 0, sizeof(tmp_ctx)); ++ } ++ tree = yajl_tree_parse(jsondata, errbuf, sizeof(errbuf)); ++ if (tree == NULL) { ++ if (asprintf(err, "cannot parse the data: %s", errbuf) < 0) ++ *err = safe_strdup("error allocating memory"); ++ return NULL; ++ } ++ ptr = make_logger_json_file(tree, ctx, err); ++ yajl_tree_free(tree); ++ return ptr; + } + char *logger_json_file_generate_json(logger_json_file *ptr, struct parser_context *ctx, parser_error *err) { +- yajl_gen g = NULL; +- struct parser_context tmp_ctx; +- const unsigned char *gen_buf = NULL; +- char *json_buf = NULL; +- size_t gen_len = 0; +- +- if (ptr == NULL || err == NULL) +- return NULL; +- +- *err = NULL; +- if (ctx == NULL) { +- ctx = &tmp_ctx; +- memset(&tmp_ctx, 0, sizeof(tmp_ctx)); +- } +- +- if (!json_gen_init(&g, ctx)) { +- *err = safe_strdup("Json_gen init failed"); +- goto out; +- } +- if (yajl_gen_status_ok != gen_logger_json_file(g, ptr, ctx, err)) { +- if (*err == NULL) +- *err = safe_strdup("Failed to generate json"); +- goto free_out; +- } +- yajl_gen_get_buf(g, &gen_buf, &gen_len); +- if (gen_buf == NULL) { +- *err = safe_strdup("Error to get generated json"); +- goto free_out; +- } +- +- json_buf = safe_malloc(gen_len + 1); +- memcpy(json_buf, gen_buf, gen_len); +- json_buf[gen_len] = '\0'; ++ yajl_gen g = NULL; ++ struct parser_context tmp_ctx; ++ const unsigned char *gen_buf = NULL; ++ char *json_buf = NULL; ++ size_t gen_len = 0; ++ ++ if (ptr == NULL || err == NULL) ++ return NULL; ++ ++ *err = NULL; ++ if (ctx == NULL) { ++ ctx = &tmp_ctx; ++ memset(&tmp_ctx, 0, sizeof(tmp_ctx)); ++ } ++ ++ if (!json_gen_init(&g, ctx)) { ++ *err = safe_strdup("Json_gen init failed"); ++ goto out; ++ } ++ if (yajl_gen_status_ok != gen_logger_json_file(g, ptr, ctx, err)) { ++ if (*err == NULL) ++ *err = safe_strdup("Failed to generate json"); ++ goto free_out; ++ } ++ yajl_gen_get_buf(g, &gen_buf, &gen_len); ++ if (gen_buf == NULL) { ++ *err = safe_strdup("Error to get generated json"); ++ goto free_out; ++ } ++ ++ json_buf = safe_malloc(gen_len + 1); ++ memcpy(json_buf, gen_buf, gen_len); ++ json_buf[gen_len] = '\0'; + + free_out: +- yajl_gen_clear(g); +- yajl_gen_free(g); ++ yajl_gen_clear(g); ++ yajl_gen_free(g); + out: +- return json_buf; ++ return json_buf; + } +diff --git a/src/lxc/json/read-file.c b/src/lxc/json/read-file.c +index ad0eda1..70e73e5 100644 +--- a/src/lxc/json/read-file.c ++++ b/src/lxc/json/read-file.c +@@ -16,79 +16,80 @@ + + char *fread_file(FILE *stream, size_t *length) + { +- char *buf = NULL, *tmpbuf = NULL; +- size_t off = 0; +- +- while (1) { +- size_t ret, newsize; +- +- newsize = off + BUFSIZ + 1; +- tmpbuf = (char *)calloc(1, newsize); +- if (tmpbuf == NULL) { +- goto out; +- } +- +- if (buf) { +- memcpy(tmpbuf, buf, off); +- +- memset(buf, 0, off); +- +- free(buf); +- } +- +- buf = tmpbuf; +- ret = fread(buf + off, 1, BUFSIZ, stream); +- if (!ret && ferror(stream)) { +- tmpbuf = NULL; +- goto out; +- } +- if (ret < BUFSIZ || feof(stream)) { +- *length = off + ret + 1; +- buf[*length - 1] = '\0'; +- return buf; +- } +- off += BUFSIZ; +- } ++ char *buf = NULL, *tmpbuf = NULL; ++ size_t off = 0; ++ ++ while (1) { ++ size_t ret, newsize; ++ ++ newsize = off + BUFSIZ + 1; ++ tmpbuf = (char *)calloc(1, newsize); ++ if (tmpbuf == NULL) { ++ goto out; ++ } ++ ++ if (buf) { ++ memcpy(tmpbuf, buf, off); ++ ++ memset(buf, 0, off); ++ ++ free(buf); ++ } ++ ++ buf = tmpbuf; ++ ret = fread(buf + off, 1, BUFSIZ, stream); ++ if (!ret && ferror(stream)) { ++ tmpbuf = NULL; ++ goto out; ++ } ++ if (ret < BUFSIZ || feof(stream)) { ++ *length = off + ret + 1; ++ buf[*length - 1] = '\0'; ++ return buf; ++ } ++ off += BUFSIZ; ++ } + out: +- if (buf) { +- free(buf); +- } +- if (tmpbuf) { +- free(tmpbuf); +- } +- return NULL; ++ if (buf) { ++ free(buf); ++ } ++ if (tmpbuf) { ++ free(tmpbuf); ++ } ++ return NULL; + + } + + char *read_file(const char *path, size_t *length) + { +- char *buf = NULL; +- char rpath[PATH_MAX + 1] = {0}; +- int fd, tmperrno; +- FILE *fp; +- +- if (!path || !length) { +- return NULL; +- } +- +- if (strlen(path) > PATH_MAX || NULL == realpath(path, rpath)) { +- return NULL; +- } +- +- fd = open(rpath, O_RDONLY | O_CLOEXEC, 0640); +- if (fd < 0) { +- return NULL; +- } +- +- fp = fdopen(fd, "r"); +- tmperrno = errno; +- if (!fp) { +- close(fd); +- errno = tmperrno; +- return NULL; +- } +- +- buf = fread_file(fp, length); +- fclose(fp); +- return buf; ++ char *buf = NULL; ++ char rpath[PATH_MAX + 1] = {0}; ++ int fd = -1; ++ int tmperrno; ++ FILE *fp = NULL; ++ ++ if (!path || !length) { ++ return NULL; ++ } ++ ++ if (strlen(path) > PATH_MAX || NULL == realpath(path, rpath)) { ++ return NULL; ++ } ++ ++ fd = open(rpath, O_RDONLY | O_CLOEXEC, 0640); ++ if (fd < 0) { ++ return NULL; ++ } ++ ++ fp = fdopen(fd, "r"); ++ tmperrno = errno; ++ if (!fp) { ++ close(fd); ++ errno = tmperrno; ++ return NULL; ++ } ++ ++ buf = fread_file(fp, length); ++ fclose(fp); ++ return buf; + } +diff --git a/src/lxc/log.c b/src/lxc/log.c +index 91fb7ef..e598a5f 100644 +--- a/src/lxc/log.c ++++ b/src/lxc/log.c +@@ -157,7 +157,7 @@ static int isulad_open_fifo(const char *file_path) + #define LOG_FIFO_SIZE (1024 * 1024) + int fd = -1; + +- fd = lxc_unpriv(open(file_path, O_RDWR | O_NONBLOCK | O_CLOEXEC, 0640)); ++ fd = lxc_unpriv(lxc_open(file_path, O_RDWR | O_NONBLOCK | O_CLOEXEC, 0640)); + if (fd == -1) { + fprintf(stderr, "Open fifo %s failed: %s\n", file_path, strerror(errno)); + return -1; +@@ -174,7 +174,7 @@ static int isulad_open_fifo(const char *file_path) + + /*---------------------------------------------------------------------------*/ + static int log_append_syslog(const struct lxc_log_appender *appender, +- struct lxc_log_event *event) ++ struct lxc_log_event *event) + { + char *msg; + const char *log_container_name; +@@ -189,7 +189,7 @@ static int log_append_syslog(const struct lxc_log_appender *appender, + return 0; + + syslog(lxc_log_priority_to_syslog(event->priority), +- "%s%s %s - %s:%s:%d - %s" , ++ "%s%s %s - %s:%s:%d - %s", + log_container_name ? log_container_name : "", + log_container_name ? ":" : "", + event->category, +@@ -203,7 +203,7 @@ static int log_append_syslog(const struct lxc_log_appender *appender, + + /*---------------------------------------------------------------------------*/ + static int log_append_stderr(const struct lxc_log_appender *appender, +- struct lxc_log_event *event) ++ struct lxc_log_event *event) + { + const char *log_container_name; + +@@ -227,7 +227,7 @@ static int log_append_stderr(const struct lxc_log_appender *appender, + static int lxc_unix_epoch_to_utc(char *buf, size_t bufsize, const struct timespec *time) + { + int64_t epoch_to_days, z, era, doe, yoe, year, doy, mp, day, month, +- d_in_s, hours, h_in_s, minutes, seconds; ++ d_in_s, hours, h_in_s, minutes, seconds; + char nanosec[INTTYPE_TO_STRLEN(int64_t)]; + int ret; + +@@ -313,9 +313,9 @@ static int lxc_unix_epoch_to_utc(char *buf, size_t bufsize, const struct timespe + * digit precision. + */ + ret = snprintf(buf, bufsize, +- "%" PRId64 "%02" PRId64 "%02" PRId64 "%02" PRId64 +- "%02" PRId64 "%02" PRId64 ".%.3s", +- year, month, day, hours, minutes, seconds, nanosec); ++ "%" PRId64 "%02" PRId64 "%02" PRId64 "%02" PRId64 ++ "%02" PRId64 "%02" PRId64 ".%.3s", ++ year, month, day, hours, minutes, seconds, nanosec); + if (ret < 0 || (size_t)ret >= bufsize) + return -1; + +@@ -343,15 +343,15 @@ static int lxc_unix_epoch_to_utc(char *buf, size_t bufsize, const struct timespe + * to make it pretty. Pretty might cost you thread-safety. + */ + static int log_append_logfile(const struct lxc_log_appender *appender, +- struct lxc_log_event *event) ++ struct lxc_log_event *event) + { + char buffer[LXC_LOG_BUFFER_SIZE]; + char date_time[LXC_LOG_TIME_SIZE]; + int n; + ssize_t ret; + int fd_to_use = -1; +- const char *log_container_name; +- const char *isulad_prefix; ++ const char *log_container_name = NULL; ++ const char *isulad_prefix = NULL; + size_t isulad_len = 0; + + #ifndef NO_LXC_CONF +@@ -377,13 +377,13 @@ static int log_append_logfile(const struct lxc_log_appender *appender, + } + isulad_prefix = log_container_name ? (log_container_name + isulad_len) : log_prefix; + n = snprintf(buffer, sizeof(buffer), +- "%15s %s %-8s %s - %s:%s:%d - ", +- isulad_prefix, +- date_time, +- lxc_log_priority_to_string(event->priority), +- event->category, +- event->locinfo->file, event->locinfo->func, +- event->locinfo->line); ++ "%15s %s %-8s %s - %s:%s:%d - ", ++ isulad_prefix, ++ date_time, ++ lxc_log_priority_to_string(event->priority), ++ event->category, ++ event->locinfo->file, event->locinfo->func, ++ event->locinfo->line); + if (n < 0) + return n; + +@@ -405,7 +405,7 @@ static int log_append_logfile(const struct lxc_log_appender *appender, + + #if HAVE_DLOG + static int log_append_dlog(const struct lxc_log_appender *appender, +- struct lxc_log_event *event) ++ struct lxc_log_event *event) + { + char *msg = lxc_log_get_va_msg(event); + const char *log_container_name = lxc_log_get_container_name(); +@@ -643,10 +643,10 @@ static int __lxc_log_set_file(const char *fname, int create_dirs) + */ + if (create_dirs) + #endif +- if (build_dir(fname)) { +- SYSERROR("Failed to create dir for log file \"%s\"", fname); +- return -1; +- } ++ if (build_dir(fname)) { ++ SYSERROR("Failed to create dir for log file \"%s\"", fname); ++ return -1; ++ } + + if (isulad_use_log_fifo_flag) { + lxc_log_fd = isulad_open_fifo(fname); +@@ -685,7 +685,7 @@ int lxc_log_init(struct lxc_log *log) + { + int ret; + int lxc_priority = LXC_LOG_LEVEL_ERROR; +- const char *tmp_log_fname; ++ const char *tmp_log_fname = NULL; + + if (!log) + return -1; +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index e0c4de3..e32f524 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -111,7 +111,7 @@ static const char *lxcapi_get_config_path(struct lxc_container *c); + #define do_lxcapi_get_config_path(c) lxcapi_get_config_path(c) + static bool do_lxcapi_set_config_item(struct lxc_container *c, const char *key, const char *v); + static bool container_destroy(struct lxc_container *c, +- struct lxc_storage *storage); ++ struct lxc_storage *storage); + static bool get_snappath_dir(struct lxc_container *c, char *snappath); + static bool lxcapi_snapshot_destroy_all(struct lxc_container *c); + static bool do_lxcapi_save_config(struct lxc_container *c, const char *alt_file); +@@ -551,7 +551,7 @@ static int do_lxcapi_console_getfd(struct lxc_container *c, int *ttynum, int *ma + WRAP_API_2(int, lxcapi_console_getfd, int *, int *) + + static int lxcapi_console(struct lxc_container *c, int ttynum, int stdinfd, +- int stdoutfd, int stderrfd, int escape) ++ int stdoutfd, int stderrfd, int escape) + { + int ret; + +@@ -619,7 +619,7 @@ static bool load_config_locked(struct lxc_container *c, const char *fname) + static bool load_ocihooks_locked(struct lxc_container *c) + { + parser_error err = NULL; +- oci_runtime_spec_hooks *hooks; ++ oci_runtime_spec_hooks *hooks = NULL; + + if (!c->lxc_conf) + c->lxc_conf = lxc_conf_init(); +@@ -755,7 +755,7 @@ static bool do_lxcapi_want_close_all_fds(struct lxc_container *c, bool state) + WRAP_API_1(bool, lxcapi_want_close_all_fds, bool) + + static bool do_lxcapi_wait(struct lxc_container *c, const char *state, +- int timeout) ++ int timeout) + { + int ret; + +@@ -833,7 +833,7 @@ static char **split_init_cmd(const char *incmd) + + argv[0] = NULL; + lxc_iterate_parts(p, copy, " ") +- push_arg(&argv, p, &nargs); ++ push_arg(&argv, p, &nargs); + + if (nargs == 0) { + free(argv); +@@ -1116,7 +1116,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a + keepfds[2] = handler->state_socket_pair[1]; + keepfds[4] = conf->errpipe[1]; + ret = lxc_check_inherited(conf, true, keepfds, +- sizeof(keepfds) / sizeof(keepfds[0])); ++ sizeof(keepfds) / sizeof(keepfds[0])); + if (ret < 0) + _exit(EXIT_FAILURE); + +@@ -1176,7 +1176,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a + + /* isulad: open exit fifo */ + if (c->exit_fifo) { +- conf->exit_fd = open(c->exit_fifo, O_WRONLY | O_NONBLOCK | O_CLOEXEC); ++ conf->exit_fd = lxc_open(c->exit_fifo, O_WRONLY | O_NONBLOCK | O_CLOEXEC, 0); + if (conf->exit_fd < 0) { + ERROR("Failed to open exit fifo %s: %s.", c->exit_fifo, strerror(errno)); + ret = 1; +@@ -1226,7 +1226,7 @@ reboot: + if (c->daemonize) + keepfds[4] = conf->errpipe[1]; + ret = lxc_check_inherited(conf, c->daemonize, keepfds, +- sizeof(keepfds) / sizeof(keepfds[0])); ++ sizeof(keepfds) / sizeof(keepfds[0])); + if (ret < 0) { + lxc_free_handler(handler); + ret = 1; +@@ -1235,12 +1235,12 @@ reboot: + + if (useinit) { + ret = lxc_execute(c->name, argv, 1, handler, c->config_path, +- c->daemonize, &c->error_num, c->start_timeout); ++ c->daemonize, &c->error_num, c->start_timeout); + } else { + handler->disable_pty = c->disable_pty; + handler->open_stdin = c->open_stdin; + ret = lxc_start(c->name, argv, handler, c->config_path, +- c->daemonize, &c->error_num, c->start_timeout); ++ c->daemonize, &c->error_num, c->start_timeout); + } + + if (conf->reboot == REBOOT_REQ) { +@@ -1269,7 +1269,7 @@ on_error: + } + + static bool lxcapi_start(struct lxc_container *c, int useinit, +- char *const argv[]) ++ char *const argv[]) + { + bool ret; + +@@ -1390,8 +1390,8 @@ static bool create_container_dir(struct lxc_container *c) + * storage_create(), it returns a mounted bdev on success, NULL on error. + */ + static struct lxc_storage *do_storage_create(struct lxc_container *c, +- const char *type, +- struct bdev_specs *specs) ++ const char *type, ++ struct bdev_specs *specs) + { + int ret; + size_t len; +@@ -1400,7 +1400,7 @@ static struct lxc_storage *do_storage_create(struct lxc_container *c, + + /* rootfs.path or lxcpath/lxcname/rootfs */ + if (c->lxc_conf->rootfs.path && +- (access(c->lxc_conf->rootfs.path, F_OK) == 0)) { ++ (access(c->lxc_conf->rootfs.path, F_OK) == 0)) { + const char *rpath = c->lxc_conf->rootfs.path; + len = strlen(rpath) + 1; + dest = alloca(len); +@@ -1454,7 +1454,7 @@ static char *lxcbasename(char *path) + } + + static bool create_run_template(struct lxc_container *c, char *tpath, +- bool need_null_stdfds, char *const argv[]) ++ bool need_null_stdfds, char *const argv[]) + { + int ret; + pid_t pid; +@@ -1515,7 +1515,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath, + } + + if (strcmp(bdev->type, "overlay") == 0 || +- strcmp(bdev->type, "overlayfs") == 0) { ++ strcmp(bdev->type, "overlayfs") == 0) { + /* If we create an overlay container we need to + * rsync the contents into + * //rootfs. +@@ -1535,7 +1535,9 @@ static bool create_run_template(struct lxc_container *c, char *tpath, + */ + char *src; + +- src = ovl_get_rootfs(bdev->src, &(size_t){0}); ++ src = ovl_get_rootfs(bdev->src, &(size_t) { ++ 0 ++ }); + if (!src) { + ERROR("Failed to get rootfs"); + _exit(EXIT_FAILURE); +@@ -1654,8 +1656,8 @@ static bool create_run_template(struct lxc_container *c, char *tpath, + _exit(EXIT_FAILURE); + + ret = snprintf(n2[n2args - 1], 200, "%c:%lu:%lu:%lu", +- map->idtype == ID_TYPE_UID ? 'u' : 'g', +- map->nsid, map->hostid, map->range); ++ map->idtype == ID_TYPE_UID ? 'u' : 'g', ++ map->nsid, map->hostid, map->range); + if (ret < 0 || ret >= 200) + _exit(EXIT_FAILURE); + } +@@ -1682,7 +1684,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath, + } + + ret = snprintf(n2[n2args - 1], 200, "u:%d:%d:1", +- hostuid_mapped, geteuid()); ++ hostuid_mapped, geteuid()); + if (ret < 0 || ret >= 200) + _exit(EXIT_FAILURE); + } +@@ -1709,7 +1711,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath, + } + + ret = snprintf(n2[n2args - 1], 200, "g:%d:%d:1", +- hostgid_mapped, getegid()); ++ hostgid_mapped, getegid()); + if (ret < 0 || ret >= 200) + _exit(EXIT_FAILURE); + } +@@ -1915,8 +1917,8 @@ static void lxcapi_clear_config(struct lxc_container *c) + * arguments, you can just pass NULL. + */ + static bool do_lxcapi_create(struct lxc_container *c, const char *t, +- const char *bdevtype, struct bdev_specs *specs, +- int flags, char *const argv[]) ++ const char *bdevtype, struct bdev_specs *specs, ++ int flags, char *const argv[]) + { + int partial_fd; + mode_t mask; +@@ -1940,7 +1942,7 @@ static bool do_lxcapi_create(struct lxc_container *c, const char *t, + * existing container. Return an error, but do NOT delete the container. + */ + if (do_lxcapi_is_defined(c) && c->lxc_conf && c->lxc_conf->rootfs.path && +- access(c->lxc_conf->rootfs.path, F_OK) == 0 && tpath) { ++ access(c->lxc_conf->rootfs.path, F_OK) == 0 && tpath) { + ERROR("Container \"%s\" already exists in \"%s\"", c->name, + c->config_path); + goto free_tpath; +@@ -2072,8 +2074,8 @@ free_tpath: + } + + static bool lxcapi_create(struct lxc_container *c, const char *t, +- const char *bdevtype, struct bdev_specs *specs, +- int flags, char *const argv[]) ++ const char *bdevtype, struct bdev_specs *specs, ++ int flags, char *const argv[]) + { + bool ret; + +@@ -2140,7 +2142,7 @@ static bool do_lxcapi_reboot2(struct lxc_container *c, int timeout) + if (timeout != 0) { + states[RUNNING] = 2; + ret = lxc_cmd_add_state_client(c->name, c->config_path, states, +- &state_client_fd); ++ &state_client_fd); + if (ret < 0) + return false; + +@@ -2209,7 +2211,7 @@ static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout) + if (timeout != 0) { + states[STOPPED] = 1; + ret = lxc_cmd_add_state_client(c->name, c->config_path, states, +- &state_client_fd); ++ &state_client_fd); + if (ret < 0) + return false; + +@@ -2252,7 +2254,7 @@ static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout) + WRAP_API_1(bool, lxcapi_shutdown, int) + + static bool lxcapi_createl(struct lxc_container *c, const char *t, +- const char *bdevtype, struct bdev_specs *specs, int flags, ...) ++ const char *bdevtype, struct bdev_specs *specs, int flags, ...) + { + bool bret = false; + char **args = NULL; +@@ -2300,7 +2302,9 @@ static void do_clear_unexp_config_line(struct lxc_conf *conf, const char *key) + const char *idx; + + idx = key + 8; +- ret = lxc_safe_uint(idx, &(unsigned int){0}); ++ ret = lxc_safe_uint(idx, &(unsigned int) { ++ 0 ++ }); + if (!ret) + return clear_unexp_config_line(conf, key, true); + } +@@ -2312,7 +2316,7 @@ static void do_clear_unexp_config_line(struct lxc_conf *conf, const char *key) + } + + static bool do_lxcapi_clear_config_item(struct lxc_container *c, +- const char *key) ++ const char *key) + { + int ret = 1; + struct lxc_config_t *config; +@@ -2344,7 +2348,7 @@ static inline bool enter_net_ns(struct lxc_container *c) + pid_t pid = do_lxcapi_init_pid(c); + + if ((geteuid() != 0 || (c->lxc_conf && !lxc_list_empty(&c->lxc_conf->id_map))) && +- (access("/proc/self/ns/user", F_OK) == 0)) ++ (access("/proc/self/ns/user", F_OK) == 0)) + if (!switch_to_ns(pid, "user")) + return false; + +@@ -2359,7 +2363,7 @@ static inline int string_cmp(char **first, char **second) + + /* Used by qsort and bsearch functions for comparing container names. */ + static inline int container_cmp(struct lxc_container **first, +- struct lxc_container **second) ++ struct lxc_container **second) + { + return strcmp((*first)->name, (*second)->name); + } +@@ -2385,7 +2389,7 @@ static bool add_to_array(char ***names, char *cname, int pos) + } + + static bool add_to_clist(struct lxc_container ***list, struct lxc_container *c, +- int pos, bool sort) ++ int pos, bool sort) + { + struct lxc_container **newlist = realloc(*list, (pos + 1) * sizeof(struct lxc_container *)); + if (!newlist) { +@@ -2459,14 +2463,16 @@ static char **do_lxcapi_get_interfaces(struct lxc_container *c) + } + + /* Grab the list of interfaces */ +- if (netns_getifaddrs(&interfaceArray, -1, &(bool){false})) { ++ if (netns_getifaddrs(&interfaceArray, -1, &(bool) { ++ false ++ })) { + SYSERROR("Failed to get interfaces list"); + goto out; + } + + /* Iterate through the interfaces */ + for (tempIfAddr = interfaceArray; tempIfAddr != NULL; +- tempIfAddr = tempIfAddr->ifa_next) { ++ tempIfAddr = tempIfAddr->ifa_next) { + nbytes = lxc_write_nointr(pipefd[1], tempIfAddr->ifa_name, IFNAMSIZ); + if (nbytes < 0) + goto out; +@@ -2476,7 +2482,7 @@ static char **do_lxcapi_get_interfaces(struct lxc_container *c) + + ret = 0; + +- out: ++out: + if (interfaceArray) + netns_freeifaddrs(interfaceArray); + +@@ -2521,7 +2527,7 @@ static char **do_lxcapi_get_interfaces(struct lxc_container *c) + WRAP_API(char **, lxcapi_get_interfaces) + + static char **do_lxcapi_get_ips(struct lxc_container *c, const char *interface, +- const char *family, int scope) ++ const char *family, int scope) + { + int i, ret; + pid_t pid; +@@ -2561,14 +2567,16 @@ static char **do_lxcapi_get_ips(struct lxc_container *c, const char *interface, + } + + /* Grab the list of interfaces */ +- if (netns_getifaddrs(&interfaceArray, -1, &(bool){false})) { ++ if (netns_getifaddrs(&interfaceArray, -1, &(bool) { ++ false ++ })) { + SYSERROR("Failed to get interfaces list"); + goto out; + } + + /* Iterate through the interfaces */ + for (tempIfAddr = interfaceArray; tempIfAddr; +- tempIfAddr = tempIfAddr->ifa_next) { ++ tempIfAddr = tempIfAddr->ifa_next) { + if (tempIfAddr->ifa_addr == NULL) + continue; + +@@ -2598,15 +2606,15 @@ static char **do_lxcapi_get_ips(struct lxc_container *c, const char *interface, + continue; + + address = (char *)inet_ntop(tempIfAddr->ifa_addr->sa_family, +- tempAddrPtr, addressOutputBuffer, +- sizeof(addressOutputBuffer)); ++ tempAddrPtr, addressOutputBuffer, ++ sizeof(addressOutputBuffer)); + if (!address) + continue; + + nbytes = lxc_write_nointr(pipefd[1], address, INET6_ADDRSTRLEN); + if (nbytes != INET6_ADDRSTRLEN) { + SYSERROR("Failed to send ipv6 address \"%s\"", +- address); ++ address); + goto out; + } + +@@ -2615,7 +2623,7 @@ static char **do_lxcapi_get_ips(struct lxc_container *c, const char *interface, + + ret = 0; + +- out: ++out: + if (interfaceArray) + netns_freeifaddrs(interfaceArray); + +@@ -2766,7 +2774,7 @@ static bool do_lxcapi_save_config(struct lxc_container *c, const char *alt_file) + return false; + + fd = open(alt_file, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, +- S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); ++ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + if (fd < 0) + goto on_error; + +@@ -2926,7 +2934,7 @@ void mod_all_rdeps(struct lxc_container *c, bool inc) + int ret; + + ret = snprintf(path, PATH_MAX, "%s/%s/lxc_rdepends", +- c->config_path, c->name); ++ c->config_path, c->name); + if (ret < 0 || ret >= PATH_MAX) { + ERROR("Path name too long"); + return; +@@ -2947,13 +2955,13 @@ void mod_all_rdeps(struct lxc_container *c, bool inc) + + if ((p = lxc_container_new(lxcname, lxcpath)) == NULL) { + ERROR("Unable to find dependent container %s:%s", +- lxcpath, lxcname); ++ lxcpath, lxcname); + continue; + } + + if (!mod_rdep(p, c, inc)) + ERROR("Failed to update snapshots file for %s:%s", +- lxcpath, lxcname); ++ lxcpath, lxcname); + + lxc_container_put(p); + } +@@ -2973,7 +2981,7 @@ static bool has_fs_snapshots(struct lxc_container *c) + bool bret = false; + + ret = snprintf(path, PATH_MAX, "%s/%s/lxc_snapshots", c->config_path, +- c->name); ++ c->name); + if (ret < 0 || ret > PATH_MAX) + goto out; + +@@ -3033,7 +3041,7 @@ static bool do_destroy_container(struct lxc_conf *conf) { + + if (am_guest_unpriv()) { + ret = userns_exec_full(conf, storage_destroy_wrapper, conf, +- "storage_destroy_wrapper"); ++ "storage_destroy_wrapper"); + if (ret < 0) + return false; + +@@ -3056,7 +3064,7 @@ static int lxc_unlink_exec_wrapper(void *data) + } + + static bool container_destroy(struct lxc_container *c, +- struct lxc_storage *storage) ++ struct lxc_storage *storage) + { + const char *p1; + size_t len; +@@ -3154,15 +3162,15 @@ static bool container_destroy(struct lxc_container *c, + * cannot be removed when restoring from a snapshot. + */ + if (storage && (!strcmp(storage->type, "overlay") || +- !strcmp(storage->type, "overlayfs")) && +- (storage->flags & LXC_STORAGE_INTERNAL_OVERLAY_RESTORE)) { ++ !strcmp(storage->type, "overlayfs")) && ++ (storage->flags & LXC_STORAGE_INTERNAL_OVERLAY_RESTORE)) { + ret = snprintf(path, len, "%s/%s/config", p1, c->name); + if (ret < 0 || (size_t)ret >= len) + goto out; + + if (am_guest_unpriv()) + ret = userns_exec_1(conf, lxc_unlink_exec_wrapper, path, +- "lxc_unlink_exec_wrapper"); ++ "lxc_unlink_exec_wrapper"); + else + ret = unlink(path); + if (ret < 0) { +@@ -3182,7 +3190,7 @@ static bool container_destroy(struct lxc_container *c, + + if (am_guest_unpriv()) + ret = userns_exec_full(conf, lxc_rmdir_onedev_wrapper, path, +- "lxc_rmdir_onedev_wrapper"); ++ "lxc_rmdir_onedev_wrapper"); + else + ret = lxc_rmdir_onedev(path, "snaps"); + if (ret < 0) { +@@ -3245,7 +3253,7 @@ static bool do_lxcapi_destroy_with_snapshots(struct lxc_container *c) + WRAP_API(bool, lxcapi_destroy_with_snapshots) + + int lxc_set_config_item_locked(struct lxc_conf *conf, const char *key, +- const char *v) ++ const char *v) + { + int ret; + struct lxc_config_t *config; +@@ -3270,7 +3278,7 @@ int lxc_set_config_item_locked(struct lxc_conf *conf, const char *key, + } + + static bool do_set_config_item_locked(struct lxc_container *c, const char *key, +- const char *v) ++ const char *v) + { + int ret; + +@@ -3360,7 +3368,7 @@ static bool set_config_filename(struct lxc_container *c) + static bool set_oci_hook_config_filename(struct lxc_container *c) + { + #define OCI_HOOK_JSON_FILE_NAME "ocihooks.json" +- char *newpath; ++ char *newpath = NULL; + int len, ret; + + if (!c->config_path) +@@ -3466,7 +3474,7 @@ static int do_lxcapi_get_cgroup_item(struct lxc_container *c, const char *subsys + return -1; + + ret = cgroup_ops->get(cgroup_ops, subsys, retv, inlen, c->name, +- c->config_path); ++ c->config_path); + + cgroup_exit(cgroup_ops); + +@@ -3578,7 +3586,7 @@ static int copyhooks(struct lxc_container *oldc, struct lxc_container *c) + + /* copy the script, and change the entry in confile */ + ret = snprintf(tmppath, PATH_MAX, "%s/%s/%s", +- c->config_path, c->name, fname+1); ++ c->config_path, c->name, fname+1); + if (ret < 0 || ret >= PATH_MAX) + return -1; + +@@ -3597,7 +3605,7 @@ static int copyhooks(struct lxc_container *oldc, struct lxc_container *c) + } + + if (!clone_update_unexp_hooks(c->lxc_conf, oldc->config_path, +- c->config_path, oldc->name, c->name)) { ++ c->config_path, oldc->name, c->name)) { + ERROR("Error saving new hooks in clone"); + return -1; + } +@@ -3623,7 +3631,7 @@ static int copy_fstab(struct lxc_container *oldc, struct lxc_container *c) + return -1; + + ret = snprintf(newpath, PATH_MAX, "%s/%s%s", +- c->config_path, c->name, p); ++ c->config_path, c->name, p); + if (ret < 0 || ret >= PATH_MAX) { + ERROR("error printing new path for %s", oldpath); + return -1; +@@ -3661,14 +3669,14 @@ static void copy_rdepends(struct lxc_container *c, struct lxc_container *c0) + int ret; + + ret = snprintf(path0, PATH_MAX, "%s/%s/lxc_rdepends", c0->config_path, +- c0->name); ++ c0->name); + if (ret < 0 || ret >= PATH_MAX) { + WARN("Error copying reverse dependencies"); + return; + } + + ret = snprintf(path1, PATH_MAX, "%s/%s/lxc_rdepends", c->config_path, +- c->name); ++ c->name); + if (ret < 0 || ret >= PATH_MAX) { + WARN("Error copying reverse dependencies"); + return; +@@ -3688,7 +3696,7 @@ static bool add_rdepends(struct lxc_container *c, struct lxc_container *c0) + bool bret; + + ret = snprintf(path, PATH_MAX, "%s/%s/lxc_rdepends", c->config_path, +- c->name); ++ c->name); + if (ret < 0 || ret >= PATH_MAX) + return false; + +@@ -3714,7 +3722,7 @@ static bool add_rdepends(struct lxc_container *c, struct lxc_container *c0) + * Currently we only do this for btrfs. + */ + bool should_default_to_snapshot(struct lxc_container *c0, +- struct lxc_container *c1) ++ struct lxc_container *c1) + { + int ret; + size_t l0 = strlen(c0->config_path) + strlen(c0->name) + 2; +@@ -3741,8 +3749,8 @@ bool should_default_to_snapshot(struct lxc_container *c0, + } + + static int copy_storage(struct lxc_container *c0, struct lxc_container *c, +- const char *newtype, int flags, const char *bdevdata, +- uint64_t newsize) ++ const char *newtype, int flags, const char *bdevdata, ++ uint64_t newsize) + { + struct lxc_storage *bdev; + bool need_rdep; +@@ -3751,7 +3759,7 @@ static int copy_storage(struct lxc_container *c0, struct lxc_container *c, + flags |= LXC_CLONE_SNAPSHOT; + + bdev = storage_copy(c0, c->name, c->config_path, newtype, flags, +- bdevdata, newsize, &need_rdep); ++ bdevdata, newsize, &need_rdep); + if (!bdev) { + ERROR("Error copying storage."); + return -1; +@@ -3770,7 +3778,7 @@ static int copy_storage(struct lxc_container *c0, struct lxc_container *c, + /* Append a new lxc.rootfs.path entry to the unexpanded config. */ + clear_unexp_config_line(c->lxc_conf, "lxc.rootfs.path", false); + if (!do_append_unexp_config_line(c->lxc_conf, "lxc.rootfs.path", +- c->lxc_conf->rootfs.path)) { ++ c->lxc_conf->rootfs.path)) { + ERROR("Error saving new rootfs to cloned config."); + return -1; + } +@@ -3940,9 +3948,9 @@ static int create_file_dirname(char *path, struct lxc_conf *conf) + } + + static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char *newname, +- const char *lxcpath, int flags, +- const char *bdevtype, const char *bdevdata, uint64_t newsize, +- char **hookargs) ++ const char *lxcpath, int flags, ++ const char *bdevtype, const char *bdevdata, uint64_t newsize, ++ char **hookargs) + { + char newpath[PATH_MAX]; + int fd, ret; +@@ -3995,7 +4003,7 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char + } + + fd = open(newpath, O_WRONLY | O_CREAT | O_CLOEXEC, +- S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); ++ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + if (fd < 0) { + SYSERROR("Failed to open \"%s\"", newpath); + goto out; +@@ -4033,7 +4041,7 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char + * snapshot. + */ + if (errno != ENOENT && +- !(flags & LXC_STORAGE_INTERNAL_OVERLAY_RESTORE)) { ++ !(flags & LXC_STORAGE_INTERNAL_OVERLAY_RESTORE)) { + SYSERROR("Failed to create directory \"%s\"", newpath); + goto out; + } +@@ -4049,7 +4057,7 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char + c2 = lxc_container_new(newname, lxcpath); + if (!c2) { + ERROR("clone: failed to create new container (%s %s)", newname, +- lxcpath); ++ lxcpath); + goto out; + } + +@@ -4122,7 +4130,7 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char + + if (am_guest_unpriv()) + ret = userns_exec_full(c->lxc_conf, clone_update_rootfs_wrapper, +- &data, "clone_update_rootfs_wrapper"); ++ &data, "clone_update_rootfs_wrapper"); + else + ret = clone_update_rootfs(&data); + if (ret < 0) +@@ -4145,9 +4153,9 @@ out: + } + + static struct lxc_container *lxcapi_clone(struct lxc_container *c, const char *newname, +- const char *lxcpath, int flags, +- const char *bdevtype, const char *bdevdata, uint64_t newsize, +- char **hookargs) ++ const char *lxcpath, int flags, ++ const char *bdevtype, const char *bdevdata, uint64_t newsize, ++ char **hookargs) + { + struct lxc_container * ret; + +@@ -4331,7 +4339,7 @@ static int do_lxcapi_snapshot(struct lxc_container *c, const char *commentfile) + * created in the original container + */ + flags = LXC_CLONE_SNAPSHOT | LXC_CLONE_KEEPMACADDR | LXC_CLONE_KEEPNAME | +- LXC_CLONE_KEEPBDEVTYPE | LXC_CLONE_MAYBE_SNAPSHOT; ++ LXC_CLONE_KEEPBDEVTYPE | LXC_CLONE_MAYBE_SNAPSHOT; + if (storage_is_dir(c->lxc_conf)) { + ERROR("Snapshot of directory-backed container requested"); + ERROR("Making a copy-clone. If you do want snapshots, then"); +@@ -4601,7 +4609,7 @@ static bool do_lxcapi_snapshot_restore(struct lxc_container *c, const char *snap + flags |= LXC_STORAGE_INTERNAL_OVERLAY_RESTORE; + + rest = lxcapi_clone(snap, newname, c->config_path, flags, bdev->type, +- NULL, 0, NULL); ++ NULL, 0, NULL); + storage_put(bdev); + if (rest && lxcapi_is_defined(rest)) + b = true; +@@ -4714,7 +4722,7 @@ static bool do_lxcapi_may_control(struct lxc_container *c) + WRAP_API(bool, lxcapi_may_control) + + static bool do_add_remove_node(pid_t init_pid, const char *path, bool add, +- struct stat *st) ++ struct stat *st) + { + int ret; + char *tmp; +@@ -4865,8 +4873,8 @@ static bool do_lxcapi_remove_device_node(struct lxc_container *c, const char *sr + WRAP_API_2(bool, lxcapi_remove_device_node, const char *, const char *) + + static bool do_lxcapi_attach_interface(struct lxc_container *c, +- const char *ifname, +- const char *dst_ifname) ++ const char *ifname, ++ const char *dst_ifname) + { + pid_t init_pid; + int ret = 0; +@@ -4904,8 +4912,8 @@ err: + WRAP_API_2(bool, lxcapi_attach_interface, const char *, const char *) + + static bool do_lxcapi_detach_interface(struct lxc_container *c, +- const char *ifname, +- const char *dst_ifname) ++ const char *ifname, ++ const char *dst_ifname) + { + int ret; + pid_t pid, pid_outside; +@@ -4980,7 +4988,7 @@ static bool do_lxcapi_detach_interface(struct lxc_container *c, + WRAP_API_2(bool, lxcapi_detach_interface, const char *, const char *) + + static int do_lxcapi_migrate(struct lxc_container *c, unsigned int cmd, +- struct migrate_opts *opts, unsigned int size) ++ struct migrate_opts *opts, unsigned int size) + { + int ret = -1; + struct migrate_opts *valid_opts = opts; +@@ -5125,7 +5133,7 @@ out: + /* isulad add set console fifos*/ + static bool do_lxcapi_set_terminal_default_fifos(struct lxc_container *c, const char *in, const char *out, const char *err) + { +- struct lxc_conf *conf; ++ struct lxc_conf *conf = NULL; + + if (!c || !c->lxc_conf) + return false; +@@ -5160,7 +5168,7 @@ WRAP_API_3(bool, lxcapi_set_terminal_default_fifos, const char *, const char *, + /* isulad add set info file path */ + static bool do_lxcapi_set_container_info_file(struct lxc_container *c, const char *info_file) + { +- struct lxc_conf *conf; ++ struct lxc_conf *conf = NULL; + + if (!c || !c->lxc_conf || !info_file) + return false; +@@ -5263,16 +5271,16 @@ static int set_start_extral_configs(struct lxc_container *c) + struct lxc_conf *lconf = c->lxc_conf; + size_t i = 0; + +- if (lconf == NULL) { +- c->lxc_conf = malloc(sizeof(struct lxc_conf)); +- lconf = c->lxc_conf; +- if (lconf == NULL) { +- fprintf(stderr, "Out of memory\n"); +- return -1; +- } +- } ++ if (lconf == NULL) { ++ c->lxc_conf = malloc(sizeof(struct lxc_conf)); ++ lconf = c->lxc_conf; ++ if (lconf == NULL) { ++ fprintf(stderr, "Out of memory\n"); ++ return -1; ++ } ++ } + if (sprintf(fpath, "%s/%s/%s", c->config_path, c->name, START_GENERATE_CONFIG) < 0) { +- fprintf(stderr, "Sprintf config path failed\n"); ++ fprintf(stderr, "Sprintf config path failed\n"); + return -1; + } + if (!file_exists(fpath)) { +@@ -5290,9 +5298,10 @@ static int set_start_extral_configs(struct lxc_container *c) + lconf->init_gid = start_conf->gid; + } + if (start_conf->additional_gids != NULL && start_conf->additional_gids_len > 0) { +- gid_t *tmp; +- tmp = realloc(lconf->init_groups, (lconf->init_groups_len + start_conf->additional_gids_len) * sizeof(gid_t)); +- if (tmp == NULL) { ++ gid_t *tmp = NULL; ++ ret = lxc_mem_realloc((void **)&tmp, (lconf->init_groups_len + start_conf->additional_gids_len) * sizeof(gid_t), ++ lconf->init_groups, (lconf->init_groups_len) * sizeof(gid_t)); ++ if (ret != 0) { + fprintf(stderr, "Out of memory"); + goto out; + } +@@ -5314,8 +5323,9 @@ out: + + static struct lxc_container *do_lxc_container_new(const char *name, const char *configpath, bool load_config) + { +- struct lxc_container *c; ++ struct lxc_container *c = NULL; + size_t len; ++ const char *tmp = NULL; + + if (!name) + return NULL; +@@ -5327,10 +5337,17 @@ static struct lxc_container *do_lxc_container_new(const char *name, const char * + } + memset(c, 0, sizeof(*c)); + +- if (configpath) ++ if (configpath) { + c->config_path = strdup(configpath); +- else +- c->config_path = strdup(lxc_global_config_value("lxc.lxcpath")); ++ } ++ else { ++ tmp = lxc_global_config_value("lxc.lxcpath"); ++ if (tmp == NULL) { ++ fprintf(stderr, "Failed to get lxc path for %s\n", name); ++ goto err; ++ } ++ c->config_path = strdup(tmp); ++ } + if (!c->config_path) { + fprintf(stderr, "Failed to allocate memory for %s\n", name); + goto err; +@@ -5534,7 +5551,7 @@ int list_defined_containers(const char *lxcpath, char ***names, struct lxc_conta + c = lxc_container_new(direntp->d_name, lxcpath); + if (!c) { + INFO("Container %s:%s has a config but could not be loaded", +- lxcpath, direntp->d_name); ++ lxcpath, direntp->d_name); + + if (names) + if(!remove_from_array(names, direntp->d_name, cfound--)) +@@ -5545,7 +5562,7 @@ int list_defined_containers(const char *lxcpath, char ***names, struct lxc_conta + + if (!do_lxcapi_is_defined(c)) { + INFO("Container %s:%s has a config but is not defined", +- lxcpath, direntp->d_name); ++ lxcpath, direntp->d_name); + + if (names) + if(!remove_from_array(names, direntp->d_name, cfound--)) +@@ -5584,7 +5601,7 @@ free_bad: + } + + int list_active_containers(const char *lxcpath, char ***nret, +- struct lxc_container ***cret) ++ struct lxc_container ***cret) + { + int i, ret = -1, cret_cnt = 0, ct_name_cnt = 0; + int lxcpath_len; +@@ -5680,7 +5697,7 @@ int list_active_containers(const char *lxcpath, char ***nret, + c = lxc_container_new(p, lxcpath); + if (!c) { + INFO("Container %s:%s is running but could not be loaded", +- lxcpath, p); ++ lxcpath, p); + + remove_from_array(&ct_name, p, ct_name_cnt--); + if (is_hashed) +@@ -5741,7 +5758,7 @@ out: + } + + int list_all_containers(const char *lxcpath, char ***nret, +- struct lxc_container ***cret) ++ struct lxc_container ***cret) + { + int i, ret, active_cnt, ct_cnt, ct_list_cnt; + char **active_name; +diff --git a/src/lxc/mainloop.c b/src/lxc/mainloop.c +index 9603d1e..a127a13 100644 +--- a/src/lxc/mainloop.c ++++ b/src/lxc/mainloop.c +@@ -65,7 +65,7 @@ int lxc_mainloop(struct lxc_epoll_descr *descr, int timeout_ms) + * mainloop. + */ + ret = handler->callback(handler->fd, events[i].events, +- handler->data, descr); ++ handler->data, descr); + if (ret == LXC_MAINLOOP_CLOSE) + return 0; + } +@@ -79,11 +79,11 @@ int lxc_mainloop(struct lxc_epoll_descr *descr, int timeout_ms) + } + + int lxc_mainloop_add_handler(struct lxc_epoll_descr *descr, int fd, +- lxc_mainloop_callback_t callback, void *data) ++ lxc_mainloop_callback_t callback, void *data) + { + struct epoll_event ev; +- struct mainloop_handler *handler; +- struct lxc_list *item; ++ struct mainloop_handler *handler = NULL; ++ struct lxc_list *item = NULL; + + if (fd < 0) + return 0; +diff --git a/src/lxc/path.c b/src/lxc/path.c +index e917dcb..45ab4c3 100644 +--- a/src/lxc/path.c ++++ b/src/lxc/path.c +@@ -10,6 +10,7 @@ + + #include "path.h" + #include "log.h" ++#include "utils.h" + + lxc_log_define(lxc_path_ui, lxc); + +@@ -29,6 +30,10 @@ bool specify_current_dir(const char *path) + } + + bname = basename(basec); ++ if (bname == NULL) { ++ ERROR("Out of memory"); ++ return false; ++ } + res = !strcmp(bname, "."); + free(basec); + return res; +@@ -45,11 +50,15 @@ bool has_traling_path_separator(const char *path) + // path already ends in a `.` path segment, then another is not added. If the + // clean path already ends in a path separator, then another is not added. + char *preserve_trailing_dot_or_separator(const char *cleanedpath, +- const char *originalpath) ++ const char *originalpath) + { + char *respath = NULL; + size_t len; + ++ if (strlen(cleanedpath) > (SIZE_MAX - 3)) { ++ return NULL; ++ } ++ + len = strlen(cleanedpath) + 3; + respath = malloc(len); + if (!respath) { +@@ -66,7 +75,7 @@ char *preserve_trailing_dot_or_separator(const char *cleanedpath, + } + + if (!has_traling_path_separator(respath) && +- has_traling_path_separator(originalpath)) ++ has_traling_path_separator(originalpath)) + strcat(respath, "/"); + + return respath; +@@ -107,160 +116,373 @@ bool filepath_split(const char *path, char **dir, char **base) + return true; + } + +-/* +- * cleanpath is similar to realpath of glibc, but not expands symbolic links, +- * and not check the existence of components of the path. +- */ +-char *cleanpath(const char *path, char *resolved) ++ ++static bool do_clean_path_continue(const char *endpos, const char *stpos, const char *respath, char **dst) + { +- char *rpath, *dest; +- const char *start, *end, *rpath_limit; ++ if (endpos - stpos == 1 && stpos[0] == '.') { ++ return true; ++ } else if (endpos - stpos == 2 && stpos[0] == '.' && stpos[1] == '.') { ++ char *dest = *dst; ++ if (dest <= respath + 1) { ++ return true; ++ } ++ for (--dest; dest > respath && !ISSLASH(dest[-1]); --dest) { ++ *dst = dest; ++ return true; ++ } ++ *dst = dest; ++ return true; ++ } ++ return false; ++} + +- if (path == NULL || path[0] == '\0') +- return NULL; ++int do_clean_path(const char *respath, const char *limit_respath, ++ const char *stpos, char **dst) ++{ ++ char *dest = *dst; ++ const char *endpos = NULL; ++ errno_t ret; + +- if (resolved == NULL) { +- rpath = malloc(PATH_MAX); +- if (rpath == NULL) { +- ERROR("Out of memory"); +- return NULL; ++ for (endpos = stpos; *stpos; stpos = endpos) { ++ while (ISSLASH(*stpos)) { ++ ++stpos; + } +- } else { +- rpath = resolved; ++ ++ for (endpos = stpos; *endpos && !ISSLASH(*endpos); ++endpos) { ++ } ++ ++ if (endpos - stpos == 0) { ++ break; ++ } else if (do_clean_path_continue(endpos, stpos, respath, &dest)) { ++ continue; ++ } ++ ++ if (!ISSLASH(dest[-1])) { ++ *dest++ = '/'; ++ } ++ ++ if (dest + (endpos - stpos) >= limit_respath) { ++ ERROR("Path is too long"); ++ if (dest > respath + 1) { ++ dest--; ++ } ++ *dest = '\0'; ++ return -1; ++ } ++ ++ memcpy(dest, stpos, (size_t)(endpos - stpos)); ++ dest += endpos - stpos; ++ *dest = '\0'; + } +- rpath_limit = rpath + PATH_MAX; ++ *dst = dest; ++ return 0; ++} ++ ++char *cleanpath(const char *path, char *realpath, size_t realpath_len) ++{ ++ char *respath = NULL; ++ char *dest = NULL; ++ const char *stpos = NULL; ++ const char *limit_respath = NULL; ++ errno_t ret; ++ ++ if (path == NULL || path[0] == '\0' || \ ++ realpath == NULL || (realpath_len < PATH_MAX)) { ++ return NULL; ++ } ++ ++ respath = realpath; ++ ++ memset(respath, 0, realpath_len); ++ limit_respath = respath + PATH_MAX; + + if (!IS_ABSOLUTE_FILE_NAME(path)) { +- if (!getcwd(rpath, PATH_MAX)) { ++ if (!getcwd(respath, PATH_MAX)) { + ERROR("Failed to getcwd"); +- rpath[0] = '\0'; ++ respath[0] = '\0'; + goto error; + } +- dest = strchr(rpath, '\0'); +- start = path; ++ dest = strchr(respath, '\0'); ++ if (dest == NULL) { ++ ERROR("Failed to get the end of respath"); ++ goto error; ++ } ++ strcat(respath, path); ++ stpos = path; + } else { +- dest = rpath; ++ dest = respath; + *dest++ = '/'; +- start = path; ++ stpos = path; + } + +- for (end = start; *start; start = end) { +- /* Skip sequence of multiple path-separators. */ +- while (ISSLASH(*start)) +- ++start; ++ if (do_clean_path(respath, limit_respath, stpos, &dest)) { ++ goto error; ++ } + +- /* Find end of path component. */ +- for (end = start; *end && !ISSLASH(*end); ++end) +- /* Nothing. */; ++ if (dest > respath + 1 && ISSLASH(dest[-1])) { ++ --dest; ++ } ++ *dest = '\0'; + +- if (end - start == 0) { +- break; +- } else if (end - start == 1 && start[0] == '.') { +- /* nothing */; +- } else if (end - start == 2 && start[0] == '.' && start[1] == '.') { +- /* Back up to previous component, ignore if at root already. */ +- if (dest > rpath + 1) +- for (--dest; dest > rpath && !ISSLASH(dest[-1]); --dest) +- continue; +- } else { +- size_t new_size; +- +- if (!ISSLASH(dest[-1])) +- *dest++ = '/'; +- +- if (dest + (end - start) >= rpath_limit) { +- long long dest_offset = dest - rpath; +- char *new_rpath; +- +- if (resolved) { +- printf("Path is to long"); +- if (dest > rpath + 1) +- dest--; +- *dest = '\0'; +- goto error; +- } +- +- new_size = rpath_limit - rpath; +- if (end - start + 1 > PATH_MAX) +- new_size += end - start + 1; +- else +- new_size += PATH_MAX; +- new_rpath = (char *) realloc(rpath, new_size); +- if (new_rpath == NULL) { +- ERROR("Out of memory"); +- goto error; +- } +- rpath = new_rpath; +- rpath_limit = rpath + new_size; +- +- dest = rpath + dest_offset; ++ return respath; ++ ++error: ++ return NULL; ++} ++ ++static int do_path_realloc(const char *start, const char *end, ++ char **rpath, char **dest, const char **rpath_limit) ++{ ++ long long dest_offset = *dest - *rpath; ++ char *new_rpath = NULL; ++ size_t new_size; ++ int nret = 0; ++ size_t gap = 0; ++ ++ if (*dest + (end - start) < *rpath_limit) { ++ return 0; ++ } ++ ++ gap = (size_t)(end - start) + 1; ++ new_size = (size_t)(*rpath_limit - *rpath); ++ if (new_size > SIZE_MAX - gap) { ++ ERROR("Out of range!"); ++ return -1; ++ } ++ ++ if (gap > PATH_MAX) { ++ new_size += gap; ++ } else { ++ new_size += PATH_MAX; ++ } ++ nret = lxc_mem_realloc((void **)&new_rpath, new_size, *rpath, PATH_MAX); ++ if (nret) { ++ ERROR("Failed to realloc memory for files limit variables"); ++ return -1; ++ } ++ *rpath = new_rpath; ++ *rpath_limit = *rpath + new_size; ++ ++ *dest = *rpath + dest_offset; ++ ++ return 0; ++} ++ ++static int do_get_symlinks_copy_buf(const char *buf, const char *prefix, size_t prefix_len, ++ char **rpath, char **dest) ++{ ++ if (IS_ABSOLUTE_FILE_NAME(buf)) { ++ if (prefix_len) { ++ memcpy(*rpath, prefix, prefix_len); ++ } ++ *dest = *rpath + prefix_len; ++ *(*dest)++ = '/'; ++ } else { ++ if (*dest > *rpath + prefix_len + 1) { ++ for (--(*dest); *dest > *rpath && !ISSLASH((*dest)[-1]); --(*dest)) { ++ continue; + } ++ } ++ } ++ return 0; ++} + +- memcpy(dest, start, end - start); +- dest += end - start; +- *dest = '\0'; ++static int do_get_symlinks(const char **fullpath, const char *prefix, size_t prefix_len, ++ char **rpath, char **dest, const char **end, ++ int *num_links, char **extra_buf) ++{ ++ char *buf = NULL; ++ size_t len; ++ errno_t rc = EOK; ++ ssize_t n; ++ int ret = -1; ++ ++ if (++(*num_links) > MAXSYMLINKS) { ++ ERROR("Too many links in '%s'", *fullpath); ++ goto out; ++ } ++ ++ buf = lxc_common_calloc_s(PATH_MAX); ++ if (buf == NULL) { ++ ERROR("Out of memory"); ++ goto out; ++ } ++ ++ n = readlink(*rpath, buf, PATH_MAX - 1); ++ if (n < 0) { ++ goto out; ++ } ++ buf[n] = '\0'; ++ ++ if (*extra_buf == NULL) { ++ *extra_buf = lxc_common_calloc_s(PATH_MAX); ++ if (*extra_buf == NULL) { ++ ERROR("Out of memory"); ++ goto out; + } + } +- if (dest > rpath + 1 && ISSLASH(dest[-1])) +- --dest; +- *dest = '\0'; + +- return rpath; ++ len = strlen(*end); ++ if (len >= PATH_MAX - n) { ++ ERROR("Path is too long"); ++ goto out; ++ } + +-error: +- if (resolved == NULL) +- free(rpath); +- return NULL; ++ memmove(&(*extra_buf)[n], *end, len + 1); ++ memcpy(*extra_buf, buf, (size_t)n); ++ ++ *fullpath = *end = *extra_buf; ++ ++ if (do_get_symlinks_copy_buf(buf, prefix, prefix_len, rpath, dest) != 0) { ++ goto out; ++ } ++ ++ ret = 0; ++out: ++ free(buf); ++ return ret; + } + +-// evalSymlinksInScope will evaluate symlinks in `path` within a scope `root` and return +-// a result guaranteed to be contained within the scope `root`, at the time of the call. +-// Symlinks in `root` are not evaluated and left as-is. +-// Errors encountered while attempting to evaluate symlinks in path will be returned. +-// Non-existing paths are valid and do not constitute an error. +-// `path` has to contain `root` as a prefix, or else an error will be returned. +-// Trying to break out from `root` does not constitute an error. +-// +-// Example: +-// If /foo/bar -> /outside, +-// FollowSymlinkInScope("/foo/bar", "/foo") == "/foo/outside" instead of "/oustide" +-char *eval_symlinks_in_scope(const char *fullpath, const char *rootpath) ++static bool do_eval_symlinks_in_scope_is_symlink(const char *path) + { +- char resroot[PATH_MAX] = {0}, *root = NULL; +- char *rpath, *dest, *prefix, *extra_buf = NULL; +- const char *start, *end, *rpath_limit; ++ struct stat st; ++ ++ if (lstat(path, &st) < 0) { ++ return true; ++ } ++ ++ if (!S_ISLNK(st.st_mode)) { ++ return true; ++ } ++ return false; ++} ++ ++static void do_eval_symlinks_skip_slash(const char **start, const char **end) ++{ ++ while (ISSLASH(**start)) { ++ ++(*start); ++ } ++ ++ for (*end = *start; **end && !ISSLASH(**end); ++(*end)) { ++ } ++} ++ ++static inline void skip_dest_traling_slash(char **dest, char **rpath, size_t prefix_len) ++{ ++ if (*dest > *rpath + prefix_len + 1) { ++ for (--(*dest); *dest > *rpath && !ISSLASH((*dest)[-1]); --(*dest)) { ++ continue; ++ } ++ } ++} ++ ++static inline bool is_current_char(const char c) ++{ ++ return c == '.'; ++} ++ ++static inline bool is_specify_current(const char *end, const char *start) ++{ ++ return (end - start == 1) && is_current_char(start[0]); ++} ++ ++static inline bool is_specify_parent(const char *end, const char *start) ++{ ++ return (end - start == 2) && is_current_char(start[0]) && is_current_char(start[1]); ++} ++ ++static int do_eval_symlinks_in_scope(const char *fullpath, const char *prefix, ++ size_t prefix_len, ++ char **rpath, char **dest, const char *rpath_limit) ++{ ++ const char *start = NULL; ++ const char *end = NULL; ++ char *extra_buf = NULL; ++ errno_t rc = EOK; ++ int nret = 0; + int num_links = 0; ++ ++ start = fullpath + prefix_len; ++ for (end = start; *start; start = end) { ++ do_eval_symlinks_skip_slash(&start, &end); ++ if (end - start == 0) { ++ break; ++ } else if (is_specify_current(end, start)) { ++ ; ++ } else if (is_specify_parent(end, start)) { ++ skip_dest_traling_slash(dest, rpath, prefix_len); ++ } else { ++ if (!ISSLASH((*dest)[-1])) { ++ *(*dest)++ = '/'; ++ } ++ ++ nret = do_path_realloc(start, end, rpath, dest, &rpath_limit); ++ if (nret != 0) { ++ nret = -1; ++ goto out; ++ } ++ ++ memcpy(*dest, start, (size_t)(end - start)); ++ *dest += end - start; ++ **dest = '\0'; ++ ++ if (do_eval_symlinks_in_scope_is_symlink(*rpath)) { ++ continue; ++ } ++ ++ nret = do_get_symlinks(&fullpath, prefix, prefix_len, rpath, dest, &end, &num_links, &extra_buf); ++ if (nret != 0) { ++ nret = -1; ++ goto out; ++ } ++ } ++ } ++out: ++ free(extra_buf); ++ return nret; ++} ++static char *eval_symlinks_in_scope(const char *fullpath, const char *rootpath) ++{ ++ char resroot[PATH_MAX] = {0}; ++ char *root = NULL; ++ char *rpath = NULL; ++ char *dest = NULL; ++ char *prefix = NULL; ++ const char *rpath_limit = NULL; + size_t prefix_len; ++ errno_t rc = EOK; + +- if (!fullpath || !rootpath) ++ if (fullpath == NULL || rootpath == NULL) { + return NULL; ++ } + +- root = cleanpath(rootpath, resroot); +- if (!root) { ++ root = cleanpath(rootpath, resroot, sizeof(resroot)); ++ if (root == NULL) { + ERROR("Failed to get cleaned path"); + return NULL; + } + +- if (!strcmp(fullpath, root)) ++ if (!strcmp(fullpath, root)) { + return strdup(fullpath); ++ } + +- if (!strstr(fullpath, root)) { ++ if (strstr(fullpath, root) == NULL) { + ERROR("Path '%s' is not in '%s'", fullpath, root); + return NULL; + } + +- rpath = malloc(PATH_MAX); ++ rpath = lxc_common_calloc_s(PATH_MAX); + if (rpath == NULL) { + ERROR("Out of memory"); +- goto error; +- return NULL; ++ goto out; + } + rpath_limit = rpath + PATH_MAX; + + prefix = root; +- prefix_len = strlen(prefix); +- if (!strcmp(prefix, "/")) ++ prefix_len = (size_t)strlen(prefix); ++ if (!strcmp(prefix, "/")) { + prefix_len = 0; ++ } + + dest = rpath; + if (prefix_len) { +@@ -268,133 +490,19 @@ char *eval_symlinks_in_scope(const char *fullpath, const char *rootpath) + dest += prefix_len; + } + *dest++ = '/'; +- start = fullpath + prefix_len; + +- for (end = start; *start; start = end) { +- struct stat st; +- int n; +- +- /* Skip sequence of multiple path-separators. */ +- while (ISSLASH(*start)) +- ++start; +- +- /* Find end of path component. */ +- for (end = start; *end && !ISSLASH(*end); ++end) +- /* Nothing. */; +- +- if (end - start == 0) { +- break; +- } else if (end - start == 1 && start[0] == '.') { +- /* nothing */; +- } else if (end - start == 2 && start[0] == '.' && start[1] == '.') { +- /* Back up to previous component, ignore if at root already. */ +- if (dest > rpath + prefix_len + 1) +- for (--dest; dest > rpath && !ISSLASH(dest[-1]); --dest) +- continue; +- } else { +- size_t new_size; +- +- if (!ISSLASH(dest[-1])) +- *dest++ = '/'; +- +- if (dest + (end - start) >= rpath_limit) { +- long long dest_offset = dest - rpath; +- char *new_rpath; +- +- new_size = rpath_limit - rpath; +- if (end - start + 1 > PATH_MAX) +- new_size += end - start + 1; +- else +- new_size += PATH_MAX; +- new_rpath = (char *) realloc(rpath, new_size); +- if (new_rpath == NULL) { +- ERROR("Out of memory"); +- goto error; +- } +- rpath = new_rpath; +- rpath_limit = rpath + new_size; +- +- dest = rpath + dest_offset; +- } +- +- memcpy(dest, start, end - start); +- dest += end - start; +- *dest = '\0'; +- +- if (lstat(rpath, &st) < 0) { +- // if rpath does not exist, accept it +- continue; +- } +- +- if (S_ISLNK(st.st_mode)) { +- char *buf; +- size_t len; +- +- if (++num_links > MAXSYMLINKS) { +- ERROR("Too many links in '%s'", fullpath); +- goto error; +- } +- +- buf = malloc(PATH_MAX); +- if (!buf) { +- ERROR("Out of memory"); +- goto error; +- } +- +- n = readlink(rpath, buf, PATH_MAX - 1); +- if (n < 0) { +- free(buf); +- goto error; +- } +- buf[n] = '\0'; +- +- if (!extra_buf) { +- extra_buf = malloc(PATH_MAX); +- if (!extra_buf) { +- ERROR("Out of memory"); +- free(buf); +- goto error; +- } +- } +- +- len = strlen(end); +- if ((long int)(n + len) >= PATH_MAX) { +- free(buf); +- ERROR("Path is too long"); +- goto error; +- } +- +- /* Careful here, end may be a pointer into extra_buf... */ +- memmove(&extra_buf[n], end, len + 1); +- fullpath = end = memcpy(extra_buf, buf, n); +- +- if (IS_ABSOLUTE_FILE_NAME(buf)) { +- if (prefix_len) +- memcpy(rpath, prefix, prefix_len); +- dest = rpath + prefix_len; +- *dest++ = '/'; /* It's an absolute symlink */ +- } else { +- /* Back up to previous component, ignore if at root +- already: */ +- if (dest > rpath + prefix_len + 1) +- for (--dest; dest > rpath && !ISSLASH(dest[-1]); --dest) +- continue; +- } +- } +- } ++ if (do_eval_symlinks_in_scope(fullpath, prefix, prefix_len, &rpath, &dest, ++ rpath_limit)) { ++ goto out; + } +- if (dest > rpath + prefix_len + 1 && ISSLASH(dest[-1])) ++ ++ if (dest > rpath + prefix_len + 1 && ISSLASH(dest[-1])) { + --dest; ++ } + *dest = '\0'; +- +- if (extra_buf) +- free(extra_buf); +- + return rpath; + +-error: +- if (extra_buf) +- free(extra_buf); ++out: + free(rpath); + return NULL; + } +@@ -406,13 +514,13 @@ char *follow_symlink_in_scope(const char *fullpath, const char *rootpath) + char resfull[PATH_MAX] = {0}, *full = NULL; + char resroot[PATH_MAX] = {0}, *root = NULL; + +- full = cleanpath(fullpath, resfull); ++ full = cleanpath(fullpath, resfull, PATH_MAX); + if (!full) { + ERROR("Failed to get cleaned path"); + return NULL; + } + +- root = cleanpath(rootpath, resroot); ++ root = cleanpath(rootpath, resroot, PATH_MAX); + if (!root) { + ERROR("Failed to get cleaned path"); + return NULL; +@@ -430,7 +538,7 @@ char *follow_symlink_in_scope(const char *fullpath, const char *rootpath) + // particular path inside the container as though you were a process in that + // container. + int get_resource_path(const char *rootpath, const char *path, +- char **scopepath) ++ char **scopepath) + { + char resolved[PATH_MAX] = {0}, *cleanedpath = NULL; + char *fullpath = NULL; +@@ -441,7 +549,7 @@ int get_resource_path(const char *rootpath, const char *path, + + *scopepath = NULL; + +- cleanedpath = cleanpath(path, resolved); ++ cleanedpath = cleanpath(path, resolved, PATH_MAX); + if (!cleanedpath) { + ERROR("Failed to get cleaned path"); + return -1; +@@ -475,13 +583,13 @@ char *path_relative(const char *basepath, const char *targpath) + char restarg[PATH_MAX] = {0}, *targ = NULL; + size_t bl = 0, tl = 0, b0 = 0, bi = 0, t0 = 0, ti = 0; + +- base = cleanpath(basepath, resbase); ++ base = cleanpath(basepath, resbase, PATH_MAX); + if (!base) { + ERROR("Failed to get cleaned path"); + return NULL; + } + +- targ = cleanpath(targpath, restarg); ++ targ = cleanpath(targpath, restarg, PATH_MAX); + if (!targ) { + ERROR("Failed to get cleaned path"); + return NULL; +@@ -512,7 +620,7 @@ char *path_relative(const char *basepath, const char *targpath) + // Base elements left. Must go up before going down. + int seps = 0, i; + size_t ncopyed = 0, seps_size; +- char *buf; ++ char *buf = NULL; + + for (bi = b0; bi < bl; bi++) { + if (ISSLASH(base[bi])) +@@ -543,4 +651,4 @@ char *path_relative(const char *basepath, const char *targpath) + } + + return strdup(targ + t0); +-} +\ No newline at end of file ++} +diff --git a/src/lxc/path.h b/src/lxc/path.h +index e3a04cc..5100941 100644 +--- a/src/lxc/path.h ++++ b/src/lxc/path.h +@@ -13,7 +13,7 @@ bool has_traling_path_separator(const char *path); + // path already ends in a `.` path segment, then another is not added. If the + // clean path already ends in a path separator, then another is not added. + char *preserve_trailing_dot_or_separator(const char *cleanedpath, +- const char *originalpath); ++ const char *originalpath); + + + // Split splits path immediately following the final Separator, +@@ -27,20 +27,8 @@ bool filepath_split(const char *path, char **dir, char **base); + * cleanpath is similar to realpath of glibc, but not expands symbolic links, + * and not check the existence of components of the path. + */ +-char *cleanpath(const char *path, char *resolved); ++char *cleanpath(const char *path, char *realpath, size_t realpath_len); + +-// evalSymlinksInScope will evaluate symlinks in `path` within a scope `root` and return +-// a result guaranteed to be contained within the scope `root`, at the time of the call. +-// Symlinks in `root` are not evaluated and left as-is. +-// Errors encountered while attempting to evaluate symlinks in path will be returned. +-// Non-existing paths are valid and do not constitute an error. +-// `path` has to contain `root` as a prefix, or else an error will be returned. +-// Trying to break out from `root` does not constitute an error. +-// +-// Example: +-// If /foo/bar -> /outside, +-// FollowSymlinkInScope("/foo/bar", "/foo") == "/foo/outside" instead of "/oustide" +-char *eval_symlinks_in_scope(const char *fullpath, const char *rootpath); + + // FollowSymlinkInScope is a wrapper around evalSymlinksInScope that returns an + // absolute path. This function handles paths in a platform-agnostic manner. +@@ -55,7 +43,7 @@ char *follow_symlink_in_scope(const char *fullpath, const char *rootpath); + // particular path inside the container as though you were a process in that + // container. + int get_resource_path(const char *rootpath, const char *path, +- char **scopepath); ++ char **scopepath); + + // Rel returns a relative path that is lexically equivalent to targpath when + // joined to basepath with an intervening separator. That is, +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 4541793..ccdd844 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -93,7 +93,7 @@ extern void mod_all_rdeps(struct lxc_container *c, bool inc); + static bool do_destroy_container(struct lxc_handler *handler); + static int lxc_rmdir_onedev_wrapper(void *data); + static void lxc_destroy_container_on_signal(struct lxc_handler *handler, +- const char *name); ++ const char *name); + + /* isulad: start timeout thread */ + typedef enum { +@@ -136,8 +136,8 @@ static void print_top_failing_dir(const char *path) + ret = access(copy, X_OK); + if (ret != 0) { + SYSERROR("Could not access %s. Please grant it x " +- "access, or add an ACL for the container " +- "root", copy); ++ "access, or add an ACL for the container " ++ "root", copy); + return; + } + *p = saved; +@@ -180,7 +180,7 @@ static int lxc_try_preserve_ns(const int pid, const char *ns) + * Return true on success, false on failure. + */ + static bool lxc_try_preserve_namespaces(struct lxc_handler *handler, +- int ns_clone_flags, pid_t pid) ++ int ns_clone_flags, pid_t pid) + { + int i; + +@@ -243,8 +243,8 @@ static bool match_dlog_fds(struct dirent *direntp) + } + + if (strcmp(link, "/dev/log_main") == 0 || +- strcmp(link, "/dev/log_system") == 0 || +- strcmp(link, "/dev/log_radio") == 0) ++ strcmp(link, "/dev/log_system") == 0 || ++ strcmp(link, "/dev/log_radio") == 0) + return true; + + return false; +@@ -252,7 +252,7 @@ static bool match_dlog_fds(struct dirent *direntp) + #endif + + int lxc_check_inherited(struct lxc_conf *conf, bool closeall, +- int *fds_to_ignore, size_t len_fds) ++ int *fds_to_ignore, size_t len_fds) + { + int fd, fddir; + size_t i; +@@ -293,7 +293,7 @@ restart: + break; + + if (fd == fddir || fd == lxc_log_fd || +- (i < len_fds && fd == fds_to_ignore[i])) ++ (i < len_fds && fd == fds_to_ignore[i])) + continue; + + /* Keep state clients that wait on reboots. */ +@@ -377,7 +377,7 @@ static int setup_signal_fd(sigset_t *oldmask) + } + + static int signal_handler(int fd, uint32_t events, void *data, +- struct lxc_epoll_descr *descr) ++ struct lxc_epoll_descr *descr) + { + int ret; + siginfo_t info; +@@ -427,14 +427,14 @@ static int signal_handler(int fd, uint32_t events, void *data, + kill(hdlr->pid, SIGTERM); + INFO("Killing %d since terminal hung up", hdlr->pid); + return hdlr->init_died ? LXC_MAINLOOP_CLOSE +- : LXC_MAINLOOP_CONTINUE; ++ : LXC_MAINLOOP_CONTINUE; + } + + if (siginfo.ssi_signo != SIGCHLD) { + kill(hdlr->pid, siginfo.ssi_signo); + INFO("Forwarded signal %d to pid %d", siginfo.ssi_signo, hdlr->pid); + return hdlr->init_died ? LXC_MAINLOOP_CLOSE +- : LXC_MAINLOOP_CONTINUE; ++ : LXC_MAINLOOP_CONTINUE; + } + + /* More robustness, protect ourself from a SIGCHLD sent +@@ -444,19 +444,19 @@ static int signal_handler(int fd, uint32_t events, void *data, + NOTICE("Received %d from pid %d instead of container init %d", + siginfo.ssi_signo, siginfo.ssi_pid, hdlr->pid); + return hdlr->init_died ? LXC_MAINLOOP_CLOSE +- : LXC_MAINLOOP_CONTINUE; ++ : LXC_MAINLOOP_CONTINUE; + } + + if (siginfo.ssi_code == CLD_STOPPED) { + INFO("Container init process was stopped"); + return hdlr->init_died ? LXC_MAINLOOP_CLOSE +- : LXC_MAINLOOP_CONTINUE; ++ : LXC_MAINLOOP_CONTINUE; + } + + if (siginfo.ssi_code == CLD_CONTINUED) { + INFO("Container init process was continued"); + return hdlr->init_died ? LXC_MAINLOOP_CLOSE +- : LXC_MAINLOOP_CONTINUE; ++ : LXC_MAINLOOP_CONTINUE; + } + + DEBUG("Container init process %d exited", hdlr->pid); +@@ -465,7 +465,7 @@ static int signal_handler(int fd, uint32_t events, void *data, + } + + int lxc_serve_state_clients(const char *name, struct lxc_handler *handler, +- lxc_state_t state) ++ lxc_state_t state) + { + size_t retlen; + ssize_t ret; +@@ -516,14 +516,14 @@ int lxc_serve_state_clients(const char *name, struct lxc_handler *handler, + } + + static int lxc_serve_state_socket_pair(const char *name, +- struct lxc_handler *handler, +- lxc_state_t state) ++ struct lxc_handler *handler, ++ lxc_state_t state) + { + ssize_t ret; + + if (!handler->daemonize || +- handler->state_socket_pair[1] < 0 || +- state == STARTING) ++ handler->state_socket_pair[1] < 0 || ++ state == STARTING) + return 0; + + /* Close read end of the socket pair. */ +@@ -532,7 +532,9 @@ static int lxc_serve_state_socket_pair(const char *name, + + again: + ret = lxc_abstract_unix_send_credential(handler->state_socket_pair[1], +- &(int){state}, sizeof(int)); ++ &(int) { ++ state ++ }, sizeof(int)); + if (ret < 0) { + SYSERROR("Failed to send state to %d", handler->state_socket_pair[1]); + +@@ -558,7 +560,7 @@ again: + } + + int lxc_set_state(const char *name, struct lxc_handler *handler, +- lxc_state_t state) ++ lxc_state_t state) + { + int ret; + +@@ -587,7 +589,7 @@ int lxc_poll(const char *name, struct lxc_handler *handler) + struct lxc_epoll_descr descr, descr_console; + + if (handler->conf->console.path && +- strcmp(handler->conf->console.path, "none") == 0) ++ strcmp(handler->conf->console.path, "none") == 0) + has_console = false; + + ret = lxc_mainloop_open(&descr); +@@ -726,7 +728,7 @@ void lxc_free_handler(struct lxc_handler *handler) + } + + struct lxc_handler *lxc_init_handler(const char *name, struct lxc_conf *conf, +- const char *lxcpath, bool daemonize) ++ const char *lxcpath, bool daemonize) + { + int i, ret; + struct lxc_handler *handler; +@@ -764,7 +766,7 @@ struct lxc_handler *lxc_init_handler(const char *name, struct lxc_conf *conf, + * again currently so don't open another socketpair(). + */ + ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, +- handler->state_socket_pair); ++ handler->state_socket_pair); + if (ret < 0) { + ERROR("Failed to create anonymous pair of unix sockets"); + goto on_error; +@@ -829,49 +831,49 @@ int lxc_init(const char *name, struct lxc_handler *handler) + ret = setenv("LXC_CONFIG_FILE", conf->rcfile, 1); + if (ret < 0) + SYSERROR("Failed to set environment variable: " +- "LXC_CONFIG_FILE=%s", conf->rcfile); ++ "LXC_CONFIG_FILE=%s", conf->rcfile); + } + + if (conf->rootfs.mount) { + ret = setenv("LXC_ROOTFS_MOUNT", conf->rootfs.mount, 1); + if (ret < 0) + SYSERROR("Failed to set environment variable: " +- "LXC_ROOTFS_MOUNT=%s", conf->rootfs.mount); ++ "LXC_ROOTFS_MOUNT=%s", conf->rootfs.mount); + } + + if (conf->rootfs.path) { + ret = setenv("LXC_ROOTFS_PATH", conf->rootfs.path, 1); + if (ret < 0) + SYSERROR("Failed to set environment variable: " +- "LXC_ROOTFS_PATH=%s", conf->rootfs.path); ++ "LXC_ROOTFS_PATH=%s", conf->rootfs.path); + } + + if (conf->console.path) { + ret = setenv("LXC_CONSOLE", conf->console.path, 1); + if (ret < 0) + SYSERROR("Failed to set environment variable: " +- "LXC_CONSOLE=%s", conf->console.path); ++ "LXC_CONSOLE=%s", conf->console.path); + } + + if (conf->console.log_path) { + ret = setenv("LXC_CONSOLE_LOGPATH", conf->console.log_path, 1); + if (ret < 0) + SYSERROR("Failed to set environment variable: " +- "LXC_CONSOLE_LOGPATH=%s", conf->console.log_path); ++ "LXC_CONSOLE_LOGPATH=%s", conf->console.log_path); + } + + if (cgns_supported()) { + ret = setenv("LXC_CGNS_AWARE", "1", 1); + if (ret < 0) + SYSERROR("Failed to set environment variable " +- "LXC_CGNS_AWARE=1"); ++ "LXC_CGNS_AWARE=1"); + } + + loglevel = lxc_log_priority_to_string(lxc_log_get_level()); + ret = setenv("LXC_LOG_LEVEL", loglevel, 1); + if (ret < 0) + SYSERROR("Set environment variable LXC_LOG_LEVEL=%s", +- loglevel); ++ loglevel); + + if (conf->hooks_version == 0) + ret = setenv("LXC_HOOK_VERSION", "0", 1); +@@ -959,6 +961,7 @@ static int _read_procs_file(const char *path, pid_t **pids, size_t *len) + FILE *f; + char *line = NULL; + size_t sz = 0; ++ pid_t *tmp_pids = NULL; + + f = fopen_cloexec(path, "r"); + if (!f) +@@ -968,7 +971,16 @@ static int _read_procs_file(const char *path, pid_t **pids, size_t *len) + pid_t pid; + trim_line(line); + pid = (pid_t)atoll(line); +- *pids = realloc(*pids, sizeof(pid_t) * (*len + 1)); ++ if (lxc_mem_realloc((void **)&tmp_pids, sizeof(pid_t) * (*len + 1), *pids, sizeof(pid_t) * (*len)) != 0) { ++ free(*pids); ++ *pids = NULL; ++ ERROR("out of memory"); ++ free(line); ++ fclose(f); ++ return -1; ++ } ++ *pids = tmp_pids; ++ + (*pids)[*len] = pid; + (*len)++; + } +@@ -980,8 +992,8 @@ static int _read_procs_file(const char *path, pid_t **pids, size_t *len) + + static int _recursive_read_cgroup_procs(const char *dirpath, pid_t **pids, size_t *len) + { +- struct dirent *direntp; +- DIR *dir; ++ struct dirent *direntp = NULL; ++ DIR *dir = NULL; + int ret, failed = 0; + char pathname[PATH_MAX]; + +@@ -996,7 +1008,7 @@ static int _recursive_read_cgroup_procs(const char *dirpath, pid_t **pids, size_ + int rc; + + if (!strcmp(direntp->d_name, ".") || +- !strcmp(direntp->d_name, "..")) ++ !strcmp(direntp->d_name, "..")) + continue; + + rc = snprintf(pathname, PATH_MAX, "%s/%s", dirpath, direntp->d_name); +@@ -1122,11 +1134,11 @@ void lxc_fini(const char *name, struct lxc_handler *handler) + + if (handler->conf->hooks_version == 0) + ret = asprintf(&namespaces[namespace_count], +- "%s:/proc/%d/fd/%d", ns_info[i].proc_name, +- self, handler->nsfd[i]); ++ "%s:/proc/%d/fd/%d", ns_info[i].proc_name, ++ self, handler->nsfd[i]); + else + ret = asprintf(&namespaces[namespace_count], +- "/proc/%d/fd/%d", self, handler->nsfd[i]); ++ "/proc/%d/fd/%d", self, handler->nsfd[i]); + if (ret == -1) { + SYSERROR("Failed to allocate memory"); + break; +@@ -1140,7 +1152,7 @@ void lxc_fini(const char *name, struct lxc_handler *handler) + ret = setenv(ns_info[i].env_name, namespaces[namespace_count], 1); + if (ret < 0) + SYSERROR("Failed to set environment variable %s=%s", +- ns_info[i].env_name, namespaces[namespace_count]); ++ ns_info[i].env_name, namespaces[namespace_count]); + else + TRACE("Set environment variable %s=%s", + ns_info[i].env_name, namespaces[namespace_count]); +@@ -1153,14 +1165,14 @@ void lxc_fini(const char *name, struct lxc_handler *handler) + ret = setenv("LXC_TARGET", "reboot", 1); + if (ret < 0) + SYSERROR("Failed to set environment variable: " +- "LXC_TARGET=reboot"); ++ "LXC_TARGET=reboot"); + } + + if (handler->conf->reboot == REBOOT_NONE) { + ret = setenv("LXC_TARGET", "stop", 1); + if (ret < 0) + SYSERROR("Failed to set environment variable: " +- "LXC_TARGET=stop"); ++ "LXC_TARGET=stop"); + } + + if (handler->conf->hooks_version == 0) +@@ -1252,7 +1264,7 @@ retry: + + /* Keep state clients that want to be notified about reboots. */ + if ((handler->conf->reboot > REBOOT_NONE) && +- (client->states[RUNNING] == 2)) ++ (client->states[RUNNING] == 2)) + continue; + + /* close state client socket */ +@@ -1287,7 +1299,8 @@ void lxc_abort(const char *name, struct lxc_handler *handler) + + static int do_start(void *data) + { +- int ret, i; ++ int ret = 0; ++ int i; + char path[PATH_MAX]; + uid_t new_uid; + gid_t new_gid; +@@ -1351,7 +1364,7 @@ static int do_start(void *data) + * https://github.com/lxc/lxd/issues/1978. + */ + if ((handler->ns_clone_flags & (CLONE_NEWNET | CLONE_NEWUSER)) == +- (CLONE_NEWNET | CLONE_NEWUSER)) { ++ (CLONE_NEWNET | CLONE_NEWUSER)) { + ret = unshare(CLONE_NEWNET); + if (ret < 0) { + SYSERROR("Failed to unshare CLONE_NEWNET"); +@@ -1390,11 +1403,11 @@ static int do_start(void *data) + * user namespace. + */ + if (!lxc_setgroups(0, NULL) && +- (handler->am_root || errno != EPERM)) ++ (handler->am_root || errno != EPERM)) + goto out_warn_father; + + ret = prctl(PR_SET_DUMPABLE, prctl_arg(1), prctl_arg(0), +- prctl_arg(0), prctl_arg(0)); ++ prctl_arg(0), prctl_arg(0)); + if (ret < 0) + goto out_warn_father; + +@@ -1413,7 +1426,7 @@ static int do_start(void *data) + } + + ret = snprintf(path, sizeof(path), "%s/dev/null", +- handler->conf->rootfs.mount); ++ handler->conf->rootfs.mount); + if (ret < 0 || ret >= sizeof(path)) + goto out_warn_father; + +@@ -1474,7 +1487,7 @@ static int do_start(void *data) + ret = putenv((char *)iterator->elem); + if (ret < 0) { + SYSERROR("Failed to set environment variable: %s", +- (char *)iterator->elem); ++ (char *)iterator->elem); + goto out_warn_father; + } + } +@@ -1498,10 +1511,10 @@ static int do_start(void *data) + */ + if (handler->conf->no_new_privs) { + ret = prctl(PR_SET_NO_NEW_PRIVS, prctl_arg(1), prctl_arg(0), +- prctl_arg(0), prctl_arg(0)); ++ prctl_arg(0), prctl_arg(0)); + if (ret < 0) { + SYSERROR("Could not set PR_SET_NO_NEW_PRIVS to block " +- "execve() gainable privileges"); ++ "execve() gainable privileges"); + goto out_warn_father; + } + DEBUG("Set PR_SET_NO_NEW_PRIVS to block execve() gainable " +@@ -1550,25 +1563,25 @@ static int do_start(void *data) + * setup on its console ie. the pty allocated in lxc_terminal_setup() so + * make sure that that pty is stdin,stdout,stderr. + */ +- setsid(); +- if (!handler->disable_pty && handler->conf->console.slave >= 0) { ++ setsid(); ++ if (!handler->disable_pty && handler->conf->console.slave >= 0) { + /* isulad:make the given terminal as controlling terminal to avoid warning + * sh: cannot set terminal process group (-1): Inappropriate ioctl for device + * sh: no job control in this shell */ +- if (ioctl(handler->conf->console.slave, TIOCSCTTY, NULL) < 0) { +- ERROR("Faild to make the given terminal the controlling terminal of the calling process"); +- goto out_warn_father; +- } +- if (handler->daemonize || !handler->conf->is_execute) +- ret = set_stdfds(handler->conf->console.slave); +- else +- ret = lxc_terminal_set_stdfds(handler->conf->console.slave); +- if (ret < 0) { ++ if (ioctl(handler->conf->console.slave, TIOCSCTTY, NULL) < 0) { ++ ERROR("Faild to make the given terminal the controlling terminal of the calling process"); ++ goto out_warn_father; ++ } ++ if (handler->daemonize || !handler->conf->is_execute) ++ ret = set_stdfds(handler->conf->console.slave); ++ else ++ ret = lxc_terminal_set_stdfds(handler->conf->console.slave); ++ if (ret < 0) { + ERROR("Failed to redirect std{in,out,err} to pty file " + "descriptor %d", handler->conf->console.slave); + goto out_warn_father; +- } +- } ++ } ++ } + + /* If we mounted a temporary proc, then unmount it now. */ + tmp_proc_unmount(handler->conf); +@@ -1611,7 +1624,7 @@ static int do_start(void *data) + if (stat(handler->conf->init_cwd, &st) < 0 && mkdir_p(handler->conf->init_cwd, 0755) < 0) { + SYSERROR("Try to create directory \"%s\" as workdir failed", handler->conf->init_cwd); + lxc_write_error_message(handler->conf->errpipe[1], "%s:%d: Failed to create workdir: %s.", +- __FILE__, __LINE__, strerror(errno)); ++ __FILE__, __LINE__, strerror(errno)); + goto out_warn_father; + } + if (chdir(handler->conf->init_cwd)) { +@@ -1636,7 +1649,7 @@ static int do_start(void *data) + ret = putenv((char *)iterator->elem); + if (ret < 0) { + SYSERROR("Failed to set environment variable: %s", +- (char *)iterator->elem); ++ (char *)iterator->elem); + goto out_warn_father; + } + } +@@ -1675,9 +1688,9 @@ static int do_start(void *data) + * drop groups if we can, so ensure that we have necessary privilege. + */ + if (lxc_list_empty(&handler->conf->id_map)) +- #if HAVE_LIBCAP ++#if HAVE_LIBCAP + if (lxc_proc_cap_is_set(CAP_SETGID, CAP_EFFECTIVE)) +- #endif ++#endif + /* isulad: set groups for init process, and before we set uid and gid */ + if (!lxc_setgroups(handler->conf->init_groups_len, handler->conf->init_groups)) { + ERROR("Can not set groups"); +@@ -1834,7 +1847,7 @@ static inline int do_share_ns(void *arg) + * setns() will fail here. + */ + SYSERROR("Failed to inherit %s namespace", +- ns_info[i].proc_name); ++ ns_info[i].proc_name); + return -1; + } + +@@ -1855,7 +1868,7 @@ static int lxc_write_container_info(char *filename, pid_t pid, pid_t p_pid, unsi + FILE *pid_fp = NULL; + int ret = 0; + +- pid_fp = fopen(filename, "w"); ++ pid_fp = lxc_fopen(filename, "w"); + if (pid_fp == NULL) { + SYSERROR("Failed to create pidfile '%s'",filename); + ret = -1; +@@ -1898,7 +1911,7 @@ static int lxc_check_container_info(char *filename, pid_t pid, pid_t p_pid, unsi + } + + if (pid != saved_pid || p_pid != saved_ppid +- || start_at != saved_start_time || p_start_at != saved_pstart_time) { ++ || start_at != saved_start_time || p_start_at != saved_pstart_time) { + ERROR("Check container info failed"); + ret = -1; + goto out; +@@ -1973,7 +1986,7 @@ static int lxc_spawn(struct lxc_handler *handler) + return -1; + + ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, +- handler->data_sock); ++ handler->data_sock); + if (ret < 0) { + lxc_sync_fini(handler); + return -1; +@@ -2044,7 +2057,7 @@ static int lxc_spawn(struct lxc_handler *handler) + pid_t attacher_pid; + + attacher_pid = lxc_clone(do_share_ns, handler, +- CLONE_VFORK | CLONE_VM | CLONE_FILES); ++ CLONE_VFORK | CLONE_VM | CLONE_FILES); + if (attacher_pid < 0) { + SYSERROR(LXC_CLONE_ERROR); + goto out_delete_net; +@@ -2057,7 +2070,7 @@ static int lxc_spawn(struct lxc_handler *handler) + } + } else { + handler->pid = lxc_raw_clone_cb(do_start, handler, +- handler->ns_on_clone_flags); ++ handler->ns_on_clone_flags); + } + if (handler->pid < 0) { + SYSERROR(LXC_CLONE_ERROR); +@@ -2108,7 +2121,7 @@ static int lxc_spawn(struct lxc_handler *handler) + */ + if (wants_to_map_ids) { + if (!handler->conf->ns_share[LXC_NS_USER] && +- (handler->conf->ns_keep & CLONE_NEWUSER) == 0) { ++ (handler->conf->ns_keep & CLONE_NEWUSER) == 0) { + ret = lxc_map_ids(id_map, handler->pid); + if (ret < 0) { + ERROR("Failed to set up id mapping."); +@@ -2157,16 +2170,16 @@ static int lxc_spawn(struct lxc_handler *handler) + /* Create the network configuration. */ + if (handler->ns_clone_flags & CLONE_NEWNET) { + ret = lxc_network_move_created_netdev_priv(handler->lxcpath, +- handler->name, +- &conf->network, +- handler->pid); ++ handler->name, ++ &conf->network, ++ handler->pid); + if (ret < 0) { + ERROR("Failed to create the configured network"); + goto out_delete_net; + } + + ret = lxc_create_network_unpriv(handler->lxcpath, handler->name, +- &conf->network, handler->pid, conf->hooks_version); ++ &conf->network, handler->pid, conf->hooks_version); + if (ret < 0) { + ERROR("Failed to create the configured network"); + goto out_delete_net; +@@ -2245,10 +2258,7 @@ static int lxc_spawn(struct lxc_handler *handler) + } + + /* isulad: Run oci prestart hook at here */ +- char* oci_hook_args[1]; +- oci_hook_args[0] = alloca(strlen(lxcpath) + 1); +- (void)strlcpy(oci_hook_args[0], lxcpath, strlen(lxcpath) + 1); +- ret = run_lxc_hooks(name, "oci-prestart", conf, oci_hook_args); ++ ret = run_oci_hooks(name, "oci-prestart", conf, lxcpath); + if (ret < 0) { + ERROR("Failed to run oci prestart hooks"); + goto out_delete_net; +@@ -2302,7 +2312,7 @@ static int lxc_spawn(struct lxc_handler *handler) + goto out_abort; + + /* isulad: Run oci prestart hook at here */ +- ret = run_lxc_hooks(name, "oci-poststart", conf, oci_hook_args); ++ ret = run_oci_hooks(name, "oci-poststart", conf, lxcpath); + if (ret < 0) { + ERROR("Failed to run oci poststart hooks"); + goto out_abort; +@@ -2402,8 +2412,8 @@ out: + #define ExitSignalOffset 128 + + int __lxc_start(const char *name, struct lxc_handler *handler, +- struct lxc_operations* ops, void *data, const char *lxcpath, +- bool daemonize, int *error_num, unsigned int start_timeout) ++ struct lxc_operations* ops, void *data, const char *lxcpath, ++ bool daemonize, int *error_num, unsigned int start_timeout) + { + int ret, status, exit_code; + struct lxc_conf *conf = handler->conf; +@@ -2560,7 +2570,7 @@ static struct lxc_operations start_ops = { + }; + + int lxc_start(const char *name, char *const argv[], struct lxc_handler *handler, +- const char *lxcpath, bool daemonize, int *error_num, unsigned int start_timeout) ++ const char *lxcpath, bool daemonize, int *error_num, unsigned int start_timeout) + { + struct start_args start_arg = { + .argv = argv, +@@ -2571,7 +2581,7 @@ int lxc_start(const char *name, char *const argv[], struct lxc_handler *handler, + } + + static void lxc_destroy_container_on_signal(struct lxc_handler *handler, +- const char *name) ++ const char *name) + { + char destroy[PATH_MAX]; + struct lxc_container *c; +@@ -2607,7 +2617,7 @@ static void lxc_destroy_container_on_signal(struct lxc_handler *handler, + + if (!handler->am_root) + ret = userns_exec_full(handler->conf, lxc_rmdir_onedev_wrapper, +- destroy, "lxc_rmdir_onedev_wrapper"); ++ destroy, "lxc_rmdir_onedev_wrapper"); + else + ret = lxc_rmdir_onedev(destroy, NULL); + +@@ -2630,7 +2640,7 @@ static bool do_destroy_container(struct lxc_handler *handler) + + if (!handler->am_root) { + ret = userns_exec_full(handler->conf, storage_destroy_wrapper, +- handler->conf, "storage_destroy_wrapper"); ++ handler->conf, "storage_destroy_wrapper"); + if (ret < 0) + return false; + +@@ -2846,11 +2856,7 @@ int do_lxcapi_clean_resource(char *name, char *lxcpath, struct lxc_conf *conf, p + signal_all_processes(handler); + } + +- char* oci_hook_args[1]; +- oci_hook_args[0] = alloca(strlen(handler->lxcpath) + 1); +- (void)strlcpy(oci_hook_args[0], handler->lxcpath, strlen(handler->lxcpath) + 1); +- +- if (run_lxc_hooks(handler->name, "oci-poststop", handler->conf, oci_hook_args)) { ++ if (run_oci_hooks(handler->name, "oci-poststop", handler->conf, handler->lxcpath)) { + ERROR("Failed to run lxc.hook.post-stop for container \"%s\".", handler->name); + ret = -1; + } +diff --git a/src/lxc/storage/block.c b/src/lxc/storage/block.c +index eb75e70..8998923 100644 +--- a/src/lxc/storage/block.c ++++ b/src/lxc/storage/block.c +@@ -62,7 +62,8 @@ bool blk_detect(const char *path) + + int blk_mount(struct lxc_storage *bdev) + { +- const char *src; ++ const char *src = NULL; ++ + if (strcmp(bdev->type, "blk")) + return -22; + +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index 88653b4..802bf39 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -113,7 +113,7 @@ void lxc_terminal_sigwinch(int sig) + } + + int lxc_terminal_signalfd_cb(int fd, uint32_t events, void *cbdata, +- struct lxc_epoll_descr *descr) ++ struct lxc_epoll_descr *descr) + { + ssize_t ret; + struct signalfd_siginfo siginfo; +@@ -300,7 +300,7 @@ static int lxc_terminal_rotate_log_file(struct lxc_terminal *terminal) + } + + static int lxc_terminal_rotate_write_data(struct lxc_terminal *terminal, const char *buf, +- int bytes_read) ++ int bytes_read) + { + int ret; + struct stat st; +@@ -310,7 +310,7 @@ static int lxc_terminal_rotate_write_data(struct lxc_terminal *terminal, const c + return 0; + + /* A log size <= 0 means that there's no limit on the size of the log +- * file at which point we simply ignore whether the log is supposed to ++ * file at which point we simply ignore whether the log is supposed to + * be rotated or not. + */ + if (terminal->log_size <= 0) +@@ -397,48 +397,49 @@ static int lxc_terminal_rotate_write_data(struct lxc_terminal *terminal, const c + + /* get time buffer */ + static bool get_time_buffer(struct timespec *timestamp, char *timebuffer, +- size_t maxsize) ++ size_t maxsize) + { +- struct tm tm_utc = { 0 }; +- int32_t nanos = 0; +- time_t seconds; ++ struct tm tm_utc = { 0 }; ++ int32_t nanos = 0; ++ time_t seconds; + +- if (!timebuffer || !maxsize) { +- return false; +- } ++ if (!timebuffer || !maxsize) { ++ return false; ++ } + +- seconds = (time_t)timestamp->tv_sec; +- gmtime_r(&seconds, &tm_utc); +- strftime(timebuffer, maxsize, "%Y-%m-%dT%H:%M:%S", &tm_utc); ++ seconds = (time_t)timestamp->tv_sec; ++ gmtime_r(&seconds, &tm_utc); ++ strftime(timebuffer, maxsize, "%Y-%m-%dT%H:%M:%S", &tm_utc); + +- nanos = (int32_t)timestamp->tv_nsec; +- sprintf(timebuffer + strlen(timebuffer), ".%09dZ", nanos); ++ nanos = (int32_t)timestamp->tv_nsec; ++ sprintf(timebuffer + strlen(timebuffer), ".%09dZ", nanos); + +- return true; ++ return true; + } + + /* get now time buffer */ + static bool get_now_time_buffer(char *timebuffer, size_t maxsize) + { +- int err = 0; +- struct timespec ts; ++ int err = 0; ++ struct timespec ts; + +- err = clock_gettime(CLOCK_REALTIME, &ts); +- if (err != 0) { +- ERROR("failed to get time"); +- return false; +- } ++ err = clock_gettime(CLOCK_REALTIME, &ts); ++ if (err != 0) { ++ ERROR("failed to get time"); ++ return false; ++ } + +- return get_time_buffer(&ts, timebuffer, maxsize); ++ return get_time_buffer(&ts, timebuffer, maxsize); + } + + static ssize_t lxc_logger_write(struct lxc_terminal *terminal, const char *type, const char *buf, +- int bytes_read) ++ int bytes_read) + { + logger_json_file *msg = NULL; + ssize_t ret = -1; + size_t len; +- char *json = NULL, timebuffer[64]; ++ char *json = NULL; ++ char timebuffer[64] = { 0 }; + parser_error err = NULL; + struct parser_context ctx = { GEN_OPTIONS_SIMPLIFY | GEN_OPTIONS_NOT_VALIDATE_UTF8, stderr }; + +@@ -473,7 +474,7 @@ cleanup: + } + + static int lxc_terminal_write_log_file(struct lxc_terminal *terminal, const char *type, char *buf, +- int bytes_read) ++ int bytes_read) + { + #define __BUF_CACHE_SIZE (16 * LXC_TERMINAL_BUFFER_SIZE) + static char cache[__BUF_CACHE_SIZE]; +@@ -541,9 +542,10 @@ static int lxc_terminal_write_log_file(struct lxc_terminal *terminal, const char + } + + /* isulad: forward data to all fifos */ +-static void lxc_forward_data_to_fifo(struct lxc_list *list, bool is_err, char *buf, int r) ++static void lxc_forward_data_to_fifo(struct lxc_list *list, bool is_err, const char *buf, int r) + { +- struct lxc_list *it,*next; ++ struct lxc_list *it = NULL; ++ struct lxc_list *next = NULL; + struct lxc_fifos_fd *elem = NULL; + + lxc_list_for_each_safe(it, list, next) { +@@ -563,7 +565,8 @@ static void lxc_forward_data_to_fifo(struct lxc_list *list, bool is_err, char *b + /* isulad: judge the fd whether is fifo */ + static bool lxc_terminal_is_fifo(int fd, struct lxc_list *list) + { +- struct lxc_list *it,*next; ++ struct lxc_list *it = NULL; ++ struct lxc_list *next = NULL; + struct lxc_fifos_fd *elem = NULL; + + lxc_list_for_each_safe(it, list, next) { +@@ -576,7 +579,7 @@ static bool lxc_terminal_is_fifo(int fd, struct lxc_list *list) + } + + int lxc_terminal_io_cb(int fd, uint32_t events, void *data, +- struct lxc_epoll_descr *descr) ++ struct lxc_epoll_descr *descr) + { + struct lxc_terminal *terminal = data; + char buf[2 * LXC_TERMINAL_BUFFER_SIZE]; +@@ -684,7 +687,7 @@ static int lxc_terminal_mainloop_add_peer(struct lxc_terminal *terminal) + + if (terminal->peer >= 0) { + ret = lxc_mainloop_add_handler(terminal->descr, terminal->peer, +- lxc_terminal_io_cb, terminal); ++ lxc_terminal_io_cb, terminal); + if (ret < 0) { + WARN("Failed to add terminal peer handler to mainloop"); + return -1; +@@ -695,7 +698,7 @@ static int lxc_terminal_mainloop_add_peer(struct lxc_terminal *terminal) + return 0; + + ret = lxc_mainloop_add_handler(terminal->descr, terminal->tty_state->sigfd, +- lxc_terminal_signalfd_cb, terminal->tty_state); ++ lxc_terminal_signalfd_cb, terminal->tty_state); + if (ret < 0) { + WARN("Failed to add signal handler to mainloop"); + return -1; +@@ -712,7 +715,7 @@ static int lxc_terminal_mainloop_add_pipes(struct lxc_terminal *terminal) + // parent read data from fifo, and send to stdin of container + if (terminal->pipes[0][1] > 0) { + ret = lxc_mainloop_add_handler(terminal->descr, terminal->pipes[0][1], +- lxc_terminal_io_cb, terminal); ++ lxc_terminal_io_cb, terminal); + if (ret) { + ERROR("pipe fd %d not added to mainloop", terminal->pipes[0][1]); + return -1; +@@ -721,7 +724,7 @@ static int lxc_terminal_mainloop_add_pipes(struct lxc_terminal *terminal) + // parent read data from stdout of container, and send to fifo + if (terminal->pipes[1][0] > 0) { + ret = lxc_mainloop_add_handler(terminal->descr, terminal->pipes[1][0], +- lxc_terminal_io_cb, terminal); ++ lxc_terminal_io_cb, terminal); + if (ret) { + ERROR("pipe fd %d not added to mainloop", terminal->pipes[1][0]); + return -1; +@@ -730,7 +733,7 @@ static int lxc_terminal_mainloop_add_pipes(struct lxc_terminal *terminal) + // parent read data from stderr of container, and send to fifo + if (terminal->pipes[2][0] > 0) { + ret = lxc_mainloop_add_handler(terminal->descr, terminal->pipes[2][0], +- lxc_terminal_io_cb, terminal); ++ lxc_terminal_io_cb, terminal); + if (ret) { + ERROR("pipe fd %d not added to mainloop", terminal->pipes[2][0]); + return -1; +@@ -743,14 +746,15 @@ static int lxc_terminal_mainloop_add_pipes(struct lxc_terminal *terminal) + static int lxc_terminal_mainloop_add_fifo(struct lxc_terminal *terminal) + { + int ret = 0; +- struct lxc_list *it,*next; ++ struct lxc_list *it = NULL; ++ struct lxc_list *next = NULL; + struct lxc_fifos_fd *elem = NULL; + + lxc_list_for_each_safe(it, &terminal->fifos, next) { + elem = it->elem; + if (elem->in_fd >= 0) { + ret = lxc_mainloop_add_handler(terminal->descr, elem->in_fd, +- lxc_terminal_io_cb, terminal); ++ lxc_terminal_io_cb, terminal); + if (ret) { + ERROR("console fifo %s not added to mainloop", elem->in_fifo); + return -1; +@@ -761,7 +765,7 @@ static int lxc_terminal_mainloop_add_fifo(struct lxc_terminal *terminal) + } + + int lxc_terminal_mainloop_add(struct lxc_epoll_descr *descr, +- struct lxc_terminal *terminal) ++ struct lxc_terminal *terminal) + { + int ret; + +@@ -796,7 +800,7 @@ int lxc_terminal_mainloop_add(struct lxc_epoll_descr *descr, + } + + ret = lxc_mainloop_add_handler(descr, terminal->master, +- lxc_terminal_io_cb, terminal); ++ lxc_terminal_io_cb, terminal); + if (ret < 0) { + ERROR("Failed to add handler for terminal master fd %d to " + "mainloop", terminal->master); +@@ -879,7 +883,7 @@ static void lxc_terminal_peer_proxy_free(struct lxc_terminal *terminal) + } + + static int lxc_terminal_peer_proxy_alloc(struct lxc_terminal *terminal, +- int sockfd) ++ int sockfd) + { + int ret; + struct termios oldtermio; +@@ -904,14 +908,14 @@ static int lxc_terminal_peer_proxy_alloc(struct lxc_terminal *terminal, + * that the real terminal master will send to / recv from. + */ + ret = openpty(&terminal->proxy.master, &terminal->proxy.slave, NULL, +- NULL, NULL); ++ NULL, NULL); + if (ret < 0) { + SYSERROR("Failed to open proxy terminal"); + return -1; + } + + ret = ttyname_r(terminal->proxy.slave, terminal->proxy.name, +- sizeof(terminal->proxy.name)); ++ sizeof(terminal->proxy.name)); + if (ret < 0) { + SYSERROR("Failed to retrieve name of proxy terminal slave"); + goto on_error; +@@ -1253,7 +1257,7 @@ static int terminal_fifo_open(const char *fifo_path, int flags) + { + int fd = -1; + +- fd = open(fifo_path, flags); ++ fd = lxc_open(fifo_path, flags, 0); + if (fd < 0) { + WARN("Failed to open fifo %s to send message: %s.", fifo_path, + strerror(errno)); +@@ -1491,15 +1495,17 @@ int lxc_terminal_set_stdfds(int fd) + return 0; + + for (i = 0; i < 3; i++) +- if (!__terminal_dup2(fd, (int[]){STDIN_FILENO, STDOUT_FILENO, +- STDERR_FILENO}[i])) +- return -1; ++ if (!__terminal_dup2(fd, (int[]) { ++ STDIN_FILENO, STDOUT_FILENO, ++ STDERR_FILENO ++ }[i])) ++ return -1; + + return 0; + } + + int lxc_terminal_stdin_cb(int fd, uint32_t events, void *cbdata, +- struct lxc_epoll_descr *descr) ++ struct lxc_epoll_descr *descr) + { + int ret; + char c; +@@ -1533,7 +1539,7 @@ int lxc_terminal_stdin_cb(int fd, uint32_t events, void *cbdata, + } + + int lxc_terminal_master_cb(int fd, uint32_t events, void *cbdata, +- struct lxc_epoll_descr *descr) ++ struct lxc_epoll_descr *descr) + { + int r, w; + char buf[LXC_TERMINAL_BUFFER_SIZE]; +@@ -1559,8 +1565,8 @@ int lxc_terminal_getfd(struct lxc_container *c, int *ttynum, int *masterfd) + } + + int lxc_console(struct lxc_container *c, int ttynum, +- int stdinfd, int stdoutfd, int stderrfd, +- int escape) ++ int stdinfd, int stdoutfd, int stderrfd, ++ int escape) + { + int masterfd, ret, ttyfd; + struct lxc_epoll_descr descr; +@@ -1602,7 +1608,7 @@ int lxc_console(struct lxc_container *c, int ttynum, + + if (ts->sigfd != -1) { + ret = lxc_mainloop_add_handler(&descr, ts->sigfd, +- lxc_terminal_signalfd_cb, ts); ++ lxc_terminal_signalfd_cb, ts); + if (ret < 0) { + ERROR("Failed to add signal handler to mainloop"); + goto close_mainloop; +@@ -1610,14 +1616,14 @@ int lxc_console(struct lxc_container *c, int ttynum, + } + + ret = lxc_mainloop_add_handler(&descr, ts->stdinfd, +- lxc_terminal_stdin_cb, ts); ++ lxc_terminal_stdin_cb, ts); + if (ret < 0) { + ERROR("Failed to add stdin handler"); + goto close_mainloop; + } + + ret = lxc_mainloop_add_handler(&descr, ts->masterfd, +- lxc_terminal_master_cb, ts); ++ lxc_terminal_master_cb, ts); + if (ret < 0) { + ERROR("Failed to add master handler"); + goto close_mainloop; +@@ -1625,11 +1631,11 @@ int lxc_console(struct lxc_container *c, int ttynum, + + if (ts->escape >= 1) { + fprintf(stderr, +- "\n" +- "Connected to tty %1$d\n" +- "Type to exit the console, " +- " to enter Ctrl+%2$c itself\n", +- ttynum, 'a' + escape - 1); ++ "\n" ++ "Connected to tty %1$d\n" ++ "Type to exit the console, " ++ " to enter Ctrl+%2$c itself\n", ++ ttynum, 'a' + escape - 1); + } + + if (istty) { +@@ -1729,7 +1735,8 @@ void lxc_terminal_init(struct lxc_terminal *terminal) + /* isulad: if fd == -1, means delete all the fifos*/ + int lxc_terminal_delete_fifo(int fd, struct lxc_list *list) + { +- struct lxc_list *it,*next; ++ struct lxc_list *it = NULL; ++ struct lxc_list *next = NULL; + struct lxc_fifos_fd *elem = NULL; + + lxc_list_for_each_safe(it, list, next) { +@@ -1837,7 +1844,7 @@ int lxc_terminal_add_fifos(struct lxc_conf *conf, const char *fifonames) + } + + if (lxc_mainloop_add_handler(terminal->descr, fifofd_in, +- lxc_terminal_io_cb, terminal)) { ++ lxc_terminal_io_cb, terminal)) { + ERROR("console fifo not added to mainloop"); + lxc_terminal_delete_fifo(fifofd_in, &terminal->fifos); + ret = -1; +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index dc0e6c5..9ce2473 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -56,6 +56,7 @@ + #include "raw_syscalls.h" + #include "syscall_wrappers.h" + #include "utils.h" ++#include "path.h" + + #ifndef HAVE_STRLCPY + #include "include/strlcpy.h" +@@ -81,7 +82,7 @@ lxc_log_define(utils, lxc); + extern bool btrfs_try_remove_subvol(const char *path); + + static int _recursive_rmdir(const char *dirname, dev_t pdev, +- const char *exclude, int level, bool onedev) ++ const char *exclude, int level, bool onedev) + { + struct dirent *direntp; + DIR *dir; +@@ -101,7 +102,7 @@ static int _recursive_rmdir(const char *dirname, dev_t pdev, + int rc; + + if (!strcmp(direntp->d_name, ".") || +- !strcmp(direntp->d_name, "..")) ++ !strcmp(direntp->d_name, "..")) + continue; + + rc = snprintf(pathname, PATH_MAX, "%s/%s", dirname, direntp->d_name); +@@ -155,8 +156,8 @@ static int _recursive_rmdir(const char *dirname, dev_t pdev, + } else { + if (unlink(pathname) < 0) { + if (saved_errno == 0) { +- saved_errno = errno; +- } ++ saved_errno = errno; ++ } + SYSERROR("Failed to delete \"%s\"", pathname); + failed=1; + } +@@ -186,7 +187,7 @@ static int _recursive_rmdir(const char *dirname, dev_t pdev, + static bool is_native_overlayfs(const char *path) + { + if (has_fs_type(path, OVERLAY_SUPER_MAGIC) || +- has_fs_type(path, OVERLAYFS_SUPER_MAGIC)) ++ has_fs_type(path, OVERLAYFS_SUPER_MAGIC)) + return true; + + return false; +@@ -650,7 +651,7 @@ uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval) + * multiply by the 64 bit FNV magic prime mod 2^64 + */ + hval += (hval << 1) + (hval << 4) + (hval << 5) + +- (hval << 7) + (hval << 8) + (hval << 40); ++ (hval << 7) + (hval << 8) + (hval << 40); + } + + return hval; +@@ -792,7 +793,7 @@ char *on_path(const char *cmd, const char *rootfs) + lxc_iterate_parts (entry, path, ":") { + if (rootfs) + ret = snprintf(cmdpath, PATH_MAX, "%s/%s/%s", rootfs, +- entry, cmd); ++ entry, cmd); + else + ret = snprintf(cmdpath, PATH_MAX, "%s/%s", entry, cmd); + if (ret < 0 || ret >= PATH_MAX) +@@ -820,7 +821,7 @@ char *choose_init(const char *rootfs) + { + char *retv = NULL; + const char *empty = "", +- *tmp; ++ *tmp; + int ret, env_set = 0; + + if (!getenv("PATH")) { +@@ -1141,7 +1142,7 @@ out: + * setup before executing the container's init + */ + int safe_mount(const char *src, const char *dest, const char *fstype, +- unsigned long flags, const void *data, const char *rootfs) ++ unsigned long flags, const void *data, const char *rootfs) + { + int destfd, ret, saved_errno; + /* Only needs enough for /proc/self/fd/. */ +@@ -1368,7 +1369,7 @@ out: + int lxc_preserve_ns(const int pid, const char *ns) + { + int ret; +-/* 5 /proc + 21 /int_as_str + 3 /ns + 20 /NS_NAME + 1 \0 */ ++ /* 5 /proc + 21 /int_as_str + 3 /ns + 20 /NS_NAME + 1 \0 */ + #define __NS_PATH_LEN 50 + char path[__NS_PATH_LEN]; + +@@ -1377,8 +1378,8 @@ int lxc_preserve_ns(const int pid, const char *ns) + * string. + */ + ret = snprintf(path, __NS_PATH_LEN, "/proc/%d/ns%s%s", pid, +- !ns || strcmp(ns, "") == 0 ? "" : "/", +- !ns || strcmp(ns, "") == 0 ? "" : ns); ++ !ns || strcmp(ns, "") == 0 ? "" : "/", ++ !ns || strcmp(ns, "") == 0 ? "" : ns); + if (ret < 0 || (size_t)ret >= __NS_PATH_LEN) { + errno = EFBIG; + return -1; +@@ -1452,7 +1453,7 @@ static int lxc_get_unused_loop_dev_legacy(char *loop_name) + ret = ioctl(fd, LOOP_GET_STATUS64, &lo64); + if (ret < 0) { + if (ioctl(fd, LOOP_GET_STATUS64, &lo64) == 0 || +- errno != ENXIO) { ++ errno != ENXIO) { + close(fd); + fd = -1; + continue; +@@ -1726,7 +1727,7 @@ int lxc_set_death_signal(int signal, pid_t parent) + //pid_t ppid; + + ret = prctl(PR_SET_PDEATHSIG, prctl_arg(signal), prctl_arg(0), +- prctl_arg(0), prctl_arg(0)); ++ prctl_arg(0), prctl_arg(0)); + + /* Check whether we have been orphaned. */ + /* isulad: delete this check, ppid will not be 0 if we shared host pid */ +@@ -1770,7 +1771,7 @@ int fd_nonblock(int fd) + { + long flags; + +- flags = fcntl(fd, F_GETFL); ++ flags = fcntl(fd, F_GETFL); + + return fcntl(fd, F_SETFL, flags | O_NONBLOCK); + } +@@ -1797,7 +1798,7 @@ int recursive_destroy(char *dirname) + struct stat mystat; + + if (!strcmp(direntp->d_name, ".") || +- !strcmp(direntp->d_name, "..")) ++ !strcmp(direntp->d_name, "..")) + continue; + + pathname = must_make_path(dirname, direntp->d_name, NULL); +@@ -1818,7 +1819,7 @@ int recursive_destroy(char *dirname) + if (ret < 0) + r = -1; + +- next: ++next: + free(pathname); + } + +@@ -1850,7 +1851,7 @@ int lxc_setup_keyring(void) + * information leaks. + */ + keyring = keyctl(KEYCTL_JOIN_SESSION_KEYRING, prctl_arg(0), +- prctl_arg(0), prctl_arg(0), prctl_arg(0)); ++ prctl_arg(0), prctl_arg(0), prctl_arg(0)); + if (keyring < 0) { + switch (errno) { + case ENOSYS: +@@ -1913,7 +1914,7 @@ int lxc_file2str(const char *filename, char ret[], int cap) + { + int fd, num_read; + +- if ((fd = open(filename, O_RDONLY | O_CLOEXEC)) == -1) ++ if ((fd = lxc_open(filename, O_RDONLY | O_CLOEXEC, 0)) == -1) + return -1; + if ((num_read = read(fd, ret, cap - 1)) <= 0) + num_read = -1; +@@ -1929,7 +1930,7 @@ int lxc_file2str(const char *filename, char ret[], int cap) + * Such names confuse %s (see scanf(3)), so the string is split and %39c + * is used instead. (except for embedded ')' "(%[^)]c)" would work. + */ +-static proc_t *lxc_stat2proc(char *S) ++static proc_t *lxc_stat2proc(const char *S) + { + int num; + proc_t *P = NULL; +@@ -1956,33 +1957,33 @@ static proc_t *lxc_stat2proc(char *S) + return NULL; + } + num = sscanf(tmp + 2, /* skip space after ')' too */ +- "%c " +- "%d %d %d %d %d " +- "%lu %lu %lu %lu %lu " +- "%Lu %Lu %Lu %Lu " /* utime stime cutime cstime */ +- "%ld %ld %ld %ld " +- "%Lu " /* start_time */ +- "%lu " +- "%ld " +- "%lu %lu %lu %lu %lu %lu " +- "%*s %*s %*s %*s " /* discard, no RT signals & Linux 2.1 used hex */ +- "%lu %lu %lu " +- "%d %d " +- "%lu %lu", +- &P->state, +- &P->ppid, &P->pgrp, &P->session, &P->tty, &P->tpgid, +- &P->flags, &P->min_flt, &P->cmin_flt, &P->maj_flt, &P->cmaj_flt, +- &P->utime, &P->stime, &P->cutime, &P->cstime, +- &P->priority, &P->nice, &P->timeout, &P->it_real_value, +- &P->start_time, +- &P->vsize, +- &P->rss, +- &P->rss_rlim, &P->start_code, &P->end_code, &P->start_stack, &P->kstk_esp, +- &P->kstk_eip, +- &P->wchan, &P->nswap, &P->cnswap, +- &P->exit_signal, &P->processor, /* 2.2.1 ends with "exit_signal" */ +- &P->rtprio, &P->sched /* both added to 2.5.18 */ +- ); ++ "%c " ++ "%d %d %d %d %d " ++ "%lu %lu %lu %lu %lu " ++ "%Lu %Lu %Lu %Lu " /* utime stime cutime cstime */ ++ "%ld %ld %ld %ld " ++ "%Lu " /* start_time */ ++ "%lu " ++ "%ld " ++ "%lu %lu %lu %lu %lu %lu " ++ "%*s %*s %*s %*s " /* discard, no RT signals & Linux 2.1 used hex */ ++ "%lu %lu %lu " ++ "%d %d " ++ "%lu %lu", ++ &P->state, ++ &P->ppid, &P->pgrp, &P->session, &P->tty, &P->tpgid, ++ &P->flags, &P->min_flt, &P->cmin_flt, &P->maj_flt, &P->cmaj_flt, ++ &P->utime, &P->stime, &P->cutime, &P->cstime, ++ &P->priority, &P->nice, &P->timeout, &P->it_real_value, ++ &P->start_time, ++ &P->vsize, ++ &P->rss, ++ &P->rss_rlim, &P->start_code, &P->end_code, &P->start_stack, &P->kstk_esp, ++ &P->kstk_eip, ++ &P->wchan, &P->nswap, &P->cnswap, ++ &P->exit_signal, &P->processor, /* 2.2.1 ends with "exit_signal" */ ++ &P->rtprio, &P->sched /* both added to 2.5.18 */ ++ ); + + if (P->tty == 0) + P->tty = -1; /* the old notty val, update elsewhere bef. moving to 0 */ +@@ -2092,3 +2093,67 @@ bool is_non_negative_num(const char *s) + return true; + } + ++void *lxc_common_calloc_s(size_t size) ++{ ++ if (size == 0 || size > SIZE_MAX) { ++ return NULL; ++ } ++ ++ return calloc((size_t)1, size); ++} ++ ++ ++int lxc_mem_realloc(void **newptr, size_t newsize, void *oldptr, size_t oldsize) ++{ ++ void *tmp = NULL; ++ int nret = 0; ++ if (newsize == 0) { ++ goto err_out; ++ } ++ ++ tmp = lxc_common_calloc_s(newsize); ++ if (tmp == NULL) { ++ ERROR("Failed to malloc memory"); ++ goto err_out; ++ } ++ ++ if (oldptr != NULL) { ++ memcpy(tmp, oldptr, (newsize < oldsize) ? newsize : oldsize); ++ ++ memset(oldptr, 0, oldsize); ++ ++ free(oldptr); ++ } ++ ++ *newptr = tmp; ++ return 0; ++ ++err_out: ++ return -1; ++} ++ ++int lxc_open(const char *filename, int flags, mode_t mode) ++{ ++ char rpath[PATH_MAX] = {0x00}; ++ ++ if (cleanpath(filename, rpath, sizeof(rpath)) == NULL) { ++ return -1; ++ } ++ if (mode) { ++ return open(rpath, flags | O_CLOEXEC, mode); ++ } else { ++ return open(rpath, flags | O_CLOEXEC); ++ } ++} ++ ++FILE *lxc_fopen(const char *filename, const char *mode) ++{ ++ char rpath[PATH_MAX] = {0x00}; ++ ++ if (cleanpath(filename, rpath, sizeof(rpath)) == NULL) { ++ return NULL; ++ } ++ ++ return fopen_cloexec(rpath, mode); ++} ++ +diff --git a/src/lxc/utils.h b/src/lxc/utils.h +index 4410ff2..2406ee1 100644 +--- a/src/lxc/utils.h ++++ b/src/lxc/utils.h +@@ -229,8 +229,8 @@ extern bool switch_to_ns(pid_t pid, const char *ns); + extern char *get_template_path(const char *t); + extern int open_without_symlink(const char *target, const char *prefix_skip); + extern int safe_mount(const char *src, const char *dest, const char *fstype, +- unsigned long flags, const void *data, +- const char *rootfs); ++ unsigned long flags, const void *data, ++ const char *rootfs); + extern int lxc_mount_proc_if_needed(const char *rootfs); + extern int open_devnull(void); + extern int set_stdfds(int fd); +@@ -269,7 +269,7 @@ extern int lxc_unstack_mountpoint(const char *path, bool lazy); + * @param[in] args Arguments to be passed to child_fn. + */ + extern int run_command(char *buf, size_t buf_size, int (*child_fn)(void *), +- void *args); ++ void *args); + + /* Concatenate all passed-in strings into one path. Do not fail. If any piece + * is not prefixed with '/', add a '/'. +@@ -324,5 +324,8 @@ extern bool lxc_process_alive(pid_t pid, unsigned long long start_time); + + extern bool is_non_negative_num(const char *s); + extern int lxc_file2str(const char *filename, char ret[], int cap); +- ++extern int lxc_mem_realloc(void **newptr, size_t newsize, void *oldptr, size_t oldsize); ++extern void *lxc_common_calloc_s(size_t size); ++extern int lxc_open(const char *filename, int flags, mode_t mode); ++extern FILE *lxc_fopen(const char *filename, const char *mode); + #endif /* __LXC_UTILS_H */ +-- +1.8.3.1 + diff --git a/0102-lxc-fix-compile-warnings.patch b/0102-lxc-fix-compile-warnings.patch new file mode 100644 index 0000000..11c2e2a --- /dev/null +++ b/0102-lxc-fix-compile-warnings.patch @@ -0,0 +1,84 @@ +From 1693410ec532fb2197ae8f7152409ee4c29180a3 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Mon, 3 Jun 2019 06:19:07 -0400 +Subject: [PATCH 102/122] lxc: fix compile warnings + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 1 - + src/lxc/path.c | 5 ----- + src/lxc/utils.c | 2 +- + 3 files changed, 1 insertion(+), 7 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index ec1667d..e7df336 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4992,7 +4992,6 @@ int run_lxc_hooks(const char *name, char *hookname, struct lxc_conf *conf, + + int run_oci_hooks(const char *name, char *hookname, struct lxc_conf *conf, const char *lxcpath) + { +- struct lxc_list *it; + int which = -1; + + if (strcmp(hookname, "oci-prestart") == 0) { +diff --git a/src/lxc/path.c b/src/lxc/path.c +index 45ab4c3..92692de 100644 +--- a/src/lxc/path.c ++++ b/src/lxc/path.c +@@ -141,7 +141,6 @@ int do_clean_path(const char *respath, const char *limit_respath, + { + char *dest = *dst; + const char *endpos = NULL; +- errno_t ret; + + for (endpos = stpos; *stpos; stpos = endpos) { + while (ISSLASH(*stpos)) { +@@ -184,7 +183,6 @@ char *cleanpath(const char *path, char *realpath, size_t realpath_len) + char *dest = NULL; + const char *stpos = NULL; + const char *limit_respath = NULL; +- errno_t ret; + + if (path == NULL || path[0] == '\0' || \ + realpath == NULL || (realpath_len < PATH_MAX)) { +@@ -293,7 +291,6 @@ static int do_get_symlinks(const char **fullpath, const char *prefix, size_t pre + { + char *buf = NULL; + size_t len; +- errno_t rc = EOK; + ssize_t n; + int ret = -1; + +@@ -398,7 +395,6 @@ static int do_eval_symlinks_in_scope(const char *fullpath, const char *prefix, + const char *start = NULL; + const char *end = NULL; + char *extra_buf = NULL; +- errno_t rc = EOK; + int nret = 0; + int num_links = 0; + +@@ -450,7 +446,6 @@ static char *eval_symlinks_in_scope(const char *fullpath, const char *rootpath) + char *prefix = NULL; + const char *rpath_limit = NULL; + size_t prefix_len; +- errno_t rc = EOK; + + if (fullpath == NULL || rootpath == NULL) { + return NULL; +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index 9ce2473..e674947 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -2106,7 +2106,7 @@ void *lxc_common_calloc_s(size_t size) + int lxc_mem_realloc(void **newptr, size_t newsize, void *oldptr, size_t oldsize) + { + void *tmp = NULL; +- int nret = 0; ++ + if (newsize == 0) { + goto err_out; + } +-- +1.8.3.1 + diff --git a/0103-lxc-fix-code-error-in-conf.c.patch b/0103-lxc-fix-code-error-in-conf.c.patch new file mode 100644 index 0000000..14d1efe --- /dev/null +++ b/0103-lxc-fix-code-error-in-conf.c.patch @@ -0,0 +1,109 @@ +From d3f6e8e611dd6b3160d58159e99565c3686e6398 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Mon, 3 Jun 2019 11:14:22 -0400 +Subject: [PATCH 103/122] lxc: fix code error in conf.c + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 21 ++++++++++++++++----- + src/lxc/conf.h | 2 +- + 2 files changed, 17 insertions(+), 6 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index e7df336..127ef77 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -2446,7 +2446,8 @@ static int check_mount_destination(const char *rootfs, const char *dest) + } + + for(invalid = invalid_destinations; *invalid != NULL; invalid++) { +- char *fullpath, *relpath; ++ char *fullpath = NULL; ++ char *relpath = NULL; + const char *parts[3] = { + rootfs, + *invalid, +@@ -2588,6 +2589,8 @@ retry: + max_retry--; + DEBUG("mount entry with loop dev failed, retry mount." + "retry count left %d", max_retry); ++ if (loop.lofd != -1) ++ close(loop.lofd); + goto retry; + } + } +@@ -2799,7 +2802,9 @@ static int mount_file_entries(const struct lxc_conf *conf, + ret = mount_entry_on_absolute_rootfs(&mntent, rootfs, + lxc_name, lxc_path); + free(mntent.mnt_fsname); ++ mntent.mnt_fsname = NULL; + free(mntent.mnt_dir); ++ mntent.mnt_dir = NULL; + if (ret < 0) + return -1; + } +@@ -4378,8 +4383,9 @@ int lxc_drop_caps(struct lxc_conf *conf) + int ret = 0; + struct lxc_list *iterator = NULL; + char *keep_entry = NULL; +- int i, capid; +- int numcaps = lxc_caps_last_cap() + 1; ++ size_t i = 0; ++ int capid; ++ size_t numcaps = (size_t)lxc_caps_last_cap() + 1; + struct lxc_list *caps = NULL; + int *caplist = NULL; + +@@ -4545,6 +4551,10 @@ static char **merge_ocihook_env(char **oldenvs, size_t env_len, size_t *merge_en + for(j = 0; j < (sizeof(lxc_envs) / sizeof(char *)); j++) { + tmpenv = getenv(lxc_envs[j]); + if (tmpenv && i < (result_len - 1)) { ++ if (strlen(tmpenv) > (SIZE_MAX - 1 - 1 - strlen(lxc_envs[j]))) { ++ lxc_free_array((void **)result, free); ++ return NULL; ++ } + lxcenv_buf = malloc(strlen(tmpenv) + 1 + strlen(lxc_envs[j]) + 1); + if (!lxcenv_buf) { + lxc_free_array((void **)result, free); +@@ -4837,7 +4847,7 @@ static int run_ocihook_script_argv(const char *name, const char *section, + { + int ret; + const char *script = oconf->ocihook->path; +- char *inmsg; ++ char *inmsg = NULL; + + INFO("Executing script \"%s\" for container \"%s\", config section \"%s\".", + script, name, section); +@@ -4990,7 +5000,7 @@ int run_lxc_hooks(const char *name, char *hookname, struct lxc_conf *conf, + return 0; + } + +-int run_oci_hooks(const char *name, char *hookname, struct lxc_conf *conf, const char *lxcpath) ++int run_oci_hooks(const char *name, const char *hookname, struct lxc_conf *conf, const char *lxcpath) + { + int which = -1; + +@@ -5327,6 +5337,7 @@ int lxc_clear_init_args(struct lxc_conf *lxc_conf) + int lxc_clear_init_groups(struct lxc_conf *lxc_conf) + { + free(lxc_conf->init_groups); ++ lxc_conf->init_groups = NULL; + lxc_conf->init_groups_len = 0; + + return 0; +diff --git a/src/lxc/conf.h b/src/lxc/conf.h +index 26bb70f..e4bfc48 100644 +--- a/src/lxc/conf.h ++++ b/src/lxc/conf.h +@@ -445,7 +445,7 @@ extern struct lxc_conf *current_config; + + extern int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf, + char *argv[]); +-extern int run_oci_hooks(const char *name, char *hookname, struct lxc_conf *conf, const char *lxcpath); ++extern int run_oci_hooks(const char *name, const char *hookname, struct lxc_conf *conf, const char *lxcpath); + + extern int detect_shared_rootfs(void); + extern struct lxc_conf *lxc_conf_init(void); +-- +1.8.3.1 + diff --git a/0104-lxc-fix-code-error.patch b/0104-lxc-fix-code-error.patch new file mode 100644 index 0000000..2e518a7 --- /dev/null +++ b/0104-lxc-fix-code-error.patch @@ -0,0 +1,179 @@ +From 6068ac0d2ac11c158749ffda00135cf5325207fe Mon Sep 17 00:00:00 2001 +From: tanyifeng +Date: Mon, 3 Jun 2019 11:27:34 -0400 +Subject: [PATCH 104/122] lxc: fix code error + +Signed-off-by: tanyifeng +Signed-off-by: LiFeng +--- + src/lxc/af_unix.c | 8 +++++++- + src/lxc/cgroups/cgfsng.c | 10 +++++++++- + src/lxc/lxccontainer.c | 2 ++ + src/lxc/path.c | 1 + + src/lxc/terminal.c | 16 ++++++++-------- + src/lxc/utils.c | 8 ++++---- + 6 files changed, 31 insertions(+), 14 deletions(-) + +diff --git a/src/lxc/af_unix.c b/src/lxc/af_unix.c +index 4c45946..1fc8ab0 100644 +--- a/src/lxc/af_unix.c ++++ b/src/lxc/af_unix.c +@@ -204,12 +204,18 @@ int lxc_abstract_unix_recv_fds_timeout(int fd, int *recvfds, int num_recvfds, + struct cmsghdr *cmsg = NULL; + char buf[1] = {0}; + char *cmsgbuf = NULL; +- size_t cmsgbufsize = CMSG_SPACE(num_recvfds * sizeof(int)); ++ size_t cmsgbufsize = 0; + struct timeval out; + + memset(&msg, 0, sizeof(msg)); + memset(&iov, 0, sizeof(iov)); + ++ if (num_recvfds <= 0 || (SIZE_MAX / sizeof(int) < num_recvfds)) { ++ errno = EINVAL; ++ return -1; ++ } ++ ++ cmsgbufsize = CMSG_SPACE((num_recvfds * sizeof(int))); + cmsgbuf = malloc(cmsgbufsize); + if (!cmsgbuf) { + errno = ENOMEM; +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index 67c7a0e..46f13f4 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -1688,7 +1688,7 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, + if (merged) { + char **mc = NULL; + for (mc = merged; *mc; mc++) { +- char *token; ++ char *token = NULL; + char *copy = must_copy_string(*mc); + lxc_iterate_parts(token, copy, ",") { + int mret; +@@ -2249,7 +2249,15 @@ static int cg_legacy_get_data(struct cgroup_ops *ops, const char *filename, + char *controller = NULL; + + len = strlen(filename); ++ if (SIZE_MAX - 1 < len) { ++ errno = EINVAL; ++ return -1; ++ } + controller = calloc(1, len + 1); ++ if (controller == NULL) { ++ errno = ENOMEM; ++ return -1; ++ } + (void)strlcpy(controller, filename, len + 1); + + p = strchr(controller, '.'); +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index e32f524..72417ed 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -1208,6 +1208,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a + reboot: + if (conf->reboot == REBOOT_INIT) { + /* initialize handler */ ++ lxc_free_handler(handler); + handler = lxc_init_handler(c->name, conf, c->config_path, c->daemonize); + if (!handler) { + ret = 1; +@@ -1248,6 +1249,7 @@ reboot: + conf->reboot = REBOOT_INIT; + goto reboot; + } ++ lxc_free_handler(handler); + + on_error: + if (c->pidfile) { +diff --git a/src/lxc/path.c b/src/lxc/path.c +index 92692de..36d5e0b 100644 +--- a/src/lxc/path.c ++++ b/src/lxc/path.c +@@ -31,6 +31,7 @@ bool specify_current_dir(const char *path) + + bname = basename(basec); + if (bname == NULL) { ++ free(basec); + ERROR("Out of memory"); + return false; + } +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index 802bf39..a8a0dc9 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -231,7 +231,7 @@ static int lxc_terminal_truncate_log_file(struct lxc_terminal *terminal) + } + + /* +- * isuald: support mult-logfiles ++ * isulad: support mult-logfiles + * */ + static int lxc_terminal_rename_old_log_file(struct lxc_terminal *terminal) + { +@@ -242,10 +242,10 @@ static int lxc_terminal_rename_old_log_file(struct lxc_terminal *terminal) + + for (i = terminal->log_rotate - 1; i > 1; i--) { + ret = sprintf(tmp, "%s.%u", terminal->log_path, i); +- if (ret < 0) ++ if (ret < 0) { + return -EFBIG; +- if (rename_fname) +- free(rename_fname); ++ } ++ free(rename_fname); + rename_fname = strdup(tmp); + ret = sprintf(tmp, "%s.%u", terminal->log_path, (i - 1)); + if (ret < 0) { +@@ -253,13 +253,13 @@ static int lxc_terminal_rename_old_log_file(struct lxc_terminal *terminal) + return -EFBIG; + } + ret = lxc_unpriv(rename(tmp, rename_fname)); +- if (ret < 0 && errno != ENOENT) ++ if (ret < 0 && errno != ENOENT) { ++ free(rename_fname); + return ret; ++ } + } + +- if (rename_fname) +- free(rename_fname); +- ++ free(rename_fname); + return 0; + } + +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index e674947..9db762f 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -1769,11 +1769,11 @@ int fd_cloexec(int fd, bool cloexec) + /* isulad: fd_nonblock */ + int fd_nonblock(int fd) + { +- long flags; ++ int flags; + + flags = fcntl(fd, F_GETFL); + +- return fcntl(fd, F_SETFL, flags | O_NONBLOCK); ++ return fcntl(fd, F_SETFL, (int)((unsigned int)flags | O_NONBLOCK)); + } + + int recursive_destroy(char *dirname) +@@ -2140,9 +2140,9 @@ int lxc_open(const char *filename, int flags, mode_t mode) + return -1; + } + if (mode) { +- return open(rpath, flags | O_CLOEXEC, mode); ++ return open(rpath, (int)((unsigned int)flags | O_CLOEXEC), mode); + } else { +- return open(rpath, flags | O_CLOEXEC); ++ return open(rpath, (int)((unsigned int)flags | O_CLOEXEC)); + } + } + +-- +1.8.3.1 + diff --git a/0105-lxc-fix-code-error-warnings.patch b/0105-lxc-fix-code-error-warnings.patch new file mode 100644 index 0000000..a7f9bf5 --- /dev/null +++ b/0105-lxc-fix-code-error-warnings.patch @@ -0,0 +1,74 @@ +From 2ec27dbac6d9e6e9b6aafb7eef205d4e89e2950e Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Mon, 3 Jun 2019 23:02:50 -0400 +Subject: [PATCH 105/122] lxc: fix code error warnings + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 5 ++++- + src/lxc/lxccontainer.c | 3 +-- + src/lxc/start.c | 2 +- + 3 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 127ef77..8311723 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -5325,9 +5325,12 @@ int lxc_clear_init_args(struct lxc_conf *lxc_conf) + { + int i; + +- for (i = 0; i < lxc_conf->init_argc; i++) ++ for (i = 0; i < lxc_conf->init_argc; i++) { + free(lxc_conf->init_argv[i]); ++ lxc_conf->init_argv[i] = NULL; ++ } + free(lxc_conf->init_argv); ++ lxc_conf->init_argv = NULL; + lxc_conf->init_argc = 0; + + return 0; +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index 72417ed..a09e066 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -1180,6 +1180,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a + if (conf->exit_fd < 0) { + ERROR("Failed to open exit fifo %s: %s.", c->exit_fifo, strerror(errno)); + ret = 1; ++ lxc_free_handler(handler); + goto on_error; + } + } +@@ -1208,7 +1209,6 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a + reboot: + if (conf->reboot == REBOOT_INIT) { + /* initialize handler */ +- lxc_free_handler(handler); + handler = lxc_init_handler(c->name, conf, c->config_path, c->daemonize); + if (!handler) { + ret = 1; +@@ -1249,7 +1249,6 @@ reboot: + conf->reboot = REBOOT_INIT; + goto reboot; + } +- lxc_free_handler(handler); + + on_error: + if (c->pidfile) { +diff --git a/src/lxc/start.c b/src/lxc/start.c +index ccdd844..2380581 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -2421,7 +2421,7 @@ int __lxc_start(const char *name, struct lxc_handler *handler, + ret = lxc_init(name, handler); + if (ret < 0) { + ERROR("Failed to initialize container \"%s\"", name); +- return -1; ++ goto out_fini_nonet; + } + handler->ops = ops; + handler->data = data; +-- +1.8.3.1 + diff --git a/0106-set-timeout-to-1s-for-cmds-send-to-lxc-monitor.patch b/0106-set-timeout-to-1s-for-cmds-send-to-lxc-monitor.patch new file mode 100644 index 0000000..84ebf12 --- /dev/null +++ b/0106-set-timeout-to-1s-for-cmds-send-to-lxc-monitor.patch @@ -0,0 +1,31 @@ +From b3df22c4905ca0ad208643a015e01405ae395cdb Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Thu, 6 Jun 2019 22:48:38 -0400 +Subject: [PATCH 106/122] set timeout to 1s for cmds send to [lxc monitor] + +Signed-off-by: LiFeng +--- + src/lxc/commands.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/lxc/commands.c b/src/lxc/commands.c +index c74b8c1..0802a16 100644 +--- a/src/lxc/commands.c ++++ b/src/lxc/commands.c +@@ -127,10 +127,10 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd) + int ret, rspfd; + struct lxc_cmd_rsp *rsp = &cmd->rsp; + +- /*isulad: add timeout 200ms to avoid long block due to [lxc monitor] error*/ +- ret = lxc_abstract_unix_recv_fds_timeout(sock, &rspfd, 1, rsp, sizeof(*rsp), 200 * 1000); ++ /*isulad: add timeout 1s to avoid long block due to [lxc monitor] error*/ ++ ret = lxc_abstract_unix_recv_fds_timeout(sock, &rspfd, 1, rsp, sizeof(*rsp), 1000 * 1000); + if (ret < 0) { +- SYSWARN("Failed to receive response for command \"%s\"", ++ SYSERROR("Failed to receive response for command \"%s\"", + lxc_cmd_str(cmd->req.cmd)); + + if (errno == ECONNRESET || errno == EAGAIN || errno == EWOULDBLOCK) { +-- +1.8.3.1 + diff --git a/0107-add-log-for-failure-of-rename-file.patch b/0107-add-log-for-failure-of-rename-file.patch new file mode 100644 index 0000000..040184f --- /dev/null +++ b/0107-add-log-for-failure-of-rename-file.patch @@ -0,0 +1,33 @@ +From a3e02850527e08f396f8050c41afdd5f23d836b8 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Mon, 17 Jun 2019 20:17:37 +0800 +Subject: [PATCH 107/122] add log for failure of rename file + +1. add log message of rename operator +2. if rename console file failed, reopen terminal fd + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + src/lxc/terminal.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index a8a0dc9..778a0ab 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -293,8 +293,9 @@ static int lxc_terminal_rotate_log_file(struct lxc_terminal *terminal) + close(terminal->log_fd); + terminal->log_fd = -1; + ret = lxc_unpriv(rename(terminal->log_path, tmp)); +- if (ret < 0) +- return ret; ++ if (ret < 0) { ++ SYSERROR("Rename container log file failed"); ++ } + + return lxc_terminal_create_log_file(terminal); + } +-- +1.8.3.1 + diff --git a/0108-check-calloc-input-valid.patch b/0108-check-calloc-input-valid.patch new file mode 100644 index 0000000..612c5aa --- /dev/null +++ b/0108-check-calloc-input-valid.patch @@ -0,0 +1,33 @@ +From 6c12aebb600013e2eb8b970be51bff4d4bed6fb6 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Tue, 18 Jun 2019 23:16:09 +0800 +Subject: [PATCH 108/122] check calloc input valid + +check calloc input valid + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + src/lxc/terminal.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index 778a0ab..6b117de 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -444,8 +444,11 @@ static ssize_t lxc_logger_write(struct lxc_terminal *terminal, const char *type, + parser_error err = NULL; + struct parser_context ctx = { GEN_OPTIONS_SIMPLIFY | GEN_OPTIONS_NOT_VALIDATE_UTF8, stderr }; + ++ if (bytes_read < 0 || bytes_read >= INT_MAX) { ++ return -1; ++ } + msg = calloc(sizeof(logger_json_file), 1); +- if (!msg) { ++ if (msg == NULL) { + return -errno; + } + msg->log = calloc(bytes_read, 1); +-- +1.8.3.1 + diff --git a/0109-add-secure-compile-flags-to-lxc.patch b/0109-add-secure-compile-flags-to-lxc.patch new file mode 100644 index 0000000..ebf2bb1 --- /dev/null +++ b/0109-add-secure-compile-flags-to-lxc.patch @@ -0,0 +1,104 @@ +From f6b39a07c8622c65bf10f484a455ba79f53b15f7 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Thu, 20 Jun 2019 17:46:40 +0800 +Subject: [PATCH 109/122] add secure compile flags to lxc + +add secure compile flags to lxc + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + configure.ac | 25 +++++++++++++++++++------ + src/lxc/Makefile.am | 5 +++++ + 2 files changed, 24 insertions(+), 6 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 4da52a2..a714779 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -44,6 +44,7 @@ AM_INIT_AUTOMAKE([-Wall -Werror -Wno-portability subdir-objects]) + AC_CANONICAL_HOST + AM_PROG_CC_C_O + AC_GNU_SOURCE ++CFLAGS=`echo "${CFLAGS#\-g}"` + + # Test if we have a new enough compiler. + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +@@ -192,6 +193,11 @@ AC_ARG_ENABLE([werror], + [do not treat warnings as errors])], + [], [enable_werror=yes]) + ++AC_ARG_ENABLE([debug], ++ [AC_HELP_STRING([--enable-debug], ++ [set -g into cflags [default=no]])], ++ [], [enable_debug=no]) ++ + # Allow disabling rpath + AC_ARG_ENABLE([rpath], + [AC_HELP_STRING([--enable-rpath], [set rpath in executables [default=no]])], +@@ -200,8 +206,8 @@ AM_CONDITIONAL([ENABLE_RPATH], [test "x$enable_rpath" = "xyes"]) + + # Documentation (manpages) + AC_ARG_ENABLE([doc], +- [AC_HELP_STRING([--enable-doc], [make man pages [default=auto]])], +- [], [enable_doc=auto]) ++ [AC_HELP_STRING([--enable-doc], [make man pages [default=no]])], ++ [], [enable_doc=no]) + + if test "x$enable_doc" = "xyes" -o "x$enable_doc" = "xauto"; then + db2xman="" +@@ -692,18 +698,25 @@ AX_CHECK_COMPILE_FLAG([-Wstrict-prototypes], [CFLAGS="$CFLAGS -Wstrict-prototype + AX_CHECK_COMPILE_FLAG([-fno-strict-aliasing], [CFLAGS="$CFLAGS -fno-strict-aliasing"],,[-Werror]) + AX_CHECK_COMPILE_FLAG([-fstack-clash-protection], [CFLAGS="$CFLAGS -fstack-clash-protection"],,[-Werror]) + AX_CHECK_COMPILE_FLAG([-fstack-protector-strong], [CFLAGS="$CFLAGS -fstack-protector-strong"],,[-Werror]) +-AX_CHECK_COMPILE_FLAG([-g], [CFLAGS="$CFLAGS -g"],,[-Werror]) + AX_CHECK_COMPILE_FLAG([--mcet -fcf-protection], [CFLAGS="$CFLAGS --mcet -fcf-protection"],,[-Werror]) + AX_CHECK_COMPILE_FLAG([-Werror=implicit-function-declaration], [CFLAGS="$CFLAGS -Werror=implicit-function-declaration"],,[-Werror]) + +-AX_CHECK_LINK_FLAG([-z relro], [LDLAGS="$LDLAGS -z relro"],,[]) +-AX_CHECK_LINK_FLAG([-z now], [LDLAGS="$LDLAGS -z now"],,[]) + +-CFLAGS="$CFLAGS -Wvla -std=gnu11" ++AX_CHECK_LINK_FLAG([-z relro], [LDFLAGS="$LDFLAGS -z relro"],,[]) ++AX_CHECK_LINK_FLAG([-z now], [LDFLAGS="$LDFLAGS -z now"],,[]) ++AX_CHECK_LINK_FLAG([-z noexecstack], [LDFLAGS="$LDFLAGS -z noexecstack"],,[]) ++ ++LDFLAGS="$LDFLAGS -fPIE -pie" ++ ++CFLAGS="$CFLAGS -Wvla -std=gnu11 -D_FORTIFY_SOURCE=2 -Wall -fPIC -fPIE -pie" + if test "x$enable_werror" = "xyes"; then + CFLAGS="$CFLAGS -Werror" + fi + ++if test "x$enable_debug" = "xyes"; then ++ CFLAGS="$CFLAGS -g" ++fi ++ + AC_ARG_ENABLE([thread-safety], + [AC_HELP_STRING([--enable-thread-safety], [enforce thread-safety otherwise fail the build [default=yes]])], + [], [enable_thread_safety=yes]) +diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am +index 4ec2081..b24fcfd 100644 +--- a/src/lxc/Makefile.am ++++ b/src/lxc/Makefile.am +@@ -233,12 +233,17 @@ endif + + # build the shared library + liblxc_la_CFLAGS = -fPIC \ ++ -fPIE -pie \ + -DPIC \ ++ -D_FORTIFY_SOURCE=2 -Wall \ + $(AM_CFLAGS) \ + -pthread + + liblxc_la_LDFLAGS = -pthread \ + -Wl,-no-undefined \ ++ -Wl,-z,relro \ ++ -Wl,-z,now \ ++ -Wl,-z,noexecstack \ + -Wl,-soname,liblxc.so.$(firstword $(subst ., ,@LXC_ABI@)) \ + -version-info @LXC_ABI_MAJOR@ @YAJL_LIBS@ + +-- +1.8.3.1 + diff --git a/0110-add-doc-for-lxc.patch b/0110-add-doc-for-lxc.patch new file mode 100644 index 0000000..e5fd45e --- /dev/null +++ b/0110-add-doc-for-lxc.patch @@ -0,0 +1,31 @@ +From 4fcbbaad8e41594629cda4694e0f2b4b5850f398 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Fri, 21 Jun 2019 17:20:43 +0800 +Subject: [PATCH 110/122] add doc for lxc + +add doc for lxc + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + configure.ac | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index a714779..5963fab 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -206,8 +206,8 @@ AM_CONDITIONAL([ENABLE_RPATH], [test "x$enable_rpath" = "xyes"]) + + # Documentation (manpages) + AC_ARG_ENABLE([doc], +- [AC_HELP_STRING([--enable-doc], [make man pages [default=no]])], +- [], [enable_doc=no]) ++ [AC_HELP_STRING([--enable-doc], [make man pages [default=auto]])], ++ [], [enable_doc=auto]) + + if test "x$enable_doc" = "xyes" -o "x$enable_doc" = "xauto"; then + db2xman="" +-- +1.8.3.1 + diff --git a/0111-lxc-use-safe_strdup-instead-of-strdup.patch b/0111-lxc-use-safe_strdup-instead-of-strdup.patch new file mode 100644 index 0000000..51187c9 --- /dev/null +++ b/0111-lxc-use-safe_strdup-instead-of-strdup.patch @@ -0,0 +1,752 @@ +From 3c466cfdde64c75addc902f6e367666c18040ac3 Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Wed, 3 Jul 2019 23:41:15 -0400 +Subject: [PATCH 111/122] lxc: use safe_strdup instead of strdup + +Signed-off-by: LiFeng +--- + src/lxc/attach.c | 14 +++++--------- + src/lxc/conf.c | 32 +++++++++---------------------- + src/lxc/confile.c | 32 +++++++++---------------------- + src/lxc/json/defs.c | 1 - + src/lxc/json/json_common.c | 41 ++++++++++++---------------------------- + src/lxc/json/json_common.h | 4 +--- + src/lxc/json/logger_json_file.c | 1 - + src/lxc/json/oci_runtime_hooks.c | 4 ++-- + src/lxc/json/oci_runtime_spec.c | 1 - + src/lxc/lxccontainer.c | 16 +++++++--------- + src/lxc/path.c | 20 +++++--------------- + src/lxc/start.c | 18 +++++++++--------- + src/lxc/terminal.c | 18 +++++++----------- + src/lxc/tools/lxc_attach.c | 4 ++-- + src/lxc/tools/lxc_start.c | 2 +- + src/lxc/utils.c | 16 ++++++++++++++++ + src/lxc/utils.h | 2 ++ + 17 files changed, 87 insertions(+), 139 deletions(-) + +diff --git a/src/lxc/attach.c b/src/lxc/attach.c +index 6480eb9..d7b16e3 100644 +--- a/src/lxc/attach.c ++++ b/src/lxc/attach.c +@@ -1070,15 +1070,15 @@ static int lxc_attach_terminal(struct lxc_conf *conf, + /* isulad: if we pass fifo in option, use them as init fifos */ + if (options->init_fifo[0]) { + free(terminal->init_fifo[0]); +- terminal->init_fifo[0] = strdup(options->init_fifo[0]); ++ terminal->init_fifo[0] = safe_strdup(options->init_fifo[0]); + } + if (options->init_fifo[1]) { + free(terminal->init_fifo[1]); +- terminal->init_fifo[1] = strdup(options->init_fifo[1]); ++ terminal->init_fifo[1] = safe_strdup(options->init_fifo[1]); + } + if (options->init_fifo[2]) { + free(terminal->init_fifo[2]); +- terminal->init_fifo[2] = strdup(options->init_fifo[2]); ++ terminal->init_fifo[2] = safe_strdup(options->init_fifo[2]); + } + + ret = lxc_terminal_create(terminal); +@@ -1562,9 +1562,7 @@ int lxc_attach(const char *name, const char *lxcpath, + size_read = read(conf->errpipe[0], errbuf, BUFSIZ); + if (size_read > 0) { + if (err_msg) +- *err_msg = strdup(errbuf); +- if (!(*err_msg)) +- ERROR("Out of memory"); ++ *err_msg = safe_strdup(errbuf); + goto close_mainloop; + } + +@@ -1585,9 +1583,7 @@ int lxc_attach(const char *name, const char *lxcpath, + } + + if (g_attach_timeout_state == ATTACH_TIMEOUT && err_msg != NULL && *err_msg == NULL) { +- *err_msg = strdup("Attach exceeded timeout"); +- if (!(*err_msg)) +- ERROR("Out of memory"); ++ *err_msg = safe_strdup("Attach exceeded timeout"); + } + close_mainloop: + if (options->attach_flags & LXC_ATTACH_TERMINAL) +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 8311723..1dfdaf3 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -1356,9 +1356,7 @@ static int rootfs_parent_mount_private(char *rootfs) + target = get_field(line, 4); + if (!target) + continue; +- tmptarget = strdup(target); +- if (!tmptarget) +- continue; ++ tmptarget = safe_strdup(target); + null_endofword(tmptarget); + if (!strstr(rootfs, tmptarget)) { + free(tmptarget); +@@ -1376,9 +1374,7 @@ static int rootfs_parent_mount_private(char *rootfs) + continue; + null_endofword(opts); + free(options); +- options = strdup(opts); +- if (!options) +- continue; ++ options = safe_strdup(opts); + } + + if (!parent || !options) { +@@ -1417,7 +1413,7 @@ static int lxc_mount_rootfs(struct lxc_conf *conf) + + // isulad: bind mount / to rootfs.mount. then we can do pivot root even if we use / as root. + if (!access(rootfs->mount, F_OK)) { +- rootfs->path = strdup("/"); ++ rootfs->path = safe_strdup("/"); + if (mount("/", rootfs->mount, NULL, MS_BIND, 0)) { + SYSERROR("Failed to mount / to %s.", rootfs->mount); + return -1; +@@ -2225,9 +2221,7 @@ int parse_mntopts(const char *mntopts, unsigned long *mntflags, unsigned long *p + if (!mntopts) + return 0; + +- s = strdup(mntopts); +- if (!s) +- return -1; ++ s = safe_strdup(mntopts); + + size = strlen(s) + 1; + data = malloc(size); +@@ -4026,7 +4020,7 @@ static int setup_populate_devs(const struct lxc_rootfs *rootfs, struct lxc_list + return -1; + + /* create any missing directories */ +- pathdirname = strdup(path); ++ pathdirname = safe_strdup(path); + pathdirname = dirname(pathdirname); + ret = mkdir_p(pathdirname, 0750); + free(pathdirname); +@@ -4545,7 +4539,7 @@ static char **merge_ocihook_env(char **oldenvs, size_t env_len, size_t *merge_en + + for(i = 0; i < env_len; i++) { + if (oldenvs[i]) +- result[i] = strdup(oldenvs[i]); ++ result[i] = safe_strdup(oldenvs[i]); + } + + for(j = 0; j < (sizeof(lxc_envs) / sizeof(char *)); j++) { +@@ -4869,7 +4863,7 @@ static char *get_root_path(const char *path, const char *backend) + char *tmp = NULL; + + if (!path) { +- ret = strdup("/"); ++ ret = safe_strdup("/"); + return ret; + } + if (!backend) { +@@ -4885,20 +4879,12 @@ static char *get_root_path(const char *path, const char *backend) + return NULL; + } + tmp++; +- ret = strdup(tmp); +- if (!ret) { +- ERROR("Out of memory"); +- return NULL; +- } ++ ret = safe_strdup(tmp); + return ret; + } + + default_out: +- ret = strdup(path); +- if (!ret) { +- ERROR("Out of memory"); +- return NULL; +- } ++ ret = safe_strdup(path); + return ret; + } + +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index 216a688..8262d1e 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -1011,9 +1011,7 @@ static int set_config_group(const char *key, const char *value, + if (lxc_config_value_empty(value)) + return lxc_clear_groups(lxc_conf); + +- groups = strdup(value); +- if (!groups) +- return -1; ++ groups = safe_strdup(value); + + /* In case several groups are specified in a single line split these + * groups in a single element for the list. +@@ -2281,7 +2279,7 @@ static int set_config_populate_device(const char *key, const char *value, + int ret = 0, major = 0, minor = 0; + uid_t uid = (uid_t)-1; + gid_t gid = (gid_t)-1; +- char name[PATH_MAX] = {0}; ++ char name[4096] = {0}; /* MAX dev path name */ + char type[3] = {0}; + char *replace_value = NULL; + mode_t filemode = 0; +@@ -2295,7 +2293,7 @@ static int set_config_populate_device(const char *key, const char *value, + /* lxc.populate.device = PATH_IN_CONTAINER:DEVICETYPE:MAJOR:MINOR:MODE:UID:GID + * For e.g. lxc.populate.device = /dev/sda:b:8:0:0666:0:0 + */ +- ret = sscanf(value, "%[^:]:%2[^:]:%i:%i:%i:%u:%u", name, type, &major, &minor, &filemode, &uid, &gid); ++ ret = sscanf(value, "%4095[^:]:%2[^:]:%i:%i:%i:%u:%u", name, type, &major, &minor, &filemode, &uid, &gid); + if (ret != 7) + return -1; + +@@ -2306,9 +2304,7 @@ static int set_config_populate_device(const char *key, const char *value, + if (strcmp(name, dev_elem->name) != 0) + continue; + +- replace_value = strdup(type); +- if (!replace_value) +- return -1; ++ replace_value = safe_strdup(type); + + free(dev_elem->type); + dev_elem->type = replace_value; +@@ -2332,13 +2328,9 @@ static int set_config_populate_device(const char *key, const char *value, + goto on_error; + memset(dev_elem, 0, sizeof(*dev_elem)); + +- dev_elem->name = strdup(name); +- if (!dev_elem->name) +- goto on_error; ++ dev_elem->name = safe_strdup(name); + +- dev_elem->type = strdup(type); +- if (!dev_elem->type) +- goto on_error; ++ dev_elem->type = safe_strdup(type); + + dev_elem->file_mode = filemode; + dev_elem->maj = major; +@@ -2373,10 +2365,7 @@ static int set_config_rootfs_masked_paths(const char *key, const char *value, + if (!list_item) + goto on_error; + +- list_item->elem = strdup(value); +- +- if (!list_item->elem) +- goto on_error; ++ list_item->elem = safe_strdup(value); + + lxc_list_add_tail(&lxc_conf->rootfs.maskedpaths, list_item); + +@@ -2401,10 +2390,7 @@ static int set_config_rootfs_ro_paths(const char *key, const char *value, + if (!list_item) + goto on_error; + +- list_item->elem = strdup(value); +- +- if (!list_item->elem) +- goto on_error; ++ list_item->elem = safe_strdup(value); + + lxc_list_add_tail(&lxc_conf->rootfs.ropaths, list_item); + +@@ -2446,7 +2432,7 @@ static int set_config_systemd(const char *key, const char *value, + ERROR("Empty umask"); + return -1; + } +- lxc_conf->systemd = strdup(value); ++ lxc_conf->systemd = safe_strdup(value); + return 0; + } + +diff --git a/src/lxc/json/defs.c b/src/lxc/json/defs.c +index e7d9a09..8a052a8 100644 +--- a/src/lxc/json/defs.c ++++ b/src/lxc/json/defs.c +@@ -4,7 +4,6 @@ + #endif + #include + #include +-#include "securec.h" + #include "defs.h" + + defs_hook *make_defs_hook(yajl_val tree, struct parser_context *ctx, parser_error *err) { +diff --git a/src/lxc/json/json_common.c b/src/lxc/json/json_common.c +index 54b7b61..bea9b14 100755 +--- a/src/lxc/json/json_common.c ++++ b/src/lxc/json/json_common.c +@@ -381,23 +381,6 @@ int common_safe_int(const char *numstr, int *converted) { + return 0; + } + +-char *safe_strdup(const char *src) +-{ +- char *dst = NULL; +- +- if (src == NULL) { +- return NULL; +- } +- +- dst = strdup(src); +- if (dst == NULL) { +- abort(); +- } +- +- return dst; +-} +- +- + yajl_gen_status gen_json_map_int_int(void *ctx, json_map_int_int *map, struct parser_context *ptx, parser_error *err) { + yajl_gen_status stat = yajl_gen_status_ok; + yajl_gen g = (yajl_gen) ctx; +@@ -522,12 +505,12 @@ int append_json_map_int_int(json_map_int_int *map, int key, int val) { + vals = safe_malloc(len * sizeof(int)); + + if (map->len) { +- if (memcpy(keys, map->keys, map->len * sizeof(int)) != EOK) { ++ if (memcpy(keys, map->keys, map->len * sizeof(int)) != NULL) { + free(keys); + free(vals); + return -1; + } +- if (memcpy(vals, map->values, map->len * sizeof(int)) != EOK) { ++ if (memcpy(vals, map->values, map->len * sizeof(int)) != NULL) { + free(keys); + free(vals); + return -1; +@@ -663,12 +646,12 @@ int append_json_map_int_bool(json_map_int_bool *map, int key, bool val) { + vals = safe_malloc(len * sizeof(bool)); + + if (map->len) { +- if (memcpy(keys, map->keys, map->len * sizeof(int)) != EOK) { ++ if (memcpy(keys, map->keys, map->len * sizeof(int)) != NULL) { + free(keys); + free(vals); + return -1; + } +- if (memcpy(vals, map->values, map->len * sizeof(bool)) != EOK) { ++ if (memcpy(vals, map->values, map->len * sizeof(bool)) != NULL) { + free(keys); + free(vals); + return -1; +@@ -803,12 +786,12 @@ int append_json_map_int_string(json_map_int_string *map, int key, const char *va + vals = safe_malloc(len * sizeof(char *)); + + if (map->len) { +- if (memcpy(keys, map->keys, map->len * sizeof(int)) != EOK) { ++ if (memcpy(keys, map->keys, map->len * sizeof(int)) != NULL) { + free(keys); + free(vals); + return -1; + } +- if (memcpy(vals, map->values, map->len * sizeof(char *)) != EOK) { ++ if (memcpy(vals, map->values, map->len * sizeof(char *)) != NULL) { + free(keys); + free(vals); + return -1; +@@ -930,12 +913,12 @@ int append_json_map_string_int(json_map_string_int *map, const char *key, int va + vals = safe_malloc(len * sizeof(int)); + + if (map->len) { +- if (memcpy(keys, map->keys, map->len * sizeof(char *)) != EOK) { ++ if (memcpy(keys, map->keys, map->len * sizeof(char *)) != NULL) { + free(keys); + free(vals); + return -1; + } +- if (memcpy(vals, map->values, map->len * sizeof(int)) != EOK) { ++ if (memcpy(vals, map->values, map->len * sizeof(int)) != NULL) { + free(keys); + free(vals); + return -1; +@@ -1052,12 +1035,12 @@ int append_json_map_string_bool(json_map_string_bool *map, const char *key, bool + vals = safe_malloc(len * sizeof(bool)); + + if (map->len) { +- if (memcpy(keys, map->keys, map->len * sizeof(char *)) != EOK) { ++ if (memcpy(keys, map->keys, map->len * sizeof(char *)) != NULL) { + free(keys); + free(vals); + return -1; + } +- if (memcpy(vals, map->values, map->len * sizeof(bool)) != EOK) { ++ if (memcpy(vals, map->values, map->len * sizeof(bool)) != NULL) { + free(keys); + free(vals); + return -1; +@@ -1181,12 +1164,12 @@ int append_json_map_string_string(json_map_string_string *map, const char *key, + vals = safe_malloc(len * sizeof(char *)); + + if (map->len) { +- if (memcpy(keys, map->keys, map->len * sizeof(char *)) != EOK) { ++ if (memcpy(keys, map->keys, map->len * sizeof(char *)) != NULL) { + free(keys); + free(vals); + return -1; + } +- if (memcpy(vals, map->values, map->len * sizeof(char *)) != EOK) { ++ if (memcpy(vals, map->values, map->len * sizeof(char *)) != NULL) { + free(keys); + free(vals); + return -1; +diff --git a/src/lxc/json/json_common.h b/src/lxc/json/json_common.h +index 218a837..60aa5fd 100755 +--- a/src/lxc/json/json_common.h ++++ b/src/lxc/json/json_common.h +@@ -9,7 +9,7 @@ + #include + #include + #include +-#include "securec.h" ++#include "utils.h" + + #ifdef __cplusplus + extern "C" { +@@ -94,8 +94,6 @@ int common_safe_int64(const char *numstr, int64_t *converted); + + int common_safe_int(const char *numstr, int *converted); + +-char *safe_strdup(const char *src); +- + typedef struct { + int *keys; + int *values; +diff --git a/src/lxc/json/logger_json_file.c b/src/lxc/json/logger_json_file.c +index 409ea11..842d35b 100644 +--- a/src/lxc/json/logger_json_file.c ++++ b/src/lxc/json/logger_json_file.c +@@ -4,7 +4,6 @@ + #endif + #include + #include +-#include "securec.h" + #include "logger_json_file.h" + + logger_json_file *make_logger_json_file(yajl_val tree, struct parser_context *ctx, parser_error *err) { +diff --git a/src/lxc/json/oci_runtime_hooks.c b/src/lxc/json/oci_runtime_hooks.c +index 43ff8d7..41ddb67 100644 +--- a/src/lxc/json/oci_runtime_hooks.c ++++ b/src/lxc/json/oci_runtime_hooks.c +@@ -34,7 +34,7 @@ oci_runtime_spec_hooks *oci_runtime_spec_hooks_parse_file(const char *filename, + char errbuf[PARSE_ERR_BUFFER_SIZE]; + if (content == NULL) { + if (asprintf(err, "cannot read the file: %s", filename) < 0) { +- *err = strdup("error allocating memory"); ++ *err = safe_strdup("error allocating memory"); + } + return NULL; + } +@@ -42,7 +42,7 @@ oci_runtime_spec_hooks *oci_runtime_spec_hooks_parse_file(const char *filename, + free(content); + if (tree == NULL) { + if (asprintf(err, "cannot parse the file: %s", errbuf) < 0) { +- *err = strdup("error allocating memory"); ++ *err = safe_strdup("error allocating memory"); + } + return NULL; + } +diff --git a/src/lxc/json/oci_runtime_spec.c b/src/lxc/json/oci_runtime_spec.c +index 4ccb635..fd342de 100644 +--- a/src/lxc/json/oci_runtime_spec.c ++++ b/src/lxc/json/oci_runtime_spec.c +@@ -4,7 +4,6 @@ + #endif + #include + #include +-#include "securec.h" + #include "oci_runtime_spec.h" + + oci_runtime_spec_hooks *make_oci_runtime_spec_hooks(yajl_val tree, struct parser_context *ctx, parser_error *err) { +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index a09e066..ede4c88 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -1055,9 +1055,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a + if (!started) { + size_read = read(conf->errpipe[0], errbuf, BUFSIZ); + if (size_read > 0) { +- conf->errmsg = strdup(errbuf); +- if (!conf->errmsg) +- ERROR("Out of memory"); ++ conf->errmsg = safe_strdup(errbuf); + } + } + close(conf->errpipe[0]); +@@ -3199,7 +3197,7 @@ static bool container_destroy(struct lxc_container *c, + ERROR("Failed to destroy directory \"%s\" for \"%s\"", path, + c->name); + sprintf(msg, "Failed to destroy directory \"%s\": %s", path, errno ? strerror(errno) : "error"); +- c->error_string = strdup(msg); ++ c->error_string = safe_strdup(msg); + goto out; + } + INFO("Destroyed directory \"%s\" for \"%s\"", path, c->name); +@@ -5147,17 +5145,17 @@ static bool do_lxcapi_set_terminal_default_fifos(struct lxc_container *c, const + if (in) { + if (conf->console.init_fifo[0]) + free(conf->console.init_fifo[0]); +- conf->console.init_fifo[0] = strdup(in); ++ conf->console.init_fifo[0] = safe_strdup(in); + } + if (out) { + if (conf->console.init_fifo[1]) + free(conf->console.init_fifo[1]); +- conf->console.init_fifo[1] = strdup(out); ++ conf->console.init_fifo[1] = safe_strdup(out); + } + if (err) { + if (conf->console.init_fifo[2]) + free(conf->console.init_fifo[2]); +- conf->console.init_fifo[2] = strdup(err); ++ conf->console.init_fifo[2] = safe_strdup(err); + } + + container_mem_unlock(c); +@@ -5181,7 +5179,7 @@ static bool do_lxcapi_set_container_info_file(struct lxc_container *c, const cha + conf = c->lxc_conf; + if (conf->container_info_file) + free(conf->container_info_file); +- conf->container_info_file = strdup(info_file); ++ conf->container_info_file = safe_strdup(info_file); + + container_mem_unlock(c); + return true; +@@ -5347,7 +5345,7 @@ static struct lxc_container *do_lxc_container_new(const char *name, const char * + fprintf(stderr, "Failed to get lxc path for %s\n", name); + goto err; + } +- c->config_path = strdup(tmp); ++ c->config_path = safe_strdup(tmp); + } + if (!c->config_path) { + fprintf(stderr, "Failed to allocate memory for %s\n", name); +diff --git a/src/lxc/path.c b/src/lxc/path.c +index 36d5e0b..c545887 100644 +--- a/src/lxc/path.c ++++ b/src/lxc/path.c +@@ -23,11 +23,7 @@ bool specify_current_dir(const char *path) + char *basec = NULL, *bname = NULL; + bool res = false; + +- basec = strdup(path); +- if (!basec) { +- ERROR("Out of memory"); +- return false; +- } ++ basec = safe_strdup(path); + + bname = basename(basec); + if (bname == NULL) { +@@ -106,13 +102,7 @@ bool filepath_split(const char *path, char **dir, char **base) + memcpy(*dir, path, i + 1); + *(*dir + i + 1) = '\0'; + +- *base = strdup(path + i + 1); +- if (!*base) { +- ERROR("Out of memory"); +- free(*dir); +- *dir = NULL; +- return false; +- } ++ *base = safe_strdup(path + i + 1); + + return true; + } +@@ -459,7 +449,7 @@ static char *eval_symlinks_in_scope(const char *fullpath, const char *rootpath) + } + + if (!strcmp(fullpath, root)) { +- return strdup(fullpath); ++ return safe_strdup(fullpath); + } + + if (strstr(fullpath, root) == NULL) { +@@ -592,7 +582,7 @@ char *path_relative(const char *basepath, const char *targpath) + } + + if (strcmp(base, targ) == 0) +- return strdup("."); ++ return safe_strdup("."); + + bl = strlen(base); + tl = strlen(targ); +@@ -646,5 +636,5 @@ char *path_relative(const char *basepath, const char *targpath) + return buf; + } + +- return strdup(targ + t0); ++ return safe_strdup(targ + t0); + } +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 2380581..d6c706e 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -2795,35 +2795,35 @@ static int clean_resource_set_env(struct lxc_handler *handler) + /* Start of environment variable setup for hooks. */ + if (name) { + snprintf(bufstr, PATH_MAX + 1, "LXC_NAME=%s", name); +- conf->ocihooks->poststop[i]->env[j++] = strdup(bufstr); ++ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr); + } + if (conf->rcfile) { + snprintf(bufstr, PATH_MAX + 1, "LXC_CONFIG_FILE=%s", conf->rcfile); +- conf->ocihooks->poststop[i]->env[j++] = strdup(bufstr); ++ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr); + } + if (conf->rootfs.mount) { + snprintf(bufstr, PATH_MAX + 1, "LXC_ROOTFS_MOUNT=%s", conf->rootfs.mount); +- conf->ocihooks->poststop[i]->env[j++] = strdup(bufstr); ++ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr); + } + if (conf->rootfs.path) { + snprintf(bufstr, PATH_MAX + 1, "LXC_ROOTFS_PATH=%s", conf->rootfs.path); +- conf->ocihooks->poststop[i]->env[j++] = strdup(bufstr); ++ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr); + } + if (conf->console.path) { + snprintf(bufstr, PATH_MAX + 1, "LXC_CONSOLE=%s", conf->console.path); +- conf->ocihooks->poststop[i]->env[j++] = strdup(bufstr); ++ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr); + } + if (conf->console.log_path) { + snprintf(bufstr, PATH_MAX + 1, "LXC_CONSOLE_LOGPATH=%s", conf->console.log_path); +- conf->ocihooks->poststop[i]->env[j++] = strdup(bufstr); ++ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr); + } +- conf->ocihooks->poststop[i]->env[j++] = strdup("LXC_CGNS_AWARE=1"); ++ conf->ocihooks->poststop[i]->env[j++] = safe_strdup("LXC_CGNS_AWARE=1"); + + snprintf(bufstr, PATH_MAX + 1, "LXC_PID=%d", handler->pid); +- conf->ocihooks->poststop[i]->env[j++] = strdup(bufstr); ++ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr); + if (handler->cgroup_ops->container_cgroup) { + snprintf(bufstr, PATH_MAX + 1, "LXC_CGROUP_PATH=%s", handler->cgroup_ops->container_cgroup); +- conf->ocihooks->poststop[i]->env[j++] = strdup(bufstr); ++ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr); + } + conf->ocihooks->poststop[i]->env_len = j; + /* End of environment variable setup for hooks. */ +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index 6b117de..970db69 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -246,7 +246,7 @@ static int lxc_terminal_rename_old_log_file(struct lxc_terminal *terminal) + return -EFBIG; + } + free(rename_fname); +- rename_fname = strdup(tmp); ++ rename_fname = safe_strdup(tmp); + ret = sprintf(tmp, "%s.%u", terminal->log_path, (i - 1)); + if (ret < 0) { + free(rename_fname); +@@ -457,10 +457,10 @@ static ssize_t lxc_logger_write(struct lxc_terminal *terminal, const char *type, + } + memcpy(msg->log, buf, bytes_read); + msg->log_len = bytes_read; +- msg->stream = type ? strdup(type) : strdup("stdout"); ++ msg->stream = type ? safe_strdup(type) : safe_strdup("stdout"); + + get_now_time_buffer(timebuffer, sizeof(timebuffer)); +- msg->time = strdup(timebuffer); ++ msg->time = safe_strdup(timebuffer); + + json = logger_json_file_generate_json(msg, &ctx, &err); + if (!json) { +@@ -1324,9 +1324,9 @@ static int lxc_terminal_set_fifo(struct lxc_terminal *console, const char *in, c + } + memset(fifo_elem, 0, sizeof(*fifo_elem)); + +- fifo_elem->in_fifo = strdup(in ? in : ""); +- fifo_elem->out_fifo = strdup(out ? out : ""); +- fifo_elem->err_fifo = strdup(err ? err : ""); ++ fifo_elem->in_fifo = safe_strdup(in ? in : ""); ++ fifo_elem->out_fifo = safe_strdup(out ? out : ""); ++ fifo_elem->err_fifo = safe_strdup(err ? err : ""); + fifo_elem->in_fd = fifofd_in; + fifo_elem->out_fd = fifofd_out; + fifo_elem->err_fd = fifofd_err; +@@ -1810,11 +1810,7 @@ int lxc_terminal_add_fifos(struct lxc_conf *conf, const char *fifonames) + char *tmp = NULL, *saveptr = NULL, *in = NULL, *out = NULL, *err = NULL; + const char *none_fifo_name = "none"; + +- tmp = strdup(fifonames); +- if (!tmp) { +- ret = -1; +- goto free_out; +- } ++ tmp = safe_strdup(fifonames); + + in = strtok_r(tmp, "&&&&", &saveptr); + if (!in) { +diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c +index 854b3a2..7d51ad7 100644 +--- a/src/lxc/tools/lxc_attach.c ++++ b/src/lxc/tools/lxc_attach.c +@@ -309,7 +309,7 @@ static int do_attach_foreground(struct lxc_container *c, lxc_attach_command_t *c + } + out: + if (c->lxc_conf->errmsg) +- *errmsg = strdup(c->lxc_conf->errmsg); ++ *errmsg = safe_strdup(c->lxc_conf->errmsg); + return wexit; + } + +@@ -353,7 +353,7 @@ static int do_attach_background(struct lxc_container *c, lxc_attach_command_t *c + msgpipe[1] = -1; + size_read = read(msgpipe[0], msgbuf, BUFSIZ); + if (size_read > 0) { +- *errmsg = strdup(msgbuf); ++ *errmsg = safe_strdup(msgbuf); + ret = -1; + } + +diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c +index af63f58..e48e5b3 100644 +--- a/src/lxc/tools/lxc_start.c ++++ b/src/lxc/tools/lxc_start.c +@@ -360,7 +360,7 @@ int main(int argc, char *argv[]) + + /* isulad: fifo used to monitor state of monitor process */ + if (my_args.exit_monitor_fifo != NULL) { +- c->exit_fifo = strdup(my_args.exit_monitor_fifo); ++ c->exit_fifo = safe_strdup(my_args.exit_monitor_fifo); + } + + /* isulad: add start timeout */ +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index 9db762f..e6e8905 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -2157,3 +2157,19 @@ FILE *lxc_fopen(const char *filename, const char *mode) + return fopen_cloexec(rpath, mode); + } + ++char *safe_strdup(const char *src) ++{ ++ char *dst = NULL; ++ ++ if (src == NULL) { ++ return NULL; ++ } ++ ++ dst = strdup(src); ++ if (dst == NULL) { ++ abort(); ++ } ++ ++ return dst; ++} ++ +diff --git a/src/lxc/utils.h b/src/lxc/utils.h +index 2406ee1..0b33f69 100644 +--- a/src/lxc/utils.h ++++ b/src/lxc/utils.h +@@ -328,4 +328,6 @@ extern int lxc_mem_realloc(void **newptr, size_t newsize, void *oldptr, size_t o + extern void *lxc_common_calloc_s(size_t size); + extern int lxc_open(const char *filename, int flags, mode_t mode); + extern FILE *lxc_fopen(const char *filename, const char *mode); ++extern char *safe_strdup(const char *src); ++ + #endif /* __LXC_UTILS_H */ +-- +1.8.3.1 + diff --git a/0112-fix-secure-errors.patch b/0112-fix-secure-errors.patch new file mode 100644 index 0000000..86bd6af --- /dev/null +++ b/0112-fix-secure-errors.patch @@ -0,0 +1,278 @@ +From aa6bea319eb9d86b296589e17219f96f6d0e3ed1 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Thu, 4 Jul 2019 11:08:26 +0800 +Subject: [PATCH 112/122] fix secure errors + +1. use snprintf replace sprintf +2. use malloc replace alloca + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 6 ++++-- + src/lxc/confile.c | 38 ++++++++++++++++++++++++-------------- + src/lxc/json/json_common.c | 12 ++++++------ + src/lxc/lxccontainer.c | 8 ++++++-- + src/lxc/terminal.c | 31 ++++++++++++++++++++++++------- + 5 files changed, 64 insertions(+), 31 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 1dfdaf3..996d267 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4543,18 +4543,20 @@ static char **merge_ocihook_env(char **oldenvs, size_t env_len, size_t *merge_en + } + + for(j = 0; j < (sizeof(lxc_envs) / sizeof(char *)); j++) { ++ size_t env_buf_len = 0; + tmpenv = getenv(lxc_envs[j]); + if (tmpenv && i < (result_len - 1)) { + if (strlen(tmpenv) > (SIZE_MAX - 1 - 1 - strlen(lxc_envs[j]))) { + lxc_free_array((void **)result, free); + return NULL; + } +- lxcenv_buf = malloc(strlen(tmpenv) + 1 + strlen(lxc_envs[j]) + 1); ++ env_buf_len = ((strlen(tmpenv) + 1) + strlen(lxc_envs[j])) + 1; ++ lxcenv_buf = malloc(env_buf_len); + if (!lxcenv_buf) { + lxc_free_array((void **)result, free); + return NULL; + } +- if (sprintf(lxcenv_buf, "%s=%s", lxc_envs[j], tmpenv) < 0) { ++ if (snprintf(lxcenv_buf, env_buf_len, "%s=%s", lxc_envs[j], tmpenv) < 0) { + free(lxcenv_buf); + continue; + } +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index 8262d1e..8a082d5 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -3802,9 +3802,11 @@ static int get_config_no_new_privs(const char *key, char *retv, int inlen, + static int get_config_prlimit(const char *key, char *retv, int inlen, + struct lxc_conf *c, void *data) + { +- int fulllen = 0, len; ++ int fulllen = 0; ++ int len = 0; + bool get_all = false; +- struct lxc_list *it; ++ struct lxc_list *it = NULL; ++ int nret = 0; + + if (!retv) + inlen = 0; +@@ -3818,32 +3820,40 @@ static int get_config_prlimit(const char *key, char *retv, int inlen, + else + return -1; + ++#define MAX_LIMIT_BUF_LEN ((INTTYPE_TO_STRLEN(uint64_t) * 2) + 2) + lxc_list_for_each(it, &c->limits) { + /* 2 colon separated 64 bit integers or the word 'unlimited' */ +- char buf[INTTYPE_TO_STRLEN(uint64_t) * 2 + 2]; ++ char buf[MAX_LIMIT_BUF_LEN] = { 0 }; + int partlen; + struct lxc_limit *lim = it->elem; + + if (lim->limit.rlim_cur == RLIM_INFINITY) { +- memcpy(buf, "unlimited", STRLITERALLEN("unlimited") + 1); ++ if (memcpy(buf, "unlimited", STRLITERALLEN("unlimited") + 1) == NULL) { ++ return -1; ++ } + partlen = STRLITERALLEN("unlimited"); + } else { +- partlen = sprintf(buf, "%" PRIu64, +- (uint64_t)lim->limit.rlim_cur); ++ partlen = snprintf(buf, MAX_LIMIT_BUF_LEN, "%" PRIu64, (uint64_t)lim->limit.rlim_cur); ++ if (partlen < 0) { ++ return -1; ++ } + } + + if (lim->limit.rlim_cur != lim->limit.rlim_max) { +- if (lim->limit.rlim_max == RLIM_INFINITY) +- memcpy(buf + partlen, ":unlimited", +- STRLITERALLEN(":unlimited") + 1); +- else +- sprintf(buf + partlen, ":%" PRIu64, +- (uint64_t)lim->limit.rlim_max); ++ if (lim->limit.rlim_max == RLIM_INFINITY) { ++ if (memcpy(buf + partlen, ":unlimited", STRLITERALLEN(":unlimited") + 1) == NULL) { ++ return -1; ++ } ++ } else { ++ nret = snprintf(buf + partlen, (MAX_LIMIT_BUF_LEN - partlen), ":%" PRIu64, (uint64_t)lim->limit.rlim_max); ++ if (nret < 0) { ++ return -1; ++ } ++ } + } + + if (get_all) { +- strprint(retv, inlen, "lxc.prlimit.%s = %s\n", +- lim->resource, buf); ++ strprint(retv, inlen, "lxc.prlimit.%s = %s\n", lim->resource, buf); + } else if (strcmp(lim->resource, key) == 0) { + strprint(retv, inlen, "%s", buf); + } +diff --git a/src/lxc/json/json_common.c b/src/lxc/json/json_common.c +index bea9b14..5da1e6d 100755 +--- a/src/lxc/json/json_common.c ++++ b/src/lxc/json/json_common.c +@@ -16,7 +16,7 @@ yajl_gen_status reformat_uint(void *ctx, long long unsigned int num) { + char numstr[MAX_NUM_STR_LEN]; + int ret; + +- ret = sprintf(numstr, "%llu", num); ++ ret = snprintf(numstr, MAX_NUM_STR_LEN, "%llu", num); + if (ret < 0) { + return yajl_gen_in_error_state; + } +@@ -27,7 +27,7 @@ yajl_gen_status reformat_int(void *ctx, long long int num) { + char numstr[MAX_NUM_STR_LEN]; + int ret; + +- ret = sprintf(numstr, "%lld", num); ++ ret = snprintf(numstr, MAX_NUM_STR_LEN, "%lld", num); + if (ret < 0) { + return yajl_gen_in_error_state; + } +@@ -399,7 +399,7 @@ yajl_gen_status gen_json_map_int_int(void *ctx, json_map_int_int *map, struct pa + for (i = 0; i < len; i++) { + char numstr[MAX_NUM_STR_LEN]; + int nret; +- nret = sprintf(numstr, "%lld", (long long int)map->keys[i]); ++ nret = snprintf(numstr, MAX_NUM_STR_LEN, "%lld", (long long int)map->keys[i]); + if (nret < 0) { + if (!*err && asprintf(err, "Error to print string") < 0) { + *(err) = safe_strdup("error allocating memory"); +@@ -545,7 +545,7 @@ yajl_gen_status gen_json_map_int_bool(void *ctx, json_map_int_bool *map, struct + for (i = 0; i < len; i++) { + char numstr[MAX_NUM_STR_LEN]; + int nret; +- nret = sprintf(numstr, "%lld", (long long int)map->keys[i]); ++ nret = snprintf(numstr, MAX_NUM_STR_LEN, "%lld", (long long int)map->keys[i]); + if (nret < 0) { + if (!*err && asprintf(err, "Error to print string") < 0) { + *(err) = safe_strdup("error allocating memory"); +@@ -686,7 +686,7 @@ yajl_gen_status gen_json_map_int_string(void *ctx, json_map_int_string *map, str + for (i = 0; i < len; i++) { + char numstr[MAX_NUM_STR_LEN]; + int nret; +- nret = sprintf(numstr, "%lld", (long long int)map->keys[i]); ++ nret = snprintf(numstr, MAX_NUM_STR_LEN, "%lld", (long long int)map->keys[i]); + if (nret < 0) { + if (!*err && asprintf(err, "Error to print string") < 0) { + *(err) = safe_strdup("error allocating memory"); +@@ -1184,4 +1184,4 @@ int append_json_map_string_string(json_map_string_string *map, const char *key, + + map->len++; + return 0; +-} +\ No newline at end of file ++} +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index ede4c88..3b2c5af 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -3196,7 +3196,11 @@ static bool container_destroy(struct lxc_container *c, + char msg[BUFSIZ] = { 0 }; + ERROR("Failed to destroy directory \"%s\" for \"%s\"", path, + c->name); +- sprintf(msg, "Failed to destroy directory \"%s\": %s", path, errno ? strerror(errno) : "error"); ++ ret = snprintf(msg, BUFSIZ, "Failed to destroy directory \"%s\": %s", path, errno ? strerror(errno) : "error"); ++ if (ret < 0) { ++ ERROR("Sprintf failed"); ++ goto out; ++ } + c->error_string = safe_strdup(msg); + goto out; + } +@@ -5278,7 +5282,7 @@ static int set_start_extral_configs(struct lxc_container *c) + return -1; + } + } +- if (sprintf(fpath, "%s/%s/%s", c->config_path, c->name, START_GENERATE_CONFIG) < 0) { ++ if (snprintf(fpath, PATH_MAX, "%s/%s/%s", c->config_path, c->name, START_GENERATE_CONFIG) < 0) { + fprintf(stderr, "Sprintf config path failed\n"); + return -1; + } +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index 970db69..b9b65c6 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -241,13 +241,13 @@ static int lxc_terminal_rename_old_log_file(struct lxc_terminal *terminal) + char *rename_fname = NULL; + + for (i = terminal->log_rotate - 1; i > 1; i--) { +- ret = sprintf(tmp, "%s.%u", terminal->log_path, i); ++ ret = snprintf(tmp, PATH_MAX, "%s.%u", terminal->log_path, i); + if (ret < 0) { + return -EFBIG; + } + free(rename_fname); + rename_fname = safe_strdup(tmp); +- ret = sprintf(tmp, "%s.%u", terminal->log_path, (i - 1)); ++ ret = snprintf(tmp, PATH_MAX, "%s.%u", terminal->log_path, (i - 1)); + if (ret < 0) { + free(rename_fname); + return -EFBIG; +@@ -284,11 +284,21 @@ static int lxc_terminal_rotate_log_file(struct lxc_terminal *terminal) + } + + len = strlen(terminal->log_path) + sizeof(".1"); +- tmp = alloca(len); ++ tmp = malloc(len); ++ if (tmp == NULL) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ if (memset(tmp, 0, len) != NULL) { ++ ERROR("Memset failed"); ++ goto free_out; ++ } + + ret = snprintf(tmp, len, "%s.1", terminal->log_path); +- if (ret < 0 || (size_t)ret >= len) +- return -EFBIG; ++ if (ret < 0 || (size_t)ret >= len) { ++ ret = -EFBIG; ++ goto free_out; ++ } + + close(terminal->log_fd); + terminal->log_fd = -1; +@@ -297,7 +307,10 @@ static int lxc_terminal_rotate_log_file(struct lxc_terminal *terminal) + SYSERROR("Rename container log file failed"); + } + +- return lxc_terminal_create_log_file(terminal); ++ ret = lxc_terminal_create_log_file(terminal); ++free_out: ++ free(tmp); ++ return ret; + } + + static int lxc_terminal_rotate_write_data(struct lxc_terminal *terminal, const char *buf, +@@ -403,6 +416,7 @@ static bool get_time_buffer(struct timespec *timestamp, char *timebuffer, + struct tm tm_utc = { 0 }; + int32_t nanos = 0; + time_t seconds; ++ size_t len = 0; + + if (!timebuffer || !maxsize) { + return false; +@@ -413,7 +427,10 @@ static bool get_time_buffer(struct timespec *timestamp, char *timebuffer, + strftime(timebuffer, maxsize, "%Y-%m-%dT%H:%M:%S", &tm_utc); + + nanos = (int32_t)timestamp->tv_nsec; +- sprintf(timebuffer + strlen(timebuffer), ".%09dZ", nanos); ++ len = strlen(timebuffer); ++ if (snprintf(timebuffer + len, (maxsize - len), ".%09dZ", nanos) < 0) { ++ return false; ++ } + + return true; + } +-- +1.8.3.1 + diff --git a/0113-Malloc-parameter-check-and-judgment.patch b/0113-Malloc-parameter-check-and-judgment.patch new file mode 100644 index 0000000..8416812 --- /dev/null +++ b/0113-Malloc-parameter-check-and-judgment.patch @@ -0,0 +1,575 @@ +From f53063c9edbb851756c4e0af0840a0d81e0b5276 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Thu, 4 Jul 2019 12:08:17 +0800 +Subject: [PATCH 113/122] Malloc parameter check and judgment + +Signed-off-by: wujing +Signed-off-by: LiFeng +--- + src/lxc/attach.c | 2 +- + src/lxc/commands.c | 9 ++- + src/lxc/conf.c | 20 ++++-- + src/lxc/confile.c | 8 +-- + src/lxc/json/container_start_generate_config.c | 12 +++- + src/lxc/json/defs.c | 8 +++ + src/lxc/json/json_common.c | 97 +++++++++----------------- + src/lxc/json/logger_json_file.c | 6 +- + src/lxc/lxccontainer.c | 12 +++- + src/lxc/path.c | 8 ++- + src/lxc/start.c | 6 +- + src/lxc/terminal.c | 2 +- + src/lxc/utils.c | 4 +- + 13 files changed, 104 insertions(+), 90 deletions(-) + +diff --git a/src/lxc/attach.c b/src/lxc/attach.c +index d7b16e3..ac4bd39 100644 +--- a/src/lxc/attach.c ++++ b/src/lxc/attach.c +@@ -1188,7 +1188,7 @@ static int create_attach_timeout_thread(int64_t attach_timeout, pid_t pid) + struct attach_timeout_conf *timeout_conf = NULL; + + timeout_conf = malloc(sizeof(struct attach_timeout_conf)); +- if (!timeout_conf) { ++ if (timeout_conf == NULL) { + ERROR("Failed to malloc attach timeout conf"); + ret = -1; + goto out; +diff --git a/src/lxc/commands.c b/src/lxc/commands.c +index 0802a16..fa02a4b 100644 +--- a/src/lxc/commands.c ++++ b/src/lxc/commands.c +@@ -1075,11 +1075,16 @@ int lxc_cmd_set_terminal_fifos(const char *name, const char *lxcpath, const char + const char *cmd_out_fifo = out_fifo ? out_fifo : none_fifo_name; + const char *cmd_err_fifo = err_fifo ? err_fifo : none_fifo_name; + ++ if (len + strlen(cmd_in_fifo) + strlen(split) + strlen(cmd_out_fifo) + ++ strlen(split) + strlen(cmd_err_fifo) == SIZE_MAX) ++ return -1; + len += strlen(cmd_in_fifo) + strlen(split) + strlen(cmd_out_fifo) + strlen(split) + strlen(cmd_err_fifo) + 1; + tmp = malloc(len); +- if (!tmp) ++ if (tmp == NULL) ++ return -1; ++ ret = snprintf(tmp, len, "%s%s%s%s%s", cmd_in_fifo, split, cmd_out_fifo, split, cmd_err_fifo); ++ if (ret < 0) + return -1; +- snprintf(tmp, len, "%s%s%s%s%s", cmd_in_fifo, split, cmd_out_fifo, split, cmd_err_fifo); + + struct lxc_cmd_rr cmd = { + .req = { +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 996d267..3ecccbd 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4393,7 +4393,11 @@ int lxc_drop_caps(struct lxc_conf *conf) + + // caplist[i] is 1 if we keep capability i + caplist = malloc(numcaps * sizeof(int)); +- memset(caplist, 0, numcaps * sizeof(int)); ++ if (caplist == NULL) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ (void)memset(caplist, 0, numcaps * sizeof(int)); + + lxc_list_for_each(iterator, caps) { + +@@ -4488,8 +4492,8 @@ static char* generate_json_str(const char *name, const char *lxcpath, const char + cpid = "-1"; + } + +- if ((SIZE_MAX - strlen(name) - strlen(cpid) - strlen(rootfs) - strlen(lxcpath) - strlen(name)) < +- (strlen("{\"ociVersion\":\"\",\"id\":\"\",\"pid\":,\"root\":\"\",\"bundle\":\"\"}") + 1 + 1)) { ++ if ((strlen(name) + strlen(cpid) + strlen(rootfs) + strlen(lxcpath) + strlen(name)) > ++ SIZE_MAX - (strlen("{\"ociVersion\":\"\",\"id\":\"\",\"pid\":,\"root\":\"\",\"bundle\":\"\"}") - 1 - 1)) { + ERROR("Out of memory"); + ret = -1; + goto out_free; +@@ -4499,7 +4503,7 @@ static char* generate_json_str(const char *name, const char *lxcpath, const char + size = strlen("{\"ociVersion\":\"\",\"id\":\"\",\"pid\":,\"root\":\"\",\"bundle\":\"\"}") + + strlen(name) + strlen(cpid) + strlen(rootfs) + strlen(lxcpath) + 1 + strlen(name) + 1; + inmsg = malloc(size); +- if (!inmsg) { ++ if (inmsg == NULL) { + ERROR("Out of memory"); + ret = -1; + goto out_free; +@@ -4531,9 +4535,11 @@ static char **merge_ocihook_env(char **oldenvs, size_t env_len, size_t *merge_en + }; + char *lxcenv_buf = NULL; + ++ if (result_len > SIZE_MAX - (sizeof(lxc_envs) / sizeof(char *)) - 1) ++ return NULL; + result_len += (sizeof(lxc_envs) / sizeof(char *)) + 1; + result = malloc(sizeof(char *) * result_len); +- if (!result) ++ if (result == NULL) + return NULL; + memset(result, 0, sizeof(char *) * result_len); + +@@ -4552,7 +4558,7 @@ static char **merge_ocihook_env(char **oldenvs, size_t env_len, size_t *merge_en + } + env_buf_len = ((strlen(tmpenv) + 1) + strlen(lxc_envs[j])) + 1; + lxcenv_buf = malloc(env_buf_len); +- if (!lxcenv_buf) { ++ if (lxcenv_buf == NULL) { + lxc_free_array((void **)result, free); + return NULL; + } +@@ -4759,7 +4765,7 @@ static int run_ocihook_buffer(struct oci_hook_conf *oconf, const char *inmsg) + } + + conf = malloc(sizeof(struct wait_conf)); +- if (!conf) { ++ if (conf == NULL) { + SYSERROR("Failed to malloc."); + goto on_error; + } +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index 8a082d5..a75e023 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -2318,13 +2318,13 @@ static int set_config_populate_device(const char *key, const char *value, + + /* allocate list element */ + dev_list = malloc(sizeof(*dev_list)); +- if (!dev_list) ++ if (dev_list == NULL) + goto on_error; + + lxc_list_init(dev_list); + + dev_elem = malloc(sizeof(*dev_elem)); +- if (!dev_elem) ++ if (dev_elem == NULL) + goto on_error; + memset(dev_elem, 0, sizeof(*dev_elem)); + +@@ -2362,7 +2362,7 @@ static int set_config_rootfs_masked_paths(const char *key, const char *value, + return lxc_clear_rootfs_masked_paths(lxc_conf); + + list_item = malloc(sizeof(*list_item)); +- if (!list_item) ++ if (list_item == NULL) + goto on_error; + + list_item->elem = safe_strdup(value); +@@ -2387,7 +2387,7 @@ static int set_config_rootfs_ro_paths(const char *key, const char *value, + return lxc_clear_rootfs_ro_paths(lxc_conf); + + list_item = malloc(sizeof(*list_item)); +- if (!list_item) ++ if (list_item == NULL) + goto on_error; + + list_item->elem = safe_strdup(value); +diff --git a/src/lxc/json/container_start_generate_config.c b/src/lxc/json/container_start_generate_config.c +index 5ec8311..3748973 100644 +--- a/src/lxc/json/container_start_generate_config.c ++++ b/src/lxc/json/container_start_generate_config.c +@@ -41,6 +41,11 @@ container_start_generate_config *make_container_start_generate_config(yajl_val t + if (tmp != NULL && YAJL_GET_ARRAY(tmp) != NULL && YAJL_GET_ARRAY(tmp)->len > 0) { + size_t i; + ret->additional_gids_len = YAJL_GET_ARRAY(tmp)->len; ++ if (YAJL_GET_ARRAY(tmp)->len > SIZE_MAX / sizeof(*ret->additional_gids) - 1) { ++ *err = safe_strdup("invalid additional gids size"); ++ free_container_start_generate_config(ret); ++ return NULL; ++ } + ret->additional_gids = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) * sizeof(*ret->additional_gids)); + for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) { + yajl_val val = YAJL_GET_ARRAY(tmp)->values[i]; +@@ -233,8 +238,13 @@ char *container_start_generate_config_generate_json(container_start_generate_con + goto free_out; + } + ++ if (gen_len == SIZE_MAX) { ++ *err = safe_strdup("Invalid buffer length"); ++ goto free_out; ++ } ++ + json_buf = safe_malloc(gen_len + 1); +- (void)memcpy(json_buf, gen_buf, gen_len); ++ (void)memcpy(json_buf, gen_buf, gen_len); + json_buf[gen_len] = '\0'; + + free_out: +diff --git a/src/lxc/json/defs.c b/src/lxc/json/defs.c +index 8a052a8..4bf569a 100644 +--- a/src/lxc/json/defs.c ++++ b/src/lxc/json/defs.c +@@ -24,6 +24,10 @@ defs_hook *make_defs_hook(yajl_val tree, struct parser_context *ctx, parser_erro + if (tmp != NULL && YAJL_GET_ARRAY(tmp) != NULL && YAJL_GET_ARRAY(tmp)->len > 0) { + size_t i; + ret->args_len = YAJL_GET_ARRAY(tmp)->len; ++ if (YAJL_GET_ARRAY(tmp)->len > SIZE_MAX / sizeof(*ret->args) - 1) { ++ free_defs_hook(ret); ++ return NULL; ++ } + ret->args = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) * sizeof(*ret->args)); + for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) { + yajl_val val = YAJL_GET_ARRAY(tmp)->values[i]; +@@ -39,6 +43,10 @@ defs_hook *make_defs_hook(yajl_val tree, struct parser_context *ctx, parser_erro + if (tmp != NULL && YAJL_GET_ARRAY(tmp) != NULL && YAJL_GET_ARRAY(tmp)->len > 0) { + size_t i; + ret->env_len = YAJL_GET_ARRAY(tmp)->len; ++ if (YAJL_GET_ARRAY(tmp)->len > SIZE_MAX / sizeof(*ret->env) - 1) { ++ free_defs_hook(ret); ++ return NULL; ++ } + ret->env = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) * sizeof(*ret->env)); + for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) { + yajl_val val = YAJL_GET_ARRAY(tmp)->values[i]; +diff --git a/src/lxc/json/json_common.c b/src/lxc/json/json_common.c +index 5da1e6d..ed2fe83 100755 +--- a/src/lxc/json/json_common.c ++++ b/src/lxc/json/json_common.c +@@ -445,6 +445,9 @@ json_map_int_int *make_json_map_int_int(yajl_val src, struct parser_context *ctx + if (src != NULL && YAJL_GET_OBJECT(src) != NULL) { + size_t i; + size_t len = YAJL_GET_OBJECT(src)->len; ++ if (len > SIZE_MAX / sizeof(int) - 1) { ++ return NULL; ++ } + ret = safe_malloc(sizeof(*ret)); + ret->len = len; + ret->keys = safe_malloc((len + 1) * sizeof(int)); +@@ -505,16 +508,8 @@ int append_json_map_int_int(json_map_int_int *map, int key, int val) { + vals = safe_malloc(len * sizeof(int)); + + if (map->len) { +- if (memcpy(keys, map->keys, map->len * sizeof(int)) != NULL) { +- free(keys); +- free(vals); +- return -1; +- } +- if (memcpy(vals, map->values, map->len * sizeof(int)) != NULL) { +- free(keys); +- free(vals); +- return -1; +- } ++ (void)memcpy(keys, map->keys, map->len * sizeof(int)); ++ (void)memcpy(vals, map->values, map->len * sizeof(int)); + } + free(map->keys); + map->keys = keys; +@@ -591,6 +586,9 @@ json_map_int_bool *make_json_map_int_bool(yajl_val src, struct parser_context *c + if (src != NULL && YAJL_GET_OBJECT(src) != NULL) { + size_t i; + size_t len = YAJL_GET_OBJECT(src)->len; ++ if (len > SIZE_MAX / sizeof(int) - 1) { ++ return NULL; ++ } + ret = safe_malloc(sizeof(*ret)); + ret->len = len; + ret->keys = safe_malloc((len + 1) * sizeof(int)); +@@ -646,16 +644,8 @@ int append_json_map_int_bool(json_map_int_bool *map, int key, bool val) { + vals = safe_malloc(len * sizeof(bool)); + + if (map->len) { +- if (memcpy(keys, map->keys, map->len * sizeof(int)) != NULL) { +- free(keys); +- free(vals); +- return -1; +- } +- if (memcpy(vals, map->values, map->len * sizeof(bool)) != NULL) { +- free(keys); +- free(vals); +- return -1; +- } ++ (void)memcpy(keys, map->keys, map->len * sizeof(int)); ++ (void)memcpy(vals, map->values, map->len * sizeof(bool)); + } + free(map->keys); + map->keys = keys; +@@ -733,6 +723,9 @@ json_map_int_string *make_json_map_int_string(yajl_val src, struct parser_contex + if (src != NULL && YAJL_GET_OBJECT(src) != NULL) { + size_t i; + size_t len = YAJL_GET_OBJECT(src)->len; ++ if (len > SIZE_MAX / sizeof(char *) - 1) { ++ return NULL; ++ } + ret = safe_malloc(sizeof(*ret)); + ret->len = len; + ret->keys = safe_malloc((len + 1) * sizeof(int)); +@@ -786,16 +779,8 @@ int append_json_map_int_string(json_map_int_string *map, int key, const char *va + vals = safe_malloc(len * sizeof(char *)); + + if (map->len) { +- if (memcpy(keys, map->keys, map->len * sizeof(int)) != NULL) { +- free(keys); +- free(vals); +- return -1; +- } +- if (memcpy(vals, map->values, map->len * sizeof(char *)) != NULL) { +- free(keys); +- free(vals); +- return -1; +- } ++ (void)memcpy(keys, map->keys, map->len * sizeof(int)); ++ (void)memcpy(vals, map->values, map->len * sizeof(char *)); + } + free(map->keys); + map->keys = keys; +@@ -864,6 +849,9 @@ json_map_string_int *make_json_map_string_int(yajl_val src, struct parser_contex + if (src != NULL && YAJL_GET_OBJECT(src) != NULL) { + size_t i; + size_t len = YAJL_GET_OBJECT(src)->len; ++ if (len > SIZE_MAX / sizeof(char *) - 1) { ++ return NULL; ++ } + ret = safe_malloc(sizeof(*ret)); + ret->len = len; + ret->keys = safe_malloc((len + 1) * sizeof(char *)); +@@ -913,16 +901,8 @@ int append_json_map_string_int(json_map_string_int *map, const char *key, int va + vals = safe_malloc(len * sizeof(int)); + + if (map->len) { +- if (memcpy(keys, map->keys, map->len * sizeof(char *)) != NULL) { +- free(keys); +- free(vals); +- return -1; +- } +- if (memcpy(vals, map->values, map->len * sizeof(int)) != NULL) { +- free(keys); +- free(vals); +- return -1; +- } ++ (void)memcpy(keys, map->keys, map->len * sizeof(char *)); ++ (void)memcpy(vals, map->values, map->len * sizeof(int)); + } + free(map->keys); + map->keys = keys; +@@ -991,6 +971,9 @@ json_map_string_bool *make_json_map_string_bool(yajl_val src, struct parser_cont + if (src != NULL && YAJL_GET_OBJECT(src) != NULL) { + size_t i; + size_t len = YAJL_GET_OBJECT(src)->len; ++ if (len > SIZE_MAX / sizeof(char *) - 1) { ++ return NULL; ++ } + ret = safe_malloc(sizeof(*ret)); + ret->len = len; + ret->keys = safe_malloc((len + 1) * sizeof(char *)); +@@ -1017,6 +1000,7 @@ json_map_string_bool *make_json_map_string_bool(yajl_val src, struct parser_cont + } + return ret; + } ++ + int append_json_map_string_bool(json_map_string_bool *map, const char *key, bool val) { + size_t len; + char **keys = NULL; +@@ -1035,16 +1019,8 @@ int append_json_map_string_bool(json_map_string_bool *map, const char *key, bool + vals = safe_malloc(len * sizeof(bool)); + + if (map->len) { +- if (memcpy(keys, map->keys, map->len * sizeof(char *)) != NULL) { +- free(keys); +- free(vals); +- return -1; +- } +- if (memcpy(vals, map->values, map->len * sizeof(bool)) != NULL) { +- free(keys); +- free(vals); +- return -1; +- } ++ (void)memcpy(keys, map->keys, map->len * sizeof(char *)); ++ (void)memcpy(vals, map->values, map->len * sizeof(bool)); + } + free(map->keys); + map->keys = keys; +@@ -1114,6 +1090,9 @@ json_map_string_string *make_json_map_string_string(yajl_val src, struct parser_ + if (src != NULL && YAJL_GET_OBJECT(src) != NULL) { + size_t i; + size_t len = YAJL_GET_OBJECT(src)->len; ++ if (len > SIZE_MAX / sizeof(char *) - 1) { ++ return NULL; ++ } + ret = safe_malloc(sizeof(*ret)); + ret->len = len; + ret->keys = safe_malloc((len + 1) * sizeof(char *)); +@@ -1149,9 +1128,9 @@ int append_json_map_string_string(json_map_string_string *map, const char *key, + + for (i = 0; i < map->len; i++) { + if (strcmp(map->keys[i], key) == 0) { +- free(map->values[i]); +- map->values[i] = safe_strdup(val ? val : ""); +- return 0; ++ free(map->values[i]); ++ map->values[i] = safe_strdup(val ? val : ""); ++ return 0; + } + } + +@@ -1164,16 +1143,8 @@ int append_json_map_string_string(json_map_string_string *map, const char *key, + vals = safe_malloc(len * sizeof(char *)); + + if (map->len) { +- if (memcpy(keys, map->keys, map->len * sizeof(char *)) != NULL) { +- free(keys); +- free(vals); +- return -1; +- } +- if (memcpy(vals, map->values, map->len * sizeof(char *)) != NULL) { +- free(keys); +- free(vals); +- return -1; +- } ++ (void)memcpy(keys, map->keys, map->len * sizeof(char *)); ++ (void)memcpy(vals, map->values, map->len * sizeof(char *)); + } + free(map->keys); + map->keys = keys; +diff --git a/src/lxc/json/logger_json_file.c b/src/lxc/json/logger_json_file.c +index 842d35b..6abeef4 100644 +--- a/src/lxc/json/logger_json_file.c ++++ b/src/lxc/json/logger_json_file.c +@@ -230,8 +230,12 @@ char *logger_json_file_generate_json(logger_json_file *ptr, struct parser_contex + goto free_out; + } + ++ if (gen_len == SIZE_MAX) { ++ *err = safe_strdup("Invalid buffer length"); ++ goto free_out; ++ } + json_buf = safe_malloc(gen_len + 1); +- memcpy(json_buf, gen_buf, gen_len); ++ (void)memcpy(json_buf, gen_buf, gen_len); + json_buf[gen_len] = '\0'; + + free_out: +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index 3b2c5af..5a72483 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -928,6 +928,9 @@ static char **use_init_args(char **init_argv, size_t init_args) + + do { + argv = malloc(sizeof(char *)); ++ if (argv == NULL) { ++ return NULL; ++ } + } while (!argv); + + argv[0] = NULL; +@@ -3378,9 +3381,12 @@ static bool set_oci_hook_config_filename(struct lxc_container *c) + return false; + + /* $lxc_path + "/" + c->name + "/" + "config" + '\0' */ ++ if (strlen(c->config_path) + strlen(c->name) > SIZE_MAX - strlen(OCI_HOOK_JSON_FILE_NAME) - 3) ++ return false; + len = strlen(c->config_path) + strlen(c->name) + strlen(OCI_HOOK_JSON_FILE_NAME) + 3; ++ + newpath = malloc(len); +- if (!newpath) ++ if (newpath == NULL) + return false; + + ret = snprintf(newpath, len, "%s/%s/%s", c->config_path, c->name, OCI_HOOK_JSON_FILE_NAME); +@@ -5276,11 +5282,11 @@ static int set_start_extral_configs(struct lxc_container *c) + + if (lconf == NULL) { + c->lxc_conf = malloc(sizeof(struct lxc_conf)); +- lconf = c->lxc_conf; +- if (lconf == NULL) { ++ if (c->lxc_conf == NULL) { + fprintf(stderr, "Out of memory\n"); + return -1; + } ++ lconf = c->lxc_conf; + } + if (snprintf(fpath, PATH_MAX, "%s/%s/%s", c->config_path, c->name, START_GENERATE_CONFIG) < 0) { + fprintf(stderr, "Sprintf config path failed\n"); +diff --git a/src/lxc/path.c b/src/lxc/path.c +index c545887..df285f5 100644 +--- a/src/lxc/path.c ++++ b/src/lxc/path.c +@@ -58,7 +58,7 @@ char *preserve_trailing_dot_or_separator(const char *cleanedpath, + + len = strlen(cleanedpath) + 3; + respath = malloc(len); +- if (!respath) { ++ if (respath == NULL) { + ERROR("Out of memory"); + return NULL; + } +@@ -90,12 +90,16 @@ bool filepath_split(const char *path, char **dir, char **base) + size_t len; + + len = strlen(path); ++ if (len >= PATH_MAX) { ++ ERROR("Invalid path"); ++ return false; ++ } + i = len - 1; + while (i >= 0 && path[i] != '/') + i--; + + *dir = malloc(i + 2); +- if (!*dir) { ++ if (*dir == NULL) { + ERROR("Out of memory"); + return false; + } +diff --git a/src/lxc/start.c b/src/lxc/start.c +index d6c706e..00d478c 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -2383,7 +2383,7 @@ static int create_start_timeout_thread(struct lxc_conf *conf, unsigned int start + } + + timeout_conf = malloc(sizeof(struct start_timeout_conf)); +- if (!timeout_conf) { ++ if (timeout_conf == NULL) { + ERROR("Failed to malloc start timeout conf"); + ret = -1; + goto out; +@@ -2657,7 +2657,7 @@ static struct lxc_handler *lxc_init_clean_handler(char *name, char *lxcpath, str + struct lxc_handler *handler; + + handler = malloc(sizeof(*handler)); +- if (!handler) ++ if (handler == NULL) + return NULL; + + memset(handler, 0, sizeof(*handler)); +@@ -2707,7 +2707,7 @@ static struct lxc_handler *lxc_init_pids_handler(char *name, char *lxcpath, stru + struct lxc_handler *handler; + + handler = malloc(sizeof(*handler)); +- if (!handler) ++ if (handler == NULL) + return NULL; + + memset(handler, 0, sizeof(*handler)); +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index b9b65c6..1fee651 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -1330,7 +1330,7 @@ static int lxc_terminal_set_fifo(struct lxc_terminal *console, const char *in, c + } + + fifo_elem = malloc(sizeof(*fifo_elem)); +- if (!fifo_elem) { ++ if (fifo_elem == NULL) { + if (fifofd_in >= 0) + close(fifofd_in); + if (fifofd_out >= 0) +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index e6e8905..656df4a 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -1945,9 +1945,9 @@ static proc_t *lxc_stat2proc(const char *S) + *tmp = '\0'; /* replace trailing ')' with NUL */ + + P = malloc(sizeof(proc_t)); +- if (!P) ++ if (P == NULL) + return NULL; +- memset(P, 0x00, sizeof(proc_t)); ++ (void)memset(P, 0x00, sizeof(proc_t)); + + /* parse these two strings separately, skipping the leading "(". */ + num = sscanf(S, "%d (%15c", &P->pid, P->cmd); /* comm[16] in kernel */ +-- +1.8.3.1 + diff --git a/0114-lxc-fix-code-errors.patch b/0114-lxc-fix-code-errors.patch new file mode 100644 index 0000000..d755933 --- /dev/null +++ b/0114-lxc-fix-code-errors.patch @@ -0,0 +1,155 @@ +From 5797a2ceac0c911adf3edbe3e50a9c9c23858ced Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Thu, 4 Jul 2019 05:10:00 -0400 +Subject: [PATCH 114/122] lxc: fix code errors + +Signed-off-by: LiFeng +--- + src/lxc/attach.c | 14 +++++--------- + src/lxc/conf.c | 11 ++++++----- + src/lxc/confile.c | 8 ++------ + src/lxc/terminal.c | 6 ++---- + 4 files changed, 15 insertions(+), 24 deletions(-) + +diff --git a/src/lxc/attach.c b/src/lxc/attach.c +index ac4bd39..1f14eb4 100644 +--- a/src/lxc/attach.c ++++ b/src/lxc/attach.c +@@ -841,7 +841,7 @@ static int attach_child_main(struct attach_clone_payload *payload) + } + + /* isulad: set workdir */ +- if (init_ctx && init_ctx->container && init_ctx->container->lxc_conf && init_ctx->container->lxc_conf->init_cwd) { ++ if (init_ctx->container->lxc_conf->init_cwd) { + char *init_cwd; + init_cwd = init_ctx->container->lxc_conf->init_cwd; + /* try to create workdir if not exist */ +@@ -933,8 +933,7 @@ static int attach_child_main(struct attach_clone_payload *payload) + goto on_error; + } + +- if ((init_ctx->container && init_ctx->container->lxc_conf && +- init_ctx->container->lxc_conf->no_new_privs) || ++ if ((init_ctx->container->lxc_conf->no_new_privs) || + (options->attach_flags & LXC_ATTACH_NO_NEW_PRIVS)) { + ret = prctl(PR_SET_NO_NEW_PRIVS, prctl_arg(1), prctl_arg(0), + prctl_arg(0), prctl_arg(0)); +@@ -958,8 +957,7 @@ static int attach_child_main(struct attach_clone_payload *payload) + TRACE("Set %s LSM label to \"%s\"", lsm_name(), init_ctx->lsm_label); + } + +- if (init_ctx->container && init_ctx->container->lxc_conf && +- init_ctx->container->lxc_conf->seccomp) { ++ if (init_ctx->container->lxc_conf->seccomp) { + ret = lxc_seccomp_load(init_ctx->container->lxc_conf); + if (ret < 0) + goto on_error; +@@ -1028,8 +1026,7 @@ static int attach_child_main(struct attach_clone_payload *payload) + goto on_error; + } + +- if (init_ctx->container && init_ctx->container->lxc_conf && +- !lxc_setgroups(init_ctx->container->lxc_conf->init_groups_len, ++ if (!lxc_setgroups(init_ctx->container->lxc_conf->init_groups_len, + init_ctx->container->lxc_conf->init_groups)) + goto on_error; + +@@ -1041,8 +1038,7 @@ static int attach_child_main(struct attach_clone_payload *payload) + goto on_error; + } + +- if (init_ctx->container && init_ctx->container->lxc_conf && +- lxc_drop_caps(init_ctx->container->lxc_conf) != 0) { ++ if (lxc_drop_caps(init_ctx->container->lxc_conf) != 0) { + ERROR("Failed to drop caps."); + goto on_error; + } +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 3ecccbd..e22e13e 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4790,6 +4790,7 @@ static int run_ocihook_buffer(struct oci_hook_conf *oconf, const char *inmsg) + err = pthread_create(&ptid, &attr, wait_ocihook_timeout, conf); + if (err != 0) { + ERROR("Create wait timeout thread failed"); ++ free(conf); + goto on_error; + } + +@@ -4804,17 +4805,17 @@ static int run_ocihook_buffer(struct oci_hook_conf *oconf, const char *inmsg) + goto print_hook; + } else if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) { + ERROR("Script exited with status %d. output: %s", WEXITSTATUS(ret), output); +- lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"error running hook: exit status %d, output: %s\".", ++ lxc_write_error_message(oconf->errfd, "%s:%d: running %s hook caused \"error running hook: exit status %d, output: %s\".", + __FILE__, __LINE__, +- (conf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[conf->which], ++ (oconf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[oconf->which], + WEXITSTATUS(ret), output); + + goto print_hook; + } else if (WIFSIGNALED(ret)) { + ERROR("Script terminated by signal %d.", WTERMSIG(ret)); +- lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"error running hook: Script terminated by signal %d\".", ++ lxc_write_error_message(oconf->errfd, "%s:%d: running %s hook caused \"error running hook: Script terminated by signal %d\".", + __FILE__, __LINE__, +- (conf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[conf->which], ++ (oconf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[oconf->which], + WTERMSIG(ret)); + + goto print_hook; +@@ -4836,7 +4837,7 @@ print_hook: + err_envs_msg = lxc_string_join(" ", (const char **)oconf->ocihook->env, false); + ERROR("Hook script command: \"%s\", args: \"%s\", envs: \"%s\", timeout: %d.", + buffer, err_args_msg ? err_args_msg : "", +- err_envs_msg ? err_envs_msg : "", conf->timeout); ++ err_envs_msg ? err_envs_msg : "", oconf->ocihook->timeout); + + free(err_args_msg); + free(err_envs_msg); +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index a75e023..0537ebc 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -3828,9 +3828,7 @@ static int get_config_prlimit(const char *key, char *retv, int inlen, + struct lxc_limit *lim = it->elem; + + if (lim->limit.rlim_cur == RLIM_INFINITY) { +- if (memcpy(buf, "unlimited", STRLITERALLEN("unlimited") + 1) == NULL) { +- return -1; +- } ++ (void)memcpy(buf, "unlimited", STRLITERALLEN("unlimited") + 1); + partlen = STRLITERALLEN("unlimited"); + } else { + partlen = snprintf(buf, MAX_LIMIT_BUF_LEN, "%" PRIu64, (uint64_t)lim->limit.rlim_cur); +@@ -3841,9 +3839,7 @@ static int get_config_prlimit(const char *key, char *retv, int inlen, + + if (lim->limit.rlim_cur != lim->limit.rlim_max) { + if (lim->limit.rlim_max == RLIM_INFINITY) { +- if (memcpy(buf + partlen, ":unlimited", STRLITERALLEN(":unlimited") + 1) == NULL) { +- return -1; +- } ++ (void)memcpy(buf + partlen, ":unlimited", STRLITERALLEN(":unlimited") + 1); + } else { + nret = snprintf(buf + partlen, (MAX_LIMIT_BUF_LEN - partlen), ":%" PRIu64, (uint64_t)lim->limit.rlim_max); + if (nret < 0) { +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index 1fee651..32c69a4 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -289,10 +289,8 @@ static int lxc_terminal_rotate_log_file(struct lxc_terminal *terminal) + ERROR("Out of memory"); + return -1; + } +- if (memset(tmp, 0, len) != NULL) { +- ERROR("Memset failed"); +- goto free_out; +- } ++ ++ (void)memset(tmp, 0, len); + + ret = snprintf(tmp, len, "%s.1", terminal->log_path); + if (ret < 0 || (size_t)ret >= len) { +-- +1.8.3.1 + diff --git a/0115-fix-compile-error-on-ubuntu.patch b/0115-fix-compile-error-on-ubuntu.patch new file mode 100644 index 0000000..ac4269d --- /dev/null +++ b/0115-fix-compile-error-on-ubuntu.patch @@ -0,0 +1,371 @@ +From 7fb5e2b059486b8bd466e2bcb9294653cc62c6d0 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Thu, 11 Jul 2019 17:42:00 +0800 +Subject: [PATCH 115/122] fix compile error on ubuntu + +fix compile error on ubuntu + +Signed-off-by: liuhao +Signed-off-by: LiFeng +--- + configure.ac | 1 - + src/lxc/Makefile.am | 10 ++++-- + src/lxc/conf.c | 2 +- + src/lxc/confile.c | 2 +- + src/lxc/isulad_utils.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++ + src/lxc/isulad_utils.h | 13 ++++++++ + src/lxc/path.c | 2 +- + src/lxc/utils.c | 82 +---------------------------------------------- + src/lxc/utils.h | 6 +--- + 9 files changed, 113 insertions(+), 92 deletions(-) + create mode 100644 src/lxc/isulad_utils.c + create mode 100644 src/lxc/isulad_utils.h + +diff --git a/configure.ac b/configure.ac +index 5963fab..dc85f74 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -706,7 +706,6 @@ AX_CHECK_LINK_FLAG([-z relro], [LDFLAGS="$LDFLAGS -z relro"],,[]) + AX_CHECK_LINK_FLAG([-z now], [LDFLAGS="$LDFLAGS -z now"],,[]) + AX_CHECK_LINK_FLAG([-z noexecstack], [LDFLAGS="$LDFLAGS -z noexecstack"],,[]) + +-LDFLAGS="$LDFLAGS -fPIE -pie" + + CFLAGS="$CFLAGS -Wvla -std=gnu11 -D_FORTIFY_SOURCE=2 -Wall -fPIC -fPIE -pie" + if test "x$enable_werror" = "xyes"; then +diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am +index b24fcfd..27240cc 100644 +--- a/src/lxc/Makefile.am ++++ b/src/lxc/Makefile.am +@@ -50,6 +50,7 @@ noinst_HEADERS = attach.h \ + json/oci_runtime_spec.h \ + json/logger_json_file.h \ + json/read-file.h \ ++ isulad_utils.h \ + utils.h + + if IS_BIONIC +@@ -146,6 +147,7 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \ + sync.c sync.h \ + syscall_wrappers.h \ + terminal.c \ ++ isulad_utils.c isulad_utils.h \ + utils.c utils.h \ + version.h \ + json/json_common.c json/json_common.h \ +@@ -232,14 +234,14 @@ AM_CFLAGS += -DUSE_CONFIGPATH_LOGS + endif + + # build the shared library +-liblxc_la_CFLAGS = -fPIC \ +- -fPIE -pie \ ++liblxc_la_CFLAGS = \ + -DPIC \ + -D_FORTIFY_SOURCE=2 -Wall \ + $(AM_CFLAGS) \ + -pthread + + liblxc_la_LDFLAGS = -pthread \ ++ -fPIC \ + -Wl,-no-undefined \ + -Wl,-z,relro \ + -Wl,-z,now \ +@@ -375,6 +377,7 @@ lxc_monitord_SOURCES = cmd/lxc_monitord.c \ + mainloop.c mainloop.h \ + monitor.c monitor.h \ + raw_syscalls.c raw_syscalls.h \ ++ isulad_utils.c isulad_utils.h \ + utils.c utils.h + lxc_user_nic_SOURCES = cmd/lxc_user_nic.c \ + ../include/netns_ifaddrs.c ../include/netns_ifaddrs.h \ +@@ -391,6 +394,7 @@ lxc_usernsexec_SOURCES = cmd/lxc_usernsexec.c \ + file_utils.c file_utils.h \ + string_utils.c string_utils.h \ + syscall_wrappers.h \ ++ isulad_utils.c isulad_utils.h \ + utils.c utils.h + endif + +@@ -411,6 +415,8 @@ init_lxc_static_SOURCES = cmd/lxc_init.c \ + initutils.c initutils.h \ + file_utils.c file_utils.h \ + log.c log.h \ ++ path.c path.h \ ++ isulad_utils.c isulad_utils.h \ + macro.h \ + namespace.c namespace.h \ + string_utils.c string_utils.h +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index e22e13e..d9a7aae 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4934,7 +4934,7 @@ static int do_run_oci_hooks(const char *name, const char *lxcpath, struct lxc_co + work_conf.ocihook = lc->ocihooks->poststart[i]; + nret = run_ocihook_script_argv(name, "lxc", &work_conf, lxcpath, rootpath); + if (nret != 0) +- WARN("running poststart hook %ld failed, ContainerId: %s", i, name); ++ WARN("running poststart hook %zu failed, ContainerId: %s", i, name); + } + break; + case OCI_HOOK_POSTSTOP: +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index 0537ebc..01fc944 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -2212,7 +2212,7 @@ static int set_config_init_args(const char *key, const char *value, + struct lxc_conf *lxc_conf, void *data) + { + int ret = 0; +- char *tmp = NULL; ++ void *tmp = NULL; + char *new_value = NULL; + + ret = set_config_string_item(&new_value, value); +diff --git a/src/lxc/isulad_utils.c b/src/lxc/isulad_utils.c +new file mode 100644 +index 0000000..66516a8 +--- /dev/null ++++ b/src/lxc/isulad_utils.c +@@ -0,0 +1,87 @@ ++#include ++#include ++ ++#include "isulad_utils.h" ++#include "log.h" ++#include "path.h" ++ ++lxc_log_define(isulad_utils, lxc); ++ ++void *lxc_common_calloc_s(size_t size) ++{ ++ if (size == 0 || size > SIZE_MAX) { ++ return NULL; ++ } ++ ++ return calloc((size_t)1, size); ++} ++ ++int lxc_mem_realloc(void **newptr, size_t newsize, void *oldptr, size_t oldsize) ++{ ++ void *tmp = NULL; ++ ++ if (newsize == 0) { ++ goto err_out; ++ } ++ ++ tmp = lxc_common_calloc_s(newsize); ++ if (tmp == NULL) { ++ ERROR("Failed to malloc memory"); ++ goto err_out; ++ } ++ ++ if (oldptr != NULL) { ++ memcpy(tmp, oldptr, (newsize < oldsize) ? newsize : oldsize); ++ ++ memset(oldptr, 0, oldsize); ++ ++ free(oldptr); ++ } ++ ++ *newptr = tmp; ++ return 0; ++ ++err_out: ++ return -1; ++} ++ ++char *safe_strdup(const char *src) ++{ ++ char *dst = NULL; ++ ++ if (src == NULL) { ++ return NULL; ++ } ++ ++ dst = strdup(src); ++ if (dst == NULL) { ++ abort(); ++ } ++ ++ return dst; ++} ++ ++int lxc_open(const char *filename, int flags, mode_t mode) ++{ ++ char rpath[PATH_MAX] = {0x00}; ++ ++ if (cleanpath(filename, rpath, sizeof(rpath)) == NULL) { ++ return -1; ++ } ++ if (mode) { ++ return open(rpath, (int)((unsigned int)flags | O_CLOEXEC), mode); ++ } else { ++ return open(rpath, (int)((unsigned int)flags | O_CLOEXEC)); ++ } ++} ++ ++FILE *lxc_fopen(const char *filename, const char *mode) ++{ ++ char rpath[PATH_MAX] = {0x00}; ++ ++ if (cleanpath(filename, rpath, sizeof(rpath)) == NULL) { ++ return NULL; ++ } ++ ++ return fopen_cloexec(rpath, mode); ++} +diff --git a/src/lxc/isulad_utils.h b/src/lxc/isulad_utils.h +new file mode 100644 +index 0000000..852d956 +--- /dev/null ++++ b/src/lxc/isulad_utils.h +@@ -0,0 +1,13 @@ ++#ifndef __LXC_MEM_UTILS_H ++#define __LXC_MEM_UTILS_H ++ ++#include ++ ++extern int lxc_mem_realloc(void **newptr, size_t newsize, void *oldptr, size_t oldsize); ++extern void *lxc_common_calloc_s(size_t size); ++extern char *safe_strdup(const char *src); ++ ++extern int lxc_open(const char *filename, int flags, mode_t mode); ++extern FILE *lxc_fopen(const char *filename, const char *mode); ++ ++#endif +diff --git a/src/lxc/path.c b/src/lxc/path.c +index df285f5..7a5dce9 100644 +--- a/src/lxc/path.c ++++ b/src/lxc/path.c +@@ -10,7 +10,7 @@ + + #include "path.h" + #include "log.h" +-#include "utils.h" ++#include "isulad_utils.h" + + lxc_log_define(lxc_path_ui, lxc); + +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index 656df4a..1d2e9ee 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -57,6 +57,7 @@ + #include "syscall_wrappers.h" + #include "utils.h" + #include "path.h" ++#include "isulad_utils.h" + + #ifndef HAVE_STRLCPY + #include "include/strlcpy.h" +@@ -2092,84 +2093,3 @@ bool is_non_negative_num(const char *s) + } + return true; + } +- +-void *lxc_common_calloc_s(size_t size) +-{ +- if (size == 0 || size > SIZE_MAX) { +- return NULL; +- } +- +- return calloc((size_t)1, size); +-} +- +- +-int lxc_mem_realloc(void **newptr, size_t newsize, void *oldptr, size_t oldsize) +-{ +- void *tmp = NULL; +- +- if (newsize == 0) { +- goto err_out; +- } +- +- tmp = lxc_common_calloc_s(newsize); +- if (tmp == NULL) { +- ERROR("Failed to malloc memory"); +- goto err_out; +- } +- +- if (oldptr != NULL) { +- memcpy(tmp, oldptr, (newsize < oldsize) ? newsize : oldsize); +- +- memset(oldptr, 0, oldsize); +- +- free(oldptr); +- } +- +- *newptr = tmp; +- return 0; +- +-err_out: +- return -1; +-} +- +-int lxc_open(const char *filename, int flags, mode_t mode) +-{ +- char rpath[PATH_MAX] = {0x00}; +- +- if (cleanpath(filename, rpath, sizeof(rpath)) == NULL) { +- return -1; +- } +- if (mode) { +- return open(rpath, (int)((unsigned int)flags | O_CLOEXEC), mode); +- } else { +- return open(rpath, (int)((unsigned int)flags | O_CLOEXEC)); +- } +-} +- +-FILE *lxc_fopen(const char *filename, const char *mode) +-{ +- char rpath[PATH_MAX] = {0x00}; +- +- if (cleanpath(filename, rpath, sizeof(rpath)) == NULL) { +- return NULL; +- } +- +- return fopen_cloexec(rpath, mode); +-} +- +-char *safe_strdup(const char *src) +-{ +- char *dst = NULL; +- +- if (src == NULL) { +- return NULL; +- } +- +- dst = strdup(src); +- if (dst == NULL) { +- abort(); +- } +- +- return dst; +-} +- +diff --git a/src/lxc/utils.h b/src/lxc/utils.h +index 0b33f69..1c9bf41 100644 +--- a/src/lxc/utils.h ++++ b/src/lxc/utils.h +@@ -42,6 +42,7 @@ + #include "macro.h" + #include "raw_syscalls.h" + #include "string_utils.h" ++#include "isulad_utils.h" + + /* isulad: replace space with SPACE_MAGIC_STR */ + #define SPACE_MAGIC_STR "[#)" +@@ -324,10 +325,5 @@ extern bool lxc_process_alive(pid_t pid, unsigned long long start_time); + + extern bool is_non_negative_num(const char *s); + extern int lxc_file2str(const char *filename, char ret[], int cap); +-extern int lxc_mem_realloc(void **newptr, size_t newsize, void *oldptr, size_t oldsize); +-extern void *lxc_common_calloc_s(size_t size); +-extern int lxc_open(const char *filename, int flags, mode_t mode); +-extern FILE *lxc_fopen(const char *filename, const char *mode); +-extern char *safe_strdup(const char *src); + + #endif /* __LXC_UTILS_H */ +-- +1.8.3.1 + diff --git a/0116-lxc-set-base-cgroup-path-to.patch b/0116-lxc-set-base-cgroup-path-to.patch new file mode 100644 index 0000000..b1eaa84 --- /dev/null +++ b/0116-lxc-set-base-cgroup-path-to.patch @@ -0,0 +1,34 @@ +From 575a5f505195e9282b0cbffa3f8a446613252861 Mon Sep 17 00:00:00 2001 +From: liuhao +Date: Wed, 19 Jun 2019 16:48:50 +0800 +Subject: [PATCH 116/122] lxc: set base cgroup path to '/' + +reason:base cgroup may be started with /system.slice when cg_hybrid_init +read /proc/1/cgroup on host, and cgroup init will set all containers +cgroup path under /sys/fs/cgroup//system.slice/xxx/lxc +directory, this is not consistent with docker. The default cgroup path +should be under /sys/fs/cgroup//lxc directory. + +Signed-off-by: zhangsong +Signed-off-by: LiFeng +--- + src/lxc/cgroups/cgfsng.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c +index 46f13f4..7c92abe 100644 +--- a/src/lxc/cgroups/cgfsng.c ++++ b/src/lxc/cgroups/cgfsng.c +@@ -2545,6 +2545,9 @@ static bool cg_hybrid_init(struct cgroup_ops *ops) + if (!writeable) + goto next; + */ ++ if (strlen(base_cgroup) > 1 && base_cgroup[0] == '/') { ++ base_cgroup[1] = '\0'; ++ } + if (type == CGROUP2_SUPER_MAGIC) { + char *cgv2_ctrl_path; + +-- +1.8.3.1 + diff --git a/0117-pupulate-device-with-dir-mode-750-and-set-uid-gid.patch b/0117-pupulate-device-with-dir-mode-750-and-set-uid-gid.patch new file mode 100644 index 0000000..696a933 --- /dev/null +++ b/0117-pupulate-device-with-dir-mode-750-and-set-uid-gid.patch @@ -0,0 +1,53 @@ +From d17249766b7e2de7246b5c2bfcd30dca2da6d38e Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Wed, 31 Jul 2019 05:24:11 -0400 +Subject: [PATCH 117/122] pupulate device with dir mode 750 and set uid/gid + +Signed-off-by: LiFeng +--- + src/lxc/conf.c | 3 --- + src/lxc/confile.c | 2 ++ + 2 files changed, 2 insertions(+), 3 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index d9a7aae..0b10a2d 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4005,13 +4005,11 @@ static int setup_populate_devs(const struct lxc_rootfs *rootfs, struct lxc_list + int ret = 0; + char *pathdirname = NULL; + char path[MAXPATHLEN]; +- mode_t cmask; + mode_t file_mode = 0; + struct lxc_populate_devs *dev_elem = NULL; + struct lxc_list *it = NULL; + + INFO("Populating devices into container"); +- cmask = umask(S_IXUSR | S_IXGRP | S_IXOTH); + lxc_list_for_each(it, devs) { + dev_elem = it->elem; + +@@ -4072,7 +4070,6 @@ static int setup_populate_devs(const struct lxc_rootfs *rootfs, struct lxc_list + return -1; + } + } +- umask(cmask); + + INFO("Populated devices into container /dev"); + return 0; +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index 01fc944..3a02e09 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -2335,6 +2335,8 @@ static int set_config_populate_device(const char *key, const char *value, + dev_elem->file_mode = filemode; + dev_elem->maj = major; + dev_elem->min = minor; ++ dev_elem->uid = (uid_t)uid; ++ dev_elem->gid = (gid_t)gid; + + lxc_list_add_elem(dev_list, dev_elem); + +-- +1.8.3.1 + diff --git a/0118-fix-sscanf-return-value-check.patch b/0118-fix-sscanf-return-value-check.patch new file mode 100644 index 0000000..de4ff9d --- /dev/null +++ b/0118-fix-sscanf-return-value-check.patch @@ -0,0 +1,55 @@ +From 0aade3f699ec02ead3b4707be0e259ded5c1e9ec Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Mon, 2 Sep 2019 06:24:07 -0400 +Subject: [PATCH 118/122] fix sscanf return value check + +Signed-off-by: LiFeng +--- + src/lxc/start.c | 2 +- + src/lxc/utils.c | 10 +++++++--- + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/src/lxc/start.c b/src/lxc/start.c +index 00d478c..c1e0d5d 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -1904,7 +1904,7 @@ static int lxc_check_container_info(char *filename, pid_t pid, pid_t p_pid, unsi + } + + num = sscanf(sbuf, "%d %Lu %d %Lu", &saved_pid, &saved_start_time, &saved_ppid, &saved_pstart_time); +- if (num < 0) { ++ if (num != 4) { + SYSERROR("Call sscanf error"); + ret = -1; + goto out; +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index 1d2e9ee..c83c7a3 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -1952,8 +1952,8 @@ static proc_t *lxc_stat2proc(const char *S) + + /* parse these two strings separately, skipping the leading "(". */ + num = sscanf(S, "%d (%15c", &P->pid, P->cmd); /* comm[16] in kernel */ +- if (num < 0 && errno) { +- ERROR("Call sscanf error: %s", strerror(errno)); ++ if (num != 2) { ++ ERROR("Call sscanf error: %s", errno ? strerror(errno) : ""); + free(P); + return NULL; + } +@@ -1985,7 +1985,11 @@ static proc_t *lxc_stat2proc(const char *S) + &P->exit_signal, &P->processor, /* 2.2.1 ends with "exit_signal" */ + &P->rtprio, &P->sched /* both added to 2.5.18 */ + ); +- ++ if (num != 35) { ++ ERROR("Call sscanf error: %s", errno ? strerror(errno) : ""); ++ free(P); ++ return NULL; ++ } + if (P->tty == 0) + P->tty = -1; /* the old notty val, update elsewhere bef. moving to 0 */ + return P; +-- +1.8.3.1 + diff --git a/0119-remove-unuse-binary.patch b/0119-remove-unuse-binary.patch new file mode 100644 index 0000000..1526df1 --- /dev/null +++ b/0119-remove-unuse-binary.patch @@ -0,0 +1,33 @@ +From 787c3c652d02b6398d6b7fcf2a2f8c9e406552fb Mon Sep 17 00:00:00 2001 +From: LiuHao +Date: Wed, 4 Sep 2019 18:01:39 +0800 +Subject: [PATCH 119/122] remove unuse binary + +Signed-off-by: LiuHao +--- + hooks/Makefile.am | 11 ----------- + 1 file changed, 11 deletions(-) + +diff --git a/hooks/Makefile.am b/hooks/Makefile.am +index 5ae73d7..f55c4a9 100644 +--- a/hooks/Makefile.am ++++ b/hooks/Makefile.am +@@ -10,15 +10,4 @@ hooks_SCRIPTS = \ + squid-deb-proxy-client \ + nvidia + +-binhooks_PROGRAMS = \ +- unmount-namespace +- +-unmount_namespace_SOURCES = \ +- unmount-namespace.c +- +-if IS_BIONIC +-unmount_namespace_SOURCES += \ +- ../src/include/lxcmntent.c ../src/include/lxcmntent.h +-endif +- + EXTRA_DIST=$(hooks_SCRIPTS) +-- +1.8.3.1 + diff --git a/0120-remove-unuse-unmount-namespace.patch b/0120-remove-unuse-unmount-namespace.patch new file mode 100644 index 0000000..8127da7 --- /dev/null +++ b/0120-remove-unuse-unmount-namespace.patch @@ -0,0 +1,25 @@ +From 14cba1d8fc2139afeb0db68c969540c3315768f2 Mon Sep 17 00:00:00 2001 +From: LiuHao +Date: Thu, 5 Sep 2019 11:48:57 +0800 +Subject: [PATCH 120/122] remove unuse unmount-namespace + +Signed-off-by: LiuHao +--- + lxc.spec.in | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/lxc.spec.in b/lxc.spec.in +index 7fcd811..2ca12fe 100644 +--- a/lxc.spec.in ++++ b/lxc.spec.in +@@ -259,7 +259,6 @@ fi + %{_libdir}/*.a + %{_libdir}/%{name} + %{_localstatedir}/* +-%{_libexecdir}/%{name}/hooks/unmount-namespace + %{_libexecdir}/%{name}/lxc-apparmor-load + %{_libexecdir}/%{name}/lxc-monitord + %attr(4111,root,root) %{_libexecdir}/%{name}/lxc-user-nic +-- +1.8.3.1 + diff --git a/0121-optimize-log-when-root-path-is-invalid.patch b/0121-optimize-log-when-root-path-is-invalid.patch new file mode 100644 index 0000000..8bc5ce9 --- /dev/null +++ b/0121-optimize-log-when-root-path-is-invalid.patch @@ -0,0 +1,26 @@ +From a466acb2c1e5d54822e9a7b93f75e9ff93ad511a Mon Sep 17 00:00:00 2001 +From: TanYifeng +Date: Sat, 21 Sep 2019 06:19:25 -0400 +Subject: [PATCH 121/122] optimize log when root path is invalid + +Signed-off-by: TanYifeng +--- + src/lxc/conf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 0b10a2d..5fd65e7 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -4881,7 +4881,7 @@ static char *get_root_path(const char *path, const char *backend) + strcmp(backend, "loop") == 0) { + tmp = strrchr(path, ':'); + if (tmp == NULL) { +- ERROR("Out of memory"); ++ ERROR("Invalid root path format"); + return NULL; + } + tmp++; +-- +1.8.3.1 + diff --git a/0122-lxc-fix-code-reivew-errors.patch b/0122-lxc-fix-code-reivew-errors.patch new file mode 100644 index 0000000..5feefc2 --- /dev/null +++ b/0122-lxc-fix-code-reivew-errors.patch @@ -0,0 +1,210 @@ +From 2313b7a2a444d841e57dca83814e7b17e67354db Mon Sep 17 00:00:00 2001 +From: LiFeng +Date: Thu, 26 Sep 2019 07:47:19 -0400 +Subject: [PATCH 122/122] lxc: fix code reivew errors + +Signed-off-by: LiFeng +--- + src/lxc/commands.c | 2 +- + src/lxc/commands_utils.c | 2 +- + src/lxc/confile.c | 4 ++-- + src/lxc/json/json_common.c | 15 +++++---------- + src/lxc/lxccontainer.c | 6 ++++-- + src/lxc/terminal.c | 8 +++++--- + src/lxc/utils.c | 2 +- + 7 files changed, 19 insertions(+), 20 deletions(-) + +diff --git a/src/lxc/commands.c b/src/lxc/commands.c +index fa02a4b..7d6cf6f 100644 +--- a/src/lxc/commands.c ++++ b/src/lxc/commands.c +@@ -1083,7 +1083,7 @@ int lxc_cmd_set_terminal_fifos(const char *name, const char *lxcpath, const char + if (tmp == NULL) + return -1; + ret = snprintf(tmp, len, "%s%s%s%s%s", cmd_in_fifo, split, cmd_out_fifo, split, cmd_err_fifo); +- if (ret < 0) ++ if (ret < 0 || ret >= len) + return -1; + + struct lxc_cmd_rr cmd = { +diff --git a/src/lxc/commands_utils.c b/src/lxc/commands_utils.c +index f48f118..56ecce7 100644 +--- a/src/lxc/commands_utils.c ++++ b/src/lxc/commands_utils.c +@@ -144,7 +144,7 @@ int lxc_make_abstract_socket_name(char *path, size_t pathlen, + } + + ret = snprintf(offset, len, "%s/%s/%s", lxcpath, name, suffix); +- if (ret < 0) { ++ if (ret < 0 || ret >= len) { + ERROR("Failed to create abstract socket name"); + return -1; + } +diff --git a/src/lxc/confile.c b/src/lxc/confile.c +index 3a02e09..3eaae4a 100644 +--- a/src/lxc/confile.c ++++ b/src/lxc/confile.c +@@ -3834,7 +3834,7 @@ static int get_config_prlimit(const char *key, char *retv, int inlen, + partlen = STRLITERALLEN("unlimited"); + } else { + partlen = snprintf(buf, MAX_LIMIT_BUF_LEN, "%" PRIu64, (uint64_t)lim->limit.rlim_cur); +- if (partlen < 0) { ++ if (partlen < 0 || partlen >= MAX_LIMIT_BUF_LEN) { + return -1; + } + } +@@ -3844,7 +3844,7 @@ static int get_config_prlimit(const char *key, char *retv, int inlen, + (void)memcpy(buf + partlen, ":unlimited", STRLITERALLEN(":unlimited") + 1); + } else { + nret = snprintf(buf + partlen, (MAX_LIMIT_BUF_LEN - partlen), ":%" PRIu64, (uint64_t)lim->limit.rlim_max); +- if (nret < 0) { ++ if (nret < 0 || nret >= (MAX_LIMIT_BUF_LEN - partlen)) { + return -1; + } + } +diff --git a/src/lxc/json/json_common.c b/src/lxc/json/json_common.c +index ed2fe83..ec20c59 100755 +--- a/src/lxc/json/json_common.c ++++ b/src/lxc/json/json_common.c +@@ -17,7 +17,7 @@ yajl_gen_status reformat_uint(void *ctx, long long unsigned int num) { + int ret; + + ret = snprintf(numstr, MAX_NUM_STR_LEN, "%llu", num); +- if (ret < 0) { ++ if (ret < 0 || ret >= MAX_NUM_STR_LEN) { + return yajl_gen_in_error_state; + } + return reformat_number(ctx, (const char *)numstr, strlen(numstr)); +@@ -28,7 +28,7 @@ yajl_gen_status reformat_int(void *ctx, long long int num) { + int ret; + + ret = snprintf(numstr, MAX_NUM_STR_LEN, "%lld", num); +- if (ret < 0) { ++ if (ret < 0 || ret >= MAX_NUM_STR_LEN) { + return yajl_gen_in_error_state; + } + return reformat_number(ctx, (const char *)numstr, strlen(numstr)); +@@ -400,7 +400,7 @@ yajl_gen_status gen_json_map_int_int(void *ctx, json_map_int_int *map, struct pa + char numstr[MAX_NUM_STR_LEN]; + int nret; + nret = snprintf(numstr, MAX_NUM_STR_LEN, "%lld", (long long int)map->keys[i]); +- if (nret < 0) { ++ if (nret < 0 || nret >= MAX_NUM_STR_LEN) { + if (!*err && asprintf(err, "Error to print string") < 0) { + *(err) = safe_strdup("error allocating memory"); + } +@@ -541,7 +541,7 @@ yajl_gen_status gen_json_map_int_bool(void *ctx, json_map_int_bool *map, struct + char numstr[MAX_NUM_STR_LEN]; + int nret; + nret = snprintf(numstr, MAX_NUM_STR_LEN, "%lld", (long long int)map->keys[i]); +- if (nret < 0) { ++ if (nret < 0 || nret >= MAX_NUM_STR_LEN) { + if (!*err && asprintf(err, "Error to print string") < 0) { + *(err) = safe_strdup("error allocating memory"); + } +@@ -569,11 +569,6 @@ yajl_gen_status gen_json_map_int_bool(void *ctx, json_map_int_bool *map, struct + + void free_json_map_int_bool(json_map_int_bool *map) { + if (map != NULL) { +- size_t i; +- for (i = 0; i < map->len; i++) { +- // No need to free key for type int +- // No need to free value for type bool +- } + free(map->keys); + map->keys = NULL; + free(map->values); +@@ -677,7 +672,7 @@ yajl_gen_status gen_json_map_int_string(void *ctx, json_map_int_string *map, str + char numstr[MAX_NUM_STR_LEN]; + int nret; + nret = snprintf(numstr, MAX_NUM_STR_LEN, "%lld", (long long int)map->keys[i]); +- if (nret < 0) { ++ if (nret < 0 || nret >= MAX_NUM_STR_LEN) { + if (!*err && asprintf(err, "Error to print string") < 0) { + *(err) = safe_strdup("error allocating memory"); + } +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index 5a72483..9f9cbfc 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -3200,7 +3200,7 @@ static bool container_destroy(struct lxc_container *c, + ERROR("Failed to destroy directory \"%s\" for \"%s\"", path, + c->name); + ret = snprintf(msg, BUFSIZ, "Failed to destroy directory \"%s\": %s", path, errno ? strerror(errno) : "error"); +- if (ret < 0) { ++ if (ret < 0 || ret >= BUFSIZ) { + ERROR("Sprintf failed"); + goto out; + } +@@ -5276,6 +5276,7 @@ static int set_start_extral_configs(struct lxc_container *c) + char fpath[PATH_MAX] = {0}; + parser_error jerr = NULL; + int ret = -1; ++ int nret = 0; + container_start_generate_config *start_conf = NULL; + struct lxc_conf *lconf = c->lxc_conf; + size_t i = 0; +@@ -5288,7 +5289,8 @@ static int set_start_extral_configs(struct lxc_container *c) + } + lconf = c->lxc_conf; + } +- if (snprintf(fpath, PATH_MAX, "%s/%s/%s", c->config_path, c->name, START_GENERATE_CONFIG) < 0) { ++ nret = snprintf(fpath, PATH_MAX, "%s/%s/%s", c->config_path, c->name, START_GENERATE_CONFIG); ++ if (nret < 0 || nret >= PATH_MAX) { + fprintf(stderr, "Sprintf config path failed\n"); + return -1; + } +diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c +index 32c69a4..e81f57e 100644 +--- a/src/lxc/terminal.c ++++ b/src/lxc/terminal.c +@@ -242,13 +242,13 @@ static int lxc_terminal_rename_old_log_file(struct lxc_terminal *terminal) + + for (i = terminal->log_rotate - 1; i > 1; i--) { + ret = snprintf(tmp, PATH_MAX, "%s.%u", terminal->log_path, i); +- if (ret < 0) { ++ if (ret < 0 || ret >= PATH_MAX) { + return -EFBIG; + } + free(rename_fname); + rename_fname = safe_strdup(tmp); + ret = snprintf(tmp, PATH_MAX, "%s.%u", terminal->log_path, (i - 1)); +- if (ret < 0) { ++ if (ret < 0 || ret >= PATH_MAX) { + free(rename_fname); + return -EFBIG; + } +@@ -415,6 +415,7 @@ static bool get_time_buffer(struct timespec *timestamp, char *timebuffer, + int32_t nanos = 0; + time_t seconds; + size_t len = 0; ++ int ret = 0; + + if (!timebuffer || !maxsize) { + return false; +@@ -426,7 +427,8 @@ static bool get_time_buffer(struct timespec *timestamp, char *timebuffer, + + nanos = (int32_t)timestamp->tv_nsec; + len = strlen(timebuffer); +- if (snprintf(timebuffer + len, (maxsize - len), ".%09dZ", nanos) < 0) { ++ ret = snprintf(timebuffer + len, (maxsize - len), ".%09dZ", nanos); ++ if (ret < 0 || ret >= (maxsize - len)) { + return false; + } + +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index c83c7a3..31bcac7 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -2041,7 +2041,7 @@ void lxc_write_error_message(int errfd, const char *format, ...) + va_start(argp, format); + ret = vsnprintf(errbuf, BUFSIZ, format, argp); + va_end(argp); +- if (ret < 0) ++ if (ret < 0 || ret >= BUFSIZ) + SYSERROR("Failed to call vsnprintf"); + sret = write(errfd, errbuf, strlen(errbuf)); + if (sret < 0) +-- +1.8.3.1 + diff --git a/lxc-2.0.6-fix-lxc-net.patch b/lxc-2.0.6-fix-lxc-net.patch new file mode 100644 index 0000000..684cee3 --- /dev/null +++ b/lxc-2.0.6-fix-lxc-net.patch @@ -0,0 +1,11 @@ +diff -up lxc-2.0.6/config/init/systemd/lxc-net.service.in.orig lxc-2.0.6/config/init/systemd/lxc-net.service.in +--- lxc-2.0.6/config/init/systemd/lxc-net.service.in.orig 2016-11-23 20:15:59.000000000 +0100 ++++ lxc-2.0.6/config/init/systemd/lxc-net.service.in 2016-12-04 21:55:24.149093437 +0100 +@@ -1,6 +1,7 @@ + [Unit] + Description=LXC network bridge setup + After=network-online.target ++Wants=network-online.target + Before=lxc.service + + [Service] diff --git a/lxc-2.0.7-fix-init.patch b/lxc-2.0.7-fix-init.patch new file mode 100644 index 0000000..38f771d --- /dev/null +++ b/lxc-2.0.7-fix-init.patch @@ -0,0 +1,46 @@ +diff -up lxc-2.0.7/config/init/sysvinit/lxc-containers.in.orig lxc-2.0.7/config/init/sysvinit/lxc-containers.in +--- lxc-2.0.7/config/init/sysvinit/lxc-containers.in.orig 2017-01-23 18:45:30.000000000 +0100 ++++ lxc-2.0.7/config/init/sysvinit/lxc-containers.in 2017-01-29 13:00:23.934781187 +0100 +@@ -2,7 +2,7 @@ + # + # lxc Start/Stop LXC autoboot containers + # +-# chkconfig: 345 99 01 ++# chkconfig: - 99 01 + # description: Starts/Stops all LXC containers configured for autostart. + # + ### BEGIN INIT INFO +@@ -11,8 +11,8 @@ + # Required-Stop: $syslog $remote_fs + # Should-Start: cgroupfs-mount + # Should-Stop: cgroupfs-mount +-# Default-Start: 2 3 4 5 +-# Default-Stop: 0 1 6 ++# Default-Start: ++# Default-Stop: + # Short-Description: Bring up/down LXC autostart containers + # Description: Bring up/down LXC autostart containers + ### END INIT INFO +diff -up lxc-2.0.7/config/init/sysvinit/lxc-net.in.orig lxc-2.0.7/config/init/sysvinit/lxc-net.in +--- lxc-2.0.7/config/init/sysvinit/lxc-net.in.orig 2017-01-23 18:45:30.000000000 +0100 ++++ lxc-2.0.7/config/init/sysvinit/lxc-net.in 2017-01-29 13:00:23.935781166 +0100 +@@ -2,7 +2,7 @@ + # + # lxc-net Start/Stop LXC Networking + # +-# chkconfig: 345 98 01 ++# chkconfig: - 98 01 + # description: Starts/Stops LXC Network Bridge + # + ### BEGIN INIT INFO +@@ -11,8 +11,8 @@ + # Required-Stop: $syslog $remote_fs + # Should-Start: + # Should-Stop: +-# Default-Start: 2 3 4 5 +-# Default-Stop: 0 1 6 ++# Default-Start: ++# Default-Stop: + # Short-Description: Bring up/down LXC Network Bridge + # Description: Bring up/down LXC Network Bridge + ### END INIT INFO diff --git a/lxc-3.0.3.tar.gz b/lxc-3.0.3.tar.gz new file mode 100644 index 0000000..46ba17b Binary files /dev/null and b/lxc-3.0.3.tar.gz differ diff --git a/lxc-CVE-2019-5736-runC-rexec-callers-as-memfd.patch b/lxc-CVE-2019-5736-runC-rexec-callers-as-memfd.patch new file mode 100644 index 0000000..833386e --- /dev/null +++ b/lxc-CVE-2019-5736-runC-rexec-callers-as-memfd.patch @@ -0,0 +1,401 @@ +From 113a0557d7651385d30e181a23c8e68e696ad67f Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Sat, 26 Jan 2019 01:19:29 +0100 +Subject: [PATCH] CVE-2019-5736 (runC): rexec callers as memfd +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Adam Iwaniuk and Borys Popławski discovered that an attacker can compromise the +runC host binary from inside a privileged runC container. As a result, this +could be exploited to gain root access on the host. runC is used as the default +runtime for containers with Docker, containerd, Podman, and CRI-O. + +The attack can be made when attaching to a running container or when starting a +container running a specially crafted image. For example, when runC attaches +to a container the attacker can trick it into executing itself. This could be +done by replacing the target binary inside the container with a custom binary +pointing back at the runC binary itself. As an example, if the target binary +was /bin/bash, this could be replaced with an executable script specifying the +interpreter path #!/proc/self/exe (/proc/self/exec is a symbolic link created +by the kernel for every process which points to the binary that was executed +for that process). As such when /bin/bash is executed inside the container, +instead the target of /proc/self/exe will be executed - which will point to the +runc binary on the host. The attacker can then proceed to write to the target +of /proc/self/exe to try and overwrite the runC binary on the host. However in +general, this will not succeed as the kernel will not permit it to be +overwritten whilst runC is executing. To overcome this, the attacker can +instead open a file descriptor to /proc/self/exe using the O_PATH flag and then +proceed to reopen the binary as O_WRONLY through /proc/self/fd/ and try to +write to it in a busy loop from a separate process. Ultimately it will succeed +when the runC binary exits. After this the runC binary is compromised and can +be used to attack other containers or the host itself. + +This attack is only possible with privileged containers since it requires root +privilege on the host to overwrite the runC binary. Unprivileged containers +with a non-identity ID mapping do not have the permission to write to the host +binary and therefore are unaffected by this attack. + +LXC is also impacted in a similar manner by this vulnerability, however as the +LXC project considers privileged containers to be unsafe no CVE has been +assigned for this issue for LXC. Quoting from the +https://linuxcontainers.org/lxc/security/ project's Security information page: + +"As privileged containers are considered unsafe, we typically will not consider +new container escape exploits to be security issues worthy of a CVE and quick +fix. We will however try to mitigate those issues so that accidental damage to +the host is prevented." + +To prevent this attack, LXC has been patched to create a temporary copy of the +calling binary itself when it starts or attaches to containers. To do this LXC +creates an anonymous, in-memory file using the memfd_create() system call and +copies itself into the temporary in-memory file, which is then sealed to +prevent further modifications. LXC then executes this sealed, in-memory file +instead of the original on-disk binary. Any compromising write operations from +a privileged container to the host LXC binary will then write to the temporary +in-memory binary and not to the host binary on-disk, preserving the integrity +of the host LXC binary. Also as the temporary, in-memory LXC binary is sealed, +writes to this will also fail. + +Note: memfd_create() was added to the Linux kernel in the 3.17 release. + +Signed-off-by: Christian Brauner +Co-Developed-by: Aleksa Sarai +Acked-by: Serge Hallyn +--- + configure.ac | 12 +++ + src/lxc/Makefile.am | 4 + + src/lxc/file_utils.c | 41 +++++++++- + src/lxc/file_utils.h | 1 + + src/lxc/rexec.c | 181 +++++++++++++++++++++++++++++++++++++++++++++ + src/lxc/syscall_wrappers.h | 14 ++++ + 6 files changed, 252 insertions(+), 1 deletion(-) + create mode 100644 src/lxc/rexec.c + +diff --git a/configure.ac b/configure.ac +index 950c8dd..631e607 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -706,6 +706,17 @@ AC_ARG_ENABLE([thread-safety], + [], [enable_thread_safety=yes]) + AM_CONDITIONAL([ENFORCE_THREAD_SAFETY], [test "x$enable_thread_safety" = "xyes"]) + ++AC_ARG_ENABLE([memfd-rexec], ++ [AC_HELP_STRING([--enable-memfd-rexec], [enforce liblxc as a memfd to protect against certain symlink attacks [default=yes]])], ++ [], [enable_memfd_rexec=yes]) ++AM_CONDITIONAL([ENFORCE_MEMFD_REXEC], [test "x$enable_memfd_rexec" = "xyes"]) ++if test "x$enable_memfd_rexec" = "xyes"; then ++ AC_DEFINE([ENFORCE_MEMFD_REXEC], 1, [Rexec liblxc as memfd]) ++ AC_MSG_RESULT([yes]) ++else ++ AC_MSG_RESULT([no]) ++fi ++ + # Files requiring some variable expansion + AC_CONFIG_FILES([ + Makefile +@@ -934,6 +945,7 @@ Security features: + - Linux capabilities: $enable_capabilities + - seccomp: $enable_seccomp + - SELinux: $enable_selinux ++ - memfd rexec: $enable_memfd_rexec + + PAM: + - PAM module: $enable_pam +diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am +index 08e2fab..8bbfdaf 100644 +--- a/src/lxc/Makefile.am ++++ b/src/lxc/Makefile.am +@@ -173,6 +173,10 @@ if !HAVE_STRLCAT + liblxc_la_SOURCES += ../include/strlcat.c ../include/strlcat.h + endif + ++if ENFORCE_MEMFD_REXEC ++liblxc_la_SOURCES += rexec.c ++endif ++ + AM_CFLAGS = -DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \ + -DLXCPATH=\"$(LXCPATH)\" \ + -DLXC_GLOBAL_CONF=\"$(LXC_GLOBAL_CONF)\" \ +diff --git a/src/lxc/file_utils.c b/src/lxc/file_utils.c +index f89aa63..930fd73 100644 +--- a/src/lxc/file_utils.c ++++ b/src/lxc/file_utils.c +@@ -31,7 +31,7 @@ + #include "config.h" + #include "file_utils.h" + #include "macro.h" +-#include "string.h" ++#include "string_utils.h" + + int lxc_write_to_file(const char *filename, const void *buf, size_t count, + bool add_newline, mode_t mode) +@@ -327,3 +327,42 @@ again: + + return ret; + } ++ ++char *file_to_buf(char *path, size_t *length) ++{ ++ int fd; ++ char buf[PATH_MAX]; ++ char *copy = NULL; ++ ++ if (!length) ++ return NULL; ++ ++ fd = open(path, O_RDONLY | O_CLOEXEC); ++ if (fd < 0) ++ return NULL; ++ ++ *length = 0; ++ for (;;) { ++ int n; ++ char *old = copy; ++ ++ n = lxc_read_nointr(fd, buf, sizeof(buf)); ++ if (n < 0) ++ goto on_error; ++ if (!n) ++ break; ++ ++ copy = must_realloc(old, (*length + n) * sizeof(*old)); ++ memcpy(copy + *length, buf, n); ++ *length += n; ++ } ++ ++ close(fd); ++ return copy; ++ ++on_error: ++ close(fd); ++ free(copy); ++ ++ return NULL; ++} +diff --git a/src/lxc/file_utils.h b/src/lxc/file_utils.h +index 6361557..518a61a 100644 +--- a/src/lxc/file_utils.h ++++ b/src/lxc/file_utils.h +@@ -55,5 +55,6 @@ extern bool is_fs_type(const struct statfs *fs, fs_type_magic magic_val); + extern FILE *fopen_cloexec(const char *path, const char *mode); + extern ssize_t lxc_sendfile_nointr(int out_fd, int in_fd, off_t *offset, + size_t count); ++extern char *file_to_buf(char *path, size_t *length); + + #endif /* __LXC_FILE_UTILS_H */ +diff --git a/src/lxc/rexec.c b/src/lxc/rexec.c +new file mode 100644 +index 0000000..396bd61 +--- /dev/null ++++ b/src/lxc/rexec.c +@@ -0,0 +1,181 @@ ++/* liblxcapi ++ * ++ * Copyright © 2019 Christian Brauner . ++ * Copyright © 2019 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 _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++#include ++#include ++#include ++#include ++ ++#include "config.h" ++#include "file_utils.h" ++#include "raw_syscalls.h" ++#include "string_utils.h" ++#include "syscall_wrappers.h" ++ ++#define LXC_MEMFD_REXEC_SEALS \ ++ (F_SEAL_SEAL | F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE) ++ ++static int push_vargs(char *data, int data_length, char ***output) ++{ ++ int num = 0; ++ char *cur = data; ++ ++ if (!data || *output) ++ return -1; ++ ++ *output = must_realloc(NULL, sizeof(**output)); ++ ++ while (cur < data + data_length) { ++ num++; ++ *output = must_realloc(*output, (num + 1) * sizeof(**output)); ++ ++ (*output)[num - 1] = cur; ++ cur += strlen(cur) + 1; ++ } ++ (*output)[num] = NULL; ++ return num; ++} ++ ++static int parse_exec_params(char ***argv, char ***envp) ++{ ++ int ret; ++ char *cmdline = NULL, *env = NULL; ++ size_t cmdline_size, env_size; ++ ++ cmdline = file_to_buf("/proc/self/cmdline", &cmdline_size); ++ if (!cmdline) ++ goto on_error; ++ ++ env = file_to_buf("/proc/self/environ", &env_size); ++ if (!env) ++ goto on_error; ++ ++ ret = push_vargs(cmdline, cmdline_size, argv); ++ if (ret <= 0) ++ goto on_error; ++ ++ ret = push_vargs(env, env_size, envp); ++ if (ret <= 0) ++ goto on_error; ++ ++ return 0; ++ ++on_error: ++ free(env); ++ free(cmdline); ++ ++ return -1; ++} ++ ++static int is_memfd(void) ++{ ++ int fd, saved_errno, seals; ++ ++ fd = open("/proc/self/exe", O_RDONLY | O_CLOEXEC); ++ if (fd < 0) ++ return -ENOTRECOVERABLE; ++ ++ seals = fcntl(fd, F_GET_SEALS); ++ saved_errno = errno; ++ close(fd); ++ errno = saved_errno; ++ if (seals < 0) ++ return -EINVAL; ++ ++ return seals == LXC_MEMFD_REXEC_SEALS; ++} ++ ++static void lxc_rexec_as_memfd(char **argv, char **envp, const char *memfd_name) ++{ ++ int saved_errno; ++ ssize_t bytes_sent; ++ int fd = -1, memfd = -1; ++ ++ memfd = memfd_create(memfd_name, MFD_ALLOW_SEALING | MFD_CLOEXEC); ++ if (memfd < 0) ++ return; ++ ++ fd = open("/proc/self/exe", O_RDONLY | O_CLOEXEC); ++ if (fd < 0) ++ goto on_error; ++ ++ /* sendfile() handles up to 2GB. */ ++ bytes_sent = lxc_sendfile_nointr(memfd, fd, NULL, LXC_SENDFILE_MAX); ++ saved_errno = errno; ++ close(fd); ++ errno = saved_errno; ++ if (bytes_sent < 0) ++ goto on_error; ++ ++ if (fcntl(memfd, F_ADD_SEALS, LXC_MEMFD_REXEC_SEALS)) ++ goto on_error; ++ ++ fexecve(memfd, argv, envp); ++ ++on_error: ++ saved_errno = errno; ++ close(memfd); ++ errno = saved_errno; ++} ++ ++static int lxc_rexec(const char *memfd_name) ++{ ++ int ret; ++ char **argv = NULL, **envp = NULL; ++ ++ ret = is_memfd(); ++ if (ret < 0 && ret == -ENOTRECOVERABLE) { ++ fprintf(stderr, ++ "%s - Failed to determine whether this is a memfd\n", ++ strerror(errno)); ++ return -1; ++ } else if (ret > 0) { ++ return 0; ++ } ++ ++ ret = parse_exec_params(&argv, &envp); ++ if (ret < 0) { ++ fprintf(stderr, ++ "%s - Failed to parse command line parameters\n", ++ strerror(errno)); ++ return -1; ++ } ++ ++ lxc_rexec_as_memfd(argv, envp, memfd_name); ++ fprintf(stderr, "%s - Failed to rexec as memfd\n", strerror(errno)); ++ return -1; ++} ++ ++/** ++ * This function will copy any binary that calls liblxc into a memory file and ++ * will use the memfd to rexecute the binary. This is done to prevent attacks ++ * through the /proc/self/exe symlink to corrupt the host binary when host and ++ * container are in the same user namespace or have set up an identity id ++ * mapping: CVE-2019-5736. ++ */ ++__attribute__((constructor)) static void liblxc_rexec(void) ++{ ++ if (lxc_rexec("liblxc")) { ++ fprintf(stderr, "Failed to re-execute liblxc via memory file descriptor\n"); ++ _exit(EXIT_FAILURE); ++ } ++} +diff --git a/src/lxc/syscall_wrappers.h b/src/lxc/syscall_wrappers.h +index 42d94db..dca4d15 100644 +--- a/src/lxc/syscall_wrappers.h ++++ b/src/lxc/syscall_wrappers.h +@@ -58,6 +58,20 @@ static inline long __keyctl(int cmd, unsigned long arg2, unsigned long arg3, + #define keyctl __keyctl + #endif + ++#ifndef F_LINUX_SPECIFIC_BASE ++#define F_LINUX_SPECIFIC_BASE 1024 ++#endif ++#ifndef F_ADD_SEALS ++#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9) ++#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10) ++#endif ++#ifndef F_SEAL_SEAL ++#define F_SEAL_SEAL 0x0001 ++#define F_SEAL_SHRINK 0x0002 ++#define F_SEAL_GROW 0x0004 ++#define F_SEAL_WRITE 0x0008 ++#endif ++ + #ifndef HAVE_MEMFD_CREATE + static inline int memfd_create(const char *name, unsigned int flags) { + #ifndef __NR_memfd_create +-- +1.8.3.1 + diff --git a/lxc.spec b/lxc.spec new file mode 100644 index 0000000..f45fe64 --- /dev/null +++ b/lxc.spec @@ -0,0 +1,428 @@ +%global with_seccomp 1 +%global _release 20190926 +%global debug_package %{nil} + +Name: lxc +Version: 3.0.3 +Release: %{_release}%{?dist} +Summary: Linux Containers userspace tools +License: LGPLv2+ +URL: http://linuxcontainers.org +Source0: http://linuxcontainers.org/downloads/%{name}-%{version}.tar.gz +Patch6000: lxc-2.0.7-fix-init.patch +Patch6001: lxc-2.0.6-fix-lxc-net.patch +Patch6002: lxc-CVE-2019-5736-runC-rexec-callers-as-memfd.patch +Patch9003: 0001-confile-add-lxc.isulad.init.args-config-interface.patch +Patch9004: 0002-namespace-add-support-share-namespace-by-path.patch +Patch9005: 0003-confile-add-lxc.isulad.populate.device-interface.patch +Patch9006: 0004-support-isulad-fifo-log.patch +Patch9007: 0005-auto-mount-cgroup-sys-and-proc.patch +Patch9008: 0006-conf.c-fix-bug-when-set-no-ro-mount-mount-propagatio.patch +Patch9009: 0007-use-isulad-log-format.patch +Patch9010: 0008-isulad-modify-exit-code-and-stop-signal.patch +Patch9011: 0009-lxc_start-add-default-terminal-fifos.patch +Patch9012: 0010-Save-pid-ppid-info-into-file-for-isulad.patch +Patch9013: 0011-Add-exit-FIFO-to-monitor-state-of-lxc-monitor.patch +Patch9014: 0012-Init-fifos-in-lxc_attach_terminal.patch +Patch9015: 0013-isulad-set-env-home-in-container.patch +Patch9016: 0014-support-rotate-for-container-log-file.patch +Patch9017: 0015-fix-high-gcc-compile-bug.patch +Patch9018: 0016-add-masked-paths-and-ro-paths.patch +Patch9019: 0017-isulad-check-cgroup-cpu.shares-after-setted.patch +Patch9020: 0018-lxc-attach-add-support-terminal-fifos.patch +Patch9021: 0019-remount-cgroup-readonly-and-make-soft-link-of-subcgr.patch +Patch9022: 0020-fix-log-error-when-symlink-subcgroup.patch +Patch9023: 0021-lxc-attch-add-error-message.patch +Patch9024: 0022-support-rootfs-mount-propagation.patch +Patch9025: 0023-attach.c-change-uid-and-gid-from-lxc-container-confi.patch +Patch9026: 0024-isulad-support-symlink-in-mount-entry-and-not-permit.patch +Patch9027: 0025-support-oci-hooks.patch +Patch9028: 0026-remove-filelock-and-do-not-destroy-directory-when-de.patch +Patch9029: 0027-fix-bug-of-memory-leak.patch +Patch9030: 0028-support-rootfs-for-container.patch +Patch9031: 0029-add-start-timeout-to-limit-start-time.patch +Patch9032: 0030-support-block-device-as-rootfs.patch +Patch9033: 0031-clean-add-clean-resources-api.patch +Patch9034: 0032-Drop-all-caps-when-cap.keep-ISULAD_KEEP_NONE.patch +Patch9035: 0033-support-mount-squashfs-in-mount-entry.patch +Patch9036: 0034-some-small-bugfix.patch +Patch9037: 0035-lxc-fixup-builds-with-newer-glibc.patch +Patch9038: 0036-drop_caps-add-drop-caps-of-current-process.patch +Patch9039: 0037-restore-default-signal-handlers-and-set-umask-0027.patch +Patch9040: 0038-make-the-given-terminal-as-controlling-terminal.patch +Patch9041: 0039-print-error-message-when-container-start-failed.patch +Patch9042: 0040-add-timeout-200ms-for-cmds-send-to-lxc-monitor.patch +Patch9043: 0041-return-1-when-_lxc_start-fails.patch +Patch9044: 0042-lxc-seccomp-adopt-to-lxc3.0.patch +Patch9045: 0043-check-null-pointer-of-handler-to-fix-coredump-of-att.patch +Patch9046: 0044-support-space-in-volume-mount-and-env.patch +Patch9047: 0045-add_terminal_fifos-Add-terminal-fifos-dynamically.patch +Patch9048: 0046-Do-not-test-cgroup-writeable.patch +Patch9049: 0047-Fix-memory-leak-in-lxc_global_config_value.patch +Patch9050: 0048-clear-ONLCR-flag-from-master-of-terminal.patch +Patch9051: 0049-Add-100ms-timeout-for-console-epoll.patch +Patch9052: 0050-seccomp-add-rules-for-specified-architecture-only.patch +Patch9053: 0051-if-ocihook-is-empty.patch +Patch9054: 0052-Fix-seccomp-fail-when-all-specified-in-config.patch +Patch9055: 0053-destroy-empty-cgroup-path-return-ture.patch +Patch9056: 0054-fix-invalid-log-message.patch +Patch9057: 0055-Fix-compile-error.patch +Patch9058: 0056-caps-use-_LINUX_CAPABILITY_VERSION_3-to-set-cap.patch +Patch9059: 0057-confile-add-support-umask.patch +Patch9060: 0058-do-not-check-ppid-when-set-death-signal.patch +Patch9061: 0059-delete-unused-variable-ppid.patch +Patch9062: 0060-using-json-file-to-write-console-log-of-container.patch +Patch9063: 0061-Fix-hook-use-the-path-args-envs-execvp-dirctory.patch +Patch9064: 0062-setup-sysctls-before-set-read-only-path-and-masked-p.patch +Patch9065: 0063-lxc-ignore-systemcall-load-failure-error.patch +Patch9066: 0064-lxc-Reduce-seccomp-processing-log-level.patch +Patch9067: 0065-Storage-return-true-if-storage_init-init-fail.patch +Patch9068: 0066-lxc-Pids-limit-does-not-report-an-error-after-execut.patch +Patch9069: 0067-lxc-report-error-when-remove-directory-failed.patch +Patch9070: 0068-support-record-stdout-stderr-log-of-container-consol.patch +Patch9071: 0069-lxc-killall-processes-if-container-shared-pid-namesp.patch +Patch9072: 0070-lxc-signal-all-process-for-shared-container-when-con.patch +Patch9073: 0071-lxc-get-cgroup-path-according-to-cgroup-mountpoint.patch +Patch9074: 0072-lxc-adapt-to-docker-18.09.patch +Patch9075: 0073-lxc-support-set-additional-groups.patch +Patch9076: 0074-lxc-only-add-valid-fd-to-mainloop.patch +Patch9077: 0075-lxc-add-timeout-for-attach.patch +Patch9078: 0076-lxc-delete-unused-variable.patch +Patch9079: 0077-lxc-set-negative-files.limit-to-max-and-fix-bug-of-s.patch +Patch9080: 0078-Run-pre-start-hook-before-chroot.patch +Patch9081: 0079-inherid-env-from-parent-in-oci-hooks.patch +Patch9082: 0080-lxc-fix-compile-error.patch +Patch9083: 0081-lxc-Change-the-range-of-attach-timeout.patch +Patch9084: 0082-lxc-fix-memory-leak-cause-by-setenv.patch +Patch9085: 0083-lxc-free-lxc-handler.patch +Patch9086: 0084-lxc-memory-leak-of-lxc_grow_array.patch +Patch9087: 0085-lxc-update-json-file-from-isulad.patch +Patch9088: 0086-confile-add-support-systemd.patch +Patch9089: 0087-lxc-adapt-to-spec-of-oci-hook.patch +Patch9090: 0088-fix-lxc-build-error.patch +Patch9091: 0089-lxc-add-get-container-processes-pids-func.patch +Patch9092: 0090-lxc-remove-unused-variable.patch +Patch9093: 0091-lxc-support-namespaced-kernel-params-can-be-changed-.patch +Patch9094: 0092-lxc-add-output-error-when-create-unified-cgroup.patch +Patch9095: 0093-optimize-isulad_kit-operator.patch +Patch9096: 0094-exec-load-uid-gid-and-groups.patch +Patch9097: 0095-lxc-don-t-use-the-unified-hierarchy-for-the-systemd-.patch +Patch9098: 0096-close-inherited-fd-in-hook-process.patch +Patch9099: 0097-lxc-report-error-when-fork-exec-error-for-hooks.patch +Patch9100: 0098-lxc-make-dev-bind-mount-from-host-tmpfs-for-system-c.patch +Patch9101: 0099-terminal-do-not-close-the-master-fd-of-pty.patch +Patch9102: 0100-start-add-check-save-pid-info-file.patch +Patch9103: 0101-lxc-fix-code-error.patch +Patch9104: 0102-lxc-fix-compile-warnings.patch +Patch9105: 0103-lxc-fix-code-error-in-conf.c.patch +Patch9106: 0104-lxc-fix-code-error.patch +Patch9107: 0105-lxc-fix-code-error-warnings.patch +Patch9108: 0106-set-timeout-to-1s-for-cmds-send-to-lxc-monitor.patch +Patch9109: 0107-add-log-for-failure-of-rename-file.patch +Patch9110: 0108-check-calloc-input-valid.patch +Patch9111: 0109-add-secure-compile-flags-to-lxc.patch +Patch9112: 0110-add-doc-for-lxc.patch +Patch9113: 0111-lxc-use-safe_strdup-instead-of-strdup.patch +Patch9114: 0112-fix-secure-errors.patch +Patch9115: 0113-Malloc-parameter-check-and-judgment.patch +Patch9116: 0114-lxc-fix-code-errors.patch +Patch9117: 0115-fix-compile-error-on-ubuntu.patch +Patch9118: 0116-lxc-set-base-cgroup-path-to.patch +Patch9119: 0117-pupulate-device-with-dir-mode-750-and-set-uid-gid.patch +Patch9120: 0118-fix-sscanf-return-value-check.patch +Patch9121: 0119-remove-unuse-binary.patch +Patch9122: 0120-remove-unuse-unmount-namespace.patch +Patch9123: 0121-optimize-log-when-root-path-is-invalid.patch +Patch9124: 0122-lxc-fix-code-reivew-errors.patch + +BuildRequires: systemd-units +BuildRequires: git libtool +BuildRequires: docbook2X doxygen +BuildRequires: chrpath +%if 0%{?with_seccomp} +BuildRequires: pkgconfig(libseccomp) +%endif +BuildRequires: libcap libcap-devel +BuildRequires: libselinux-devel +BuildRequires: yajl yajl-devel +BuildRequires: libsecurec libsecurec-devel +BuildRequires: pkgconfig(bash-completion) + +Requires: rsync +Requires(post): systemd +Requires(preun): systemd +Requires(postun): systemd +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig + +%{!?_pkgdocdir: %global _pkgdocdir %{_docdir}/%{name}-%{version}} + +%description +Containers are insulated areas inside a system, which have their own namespace +for filesystem, network, PID, IPC, CPU and memory allocation and which can be +created using the Control Group and Namespace features included in the Linux +kernel. + +This package provides the lxc-* tools and libraries for running %{name} +applications, which can be used to start a single daemon in a container, or to +boot an entire "containerized" system, and to manage and debug your containers. + +%package devel +Summary: Development files for %{name} +Requires: %{name} = %{version}-%{release} +Requires: pkgconfig + +%description devel +The %{name}-devel package contains header files ,library and templates needed for +development of the Linux containers. + + +%package help +Summary: Documentation and templates for %{name} +BuildArch: noarch + +%description help +This package contains documentation for %{name} for creating containers. + +%prep +%setup -q -n %{name}-%{version} +%patch6000 -p1 +%patch6001 -p1 +%patch6002 -p1 +%patch9003 -p1 +%patch9004 -p1 +%patch9005 -p1 +%patch9006 -p1 +%patch9007 -p1 +%patch9008 -p1 +%patch9009 -p1 +%patch9010 -p1 +%patch9011 -p1 +%patch9012 -p1 +%patch9013 -p1 +%patch9014 -p1 +%patch9015 -p1 +%patch9016 -p1 +%patch9017 -p1 +%patch9018 -p1 +%patch9019 -p1 +%patch9020 -p1 +%patch9021 -p1 +%patch9022 -p1 +%patch9023 -p1 +%patch9024 -p1 +%patch9025 -p1 +%patch9026 -p1 +%patch9027 -p1 +%patch9028 -p1 +%patch9029 -p1 +%patch9030 -p1 +%patch9031 -p1 +%patch9032 -p1 +%patch9033 -p1 +%patch9034 -p1 +%patch9035 -p1 +%patch9036 -p1 +%patch9037 -p1 +%patch9038 -p1 +%patch9039 -p1 +%patch9040 -p1 +%patch9041 -p1 +%patch9042 -p1 +%patch9043 -p1 +%patch9044 -p1 +%patch9045 -p1 +%patch9046 -p1 +%patch9047 -p1 +%patch9048 -p1 +%patch9049 -p1 +%patch9050 -p1 +%patch9051 -p1 +%patch9052 -p1 +%patch9053 -p1 +%patch9054 -p1 +%patch9055 -p1 +%patch9056 -p1 +%patch9057 -p1 +%patch9058 -p1 +%patch9059 -p1 +%patch9060 -p1 +%patch9061 -p1 +%patch9062 -p1 +%patch9063 -p1 +%patch9064 -p1 +%patch9065 -p1 +%patch9066 -p1 +%patch9067 -p1 +%patch9068 -p1 +%patch9069 -p1 +%patch9070 -p1 +%patch9071 -p1 +%patch9072 -p1 +%patch9073 -p1 +%patch9074 -p1 +%patch9075 -p1 +%patch9076 -p1 +%patch9077 -p1 +%patch9078 -p1 +%patch9079 -p1 +%patch9080 -p1 +%patch9081 -p1 +%patch9082 -p1 +%patch9083 -p1 +%patch9084 -p1 +%patch9085 -p1 +%patch9086 -p1 +%patch9087 -p1 +%patch9088 -p1 +%patch9089 -p1 +%patch9090 -p1 +%patch9091 -p1 +%patch9092 -p1 +%patch9093 -p1 +%patch9094 -p1 +%patch9095 -p1 +%patch9096 -p1 +%patch9097 -p1 +%patch9098 -p1 +%patch9099 -p1 +%patch9100 -p1 +%patch9101 -p1 +%patch9102 -p1 +%patch9103 -p1 +%patch9104 -p1 +%patch9105 -p1 +%patch9106 -p1 +%patch9107 -p1 +%patch9108 -p1 +%patch9109 -p1 +%patch9110 -p1 +%patch9111 -p1 +%patch9112 -p1 +%patch9113 -p1 +%patch9114 -p1 +%patch9115 -p1 +%patch9116 -p1 +%patch9117 -p1 +%patch9118 -p1 +%patch9119 -p1 +%patch9120 -p1 +%patch9121 -p1 +%patch9122 -p1 +%patch9123 -p1 +%patch9124 -p1 + +%build +%configure --with-distro=fedora --enable-doc --enable-api-docs \ + --disable-silent-rules --docdir=%{_pkgdocdir} --disable-rpath \ + --disable-static --disable-apparmor --enable-selinux \ +%if 0%{?with_seccomp} + --enable-seccomp \ +%endif + --with-init-script=systemd --disable-werror + +%{make_build} + +%install +%{make_install} +mkdir -p %{buildroot}%{_sharedstatedir}/%{name} + +for file in $(find %{buildroot}/usr/bin/lxc-* -type f -exec file {} ';' | grep "\" | awk -F ':' '{print $1}') +do + strip --strip-debug ${file} + chrpath -d ${file} +done + +for file in $(find %{buildroot}/usr/sbin/* -type f -exec file {} ';' | grep "\" | awk -F ':' '{print $1}') +do + strip --strip-debug ${file} + chrpath -d ${file} +done + +for file in $(find %{buildroot}/usr/libexec/lxc/lxc-* -type f -exec file {} ';' | grep "\" | awk -F ':' '{print $1}') +do + strip --strip-debug ${file} + chrpath -d ${file} +done + +strip --strip-debug %{buildroot}/usr/lib64/liblxc.so +chrpath -d %{buildroot}/usr/lib64/liblxc.so + +# docs +mkdir -p %{buildroot}%{_pkgdocdir}/api +cp -a AUTHORS README %{buildroot}%{_pkgdocdir} +cp -a doc/api/html/* %{buildroot}%{_pkgdocdir}/api/ + +# cache dir +mkdir -p %{buildroot}%{_localstatedir}/cache/%{name} + +# remove libtool .la file +rm -rf %{buildroot}%{_libdir}/liblxc.la + +%check +make check + +%post +%{?ldconfig} +%systemd_post %{name}-net.service +%systemd_post %{name}.service +%systemd_post %{name}@.service + +%preun +%systemd_preun %{name}-net.service +%systemd_preun %{name}.service +%systemd_preun %{name}@.service + +%postun +%{?ldconfig} +%systemd_postun %{name}-net.service +%systemd_postun %{name}.service +%systemd_postun %{name}@.service + +%files +%defattr(-,root,root) +%{_bindir}/%{name}-* +%{_datadir}/%{name}/%{name}.functions +%dir %{_datadir}/bash-completion +%dir %{_datadir}/bash-completion/completions +%{_datadir}/bash-completion/completions/%{name} +%{_libdir}/liblxc.so +%{_libdir}/liblxc.so.* +%{_libdir}/%{name} +%{_libexecdir}/%{name} +%{_sbindir}/init.%{name} +%{_sharedstatedir}/%{name} +%dir %{_sysconfdir}/%{name} +%config(noreplace) %{_sysconfdir}/%{name}/default.conf +%config(noreplace) %{_sysconfdir}/sysconfig/%{name} +%license COPYING +%dir %{_pkgdocdir} +%{_pkgdocdir}/AUTHORS +%{_pkgdocdir}/README +%{_unitdir}/%{name}.service +%{_unitdir}/%{name}@.service +%{_unitdir}/%{name}-net.service +%dir %{_localstatedir}/cache/%{name} + +%files devel +%defattr(-,root,root) +%{_includedir}/%{name}/* +%{_libdir}/pkgconfig/%{name}.pc +%dir %{_datadir}/%{name} +%{_datadir}/%{name}/hooks +%{_datadir}/%{name}/%{name}-patch.py* +%{_datadir}/%{name}/selinux +%dir %{_datadir}/%{name}/templates +%{_datadir}/%{name}/templates/lxc-* +%dir %{_datadir}/%{name}/config +%{_datadir}/%{name}/config/* + +%files help +%dir %{_pkgdocdir} +%{_pkgdocdir}/* +%{_mandir}/man1/%{name}* +%{_mandir}/*/man1/%{name}* +%{_mandir}/man5/%{name}* +%{_mandir}/man7/%{name}* +%{_mandir}/*/man5/%{name}* +%{_mandir}/*/man7/%{name}*