From bafd1071fb8f73ec8dc05e658efb461bff776650 Mon Sep 17 00:00:00 2001 From: Nick Kew Date: Sat, 12 Jan 2008 21:16:27 +0000 Subject: [PATCH] Support chroot on unix-family platforms PR 43596 (Dimitar Pashev) git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@611483 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 3 +++ os/unix/unixd.c | 40 ++++++++++++++++++++++++++++++++++++++++ os/unix/unixd.h | 8 +++++++- 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 4af62a1805..be0eecf50d 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,9 @@ Changes with Apache 2.3.0 [ When backported to 2.2.x, remove entry from this file ] + *) Support chroot on Unix-family platforms + PR 43596 [Dimitar Pashev ] + *) Don't add bogus duplicate Content-Language entries PR 11035 [Davi Arnaut] diff --git a/os/unix/unixd.c b/os/unix/unixd.c index 8da536b513..96784d791e 100644 --- a/os/unix/unixd.c +++ b/os/unix/unixd.c @@ -117,6 +117,30 @@ AP_DECLARE(int) unixd_setup_child(void) if (set_group_privs()) { return -1; } + + if (NULL != unixd_config.chroot_dir) { + if (geteuid()) { + ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, + "Cannot chroot when not started as root"); + return -1; + } + if (chdir(unixd_config.chroot_dir) != 0) { + ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, + "Can't chdir to %s", unixd_config.chroot_dir); + return -1; + } + if (chroot(unixd_config.chroot_dir) != 0) { + ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, + "Can't chroot to %s", unixd_config.chroot_dir); + return -1; + } + if (chdir("/") != 0) { + ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, + "Can't chdir to new root"); + return -1; + } + } + #ifdef MPE /* Only try to switch if we're running as MANAGER.SYS */ if (geteuid() == 1 && unixd_config.user_id > 1) { @@ -198,6 +222,20 @@ AP_DECLARE(const char *) unixd_set_group(cmd_parms *cmd, void *dummy, return NULL; } +AP_DECLARE(const char *) unixd_set_chroot_dir(cmd_parms *cmd, void *dummy, + const char *arg) +{ + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if (err != NULL) { + return err; + } + if (!ap_is_directory(cmd->pool, arg)) { + return "ChrootDir must be a valid directory"; + } + + unixd_config.chroot_dir = arg; + return NULL; +} AP_DECLARE(void) unixd_pre_config(apr_pool_t *ptemp) { @@ -206,6 +244,8 @@ AP_DECLARE(void) unixd_pre_config(apr_pool_t *ptemp) unixd_config.user_name = DEFAULT_USER; unixd_config.user_id = ap_uname2id(DEFAULT_USER); unixd_config.group_id = ap_gname2id(DEFAULT_GROUP); + + unixd_config.chroot_dir = NULL; /* none */ /* Check for suexec */ unixd_config.suexec_enabled = 0; diff --git a/os/unix/unixd.h b/os/unix/unixd.h index fa62ef68e0..a916f0f50d 100644 --- a/os/unix/unixd.h +++ b/os/unix/unixd.h @@ -76,6 +76,7 @@ typedef struct { uid_t user_id; gid_t group_id; int suexec_enabled; + const char *chroot_dir; } unixd_config_rec; AP_DECLARE_DATA extern unixd_config_rec unixd_config; @@ -85,6 +86,9 @@ AP_DECLARE(const char *) unixd_set_user(cmd_parms *cmd, void *dummy, const char *arg); AP_DECLARE(const char *) unixd_set_group(cmd_parms *cmd, void *dummy, const char *arg); +AP_DECLARE(const char *) unixd_set_chroot_dir(cmd_parms *cmd, void *dummy, + const char *arg); + #if defined(RLIMIT_CPU) || defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_NPROC) || defined(RLIMIT_AS) AP_DECLARE(void) unixd_set_rlimit(cmd_parms *cmd, struct rlimit **plimit, const char *arg, const char * arg2, int type); @@ -115,7 +119,9 @@ AP_DECLARE(apr_status_t) unixd_accept(void **accepted, ap_listen_rec *lr, apr_po AP_INIT_TAKE1("User", unixd_set_user, NULL, RSRC_CONF, \ "Effective user id for this server"), \ AP_INIT_TAKE1("Group", unixd_set_group, NULL, RSRC_CONF, \ - "Effective group id for this server") + "Effective group id for this server"), \ +AP_INIT_TAKE1("ChrootDir", unixd_set_chroot_dir, NULL, RSRC_CONF, \ + "The directory to chroot(2) into") #ifdef __cplusplus } -- 2.50.1