Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions hack/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,21 @@ set -eu -o pipefail -x

cd $(dirname $0)/..

ref=rootless-containers/rootlesskit:test
# build -q but keep printing something (....) so as to avoid Travis timeout
(while sleep 60; do echo -n .; done) & docker build -q -t rootless-containers/rootlesskit:test -f ./hack/test/Dockerfile . ; kill %1
docker run -it --rm --privileged rootless-containers/rootlesskit:test
(while sleep 60; do echo -n .; done) & docker build -q -t ${ref} -f ./hack/test/Dockerfile . ; kill %1

# TODO: add `--security-opt unconfined-paths=/sys` when https://github.com/docker/cli/pull/1347 gets merged.
# See https://github.com/rootless-containers/rootlesskit/pull/23 for the context.
#
# NOTE: bind-mounting /dev/net/tun is needed because we cannot mknod the tun device, at least with kernel < 4.18
#
# FIXME: --privilege is needed because the test suite compares rootlesskit with rootful `ip netns`.
# TODO: split the rootful test to separate container and remove --privilege
docker run \
--rm \
--security-opt seccomp=unconfined \
--security-opt apparmor=unconfined \
-v /dev/net/tun:/dev/net/tun \
--privileged \
${ref}
53 changes: 36 additions & 17 deletions hack/test/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
FROM golang:1.10 AS rootlesskit
FROM golang:1.11 AS rootlesskit
ADD . /go/src/github.com/rootless-containers/rootlesskit
RUN go build -o /rootlesskit github.com/rootless-containers/rootlesskit/cmd/rootlesskit

FROM ubuntu as build-c
FROM ubuntu:18.04 as build-c
RUN apt update && apt install -y git make gcc automake autotools-dev libtool

