Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use a sandbox with mkcomposefs --from-file #221

Closed
wants to merge 4 commits into from
Closed
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
4 changes: 4 additions & 0 deletions man/mkcomposefs.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ will be a mountable composefs image.
: The source is a file in the **composefs-dump(5)** format. If
the specified file is "-", the data is read from stdin.

**\-\-no-sandbox**
: Normally, when using **--from-file** a sandbox is set up to protect
the parsing code. This option disables this.


# SEE ALSO
**composefs-info(1)**, **mount.composefs(1)**, **composefs-dump(5)**
Expand Down
6 changes: 3 additions & 3 deletions tools/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ endif

AM_CFLAGS = $(WARN_CFLAGS) -I$(top_srcdir)/

mkcomposefs_SOURCES = mkcomposefs.c
mkcomposefs_LDADD = ../libcomposefs/libcomposefs.la $(LIBCRYPTO_LIBS)
mkcomposefs_SOURCES = mkcomposefs.c sandbox.c sandbox.h
mkcomposefs_LDADD = ../libcomposefs/libcomposefs.la $(LIBCRYPTO_LIBS) $(LIBS_SECCOMP)

mount_composefs_SOURCES = mountcomposefs.c
mount_composefs_LDADD = ../libcomposefs/libcomposefs.la $(LIBCRYPTO_LIBS)

composefs_from_json_SOURCES = composefs-from-json.c read-file.c read-file.h
composefs_from_json_SOURCES = composefs-from-json.c read-file.c read-file.h sandbox.c sandbox.h
composefs_from_json_LDADD = ../libcomposefs/libcomposefs.la $(LIBS_YAJL) $(LIBCRYPTO_LIBS) $(LIBS_SECCOMP)

composefs_info_SOURCES = composefs-info.c ../libcomposefs/hash.c
Expand Down
194 changes: 1 addition & 193 deletions tools/composefs-from-json.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,212 +22,20 @@
#include "libcomposefs/lcfs-writer.h"
#include "libcomposefs/lcfs-utils.h"
#include "read-file.h"
#include "sandbox.h"

#include <stdio.h>
#include <linux/limits.h>
#include <string.h>
#include <err.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/sysmacros.h>
#include <yajl/yajl_tree.h>
#include <getopt.h>
#include <sys/prctl.h>
#include <sched.h>
#include <sys/mount.h>
#ifdef HAVE_SYS_CAPABILITY_H
#include <sys/capability.h>
#endif
#ifdef HAVE_LIBSECCOMP
#include <linux/seccomp.h>
#include <seccomp.h>
#endif
#include <time.h>

static void do_seccomp_sandbox(void)
{
#ifdef HAVE_LIBSECCOMP
scmp_filter_ctx ctx;
int ret;
size_t i;
int syscalls[] = {
SCMP_SYS(brk), SCMP_SYS(close), SCMP_SYS(exit),
SCMP_SYS(exit_group), SCMP_SYS(fstat), SCMP_SYS(lseek),
SCMP_SYS(mmap), SCMP_SYS(mremap), SCMP_SYS(munmap),
SCMP_SYS(newfstatat), SCMP_SYS(read), SCMP_SYS(readv),
SCMP_SYS(sysinfo), SCMP_SYS(write), SCMP_SYS(writev),
};

ctx = seccomp_init(SCMP_ACT_ERRNO(ENOSYS));
if (ctx == NULL)
err(EXIT_FAILURE, "seccomp_init");

for (i = 0; i < sizeof(syscalls) / sizeof(syscalls[0]); i++) {
ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscalls[i], 0);
if (ret < 0) {
errno = -ret;
err(EXIT_FAILURE, "seccomp_rule_add");
}
}

ret = seccomp_load(ctx);
if (ret < 0) {
errno = -ret;
err(EXIT_FAILURE, "seccomp_load");
}
#endif
}

#ifdef __NR_pivot_root
static int pivot_root(const char *new_root, const char *put_old)
{
return syscall(__NR_pivot_root, new_root, put_old);
}
#endif

static void do_namespace_sandbox(void)
{
uid_t uid = geteuid();
gid_t gid = getegid();
int ret, fd;
#ifdef __NR_pivot_root
int old_root;
char *cwd;
#endif

ret = unshare(CLONE_NEWUSER | CLONE_NEWNS | CLONE_NEWUTS |
CLONE_NEWIPC | CLONE_NEWNET);
if (ret < 0)
return;

fd = open("/proc/self/setgroups", O_WRONLY | O_CLOEXEC);
if (fd < 0)
err(EXIT_FAILURE, "open /proc/self/setgroups");
ret = write(fd, "deny", 4);
if (ret < 0)
err(EXIT_FAILURE, "write to /proc/self/gid_map");
close(fd);

fd = open("/proc/self/gid_map", O_WRONLY | O_CLOEXEC);
if (fd < 0)
err(EXIT_FAILURE, "open /proc/self/gid_map");
ret = dprintf(fd, "0 %d 1\n", gid);
if (ret < 0)
err(EXIT_FAILURE, "write to /proc/self/gid_map");
close(fd);

fd = open("/proc/self/uid_map", O_WRONLY | O_CLOEXEC);
if (fd < 0)
err(EXIT_FAILURE, "open /proc/self/uid_map");
ret = dprintf(fd, "0 %d 1\n", uid);
if (ret < 0)
err(EXIT_FAILURE, "write to /proc/self/uid_map");
close(fd);

#ifdef __NR_pivot_root
ret = mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL);
if (ret < 0)
err(EXIT_FAILURE, "mount /");

