diff -Nru lxcfs-2.0.3/aclocal.m4 lxcfs-2.0.4/aclocal.m4 --- lxcfs-2.0.3/aclocal.m4 2016-08-16 02:36:36.000000000 +0000 +++ lxcfs-2.0.4/aclocal.m4 2016-10-05 09:43:21.000000000 +0000 @@ -744,7 +744,6 @@ cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. diff -Nru lxcfs-2.0.3/bindings.c lxcfs-2.0.4/bindings.c --- lxcfs-2.0.3/bindings.c 2016-08-16 02:36:32.000000000 +0000 +++ lxcfs-2.0.4/bindings.c 2016-10-05 09:43:15.000000000 +0000 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -29,6 +30,7 @@ #include #include #include +#include #include "bindings.h" #include "config.h" // for VERSION @@ -106,7 +108,7 @@ int ret; if ((ret = pthread_mutex_lock(l)) != 0) { - fprintf(stderr, "pthread_mutex_lock returned:%d %s\n", ret, strerror(ret)); + lxcfs_error("returned:%d %s\n", ret, strerror(ret)); exit(1); } } @@ -136,7 +138,7 @@ int ret; if ((ret = pthread_mutex_unlock(l)) != 0) { - fprintf(stderr, "pthread_mutex_unlock returned:%d %s\n", ret, strerror(ret)); + lxcfs_error("returned:%d %s\n", ret, strerror(ret)); exit(1); } } @@ -160,10 +162,10 @@ snprintf(fnam, 100, "/proc/%d", e->initpid); if (stat(fnam, &initsb) < 0) return false; -#if DEBUG - fprintf(stderr, "comparing ctime %ld %ld for pid %d\n", - e->ctime, initsb.st_ctime, e->initpid); -#endif + + lxcfs_debug("Comparing ctime %ld == %ld for pid %d.\n", e->ctime, + initsb.st_ctime, e->initpid); + if (e->ctime != initsb.st_ctime) return false; return true; @@ -175,9 +177,8 @@ struct pidns_init_store *tmp; int h; -#if DEBUG - fprintf(stderr, "remove_initpid: removing entry for %d\n", e->initpid); -#endif + lxcfs_debug("Remove_initpid: removing entry for %d.\n", e->initpid); + h = HASH(e->ino); if (pidns_hash_table[h] == e) { pidns_hash_table[h] = e->next; @@ -212,18 +213,18 @@ now = time(NULL); if (now < last_prune + PURGE_SECS) return; -#if DEBUG - fprintf(stderr, "pruning\n"); -#endif + + lxcfs_debug("%s\n", "Pruning."); + last_prune = now; threshold = now - 2 * PURGE_SECS; for (i = 0; i < PIDNS_HASH_SIZE; i++) { for (prev = NULL, e = pidns_hash_table[i]; e; ) { if (e->lastcheck < threshold) { -#if DEBUG - fprintf(stderr, "Removing cached entry for %d\n", e->initpid); -#endif + + lxcfs_debug("Removing cached entry for %d.\n", e->initpid); + delme = e; if (prev) prev->next = e->next; @@ -247,9 +248,8 @@ struct stat procsb; int h; -#if DEBUG - fprintf(stderr, "save_initpid: adding entry for %d\n", pid); -#endif + lxcfs_debug("Save_initpid: adding entry for %d.\n", pid); + snprintf(fpath, 100, "/proc/%d", pid); if (stat(fpath, &procsb) < 0) return; @@ -375,12 +375,12 @@ len = strlen(string); ret = fwrite(string, 1, len, f); if (ret != len) { - fprintf(stderr, "Error writing to file: %s\n", strerror(errno)); + lxcfs_error("Error writing to file: %s\n", strerror(errno)); fclose(f); return false; } if (fclose(f) < 0) { - fprintf(stderr, "Error writing to file: %s\n", strerror(errno)); + lxcfs_error("Error writing to file: %s\n", strerror(errno)); return false; } return true; @@ -400,7 +400,7 @@ n *= ALLOC_NUM; char **tmp = realloc(hierarchies, n * sizeof(char *)); if (!tmp) { - fprintf(stderr, "Out of memory\n"); + lxcfs_error("%s\n", strerror(errno)); exit(1); } hierarchies = tmp; @@ -417,7 +417,8 @@ fprintf(stderr, "hierarchies:\n"); for (i = 0; i < num_hierarchies; i++) { if (hierarchies[i]) - fprintf(stderr, " %d: %s\n", i, hierarchies[i]); + fprintf(stderr, " %2d: fd: %3d: %s\n", i, + fd_hierarchies[i], hierarchies[i]); } } @@ -504,7 +505,7 @@ len = strlen(dirname); if (len >= MAXPATHLEN) { - fprintf(stderr, "chown_all_cgroup_files: pathname too long: %s\n", dirname); + lxcfs_error("Pathname too long: %s\n", dirname); return; } @@ -514,7 +515,7 @@ d = fdopendir(fd1); if (!d) { - fprintf(stderr, "chown_all_cgroup_files: failed to open %s\n", dirname); + lxcfs_error("Failed to open %s\n", dirname); return; } @@ -523,11 +524,11 @@ continue; ret = snprintf(path, MAXPATHLEN, "%s/%s", dirname, direntp->d_name); if (ret < 0 || ret >= MAXPATHLEN) { - fprintf(stderr, "chown_all_cgroup_files: pathname too long under %s\n", dirname); + lxcfs_error("Pathname too long under %s\n", dirname); continue; } if (fchownat(fd, path, uid, gid, 0) < 0) - fprintf(stderr, "Failed to chown file %s to %u:%u", path, uid, gid); + lxcfs_error("Failed to chown file %s to %u:%u", path, uid, gid); } closedir(d); } @@ -563,7 +564,7 @@ return 0; } -static bool recursive_rmdir(const char *dirname, int fd) +static bool recursive_rmdir(const char *dirname, int fd, const int cfd) { struct dirent *direntp; DIR *dir; @@ -577,9 +578,8 @@ dir = fdopendir(dupfd); if (!dir) { -#if DEBUG - fprintf(stderr, "%s: failed to open %s: %s\n", __func__, dirname, strerror(errno)); -#endif + lxcfs_debug("Failed to open %s: %s.\n", dirname, strerror(errno)); + close(dupfd); return false; } @@ -587,48 +587,38 @@ struct stat mystat; int rc; - if (!direntp) - break; - if (!strcmp(direntp->d_name, ".") || !strcmp(direntp->d_name, "..")) continue; rc = snprintf(pathname, MAXPATHLEN, "%s/%s", dirname, direntp->d_name); if (rc < 0 || rc >= MAXPATHLEN) { - fprintf(stderr, "pathname too long\n"); + lxcfs_error("%s\n", "Pathname too long."); continue; } - ret = fstatat(fd, pathname, &mystat, AT_SYMLINK_NOFOLLOW); - if (ret) { -#if DEBUG - fprintf(stderr, "%s: failed to stat %s: %s\n", __func__, pathname, strerror(errno)); -#endif + rc = fstatat(cfd, pathname, &mystat, AT_SYMLINK_NOFOLLOW); + if (rc) { + lxcfs_debug("Failed to stat %s: %s.\n", pathname, strerror(errno)); continue; } - if (S_ISDIR(mystat.st_mode)) { - if (!recursive_rmdir(pathname, fd)) { -#if DEBUG - fprintf(stderr, "Error removing %s\n", pathname); -#endif - } - } + if (S_ISDIR(mystat.st_mode)) + if (!recursive_rmdir(pathname, fd, cfd)) + lxcfs_debug("Error removing %s.\n", pathname); } ret = true; if (closedir(dir) < 0) { - fprintf(stderr, "%s: failed to close directory %s: %s\n", __func__, dirname, strerror(errno)); + lxcfs_error("Failed to close directory %s: %s\n", dirname, strerror(errno)); ret = false; } - if (unlinkat(fd, dirname, AT_REMOVEDIR) < 0) { -#if DEBUG - fprintf(stderr, "%s: failed to delete %s: %s\n", __func__, dirname, strerror(errno)); -#endif + if (unlinkat(cfd, dirname, AT_REMOVEDIR) < 0) { + lxcfs_debug("Failed to delete %s: %s.\n", dirname, strerror(errno)); ret = false; } - close(fd); + + close(dupfd); return ret; } @@ -638,6 +628,7 @@ int fd, cfd; size_t len; char *dirnam, *tmpc; + bool bret; tmpc = find_mounted_controller(controller, &cfd); if (!tmpc) @@ -654,7 +645,9 @@ if (fd < 0) return false; - return recursive_rmdir(dirnam, fd); + bret = recursive_rmdir(dirnam, fd, cfd); + close(fd); + return bret; } bool cgfs_chmod_file(const char *controller, const char *file, mode_t mode) @@ -766,7 +759,7 @@ cg = alloca(len); ret = snprintf(cg, len, "%s%s", *cgroup == '/' ? "." : "", cgroup); if (ret < 0 || (size_t)ret >= len) { - fprintf(stderr, "%s: pathname too long under %s\n", __func__, cgroup); + lxcfs_error("Pathname too long under %s\n", cgroup); return false; } @@ -787,13 +780,13 @@ ret = snprintf(pathname, MAXPATHLEN, "%s/%s", cg, dirent->d_name); if (ret < 0 || ret >= MAXPATHLEN) { - fprintf(stderr, "%s: pathname too long under %s\n", __func__, cg); + lxcfs_error("Pathname too long under %s\n", cg); continue; } ret = fstatat(cfd, pathname, &mystat, AT_SYMLINK_NOFOLLOW); if (ret) { - fprintf(stderr, "%s: failed to stat %s: %s\n", __func__, pathname, strerror(errno)); + lxcfs_error("Failed to stat %s: %s\n", pathname, strerror(errno)); continue; } if ((!directories && !S_ISREG(mystat.st_mode)) || @@ -813,7 +806,7 @@ sz++; } if (closedir(dir) < 0) { - fprintf(stderr, "%s: failed closedir for %s: %s\n", __func__, cgroup, strerror(errno)); + lxcfs_error("Failed closedir for %s: %s\n", cgroup, strerror(errno)); return false; } return true; @@ -932,8 +925,8 @@ { struct cgfs_files *entry = cgfs_get_key(controller, cgroup, dir_entry); if (!entry) { - fprintf(stderr, "%s: Error getting files under %s:%s\n", - __func__, controller, cgroup); + lxcfs_error("Error getting files under %s:%s\n", controller, + cgroup); } return entry; } @@ -1170,7 +1163,7 @@ * uids wrapped around - unexpected as this is a procfile, * so just bail. */ - fprintf(stderr, "pid wrapparound at entry %u %u %u in %s\n", + lxcfs_error("pid wrapparound at entry %u %u %u in %s\n", nsuid, hostuid, count, line); return -1; } @@ -1276,7 +1269,7 @@ char *start, *end; if (strlen(taskcg) <= strlen(querycg)) { - fprintf(stderr, "%s: I was fed bad input\n", __func__); + lxcfs_error("%s\n", "I was fed bad input."); return NULL; } @@ -1506,23 +1499,30 @@ const char *p1; char *contr, *slash; - if (strlen(path) < 9) + if (strlen(path) < 9) { + errno = EACCES; return NULL; - if (*(path+7) != '/') + } + if (*(path + 7) != '/') { + errno = EINVAL; return NULL; - p1 = path+8; + } + p1 = path + 8; contr = strdupa(p1); - if (!contr) + if (!contr) { + errno = ENOMEM; return NULL; + } slash = strstr(contr, "/"); if (slash) *slash = '\0'; int i; - for (i = 0; i < num_hierarchies; i++) { + for (i = 0; i < num_hierarchies; i++) { if (hierarchies[i] && strcmp(hierarchies[i], contr) == 0) return hierarchies[i]; } + errno = ENOENT; return NULL; } @@ -1534,12 +1534,17 @@ { const char *p1; - if (strlen(path) < 9) + if (strlen(path) < 9) { + errno = EACCES; return NULL; - p1 = strstr(path+8, "/"); - if (!p1) + } + p1 = strstr(path + 8, "/"); + if (!p1) { + errno = EINVAL; return NULL; - return p1+1; + } + errno = 0; + return p1 + 1; } /* @@ -1598,7 +1603,7 @@ controller = pick_controller_from_path(fc, path); if (!controller) - return -EIO; + return -errno; cgroup = find_cgroup_in_path(path); if (!cgroup) { /* this is just /cgroup/controller, return it as a dir */ @@ -1698,7 +1703,7 @@ // return list of keys for the controller, and list of child cgroups controller = pick_controller_from_path(fc, path); if (!controller) - return -EIO; + return -errno; cgroup = find_cgroup_in_path(path); if (!cgroup) { @@ -1742,8 +1747,11 @@ struct fuse_context *fc = fuse_get_context(); char **clist = NULL; + if (filler(buf, ".", NULL, 0) != 0 || filler(buf, "..", NULL, 0) != 0) + return -EIO; + if (d->type != LXC_TYPE_CGDIR) { - fprintf(stderr, "Internal error: file cache info used in readdir\n"); + lxcfs_error("%s\n", "Internal error: file cache info used in readdir."); return -EIO; } if (!d->cgroup && !d->controller) { @@ -1853,10 +1861,10 @@ controller = pick_controller_from_path(fc, path); if (!controller) - return -EIO; + return -errno; cgroup = find_cgroup_in_path(path); if (!cgroup) - return -EINVAL; + return -errno; get_cgdir_and_path(cgroup, &cgdir, &last); if (!last) { @@ -1909,18 +1917,22 @@ int cg_access(const char *path, int mode) { + int ret; const char *cgroup; - char *last = NULL, *path1, *path2, * cgdir = NULL, *controller; + char *path1, *path2, *controller; + char *last = NULL, *cgdir = NULL; struct cgfs_files *k = NULL; struct fuse_context *fc = fuse_get_context(); - int ret; + + if (strcmp(path, "/cgroup") == 0) + return 0; if (!fc) return -EIO; controller = pick_controller_from_path(fc, path); if (!controller) - return -EIO; + return -errno; cgroup = find_cgroup_in_path(path); if (!cgroup) { // access("/sys/fs/cgroup/systemd", mode) - rx allowed, w not @@ -1984,14 +1996,14 @@ return false; if ((epfd = epoll_create(1)) < 0) { - fprintf(stderr, "Failed to create epoll socket: %m\n"); + lxcfs_error("%s\n", "Failed to create epoll socket: %m."); return false; } ev.events = POLLIN_SET; ev.data.fd = sock; if (epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &ev) < 0) { - fprintf(stderr, "Failed adding socket to epoll: %m\n"); + lxcfs_error("%s\n", "Failed adding socket to epoll: %m."); close(epfd); return false; } @@ -2039,8 +2051,7 @@ if (pingfirst) { if (msgrecv(sock, buf, 1) != 1) { - fprintf(stderr, "%s: Error getting reply from server over socketpair\n", - __func__); + lxcfs_error("%s\n", "Error getting reply from server over socketpair."); return SEND_CREDS_FAIL; } } @@ -2064,8 +2075,7 @@ msg.msg_iovlen = 1; if (sendmsg(sock, &msg, 0) < 0) { - fprintf(stderr, "%s: failed at sendmsg: %s\n", __func__, - strerror(errno)); + lxcfs_error("Failed at sendmsg: %s.\n",strerror(errno)); if (errno == 3) return SEND_CREDS_NOTSK; return SEND_CREDS_FAIL; @@ -2091,12 +2101,12 @@ cred->gid = -1; if (setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) { - fprintf(stderr, "Failed to set passcred: %s\n", strerror(errno)); + lxcfs_error("Failed to set passcred: %s\n", strerror(errno)); return false; } buf[0] = '1'; if (write(sock, buf, 1) != 1) { - fprintf(stderr, "Failed to start write on scm fd: %s\n", strerror(errno)); + lxcfs_error("Failed to start write on scm fd: %s\n", strerror(errno)); return false; } @@ -2111,14 +2121,12 @@ msg.msg_iovlen = 1; if (!wait_for_sock(sock, 2)) { - fprintf(stderr, "Timed out waiting for scm_cred: %s\n", - strerror(errno)); + lxcfs_error("Timed out waiting for scm_cred: %s\n", strerror(errno)); return false; } ret = recvmsg(sock, &msg, MSG_DONTWAIT); if (ret < 0) { - fprintf(stderr, "Failed to receive scm_cred: %s\n", - strerror(errno)); + lxcfs_error("Failed to receive scm_cred: %s\n", strerror(errno)); return false; } @@ -2151,10 +2159,8 @@ char b = '1'; close(args->cpipe[0]); - if (write(args->cpipe[1], &b, sizeof(char)) < 0) { - fprintf(stderr, "%s (child): error on write: %s\n", - __func__, strerror(errno)); - } + if (write(args->cpipe[1], &b, sizeof(char)) < 0) + lxcfs_error("(child): error on write: %s.\n", strerror(errno)); close(args->cpipe[1]); return args->wrapped(args->sock, args->tpid); } @@ -2288,13 +2294,11 @@ // read converted results if (!wait_for_sock(sock[0], 2)) { - fprintf(stderr, "%s: timed out waiting for pid from child: %s\n", - __func__, strerror(errno)); + lxcfs_error("Timed out waiting for pid from child: %s.\n", strerror(errno)); goto out; } if (read(sock[0], &qpid, sizeof(qpid)) != sizeof(qpid)) { - fprintf(stderr, "%s: error reading pid from child: %s\n", - __func__, strerror(errno)); + lxcfs_error("Error reading pid from child: %s.\n", strerror(errno)); goto out; } must_strcat_pid(d, &sz, &asz, qpid); @@ -2309,8 +2313,7 @@ v = '1'; if (send_creds(sock[0], &cred, v, true) != SEND_CREDS_OK) { // failed to ask child to exit - fprintf(stderr, "%s: failed to ask child to exit: %s\n", - __func__, strerror(errno)); + lxcfs_error("Failed to ask child to exit: %s.\n", strerror(errno)); goto out; } @@ -2338,7 +2341,7 @@ bool r; if (f->type != LXC_TYPE_CGFILE) { - fprintf(stderr, "Internal error: directory cache info used in cg_read\n"); + lxcfs_error("%s\n", "Internal error: directory cache info used in cg_read."); return -EIO; } @@ -2405,12 +2408,11 @@ cred.gid = 0; while (1) { if (!wait_for_sock(sock, 2)) { - fprintf(stderr, "%s: timeout reading from parent\n", __func__); + lxcfs_error("%s\n", "Timeout reading from parent."); return 1; } if ((ret = read(sock, &vpid, sizeof(pid_t))) != sizeof(pid_t)) { - fprintf(stderr, "%s: bad read from parent: %s\n", - __func__, strerror(errno)); + lxcfs_error("Bad read from parent: %s.\n", strerror(errno)); return 1; } if (vpid == -1) // done @@ -2511,20 +2513,20 @@ *gid = -1; sprintf(line, "/proc/%d/status", pid); if ((f = fopen(line, "r")) == NULL) { - fprintf(stderr, "Error opening %s: %s\n", line, strerror(errno)); + lxcfs_error("Error opening %s: %s\n", line, strerror(errno)); return; } while (fgets(line, 400, f)) { if (strncmp(line, "Uid:", 4) == 0) { if (sscanf(line+4, "%u", &u) != 1) { - fprintf(stderr, "bad uid line for pid %u\n", pid); + lxcfs_error("bad uid line for pid %u\n", pid); fclose(f); return; } *uid = u; } else if (strncmp(line, "Gid:", 4) == 0) { if (sscanf(line+4, "%u", &g) != 1) { - fprintf(stderr, "bad gid line for pid %u\n", pid); + lxcfs_error("bad gid line for pid %u\n", pid); fclose(f); return; } @@ -2596,8 +2598,7 @@ char v; if (write(sock[0], &qpid, sizeof(qpid)) != sizeof(qpid)) { - fprintf(stderr, "%s: error writing pid to child: %s\n", - __func__, strerror(errno)); + lxcfs_error("Error writing pid to child: %s.\n", strerror(errno)); goto out; } @@ -2621,7 +2622,7 @@ /* All good, write the value */ qpid = -1; if (write(sock[0], &qpid ,sizeof(qpid)) != sizeof(qpid)) - fprintf(stderr, "Warning: failed to ask child to exit\n"); + lxcfs_error("%s\n", "Warning: failed to ask child to exit."); if (!fail) answer = true; @@ -2650,7 +2651,7 @@ bool r; if (f->type != LXC_TYPE_CGFILE) { - fprintf(stderr, "Internal error: directory cache info used in cg_write\n"); + lxcfs_error("%s\n", "Internal error: directory cache info used in cg_write."); return -EIO; } @@ -2703,15 +2704,16 @@ return -EIO; if (strcmp(path, "/cgroup") == 0) - return -EINVAL; + return -EPERM; controller = pick_controller_from_path(fc, path); if (!controller) - return -EINVAL; + return errno == ENOENT ? -EPERM : -errno; + cgroup = find_cgroup_in_path(path); if (!cgroup) /* this is just /cgroup/controller */ - return -EINVAL; + return -EPERM; get_cgdir_and_path(cgroup, &cgdir, &last); @@ -2768,15 +2770,16 @@ return -EIO; if (strcmp(path, "/cgroup") == 0) - return -EINVAL; + return -EPERM; controller = pick_controller_from_path(fc, path); if (!controller) - return -EINVAL; + return errno == ENOENT ? -EPERM : -errno; + cgroup = find_cgroup_in_path(path); if (!cgroup) /* this is just /cgroup/controller */ - return -EINVAL; + return -EPERM; get_cgdir_and_path(cgroup, &cgdir, &last); @@ -2834,14 +2837,13 @@ if (!fc) return -EIO; - controller = pick_controller_from_path(fc, path); if (!controller) - return -EINVAL; + return errno == ENOENT ? -EPERM : -errno; cgroup = find_cgroup_in_path(path); if (!cgroup) - return -EINVAL; + return -errno; get_cgdir_and_path(cgroup, &cgdir, &last); if (!last) @@ -2858,7 +2860,7 @@ else if (last && strcmp(next, last) == 0) ret = -EEXIST; else - ret = -ENOENT; + ret = -EPERM; goto out; } @@ -2890,16 +2892,20 @@ return -EIO; controller = pick_controller_from_path(fc, path); - if (!controller) - return -EINVAL; + if (!controller) /* Someone's trying to delete "/cgroup". */ + return -EPERM; cgroup = find_cgroup_in_path(path); - if (!cgroup) - return -EINVAL; + if (!cgroup) /* Someone's trying to delete a controller e.g. "/blkio". */ + return -EPERM; get_cgdir_and_path(cgroup, &cgdir, &last); if (!last) { - ret = -EINVAL; + /* Someone's trying to delete a cgroup on the same level as the + * "/lxc" cgroup e.g. rmdir "/cgroup/blkio/lxc" or + * rmdir "/cgroup/blkio/init.slice". + */ + ret = -EPERM; goto out; } @@ -2943,16 +2949,32 @@ return false; } -static void get_mem_cached(char *memstat, unsigned long *v) +static void parse_memstat(char *memstat, unsigned long *cached, + unsigned long *active_anon, unsigned long *inactive_anon, + unsigned long *active_file, unsigned long *inactive_file, + unsigned long *unevictable) { char *eol; - *v = 0; while (*memstat) { - if (startswith(memstat, "total_cache")) { - sscanf(memstat + 11, "%lu", v); - *v /= 1024; - return; + if (startswith(memstat, "cache")) { + sscanf(memstat + 11, "%lu", cached); + *cached /= 1024; + } else if (startswith(memstat, "active_anon")) { + sscanf(memstat + 11, "%lu", active_anon); + *active_anon /= 1024; + } else if (startswith(memstat, "inactive_anon")) { + sscanf(memstat + 11, "%lu", inactive_anon); + *inactive_anon /= 1024; + } else if (startswith(memstat, "active_file")) { + sscanf(memstat + 11, "%lu", active_file); + *active_file /= 1024; + } else if (startswith(memstat, "inactive_file")) { + sscanf(memstat + 11, "%lu", inactive_file); + *inactive_file /= 1024; + } else if (startswith(memstat, "unevictable")) { + sscanf(memstat + 11, "%lu", unevictable); + *unevictable /= 1024; } eol = strchr(memstat, '\n'); if (!eol) @@ -3003,7 +3025,7 @@ goto err; } if (l >= cache_size) { - fprintf(stderr, "Internal error: truncated write to cache\n"); + lxcfs_error("%s\n", "Internal error: truncated write to cache."); rv = 0; goto err; } @@ -3069,7 +3091,8 @@ *memswlimit_str = NULL, *memswusage_str = NULL, *memswlimit_default_str = NULL, *memswusage_default_str = NULL; unsigned long memlimit = 0, memusage = 0, memswlimit = 0, memswusage = 0, - cached = 0, hosttotal = 0; + cached = 0, hosttotal = 0, active_anon = 0, inactive_anon = 0, + active_file = 0, inactive_file = 0, unevictable = 0; char *line = NULL; size_t linelen = 0, total_len = 0, rv = 0; char *cache = d->buf; @@ -3128,7 +3151,9 @@ memlimit /= 1024; memusage /= 1024; - get_mem_cached(memstat_str, &cached); + parse_memstat(memstat_str, &cached, &active_anon, + &inactive_anon, &active_file, &inactive_file, + &unevictable); f = fopen("/proc/meminfo", "r"); if (!f) @@ -3155,8 +3180,10 @@ snprintf(lbuf, 100, "SwapTotal: %8lu kB\n", memswlimit - memlimit); printme = lbuf; } else if (startswith(line, "SwapFree:") && memswlimit > 0 && memswusage > 0) { - snprintf(lbuf, 100, "SwapFree: %8lu kB\n", - (memswlimit - memlimit) - (memswusage - memusage)); + unsigned long swaptotal = memswlimit - memlimit, + swapusage = memswusage - memusage, + swapfree = swapusage < swaptotal ? swaptotal - swapusage : 0; + snprintf(lbuf, 100, "SwapFree: %8lu kB\n", swapfree); printme = lbuf; } else if (startswith(line, "Slab:")) { snprintf(lbuf, 100, "Slab: %8lu kB\n", 0UL); @@ -3170,6 +3197,35 @@ } else if (startswith(line, "SwapCached:")) { snprintf(lbuf, 100, "SwapCached: %8lu kB\n", 0UL); printme = lbuf; + } else if (startswith(line, "Active")) { + snprintf(lbuf, 100, "Active: %8lu kB\n", + active_anon + active_file); + printme = lbuf; + } else if (startswith(line, "Inactive")) { + snprintf(lbuf, 100, "Inactive: %8lu kB\n", + inactive_anon + inactive_file); + printme = lbuf; + } else if (startswith(line, "Active(anon)")) { + snprintf(lbuf, 100, "Active(anon): %8lu kB\n", active_anon); + printme = lbuf; + } else if (startswith(line, "Inactive(anon)")) { + snprintf(lbuf, 100, "Inactive(anon): %8lu kB\n", inactive_anon); + printme = lbuf; + } else if (startswith(line, "Active(file)")) { + snprintf(lbuf, 100, "Active(file): %8lu kB\n", active_file); + printme = lbuf; + } else if (startswith(line, "Inactive(file)")) { + snprintf(lbuf, 100, "Inactive(file): %8lu kB\n", inactive_file); + printme = lbuf; + } else if (startswith(line, "Unevictable")) { + snprintf(lbuf, 100, "Unevictable: %8lu kB\n", unevictable); + printme = lbuf; + } else if (startswith(line, "SReclaimable")) { + snprintf(lbuf, 100, "SReclaimable: %8lu kB\n", 0UL); + printme = lbuf; + } else if (startswith(line, "SUnreclaim")) { + snprintf(lbuf, 100, "SUnreclaim: %8lu kB\n", 0UL); + printme = lbuf; } else printme = line; @@ -3181,7 +3237,7 @@ } if (l >= cache_size) { - fprintf(stderr, "Internal error: truncated write to cache\n"); + lxcfs_error("%s\n", "Internal error: truncated write to cache."); rv = 0; goto err; } @@ -3312,7 +3368,7 @@ goto err; } if (l >= cache_size) { - fprintf(stderr, "Internal error: truncated write to cache\n"); + lxcfs_error("%s\n", "Internal error: truncated write to cache."); rv = 0; goto err; } @@ -3337,7 +3393,7 @@ goto err; } if (l >= cache_size) { - fprintf(stderr, "Internal error: truncated write to cache\n"); + lxcfs_error("%s\n", "Internal error: truncated write to cache."); rv = 0; goto err; } @@ -3355,7 +3411,7 @@ goto err; } if (l >= cache_size) { - fprintf(stderr, "Internal error: truncated write to cache\n"); + lxcfs_error("%s\n", "Internal error: truncated write to cache."); rv = 0; goto err; } @@ -3462,7 +3518,7 @@ //skip first line if (getline(&line, &linelen, f) < 0) { - fprintf(stderr, "proc_stat_read read first line failed\n"); + lxcfs_error("%s\n", "proc_stat_read read first line failed."); goto err; } @@ -3472,6 +3528,8 @@ char cpu_char[10]; /* That's a lot of cores */ char *c; + if (strlen(line) == 0) + continue; if (sscanf(line, "cpu%9[^ ]", cpu_char) != 1) { /* not a ^cpuN line containing a number N, just print it */ l = snprintf(cache, cache_size, "%s", line); @@ -3481,7 +3539,7 @@ goto err; } if (l >= cache_size) { - fprintf(stderr, "Internal error: truncated write to cache\n"); + lxcfs_error("%s\n", "Internal error: truncated write to cache."); rv = 0; goto err; } @@ -3508,7 +3566,7 @@ } if (l >= cache_size) { - fprintf(stderr, "Internal error: truncated write to cache\n"); + lxcfs_error("%s\n", "Internal error: truncated write to cache."); rv = 0; goto err; } @@ -3540,7 +3598,7 @@ cache += cpuall_len; } else{ /* shouldn't happen */ - fprintf(stderr, "proc_stat_read copy cpuall failed, cpuall_len=%d\n", cpuall_len); + lxcfs_error("proc_stat_read copy cpuall failed, cpuall_len=%d.", cpuall_len); cpuall_len = 0; } @@ -3610,17 +3668,9 @@ #if RELOADTEST void iwashere(void) { - char *name, *cwd = get_current_dir_name(); - size_t len; int fd; - if (!cwd) - exit(1); - len = strlen(cwd) + strlen("/iwashere") + 1; - name = alloca(len); - snprintf(name, len, "%s/iwashere", cwd); - free(cwd); - fd = creat(name, 0755); + fd = creat("/tmp/lxcfs-iwashere", 0644); if (fd >= 0) close(fd); } @@ -3780,7 +3830,7 @@ goto err; } if (l >= cache_size) { - fprintf(stderr, "Internal error: truncated write to cache\n"); + lxcfs_error("%s\n", "Internal error: truncated write to cache."); rv = 0; goto err; } @@ -3973,12 +4023,14 @@ int proc_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { - if (filler(buf, "cpuinfo", NULL, 0) != 0 || - filler(buf, "meminfo", NULL, 0) != 0 || - filler(buf, "stat", NULL, 0) != 0 || - filler(buf, "uptime", NULL, 0) != 0 || - filler(buf, "diskstats", NULL, 0) != 0 || - filler(buf, "swaps", NULL, 0) != 0) + if (filler(buf, ".", NULL, 0) != 0 || + filler(buf, "..", NULL, 0) != 0 || + filler(buf, "cpuinfo", NULL, 0) != 0 || + filler(buf, "meminfo", NULL, 0) != 0 || + filler(buf, "stat", NULL, 0) != 0 || + filler(buf, "uptime", NULL, 0) != 0 || + filler(buf, "diskstats", NULL, 0) != 0 || + filler(buf, "swaps", NULL, 0) != 0) return -EINVAL; return 0; } @@ -4024,6 +4076,9 @@ int proc_access(const char *path, int mask) { + if (strcmp(path, "/proc") == 0 && access(path, R_OK) == 0) + return 0; + /* these are all read-only */ if ((mask & ~R_OK) != 0) return -EACCES; @@ -4076,7 +4131,7 @@ if (!makeme) return false; if (mkdir(makeme, mode) && errno != EEXIST) { - fprintf(stderr, "failed to create directory '%s': %s", + lxcfs_error("Failed to create directory '%s': %s.\n", makeme, strerror(errno)); free(makeme); return false; @@ -4090,37 +4145,87 @@ static bool umount_if_mounted(void) { if (umount2(BASEDIR, MNT_DETACH) < 0 && errno != EINVAL) { - fprintf(stderr, "failed to unmount %s: %s.\n", BASEDIR, strerror(errno)); + lxcfs_error("Failed to unmount %s: %s.\n", BASEDIR, strerror(errno)); return false; } return true; } -static int pivot_enter(void) +/* __typeof__ should be safe to use with all compilers. */ +typedef __typeof__(((struct statfs *)NULL)->f_type) fs_type_magic; +static bool has_fs_type(const struct statfs *fs, fs_type_magic magic_val) +{ + return (fs->f_type == (fs_type_magic)magic_val); +} + +/* + * looking at fs/proc_namespace.c, it appears we can + * actually expect the rootfs entry to very specifically contain + * " - rootfs rootfs " + * IIUC, so long as we've chrooted so that rootfs is not our root, + * the rootfs entry should always be skipped in mountinfo contents. + */ +static bool is_on_ramfs(void) +{ + FILE *f; + char *p, *p2; + char *line = NULL; + size_t len = 0; + int i; + + f = fopen("/proc/self/mountinfo", "r"); + if (!f) + return false; + + while (getline(&line, &len, f) != -1) { + for (p = line, i = 0; p && i < 4; i++) + p = strchr(p + 1, ' '); + if (!p) + continue; + p2 = strchr(p + 1, ' '); + if (!p2) + continue; + *p2 = '\0'; + if (strcmp(p + 1, "/") == 0) { + // this is '/'. is it the ramfs? + p = strchr(p2 + 1, '-'); + if (p && strncmp(p, "- rootfs rootfs ", 16) == 0) { + free(line); + fclose(f); + return true; + } + } + } + free(line); + fclose(f); + return false; +} + +static int pivot_enter() { int ret = -1, oldroot = -1, newroot = -1; oldroot = open("/", O_DIRECTORY | O_RDONLY); if (oldroot < 0) { - fprintf(stderr, "%s: Failed to open old root for fchdir.\n", __func__); + lxcfs_error("%s\n", "Failed to open old root for fchdir."); return ret; } newroot = open(ROOTDIR, O_DIRECTORY | O_RDONLY); if (newroot < 0) { - fprintf(stderr, "%s: Failed to open new root for fchdir.\n", __func__); + lxcfs_error("%s\n", "Failed to open new root for fchdir."); goto err; } /* change into new root fs */ if (fchdir(newroot) < 0) { - fprintf(stderr, "%s: Failed to change directory to new rootfs: %s.\n", __func__, ROOTDIR); + lxcfs_error("Failed to change directory to new rootfs: %s.\n", ROOTDIR); goto err; } /* pivot_root into our new root fs */ if (pivot_root(".", ".") < 0) { - fprintf(stderr, "%s: pivot_root() syscall failed: %s.\n", __func__, strerror(errno)); + lxcfs_error("pivot_root() syscall failed: %s.\n", strerror(errno)); goto err; } @@ -4130,16 +4235,17 @@ * to the old-root. */ if (fchdir(oldroot) < 0) { - fprintf(stderr, "%s: Failed to enter old root.\n", __func__); + lxcfs_error("%s\n", "Failed to enter old root."); goto err; } + if (umount2(".", MNT_DETACH) < 0) { - fprintf(stderr, "%s: Failed to detach old root.\n", __func__); + lxcfs_error("%s\n", "Failed to detach old root."); goto err; } if (fchdir(newroot) < 0) { - fprintf(stderr, "%s: Failed to re-enter new root.\n", __func__); + lxcfs_error("%s\n", "Failed to re-enter new root."); goto err; } @@ -4150,79 +4256,124 @@ close(oldroot); if (newroot > 0) close(newroot); + return ret; } +static int chroot_enter() +{ + if (mount(ROOTDIR, "/", NULL, MS_REC | MS_BIND, NULL)) { + lxcfs_error("Failed to recursively bind-mount %s into /.", ROOTDIR); + return -1; + } + + if (chroot(".") < 0) { + lxcfs_error("Call to chroot() failed: %s.\n", strerror(errno)); + return -1; + } + + if (chdir("/") < 0) { + lxcfs_error("Failed to change directory: %s.\n", strerror(errno)); + return -1; + } + + return 0; +} + +static int permute_and_enter(void) +{ + struct statfs sb; + + if (statfs("/", &sb) < 0) { + lxcfs_error("%s\n", "Could not stat / mountpoint."); + return -1; + } + + /* has_fs_type() is not reliable. When the ramfs is a tmpfs it will + * likely report TMPFS_MAGIC. Hence, when it reports no we still check + * /proc/1/mountinfo. */ + if (has_fs_type(&sb, RAMFS_MAGIC) || is_on_ramfs()) + return chroot_enter(); + + if (pivot_enter() < 0) { + lxcfs_error("%s\n", "Could not perform pivot root."); + return -1; + } + + return 0; +} + /* Prepare our new clean root. */ -static int pivot_prepare(void) +static int permute_prepare(void) { if (mkdir(ROOTDIR, 0700) < 0 && errno != EEXIST) { - fprintf(stderr, "%s: Failed to create directory for new root.\n", __func__); + lxcfs_error("%s\n", "Failed to create directory for new root."); return -1; } if (mount("/", ROOTDIR, NULL, MS_BIND, 0) < 0) { - fprintf(stderr, "%s: Failed to bind-mount / for new root: %s.\n", __func__, strerror(errno)); + lxcfs_error("Failed to bind-mount / for new root: %s.\n", strerror(errno)); return -1; } if (mount(RUNTIME_PATH, ROOTDIR RUNTIME_PATH, NULL, MS_BIND, 0) < 0) { - fprintf(stderr, "%s: Failed to bind-mount /run into new root: %s.\n", __func__, strerror(errno)); + lxcfs_error("Failed to bind-mount /run into new root: %s.\n", strerror(errno)); return -1; } if (mount(BASEDIR, ROOTDIR BASEDIR, NULL, MS_REC | MS_MOVE, 0) < 0) { - printf("%s: failed to move " BASEDIR " into new root: %s.\n", __func__, strerror(errno)); + printf("Failed to move " BASEDIR " into new root: %s.\n", strerror(errno)); return -1; } return 0; } -static bool pivot_new_root(void) +/* Calls chroot() on ramfs, pivot_root() in all other cases. */ +static bool permute_root(void) { /* Prepare new root. */ - if (pivot_prepare() < 0) + if (permute_prepare() < 0) return false; /* Pivot into new root. */ - if (pivot_enter() < 0) + if (permute_and_enter() < 0) return false; return true; } -static bool setup_cgfs_dir(void) +static bool cgfs_prepare_mounts(void) { if (!mkdir_p(BASEDIR, 0700)) { - fprintf(stderr, "Failed to create lxcfs cgroup mountpoint.\n"); + lxcfs_error("%s\n", "Failed to create lxcfs cgroup mountpoint."); return false; } if (!umount_if_mounted()) { - fprintf(stderr, "Failed to clean up old lxcfs cgroup mountpoint.\n"); + lxcfs_error("%s\n", "Failed to clean up old lxcfs cgroup mountpoint."); return false; } if (unshare(CLONE_NEWNS) < 0) { - fprintf(stderr, "%s: Failed to unshare mount namespace: %s.\n", __func__, strerror(errno)); + lxcfs_error("Failed to unshare mount namespace: %s.\n", strerror(errno)); return false; } if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0) < 0) { - fprintf(stderr, "%s: Failed to remount / private: %s.\n", __func__, strerror(errno)); + lxcfs_error("Failed to remount / private: %s.\n", strerror(errno)); return false; } if (mount("tmpfs", BASEDIR, "tmpfs", 0, "size=100000,mode=700") < 0) { - fprintf(stderr, "Failed to mount tmpfs over lxcfs cgroup mountpoint.\n"); + lxcfs_error("%s\n", "Failed to mount tmpfs over lxcfs cgroup mountpoint."); return false; } return true; } -static bool do_mount_cgroups(void) +static bool cgfs_mount_hierarchies(void) { char *target; size_t clen, len; @@ -4245,7 +4396,7 @@ return false; } if (mount(controller, target, "cgroup", 0, controller) < 0) { - fprintf(stderr, "Failed mounting cgroup %s\n", controller); + lxcfs_error("Failed mounting cgroup %s\n", controller); free(target); return false; } @@ -4262,15 +4413,15 @@ static bool cgfs_setup_controllers(void) { - if (!setup_cgfs_dir()) + if (!cgfs_prepare_mounts()) return false; - if (!do_mount_cgroups()) { - fprintf(stderr, "Failed to set up private lxcfs cgroup mounts.\n"); + if (!cgfs_mount_hierarchies()) { + lxcfs_error("%s\n", "Failed to set up private lxcfs cgroup mounts."); return false; } - if (!pivot_new_root()) + if (!permute_root()) return false; return true; @@ -4292,14 +4443,16 @@ static void __attribute__((constructor)) collect_and_mount_subsystems(void) { FILE *f; - char *line = NULL; + char *cret, *line = NULL; + char cwd[MAXPATHLEN]; size_t len = 0; int i, init_ns = -1; if ((f = fopen("/proc/self/cgroup", "r")) == NULL) { - fprintf(stderr, "Error opening /proc/self/cgroup: %s\n", strerror(errno)); + lxcfs_error("Error opening /proc/self/cgroup: %s\n", strerror(errno)); return; } + while (getline(&line, &len, f) != -1) { char *p, *p2; @@ -4327,23 +4480,38 @@ /* Preserve initial namespace. */ init_ns = preserve_ns(getpid()); - if (init_ns < 0) + if (init_ns < 0) { + lxcfs_error("%s\n", "Failed to preserve initial mount namespace."); goto out; + } fd_hierarchies = malloc(sizeof(int *) * num_hierarchies); - if (!fd_hierarchies) + if (!fd_hierarchies) { + lxcfs_error("%s\n", strerror(errno)); goto out; + } for (i = 0; i < num_hierarchies; i++) fd_hierarchies[i] = -1; + cret = getcwd(cwd, MAXPATHLEN); + if (!cret) + lxcfs_debug("Could not retrieve current working directory: %s.\n", strerror(errno)); + /* This function calls unshare(CLONE_NEWNS) our initial mount namespace * to privately mount lxcfs cgroups. */ - if (!cgfs_setup_controllers()) + if (!cgfs_setup_controllers()) { + lxcfs_error("%s\n", "Failed to setup private cgroup mounts for lxcfs."); goto out; + } - if (setns(init_ns, 0) < 0) + if (setns(init_ns, 0) < 0) { + lxcfs_error("Failed to switch back to initial mount namespace: %s.\n", strerror(errno)); goto out; + } + + if (!cret || chdir(cwd) < 0) + lxcfs_debug("Could not change back to original working directory: %s.\n", strerror(errno)); print_subsystems(); @@ -4358,6 +4526,8 @@ { int i; + lxcfs_debug("%s\n", "Running destructor for liblxcfs."); + for (i = 0; i < num_hierarchies; i++) { if (hierarchies[i]) free(hierarchies[i]); diff -Nru lxcfs-2.0.3/bindings.h lxcfs-2.0.4/bindings.h --- lxcfs-2.0.3/bindings.h 2016-08-16 02:36:32.000000000 +0000 +++ lxcfs-2.0.4/bindings.h 2016-10-05 09:43:15.000000000 +0000 @@ -1,7 +1,24 @@ +#ifndef __LXCFS_BINDINGS_H +#define __LXCFS_BINDINGS_H + /* directory under which we mount the controllers - /run/lxcfs/controllers */ #define BASEDIR RUNTIME_PATH "/lxcfs/controllers" #define ROOTDIR RUNTIME_PATH "/lxcfs/root" +#define lxcfs_debug_stream(stream, format, ...) \ + do { \ + fprintf(stream, "%s: %d: %s: " format, __FILE__, __LINE__, \ + __func__, __VA_ARGS__); \ + } while (false) + +#define lxcfs_error(format, ...) lxcfs_debug_stream(stderr, format, __VA_ARGS__) + +#ifdef DEBUG +#define lxcfs_debug(format, ...) lxcfs_error(format, __VA_ARGS__) +#else +#define lxcfs_debug(format, ...) +#endif /* DEBUG */ + extern int cg_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi); extern int cg_mkdir(const char *path, mode_t mode); @@ -27,3 +44,5 @@ extern int proc_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi); extern int proc_access(const char *path, int mask); + +#endif /* __LXCFS__BINDINGS_H */ diff -Nru lxcfs-2.0.3/config/init/sysvinit/Makefile.in lxcfs-2.0.4/config/init/sysvinit/Makefile.in --- lxcfs-2.0.3/config/init/sysvinit/Makefile.in 2016-08-16 02:36:38.000000000 +0000 +++ lxcfs-2.0.4/config/init/sysvinit/Makefile.in 2016-10-05 09:43:22.000000000 +0000 @@ -361,8 +361,8 @@ maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -@INIT_SCRIPT_SYSV_FALSE@uninstall-local: @INIT_SCRIPT_SYSV_FALSE@install-data-local: +@INIT_SCRIPT_SYSV_FALSE@uninstall-local: clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am diff -Nru lxcfs-2.0.3/config/init/upstart/Makefile.in lxcfs-2.0.4/config/init/upstart/Makefile.in --- lxcfs-2.0.3/config/init/upstart/Makefile.in 2016-08-16 02:36:38.000000000 +0000 +++ lxcfs-2.0.4/config/init/upstart/Makefile.in 2016-10-05 09:43:22.000000000 +0000 @@ -361,8 +361,8 @@ maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -@INIT_SCRIPT_UPSTART_FALSE@install-data-local: @INIT_SCRIPT_UPSTART_FALSE@uninstall-local: +@INIT_SCRIPT_UPSTART_FALSE@install-data-local: clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am diff -Nru lxcfs-2.0.3/config.guess lxcfs-2.0.4/config.guess --- lxcfs-2.0.3/config.guess 2016-08-16 02:36:38.000000000 +0000 +++ lxcfs-2.0.4/config.guess 2016-10-05 09:43:22.000000000 +0000 @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2015 Free Software Foundation, Inc. +# Copyright 1992-2016 Free Software Foundation, Inc. -timestamp='2015-08-20' +timestamp='2016-04-02' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -27,7 +27,7 @@ # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . @@ -50,7 +50,7 @@ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2015 Free Software Foundation, Inc. +Copyright 1992-2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -237,6 +237,10 @@ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} + exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; @@ -268,42 +272,42 @@ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; + UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; + UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; + UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; + UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; + UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; + UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; + UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; + UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; + UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 @@ -376,16 +380,16 @@ exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build - SUN_ARCH="i386" + SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then - SUN_ARCH="x86_64" + SUN_ARCH=x86_64 fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` @@ -410,7 +414,7 @@ exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} @@ -635,13 +639,13 @@ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi @@ -680,11 +684,11 @@ exit (0); } EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ ${HP_ARCH} = "hppa2.0w" ] + if [ ${HP_ARCH} = hppa2.0w ] then eval $set_cc_for_build @@ -697,12 +701,12 @@ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then - HP_ARCH="hppa2.0w" + HP_ARCH=hppa2.0w else - HP_ARCH="hppa64" + HP_ARCH=hppa64 fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} @@ -807,14 +811,14 @@ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) @@ -896,7 +900,7 @@ exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix @@ -919,7 +923,7 @@ EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) @@ -965,6 +969,9 @@ ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; + k1om:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; @@ -1120,7 +1127,7 @@ # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that + # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; @@ -1269,6 +1276,9 @@ SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux${UNAME_RELEASE} + exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; @@ -1282,9 +1292,9 @@ UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in @@ -1306,7 +1316,7 @@ exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then + if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi @@ -1337,7 +1347,7 @@ # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - if test "$cputype" = "386"; then + if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" @@ -1379,7 +1389,7 @@ echo i386-pc-xenix exit ;; i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos @@ -1390,6 +1400,9 @@ x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs + exit ;; esac cat >&2 <. # @@ -590,8 +590,8 @@ # Identity of this package. PACKAGE_NAME='lxcfs' PACKAGE_TARNAME='lxcfs' -PACKAGE_VERSION='2.0.3' -PACKAGE_STRING='lxcfs 2.0.3' +PACKAGE_VERSION='2.0.4' +PACKAGE_STRING='lxcfs 2.0.4' PACKAGE_BUGREPORT='lxc-devel@lists.linuxcontainers.org' PACKAGE_URL='' @@ -1368,7 +1368,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures lxcfs 2.0.3 to adapt to many kinds of systems. +\`configure' configures lxcfs 2.0.4 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1439,7 +1439,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of lxcfs 2.0.3:";; + short | recursive ) echo "Configuration of lxcfs 2.0.4:";; esac cat <<\_ACEOF @@ -1569,7 +1569,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -lxcfs configure 2.0.3 +lxcfs configure 2.0.4 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1938,7 +1938,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by lxcfs $as_me 2.0.3, which was +It was created by lxcfs $as_me 2.0.4, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2805,7 +2805,7 @@ # Define the identity of the package. PACKAGE='lxcfs' - VERSION='2.0.3' + VERSION='2.0.4' cat >>confdefs.h <<_ACEOF @@ -13676,6 +13676,25 @@ with_distro="pardus" fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /etc/pld-release" >&5 +$as_echo_n "checking for /etc/pld-release... " >&6; } +if ${ac_cv_file__etc_pld_release+:} false; then : + $as_echo_n "(cached) " >&6 +else + test "$cross_compiling" = yes && + as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 +if test -r "/etc/pld-release"; then + ac_cv_file__etc_pld_release=yes +else + ac_cv_file__etc_pld_release=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file__etc_pld_release" >&5 +$as_echo "$ac_cv_file__etc_pld_release" >&6; } +if test "x$ac_cv_file__etc_pld_release" = xyes; then : + with_distro="pld" +fi + fi with_distro=`echo ${with_distro} | tr '[:upper:]' '[:lower:]'` @@ -13686,7 +13705,7 @@ ubuntu) distroconf=default.conf.ubuntu ;; - redhat|centos|fedora|oracle|oracleserver) + redhat|centos|fedora|oracle|oracleserver|pld) distroconf=default.conf.libvirt ;; *) @@ -13738,6 +13757,9 @@ ubuntu) init_script=upstart,systemd,sysvinit ;; + pld) + init_script=systemd,sysvinit + ;; slackware) echo -n "Warning: bsd init job not yet implemented" init_script= @@ -14497,7 +14519,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by lxcfs $as_me 2.0.3, which was +This file was extended by lxcfs $as_me 2.0.4, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -14563,7 +14585,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -lxcfs config.status 2.0.3 +lxcfs config.status 2.0.4 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -15692,7 +15714,6 @@ cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. diff -Nru lxcfs-2.0.3/configure.ac lxcfs-2.0.4/configure.ac --- lxcfs-2.0.3/configure.ac 2016-08-16 02:36:32.000000000 +0000 +++ lxcfs-2.0.4/configure.ac 2016-10-05 09:43:15.000000000 +0000 @@ -1,7 +1,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT([lxcfs], [2.0.3], [lxc-devel@lists.linuxcontainers.org]) +AC_INIT([lxcfs], [2.0.4], [lxc-devel@lists.linuxcontainers.org]) AC_SUBST(ACLOCAL_AMFLAGS, "-I m4") AC_CONFIG_MACRO_DIR([m4]) @@ -66,6 +66,7 @@ AC_CHECK_FILE(/etc/mandrakelinux-release, with_distro="openmandriva") AC_CHECK_FILE(/etc/mandriva-release,with_distro="openmandriva") AC_CHECK_FILE(/etc/pardus-release,with_distro="pardus") + AC_CHECK_FILE(/etc/pld-release,with_distro="pld") fi with_distro=`echo ${with_distro} | tr '[[:upper:]]' '[[:lower:]]'` @@ -76,7 +77,7 @@ ubuntu) distroconf=default.conf.ubuntu ;; - redhat|centos|fedora|oracle|oracleserver) + redhat|centos|fedora|oracle|oracleserver|pld) distroconf=default.conf.libvirt ;; *) @@ -108,6 +109,9 @@ ubuntu) init_script=upstart,systemd,sysvinit ;; + pld) + init_script=systemd,sysvinit + ;; slackware) echo -n "Warning: bsd init job not yet implemented" init_script= diff -Nru lxcfs-2.0.3/debian/changelog lxcfs-2.0.4/debian/changelog --- lxcfs-2.0.3/debian/changelog 2016-08-17 00:31:32.000000000 +0000 +++ lxcfs-2.0.4/debian/changelog 2016-10-05 20:30:52.000000000 +0000 @@ -1,8 +1,48 @@ -lxcfs (2.0.3-0ubuntu2~ubuntu14.04.1~ppa1) trusty; urgency=medium +lxcfs (2.0.4-0ubuntu1~ubuntu14.04.1~ppa1) trusty; urgency=medium * No-change backport to trusty - -- Stéphane Graber Wed, 17 Aug 2016 00:31:32 +0000 + -- Stéphane Graber Wed, 05 Oct 2016 20:30:52 +0000 + +lxcfs (2.0.4-0ubuntu1) yakkety; urgency=medium + + * New upstream bugfix release (2.0.4): + - Fix test_reload for lxcfs chroot + - Virtualize more of the meminfo fields + - pam: fix race in cgroup creation + - meminfo: don't show negative swapfree + - bindings: improve debugging + - bindings: use openat fd for fstatat(), unlinkat() + - bindings: close open fds on error + - bindings: grant access to /var/lib/lxcfs + - bindings: enable access to /var/lib/lxcfs/cgroup + - bindings: allow access to /var/lib/lxcfs/proc + - lxcfs, bindings: show "." and ".." dir entries + - lxcfs: better fs behavior on /var/lib/lxcfs + - bindings: non functional changes + - bindings: set errno in pick_controller_from_path() + - bindings: more consistent fs behavior + - add pld linux support + - don't use argv[0] in usage output + - bindings: revert cgroup check + - bindings: improve returned errnos + - bindings: make rmdir behave more consistently + - libtool: do not link lxcfs against liblxcfs + - bindings, lxcfs: improve debugging + - bindings: fix debug macro + - autotools: add -avoid-version + - bindings: restore original working directory + - bindings: add function to check fs type + - bindings: agnostic naming + - bindings: use chroot() on ramfs + - bindings: fix type weirdness with statfs f_type + - bindings: make pivot_enter() contain all its code + * Drop all patches, now upstream + * Cherry-pick from upstream: + - 0001-Add-Documentation-key-to-systemd-unit.patch + * Update linitan overrides + + -- Stéphane Graber Wed, 05 Oct 2016 14:25:51 +0200 lxcfs (2.0.3-0ubuntu2) yakkety; urgency=medium diff -Nru lxcfs-2.0.3/debian/control lxcfs-2.0.4/debian/control --- lxcfs-2.0.3/debian/control 2016-06-29 19:22:21.000000000 +0000 +++ lxcfs-2.0.4/debian/control 2016-10-05 12:25:51.000000000 +0000 @@ -18,7 +18,6 @@ Homepage: https://linuxcontainers.org Vcs-Git: https://anonscm.debian.org/cgit/pkg-lxc/lxcfs.git Vcs-Browser: https://anonscm.debian.org/cgit/pkg-lxc/lxcfs.git -XS-Testsuite: autopkgtest Package: lxcfs Architecture: linux-any diff -Nru lxcfs-2.0.3/debian/patches/0001-Add-Documentation-key-to-systemd-unit.patch lxcfs-2.0.4/debian/patches/0001-Add-Documentation-key-to-systemd-unit.patch --- lxcfs-2.0.3/debian/patches/0001-Add-Documentation-key-to-systemd-unit.patch 1970-01-01 00:00:00.000000000 +0000 +++ lxcfs-2.0.4/debian/patches/0001-Add-Documentation-key-to-systemd-unit.patch 2016-10-05 12:25:51.000000000 +0000 @@ -0,0 +1,28 @@ +From 4cc64218a7bc530d0015bee760720d000ec74306 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?St=C3=A9phane=20Graber?= +Date: Wed, 5 Oct 2016 14:39:45 +0200 +Subject: [PATCH] Add Documentation key to systemd unit +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Stéphane Graber +--- + config/init/systemd/lxcfs.service | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/config/init/systemd/lxcfs.service b/config/init/systemd/lxcfs.service +index 004e54f..95e3ee9 100644 +--- a/config/init/systemd/lxcfs.service ++++ b/config/init/systemd/lxcfs.service +@@ -2,6 +2,7 @@ + Description=FUSE filesystem for LXC + ConditionVirtualization=!container + Before=lxc.service ++Documentation=man:lxcfs(1) + + [Service] + ExecStart=/usr/bin/lxcfs /var/lib/lxcfs/ +-- +2.9.3 + diff -Nru lxcfs-2.0.3/debian/patches/0001-Fix-test_reload-for-lxcfs-chroot.patch lxcfs-2.0.4/debian/patches/0001-Fix-test_reload-for-lxcfs-chroot.patch --- lxcfs-2.0.3/debian/patches/0001-Fix-test_reload-for-lxcfs-chroot.patch 2016-08-16 16:36:34.000000000 +0000 +++ lxcfs-2.0.4/debian/patches/0001-Fix-test_reload-for-lxcfs-chroot.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -From 4e29cb8abdfcaea83b35930cf64dbe1ad6efc60a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?St=C3=A9phane=20Graber?= -Date: Tue, 16 Aug 2016 12:36:01 -0400 -Subject: [PATCH] Fix test_reload for lxcfs chroot -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Stéphane Graber ---- - bindings.c | 10 +--------- - tests/test_reload.sh | 8 ++++---- - 2 files changed, 5 insertions(+), 13 deletions(-) - -diff --git a/bindings.c b/bindings.c -index 04f0b08..2fb4acf 100644 ---- a/bindings.c -+++ b/bindings.c -@@ -3610,17 +3610,9 @@ out: - #if RELOADTEST - void iwashere(void) - { -- char *name, *cwd = get_current_dir_name(); -- size_t len; - int fd; - -- if (!cwd) -- exit(1); -- len = strlen(cwd) + strlen("/iwashere") + 1; -- name = alloca(len); -- snprintf(name, len, "%s/iwashere", cwd); -- free(cwd); -- fd = creat(name, 0755); -+ fd = creat("/tmp/lxcfs-iwashere", 0644); - if (fd >= 0) - close(fd); - } -diff --git a/tests/test_reload.sh b/tests/test_reload.sh -index 5474cbb..5e37ace 100755 ---- a/tests/test_reload.sh -+++ b/tests/test_reload.sh -@@ -26,7 +26,7 @@ cleanup() { - umount -l ${testdir} - fi - rm -rf ${testdir} ${installdir} -- rm -f iwashere -+ rm -f /tmp/lxcfs-iwashere - rm -f ${pidfile} - if [ ${FAILED} -eq 1 ]; then - echo "liblxcfs.so reload test FAILED" -@@ -50,9 +50,9 @@ while [ ! -d ${testdir}/proc ]; do - count=$((count+1)) - done - --rm -f iwashere -+rm -f /tmp/lxcfs-iwashere - cat ${testdir}/proc/uptime --[ ! -f iwashere ] -+[ ! -f /tmp/lxcfs-iwashere ] - ( - cd ${topdir}; - make liblxcfstest.la -@@ -65,5 +65,5 @@ cp ${libdir}/liblxcfstest.so ${libdir}/liblxcfs.so - kill -USR1 ${lxcfspid} - - cat ${testdir}/proc/uptime --[ -f iwashere ] -+[ -f /tmp/lxcfs-iwashere ] - FAILED=0 --- -2.8.1 - diff -Nru lxcfs-2.0.3/debian/patches/series lxcfs-2.0.4/debian/patches/series --- lxcfs-2.0.3/debian/patches/series 2016-08-16 16:38:35.000000000 +0000 +++ lxcfs-2.0.4/debian/patches/series 2016-10-05 12:25:51.000000000 +0000 @@ -1 +1 @@ -0001-Fix-test_reload-for-lxcfs-chroot.patch +0001-Add-Documentation-key-to-systemd-unit.patch diff -Nru lxcfs-2.0.3/debian/source.lintian-overrides lxcfs-2.0.4/debian/source.lintian-overrides --- lxcfs-2.0.3/debian/source.lintian-overrides 2016-03-31 18:28:42.000000000 +0000 +++ lxcfs-2.0.4/debian/source.lintian-overrides 2016-10-05 12:25:51.000000000 +0000 @@ -1 +1 @@ -lxcfs source: xs-testsuite-header-in-debian-control xs-testsuite +lxcfs source: unknown-field-in-dsc testsuite-triggers diff -Nru lxcfs-2.0.3/ltmain.sh lxcfs-2.0.4/ltmain.sh --- lxcfs-2.0.3/ltmain.sh 2016-02-07 23:39:37.000000000 +0000 +++ lxcfs-2.0.4/ltmain.sh 2016-07-25 17:42:23.000000000 +0000 @@ -31,7 +31,7 @@ PROGRAM=libtool PACKAGE=libtool -VERSION="2.4.6 Debian-2.4.6-0.1" +VERSION="2.4.6 Debian-2.4.6-1" package_revision=2.4.6 @@ -1977,7 +1977,7 @@ # End: # Set a version string. -scriptversion='(GNU libtool) 2.4.6' +scriptversion='(GNU libtool) 2.4.6 Debian-2.4.6-1' # func_echo ARG... @@ -2068,7 +2068,7 @@ compiler: $LTCC compiler flags: $LTCFLAGS linker: $LD (gnu? $with_gnu_ld) - version: $progname (GNU libtool) 2.4.6 + version: $progname $scriptversion automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` diff -Nru lxcfs-2.0.3/lxcfs.c lxcfs-2.0.4/lxcfs.c --- lxcfs-2.0.3/lxcfs.c 2016-08-16 02:36:32.000000000 +0000 +++ lxcfs-2.0.4/lxcfs.c 2016-10-05 09:43:15.000000000 +0000 @@ -43,7 +43,7 @@ int ret; if ((ret = pthread_mutex_lock(l)) != 0) { - fprintf(stderr, "pthread_mutex_lock returned:%d %s\n", ret, strerror(ret)); + lxcfs_error("returned:%d %s\n", ret, strerror(ret)); exit(1); } } @@ -53,7 +53,7 @@ int ret; if ((ret = pthread_mutex_unlock(l)) != 0) { - fprintf(stderr, "pthread_mutex_unlock returned:%d %s\n", ret, strerror(ret)); + lxcfs_error("returned:%d %s\n", ret, strerror(ret)); exit(1); } } @@ -74,23 +74,27 @@ * lock and when we know the user_count was 0 */ static void do_reload(void) { - if (dlopen_handle) + if (dlopen_handle) { + lxcfs_debug("%s\n", "Closing liblxcfs.so handle."); dlclose(dlopen_handle); + } /* First try loading using ld.so */ dlopen_handle = dlopen("liblxcfs.so", RTLD_LAZY); - if (dlopen_handle) + if (dlopen_handle) { + lxcfs_debug("%s\n", "Successfully called dlopen() on liblxcfs.so."); goto good; + } dlopen_handle = dlopen("/usr/lib/lxcfs/liblxcfs.so", RTLD_LAZY); if (!dlopen_handle) { - fprintf(stderr, "Failed to open liblxcfs: %s.\n", dlerror()); + lxcfs_error("Failed to open liblxcfs.so: %s.\n", dlerror()); _exit(1); } good: if (need_reload) - fprintf(stderr, "lxcfs: reloaded\n"); + lxcfs_error("%s\n", "lxcfs: reloaded"); need_reload = 0; } @@ -124,7 +128,7 @@ cg_getattr = (int (*)(const char *, struct stat *)) dlsym(dlopen_handle, "cg_getattr"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "cg_getattr: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -139,7 +143,7 @@ proc_getattr = (int (*)(const char *, struct stat *)) dlsym(dlopen_handle, "proc_getattr"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "proc_getattr: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -157,7 +161,7 @@ cg_read = (int (*)(const char *, char *, size_t, off_t, struct fuse_file_info *)) dlsym(dlopen_handle, "cg_read"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "cg_read: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -175,7 +179,7 @@ proc_read = (int (*)(const char *, char *, size_t, off_t, struct fuse_file_info *)) dlsym(dlopen_handle, "proc_read"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "proc_read: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -192,7 +196,7 @@ cg_write = (int (*)(const char *, const char *, size_t, off_t, struct fuse_file_info *)) dlsym(dlopen_handle, "cg_write"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "cg_write: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -207,7 +211,7 @@ cg_mkdir = (int (*)(const char *, mode_t)) dlsym(dlopen_handle, "cg_mkdir"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "cg_mkdir: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -222,7 +226,7 @@ cg_chown = (int (*)(const char *, uid_t, gid_t)) dlsym(dlopen_handle, "cg_chown"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "cg_chown: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -237,7 +241,7 @@ cg_rmdir = (int (*)(const char *path)) dlsym(dlopen_handle, "cg_rmdir"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "cg_rmdir: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -252,7 +256,7 @@ cg_chmod = (int (*)(const char *, mode_t)) dlsym(dlopen_handle, "cg_chmod"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "cg_chmod: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -270,7 +274,7 @@ cg_readdir = (int (*)(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *)) dlsym(dlopen_handle, "cg_readdir"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "cg_readdir: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -288,7 +292,7 @@ proc_readdir = (int (*)(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *)) dlsym(dlopen_handle, "proc_readdir"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "proc_readdir: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -303,7 +307,7 @@ cg_open = (int (*)(const char *, struct fuse_file_info *)) dlsym(dlopen_handle, "cg_open"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "cg_open: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -318,7 +322,7 @@ cg_access = (int (*)(const char *, int mode)) dlsym(dlopen_handle, "cg_access"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "cg_access: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -333,7 +337,7 @@ proc_open = (int (*)(const char *path, struct fuse_file_info *fi)) dlsym(dlopen_handle, "proc_open"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "proc_open: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -348,7 +352,7 @@ proc_access = (int (*)(const char *, int mode)) dlsym(dlopen_handle, "proc_access"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "proc_access: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -363,7 +367,7 @@ cg_release = (int (*)(const char *path, struct fuse_file_info *)) dlsym(dlopen_handle, "cg_release"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "cg_release: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -378,7 +382,7 @@ proc_release = (int (*)(const char *path, struct fuse_file_info *)) dlsym(dlopen_handle, "proc_release"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "proc_release: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -393,7 +397,7 @@ cg_opendir = (int (*)(const char *path, struct fuse_file_info *fi)) dlsym(dlopen_handle, "cg_opendir"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "cg_opendir: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -408,7 +412,7 @@ cg_releasedir = (int (*)(const char *path, struct fuse_file_info *)) dlsym(dlopen_handle, "cg_releasedir"); error = dlerror(); if (error != NULL) { - fprintf(stderr, "cg_releasedir: %s\n", error); + lxcfs_error("%s\n", error); return -1; } @@ -424,11 +428,19 @@ static int lxcfs_getattr(const char *path, struct stat *sb) { int ret; + struct timespec now; + if (strcmp(path, "/") == 0) { + if (clock_gettime(CLOCK_REALTIME, &now) < 0) + return -EINVAL; + sb->st_uid = sb->st_gid = 0; + sb->st_atim = sb->st_mtim = sb->st_ctim = now; + sb->st_size = 0; sb->st_mode = S_IFDIR | 00755; sb->st_nlink = 2; return 0; } + if (strncmp(path, "/cgroup", 7) == 0) { up_users(); ret = do_cg_getattr(path, sb); @@ -441,7 +453,7 @@ down_users(); return ret; } - return -EINVAL; + return -ENOENT; } static int lxcfs_opendir(const char *path, struct fuse_file_info *fi) @@ -466,9 +478,11 @@ { int ret; if (strcmp(path, "/") == 0) { - if (filler(buf, "proc", NULL, 0) != 0 || - filler(buf, "cgroup", NULL, 0) != 0) - return -EINVAL; + if (filler(buf, ".", NULL, 0) != 0 || + filler(buf, "..", NULL, 0) != 0 || + filler(buf, "proc", NULL, 0) != 0 || + filler(buf, "cgroup", NULL, 0) != 0) + return -ENOMEM; return 0; } if (strncmp(path, "/cgroup", 7) == 0) { @@ -483,12 +497,16 @@ down_users(); return ret; } - return -EINVAL; + return -ENOENT; } static int lxcfs_access(const char *path, int mode) { int ret; + + if (strcmp(path, "/") == 0 && (mode & W_OK) == 0) + return 0; + if (strncmp(path, "/cgroup", 7) == 0) { up_users(); ret = do_cg_access(path, mode); @@ -502,7 +520,7 @@ return ret; } - return -EINVAL; + return -EACCES; } static int lxcfs_releasedir(const char *path, struct fuse_file_info *fi) @@ -537,7 +555,7 @@ return ret; } - return -EINVAL; + return -EACCES; } static int lxcfs_read(const char *path, char *buf, size_t size, off_t offset, @@ -613,7 +631,7 @@ return ret; } - return -EINVAL; + return -EPERM; } int lxcfs_chown(const char *path, uid_t uid, gid_t gid) @@ -626,7 +644,10 @@ return ret; } - return -EINVAL; + if (strncmp(path, "/proc", 5) == 0) + return -EPERM; + + return -ENOENT; } /* @@ -638,7 +659,7 @@ { if (strncmp(path, "/cgroup", 7) == 0) return 0; - return -EINVAL; + return -EPERM; } int lxcfs_rmdir(const char *path) @@ -650,7 +671,7 @@ down_users(); return ret; } - return -EINVAL; + return -EPERM; } int lxcfs_chmod(const char *path, mode_t mode) @@ -662,7 +683,11 @@ down_users(); return ret; } - return -EINVAL; + + if (strncmp(path, "/proc", 5) == 0) + return -EPERM; + + return -ENOENT; } const struct fuse_operations lxcfs_ops = { @@ -708,13 +733,13 @@ .fgetattr = NULL, }; -static void usage(const char *me) +static void usage() { fprintf(stderr, "Usage:\n"); fprintf(stderr, "\n"); - fprintf(stderr, "%s [-p pidfile] mountpoint\n", me); + fprintf(stderr, "lxcfs [-p pidfile] mountpoint\n"); fprintf(stderr, " Default pidfile is %s/lxcfs.pid\n", RUNTIME_PATH); - fprintf(stderr, "%s -h\n", me); + fprintf(stderr, "lxcfs -h\n"); exit(1); } @@ -777,7 +802,7 @@ fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (fd == -1) { - fprintf(stderr, "Could not open pidfile %s: %m", pidfile); + fprintf(stderr, "Could not open pidfile %s: %m\n", pidfile); return -1; } @@ -838,7 +863,7 @@ exit(EXIT_SUCCESS); } if (argc != 2 || is_help(argv[1])) - usage(argv[0]); + usage(); do_reload(); if (signal(SIGUSR1, reload_handler) == SIG_ERR) { diff -Nru lxcfs-2.0.3/Makefile.am lxcfs-2.0.4/Makefile.am --- lxcfs-2.0.3/Makefile.am 2016-08-16 02:36:32.000000000 +0000 +++ lxcfs-2.0.4/Makefile.am 2016-10-05 09:43:15.000000000 +0000 @@ -9,15 +9,15 @@ AM_LDFLAGS = $(FUSE_LIBS) -pthread #AM_CFLAGS += -DDEBUG -AM_CFLAGS += -DRUNTIME_PATH=\"$(RUNTIME_PATH)\" +AM_CFLAGS += -DRUNTIME_PATH=\"$(RUNTIME_PATH)\" liblxcfs_la_SOURCES = bindings.c cpuset.c bindings.h liblxcfs_la_CFLAGS = $(AM_CFLAGS) -liblxcfs_la_LDFLAGS = $(AM_CFLAGS) -shared +liblxcfs_la_LDFLAGS = $(AM_CFLAGS) -module -avoid-version -shared liblxcfstest_la_SOURCES = bindings.c cpuset.c bindings.h liblxcfstest_la_CFLAGS = $(AM_CFLAGS) -DRELOADTEST -liblxcfstest_la_LDFLAGS = $(AM_CFLAGS) -shared +liblxcfstest_la_LDFLAGS = $(AM_CFLAGS) -module -avoid-version -shared noinst_HEADERS = bindings.h @@ -26,7 +26,7 @@ EXTRA_LTLIBRARIES = liblxcfstest.la lxcfs_SOURCES = lxcfs.c -lxcfs_LDADD = liblxcfs.la -ldl +lxcfs_LDADD = -ldl lxcfs_CFLAGS = $(AM_CFLAGS) lxcfs_LDFLAGS = $(AM_LDFLAGS) bin_PROGRAMS = lxcfs diff -Nru lxcfs-2.0.3/Makefile.in lxcfs-2.0.4/Makefile.in --- lxcfs-2.0.3/Makefile.in 2016-08-16 02:36:38.000000000 +0000 +++ lxcfs-2.0.4/Makefile.in 2016-10-05 09:43:22.000000000 +0000 @@ -166,7 +166,7 @@ PROGRAMS = $(bin_PROGRAMS) am_lxcfs_OBJECTS = lxcfs-lxcfs.$(OBJEXT) lxcfs_OBJECTS = $(am_lxcfs_OBJECTS) -lxcfs_DEPENDENCIES = liblxcfs.la +lxcfs_DEPENDENCIES = lxcfs_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(lxcfs_CFLAGS) $(CFLAGS) \ $(lxcfs_LDFLAGS) $(LDFLAGS) -o $@ @@ -439,16 +439,16 @@ AM_LDFLAGS = $(FUSE_LIBS) -pthread liblxcfs_la_SOURCES = bindings.c cpuset.c bindings.h liblxcfs_la_CFLAGS = $(AM_CFLAGS) -liblxcfs_la_LDFLAGS = $(AM_CFLAGS) -shared +liblxcfs_la_LDFLAGS = $(AM_CFLAGS) -module -avoid-version -shared liblxcfstest_la_SOURCES = bindings.c cpuset.c bindings.h liblxcfstest_la_CFLAGS = $(AM_CFLAGS) -DRELOADTEST -liblxcfstest_la_LDFLAGS = $(AM_CFLAGS) -shared +liblxcfstest_la_LDFLAGS = $(AM_CFLAGS) -module -avoid-version -shared noinst_HEADERS = bindings.h sodir = $(libdir) lib_LTLIBRARIES = liblxcfs.la EXTRA_LTLIBRARIES = liblxcfstest.la lxcfs_SOURCES = lxcfs.c -lxcfs_LDADD = liblxcfs.la -ldl +lxcfs_LDADD = -ldl lxcfs_CFLAGS = $(AM_CFLAGS) lxcfs_LDFLAGS = $(AM_LDFLAGS) EXTRA_DIST = \ diff -Nru lxcfs-2.0.3/pam/pam_cgfs.c lxcfs-2.0.4/pam/pam_cgfs.c --- lxcfs-2.0.3/pam/pam_cgfs.c 2016-08-16 02:36:32.000000000 +0000 +++ lxcfs-2.0.4/pam/pam_cgfs.c 2016-10-05 09:43:15.000000000 +0000 @@ -585,7 +585,7 @@ #if DEBUG fprintf(stderr, "%s existed\n", path); #endif - return true; + return false; } bool pass = mkdir_p(c->mount_path, path); @@ -794,16 +794,16 @@ return PAM_SESSION_ERR; } + existed = false; if (!cgfs_create(cg, uid, gid, &existed)) { + if (existed) { + idx++; + continue; + } mysyslog(LOG_ERR, "Failed to create a cgroup for user %s\n", user); return PAM_SESSION_ERR; } - if (existed == 1) { - idx++; - continue; - } - if (!cgfs_enter(cg, false)) { mysyslog(LOG_ERR, "Failed to enter user cgroup %s for user %s\n", cg, user); return PAM_SESSION_ERR; diff -Nru lxcfs-2.0.3/tests/test_reload.sh lxcfs-2.0.4/tests/test_reload.sh --- lxcfs-2.0.3/tests/test_reload.sh 2016-08-16 02:36:32.000000000 +0000 +++ lxcfs-2.0.4/tests/test_reload.sh 2016-10-05 09:43:15.000000000 +0000 @@ -26,7 +26,7 @@ umount -l ${testdir} fi rm -rf ${testdir} ${installdir} - rm -f iwashere + rm -f /tmp/lxcfs-iwashere rm -f ${pidfile} if [ ${FAILED} -eq 1 ]; then echo "liblxcfs.so reload test FAILED" @@ -50,9 +50,9 @@ count=$((count+1)) done -rm -f iwashere +rm -f /tmp/lxcfs-iwashere cat ${testdir}/proc/uptime -[ ! -f iwashere ] +[ ! -f /tmp/lxcfs-iwashere ] ( cd ${topdir}; make liblxcfstest.la @@ -65,5 +65,5 @@ kill -USR1 ${lxcfspid} cat ${testdir}/proc/uptime -[ -f iwashere ] +[ -f /tmp/lxcfs-iwashere ] FAILED=0