From d41f484a463274ac3351cdbaeda9042628c833e2 Mon Sep 17 00:00:00 2001 From: Yu-Hsi Chiang Date: Tue, 1 Sep 2015 14:57:49 +0800 Subject: [PATCH 1/9] Use a daemon to find nacl_helper Run a daemon that handles all the requests of finding nacl_helper, and then pass the share memory fd to client using unix socket. --- host-bin/enter-chroot | 2 + src/fbserver.c | 86 +++++++++++++------ src/findnacld.c | 189 ++++++++++++++++++++++++++++++++++++++++++ targets/xiwi | 4 +- 4 files changed, 251 insertions(+), 30 deletions(-) create mode 100644 src/findnacld.c diff --git a/host-bin/enter-chroot b/host-bin/enter-chroot index 0d735aa35..da256c8cf 100755 --- a/host-bin/enter-chroot +++ b/host-bin/enter-chroot @@ -667,6 +667,8 @@ if [ ! "$NOLOGIN" = 1 ] && grep -q '^root:' "$passwd" 2>/dev/null; then ) &" addtrap "(echo $$ >> '$CROUTONLOCKDIR/frecon') & :" fi + + chrootcmd "/usr/local/bin/croutonfindnacld >/dev/null 2>&1 #include #include +#include + +const char *SOCKET_PATH = "/var/run/crouton-ext/socket"; /* X11-related variables */ static Display *dpy; @@ -241,6 +244,38 @@ void close_mmap(struct cache_entry* entry) { entry->map = NULL; } +int recv_pid_fd(int conn, long *pid) +{ + int fd = -1; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsg; + char buf[CMSG_SPACE(sizeof(int))]; + + memset(&msg, 0, sizeof(struct msghdr)); + memset(buf, 0, CMSG_SPACE(sizeof(int))); + + iov.iov_base = pid; + iov.iov_len = sizeof(pid); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = buf; + msg.msg_controllen = CMSG_SPACE(sizeof(int)); + + if (recvmsg(conn, &msg, 0) < 0) { + syserror("Cannot get response from findnacl daemon."); + return -1; + } + + cmsg = CMSG_FIRSTHDR(&msg); + if (cmsg) { + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { + fd = *((int *)CMSG_DATA(cmsg)); + } + } + return fd; +} + /* Finds NaCl/Chromium shm memory using external handler. * Reply must be in the form PID:file */ struct cache_entry* find_shm(uint64_t paddr, uint64_t sig, size_t length) { @@ -283,47 +318,44 @@ struct cache_entry* find_shm(uint64_t paddr, uint64_t sig, size_t length) { p += c; } - char* cmd = "croutonfindnacl"; - char* args[] = {cmd, arg1, arg2, NULL}; - char buffer[256]; - log(2, "Running %s %s %s", cmd, arg1, arg2); - c = popen2(cmd, args, NULL, 0, buffer, sizeof(buffer)); - if (c <= 0) { - error("Error running helper."); - return NULL; - } - buffer[c < sizeof(buffer) ? c : (sizeof(buffer)-1)] = 0; - log(2, "Result: %s", buffer); + int sock; + + sock = socket(AF_UNIX, SOCK_STREAM, 0); + struct sockaddr_un addr; + + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, SOCKET_PATH); - /* Parse PID:file output */ - char* cut = strchr(buffer, ':'); - if (!cut) { - error("No ':' in helper reply: %s.", cut); + if (connect(sock, (struct sockaddr *)&addr, offsetof(struct sockaddr_un, sun_path) + strlen(SOCKET_PATH) + 1)) { + syserror("Cannot connect to findnacl daemon."); return NULL; } - *cut = 0; - char* endptr; - long pid = strtol(buffer, &endptr, 10); - if(buffer == endptr || *endptr != '\0') { - error("Invalid pid: %s", buffer); + char args[70]; + c = snprintf(args, sizeof(args), "%s %s", arg1, arg2); + trueorabort(c > 0, "snprintf"); + + if (write(sock, args, strlen(args)) < 0) { + syserror("Cannot send arguments."); + close(sock); return NULL; - } - char* file = cut+1; - log(2, "PID:%ld, FILE:%s", pid, file); + } - entry->paddr = paddr; - entry->fd = open(file, O_RDWR); + long pid; + entry->fd = recv_pid_fd(sock, &pid); if (entry->fd < 0) { - error("Cannot open file %s\n", file); + error("Cannot open nacl file."); return NULL; } + close(sock); + + entry->paddr = paddr; entry->length = length; entry->map = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, entry->fd, 0); if (!entry->map) { - error("Cannot mmap %s\n", file); + error("Cannot mmap."); close(entry->fd); return NULL; } diff --git a/src/findnacld.c b/src/findnacld.c new file mode 100644 index 000000000..9296fcf5b --- /dev/null +++ b/src/findnacld.c @@ -0,0 +1,189 @@ +#include "websocket.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_EVENTS 100 + +const char *SOCKET_DIR = "/var/run/crouton-ext"; +const char *SOCKET_PATH = "/var/run/crouton-ext/socket"; + +int send_pid_fd(int conn, long pid, int fd) +{ + struct msghdr msg = {0}; + struct cmsghdr *cmsg; + struct iovec iov; + char buf[CMSG_SPACE(sizeof(int))]; /* ancillary data buffer */ + + iov.iov_base = &pid; + iov.iov_len = sizeof(pid); + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + if (fd > 0) { + msg.msg_control = buf; + msg.msg_controllen = CMSG_SPACE(sizeof(int)); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + + *((int *)CMSG_DATA(cmsg)) = fd; + } else { + msg.msg_control = NULL; + msg.msg_controllen = 0; + } + + return sendmsg(conn, &msg, 0); +} + + +int find_nacl(int conn) +{ + char argbuf[70], outbuf[256]; + char* cut; + int idx = 0, c, len; + + if ((len = read(conn, argbuf, 64)) < 0) { + syserror("Failed to read arguments"); + return -1; + } + argbuf[len] = 0; + + cut = strchr(argbuf, ' '); + if (!cut) { + error("No ' ' in findnacl arguments: %s.", argbuf); + return -1; + } + *cut = 0; + + char *cmd = "croutonfindnacl"; + char* args[] = {cmd, argbuf, cut + 1, NULL}; + + c = popen2(cmd, args, NULL, 0, outbuf, sizeof(outbuf)); + if (c <= 0) { + error("Error running helper"); + return -1; + } + outbuf[c < sizeof(outbuf) ? c : (sizeof(outbuf)-1)] = 0; + + /* Parse PID:file output */ + cut = strchr(outbuf, ':'); + if (!cut) { + error("No ':' in helper reply: %s.", outbuf); + return -1; + } + *cut = 0; + + char* endptr; + long pid = strtol(outbuf, &endptr, 10); + if(outbuf == endptr || *endptr != '\0') { + error("Invalid pid: %s", outbuf); + return -1; + } + + char* file = cut+1; + int ret = 0; + int fd = -1; + if (pid > 0 && (fd = open(file, O_RDWR)) < 0) { + syserror("Cannot open file %s", file); + } + + if (send_pid_fd(conn, pid, fd) < 0) { + syserror("FD-passing failed."); + ret = 1; + } + + close(fd); + return ret; +} + +int main() +{ + int sock, conn, n, i; + int epollfd; + struct sockaddr_un addr; + struct epoll_event ev, events[MAX_EVENTS]; + char args[64]; + + if (setegid(1000)) { + syserror("Cannot set gid to 1000"); + return -1; + } + if (mkdir(SOCKET_DIR)) { + if (errno != EEXIST) { + syserror("Cannot create %s", SOCKET_DIR); + return -1; + } + } + if (chmod(SOCKET_DIR, 0770)) { + syserror("Failed to change permission of %s.", SOCKET_DIR); + return -1; + } + + if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + syserror("Failed to create socket."); + return -1; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, SOCKET_PATH); + + if (bind(sock, (struct sockaddr *)&addr, offsetof(struct sockaddr_un, sun_path) + strlen(SOCKET_PATH) + 1)) { + syserror("Failed to bind address: %s.", SOCKET_PATH); + return -1; + } + if (chmod(SOCKET_PATH, 0770) < 0) { + syserror("Failed to change permission of %s.", SOCKET_PATH); + return -1; + } + + if (listen(sock, 1024) < 0) { + syserror("Failed to listen on %s.", SOCKET_PATH); + return -1; + } + + + if ((epollfd = epoll_create1(0)) < 0) { + syserror("Failed to create epoll instance."); + return -1; + } + + ev.events = POLLIN; + ev.data.fd = sock; + if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sock, &ev) < 0) { + syserror("Failed to add new poll event."); + return -1; + } + + for (;;) { + n = epoll_wait(epollfd, events, MAX_EVENTS, -1); + + for (i = 0; i < n; i++) { + if (events[i].data.fd == sock) { + conn = accept(sock, NULL, 0); + if (conn < 0) { + syserror("Connection error."); + } + ev.events = EPOLLIN; + ev.data.fd = conn; + if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn, &ev) < 0) { + syserror("Failed to add new poll event."); + } + } + else { + find_nacl(events[i].data.fd); + close(events[i].data.fd); + } + } + } + + return 0; +} diff --git a/targets/xiwi b/targets/xiwi index 0fd154d2a..5de3544a2 100644 --- a/targets/xiwi +++ b/targets/xiwi @@ -34,9 +34,7 @@ install --minimal i3 # Compile croutonfbserver compile fbserver '-lX11 -lXfixes -lXdamage -lXext -lXtst' \ libx11-dev libxfixes-dev libxdamage-dev libxext-dev libxtst-dev - -# Make croutonfbserver setuid root. See issue #1411; this is way insecure -chmod u+s /usr/local/bin/croutonfbserver +compile findnacld '' ln -sf /etc/crouton/xorg-dummy.conf /etc/X11/ From 1ca79e86d88432a2f6f2ad31f3acb38849c77ee4 Mon Sep 17 00:00:00 2001 From: Yu-Hsi Chiang Date: Wed, 2 Sep 2015 14:13:23 +0800 Subject: [PATCH 2/9] Fixes for review comments --- src/fbserver.c | 34 +++++++++------- src/findnacld.c | 100 +++++++++++++++++++++++++----------------------- 2 files changed, 72 insertions(+), 62 deletions(-) diff --git a/src/fbserver.c b/src/fbserver.c index ec0268b9e..9a1f8b5e0 100644 --- a/src/fbserver.c +++ b/src/fbserver.c @@ -244,18 +244,20 @@ void close_mmap(struct cache_entry* entry) { entry->map = NULL; } -int recv_pid_fd(int conn, long *pid) +/* Read the pid of nacl_helper and get shm from findnacl daemon. + * The socket fd is passed in and fd of nacl_helper is returned..*/ +int recv_pid_fd(int conn) { int fd = -1; - struct msghdr msg; + struct msghdr msg = { 0 }; struct iovec iov; struct cmsghdr *cmsg; + long pid; char buf[CMSG_SPACE(sizeof(int))]; - memset(&msg, 0, sizeof(struct msghdr)); - memset(buf, 0, CMSG_SPACE(sizeof(int))); + memset(buf, 0, sizeof(buf)); - iov.iov_base = pid; + iov.iov_base = &pid; iov.iov_len = sizeof(pid); msg.msg_iov = &iov; msg.msg_iovlen = 1; @@ -271,7 +273,11 @@ int recv_pid_fd(int conn, long *pid) if (cmsg) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { fd = *((int *)CMSG_DATA(cmsg)); + } else { + error("No fd is passed from findnacl daemon."); } + } else { + error("No fd is passed from findnacl daemon."); } return fd; } @@ -319,30 +325,30 @@ struct cache_entry* find_shm(uint64_t paddr, uint64_t sig, size_t length) { } int sock; - - sock = socket(AF_UNIX, SOCK_STREAM, 0); struct sockaddr_un addr; + sock = socket(AF_UNIX, SOCK_STREAM, 0); addr.sun_family = AF_UNIX; - strcpy(addr.sun_path, SOCKET_PATH); + strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path)); - if (connect(sock, (struct sockaddr *)&addr, offsetof(struct sockaddr_un, sun_path) + strlen(SOCKET_PATH) + 1)) { + if (connect(sock, (struct sockaddr *)&addr, offsetof(struct sockaddr_un, + sun_path) + strlen(SOCKET_PATH) + 1)) { syserror("Cannot connect to findnacl daemon."); return NULL; } char args[70]; - c = snprintf(args, sizeof(args), "%s %s", arg1, arg2); - trueorabort(c > 0, "snprintf"); + int sz = sizeof(args); + c = snprintf(args, sz, "%s %s", arg1, arg2); + trueorabort(c > 0 && c < sz, "snprintf"); if (write(sock, args, strlen(args)) < 0) { syserror("Cannot send arguments."); close(sock); return NULL; - } + } - long pid; - entry->fd = recv_pid_fd(sock, &pid); + entry->fd = recv_pid_fd(sock); if (entry->fd < 0) { error("Cannot open nacl file."); return NULL; diff --git a/src/findnacld.c b/src/findnacld.c index 9296fcf5b..f6a307b98 100644 --- a/src/findnacld.c +++ b/src/findnacld.c @@ -1,3 +1,7 @@ +/* Copyright (c) 2015 The crouton Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ #include "websocket.h" #include #include @@ -6,6 +10,8 @@ #include #include #include +#include +#include #include #define MAX_EVENTS 100 @@ -20,6 +26,9 @@ int send_pid_fd(int conn, long pid, int fd) struct iovec iov; char buf[CMSG_SPACE(sizeof(int))]; /* ancillary data buffer */ + /* It is not necessary to sent the pid. However, to pass fd using sendmsg, + * at least 1 byte of data must be sent. + */ iov.iov_base = &pid; iov.iov_len = sizeof(pid); @@ -50,7 +59,7 @@ int find_nacl(int conn) char* cut; int idx = 0, c, len; - if ((len = read(conn, argbuf, 64)) < 0) { + if ((len = read(conn, argbuf, sizeof(argbuf)-1)) < 0) { syserror("Failed to read arguments"); return -1; } @@ -66,12 +75,12 @@ int find_nacl(int conn) char *cmd = "croutonfindnacl"; char* args[] = {cmd, argbuf, cut + 1, NULL}; - c = popen2(cmd, args, NULL, 0, outbuf, sizeof(outbuf)); + c = popen2(cmd, args, NULL, 0, outbuf, sizeof(outbuf)-1); if (c <= 0) { error("Error running helper"); return -1; } - outbuf[c < sizeof(outbuf) ? c : (sizeof(outbuf)-1)] = 0; + outbuf[c] = 0; /* Parse PID:file output */ cut = strchr(outbuf, ':'); @@ -91,13 +100,14 @@ int find_nacl(int conn) char* file = cut+1; int ret = 0; int fd = -1; - if (pid > 0 && (fd = open(file, O_RDWR)) < 0) { - syserror("Cannot open file %s", file); + if (pid > 0) { + if ((fd = open(file, O_RDWR)) < 0) + syserror("Cannot open file %s", file); } if (send_pid_fd(conn, pid, fd) < 0) { syserror("FD-passing failed."); - ret = 1; + ret = -1; } close(fd); @@ -106,26 +116,29 @@ int find_nacl(int conn) int main() { - int sock, conn, n, i; - int epollfd; + int sock, conn, n, i, fd; + int maxfd; struct sockaddr_un addr; struct epoll_event ev, events[MAX_EVENTS]; char args[64]; - - if (setegid(1000)) { - syserror("Cannot set gid to 1000"); + fd_set readset, recvset; + + /* Set egid to be 27 (video) and change the umask to 007, + * so that normal user can also access the socket if they + * are in video group. + */ + if (setegid(27) < 0) { + syserror("Cannot set gid to 27"); return -1; } - if (mkdir(SOCKET_DIR)) { + umask(S_IROTH | S_IWOTH | S_IXOTH); + + if (mkdir(SOCKET_DIR, 0770) < 0) { if (errno != EEXIST) { syserror("Cannot create %s", SOCKET_DIR); return -1; } } - if (chmod(SOCKET_DIR, 0770)) { - syserror("Failed to change permission of %s.", SOCKET_DIR); - return -1; - } if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { syserror("Failed to create socket."); @@ -134,54 +147,45 @@ int main() memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; - strcpy(addr.sun_path, SOCKET_PATH); + strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path)); - if (bind(sock, (struct sockaddr *)&addr, offsetof(struct sockaddr_un, sun_path) + strlen(SOCKET_PATH) + 1)) { + if (bind(sock, (struct sockaddr *)&addr, offsetof(struct sockaddr_un, + sun_path) + strlen(SOCKET_PATH) + 1) < 0) { syserror("Failed to bind address: %s.", SOCKET_PATH); return -1; } - if (chmod(SOCKET_PATH, 0770) < 0) { - syserror("Failed to change permission of %s.", SOCKET_PATH); - return -1; - } if (listen(sock, 1024) < 0) { syserror("Failed to listen on %s.", SOCKET_PATH); return -1; } + FD_ZERO(&readset); + FD_SET(sock, &readset); - if ((epollfd = epoll_create1(0)) < 0) { - syserror("Failed to create epoll instance."); - return -1; - } - - ev.events = POLLIN; - ev.data.fd = sock; - if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sock, &ev) < 0) { - syserror("Failed to add new poll event."); - return -1; - } + maxfd = sock; for (;;) { - n = epoll_wait(epollfd, events, MAX_EVENTS, -1); - - for (i = 0; i < n; i++) { - if (events[i].data.fd == sock) { - conn = accept(sock, NULL, 0); - if (conn < 0) { - syserror("Connection error."); + memcpy(&recvset, &readset, sizeof(recvset)); + n = select(maxfd + 1, &recvset, NULL, NULL, NULL); + + for (fd = 0; fd <= maxfd; fd++) { + if (FD_ISSET(fd, &recvset)) { + if (fd == sock) { + conn = accept(sock, NULL, 0); + if (conn < 0) { + syserror("Connection error."); + } + if (conn > maxfd) + maxfd = conn; + FD_SET(conn, &readset); } - ev.events = EPOLLIN; - ev.data.fd = conn; - if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn, &ev) < 0) { - syserror("Failed to add new poll event."); + else { + find_nacl(fd); + close(fd); + FD_CLR(fd, &readset); } } - else { - find_nacl(events[i].data.fd); - close(events[i].data.fd); - } } } From 520c7f74fe85a29e5980a73bc6f7c8ef4a32f699 Mon Sep 17 00:00:00 2001 From: Yu-Hsi Chiang Date: Thu, 10 Sep 2015 12:02:24 +0800 Subject: [PATCH 3/9] Fixes for review comments --- src/fbserver.c | 8 +++----- src/findnacld.c | 12 ++++++------ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/fbserver.c b/src/fbserver.c index 9a1f8b5e0..9f4877bc7 100644 --- a/src/fbserver.c +++ b/src/fbserver.c @@ -331,16 +331,14 @@ struct cache_entry* find_shm(uint64_t paddr, uint64_t sig, size_t length) { addr.sun_family = AF_UNIX; strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path)); - if (connect(sock, (struct sockaddr *)&addr, offsetof(struct sockaddr_un, - sun_path) + strlen(SOCKET_PATH) + 1)) { + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { syserror("Cannot connect to findnacl daemon."); return NULL; } char args[70]; - int sz = sizeof(args); - c = snprintf(args, sz, "%s %s", arg1, arg2); - trueorabort(c > 0 && c < sz, "snprintf"); + c = snprintf(args, sizeof(args), "%s %s", arg1, arg2); + trueorabort(c > 0 && c < sizeof(args), "snprintf"); if (write(sock, args, strlen(args)) < 0) { syserror("Cannot send arguments."); diff --git a/src/findnacld.c b/src/findnacld.c index f6a307b98..185559edf 100644 --- a/src/findnacld.c +++ b/src/findnacld.c @@ -36,7 +36,7 @@ int send_pid_fd(int conn, long pid, int fd) msg.msg_iovlen = 1; if (fd > 0) { msg.msg_control = buf; - msg.msg_controllen = CMSG_SPACE(sizeof(int)); + msg.msg_controllen = sizeof(buf); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; @@ -57,13 +57,13 @@ int find_nacl(int conn) { char argbuf[70], outbuf[256]; char* cut; - int idx = 0, c, len; + int idx = 0, c; - if ((len = read(conn, argbuf, sizeof(argbuf)-1)) < 0) { + if ((c = read(conn, argbuf, sizeof(argbuf)-1)) < 0) { syserror("Failed to read arguments"); return -1; } - argbuf[len] = 0; + argbuf[c] = 0; cut = strchr(argbuf, ' '); if (!cut) { @@ -149,8 +149,7 @@ int main() addr.sun_family = AF_UNIX; strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path)); - if (bind(sock, (struct sockaddr *)&addr, offsetof(struct sockaddr_un, - sun_path) + strlen(SOCKET_PATH) + 1) < 0) { + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { syserror("Failed to bind address: %s.", SOCKET_PATH); return -1; } @@ -175,6 +174,7 @@ int main() conn = accept(sock, NULL, 0); if (conn < 0) { syserror("Connection error."); + continue; } if (conn > maxfd) maxfd = conn; From 5810a19adcd9da21fdbedbf73d3c8137198a4748 Mon Sep 17 00:00:00 2001 From: Yu-Hsi Chiang Date: Wed, 26 Aug 2015 12:07:47 +0800 Subject: [PATCH 4/9] Detect whether we are running in containers and act responsively. Detect whether we are running in containers by inspecting the environment variable $container. If we are in container, we are not able to remount or change the config in /proc/sys/*, so just skip them. We also have to patch debootstrap since we are not able to mknod and we don't want to start services in containers. --- host-bin/enter-chroot | 51 ++++++++++++++++++++++++++++++++------ host-bin/mount-chroot | 5 +++- host-bin/unmount-chroot | 9 +++++-- installer/functions | 4 ++- installer/ubuntu/bootstrap | 9 +++++++ installer/ubuntu/prepare | 28 +++++++++++++++++++-- 6 files changed, 92 insertions(+), 14 deletions(-) diff --git a/host-bin/enter-chroot b/host-bin/enter-chroot index da256c8cf..e7cc89c47 100755 --- a/host-bin/enter-chroot +++ b/host-bin/enter-chroot @@ -47,7 +47,7 @@ chrootcmd() { # env may be overridden when running in the background; don't let it fork. local ret=0 oldtrap="$TRAP" TRAP='' - env -i chroot "$CHROOT" su -s '/bin/sh' -c "$*" - root || ret=$? + env -i container="$container" chroot "$CHROOT" su -s '/bin/sh' -c "$*" - root || ret=$? local pid="$!" # $pid might not be set if env has not been redefined yet if [ -n "$BACKGROUND" ] && [ -n "$pid" ]; then @@ -338,6 +338,18 @@ tmpfsmount() { mount -i -t tmpfs -o "rw${2:+,}$2" tmpfs "$target" } +# Bind-mounts /dev/$1 into $CHROOT/dev/$1 if it is not already mounted +devmknod() { + local target="`fixabslinks "/dev/$1"`" + if mountpoint -q "$target"; then + return 0; + fi + if [ ! -f "$target" ]; then + touch $target + fi + mount --bind "/dev/$1" "$target" +} + # If /var/run isn't mounted, we know the chroot hasn't been started yet. if mountpoint -q "`fixabslinks '/var/run'`"; then firstrun='' @@ -345,16 +357,35 @@ else firstrun='y' fi -bindmount /dev +if [ -n "$container" ]; then + devmknod null + devmknod full + devmknod zero + devmknod tty + devmknod random + devmknod urandom + if [ ! -d "$CHROOT/dev/pts" ]; then + mkdir -p "$CHROOT/dev/pts" + fi + mount -t devpts devpts -o newinstance,ptmxmode=0666,mode=0620,gid=5 "$CHROOT/dev/pts" + ln -sf pts/ptmx "$CHROOT/dev/ptmx" +else + bindmount /dev +fi bindmount /dev/pts bindmount /dev/shm -bindmount /tmp /tmp exec +if [ -n "$container" ]; then + bindmount /tmp /tmp +else + bindmount /tmp /tmp exec +fi bindmount /proc tmpfsmount /var/run 'noexec,nosuid,mode=0755,size=10%' tmpfsmount /var/run/lock 'noexec,nosuid,nodev,size=5120k' bindmount /var/run/dbus /var/host/dbus bindmount /var/run/shill /var/host/shill bindmount /var/lib/timezone /var/host/timezone +bindmount /var/run/crouton-ext for m in /lib/modules/*; do if [ -d "$m" ]; then bindmount '-o ro' "$m" @@ -631,7 +662,7 @@ if [ ! "$NOLOGIN" = 1 ] && grep -q '^root:' "$passwd" 2>/dev/null; then # Launch systemd-logind if available and not already running # Whitelisted for saucy and trusty systemd_dir="`fixabslinks '/run/systemd'`" - if [ -x "$CHROOT/lib/systemd/systemd-logind" ] && \ + if [ -z "$container" ] && [ -x "$CHROOT/lib/systemd/systemd-logind" ] && \ [ ! -d "$systemd_dir" ] && \ [ "$CHROOTRELEASE" = 'saucy' -o "$CHROOTRELEASE" = 'trusty' ]; then # Every piece of systemd code ever assumes that this directory exists @@ -668,12 +699,16 @@ if [ ! "$NOLOGIN" = 1 ] && grep -q '^root:' "$passwd" 2>/dev/null; then addtrap "(echo $$ >> '$CROUTONLOCKDIR/frecon') & :" fi - chrootcmd "/usr/local/bin/croutonfindnacld >/dev/null 2>&1 /dev/null 2>&1 /dev/null; do +' -n 1 umount "$arg" 2>/dev/null; do if [ "$ntries" -eq "$TRIES" ]; then # Send signal to all processes running under the chroot # ...but confirm first. @@ -321,7 +326,7 @@ done # Re-disable USB persistence (the Chromium OS default) if we no longer # have chroots running with a root in removable media -if checkusage "$ROOT/media"; then +if [ -z "$container" ] && checkusage "$ROOT/media"; then for usbp in /sys/bus/usb/devices/*/power/persist; do if [ -e "$usbp" ]; then echo 0 > "$usbp" diff --git a/installer/functions b/installer/functions index 14451973d..f903078f5 100644 --- a/installer/functions +++ b/installer/functions @@ -156,7 +156,9 @@ release() { # sure the kernel does not panic (this is the default configuration of a vanilla # kernel). See crbug.com/260955 for details. disablehungtask() { - echo 0 > /proc/sys/kernel/hung_task_panic + if [ -z "$container" ]; then + echo 0 > /proc/sys/kernel/hung_task_panic + fi } # Run an awk program, without buffering its output. diff --git a/installer/ubuntu/bootstrap b/installer/ubuntu/bootstrap index f826dfdb4..fb8c405f9 100644 --- a/installer/ubuntu/bootstrap +++ b/installer/ubuntu/bootstrap @@ -42,6 +42,7 @@ if awk ' sub(/continue 2; fi/, "failed=y") t=1 } + /if \[ -d \"\$TARGET\/sys\" \] && \\/ { sub(/if/, "if [ -z \"$container\" ] \&\&") } 1 END { if (t != 4) exit 1 } ' "$tmp/functions" > "$tmp/functions.new"; then @@ -66,6 +67,14 @@ if [ ! -f "$tmp/scripts/$RELEASE" ]; then ln -s "$tmp/scripts/$BOOTSTRAP_RELEASE" "$tmp/scripts/$RELEASE" fi +# We are not able to mknod in containers, so make a fake mknod for debootstrap. +if [ -n "$container" ]; then + mkdir "$tmp/bin" + echo "touch \$1" > "$tmp/bin/mknod" + chmod +x "$tmp/bin/mknod" + newpath="$tmp/bin:$newpath" +fi + # Grab the release and drop it into the subdirectory echo 'Downloading bootstrap files...' 1>&2 PATH="$newpath" DEBOOTSTRAP_DIR="$tmp" $FAKEROOT \ diff --git a/installer/ubuntu/prepare b/installer/ubuntu/prepare index 5c457d606..b0d197cfb 100644 --- a/installer/ubuntu/prepare +++ b/installer/ubuntu/prepare @@ -223,11 +223,35 @@ if [ -r /debootstrap ]; then # We request a re-mount after bootstrapping, so these mounts will be fixed. # We also can't detect the mounts properly due to the chroot, so we have to # recursively find mountpoints under /sys, and hardcode /var umounts. - find /sys/* -maxdepth 2 -depth -type d \ - -exec mountpoint -q {} \; -exec umount {} \; + # However, if we are in container, debootstrap cannot mount /sys, so don't + # unmount it. + if [ -z "$container" ]; then + find /sys/* -maxdepth 2 -depth -type d \ + -exec mountpoint -q {} \; -exec umount {} \; + else + umount '/var/run/crouton-ext' + fi umount '/var/run/lock' '/var/run' + # Create a fake mknod if we are in container. + if [ -n "$container" ]; then + cp /bin/mknod /bin/mknod.old + echo "touch \$1" > /bin/mknod + fi # Start the bootstrap /debootstrap/debootstrap --second-stage + if [ -n "$container" ]; then + # Mark makedev as installed. + awk ' + BEGIN { matched = 0 } + /^Package: makedev$/ { matched = 1 } + matched == 1 && /^Status:/ { sub($4, "installed"); matched = 0 } + 1' /var/lib/dpkg/status > /var/lib/dpkg/status.new + mv -f /var/lib/dpkg/status.new /var/lib/dpkg/status + + # Deny all services to start in container. + echo exit 101 > /usr/sbin/policy-rc.d + chmod +x /usr/sbin/policy-rc.d + fi # Clean contents of /var/run (since we'll always be mounting over it). rm -rf --one-file-system /var/run/* # Request a script restart to refresh the mount environment From f9cc65144b33476cbf2372ab488c91e2b23d835b Mon Sep 17 00:00:00 2001 From: Yu-Hsi Chiang Date: Thu, 3 Sep 2015 15:54:39 +0800 Subject: [PATCH 5/9] Remove environment variable $container Instead of inspecting the environment variable $container, check whether we are able to do some operations and act responsively. --- host-bin/enter-chroot | 86 ++++++++++++++++++++++---------------- host-bin/mount-chroot | 6 ++- host-bin/unmount-chroot | 18 ++++---- installer/functions | 41 ++++++++++++++++-- installer/ubuntu/bootstrap | 8 ++-- installer/ubuntu/prepare | 24 ++++------- 6 files changed, 114 insertions(+), 69 deletions(-) diff --git a/host-bin/enter-chroot b/host-bin/enter-chroot index e7cc89c47..08d52542c 100755 --- a/host-bin/enter-chroot +++ b/host-bin/enter-chroot @@ -47,7 +47,7 @@ chrootcmd() { # env may be overridden when running in the background; don't let it fork. local ret=0 oldtrap="$TRAP" TRAP='' - env -i container="$container" chroot "$CHROOT" su -s '/bin/sh' -c "$*" - root || ret=$? + env -i chroot "$CHROOT" su -s '/bin/sh' -c "$*" - root || ret=$? local pid="$!" # $pid might not be set if env has not been redefined yet if [ -n "$BACKGROUND" ] && [ -n "$pid" ]; then @@ -323,7 +323,32 @@ bindmount() { fi mkdir -p "$target" mount --bind $bindopts "$1" "$target" - if [ -n "$3" ]; then + # Determine whether we really need to remount or not by checking the existing + # mount options. We are doing this since remount is not allowed in containers. + if [ -n "$3" ] && ! checkmountopt "$target" "$3"; then + mount -i -o "remount,$3" "$target" + fi +} + +# Recursively bind-mounts $1 into $CHROOT/${2:-"$1"} if $2 is not already mounted +# If $3 is specified, remounts with the specified options. +# If $1 starts with a -, it's considered options to the bind mount, and the rest +# of the parameters are shifted. +rbindmount() { + bindopts='' + if [ ! "${1#"-"}" = "$1" ]; then + bindopts="$1" + shift + fi + local target="`fixabslinks "${2:-"$1"}"`" + if mountpoint -q "$target"; then + return 0 + fi + mkdir -p "$target" + mount --rbind $bindopts "$1" "$target" + # Determine whether we really need to remount or not by checking the existing + # mount options. We are doing this since remount is not allowed in containers. + if [ -n "$3" ] && ! checkmountopt "$target" "$3"; then mount -i -o "remount,$3" "$target" fi } @@ -357,35 +382,18 @@ else firstrun='y' fi -if [ -n "$container" ]; then - devmknod null - devmknod full - devmknod zero - devmknod tty - devmknod random - devmknod urandom - if [ ! -d "$CHROOT/dev/pts" ]; then - mkdir -p "$CHROOT/dev/pts" - fi - mount -t devpts devpts -o newinstance,ptmxmode=0666,mode=0620,gid=5 "$CHROOT/dev/pts" - ln -sf pts/ptmx "$CHROOT/dev/ptmx" -else - bindmount /dev -fi -bindmount /dev/pts -bindmount /dev/shm -if [ -n "$container" ]; then - bindmount /tmp /tmp -else - bindmount /tmp /tmp exec -fi +rbindmount /dev +bindmount /tmp /tmp exec bindmount /proc tmpfsmount /var/run 'noexec,nosuid,mode=0755,size=10%' tmpfsmount /var/run/lock 'noexec,nosuid,nodev,size=5120k' bindmount /var/run/dbus /var/host/dbus bindmount /var/run/shill /var/host/shill bindmount /var/lib/timezone /var/host/timezone -bindmount /var/run/crouton-ext +# If findnacld socket exists, bind-mount it into chroot. +if [ -S "/var/run/crouton-ext/socket" ]; then + bindmount /var/run/crouton-ext +fi for m in /lib/modules/*; do if [ -d "$m" ]; then bindmount '-o ro' "$m" @@ -662,20 +670,25 @@ if [ ! "$NOLOGIN" = 1 ] && grep -q '^root:' "$passwd" 2>/dev/null; then # Launch systemd-logind if available and not already running # Whitelisted for saucy and trusty systemd_dir="`fixabslinks '/run/systemd'`" - if [ -z "$container" ] && [ -x "$CHROOT/lib/systemd/systemd-logind" ] && \ + if [ -x "$CHROOT/lib/systemd/systemd-logind" ] && \ [ ! -d "$systemd_dir" ] && \ [ "$CHROOTRELEASE" = 'saucy' -o "$CHROOTRELEASE" = 'trusty' ]; then # Every piece of systemd code ever assumes that this directory exists mkdir -p "$systemd_dir" # Create systemd cgroup if necessary + start_systemd=true if ! mountpoint -q "$CHROOT/sys/fs/cgroup/systemd"; then - mkdir -p "$CHROOT/sys/fs/cgroup/systemd" - mount -t cgroup -o nosuid,noexec,nodev,none,name=systemd systemd \ - "$CHROOT/sys/fs/cgroup/systemd" + if ! mkdir -p "$CHROOT/sys/fs/cgroup/systemd" || \ + ! mount -t cgroup -o nosuid,noexec,nodev,none,name=systemd systemd \ + "$CHROOT/sys/fs/cgroup/systemd"; then + start_systemd=false + fi + fi + # We cannot create/mount cgroup dirs in containers, so don't start systemd. + if $start_systemd; then + chrootcmd "/lib/systemd/systemd-logind >/dev/null 2>&1 /dev/null 2>&1 /dev/null; then addtrap "(echo $$ >> '$CROUTONLOCKDIR/frecon') & :" fi - # findnacld should have been started outside the container, so we don't need - # to start it again. - if [ -z "$container" ]; then + # If the socket file does not exist, it means findnacld is not started. + if [ ! -S "/var/run/crouton-ext/socket" ]; then chrootcmd "/usr/local/bin/croutonfindnacld >/dev/null 2>&1 &2 fi + # If there is no process running under $CHROOTSRC and we cannot + # unmount, then use lazy unmount. + # FIXME: This is a hack for running in containers, since we cannot + # unmount recursive bindmount in it. + arg='-l' for root in /proc/*/root; do if [ ! -r "$root" ] \ || [ ! "`readlink -f "$root"`" = "$base" ]; then @@ -285,6 +286,7 @@ unmount() { if [ -z "$printonly" ]; then kill "-$SIGNAL" "$pid" 2>/dev/null || true fi + arg='' done # Escalate @@ -326,10 +328,12 @@ done # Re-disable USB persistence (the Chromium OS default) if we no longer # have chroots running with a root in removable media -if [ -z "$container" ] && checkusage "$ROOT/media"; then +if checkusage "$ROOT/media"; then for usbp in /sys/bus/usb/devices/*/power/persist; do if [ -e "$usbp" ]; then - echo 0 > "$usbp" + # Don't fail since we don't have permission to write /sys/* if we are in + # container. + echo 0 > "$usbp" || true fi done fi diff --git a/installer/functions b/installer/functions index f903078f5..0751039ff 100644 --- a/installer/functions +++ b/installer/functions @@ -68,6 +68,41 @@ undotrap() { settrap "$TRAP" } +# Check if we are able to mknod. +capmknod() { + local tmp=`mktemp -d --tmpdir=/tmp 'crouton-mknod.XXX'` + if ! mknod "$tmp/test-mknod" c 0 0; then + return 1 + fi + rm -rf "$tmp" + return 0 +} + +# Check whether $1 is mounted with options $2. +# We check the options of a mount point by inspecting /proc/mounts. +# For options dev, suid and exec, since they will not show up in /proc/mounts, +# we check whether their opposite options (nodev, nosuid, noexec) exists. +checkmountopt() { + local opt + local opts="$2," + while [ -n "$opts" ]; do + opt=${opts%%,*} + opts=${opts#*,} + case $opt in + dev|suid|exec) + if ! awk -v dir="$1" -v opt="no$opt(,|$)" \ + '$2 == dir && $4 ~ opt { exit 1 }' "/proc/mounts"; then + return 1 + fi;; + *) + if ! awk -v dir="$1" -v opt="$opt(,|$)" \ + '$2 == dir && $4 !~ opt { exit 1 }' "/proc/mounts"; then + return 1 + fi;; + esac + done +} + # Works mostly like built-in getopts but silently coalesces positional arguments. # Does not take parameters. Set getopts_string prior to calling. # Sets getopts_var and getopts_arg. @@ -156,9 +191,9 @@ release() { # sure the kernel does not panic (this is the default configuration of a vanilla # kernel). See crbug.com/260955 for details. disablehungtask() { - if [ -z "$container" ]; then - echo 0 > /proc/sys/kernel/hung_task_panic - fi + # Don't fail since we do not have permission to write /proc/sys/* if we are + # in container. + echo 0 > /proc/sys/kernel/hung_task_panic || true } # Run an awk program, without buffering its output. diff --git a/installer/ubuntu/bootstrap b/installer/ubuntu/bootstrap index fb8c405f9..725d8ef88 100644 --- a/installer/ubuntu/bootstrap +++ b/installer/ubuntu/bootstrap @@ -31,7 +31,7 @@ Check your internet connection or proxy settings and try again.' fi fi -# Patch debootstrap so that it retries downloading packages +# Patch debootstrap so that it retries downloading packages and not mounting /sys echo 'Patching debootstrap...' 1>&2 if awk ' t == 3 && /warning RETRY/ { print "sleep 1"; t=4 } @@ -42,7 +42,7 @@ if awk ' sub(/continue 2; fi/, "failed=y") t=1 } - /if \[ -d \"\$TARGET\/sys\" \] && \\/ { sub(/if/, "if [ -z \"$container\" ] \&\&") } + /if \[ -d \"\$TARGET\/sys\" \] && \\/ { sub(/if/, "if false \&\&") } 1 END { if (t != 4) exit 1 } ' "$tmp/functions" > "$tmp/functions.new"; then @@ -67,8 +67,8 @@ if [ ! -f "$tmp/scripts/$RELEASE" ]; then ln -s "$tmp/scripts/$BOOTSTRAP_RELEASE" "$tmp/scripts/$RELEASE" fi -# We are not able to mknod in containers, so make a fake mknod for debootstrap. -if [ -n "$container" ]; then +# Create a fake mknod for debootstrap if we don't have CAP_MKNOD. +if ! capmknod; then mkdir "$tmp/bin" echo "touch \$1" > "$tmp/bin/mknod" chmod +x "$tmp/bin/mknod" diff --git a/installer/ubuntu/prepare b/installer/ubuntu/prepare index b0d197cfb..ceb4e65b5 100644 --- a/installer/ubuntu/prepare +++ b/installer/ubuntu/prepare @@ -219,38 +219,30 @@ export DEBIAN_FRONTEND=noninteractive # Run debootstrap second stage if it hasn't already happened if [ -r /debootstrap ]; then - # Debootstrap doesn't like anything mounted under /sys or /var when it runs + # Debootstrap doesn't like anything mounted under /var when it runs. # We request a re-mount after bootstrapping, so these mounts will be fixed. # We also can't detect the mounts properly due to the chroot, so we have to - # recursively find mountpoints under /sys, and hardcode /var umounts. - # However, if we are in container, debootstrap cannot mount /sys, so don't - # unmount it. - if [ -z "$container" ]; then - find /sys/* -maxdepth 2 -depth -type d \ - -exec mountpoint -q {} \; -exec umount {} \; - else + # hardcode /var umounts. + if mountpoint -q '/var/run/crouton-ext'; then umount '/var/run/crouton-ext' fi umount '/var/run/lock' '/var/run' - # Create a fake mknod if we are in container. - if [ -n "$container" ]; then + # Create a fake mknod for debootstrap if we don't have CAP_MKNOD. + if ! capmknod; then cp /bin/mknod /bin/mknod.old echo "touch \$1" > /bin/mknod fi # Start the bootstrap /debootstrap/debootstrap --second-stage - if [ -n "$container" ]; then - # Mark makedev as installed. + # If we cannot mknod, the installation of makedev will fail, so mark it as + # installed manually. + if ! capmknod; then awk ' BEGIN { matched = 0 } /^Package: makedev$/ { matched = 1 } matched == 1 && /^Status:/ { sub($4, "installed"); matched = 0 } 1' /var/lib/dpkg/status > /var/lib/dpkg/status.new mv -f /var/lib/dpkg/status.new /var/lib/dpkg/status - - # Deny all services to start in container. - echo exit 101 > /usr/sbin/policy-rc.d - chmod +x /usr/sbin/policy-rc.d fi # Clean contents of /var/run (since we'll always be mounting over it). rm -rf --one-file-system /var/run/* From 08a766ddbd6bf8641b6a004fd6d8c20f89be6bb8 Mon Sep 17 00:00:00 2001 From: Yu-Hsi Chiang Date: Tue, 8 Sep 2015 16:38:35 +0800 Subject: [PATCH 6/9] Check whether /sys, /media is a mount point. It is possible that /sys, /media is not mounted in a container, so check it before we bind-mount it into chroot. --- host-bin/enter-chroot | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/host-bin/enter-chroot b/host-bin/enter-chroot index 08d52542c..3670333e9 100755 --- a/host-bin/enter-chroot +++ b/host-bin/enter-chroot @@ -423,8 +423,10 @@ WARNING: CRAS not running in Chromium OS. Audio forwarding will not work." 1>&2 fi # Bind-mount /media, specifically the removable directory +# It is possible that /media is not mounted inside containers,so bind-mount it +# only if /media is a mountpoint. destmedia="`fixabslinks '/var/host/media'`" -if ! mountpoint -q "$destmedia"; then +if mountpoint -q "/media" && ! mountpoint -q "$destmedia"; then mount --make-shared /media mkdir -p "$destmedia" "$CHROOT/media" ln -sf "/var/host/media/removable" "$CHROOT/media/" @@ -562,7 +564,9 @@ if [ -z "$NOLOGIN" -a -f "$shares" ]; then fi # Bind-mount /sys recursively, making it a slave in the chroot -if ! mountpoint -q "$CHROOT/sys"; then +# It is possible that /sys is not mounted inside containers,so bind-mount it +# only if /sys is a mountpoint. +if mountpoint -q "/sys" && ! mountpoint -q "$CHROOT/sys"; then mkdir -p "$CHROOT/sys" mount --make-rshared /sys mount --rbind /sys "$CHROOT/sys" From 06ebe2f3836ba453dd3a59b2ff49b740354035a0 Mon Sep 17 00:00:00 2001 From: Yu-Hsi Chiang Date: Thu, 10 Sep 2015 12:37:31 +0800 Subject: [PATCH 7/9] Fixes for review comments --- installer/functions | 6 ++++-- installer/ubuntu/bootstrap | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/installer/functions b/installer/functions index 0751039ff..d479a2518 100644 --- a/installer/functions +++ b/installer/functions @@ -71,11 +71,12 @@ undotrap() { # Check if we are able to mknod. capmknod() { local tmp=`mktemp -d --tmpdir=/tmp 'crouton-mknod.XXX'` + local ret=0 if ! mknod "$tmp/test-mknod" c 0 0; then - return 1 + ret=1 fi rm -rf "$tmp" - return 0 + return $ret } # Check whether $1 is mounted with options $2. @@ -101,6 +102,7 @@ checkmountopt() { fi;; esac done + return 0 } # Works mostly like built-in getopts but silently coalesces positional arguments. diff --git a/installer/ubuntu/bootstrap b/installer/ubuntu/bootstrap index 725d8ef88..89ce538c8 100644 --- a/installer/ubuntu/bootstrap +++ b/installer/ubuntu/bootstrap @@ -31,7 +31,7 @@ Check your internet connection or proxy settings and try again.' fi fi -# Patch debootstrap so that it retries downloading packages and not mounting /sys +# Patch debootstrap so that it retries downloading packages and does not mount /sys echo 'Patching debootstrap...' 1>&2 if awk ' t == 3 && /warning RETRY/ { print "sleep 1"; t=4 } From 6328778a56800100543df3f8f0e77c4ca444c431 Mon Sep 17 00:00:00 2001 From: Yu-Hsi Chiang Date: Wed, 23 Sep 2015 14:35:49 +0800 Subject: [PATCH 8/9] Mute non-fatal error messages. --- installer/functions | 4 ++-- installer/main.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/installer/functions b/installer/functions index d479a2518..4564b1283 100644 --- a/installer/functions +++ b/installer/functions @@ -72,7 +72,7 @@ undotrap() { capmknod() { local tmp=`mktemp -d --tmpdir=/tmp 'crouton-mknod.XXX'` local ret=0 - if ! mknod "$tmp/test-mknod" c 0 0; then + if ! mknod "$tmp/test-mknod" c 0 0 2>/dev/null; then ret=1 fi rm -rf "$tmp" @@ -195,7 +195,7 @@ release() { disablehungtask() { # Don't fail since we do not have permission to write /proc/sys/* if we are # in container. - echo 0 > /proc/sys/kernel/hung_task_panic || true + echo 0 2>/dev/null > /proc/sys/kernel/hung_task_panic || true } # Run an awk program, without buffering its output. diff --git a/installer/main.sh b/installer/main.sh index 76a5aed03..96d35271a 100755 --- a/installer/main.sh +++ b/installer/main.sh @@ -522,7 +522,7 @@ vboot_is_safe() { local tmp="`mktemp -d --tmpdir=/tmp 'crouton-rwtest.XXX'`" local unmount="umount -l '$tmp' 2>/dev/null; rmdir '$tmp'" addtrap "$unmount" - mount --bind / "$tmp" >/dev/null + mount --bind / "$tmp" >/dev/null 2>&1 local ret=1 mount -o remount,rw "$tmp" 2>/dev/null || ret=0 undotrap From dd26bd3ac55b669537f491215eb0e106f66e0925 Mon Sep 17 00:00:00 2001 From: Yu-Hsi Chiang Date: Fri, 25 Sep 2015 17:54:41 +0800 Subject: [PATCH 9/9] Do not fail on bind-mounting dbus, since it is probably not mounted in containers. --- host-bin/enter-chroot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host-bin/enter-chroot b/host-bin/enter-chroot index 3670333e9..b910e9909 100755 --- a/host-bin/enter-chroot +++ b/host-bin/enter-chroot @@ -387,7 +387,7 @@ bindmount /tmp /tmp exec bindmount /proc tmpfsmount /var/run 'noexec,nosuid,mode=0755,size=10%' tmpfsmount /var/run/lock 'noexec,nosuid,nodev,size=5120k' -bindmount /var/run/dbus /var/host/dbus +bindmount /var/run/dbus /var/host/dbus 2>/dev/null || true bindmount /var/run/shill /var/host/shill bindmount /var/lib/timezone /var/host/timezone # If findnacld socket exists, bind-mount it into chroot.