From afe2bfb856505cbe5384554f0e57b4ab6eb66cd3 Mon Sep 17 00:00:00 2001 From: unbit Date: Wed, 4 Sep 2013 11:36:45 +0200 Subject: [PATCH] improved support for FreeBSD jails --- core/utils.c | 106 +++++++++++++++++++++++++++++++++++-------------- core/uwsgi.c | 6 +++ uwsgi.h | 6 +++ uwsgiconfig.py | 3 ++ 4 files changed, 92 insertions(+), 29 deletions(-) diff --git a/core/utils.c b/core/utils.c index 9a446625..54ae5ac2 100644 --- a/core/utils.c +++ b/core/utils.c @@ -344,6 +344,8 @@ void uwsgi_as_root() { } #endif + int in_jail = 0; + #if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) if (uwsgi.unshare && !uwsgi.reloads) { @@ -354,24 +356,7 @@ void uwsgi_as_root() { else { uwsgi_log("[linux-namespace] applied unshare() mask: %d\n", uwsgi.unshare); } - - struct uwsgi_string_list *usl = uwsgi.exec_post_jail; - while(usl) { - uwsgi_log("running \"%s\" (post-jail)...\n", usl->value); - int ret = uwsgi_run_command_and_wait(NULL, usl->value); - if (ret != 0) { - uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret); - exit(1); - } - usl = usl->next; - } - - uwsgi_foreach(usl, uwsgi.call_post_jail) { - if (uwsgi_call_symbol(usl->value)) { - uwsgi_log("unaable to call function \"%s\"\n", usl->value); - } - } - + in_jail = 1; } #endif @@ -438,9 +423,68 @@ void uwsgi_as_root() { exit(1); } + if (uwsgi.jidfile) { + if (uwsgi_write_intfile(uwsgi.jidfile, jail_id)) { + uwsgi_log("unable to write jidfile\n"); + exit(1); + } + } + uwsgi_log("--- running in FreeBSD jail %d ---\n", jail_id); - - usl = uwsgi.exec_post_jail; + in_jail = 1; + } + +#ifdef UWSGI_HAS_FREEBSD_LIBJAIL + if (uwsgi.jail2 && !uwsgi.reloads) { + struct uwsgi_string_list *usl = NULL; + unsigned nparams = 0; + uwsgi_foreach(usl, uwsgi.jail2) { + nparams++; + } + struct jailparam *params = uwsgi_malloc(sizeof(struct jailparam) * nparams); + int i = 0; + uwsgi_foreach(usl, uwsgi.jail2) { + uwsgi_log("FreeBSD libjail applying %s\n", usl->value); + char *equal = strchr(usl->value, '='); + if (equal) { + *equal = 0; + } + if (jailparam_init(¶ms[i], usl->value)) { + uwsgi_error("jailparam_init()"); + exit(1); + } + if (equal) { + jailparam_import(¶ms[i], equal+1); + *equal = '='; + } + else { + jailparam_import(¶ms[i], "1"); + } + i++; + } + int jail_id = jailparam_set(params, nparams, JAIL_CREATE|JAIL_ATTACH); + if (jail_id < 0) { + uwsgi_error("jailparam_set()"); + exit(1); + } + + jailparam_free(params, nparams); + + if (uwsgi.jidfile) { + if (uwsgi_write_intfile(uwsgi.jidfile, jail_id)) { + uwsgi_log("unable to write jidfile\n"); + exit(1); + } + } + + uwsgi_log("--- running in FreeBSD jail %d ---\n", jail_id); + in_jail = 1; + } +#endif +#endif + + if (in_jail) { + struct uwsgi_string_list *usl = uwsgi.exec_post_jail; while(usl) { uwsgi_log("running \"%s\" (post-jail)...\n", usl->value); int ret = uwsgi_run_command_and_wait(NULL, usl->value); @@ -457,9 +501,7 @@ void uwsgi_as_root() { } } - } -#endif - + } if (uwsgi.chroot && !uwsgi.reloads) { if (!uwsgi.master_as_root) @@ -3176,15 +3218,21 @@ void uwsgi_emulate_cow_for_apps(int id) { } } +int uwsgi_write_intfile(char *filename, int n) { + FILE *pidfile = fopen(filename, "w"); + if (!pidfile) { + uwsgi_error_open(filename); + exit(1); + } + if (fprintf(pidfile, "%d\n", n) <= 0 || ferror(pidfile) || fclose(pidfile)) { + return -1; + } + return 0; +} void uwsgi_write_pidfile(char *pidfile_name) { uwsgi_log("writing pidfile to %s\n", pidfile_name); - FILE *pidfile = fopen(pidfile_name, "w"); - if (!pidfile) { - uwsgi_error_open(pidfile_name); - exit(1); - } - if (fprintf(pidfile, "%d\n", (int) getpid()) <= 0 || ferror(pidfile) || fclose(pidfile)) { + if (uwsgi_write_intfile(pidfile_name, (int) getpid())) { uwsgi_log("could not write pidfile.\n"); } } diff --git a/core/uwsgi.c b/core/uwsgi.c index b485d9dc..f73f4f3f 100644 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -310,6 +310,12 @@ static struct uwsgi_option uwsgi_base_options[] = { {"jail", required_argument, 0, "put the instance in a FreeBSD jail", uwsgi_opt_set_str, &uwsgi.jail, 0}, {"jail-ip4", required_argument, 0, "add an ipv4 address to the FreeBSD jail", uwsgi_opt_add_string_list, &uwsgi.jail_ip4, 0}, {"jail-ip6", required_argument, 0, "add an ipv6 address to the FreeBSD jail", uwsgi_opt_add_string_list, &uwsgi.jail_ip6, 0}, + {"jidfile", required_argument, 0, "save the jid of a FreeBSD jail in the specified file", uwsgi_opt_set_str, &uwsgi.jidfile, 0}, + {"jid-file", required_argument, 0, "save the jid of a FreeBSD jail in the specified file", uwsgi_opt_set_str, &uwsgi.jidfile, 0}, +#ifdef UWSGI_HAS_FREEBSD_LIBJAIL + {"jail2", required_argument, 0, "add an option to the FreeBSD jail", uwsgi_opt_add_string_list, &uwsgi.jail2, 0}, + {"libjail", required_argument, 0, "add an option to the FreeBSD jail", uwsgi_opt_add_string_list, &uwsgi.jail2, 0}, +#endif #endif {"refork", no_argument, 0, "fork() again after privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork, 0}, {"re-fork", no_argument, 0, "fork() again after privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork, 0}, diff --git a/uwsgi.h b/uwsgi.h index 95399467..bff130a0 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -200,6 +200,9 @@ extern "C" { #include #include #include +#ifdef UWSGI_HAS_FREEBSD_LIBJAIL +#include +#endif #endif #include @@ -1830,6 +1833,8 @@ struct uwsgi_server { #ifdef AF_INET6 struct uwsgi_string_list *jail_ip6; #endif + struct uwsgi_string_list *jail2; + char *jidfile; #endif int refork; @@ -3528,6 +3533,7 @@ void uwsgi_setup_post_buffering(void); struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *); void uwsgi_write_pidfile(char *); +int uwsgi_write_intfile(char *, int); void uwsgi_protected_close(int); ssize_t uwsgi_protected_read(int, void *, size_t); diff --git a/uwsgiconfig.py b/uwsgiconfig.py index 245c0411..185736c9 100644 --- a/uwsgiconfig.py +++ b/uwsgiconfig.py @@ -951,6 +951,9 @@ class uConf(object): uwsgi_version += self.get('append_version') + if uwsgi_os == 'FreeBSD' and self.has_include('jail.h'): + self.cflags.append('-DUWSGI_HAS_FREEBSD_LIBJAIL') + self.libs.append('-ljail') if uwsgi_os == 'Linux': if self.get('embed_config'):