From 80013e2eae1b635973552bd2c2146f7a352aa4a0 Mon Sep 17 00:00:00 2001 From: Michael Santos Date: Sun, 9 Mar 2014 13:06:51 -0400 Subject: [PATCH] Add support for bind mounts using mount(2) Assuming a the directory "/tmp/mnt" exists: 1> Port = alcove_drv:start([{exec, "sudo"}]). % Fork a process with a new mount namespace 2> {ok, Child} = alcove:clone(Port, alcove:clone_define(Port, newns)). % Read-only bind mount of /bin on /tmp/mnt 3> alcove:mount(Port, [Child], "/bin", "/tmp/mnt", "", 4096 bxor 1, ""). % Run "/bin/ls -al /tmp/mnt" in the mount namespace 4> alcove:execvp(Port, [Child], "/bin/ls", ["/bin/ls", "-al", "/tmp/mnt]). --- c_src/alcove_call.proto | 1 + c_src/alcove_mount.c | 96 +++++++++++++++++++++++++++++++++++++++++ rebar.config | 1 + 3 files changed, 98 insertions(+) create mode 100644 c_src/alcove_mount.c diff --git a/c_src/alcove_call.proto b/c_src/alcove_call.proto index ec332c2..4c973ec 100644 --- a/c_src/alcove_call.proto +++ b/c_src/alcove_call.proto @@ -11,6 +11,7 @@ getpid/0 getrlimit/1 getuid/0 kill/2 +mount/5 pid/0 rlimit_define/1 setgid/1 diff --git a/c_src/alcove_mount.c b/c_src/alcove_mount.c new file mode 100644 index 0000000..55cccbd --- /dev/null +++ b/c_src/alcove_mount.c @@ -0,0 +1,96 @@ +/* Copyright (c) 2014, Michael Santos + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "alcove.h" +#include "alcove_call.h" + +#include + +/* + * mount(2) + * + */ + ETERM * +alcove_mount(alcove_state_t *ap, ETERM *arg) +{ + ETERM *hd = NULL; + char *source = NULL; + char *target = NULL; + char *filesystemtype = NULL; + unsigned long mountflags = 0; + char *data = NULL; + + int rv = 0; + + /* source */ + arg = alcove_list_head(&hd, arg); + if (!hd || !ALCOVE_IS_IOLIST(hd)) + goto BADARG; + + if (erl_iolist_length(hd) > 0) + source = erl_iolist_to_string(hd); + + if (!source) + goto BADARG; + + /* target */ + arg = alcove_list_head(&hd, arg); + if (!hd || !ALCOVE_IS_IOLIST(hd)) + goto BADARG; + + if (erl_iolist_length(hd) > 0) + target = erl_iolist_to_string(hd); + + if (!target) + goto BADARG; + + /* filesystemtype */ + arg = alcove_list_head(&hd, arg); + if (!hd || !ALCOVE_IS_IOLIST(hd)) + goto BADARG; + + if (erl_iolist_length(hd) > 0) + filesystemtype = erl_iolist_to_string(hd); + + /* mountflags */ + arg = alcove_list_head(&hd, arg); + if (!hd || !ERL_IS_INTEGER(hd)) + goto BADARG; + + mountflags = ERL_INT_VALUE(hd); + + /* data */ + arg = alcove_list_head(&hd, arg); + if (!hd || !ALCOVE_IS_IOLIST(hd)) + goto BADARG; + + if (erl_iolist_length(hd) > 0) + data = erl_iolist_to_string(hd); + + rv = mount(source, target, filesystemtype, mountflags, data); + + erl_free(source); + erl_free(target); + erl_free(filesystemtype); + erl_free(data); + + return ( (rv < 0) ? alcove_errno(errno) : erl_mk_atom("ok")); + +BADARG: + erl_free(source); + erl_free(target); + erl_free(filesystemtype); + erl_free(data); + return erl_mk_atom("badarg"); +} diff --git a/rebar.config b/rebar.config index 44e4466..f43bd7b 100644 --- a/rebar.config +++ b/rebar.config @@ -13,6 +13,7 @@ "c_src/alcove_exec.c", "c_src/alcove_fork.c", "c_src/alcove_limit.c", + "c_src/alcove_mount.c", "c_src/alcove_proc.c", "c_src/alcove_utsname.c",