# As of October 2018, the upstream shadow newuidmap/newgidmap requires `docker run --cap-add sys_admin`.
# We can use https://github.com/shadow-maint/shadow/pull/132 for eliminating unneeded dependency on CAP_SYS_ADMIN.
FROM build-c as idmap
RUN apt update && apt install -y byacc gettext autopoint libcap-dev libxslt1-dev
RUN ( git clone -b no-cap-sys-admin https://github.com/giuseppe/shadow.git /shadow && cd /shadow )
WORKDIR /shadow
RUN ./autogen.sh --disable-nls --disable-man --without-audit --without-selinux --without-acl --without-attr --without-tcb --without-nscd \
&& make \
&& cp src/newuidmap src/newgidmap /usr/bin

FROM build-c AS slirp4netns
ARG SLIRP4NETNS_COMMIT=0037042e2facc8818d0a254e320a739648283f2e
ARG SLIRP4NETNS_COMMIT=39e87c0e66345edf7fd6e0bd1f61aa842617e757
RUN git clone https://github.com/rootless-containers/slirp4netns.git /slirp4netns && \
cd /slirp4netns && git checkout ${SLIRP4NETNS_COMMIT} && \
./autogen.sh && ./configure && make

FROM ubuntu AS vpnkit
FROM ubuntu:18.04 AS vpnkit
RUN apt update && apt install -y ocaml opam
ARG VPNKIT_COMMIT=bbedcf42d9e6ba0afba65aca18dd5fc087192b13
ARG VPNKIT_COMMIT=7d18ec48982340f49461379d718a4538f3090e13
RUN git clone https://github.com/moby/vpnkit.git /vpnkit && \
cd /vpnkit && git checkout ${VPNKIT_COMMIT} && \
make
Expand All @@ -36,24 +46,33 @@ RUN git clone https://github.com/rd235/vdeplug_slirp.git /vdeplug_slirp && \
cd /vdeplug_slirp && git checkout ${VDEPLUGSLIRP_COMMIT} && \
autoreconf -if && ./configure && make && make install

FROM ubuntu AS test
# busybox is only for debugging purpose
# sudo is only for rootful veth benchmark (for comparison)
RUN apt update && apt install -y iperf3 uidmap iproute2 busybox sudo
RUN useradd --create-home --home-dir /home/user --uid 1000 user \
FROM ubuntu:18.04 AS test-base
# iproute2: for `ip` command that rootlesskit needs to exec
# iperf3: only for benchmark purpose
# busybox: only for debugging purpose
# sudo: only for rootful veth benchmark (for comparison)
RUN apt update && apt install -y iproute2 iperf3 busybox sudo
COPY --from=idmap /usr/bin/newuidmap /usr/bin/newuidmap
COPY --from=idmap /usr/bin/newgidmap /usr/bin/newgidmap
COPY --from=rootlesskit /rootlesskit /home/user/bin/
RUN chmod u+s /usr/bin/newuidmap /usr/bin/newgidmap \
&& useradd --create-home --home-dir /home/user --uid 1000 user \
&& mkdir -p /run/user/1000 \
&& chown -R user:user /run/user/1000 /home/user \
&& echo "user ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/user
COPY --from=rootlesskit /rootlesskit /home/user/bin/
COPY --from=slirp4netns /slirp4netns/slirp4netns /home/user/bin/
COPY --from=vpnkit /vpnkit/vpnkit.exe /home/user/bin/vpnkit
COPY --from=vdeplug_slirp /usr/local/bin/* /home/user/bin/
COPY --from=vdeplug_slirp /usr/local/lib/* /home/user/lib/
ADD ./hack/test/docker-entrypoint.sh /home/user/bin/
RUN chown -R user:user /run/user/1000 /home/user
USER user
ENV HOME /home/user
ENV USER user
ENV XDG_RUNTIME_DIR=/run/user/1000
ENV PATH /home/user/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ENV LD_LIBRARY_PATH=/home/user/lib

FROM test-base AS test-light
COPY --from=slirp4netns /slirp4netns/slirp4netns /home/user/bin/

FROM test-light AS test-full
COPY --from=vpnkit /vpnkit/vpnkit.exe /home/user/bin/vpnkit
COPY --from=vdeplug_slirp /usr/local/bin/* /home/user/bin/
COPY --from=vdeplug_slirp /usr/local/lib/* /home/user/lib/
ADD ./hack/test/docker-entrypoint.sh /home/user/bin/
ENTRYPOINT ["/home/user/bin/docker-entrypoint.sh"]
22 changes: 18 additions & 4 deletions pkg/child/child.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,25 @@ func mountSysfs() error {
return errors.Wrap(err, "creating a directory under /tmp")
}
defer os.RemoveAll(tmp)
cmds := [][]string{
{"mount", "--rbind", "/sys/fs/cgroup", tmp},
{"mount", "-t", "sysfs", "none", "/sys"},
{"mount", "-n", "--move", tmp, "/sys/fs/cgroup"},
cmds := [][]string{{"mount", "--rbind", "/sys/fs/cgroup", tmp}}
if err := common.Execs(os.Stderr, os.Environ(), cmds); err != nil {
return errors.Wrapf(err, "executing %v", cmds)
}
cmds = [][]string{{"mount", "-t", "sysfs", "none", "/sys"}}
if err := common.Execs(os.Stderr, os.Environ(), cmds); err != nil {
// when the sysfs in the parent namespace is RO,
// we can't mount RW sysfs even in the child namespace.
// https://github.com/rootless-containers/rootlesskit/pull/23#issuecomment-429292632
// https://github.com/torvalds/linux/blob/9f203e2f2f065cd74553e6474f0ae3675f39fb0f/fs/namespace.c#L3326-L3328
cmdsRo := [][]string{{"mount", "-t", "sysfs", "-o", "ro", "none", "/sys"}}
logrus.Warnf("failed to mount sysfs (%v), falling back to read-only mount (%v): %v",
cmds, cmdsRo, err)
if err := common.Execs(os.Stderr, os.Environ(), cmdsRo); err != nil {
// when /sys/firmware is masked, even RO sysfs can't be mounted
logrus.Warnf("failed to mount sysfs (%v): %v", cmdsRo, err)
}
}
cmds = [][]string{{"mount", "-n", "--move", tmp, "/sys/fs/cgroup"}}
if err := common.Execs(os.Stderr, os.Environ(), cmds); err != nil {
return errors.Wrapf(err, "executing %v", cmds)
}
Expand Down