commit 8330d04949bda07f8d8a60ef8864737399024049 Author: zhuchunyi Date: Wed Nov 6 19:42:23 2019 +0800 update code diff --git a/0001-systemd-up.patch b/0001-systemd-up.patch new file mode 100644 index 0000000..da7c36c --- /dev/null +++ b/0001-systemd-up.patch @@ -0,0 +1,18 @@ +diff --git a/config/init/systemd/lxcfs.service b/config/init/systemd/lxcfs.service +index 95e3ee9..0995607 100644 +--- a/config/init/systemd/lxcfs.service ++++ b/config/init/systemd/lxcfs.service +@@ -5,10 +5,11 @@ Before=lxc.service + Documentation=man:lxcfs(1) + + [Service] +-ExecStart=/usr/bin/lxcfs /var/lib/lxcfs/ ++ExecStart=/usr/bin/lxcfs /var/lib/lxc/lxcfs/ ++ExecStartPost=/usr/local/bin/isulad-lxcfs-toolkit remount -a + KillMode=process + Restart=on-failure +-ExecStopPost=-/bin/fusermount -u /var/lib/lxcfs ++ExecStopPost=-/bin/fusermount -u /var/lib/lxc/ + Delegate=yes + + [Install] diff --git a/0002-prestart.patch b/0002-prestart.patch new file mode 100644 index 0000000..0c76fee --- /dev/null +++ b/0002-prestart.patch @@ -0,0 +1,10 @@ +--- a/config/init/systemd/lxcfs.service ++++ b/config/init/systemd/lxcfs.service +@@ -5,6 +5,7 @@ Before=lxc.service + Documentation=man:lxcfs(1) + + [Service] ++ExecStartPre=/usr/local/bin/isulad-lxcfs-toolkit prestart + ExecStart=/usr/bin/lxcfs /var/lib/lxc/lxcfs/ + ExecStartPost=/usr/local/bin/isulad-lxcfs-toolkit remount -a + KillMode=process diff --git a/0003-remove-sysvinit-upstart.patch b/0003-remove-sysvinit-upstart.patch new file mode 100644 index 0000000..852be66 --- /dev/null +++ b/0003-remove-sysvinit-upstart.patch @@ -0,0 +1,30 @@ +diff -uprN a/config/init/Makefile.am b/config/init/Makefile.am +--- a/config/init/Makefile.am 2018-01-22 17:06:23.591442076 +0800 ++++ b/config/init/Makefile.am 2018-01-22 17:06:55.035440266 +0800 +@@ -1 +1 @@ +-SUBDIRS = systemd sysvinit upstart ++SUBDIRS = systemd +diff -uprN a/config/init/Makefile.in b/config/init/Makefile.in +--- a/config/init/Makefile.in 2018-01-22 17:06:23.590442076 +0800 ++++ b/config/init/Makefile.in 2018-01-22 17:07:15.005439117 +0800 +@@ -311,7 +311,7 @@ target_alias = @target_alias@ + top_build_prefix = @top_build_prefix@ + top_builddir = @top_builddir@ + top_srcdir = @top_srcdir@ +-SUBDIRS = systemd sysvinit upstart ++SUBDIRS = systemd + all: all-recursive + + .SUFFIXES: +diff -uprN a/configure.ac b/configure.ac +--- a/configure.ac 2018-01-22 17:06:23.587442076 +0800 ++++ b/configure.ac 2018-01-22 17:08:33.111434622 +0800 +@@ -14,8 +14,6 @@ AC_CONFIG_FILES([ + config/Makefile + config/init/Makefile + config/init/systemd/Makefile +- config/init/sysvinit/Makefile +- config/init/upstart/Makefile + share/Makefile + share/00-lxcfs.conf + share/lxc.mount.hook diff --git a/0004-show-dev-name-in-container.patch b/0004-show-dev-name-in-container.patch new file mode 100644 index 0000000..e835102 --- /dev/null +++ b/0004-show-dev-name-in-container.patch @@ -0,0 +1,171 @@ +diff --git a/bindings.c b/bindings.c +index 6387012..91de9f9 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -3743,12 +3743,136 @@ static int proc_uptime_read(char *buf, size_t size, off_t offset, + return total_len; + } + ++struct devinfo { ++ char name[100]; ++ int major, minor; ++ struct devinfo *next; ++}; ++ ++int getns(pid_t pid, char *ns_type) ++{ ++ char fpath[100]; ++ memset(fpath, 0, sizeof(fpath)); ++ snprintf(fpath, 99, "/proc/%d/ns/%s", pid, ns_type); ++ return open(fpath, O_RDONLY); ++} ++ ++struct devinfo* container_dev_read(pid_t pid) { ++ int nsfd; ++ DIR *dir; ++ struct dirent *ptr; ++ struct stat dev_stat; ++ struct devinfo *head = NULL, *end; ++ char fpath[100], dev_name[100]; ++ pid_t child_pid; ++ int mypipe[2]; ++ int dev_num; ++ FILE *stream; ++ ++ if (pipe(mypipe) < 0) { ++ perror("Error creating pipe"); ++ return head; ++ } ++ ++ child_pid = fork(); ++ if (child_pid < 0) { ++ close(mypipe[0]); ++ close(mypipe[1]); ++ perror("Error forking child"); ++ return head; ++ } ++ if (child_pid == 0) { ++ close(mypipe[0]); ++ stream = fdopen(mypipe[1], "w"); ++ if (stream == NULL) { ++ lxcfs_error("Error opening pipe for writing: %s\n", strerror(errno)); ++ goto child_out; ++ } ++ nsfd = getns(pid, "mnt"); ++ if (nsfd < 0) { ++ lxcfs_error("Error getting mnt ns: %s\n", strerror(errno)); ++ goto child_out; ++ } ++ if (setns(nsfd, 0) < 0) { ++ lxcfs_error("Error setting mnt ns: %s\n", strerror(errno)); ++ goto child_out; ++ } ++ dir = opendir("/dev"); ++ if (dir == NULL) { ++ lxcfs_error("Error opening dir /dev: %s\n", strerror(errno)); ++ goto child_out; ++ } ++ while ((ptr = readdir(dir)) != NULL) { ++ if (ptr->d_type != DT_BLK && ptr->d_type != DT_CHR) { ++ continue; ++ } ++ memset(fpath, 0, sizeof(fpath)); ++ snprintf(fpath, 99, "/dev/%s", ptr->d_name); ++ stat(fpath, &dev_stat); ++ fprintf(stream, "%s %d ", ptr->d_name, dev_stat.st_rdev); ++ fflush(stream); ++ } ++ closedir(dir); ++ stat("/", &dev_stat); ++ dev_num = dev_stat.st_dev & (~0xf); ++ fprintf(stream, "sda %d end 0 ", dev_num); ++ fflush(stream); ++child_out: ++ fclose(stream); ++ exit(0); ++ } ++ ++ close(mypipe[1]); ++ stream = fdopen(mypipe[0], "r"); ++ if (stream == NULL) { ++ lxcfs_error("Error opening pipe for reading: %s\n", strerror(errno)); ++ goto err; ++ } ++ while (fscanf(stream, "%s%d", dev_name, &dev_num) == 2) { ++ if (dev_num == 0) { ++ break; ++ } ++ if (head == NULL) { ++ do { ++ head = (struct devinfo*)malloc(sizeof(struct devinfo)); ++ } while (!head); ++ end = head; ++ } else { ++ do { ++ end->next = (struct devinfo*)malloc(sizeof(struct devinfo)); ++ } while (!end->next); ++ end = end->next; ++ } ++ end->next = NULL; ++ strncpy(end->name, dev_name, 100); ++ end->major = (dev_num & 0xff00) >> 8; ++ end->minor = dev_num & 0x00ff; ++ } ++err: ++ if (stream) ++ fclose(stream); ++ if (child_pid > 0) ++ wait_for_pid(child_pid); ++ return head; ++} ++ ++void free_devinfo_list(struct devinfo *ptr) ++{ ++ struct devinfo *tmp; ++ while (ptr != NULL) { ++ tmp = ptr; ++ ptr = ptr->next; ++ free(tmp); ++ } ++} ++ + static int proc_diskstats_read(char *buf, size_t size, off_t offset, + struct fuse_file_info *fi) + { + char dev_name[72]; + struct fuse_context *fc = fuse_get_context(); + struct file_info *d = (struct file_info *)fi->fh; ++ struct devinfo *container_devinfo = NULL, *ptr; + char *cg; + char *io_serviced_str = NULL, *io_merged_str = NULL, *io_service_bytes_str = NULL, + *io_wait_time_str = NULL, *io_service_time_str = NULL; +@@ -3801,13 +3925,21 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset, + if (!f) + goto err; + ++ container_devinfo = container_dev_read(initpid); ++ + while (getline(&line, &linelen, f) != -1) { + ssize_t l; + char lbuf[256]; + ++ memset(dev_name, 0, sizeof(dev_name)); + i = sscanf(line, "%u %u %71s", &major, &minor, dev_name); + if (i != 3) + continue; ++ for (ptr = container_devinfo; ptr != NULL; ptr = ptr->next) { ++ if (major == ptr->major && minor == ptr->minor) { ++ strncpy(dev_name, ptr->name, 71); ++ } ++ } + + get_blkio_io_value(io_serviced_str, major, minor, "Read", &read); + get_blkio_io_value(io_serviced_str, major, minor, "Write", &write); +@@ -3873,6 +4005,7 @@ err: + free(io_service_bytes_str); + free(io_wait_time_str); + free(io_service_time_str); ++ free_devinfo_list(container_devinfo); + return rv; + } + diff --git a/0005-lxcfs-fix-cpuinfo-print.patch b/0005-lxcfs-fix-cpuinfo-print.patch new file mode 100644 index 0000000..f000ce3 --- /dev/null +++ b/0005-lxcfs-fix-cpuinfo-print.patch @@ -0,0 +1,23 @@ +diff -uprN a/bindings.c b/bindings.c +--- a/bindings.c 2018-08-16 09:36:58.751107328 +0800 ++++ b/bindings.c 2018-08-16 10:02:12.719191680 +0800 +@@ -3471,7 +3471,17 @@ static int proc_cpuinfo_read(char *buf, + + } + if (am_printing) { +- l = snprintf(cache, cache_size, "%s", line); ++ if (strncmp(line, "physical id", 11) == 0) { ++ l = snprintf(cache, cache_size, "physical id : %d\n", curcpu); ++ } else if (strncmp(line, "siblings", 8) == 0) { ++ l = snprintf(cache, cache_size, "siblings : 1\n"); ++ } else if (strncmp(line, "core id", 7) == 0) { ++ l = snprintf(cache, cache_size, "core id : 0\n"); ++ } else if (strncmp(line, "cpu cores", 9) == 0) { ++ l = snprintf(cache, cache_size, "cpu cores : 1\n"); ++ } else { ++ l = snprintf(cache, cache_size, "%s", line); ++ } + if (l < 0) { + perror("Error writing to cache"); + rv = 0; + diff --git a/0006-lxcfs-3.0.2-crashes-on-centos-7.patch b/0006-lxcfs-3.0.2-crashes-on-centos-7.patch new file mode 100644 index 0000000..8e34057 --- /dev/null +++ b/0006-lxcfs-3.0.2-crashes-on-centos-7.patch @@ -0,0 +1,11 @@ +diff -uprN a/bindings.c b/bindings.c +--- a/bindings.c 2018-08-17 04:12:24.000000000 +0800 ++++ b/bindings.c 2018-11-21 11:45:56.120000000 +0800 +@@ -1848,6 +1848,7 @@ + free(f->buf); + f->buf = NULL; + free(f); ++ f = NULL; + } + + int cg_releasedir(const char *path, struct fuse_file_info *fi) diff --git a/0007-fix-memory-leak.patch b/0007-fix-memory-leak.patch new file mode 100644 index 0000000..42b9b02 --- /dev/null +++ b/0007-fix-memory-leak.patch @@ -0,0 +1,338 @@ +diff --git a/../lxcfs-3.0.2/bindings.c b/bindings.c +index 713b7ea..c04993c 100644 +--- a/../lxcfs-3.0.2/bindings.c ++++ b/bindings.c +@@ -351,7 +351,7 @@ static void append_line(char **contents, size_t *len, char *line, ssize_t linele + *len = newlen; + } + +-static char *slurp_file(const char *from, int fd) ++static char *slurp_file(int fd) + { + char *line = NULL; + char *contents = NULL; +@@ -484,6 +484,7 @@ bool cgfs_set_value(const char *controller, const char *cgroup, const char *file + const char *value) + { + int ret, fd, cfd; ++ bool ret_bool; + size_t len; + char *fnam, *tmpc; + +@@ -495,16 +496,25 @@ bool cgfs_set_value(const char *controller, const char *cgroup, const char *file + * . + /cgroup + / + file + \0 + */ + len = strlen(cgroup) + strlen(file) + 3; +- fnam = alloca(len); ++ fnam = malloc(len); ++ if (!fnam) { ++ return false; ++ } + ret = snprintf(fnam, len, "%s%s/%s", *cgroup == '/' ? "." : "", cgroup, file); +- if (ret < 0 || (size_t)ret >= len) ++ if (ret < 0 || (size_t)ret >= len) { ++ free(fnam); + return false; ++ } + + fd = openat(cfd, fnam, O_WRONLY); +- if (fd < 0) ++ if (fd < 0) { ++ free(fnam); + return false; ++ } + +- return write_string(fnam, value, fd); ++ ret_bool = write_string(fnam, value, fd); ++ free(fnam); ++ return ret_bool; + } + + // Chown all the files in the cgroup directory. We do this when we create +@@ -874,16 +884,26 @@ bool cgfs_get_value(const char *controller, const char *cgroup, const char *file + * . + /cgroup + / + file + \0 + */ + len = strlen(cgroup) + strlen(file) + 3; +- fnam = alloca(len); ++ fnam = malloc(len); ++ if (!fnam) { ++ return false; ++ } + ret = snprintf(fnam, len, "%s%s/%s", *cgroup == '/' ? "." : "", cgroup, file); +- if (ret < 0 || (size_t)ret >= len) ++ if (ret < 0 || (size_t)ret >= len) { ++ free(fnam); + return false; ++ } + + fd = openat(cfd, fnam, O_RDONLY); +- if (fd < 0) ++ if (fd < 0) { ++ free(fnam); + return false; ++ } + +- *value = slurp_file(fnam, fd); ++ free(fnam); ++ store_lock(); ++ *value = slurp_file(fd); ++ store_unlock(); + return *value != NULL; + } + +@@ -3067,7 +3087,7 @@ static int read_file(const char *path, char *buf, size_t size, + static unsigned long get_memlimit(const char *cgroup, const char *file) + { + char *memlimit_str = NULL; +- unsigned long memlimit = -1; ++ unsigned long memlimit = 0; + + if (cgfs_get_value("memory", cgroup, file, &memlimit_str)) + memlimit = strtoul(memlimit_str, NULL, 10); +@@ -3079,15 +3099,19 @@ static unsigned long get_memlimit(const char *cgroup, const char *file) + + static unsigned long get_min_memlimit(const char *cgroup, const char *file) + { +- char *copy = strdupa(cgroup); ++ char copy[MAXPATHLEN]; ++ strcpy(copy, cgroup); + unsigned long memlimit = 0, retlimit; + + retlimit = get_memlimit(copy, file); ++ if (retlimit == 0) { ++ return retlimit; ++ } + + while (strcmp(copy, "/") != 0) { +- copy = dirname(copy); ++ dirname(copy); + memlimit = get_memlimit(copy, file); +- if (memlimit != -1 && memlimit < retlimit) ++ if (memlimit != 0 && memlimit < retlimit) + retlimit = memlimit; + }; + +@@ -3100,8 +3124,7 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, + struct fuse_context *fc = fuse_get_context(); + struct file_info *d = (struct file_info *)fi->fh; + char *cg; +- char *memusage_str = NULL, *memstat_str = NULL, +- *memswlimit_str = NULL, *memswusage_str = NULL; ++ char *memusage_str = NULL, *memstat_str = NULL, *memswusage_str = NULL; + unsigned long memlimit = 0, memusage = 0, memswlimit = 0, memswusage = 0, + cached = 0, hosttotal = 0, active_anon = 0, inactive_anon = 0, + active_file = 0, inactive_file = 0, unevictable = 0, shmem = 0, +@@ -3132,6 +3155,8 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, + prune_init_slice(cg); + + memlimit = get_min_memlimit(cg, "memory.limit_in_bytes"); ++ if (memlimit == 0) ++ goto err; + if (!cgfs_get_value("memory", cg, "memory.usage_in_bytes", &memusage_str)) + goto err; + if (!cgfs_get_value("memory", cg, "memory.stat", &memstat_str)) +@@ -3139,8 +3164,7 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, + + // Following values are allowed to fail, because swapaccount might be turned + // off for current kernel +- if(cgfs_get_value("memory", cg, "memory.memsw.limit_in_bytes", &memswlimit_str) && +- cgfs_get_value("memory", cg, "memory.memsw.usage_in_bytes", &memswusage_str)) ++ if (cgfs_get_value("memory", cg, "memory.memsw.usage_in_bytes", &memswusage_str)) + { + memswlimit = get_min_memlimit(cg, "memory.memsw.limit_in_bytes"); + memswusage = strtoul(memswusage_str, NULL, 10); +@@ -3161,9 +3185,9 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, + if (!f) + goto err; + ++ char *printme, lbuf[100]; + while (getline(&line, &linelen, f) != -1) { + ssize_t l; +- char *printme, lbuf[100]; + + memset(lbuf, 0, 100); + if (startswith(line, "MemTotal:")) { +@@ -3273,7 +3297,6 @@ err: + free(line); + free(cg); + free(memusage_str); +- free(memswlimit_str); + free(memswusage_str); + free(memstat_str); + return rv; +@@ -3285,7 +3308,7 @@ err: + */ + static char *get_cpuset(const char *cg) + { +- char *answer; ++ char *answer = NULL; + + if (!cgfs_get_value("cpuset", cg, "cpuset.cpus", &answer)) + return NULL; +@@ -3888,7 +3911,7 @@ static int proc_uptime_read(char *buf, size_t size, off_t offset, + } + + struct devinfo { +- char name[100]; ++ char *name; + int major, minor; + struct devinfo *next; + }; +@@ -3896,7 +3919,7 @@ struct devinfo { + int getns(pid_t pid, char *ns_type) + { + char fpath[100]; +- memset(fpath, 0, sizeof(fpath)); ++ memset(fpath, 0, sizeof(fpath)); + snprintf(fpath, 99, "/proc/%d/ns/%s", pid, ns_type); + return open(fpath, O_RDONLY); + } +@@ -3930,42 +3953,42 @@ struct devinfo* container_dev_read(pid_t pid) { + stream = fdopen(mypipe[1], "w"); + if (stream == NULL) { + lxcfs_error("Error opening pipe for writing: %s\n", strerror(errno)); +- goto child_out; ++ goto child_out; + } + nsfd = getns(pid, "mnt"); + if (nsfd < 0) { + lxcfs_error("Error getting mnt ns: %s\n", strerror(errno)); +- goto child_out; ++ goto child_out; + } + if (setns(nsfd, 0) < 0) { + lxcfs_error("Error setting mnt ns: %s\n", strerror(errno)); +- goto child_out; ++ goto child_out; + } + dir = opendir("/dev"); + if (dir == NULL) { + lxcfs_error("Error opening dir /dev: %s\n", strerror(errno)); +- goto child_out; ++ goto child_out; + } + while ((ptr = readdir(dir)) != NULL) { + if (ptr->d_type != DT_BLK && ptr->d_type != DT_CHR) { + continue; + } +- memset(fpath, 0, sizeof(fpath)); ++ memset(fpath, 0, sizeof(fpath)); + snprintf(fpath, 99, "/dev/%s", ptr->d_name); + stat(fpath, &dev_stat); + fprintf(stream, "%s %d ", ptr->d_name, dev_stat.st_rdev); + fflush(stream); + } +- closedir(dir); ++ closedir(dir); + stat("/", &dev_stat); + dev_num = dev_stat.st_dev & (~0xf); + fprintf(stream, "sda %d end 0 ", dev_num); + fflush(stream); +-child_out: +- fclose(stream); ++ fclose(stream); + exit(0); + } + ++child_out: + close(mypipe[1]); + stream = fdopen(mypipe[0], "r"); + if (stream == NULL) { +@@ -3977,24 +4000,24 @@ child_out: + break; + } + if (head == NULL) { +- do { +- head = (struct devinfo*)malloc(sizeof(struct devinfo)); +- } while (!head); ++ do { ++ head = (struct devinfo*)malloc(sizeof(struct devinfo)); ++ } while (!head); + end = head; + } else { +- do { +- end->next = (struct devinfo*)malloc(sizeof(struct devinfo)); +- } while (!end->next); ++ do { ++ end->next = (struct devinfo*)malloc(sizeof(struct devinfo)); ++ } while (!end->next); + end = end->next; + } + end->next = NULL; +- strncpy(end->name, dev_name, 100); ++ end->name = must_copy_string(dev_name); + end->major = (dev_num & 0xff00) >> 8; + end->minor = dev_num & 0x00ff; + } + err: +- if (stream) +- fclose(stream); ++ if (stream) ++ fclose(stream); + if (child_pid > 0) + wait_for_pid(child_pid); + return head; +@@ -4006,6 +4029,7 @@ void free_devinfo_list(struct devinfo *ptr) + while (ptr != NULL) { + tmp = ptr; + ptr = ptr->next; ++ free(tmp->name); + free(tmp); + } + } +@@ -4082,6 +4106,7 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset, + for (ptr = container_devinfo; ptr != NULL; ptr = ptr->next) { + if (major == ptr->major && minor == ptr->minor) { + strncpy(dev_name, ptr->name, 71); ++ dev_name[71] = '\0'; + } + } + +@@ -4159,7 +4184,7 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset, + struct fuse_context *fc = fuse_get_context(); + struct file_info *d = (struct file_info *)fi->fh; + char *cg = NULL; +- char *memswlimit_str = NULL, *memlimit_str = NULL, *memusage_str = NULL, *memswusage_str = NULL; ++ char *memusage_str = NULL, *memswusage_str = NULL; + unsigned long memswlimit = 0, memlimit = 0, memusage = 0, memswusage = 0, swap_total = 0, swap_free = 0; + ssize_t total_len = 0, rv = 0; + ssize_t l = 0; +@@ -4185,20 +4210,25 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset, + prune_init_slice(cg); + + memlimit = get_min_memlimit(cg, "memory.limit_in_bytes"); ++ if (memlimit == 0) ++ goto err; + + if (!cgfs_get_value("memory", cg, "memory.usage_in_bytes", &memusage_str)) + goto err; + + memusage = strtoul(memusage_str, NULL, 10); + +- if (cgfs_get_value("memory", cg, "memory.memsw.usage_in_bytes", &memswusage_str) && +- cgfs_get_value("memory", cg, "memory.memsw.limit_in_bytes", &memswlimit_str)) { ++ if (cgfs_get_value("memory", cg, "memory.memsw.usage_in_bytes", &memswusage_str)) { + + memswlimit = get_min_memlimit(cg, "memory.memsw.limit_in_bytes"); + memswusage = strtoul(memswusage_str, NULL, 10); + +- swap_total = (memswlimit - memlimit) / 1024; +- swap_free = (memswusage - memusage) / 1024; ++ if (memswlimit > memlimit) { ++ swap_total = (memswlimit - memlimit) / 1024; ++ } ++ if (memswusage > memusage) { ++ swap_free = (memswusage - memusage) / 1024; ++ } + } + + total_len = snprintf(d->buf, d->size, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"); +@@ -4246,8 +4276,6 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset, + + err: + free(cg); +- free(memswlimit_str); +- free(memlimit_str); + free(memusage_str); + free(memswusage_str); + return rv; diff --git a/0008-fix-concurrency-problem.patch b/0008-fix-concurrency-problem.patch new file mode 100644 index 0000000..a3d0dc1 --- /dev/null +++ b/0008-fix-concurrency-problem.patch @@ -0,0 +1,245 @@ +diff --git a/bindings.c b/bindings.c +index c04993c..9b9f180 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -110,6 +110,7 @@ struct pidns_init_store { + + static struct pidns_init_store *pidns_hash_table[PIDNS_HASH_SIZE]; + static pthread_mutex_t pidns_store_mutex = PTHREAD_MUTEX_INITIALIZER; ++static pthread_mutex_t slurp_file_mutex = PTHREAD_MUTEX_INITIALIZER; + static void lock_mutex(pthread_mutex_t *l) + { + int ret; +@@ -330,28 +331,31 @@ static inline void drop_trailing_newlines(char *s) + } + + #define BATCH_SIZE 50 +-static void dorealloc(char **mem, size_t oldlen, size_t newlen) ++char * dorealloc(char *mem, size_t oldlen, size_t newlen) + { + int newbatches = (newlen / BATCH_SIZE) + 1; + int oldbatches = (oldlen / BATCH_SIZE) + 1; + +- if (!*mem || newbatches > oldbatches) { ++ if (!mem || newbatches > oldbatches) { + char *tmp; + do { +- tmp = realloc(*mem, newbatches * BATCH_SIZE); ++ tmp = realloc(mem, newbatches * BATCH_SIZE); + } while (!tmp); +- *mem = tmp; ++ return tmp; + } ++ return mem; + } +-static void append_line(char **contents, size_t *len, char *line, ssize_t linelen) ++char * append_line(char *contents, size_t *len, char *line, ssize_t linelen) + { ++ char *tmp; + size_t newlen = *len + linelen; +- dorealloc(contents, *len, newlen + 1); +- memcpy(*contents + *len, line, linelen+1); ++ tmp = dorealloc(contents, *len, newlen + 1); ++ memcpy(tmp + *len, line, linelen+1); + *len = newlen; ++ return tmp; + } + +-static char *slurp_file(int fd) ++char *slurp_file(int fd) + { + char *line = NULL; + char *contents = NULL; +@@ -363,7 +367,7 @@ static char *slurp_file(int fd) + return NULL; + + while ((linelen = getline(&line, &len, f)) != -1) { +- append_line(&contents, &fulllen, line, linelen); ++ contents = append_line(contents, &fulllen, line, linelen); + } + fclose(f); + +@@ -870,15 +874,15 @@ void free_keys(struct cgfs_files **keys) + free(keys); + } + +-bool cgfs_get_value(const char *controller, const char *cgroup, const char *file, char **value) ++char * cgfs_get_value(const char *controller, const char *cgroup, const char *file) + { + int ret, fd, cfd; + size_t len; +- char *fnam, *tmpc; ++ char *fnam, *tmpc, *value; + + tmpc = find_mounted_controller(controller, &cfd); + if (!tmpc) +- return false; ++ return NULL; + + /* Make sure we pass a relative path to *at() family of functions. + * . + /cgroup + / + file + \0 +@@ -886,25 +890,25 @@ bool cgfs_get_value(const char *controller, const char *cgroup, const char *file + len = strlen(cgroup) + strlen(file) + 3; + fnam = malloc(len); + if (!fnam) { +- return false; ++ return NULL; + } + ret = snprintf(fnam, len, "%s%s/%s", *cgroup == '/' ? "." : "", cgroup, file); + if (ret < 0 || (size_t)ret >= len) { + free(fnam); +- return false; ++ return NULL; + } + + fd = openat(cfd, fnam, O_RDONLY); + if (fd < 0) { + free(fnam); +- return false; ++ return NULL; + } + + free(fnam); +- store_lock(); +- *value = slurp_file(fd); +- store_unlock(); +- return *value != NULL; ++ lock_mutex(&slurp_file_mutex); ++ value = slurp_file(fd); ++ unlock_mutex(&slurp_file_mutex); ++ return value; + } + + struct cgfs_files *cgfs_get_key(const char *controller, const char *cgroup, const char *file) +@@ -2288,7 +2292,7 @@ bool do_read_pids(pid_t tpid, const char *contrl, const char *cg, const char *fi + struct ucred cred; + size_t sz = 0, asz = 0; + +- if (!cgfs_get_value(contrl, cg, file, &tmpdata)) ++ if (!(tmpdata = cgfs_get_value(contrl, cg, file))) + return false; + + /* +@@ -2401,8 +2405,10 @@ int cg_read(const char *path, char *buf, size_t size, off_t offset, + strcmp(f->file, "cgroup.procs") == 0) + // special case - we have to translate the pids + r = do_read_pids(fc->pid, f->controller, f->cgroup, f->file, &data); +- else +- r = cgfs_get_value(f->controller, f->cgroup, f->file, &data); ++ else { ++ data = cgfs_get_value(f->controller, f->cgroup, f->file); ++ r = !data; ++ } + + if (!r) { + ret = -EINVAL; +@@ -3089,7 +3095,7 @@ static unsigned long get_memlimit(const char *cgroup, const char *file) + char *memlimit_str = NULL; + unsigned long memlimit = 0; + +- if (cgfs_get_value("memory", cgroup, file, &memlimit_str)) ++ if ((memlimit_str = cgfs_get_value("memory", cgroup, file))) + memlimit = strtoul(memlimit_str, NULL, 10); + + free(memlimit_str); +@@ -3099,8 +3105,7 @@ static unsigned long get_memlimit(const char *cgroup, const char *file) + + static unsigned long get_min_memlimit(const char *cgroup, const char *file) + { +- char copy[MAXPATHLEN]; +- strcpy(copy, cgroup); ++ char *copy = strdupa(cgroup); + unsigned long memlimit = 0, retlimit; + + retlimit = get_memlimit(copy, file); +@@ -3109,7 +3114,7 @@ static unsigned long get_min_memlimit(const char *cgroup, const char *file) + } + + while (strcmp(copy, "/") != 0) { +- dirname(copy); ++ copy = dirname(copy); + memlimit = get_memlimit(copy, file); + if (memlimit != 0 && memlimit < retlimit) + retlimit = memlimit; +@@ -3157,14 +3162,14 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, + memlimit = get_min_memlimit(cg, "memory.limit_in_bytes"); + if (memlimit == 0) + goto err; +- if (!cgfs_get_value("memory", cg, "memory.usage_in_bytes", &memusage_str)) ++ if (!(memusage_str = cgfs_get_value("memory", cg, "memory.usage_in_bytes"))) + goto err; +- if (!cgfs_get_value("memory", cg, "memory.stat", &memstat_str)) ++ if (!(memstat_str = cgfs_get_value("memory", cg, "memory.stat"))) + goto err; + + // Following values are allowed to fail, because swapaccount might be turned + // off for current kernel +- if (cgfs_get_value("memory", cg, "memory.memsw.usage_in_bytes", &memswusage_str)) ++ if (memswusage_str = cgfs_get_value("memory", cg, "memory.memsw.usage_in_bytes")) + { + memswlimit = get_min_memlimit(cg, "memory.memsw.limit_in_bytes"); + memswusage = strtoul(memswusage_str, NULL, 10); +@@ -3310,7 +3315,7 @@ static char *get_cpuset(const char *cg) + { + char *answer = NULL; + +- if (!cgfs_get_value("cpuset", cg, "cpuset.cpus", &answer)) ++ if (!(answer = cgfs_get_value("cpuset", cg, "cpuset.cpus"))) + return NULL; + return answer; + } +@@ -3835,7 +3840,7 @@ static unsigned long get_reaper_busy(pid_t task) + if (!cgroup) + goto out; + prune_init_slice(cgroup); +- if (!cgfs_get_value("cpuacct", cgroup, "cpuacct.usage", &usage_str)) ++ if (!(usage_str = cgfs_get_value("cpuacct", cgroup, "cpuacct.usage"))) + goto out; + usage = strtoul(usage_str, NULL, 10); + usage /= 1000000000; +@@ -4077,15 +4082,15 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset, + return read_file("/proc/diskstats", buf, size, d); + prune_init_slice(cg); + +- if (!cgfs_get_value("blkio", cg, "blkio.io_serviced_recursive", &io_serviced_str)) ++ if (!(io_serviced_str = cgfs_get_value("blkio", cg, "blkio.io_serviced_recursive"))) + goto err; +- if (!cgfs_get_value("blkio", cg, "blkio.io_merged_recursive", &io_merged_str)) ++ if (!(io_merged_str = cgfs_get_value("blkio", cg, "blkio.io_merged_recursive"))) + goto err; +- if (!cgfs_get_value("blkio", cg, "blkio.io_service_bytes_recursive", &io_service_bytes_str)) ++ if (!(io_service_bytes_str = cgfs_get_value("blkio", cg, "blkio.io_service_bytes_recursive"))) + goto err; +- if (!cgfs_get_value("blkio", cg, "blkio.io_wait_time_recursive", &io_wait_time_str)) ++ if (!(io_wait_time_str = cgfs_get_value("blkio", cg, "blkio.io_wait_time_recursive"))) + goto err; +- if (!cgfs_get_value("blkio", cg, "blkio.io_service_time_recursive", &io_service_time_str)) ++ if (!(io_service_time_str = cgfs_get_value("blkio", cg, "blkio.io_service_time_recursive"))) + goto err; + + +@@ -4213,12 +4218,12 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset, + if (memlimit == 0) + goto err; + +- if (!cgfs_get_value("memory", cg, "memory.usage_in_bytes", &memusage_str)) ++ if (!(memusage_str = cgfs_get_value("memory", cg, "memory.usage_in_bytes"))) + goto err; + + memusage = strtoul(memusage_str, NULL, 10); + +- if (cgfs_get_value("memory", cg, "memory.memsw.usage_in_bytes", &memswusage_str)) { ++ if (memswusage_str = cgfs_get_value("memory", cg, "memory.memsw.usage_in_bytes")) { + + memswlimit = get_min_memlimit(cg, "memory.memsw.limit_in_bytes"); + memswusage = strtoul(memswusage_str, NULL, 10); +@@ -4403,6 +4408,9 @@ int proc_read(const char *path, char *buf, size_t size, off_t offset, + { + struct file_info *f = (struct file_info *) fi->fh; + ++ if (!f->buf) ++ return -EINVAL; ++ + switch (f->type) { + case LXC_TYPE_PROC_MEMINFO: + return proc_meminfo_read(buf, size, offset, fi); diff --git a/0009-set-null-after-free.patch b/0009-set-null-after-free.patch new file mode 100644 index 0000000..a1dd0df --- /dev/null +++ b/0009-set-null-after-free.patch @@ -0,0 +1,878 @@ +diff --git a/bindings.c b/bindings.c +index 9b9f180..b921d7e 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -192,6 +192,7 @@ static void remove_initpid(struct pidns_init_store *e) + if (pidns_hash_table[h] == e) { + pidns_hash_table[h] = e->next; + free(e); ++ e = NULL; + return; + } + +@@ -200,6 +201,7 @@ static void remove_initpid(struct pidns_init_store *e) + if (tmp->next == e) { + tmp->next = e->next; + free(e); ++ e = NULL; + return; + } + tmp = tmp->next; +@@ -241,6 +243,7 @@ static void prune_initpid_store(void) + pidns_hash_table[i] = e->next; + e = e->next; + free(delme); ++ delme = NULL; + } else { + prev = e; + e = e->next; +@@ -337,7 +340,7 @@ char * dorealloc(char *mem, size_t oldlen, size_t newlen) + int oldbatches = (oldlen / BATCH_SIZE) + 1; + + if (!mem || newbatches > oldbatches) { +- char *tmp; ++ char *tmp = NULL; + do { + tmp = realloc(mem, newbatches * BATCH_SIZE); + } while (!tmp); +@@ -347,7 +350,7 @@ char * dorealloc(char *mem, size_t oldlen, size_t newlen) + } + char * append_line(char *contents, size_t *len, char *line, ssize_t linelen) + { +- char *tmp; ++ char *tmp = NULL; + size_t newlen = *len + linelen; + tmp = dorealloc(contents, *len, newlen + 1); + memcpy(tmp + *len, line, linelen+1); +@@ -490,7 +493,7 @@ bool cgfs_set_value(const char *controller, const char *cgroup, const char *file + int ret, fd, cfd; + bool ret_bool; + size_t len; +- char *fnam, *tmpc; ++ char *fnam = NULL, *tmpc = NULL; + + tmpc = find_mounted_controller(controller, &cfd); + if (!tmpc) +@@ -507,17 +510,20 @@ bool cgfs_set_value(const char *controller, const char *cgroup, const char *file + ret = snprintf(fnam, len, "%s%s/%s", *cgroup == '/' ? "." : "", cgroup, file); + if (ret < 0 || (size_t)ret >= len) { + free(fnam); ++ fnam = NULL; + return false; + } + + fd = openat(cfd, fnam, O_WRONLY); + if (fd < 0) { + free(fnam); ++ fnam = NULL; + return false; + } + + ret_bool = write_string(fnam, value, fd); + free(fnam); ++ fnam = NULL; + return ret_bool; + } + +@@ -565,7 +571,7 @@ int cgfs_create(const char *controller, const char *cg, uid_t uid, gid_t gid) + { + int cfd; + size_t len; +- char *dirnam, *tmpc; ++ char *dirnam = NULL, *tmpc = NULL; + + tmpc = find_mounted_controller(controller, &cfd); + if (!tmpc) +@@ -655,7 +661,7 @@ bool cgfs_remove(const char *controller, const char *cg) + { + int fd, cfd; + size_t len; +- char *dirnam, *tmpc; ++ char *dirnam = NULL, *tmpc = NULL; + bool bret; + + tmpc = find_mounted_controller(controller, &cfd); +@@ -682,7 +688,7 @@ bool cgfs_chmod_file(const char *controller, const char *file, mode_t mode) + { + int cfd; + size_t len; +- char *pathname, *tmpc; ++ char *pathname = NULL, *tmpc = NULL; + + tmpc = find_mounted_controller(controller, &cfd); + if (!tmpc) +@@ -702,7 +708,7 @@ bool cgfs_chmod_file(const char *controller, const char *file, mode_t mode) + static int chown_tasks_files(const char *dirname, uid_t uid, gid_t gid, int fd) + { + size_t len; +- char *fname; ++ char *fname = NULL; + + len = strlen(dirname) + strlen("/cgroup.procs") + 1; + fname = alloca(len); +@@ -719,7 +725,7 @@ int cgfs_chown_file(const char *controller, const char *file, uid_t uid, gid_t g + { + int cfd; + size_t len; +- char *pathname, *tmpc; ++ char *pathname = NULL, *tmpc = NULL; + + tmpc = find_mounted_controller(controller, &cfd); + if (!tmpc) +@@ -745,7 +751,7 @@ FILE *open_pids_file(const char *controller, const char *cgroup) + { + int fd, cfd; + size_t len; +- char *pathname, *tmpc; ++ char *pathname = NULL, *tmpc = NULL; + + tmpc = find_mounted_controller(controller, &cfd); + if (!tmpc) +@@ -771,7 +777,7 @@ static bool cgfs_iterate_cgroup(const char *controller, const char *cgroup, bool + { + int cfd, fd, ret; + size_t len; +- char *cg, *tmpc; ++ char *cg = NULL, *tmpc = NULL; + char pathname[MAXPATHLEN]; + size_t sz = 0, asz = 0; + struct dirent *dirent; +@@ -842,7 +848,7 @@ static bool cgfs_iterate_cgroup(const char *controller, const char *cgroup, bool + + static void *make_children_list_entry(const char *controller, const char *cgroup, const char *dir_entry) + { +- char *dup; ++ char *dup = NULL; + do { + dup = strdup(dir_entry); + } while (!dup); +@@ -859,7 +865,9 @@ void free_key(struct cgfs_files *k) + if (!k) + return; + free(k->name); ++ k->name = NULL; + free(k); ++ k = NULL; + } + + void free_keys(struct cgfs_files **keys) +@@ -872,13 +880,14 @@ void free_keys(struct cgfs_files **keys) + free_key(keys[i]); + } + free(keys); ++ keys = NULL; + } + + char * cgfs_get_value(const char *controller, const char *cgroup, const char *file) + { + int ret, fd, cfd; + size_t len; +- char *fnam, *tmpc, *value; ++ char *fnam = NULL, *tmpc = NULL, *value = NULL; + + tmpc = find_mounted_controller(controller, &cfd); + if (!tmpc) +@@ -895,16 +904,19 @@ char * cgfs_get_value(const char *controller, const char *cgroup, const char *fi + ret = snprintf(fnam, len, "%s%s/%s", *cgroup == '/' ? "." : "", cgroup, file); + if (ret < 0 || (size_t)ret >= len) { + free(fnam); ++ fnam = NULL; + return NULL; + } + + fd = openat(cfd, fnam, O_RDONLY); + if (fd < 0) { + free(fnam); ++ fnam = NULL; + return NULL; + } + + free(fnam); ++ fnam = NULL; + lock_mutex(&slurp_file_mutex); + value = slurp_file(fd); + unlock_mutex(&slurp_file_mutex); +@@ -915,7 +927,7 @@ struct cgfs_files *cgfs_get_key(const char *controller, const char *cgroup, cons + { + int ret, cfd; + size_t len; +- char *fnam, *tmpc; ++ char *fnam = NULL, *tmpc = NULL; + struct stat sb; + struct cgfs_files *newkey; + +@@ -978,7 +990,7 @@ bool is_child_cgroup(const char *controller, const char *cgroup, const char *f) + { + int cfd; + size_t len; +- char *fnam, *tmpc; ++ char *fnam = NULL, *tmpc = NULL; + int ret; + struct stat sb; + +@@ -1165,7 +1177,7 @@ static void must_strcat_pid(char **src, size_t *sz, size_t *asz, pid_t pid) + int tmplen = sprintf(tmp, "%d\n", (int)pid); + + if (!*src || tmplen + *sz + 1 >= *asz) { +- char *tmp; ++ char *tmp = NULL; + do { + tmp = realloc(*src, *asz + BUF_RESERVE_SIZE); + } while (!tmp); +@@ -1304,7 +1316,7 @@ static bool perms_include(int fmode, mode_t req_mode) + */ + static char *get_next_cgroup_dir(const char *taskcg, const char *querycg) + { +- char *start, *end; ++ char *start = NULL, *end = NULL; + + if (strlen(taskcg) <= strlen(querycg)) { + lxcfs_error("%s\n", "I was fed bad input."); +@@ -1374,6 +1386,7 @@ static char *get_pid_cgroup(pid_t pid, const char *contrl) + out: + fclose(f); + free(line); ++ line = NULL; + return answer; + } + +@@ -1419,7 +1432,7 @@ out: + #define INITSCOPE "/init.scope" + static void prune_init_slice(char *cg) + { +- char *point; ++ char *point = NULL; + size_t cg_len = strlen(cg), initscope_len = strlen(INITSCOPE); + + if (cg_len < initscope_len) +@@ -1445,7 +1458,7 @@ static bool caller_is_in_ancestor(pid_t pid, const char *contrl, const char *cg, + { + bool answer = false; + char *c2 = get_pid_cgroup(pid, contrl); +- char *linecmp; ++ char *linecmp = NULL; + + if (!c2) + return false; +@@ -1474,6 +1487,7 @@ static bool caller_is_in_ancestor(pid_t pid, const char *contrl, const char *cg, + + out: + free(c2); ++ c2 = NULL; + return answer; + } + +@@ -1483,7 +1497,7 @@ out: + static bool caller_may_see_dir(pid_t pid, const char *contrl, const char *cg) + { + bool answer = false; +- char *c2, *task_cg; ++ char *c2 = NULL, *task_cg = NULL; + size_t target_len, task_len; + + if (strcmp(cg, "/") == 0 || strcmp(cg, "./") == 0) +@@ -1525,6 +1539,7 @@ static bool caller_may_see_dir(pid_t pid, const char *contrl, const char *cg) + + out: + free(c2); ++ c2 = NULL; + return answer; + } + +@@ -1535,7 +1550,7 @@ out: + static char *pick_controller_from_path(struct fuse_context *fc, const char *path) + { + const char *p1; +- char *contr, *slash; ++ char *contr = NULL, *slash = NULL; + + if (strlen(path) < 9) { + errno = EACCES; +@@ -1570,7 +1585,7 @@ static char *pick_controller_from_path(struct fuse_context *fc, const char *path + */ + static const char *find_cgroup_in_path(const char *path) + { +- const char *p1; ++ const char *p1 = NULL; + + if (strlen(path) < 9) { + errno = EACCES; +@@ -1591,7 +1606,7 @@ static const char *find_cgroup_in_path(const char *path) + */ + static void get_cgdir_and_path(const char *cg, char **dir, char **last) + { +- char *p; ++ char *p = NULL; + + do { + *dir = strdup(cg); +@@ -1614,9 +1629,9 @@ int cg_getattr(const char *path, struct stat *sb) + struct timespec now; + struct fuse_context *fc = fuse_get_context(); + char * cgdir = NULL; +- char *last = NULL, *path1, *path2; ++ char *last = NULL, *path1 = NULL, *path2 = NULL; + struct cgfs_files *k = NULL; +- const char *cgroup; ++ const char *cgroup = NULL; + const char *controller = NULL; + int ret = -ENOENT; + +@@ -1716,14 +1731,15 @@ int cg_getattr(const char *path, struct stat *sb) + + out: + free(cgdir); ++ cgdir = NULL; + return ret; + } + + int cg_opendir(const char *path, struct fuse_file_info *fi) + { + struct fuse_context *fc = fuse_get_context(); +- const char *cgroup; +- struct file_info *dir_info; ++ const char *cgroup = NULL; ++ struct file_info *dir_info = NULL; + char *controller = NULL; + + if (!fc) +@@ -1847,9 +1863,12 @@ int cg_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset + out: + free_keys(list); + if (clist) { +- for (i = 0; clist[i]; i++) ++ for (i = 0; clist[i]; i++) { + free(clist[i]); ++ clist[i] = NULL; ++ } + free(clist); ++ clist = NULL; + } + return ret; + } +@@ -1858,7 +1877,7 @@ static void do_release_file_info(struct fuse_file_info *fi) + { + struct file_info *f = (struct file_info *)fi->fh; + +- if (!f) ++ if (!f || !f->buf) + return; + + fi->fh = 0; +@@ -1946,6 +1965,7 @@ int cg_open(const char *path, struct fuse_file_info *fi) + + out: + free(cgdir); ++ cgdir = NULL; + return ret; + } + +@@ -2010,6 +2030,7 @@ int cg_access(const char *path, int mode) + + out: + free(cgdir); ++ cgdir = NULL; + return ret; + } + +@@ -2304,6 +2325,7 @@ bool do_read_pids(pid_t tpid, const char *contrl, const char *cg, const char *fi + if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sock) < 0) { + perror("socketpair"); + free(tmpdata); ++ tmpdata = NULL; + return false; + } + +@@ -2355,6 +2377,7 @@ next: + + out: + free(tmpdata); ++ tmpdata = NULL; + if (cpid != -1) + wait_for_pid(cpid); + if (sock[0] != -1) { +@@ -2430,6 +2453,7 @@ int cg_read(const char *path, char *buf, size_t size, off_t offset, + + out: + free(data); ++ data = NULL; + return ret; + } + +@@ -2517,7 +2541,7 @@ static void pid_from_ns_wrapper(int sock, pid_t tpid) + */ + bool hostuid_to_ns(uid_t uid, pid_t pid, uid_t *answer) + { +- FILE *f; ++ FILE *f = NULL; + char line[400]; + + sprintf(line, "/proc/%d/uid_map", pid); +@@ -2790,6 +2814,7 @@ int cg_chown(const char *path, uid_t uid, gid_t gid) + out: + free_key(k); + free(cgdir); ++ cgdir = NULL; + + return ret; + } +@@ -2860,6 +2885,7 @@ int cg_chmod(const char *path, mode_t mode) + out: + free_key(k); + free(cgdir); ++ cgdir = NULL; + return ret; + } + +@@ -2913,7 +2939,9 @@ int cg_mkdir(const char *path, mode_t mode) + + out: + free(cgdir); ++ cgdir = NULL; + free(next); ++ next = NULL; + return ret; + } + +@@ -2974,7 +3002,9 @@ int cg_rmdir(const char *path) + + out: + free(cgdir); ++ cgdir = NULL; + free(next); ++ next = NULL; + return ret; + } + +@@ -2990,7 +3020,7 @@ static void parse_memstat(char *memstat, unsigned long *cached, + unsigned long *active_file, unsigned long *inactive_file, + unsigned long *unevictable, unsigned long *shmem) + { +- char *eol; ++ char *eol = NULL; + + while (*memstat) { + if (startswith(memstat, "total_cache")) { +@@ -3024,7 +3054,7 @@ static void parse_memstat(char *memstat, unsigned long *cached, + + static void get_blkio_io_value(char *str, unsigned major, unsigned minor, char *iotype, unsigned long *v) + { +- char *eol; ++ char *eol = NULL; + char key[32]; + + memset(key, 0, 32); +@@ -3083,6 +3113,7 @@ static int read_file(const char *path, char *buf, size_t size, + err: + fclose(f); + free(line); ++ line = NULL; + return rv; + } + +@@ -3099,6 +3130,7 @@ static unsigned long get_memlimit(const char *cgroup, const char *file) + memlimit = strtoul(memlimit_str, NULL, 10); + + free(memlimit_str); ++ memlimit_str = NULL; + + return memlimit; + } +@@ -3128,7 +3160,7 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, + { + struct fuse_context *fc = fuse_get_context(); + struct file_info *d = (struct file_info *)fi->fh; +- char *cg; ++ char *cg = NULL; + char *memusage_str = NULL, *memstat_str = NULL, *memswusage_str = NULL; + unsigned long memlimit = 0, memusage = 0, memswlimit = 0, memswusage = 0, + cached = 0, hosttotal = 0, active_anon = 0, inactive_anon = 0, +@@ -3190,7 +3222,7 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, + if (!f) + goto err; + +- char *printme, lbuf[100]; ++ char *printme = NULL, lbuf[100]; + while (getline(&line, &linelen, f) != -1) { + ssize_t l; + +@@ -3300,10 +3332,15 @@ err: + if (f) + fclose(f); + free(line); ++ line = NULL; + free(cg); ++ cg = NULL; + free(memusage_str); ++ memusage_str = NULL; + free(memswusage_str); ++ memswusage_str = NULL; + free(memstat_str); ++ memstat_str = NULL; + return rv; + } + +@@ -3348,7 +3385,7 @@ static int proc_cpuinfo_read(char *buf, size_t size, off_t offset, + { + struct fuse_context *fc = fuse_get_context(); + struct file_info *d = (struct file_info *)fi->fh; +- char *cg; ++ char *cg = NULL; + char *cpuset = NULL; + char *line = NULL; + size_t linelen = 0, total_len = 0, rv = 0; +@@ -3418,7 +3455,7 @@ static int proc_cpuinfo_read(char *buf, size_t size, off_t offset, + } + continue; + } else if (is_s390x && sscanf(line, "processor %d:", &cpu) == 1) { +- char *p; ++ char *p = NULL; + if (!cpu_in_cpuset(cpu, cpuset)) + continue; + curcpu ++; +@@ -3483,6 +3520,7 @@ static int proc_cpuinfo_read(char *buf, size_t size, off_t offset, + l = snprintf(cache, cache_size, "vendor_id : IBM/S390\n"); + if (l < 0 || l >= cache_size) { + free(origcache); ++ origcache = NULL; + goto err; + } + cache_size -= l; +@@ -3491,6 +3529,7 @@ static int proc_cpuinfo_read(char *buf, size_t size, off_t offset, + l = snprintf(cache, cache_size, "# processors : %d\n", curcpu + 1); + if (l < 0 || l >= cache_size) { + free(origcache); ++ origcache = NULL; + goto err; + } + cache_size -= l; +@@ -3498,6 +3537,7 @@ static int proc_cpuinfo_read(char *buf, size_t size, off_t offset, + total_len += l; + l = snprintf(cache, cache_size, "%s", origcache); + free(origcache); ++ origcache = NULL; + if (l < 0 || l >= cache_size) + goto err; + total_len += l; +@@ -3514,8 +3554,11 @@ err: + if (f) + fclose(f); + free(line); ++ line = NULL; + free(cpuset); ++ cpuset = NULL; + free(cg); ++ cg = NULL; + return rv; + } + +@@ -3655,7 +3698,7 @@ static int proc_stat_read(char *buf, size_t size, off_t offset, + { + struct fuse_context *fc = fuse_get_context(); + struct file_info *d = (struct file_info *)fi->fh; +- char *cg; ++ char *cg = NULL; + char *cpuset = NULL; + char *line = NULL; + size_t linelen = 0, total_len = 0, rv = 0; +@@ -3706,7 +3749,7 @@ static int proc_stat_read(char *buf, size_t size, off_t offset, + ssize_t l; + int cpu; + char cpu_char[10]; /* That's a lot of cores */ +- char *c; ++ char *c = NULL; + + if (strlen(line) == 0) + continue; +@@ -3815,8 +3858,11 @@ err: + if (f) + fclose(f); + free(line); ++ line = NULL; + free(cpuset); ++ cpuset = NULL; + free(cg); ++ cg = NULL; + return rv; + } + +@@ -3847,7 +3893,9 @@ static unsigned long get_reaper_busy(pid_t task) + + out: + free(cgroup); ++ cgroup = NULL; + free(usage_str); ++ usage_str = NULL; + return usage; + } + +@@ -3939,7 +3987,7 @@ struct devinfo* container_dev_read(pid_t pid) { + pid_t child_pid; + int mypipe[2]; + int dev_num; +- FILE *stream; ++ FILE *stream[2]; + + if (pipe(mypipe) < 0) { + perror("Error creating pipe"); +@@ -3955,8 +4003,8 @@ struct devinfo* container_dev_read(pid_t pid) { + } + if (child_pid == 0) { + close(mypipe[0]); +- stream = fdopen(mypipe[1], "w"); +- if (stream == NULL) { ++ stream[1] = fdopen(mypipe[1], "w"); ++ if (stream[1] == NULL) { + lxcfs_error("Error opening pipe for writing: %s\n", strerror(errno)); + goto child_out; + } +@@ -3981,26 +4029,26 @@ struct devinfo* container_dev_read(pid_t pid) { + memset(fpath, 0, sizeof(fpath)); + snprintf(fpath, 99, "/dev/%s", ptr->d_name); + stat(fpath, &dev_stat); +- fprintf(stream, "%s %d ", ptr->d_name, dev_stat.st_rdev); +- fflush(stream); ++ fprintf(stream[1], "%s %d ", ptr->d_name, dev_stat.st_rdev); ++ fflush(stream[1]); + } + closedir(dir); + stat("/", &dev_stat); + dev_num = dev_stat.st_dev & (~0xf); +- fprintf(stream, "sda %d end 0 ", dev_num); +- fflush(stream); +- fclose(stream); ++ fprintf(stream[1], "sda %d end 0 ", dev_num); ++ fflush(stream[1]); ++child_out: ++ fclose(stream[1]); + exit(0); + } + +-child_out: + close(mypipe[1]); +- stream = fdopen(mypipe[0], "r"); +- if (stream == NULL) { ++ stream[0] = fdopen(mypipe[0], "r"); ++ if (stream[0] == NULL) { + lxcfs_error("Error opening pipe for reading: %s\n", strerror(errno)); + goto err; + } +- while (fscanf(stream, "%s%d", dev_name, &dev_num) == 2) { ++ while (fscanf(stream[0], "%s%d", dev_name, &dev_num) == 2) { + if (dev_num == 0) { + break; + } +@@ -4021,8 +4069,8 @@ child_out: + end->minor = dev_num & 0x00ff; + } + err: +- if (stream) +- fclose(stream); ++ if (stream[0]) ++ fclose(stream[0]); + if (child_pid > 0) + wait_for_pid(child_pid); + return head; +@@ -4035,7 +4083,9 @@ void free_devinfo_list(struct devinfo *ptr) + tmp = ptr; + ptr = ptr->next; + free(tmp->name); ++ tmp->name = NULL; + free(tmp); ++ tmp = NULL; + } + } + +@@ -4046,7 +4096,7 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset, + struct fuse_context *fc = fuse_get_context(); + struct file_info *d = (struct file_info *)fi->fh; + struct devinfo *container_devinfo = NULL, *ptr; +- char *cg; ++ char *cg = NULL; + char *io_serviced_str = NULL, *io_merged_str = NULL, *io_service_bytes_str = NULL, + *io_wait_time_str = NULL, *io_service_time_str = NULL; + unsigned long read = 0, write = 0; +@@ -4174,11 +4224,17 @@ err: + if (f) + fclose(f); + free(line); ++ line = NULL; + free(io_serviced_str); ++ io_serviced_str = NULL; + free(io_merged_str); ++ io_merged_str = NULL; + free(io_service_bytes_str); ++ io_service_bytes_str = NULL; + free(io_wait_time_str); ++ io_wait_time_str = NULL; + free(io_service_time_str); ++ io_service_time_str = NULL; + free_devinfo_list(container_devinfo); + return rv; + } +@@ -4256,6 +4312,7 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset, + } + + free(line); ++ line = NULL; + fclose(f); + } + +@@ -4281,8 +4338,11 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset, + + err: + free(cg); ++ cg = NULL; + free(memusage_str); ++ memusage_str = NULL; + free(memswusage_str); ++ memswusage_str = NULL; + return rv; + } + +@@ -4299,6 +4359,7 @@ static off_t get_procfile_size(const char *which) + answer += sz; + fclose (f); + free(line); ++ line = NULL; + + return answer; + } +@@ -4352,6 +4413,8 @@ int proc_open(const char *path, struct fuse_file_info *fi) + int type = -1; + struct file_info *info; + ++ fi->fh = 0; ++ + if (strcmp(path, "/proc/meminfo") == 0) + type = LXC_TYPE_PROC_MEMINFO; + else if (strcmp(path, "/proc/cpuinfo") == 0) +@@ -4437,7 +4500,7 @@ static bool mkdir_p(const char *dir, mode_t mode) + { + const char *tmp = dir; + const char *orig = dir; +- char *makeme; ++ char *makeme = NULL; + + do { + dir = tmp + strspn(tmp, "/"); +@@ -4452,6 +4515,7 @@ static bool mkdir_p(const char *dir, mode_t mode) + return false; + } + free(makeme); ++ makeme = NULL; + } while(tmp != dir); + + return true; +@@ -4482,8 +4546,8 @@ static bool has_fs_type(const struct statfs *fs, fs_type_magic magic_val) + */ + static bool is_on_ramfs(void) + { +- FILE *f; +- char *p, *p2; ++ FILE *f = NULL; ++ char *p = NULL, *p2 = NULL; + char *line = NULL; + size_t len = 0; + int i; +@@ -4506,12 +4570,14 @@ static bool is_on_ramfs(void) + p = strchr(p2 + 1, '-'); + if (p && strncmp(p, "- rootfs rootfs ", 16) == 0) { + free(line); ++ line = NULL; + fclose(f); + return true; + } + } + } + free(line); ++ line = NULL; + fclose(f); + return false; + } +@@ -4709,7 +4775,7 @@ static bool cgfs_prepare_mounts(void) + + static bool cgfs_mount_hierarchies(void) + { +- char *target; ++ char *target = NULL; + size_t clen, len; + int i, ret; + +@@ -4725,10 +4791,12 @@ static bool cgfs_mount_hierarchies(void) + ret = snprintf(target, len, "%s/%s", BASEDIR, controller); + if (ret < 0 || ret >= len) { + free(target); ++ target = NULL; + return false; + } + if (mkdir(target, 0755) < 0 && errno != EEXIST) { + free(target); ++ target = NULL; + return false; + } + if (!strcmp(controller, "unified")) +@@ -4738,15 +4806,18 @@ static bool cgfs_mount_hierarchies(void) + if (ret < 0) { + lxcfs_error("Failed mounting cgroup %s: %s\n", controller, strerror(errno)); + free(target); ++ target = NULL; + return false; + } + + fd_hierarchies[i] = open(target, O_DIRECTORY); + if (fd_hierarchies[i] < 0) { + free(target); ++ target = NULL; + return false; + } + free(target); ++ target = NULL; + } + return true; + } +@@ -4770,7 +4841,7 @@ static bool cgfs_setup_controllers(void) + static void __attribute__((constructor)) collect_and_mount_subsystems(void) + { + FILE *f; +- char *cret, *line = NULL; ++ char *cret = NULL, *line = NULL; + char cwd[MAXPATHLEN]; + size_t len = 0; + int i, init_ns = -1; +@@ -4782,7 +4853,7 @@ static void __attribute__((constructor)) collect_and_mount_subsystems(void) + } + + while (getline(&line, &len, f) != -1) { +- char *idx, *p, *p2; ++ char *idx = NULL, *p = NULL, *p2 = NULL; + + p = strchr(line, ':'); + if (!p) +@@ -4848,6 +4919,7 @@ static void __attribute__((constructor)) collect_and_mount_subsystems(void) + + out: + free(line); ++ line = NULL; + fclose(f); + if (init_ns >= 0) + close(init_ns); +@@ -4860,13 +4932,17 @@ static void __attribute__((destructor)) free_subsystems(void) + lxcfs_debug("%s\n", "Running destructor for liblxcfs."); + + for (i = 0; i < num_hierarchies; i++) { +- if (hierarchies[i]) ++ if (hierarchies[i]) { + free(hierarchies[i]); ++ hierarchies[i] = NULL; ++ } + if (fd_hierarchies && fd_hierarchies[i] >= 0) + close(fd_hierarchies[i]); + } + free(hierarchies); ++ hierarchies = NULL; + free(fd_hierarchies); ++ fd_hierarchies = NULL; + + if (cgroup_mount_ns_fd >= 0) + close(cgroup_mount_ns_fd); diff --git a/0010-fix-hang.patch b/0010-fix-hang.patch new file mode 100644 index 0000000..e86bb34 --- /dev/null +++ b/0010-fix-hang.patch @@ -0,0 +1,48 @@ +diff --git a/bindings.c b/bindings.c +index b921d7e..1023e7f 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -111,6 +111,7 @@ struct pidns_init_store { + static struct pidns_init_store *pidns_hash_table[PIDNS_HASH_SIZE]; + static pthread_mutex_t pidns_store_mutex = PTHREAD_MUTEX_INITIALIZER; + static pthread_mutex_t slurp_file_mutex = PTHREAD_MUTEX_INITIALIZER; ++static pthread_mutex_t diskstats_mutex = PTHREAD_MUTEX_INITIALIZER; + static void lock_mutex(pthread_mutex_t *l) + { + int ret; +@@ -4002,6 +4003,16 @@ struct devinfo* container_dev_read(pid_t pid) { + return head; + } + if (child_pid == 0) { ++ /* Disallow signal reception in child process */ ++ sigset_t oldset; ++ sigset_t newset; ++ sigemptyset(&newset); ++ sigaddset(&newset, SIGTERM); ++ sigaddset(&newset, SIGINT); ++ sigaddset(&newset, SIGHUP); ++ sigaddset(&newset, SIGQUIT); ++ sigprocmask(SIG_BLOCK,&newset,&oldset); ++ + close(mypipe[0]); + stream[1] = fdopen(mypipe[1], "w"); + if (stream[1] == NULL) { +@@ -4048,6 +4059,8 @@ child_out: + lxcfs_error("Error opening pipe for reading: %s\n", strerror(errno)); + goto err; + } ++ wait_for_pid(child_pid); ++ child_pid = 0; + while (fscanf(stream[0], "%s%d", dev_name, &dev_num) == 2) { + if (dev_num == 0) { + break; +@@ -4148,7 +4161,9 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset, + if (!f) + goto err; + ++ lock_mutex(&diskstats_mutex); + container_devinfo = container_dev_read(initpid); ++ unlock_mutex(&diskstats_mutex); + + while (getline(&line, &linelen, f) != -1) { + ssize_t l; diff --git a/0011-systemd-stop.patch b/0011-systemd-stop.patch new file mode 100644 index 0000000..618620b --- /dev/null +++ b/0011-systemd-stop.patch @@ -0,0 +1,11 @@ +diff --git a/config/init/systemd/lxcfs.service b/config/init/systemd/lxcfs.service +index 534907d..3f104ad 100644 +--- a/config/init/systemd/lxcfs.service ++++ b/config/init/systemd/lxcfs.service +@@ -10,6 +10,7 @@ ExecStart=/usr/bin/lxcfs /var/lib/lxc/lxcfs/ + ExecStartPost=/usr/local/bin/isulad-lxcfs-toolkit remount -a + KillMode=process + Restart=on-failure ++ExecStop=/usr/local/bin/isulad-lxcfs-toolkit umount -a + ExecStopPost=-/bin/fusermount -u /var/lib/lxc/ + Delegate=yes diff --git a/0012-limit-cpuinfo-by-quota-period-setting.patch b/0012-limit-cpuinfo-by-quota-period-setting.patch new file mode 100644 index 0000000..78ee696 --- /dev/null +++ b/0012-limit-cpuinfo-by-quota-period-setting.patch @@ -0,0 +1,130 @@ +diff -uprN a/bindings.c b/bindings.c +--- a/bindings.c 2019-01-07 15:52:33.206519758 +0800 ++++ b/bindings.c 2019-01-07 16:11:20.021464817 +0800 +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -3369,6 +3370,37 @@ static bool cpuline_in_cpuset(const char + return cpu_in_cpuset(cpu, cpuset); + } + ++static long get_cpulimit(const char *cgroup, const char *file) ++{ ++ char *cpulimit_str = NULL; ++ long cpulimit = -1; ++ ++ if (cgfs_get_value("cpu", cgroup, file, &cpulimit_str)) ++ cpulimit = strtol(cpulimit_str, NULL, 10); ++ ++ free(cpulimit_str); ++ ++ return cpulimit; ++} ++ ++static long get_cpu_count(const char *cgroup) ++{ ++ char *copy = strdupa(cgroup); ++ long double count = -1; ++ int period, quota; ++ ++ period = get_cpulimit(copy, "cpu.cfs_period_us"); ++ quota = get_cpulimit(copy, "cpu.cfs_quota_us"); ++ ++ if (quota != -1) ++ count = quota / period; ++ ++ if (quota > 0) { ++ return ceil(count); ++ } ++ ++ return -1; ++} + /* + * check whether this is a '^processor" line in /proc/cpuinfo + */ +@@ -3387,11 +3419,13 @@ static int proc_cpuinfo_read(char *buf, + struct fuse_context *fc = fuse_get_context(); + struct file_info *d = (struct file_info *)fi->fh; + char *cg = NULL; ++ char *ccg = NULL; + char *cpuset = NULL; + char *line = NULL; + size_t linelen = 0, total_len = 0, rv = 0; + bool am_printing = false, firstline = true, is_s390x = false; + int curcpu = -1, cpu; ++ long total_cpus = -1; + char *cache = d->buf; + size_t cache_size = d->buflen; + FILE *f = NULL; +@@ -3419,6 +3453,12 @@ static int proc_cpuinfo_read(char *buf, + if (!cpuset) + goto err; + ++ ccg = get_pid_cgroup(initpid, "cpu"); ++ if (ccg) { ++ prune_init_slice(ccg); ++ total_cpus = get_cpu_count(ccg); ++ } ++ + f = fopen("/proc/cpuinfo", "r"); + if (!f) + goto err; +@@ -3436,6 +3476,9 @@ static int proc_cpuinfo_read(char *buf, + if (strncmp(line, "# processors:", 12) == 0) + continue; + if (is_processor_line(line)) { ++ if (total_cpus > 0 && curcpu >= (total_cpus-1)) { ++ break; ++ } + am_printing = cpuline_in_cpuset(line, cpuset); + if (am_printing) { + curcpu ++; +@@ -3457,6 +3500,10 @@ static int proc_cpuinfo_read(char *buf, + continue; + } else if (is_s390x && sscanf(line, "processor %d:", &cpu) == 1) { + char *p = NULL; ++ ++ if (total_cpus > 0 && curcpu >= (total_cpus-1)) { ++ break; ++ } + if (!cpu_in_cpuset(cpu, cpuset)) + continue; + curcpu ++; +@@ -3509,7 +3556,7 @@ static int proc_cpuinfo_read(char *buf, + } + } + +- if (is_s390x) { ++ if ((is_s390x) && ((total_cpus < 0) || (total_cpus > 0 && curcpu < (total_cpus-1)))) { + char *origcache = d->buf; + ssize_t l; + do { +diff -uprN a/Makefile.am b/Makefile.am +--- a/Makefile.am 2019-01-07 15:52:33.211519758 +0800 ++++ b/Makefile.am 2019-01-07 16:09:21.713470585 +0800 +@@ -13,7 +13,7 @@ AM_CFLAGS += -DRUNTIME_PATH=\"$(RUNTIME_ + + liblxcfs_la_SOURCES = macro.h bindings.c cpuset.c bindings.h + liblxcfs_la_CFLAGS = $(AM_CFLAGS) +-liblxcfs_la_LDFLAGS = $(AM_CFLAGS) -module -avoid-version -shared ++liblxcfs_la_LDFLAGS = $(AM_CFLAGS) -module -avoid-version -shared -lm + + liblxcfstest_la_SOURCES = bindings.c cpuset.c bindings.h macro.h + liblxcfstest_la_CFLAGS = $(AM_CFLAGS) -DRELOADTEST +diff -uprN a/Makefile.in b/Makefile.in +--- a/Makefile.in 2019-01-07 15:52:33.204519758 +0800 ++++ b/Makefile.in 2019-01-07 16:09:21.714470585 +0800 +@@ -427,7 +427,7 @@ AM_CFLAGS = -Wall -ggdb -D_GNU_SOURCE -D + AM_LDFLAGS = $(FUSE_LIBS) -pthread + liblxcfs_la_SOURCES = macro.h bindings.c cpuset.c bindings.h + liblxcfs_la_CFLAGS = $(AM_CFLAGS) +-liblxcfs_la_LDFLAGS = $(AM_CFLAGS) -module -avoid-version -shared ++liblxcfs_la_LDFLAGS = $(AM_CFLAGS) -module -avoid-version -shared -lm + liblxcfstest_la_SOURCES = bindings.c cpuset.c bindings.h macro.h + liblxcfstest_la_CFLAGS = $(AM_CFLAGS) -DRELOADTEST + liblxcfstest_la_LDFLAGS = $(AM_CFLAGS) -module -avoid-version -shared diff --git a/0013-limit-stat-by-quota-period-setting.patch b/0013-limit-stat-by-quota-period-setting.patch new file mode 100644 index 0000000..8a85e8c --- /dev/null +++ b/0013-limit-stat-by-quota-period-setting.patch @@ -0,0 +1,39 @@ +diff -uprN a/bindings.c b/bindings.c +--- a/bindings.c 2019-01-07 16:13:51.465457433 +0800 ++++ b/bindings.c 2019-01-07 16:15:37.926452242 +0800 +@@ -3747,10 +3747,12 @@ static int proc_stat_read(char *buf, siz + struct fuse_context *fc = fuse_get_context(); + struct file_info *d = (struct file_info *)fi->fh; + char *cg = NULL; ++ char *ccg = NULL; + char *cpuset = NULL; + char *line = NULL; + size_t linelen = 0, total_len = 0, rv = 0; + int curcpu = -1; /* cpu numbering starts at 0 */ ++ long total_cpus = -1; + unsigned long user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0, steal = 0, guest = 0, guest_nice = 0; + unsigned long user_sum = 0, nice_sum = 0, system_sum = 0, idle_sum = 0, iowait_sum = 0, + irq_sum = 0, softirq_sum = 0, steal_sum = 0, guest_sum = 0, guest_nice_sum = 0; +@@ -3783,6 +3785,12 @@ static int proc_stat_read(char *buf, siz + if (!cpuset) + goto err; + ++ ccg = get_pid_cgroup(initpid, "cpu"); ++ if (ccg) { ++ prune_init_slice(ccg); ++ total_cpus = get_cpu_count(ccg); ++ } ++ + f = fopen("/proc/stat", "r"); + if (!f) + goto err; +@@ -3820,6 +3828,9 @@ static int proc_stat_read(char *buf, siz + continue; + } + ++ if (total_cpus > 0 && curcpu >= (total_cpus-1)) { ++ continue; ++ } + if (sscanf(cpu_char, "%d", &cpu) != 1) + continue; + if (!cpu_in_cpuset(cpu, cpuset)) diff --git a/0014-systemd-monitor-always-restart.patch b/0014-systemd-monitor-always-restart.patch new file mode 100644 index 0000000..be2d2eb --- /dev/null +++ b/0014-systemd-monitor-always-restart.patch @@ -0,0 +1,16 @@ +diff -uprN a/config/init/systemd/lxcfs.service b/config/init/systemd/lxcfs.service +--- a/config/init/systemd/lxcfs.service 2019-01-07 17:15:47.596276242 +0800 ++++ b/config/init/systemd/lxcfs.service 2019-01-07 17:17:32.206271142 +0800 +@@ -9,10 +9,11 @@ ExecStartPre=/usr/local/bin/isulad-lxcfs + ExecStart=/usr/bin/lxcfs /var/lib/lxc/lxcfs/ + ExecStartPost=/usr/local/bin/isulad-lxcfs-toolkit remount -a + KillMode=process +-Restart=on-failure + ExecStop=/usr/local/bin/isulad-lxcfs-toolkit umount -a + ExecStopPost=-/bin/fusermount -u /var/lib/lxc/ + Delegate=yes ++Restart=always ++RestartSec=2s + + [Install] + WantedBy=multi-user.target diff --git a/0015-lxcfs-fix-memory-leak.patch b/0015-lxcfs-fix-memory-leak.patch new file mode 100644 index 0000000..14f2616 --- /dev/null +++ b/0015-lxcfs-fix-memory-leak.patch @@ -0,0 +1,62 @@ +diff -uprN a/bindings.c b/bindings.c +--- a/bindings.c 2019-01-07 16:16:48.039448823 +0800 ++++ b/bindings.c 2019-01-07 16:34:25.904397244 +0800 +@@ -3128,9 +3128,10 @@ static unsigned long get_memlimit(const + char *memlimit_str = NULL; + unsigned long memlimit = 0; + +- if ((memlimit_str = cgfs_get_value("memory", cgroup, file))) +- memlimit = strtoul(memlimit_str, NULL, 10); ++ if (!(memlimit_str = cgfs_get_value("memory", cgroup, file))) ++ return memlimit; + ++ memlimit = strtoul(memlimit_str, NULL, 10); + free(memlimit_str); + memlimit_str = NULL; + +@@ -3375,9 +3376,10 @@ static long get_cpulimit(const char *cgr + char *cpulimit_str = NULL; + long cpulimit = -1; + +- if (cgfs_get_value("cpu", cgroup, file, &cpulimit_str)) +- cpulimit = strtol(cpulimit_str, NULL, 10); ++ if (!cgfs_get_value("cpu", cgroup, file, &cpulimit_str)) ++ return cpulimit; + ++ cpulimit = strtol(cpulimit_str, NULL, 10); + free(cpulimit_str); + + return cpulimit; +@@ -3385,12 +3387,13 @@ static long get_cpulimit(const char *cgr + + static long get_cpu_count(const char *cgroup) + { +- char *copy = strdupa(cgroup); ++ char *copy = must_copy_string(cgroup); + long double count = -1; + int period, quota; + + period = get_cpulimit(copy, "cpu.cfs_period_us"); + quota = get_cpulimit(copy, "cpu.cfs_quota_us"); ++ free(copy); + + if (quota != -1) + count = quota / period; +@@ -3607,6 +3610,8 @@ err: + cpuset = NULL; + free(cg); + cg = NULL; ++ free(ccg); ++ ccg = NULL; + return rv; + } + +@@ -3922,6 +3927,8 @@ err: + cpuset = NULL; + free(cg); + cg = NULL; ++ free(ccg); ++ ccg = NULL; + return rv; + } + diff --git a/0016-lxcfs-fix-concurrency-problem.patch b/0016-lxcfs-fix-concurrency-problem.patch new file mode 100644 index 0000000..ba53178 --- /dev/null +++ b/0016-lxcfs-fix-concurrency-problem.patch @@ -0,0 +1,36 @@ +diff -uprN a/bindings.c b/bindings.c +--- a/bindings.c 2019-01-07 16:36:42.290390594 +0800 ++++ b/bindings.c 2019-01-07 16:46:59.507360500 +0800 +@@ -2427,10 +2427,10 @@ int cg_read(const char *path, char *buf, + if (strcmp(f->file, "tasks") == 0 || + strcmp(f->file, "/tasks") == 0 || + strcmp(f->file, "/cgroup.procs") == 0 || +- strcmp(f->file, "cgroup.procs") == 0) ++ strcmp(f->file, "cgroup.procs") == 0) { + // special case - we have to translate the pids + r = do_read_pids(fc->pid, f->controller, f->cgroup, f->file, &data); +- else { ++ } else { + data = cgfs_get_value(f->controller, f->cgroup, f->file); + r = !data; + } +@@ -3376,7 +3376,7 @@ static long get_cpulimit(const char *cgr + char *cpulimit_str = NULL; + long cpulimit = -1; + +- if (!cgfs_get_value("cpu", cgroup, file, &cpulimit_str)) ++ if (!(cpulimit_str = cgfs_get_value("cpu", cgroup, file))) + return cpulimit; + + cpulimit = strtol(cpulimit_str, NULL, 10); +@@ -4552,8 +4552,9 @@ int proc_read(const char *path, char *bu + { + struct file_info *f = (struct file_info *) fi->fh; + +- if (!f->buf) ++ if (!f->buf) { + return -EINVAL; ++ } + + switch (f->type) { + case LXC_TYPE_PROC_MEMINFO: diff --git a/0017-diskstats-support-devicemapper-device.patch b/0017-diskstats-support-devicemapper-device.patch new file mode 100644 index 0000000..5e15c91 --- /dev/null +++ b/0017-diskstats-support-devicemapper-device.patch @@ -0,0 +1,77 @@ +diff --git a/bindings.c b/bindings.c +--- a/bindings.c ++++ b/bindings.c +@@ -4099,7 +4099,7 @@ struct devinfo* container_dev_read(pid_t pid) { + goto child_out; + } + while ((ptr = readdir(dir)) != NULL) { +- if (ptr->d_type != DT_BLK && ptr->d_type != DT_CHR) { ++ if (ptr->d_type != DT_BLK) { + continue; + } + memset(fpath, 0, sizeof(fpath)); +@@ -4167,10 +4167,20 @@ void free_devinfo_list(struct devinfo *ptr) + } + } + ++static bool need_record_diskstats(unsigned int major, unsigned int minor) ++{ ++ //only support device which major is 253. ++ if (major == 253) { ++ return true; ++ } ++ return false; ++} ++ + static int proc_diskstats_read(char *buf, size_t size, off_t offset, + struct fuse_file_info *fi) + { + char dev_name[72]; ++ char tmp_dev_name[72]; + struct fuse_context *fc = fuse_get_context(); + struct file_info *d = (struct file_info *)fi->fh; + struct devinfo *container_devinfo = NULL, *ptr; +@@ -4233,6 +4243,7 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset, + while (getline(&line, &linelen, f) != -1) { + ssize_t l; + char lbuf[256]; ++ bool match = false; + + memset(dev_name, 0, sizeof(dev_name)); + i = sscanf(line, "%u %u %71s", &major, &minor, dev_name); +@@ -4240,11 +4251,16 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset, + continue; + for (ptr = container_devinfo; ptr != NULL; ptr = ptr->next) { + if (major == ptr->major && minor == ptr->minor) { +- strncpy(dev_name, ptr->name, 71); ++ snprintf(dev_name, sizeof(dev_name), "%s", ptr->name); + dev_name[71] = '\0'; ++ match = true; + } + } + ++ if (!match) { ++ continue; ++ } ++ + get_blkio_io_value(io_serviced_str, major, minor, "Read", &read); + get_blkio_io_value(io_serviced_str, major, minor, "Write", &write); + get_blkio_io_value(io_merged_str, major, minor, "Read", &read_merged); +@@ -4274,8 +4290,16 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset, + snprintf(lbuf, 256, "%u %u %s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n", + major, minor, dev_name, read, read_merged, read_sectors, read_ticks, + write, write_merged, write_sectors, write_ticks, ios_pgr, tot_ticks, rq_ticks); +- else ++ else if (need_record_diskstats(major, minor)) { ++ sscanf(line, "%u %u %s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n", ++ &major, &minor, tmp_dev_name, &read, &read_merged, &read_sectors, &read_ticks, ++ &write, &write_merged, &write_sectors, &write_ticks, &ios_pgr, &tot_ticks, &rq_ticks); ++ snprintf(lbuf, 256, "%u %u %s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n", ++ major, minor, dev_name, read, read_merged, read_sectors, read_ticks, ++ write, write_merged, write_sectors, write_ticks, ios_pgr, tot_ticks, rq_ticks); ++ } else { + continue; ++ } + + l = snprintf(cache, cache_size, "%s", lbuf); + if (l < 0) { diff --git a/0018-lxcfs-add-proc-partitions.patch b/0018-lxcfs-add-proc-partitions.patch new file mode 100644 index 0000000..0d9bdb1 --- /dev/null +++ b/0018-lxcfs-add-proc-partitions.patch @@ -0,0 +1,226 @@ +diff --git a/Makefile.am b/Makefile.am +--- a/Makefile.am ++++ b/Makefile.am +@@ -26,7 +26,7 @@ lxcfs_LTLIBRARIES = liblxcfs.la + EXTRA_LTLIBRARIES = liblxcfstest.la + + lxcfs_SOURCES = lxcfs.c +-lxcfs_LDADD = -ldl ++lxcfs_LDADD = -ldl -lsecurec + lxcfs_CFLAGS = $(AM_CFLAGS) + lxcfs_LDFLAGS = $(AM_LDFLAGS) + bin_PROGRAMS = lxcfs +diff --git a/bindings.c b/bindings.c +--- a/bindings.c ++++ b/bindings.c +@@ -39,6 +39,7 @@ + + #include "bindings.h" + #include "config.h" // for VERSION ++#include "securec.h" + + /* Maximum number for 64 bit integer is a string with 21 digits: 2^64 - 1 = 21 */ + #define LXCFS_NUMSTRLEN64 21 +@@ -67,6 +68,7 @@ enum { + LXC_TYPE_PROC_STAT, + LXC_TYPE_PROC_DISKSTATS, + LXC_TYPE_PROC_SWAPS, ++ LXC_TYPE_PROC_PARTITIONS, + }; + + struct file_info { +@@ -112,7 +114,7 @@ struct pidns_init_store { + static struct pidns_init_store *pidns_hash_table[PIDNS_HASH_SIZE]; + static pthread_mutex_t pidns_store_mutex = PTHREAD_MUTEX_INITIALIZER; + static pthread_mutex_t slurp_file_mutex = PTHREAD_MUTEX_INITIALIZER; +-static pthread_mutex_t diskstats_mutex = PTHREAD_MUTEX_INITIALIZER; ++static pthread_mutex_t container_dev_mutex = PTHREAD_MUTEX_INITIALIZER; + static void lock_mutex(pthread_mutex_t *l) + { + int ret; +@@ -4226,9 +4228,9 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset, + if (!f) + goto err; + +- lock_mutex(&diskstats_mutex); ++ lock_mutex(&container_dev_mutex); + container_devinfo = container_dev_read(initpid); +- unlock_mutex(&diskstats_mutex); ++ unlock_mutex(&container_dev_mutex); + + while (getline(&line, &linelen, f) != -1) { + ssize_t l; +@@ -4426,6 +4428,132 @@ err: + return rv; + } + ++static int proc_partitions_read(char *buf, size_t size, off_t offset, ++ struct fuse_file_info *fi) ++{ ++ int ret = 0; ++ char dev_name[72] = {0}; ++ struct fuse_context *fc = fuse_get_context(); ++ struct file_info *d = (struct file_info *)fi->fh; ++ struct devinfo *container_devinfo = NULL, *ptr = NULL; ++ char *cg = NULL; ++ char *cache = d->buf; ++ size_t cache_size = d->buflen; ++ char *line = NULL; ++ size_t linelen = 0, total_len = 0; ++ int rv = 0; ++ unsigned int major = 0, minor = 0; ++ unsigned long long blocks = 0; ++ int i = 0, lines = 0; ++ bool found = false; ++ FILE *f = NULL; ++ ++ if (offset > 0){ ++ if (offset > d->size) ++ return -EINVAL; ++ if (d->cached == 0) ++ return 0; ++ int left = d->size - offset; ++ total_len = left > size ? size: left; ++ ret = memcpy_s(buf, size, cache + offset, total_len); ++ if (ret != 0) { ++ lxcfs_error("%s\n", "Internal error: memcpy buf failed"); ++ rv = 0; ++ goto err; ++ } ++ ++ return total_len; ++ } ++ ++ pid_t initpid = lookup_initpid_in_store(fc->pid); ++ if (initpid <= 0) ++ initpid = fc->pid; ++ cg = get_pid_cgroup(initpid, "blkio"); ++ if (cg == NULL) ++ return read_file("/proc/partitions", buf, size, d); ++ prune_init_slice(cg); ++ ++ f = fopen("/proc/partitions", "r"); ++ if (f == NULL) ++ goto err; ++ ++ lock_mutex(&container_dev_mutex); ++ container_devinfo = container_dev_read(initpid); ++ unlock_mutex(&container_dev_mutex); ++ ++ while (getline(&line, &linelen, f) != -1) { ++ ssize_t l; ++ char lbuf[256]; ++ ++ if (lines < 2) { ++ ret = strncpy_s(lbuf, 256, line, 255); ++ if (ret != 0) { ++ lxcfs_error("%s\n", "Internal error: strncpy line failed"); ++ rv = 0; ++ goto err; ++ } ++ ++ lines++; ++ } else { ++ ret = memset_s(dev_name, sizeof(dev_name), 0, sizeof(dev_name)); ++ if (ret != 0) { ++ lxcfs_error("%s\n", "Internal error: memset devname failed"); ++ rv = 0; ++ goto err; ++ } ++ ++ i = sscanf(line, "%u %u %llu %71s", &major, &minor, &blocks, dev_name); ++ if (i != 4) ++ continue; ++ found = false; ++ for (ptr = container_devinfo; ptr != NULL; ptr = ptr->next) { ++ if (major == ptr->major && minor == ptr->minor) { ++ snprintf(lbuf, 256, "%4u %7u %10llu %s\n", major, minor, blocks, ptr->name); ++ found = true; ++ } ++ } ++ if (!found) ++ continue; ++ } ++ ++ l = snprintf(cache, cache_size, "%s", lbuf); ++ if (l < 0) { ++ perror("Error writing to fuse buf"); ++ rv = 0; ++ goto err; ++ } ++ if (l >= cache_size) { ++ lxcfs_error("%s\n", "Internal error: truncated write to cache."); ++ rv = 0; ++ goto err; ++ } ++ cache += l; ++ cache_size -= l; ++ total_len += l; ++ } ++ d->cached = 1; ++ d->size = total_len; ++ if (total_len > size ) ++ total_len = size; ++ ++ ret = memcpy_s(buf, size, d->buf, total_len); ++ if (ret != 0) { ++ lxcfs_error("%s\n", "Internal error: memcpy buf failed"); ++ rv = 0; ++ goto err; ++ } ++ ++ rv = total_len; ++err: ++ free(cg); ++ if (f != NULL) ++ fclose(f); ++ free(line); ++ line = NULL; ++ free_devinfo_list(container_devinfo); ++ return rv; ++} ++ + static off_t get_procfile_size(const char *which) + { + FILE *f = fopen(which, "r"); +@@ -4463,7 +4591,8 @@ int proc_getattr(const char *path, struct stat *sb) + strcmp(path, "/proc/uptime") == 0 || + strcmp(path, "/proc/stat") == 0 || + strcmp(path, "/proc/diskstats") == 0 || +- strcmp(path, "/proc/swaps") == 0) { ++ strcmp(path, "/proc/swaps") == 0 || ++ strcmp(path, "/proc/partitions") == 0) { + sb->st_size = 0; + sb->st_mode = S_IFREG | 00444; + sb->st_nlink = 1; +@@ -4483,7 +4612,8 @@ int proc_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offs + filler(buf, "stat", NULL, 0) != 0 || + filler(buf, "uptime", NULL, 0) != 0 || + filler(buf, "diskstats", NULL, 0) != 0 || +- filler(buf, "swaps", NULL, 0) != 0) ++ filler(buf, "swaps", NULL, 0) != 0 || ++ filler(buf, "partitions", NULL, 0) != 0) + return -EINVAL; + return 0; + } +@@ -4507,6 +4637,8 @@ int proc_open(const char *path, struct fuse_file_info *fi) + type = LXC_TYPE_PROC_DISKSTATS; + else if (strcmp(path, "/proc/swaps") == 0) + type = LXC_TYPE_PROC_SWAPS; ++ else if (strcmp(path, "/proc/partitions") == 0) ++ type = LXC_TYPE_PROC_PARTITIONS; + if (type == -1) + return -ENOENT; + +@@ -4568,6 +4700,8 @@ int proc_read(const char *path, char *buf, size_t size, off_t offset, + return proc_diskstats_read(buf, size, offset, fi); + case LXC_TYPE_PROC_SWAPS: + return proc_swaps_read(buf, size, offset, fi); ++ case LXC_TYPE_PROC_PARTITIONS: ++ return proc_partitions_read(buf, size, offset, fi); + default: + return -EINVAL; + } +-- +1.8.3.1 + diff --git a/0019-use-bitwise-operators-only-on-unsigned.patch b/0019-use-bitwise-operators-only-on-unsigned.patch new file mode 100644 index 0000000..7d130ba --- /dev/null +++ b/0019-use-bitwise-operators-only-on-unsigned.patch @@ -0,0 +1,41 @@ +diff --git a/bindings.c b/bindings.c +--- a/bindings.c ++++ b/bindings.c +@@ -4037,7 +4037,7 @@ struct devinfo { + struct devinfo *next; + }; + +-int getns(pid_t pid, char *ns_type) ++int getns(pid_t pid, const char *ns_type) + { + char fpath[100]; + memset(fpath, 0, sizeof(fpath)); +@@ -4145,8 +4145,8 @@ child_out: + } + end->next = NULL; + end->name = must_copy_string(dev_name); +- end->major = (dev_num & 0xff00) >> 8; +- end->minor = dev_num & 0x00ff; ++ end->major = ((unsigned int)dev_num & 0xff00) >> 8; ++ end->minor = (unsigned int)dev_num & 0x00ff; + } + err: + if (stream[0]) +@@ -4185,7 +4185,7 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset, + char tmp_dev_name[72]; + struct fuse_context *fc = fuse_get_context(); + struct file_info *d = (struct file_info *)fi->fh; +- struct devinfo *container_devinfo = NULL, *ptr; ++ struct devinfo *container_devinfo = NULL, *ptr = NULL; + char *cg = NULL; + char *io_serviced_str = NULL, *io_merged_str = NULL, *io_service_bytes_str = NULL, + *io_wait_time_str = NULL, *io_service_time_str = NULL; +@@ -4510,7 +4510,7 @@ static int proc_partitions_read(char *buf, size_t size, off_t offset, + char lbuf[256]; + + if (lines < 2) { +- ret = strncpy_s(lbuf, 256, line, 255); ++ ret = strncpy_s(lbuf, sizeof(lbuf), line, sizeof(lbuf)-1); + if (ret != 0) { + lxcfs_error("%s\n", "Internal error: strncpy line failed"); + rv = 0; diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/lxcfs-3.0.2.tar.gz b/lxcfs-3.0.2.tar.gz new file mode 100644 index 0000000..0a93545 Binary files /dev/null and b/lxcfs-3.0.2.tar.gz differ diff --git a/lxcfs.spec b/lxcfs.spec new file mode 100644 index 0000000..1ed5ba3 --- /dev/null +++ b/lxcfs.spec @@ -0,0 +1,92 @@ +#Global macro or variable +%define _unpackaged_files_terminate_build 0 + +#Basic Information +Name: lxcfs +Version: 3.0.2 +Release: 0.5.h1 +Summary: FUSE filesystem for LXC +License: Apache-2.0 +URL: http://linuxcontainers.org +Source: https://linuxcontainers.org/downloads/%{name}/%{name}-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-build +Patch9000: 0001-systemd-up.patch +Patch9001: 0002-prestart.patch +Patch9003: 0003-remove-sysvinit-upstart.patch +Patch9004: 0004-show-dev-name-in-container.patch +Patch9005: 0005-lxcfs-fix-cpuinfo-print.patch +Patch9006: 0006-lxcfs-3.0.2-crashes-on-centos-7.patch +Patch9007: 0007-fix-memory-leak.patch +Patch9008: 0008-fix-concurrency-problem.patch +Patch9009: 0009-set-null-after-free.patch +Patch9010: 0010-fix-hang.patch +Patch9011: 0011-systemd-stop.patch +Patch9012: 0012-limit-cpuinfo-by-quota-period-setting.patch +Patch9013: 0013-limit-stat-by-quota-period-setting.patch +Patch9014: 0014-systemd-monitor-always-restart.patch +Patch9015: 0015-lxcfs-fix-memory-leak.patch +Patch9016: 0016-lxcfs-fix-concurrency-problem.patch +Patch9017: 0017-diskstats-support-devicemapper-device.patch +Patch9018: 0018-lxcfs-add-proc-partitions.patch +Patch9019: 0019-use-bitwise-operators-only-on-unsigned.patch + +#Dependency +BuildRequires: autoconf automake libtool help2man +BuildRequires: fuse-devel libsecurec libsecurec-devel + +%description +lxcfs is a simple userspace filesystem designed to make containers +feel more like a real independent system through. It is usable by +any runtime, written in C using libfuse and glib. + +%prep +%autosetup -p1 + +%build +autoreconf --force --install +%configure +make %{?_smp_mflags} + +%install +make install DESTDIR=%{buildroot} %{?_smp_mflags} +install -d -m 0755 %{buildroot}%{_unitdir} +install -p -m 0644 config/init/systemd/*.service %{buildroot}%{_unitdir}/ +install -d -m 0755 %{buildroot}%{_sbindir} +ln -sf service %{buildroot}%{_sbindir}/rc%{name} +install -d -m 0755 %{buildroot}%{_includedir}/%{name} +rm bindings.h +install -d -m 0755 %{buildroot}%{_localstatedir}/lib/lxc/%{name}/ + +#Install and uninstall scripts +%pre + +%preun + +%post +ret=`systemctl is-active lxcfs` +if [ "$ret" == "active" ]; then + systemctl restart lxcfs +fi + +%postun + +#Files list +%files +%defattr(-,root,root) +%doc AUTHORS ChangeLog README +%license COPYING +%{_sbindir}/* +%{_bindir}/* +%{_datadir}/lxc +%{_datadir}/%{name} +%dir %{_localstatedir}/lib/lxc/%{name} +%dir %{_libdir}/%{name} +%{_libdir}/%{name}/lib%{name}.so +%exclude %{_libdir}/%{name}/lib%{name}.la +%{_mandir}/man1/* +%{_unitdir}/* + +%changelog +* Wed Sep 18 2019 openEuler Buildteam - 3.0.2-0.5.h1 +- Package init +