Skip to content

Commit

Permalink
Merge pull request #318 from n1hility/fix-symlinks
Browse files Browse the repository at this point in the history
Add support for escaping resolv.conf symlinks
  • Loading branch information
AkihiroSuda authored Aug 17, 2023
2 parents 462be17 + 9103678 commit 0c5bdfc
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 28 deletions.
19 changes: 10 additions & 9 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,22 @@ on:

jobs:
release:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: docker/setup-buildx-action@v1
- uses: docker/setup-qemu-action@v2
- uses: docker/setup-buildx-action@v2
- name: "Build binaries from Dockerfile.artifact"
run: docker buildx build -o /tmp --platform=amd64,arm64,arm,s390x,ppc64le,riscv64 -f Dockerfile.artifact .
run: docker buildx build -o /tmp/slirpbuilds --platform=amd64,arm64,arm,s390x,ppc64le,riscv64 -f Dockerfile.artifact .
- name: "Create /tmp/artifact"
run: |
mkdir -p /tmp/artifact
mv /tmp/linux_amd64/slirp4netns /tmp/artifact/slirp4netns-x86_64
mv /tmp/linux_arm64/slirp4netns /tmp/artifact/slirp4netns-aarch64
mv /tmp/linux_arm_v7/slirp4netns /tmp/artifact/slirp4netns-armv7l
mv /tmp/linux_s390x/slirp4netns /tmp/artifact/slirp4netns-s390x
mv /tmp/linux_ppc64le/slirp4netns /tmp/artifact/slirp4netns-ppc64le
mv /tmp/linux_riscv64/slirp4netns /tmp/artifact/slirp4netns-riscv64
mv /tmp/slirpbuilds/linux_amd64/slirp4netns /tmp/artifact/slirp4netns-x86_64
mv /tmp/slirpbuilds/linux_arm64/slirp4netns /tmp/artifact/slirp4netns-aarch64
mv /tmp/slirpbuilds/linux_arm_v7/slirp4netns /tmp/artifact/slirp4netns-armv7l
mv /tmp/slirpbuilds/linux_s390x/slirp4netns /tmp/artifact/slirp4netns-s390x
mv /tmp/slirpbuilds/linux_ppc64le/slirp4netns /tmp/artifact/slirp4netns-ppc64le
mv /tmp/slirpbuilds/linux_riscv64/slirp4netns /tmp/artifact/slirp4netns-riscv64
- name: "SHA256SUMS"
run: (cd /tmp/artifact; sha256sum *) | tee /tmp/SHA256SUMS
- name: "The sha256sum of the SHA256SUMS file"
Expand Down
6 changes: 3 additions & 3 deletions Dockerfile.buildtests
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ ARG LIBSLIRP_COMMIT=v4.7.0
# Alpine
FROM alpine:3 AS buildtest-alpine3-static
RUN apk add --no-cache git build-base autoconf automake libtool linux-headers glib-dev glib-static libcap-static libcap-dev libseccomp-dev libseccomp-static git meson
RUN git clone git://git.qemu.org/libslirp.git /libslirp
RUN git clone https://git.qemu.org/libslirp.git /libslirp
WORKDIR /libslirp
ARG LIBSLIRP_COMMIT
RUN git pull && git checkout ${LIBSLIRP_COMMIT} && meson setup --default-library=both build && ninja -C build install
Expand All @@ -16,7 +16,7 @@ FROM ubuntu:18.04 AS buildtest-ubuntu1804-common
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && apt install -y automake autotools-dev make gcc libglib2.0-dev libcap-dev libseccomp-dev git ninja-build python3-pip
RUN pip3 install meson
RUN git clone git://git.qemu.org/libslirp.git /libslirp
RUN git clone https://git.qemu.org/libslirp.git /libslirp
WORKDIR /libslirp
ARG LIBSLIRP_COMMIT
RUN git pull && git checkout ${LIBSLIRP_COMMIT} && meson setup build && ninja -C build install
Expand All @@ -34,7 +34,7 @@ RUN ./configure && make && cp -f slirp4netns /
FROM opensuse/leap:15 AS buildtest-opensuse15-common
RUN zypper install -y --no-recommends autoconf automake gcc glib2-devel git make libcap-devel libseccomp-devel ninja python3-pip
RUN pip3 install meson
RUN git clone git://git.qemu.org/libslirp.git /libslirp
RUN git clone https://git.qemu.org/libslirp.git /libslirp
WORKDIR /libslirp
ARG LIBSLIRP_COMMIT
RUN git pull && git checkout ${LIBSLIRP_COMMIT} && meson setup --default-library=both build && ninja -C build install
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.tests
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ FROM ubuntu:22.04 AS build
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && apt install -y automake autotools-dev make gcc libglib2.0-dev libcap-dev libseccomp-dev git ninja-build python3-pip
RUN pip3 install meson
RUN git clone git://git.qemu.org/libslirp.git /libslirp
RUN git clone https://git.qemu.org/libslirp.git /libslirp
WORKDIR /libslirp
ARG LIBSLIRP_COMMIT
RUN git pull && git checkout ${LIBSLIRP_COMMIT} && meson setup build && ninja -C build install
Expand Down
2 changes: 1 addition & 1 deletion Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Vagrant.configure("2") do |config|
git clone --depth=1 --no-checkout https://github.com/seccomp/libseccomp
git -C ./libseccomp fetch --tags --depth=1
git clone --depth=1 --no-checkout git://git.qemu.org/libslirp.git
git clone --depth=1 --no-checkout https://git.qemu.org/libslirp.git
git -C ./libslirp fetch --tags --depth=1
touch ./build-and-test
Expand Down
66 changes: 52 additions & 14 deletions sandbox.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
Expand All @@ -27,7 +28,8 @@ static int add_mount(const char *from, const char *to)
MS_BIND | MS_REC | MS_SLAVE | MS_NOSUID | MS_NODEV | MS_NOEXEC,
NULL);
if (ret < 0) {
fprintf(stderr, "cannot bind mount %s to %s\n", from, to);
fprintf(stderr, "cannot bind mount %s to %s (errno: %d)\n", from, to,
errno);
return ret;
}
ret = mount("", to, "", MS_SLAVE | MS_REC, NULL);
Expand All @@ -46,21 +48,54 @@ static int add_mount(const char *from, const char *to)
return 0;
}

