summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Golle2019-12-04 13:06:06 +0000
committerDaniel Golle2020-01-21 10:44:31 +0000
commit58c12f74d82c68051471f9c98c86786018f17dae (patch)
tree9e0cb40504de7682ed54602ebc97a26c82bee247
parent0a11aa405d3fbe970458d1cc154970e817826616 (diff)
downloadprocd-58c12f74d82c68051471f9c98c86786018f17dae.tar.gz
jail: add basic support for network namespaces
Add new 'netns' flag for procd_add_jail to make ujail setup a new network namespace for the jailed service. Signed-off-by: Daniel Golle <daniel@makrotopia.org>
-rw-r--r--CMakeLists.txt2
-rw-r--r--jail/jail.c83
-rw-r--r--service/instance.c10
-rw-r--r--service/instance.h1
4 files changed, 78 insertions, 18 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a566acd..cff47cf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -105,7 +105,7 @@ endif()
IF(JAIL_SUPPORT)
ADD_EXECUTABLE(ujail jail/jail.c jail/elf.c jail/fs.c jail/capabilities.c)
-TARGET_LINK_LIBRARIES(ujail ${ubox} ${blobmsg_json})
+TARGET_LINK_LIBRARIES(ujail ${ubox} ${ubus} ${blobmsg_json})
INSTALL(TARGETS ujail
RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
)
diff --git a/jail/jail.c b/jail/jail.c
index c6096f8..2d23ad2 100644
--- a/jail/jail.c
+++ b/jail/jail.c
@@ -37,9 +37,18 @@
#include "log.h"
#include <libubox/uloop.h>
+#include <libubus.h>
#define STACK_SIZE (1024 * 1024)
-#define OPT_ARGS "S:C:n:h:r:w:d:psulocU:G:"
+#define OPT_ARGS "S:C:n:h:r:w:d:psulocU:G:N"
+
+#define NAMESPACE_MOUNT (1U << 0)
+#define NAMESPACE_IPC (1U << 1)
+#define NAMESPACE_NET (1U << 2)
+#define NAMESPACE_PID (1U << 3)
+#define NAMESPACE_USER (1U << 4)
+#define NAMESPACE_UTS (1U << 5)
+#define NAMESPACE_CGROUP (1U << 6)
static struct {
char *name;
@@ -224,6 +233,7 @@ static void usage(void)
fprintf(stderr, " -n <name>\tthe name of the jail\n");
fprintf(stderr, "namespace jail options:\n");
fprintf(stderr, " -h <hostname>\tchange the hostname of the jail\n");
+ fprintf(stderr, " -N\t\tjail has network namespace\n");
fprintf(stderr, " -r <file>\treadonly files that should be staged\n");
fprintf(stderr, " -w <file>\twriteable files that should be staged\n");
fprintf(stderr, " -p\t\tjail has /proc\n");
@@ -348,6 +358,29 @@ static void jail_handle_signal(int signo)
kill(jail_process.pid, signo);
}
+static void netns_updown(bool start)
+{
+ struct ubus_context *ctx = ubus_connect(NULL);
+ static struct blob_buf req;
+ uint32_t id;
+ pid_t pid = getpid();
+
+ if (!ctx)
+ return;
+
+ blob_buf_init(&req, 0);
+ blobmsg_add_string(&req, "jail", opts.name);
+ blobmsg_add_u32(&req, "pid", pid);
+ blobmsg_add_u8(&req, "start", start);
+
+ if (ubus_lookup_id(ctx, "network", &id) ||
+ ubus_invoke(ctx, id, "netns_updown", req.head, NULL, NULL, 3000))
+ INFO("ubus request failed\n");
+
+ blob_buf_free(&req);
+ ubus_free(ctx);
+}
+
int main(int argc, char **argv)
{
sigset_t sigmask;
@@ -371,15 +404,15 @@ int main(int argc, char **argv)
debug = atoi(optarg);
break;
case 'p':
- opts.namespace = 1;
+ opts.namespace |= NAMESPACE_MOUNT;
opts.procfs = 1;
break;
case 'o':
- opts.namespace = 1;
+ opts.namespace |= NAMESPACE_MOUNT;
opts.ronly = 1;
break;
case 's':
- opts.namespace = 1;
+ opts.namespace |= NAMESPACE_MOUNT;
opts.sysfs = 1;
break;
case 'S':
@@ -395,23 +428,26 @@ int main(int argc, char **argv)
case 'n':
opts.name = optarg;
break;
+ case 'N':
+ opts.namespace |= NAMESPACE_NET;
+ break;
case 'h':
opts.hostname = optarg;
break;
case 'r':
- opts.namespace = 1;
+ opts.namespace |= NAMESPACE_MOUNT;
add_path_and_deps(optarg, 1, 0, 0);
break;
case 'w':
- opts.namespace = 1;
+ opts.namespace |= NAMESPACE_MOUNT;
add_path_and_deps(optarg, 0, 0, 0);
break;
case 'u':
- opts.namespace = 1;
+ opts.namespace |= NAMESPACE_MOUNT;
add_mount(ubus, 0, -1);
break;
case 'l':
- opts.namespace = 1;
+ opts.namespace |= NAMESPACE_MOUNT;
add_mount(log, 0, -1);
break;
case 'U':
@@ -469,19 +505,29 @@ int main(int argc, char **argv)
}
if (opts.namespace) {
- add_mount("/dev/full", 0, -1);
- add_mount("/dev/null", 0, -1);
- add_mount("/dev/urandom", 0, -1);
- add_mount("/dev/zero", 0, -1);
-
- if (opts.user || opts.group) {
- add_mount("/etc/passwd", 0, -1);
- add_mount("/etc/group", 0, -1);
+ int flags = SIGCHLD | CLONE_NEWPID | CLONE_NEWIPC;
+
+ if (opts.namespace & NAMESPACE_MOUNT) {
+ flags |= CLONE_NEWNS;
+ add_mount("/dev/full", 0, -1);
+ add_mount("/dev/null", 0, -1);
+ add_mount("/dev/urandom", 0, -1);
+ add_mount("/dev/zero", 0, -1);
+
+ if (opts.user || opts.group) {
+ add_mount("/etc/passwd", 0, -1);
+ add_mount("/etc/group", 0, -1);
+ }
}
- int flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | SIGCHLD;
if (opts.hostname)
flags |= CLONE_NEWUTS;
+
+ if (opts.namespace & NAMESPACE_NET) {
+ unshare(CLONE_NEWNET);
+ netns_updown(true);
+ };
+
jail_process.pid = clone(exec_jail, child_stack + STACK_SIZE, flags, NULL);
} else {
jail_process.pid = fork();
@@ -498,6 +544,9 @@ int main(int argc, char **argv)
uloop_run();
}
uloop_done();
+ if (opts.namespace & NAMESPACE_NET)
+ netns_updown(false);
+
return jail_return_code;
} else if (jail_process.pid == 0) {
/* fork child process */
diff --git a/service/instance.c b/service/instance.c
index 14da862..3b4e93a 100644
--- a/service/instance.c
+++ b/service/instance.c
@@ -99,6 +99,7 @@ enum {
JAIL_ATTR_LOG,
JAIL_ATTR_RONLY,
JAIL_ATTR_MOUNT,
+ JAIL_ATTR_NETNS,
__JAIL_ATTR_MAX,
};
@@ -111,6 +112,7 @@ static const struct blobmsg_policy jail_attr[__JAIL_ATTR_MAX] = {
[JAIL_ATTR_LOG] = { "log", BLOBMSG_TYPE_BOOL },
[JAIL_ATTR_RONLY] = { "ronly", BLOBMSG_TYPE_BOOL },
[JAIL_ATTR_MOUNT] = { "mount", BLOBMSG_TYPE_TABLE },
+ [JAIL_ATTR_NETNS] = { "netns", BLOBMSG_TYPE_BOOL },
};
struct instance_netdev {
@@ -250,6 +252,9 @@ jail_run(struct service_instance *in, char **argv)
if (jail->ronly)
argv[argc++] = "-o";
+ if (jail->netns)
+ argv[argc++] = "-N";
+
blobmsg_list_for_each(&jail->mount, var) {
const char *type = blobmsg_data(var->data);
@@ -832,6 +837,10 @@ instance_jail_parse(struct service_instance *in, struct blob_attr *attr)
jail->ronly = blobmsg_get_bool(tb[JAIL_ATTR_RONLY]);
jail->argc++;
}
+ if (tb[JAIL_ATTR_NETNS]) {
+ jail->netns = blobmsg_get_bool(tb[JAIL_ATTR_NETNS]);
+ jail->argc++;
+ }
if (tb[JAIL_ATTR_MOUNT]) {
struct blob_attr *cur;
int rem;
@@ -1218,6 +1227,7 @@ void instance_dump(struct blob_buf *b, struct service_instance *in, int verbose)
blobmsg_add_u8(b, "ubus", in->jail.ubus);
blobmsg_add_u8(b, "log", in->jail.log);
blobmsg_add_u8(b, "ronly", in->jail.ronly);
+ blobmsg_add_u8(b, "netns", in->jail.netns);
blobmsg_close_table(b, r);
if (!avl_is_empty(&in->jail.mount.avl)) {
struct blobmsg_list_node *var;
diff --git a/service/instance.h b/service/instance.h
index 42cc4be..e53c606 100644
--- a/service/instance.h
+++ b/service/instance.h
@@ -28,6 +28,7 @@ struct jail {
bool ubus;
bool log;
bool ronly;
+ bool netns;
char *name;
char *hostname;
struct blobmsg_list mount;