cwd = get_current_dir_name();
if (!cwd)
err(EXIT_FAILURE, "get_current_dir_name");

ret = mount(NULL, cwd, "tmpfs", 0, NULL);
if (ret < 0)
err(EXIT_FAILURE, "mount tmpfs");

old_root = open("/", O_PATH | O_DIRECTORY | O_CLOEXEC);
if (old_root < 0)
err(EXIT_FAILURE, "open /");

ret = chdir(cwd);
if (ret < 0)
err(EXIT_FAILURE, "chdir cwd");

free(cwd);
cwd = NULL;

ret = pivot_root(".", ".");
if (ret < 0)
err(EXIT_FAILURE, "pivot_root");

ret = fchdir(old_root);
if (ret < 0)
err(EXIT_FAILURE, "fchdir");
close(old_root);

ret = umount2(".", MNT_DETACH);
if (ret < 0)
err(EXIT_FAILURE, "umount2");

ret = chdir("/");
if (ret < 0)
err(EXIT_FAILURE, "fchdir");
#endif
}

static void drop_caps(void)
{
#ifdef HAVE_SYS_CAPABILITY_H
struct __user_cap_header_struct hdr = { _LINUX_CAPABILITY_VERSION_3, 0 };
struct __user_cap_data_struct data[2] = { { 0 } };
#endif
int ret, cap;
ret = prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0);
if (ret < 0)
err(EXIT_FAILURE, "prctl(PR_SET_KEEPCAPS)");

for (cap = 0;; cap++) {
ret = prctl(PR_CAPBSET_DROP, cap, 0, 0, 0);
if (ret < 0 && errno != EINVAL)
err(EXIT_FAILURE, "prctl(PR_CAPBSET_DROP)");
if (ret < 0)
break;
}

#ifdef PR_CAP_AMBIENT
ret = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
if (ret < 0 && errno != EINVAL)
err(EXIT_FAILURE, "prctl(PR_CAP_AMBIENT)");
#endif

#ifdef HAVE_SYS_CAPABILITY_H
ret = capset(&hdr, data);
if (ret < 0 && errno != EINVAL)
err(EXIT_FAILURE, "capset");
#endif
}

static void do_set_oom_score_adj(void)
{
int fd, ret;

fd = open("/proc/self/oom_score_adj", O_WRONLY);
if (fd < 0)
err(EXIT_FAILURE, "open /proc/self/oom_score_adj");

ret = write(fd, "1000", 4);
if (ret < 0)
err(EXIT_FAILURE, "write to /proc/self/oom_score_adj");

close(fd);
}

static void sandbox(void)
{
do_set_oom_score_adj();
do_namespace_sandbox();
drop_caps();

if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0)
err(EXIT_FAILURE, "prctl(PR_SET_NO_NEW_PRIVS)");

do_seccomp_sandbox();
}

/* Adapted from mailutils 0.6.91(distributed under LGPL 2.0+) */
static int b64_input(char c)
{
Expand Down
18 changes: 17 additions & 1 deletion tools/mkcomposefs.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "libcomposefs/lcfs-writer.h"
#include "libcomposefs/lcfs-utils.h"
#include "libcomposefs/lcfs-internal.h"
#include "sandbox.h"

#include <stdio.h>
#include <linux/limits.h>
Expand Down Expand Up @@ -325,7 +326,8 @@ static void usage(const char *argv0)
" --user-xattrs Only store user.* xattrs\n"
" --print-digest Print the digest of the image\n"
" --print-digest-only Print the digest of the image, don't write image\n"
" --from-file The source is a dump file, not a directory\n",
" --from-file The source is a dump file, not a directory\n"
" --no-sandbox Disable sandboxing code\n",
bin);
}

Expand All @@ -337,6 +339,7 @@ static void usage(const char *argv0)
#define OPT_PRINT_DIGEST_ONLY 111
#define OPT_USER_XATTRS 112
#define OPT_FROM_FILE 113
#define OPT_NO_SANDBOX 114

static ssize_t write_cb(void *_file, void *buf, size_t count)
{
Expand Down Expand Up @@ -878,6 +881,12 @@ int main(int argc, char **argv)
flag: NULL,
val: OPT_FROM_FILE
},
{
name: "no-sandbox",
has_arg: no_argument,
flag: NULL,
val: OPT_NO_SANDBOX
},
{},
};
struct lcfs_write_options_s options = { 0 };
Expand All @@ -886,6 +895,7 @@ int main(int argc, char **argv)
bool print_digest = false;
bool print_digest_only = false;
bool from_file = false;
bool no_sandbox = false;
struct lcfs_node_s *root;
const char *out = NULL;
const char *src_path = NULL;
Expand Down Expand Up @@ -925,6 +935,9 @@ int main(int argc, char **argv)
case OPT_FROM_FILE:
from_file = true;
break;
case OPT_NO_SANDBOX:
no_sandbox = true;
break;
case ':':
fprintf(stderr, "option needs a value\n");
exit(EXIT_FAILURE);
Expand Down Expand Up @@ -994,6 +1007,9 @@ int main(int argc, char **argv)
close_input = true;
}

if (!no_sandbox)
sandbox();

root = tree_from_dump(input);
if (root == NULL)
errx(EXIT_FAILURE, "No files in dump file");
Expand Down
Loading
Loading