/* Warn (not error) if /etc/resolv.conf is a symlink to a file outside /etc or
/* Bind /etc/resolv.conf if it is a symlink to a file outside /etc or
* /run. */
static void validate_etc_resolv_conf()
static int bind_escaped_resolv_conf(const char *root)
{
char *p = realpath("/etc/resolv.conf", NULL);
if (p == NULL) {
return;
char *real_resolv = realpath("/etc/resolv.conf", NULL);

/* Doesn't exist or is not an escaping symlink */
if (real_resolv == NULL || g_str_has_prefix(real_resolv, "/etc") ||
g_str_has_prefix(real_resolv, "/run")) {
free(real_resolv);
return 0;
}

char *resolv_dest = g_strconcat(root, real_resolv, NULL);
char *resolv_dest_dir = g_path_get_dirname(resolv_dest);
int ret = 0;

fprintf(stderr,
"sandbox: /etc/resolv.conf (-> %s) seems a symlink to a file "
"outside {/etc, /run}, attempting to bind it as well.\n",
real_resolv);

ret = g_mkdir_with_parents(resolv_dest_dir, 0755);
if (ret < 0) {
fprintf(stderr, "cannot create resolve dest dir path: %s\n",
resolv_dest_dir);
goto finish;
}

ret = creat(resolv_dest, 0644);
if (ret < 0) {
fprintf(stderr, "cannot create empty resolv.conf dest file %s\n",
resolv_dest);
goto finish;
}
if (!g_str_has_prefix(p, "/etc") && !g_str_has_prefix(p, "/run")) {
fprintf(stderr,
"sandbox: /etc/resolv.conf (-> %s) seems a symlink to a file "
"outside {/etc, /run}. DNS will not work.\n",
p);
close(ret);

ret = add_mount(real_resolv, resolv_dest);
if (ret < 0) {
fprintf(stderr, "cannot bind mount resolv.conf\n");
}
free(p);

finish:

free(real_resolv);
g_free(resolv_dest);
g_free(resolv_dest_dir);
return ret;
}

/* lock down the process doing the following:
Expand All @@ -75,8 +110,6 @@ int create_sandbox()
struct __user_cap_header_struct hdr = { _LINUX_CAPABILITY_VERSION_3, 0 };
struct __user_cap_data_struct data[2] = { { 0 } };

validate_etc_resolv_conf();

ret = unshare(CLONE_NEWNS);
if (ret < 0) {
fprintf(stderr, "cannot unshare new mount namespace\n");
Expand Down Expand Up @@ -118,6 +151,11 @@ int create_sandbox()
return ret;
}

ret = bind_escaped_resolv_conf("/tmp");
if (ret < 0) {
return ret;
}

ret = add_mount("/run", "/tmp/run");
if (ret < 0) {
return ret;
Expand Down

0 comments on commit 0c5bdfc

Please sign in to comment.