On Fri, Sep 28, 2018 at 11:22:22AM +0100, Joe Orton wrote: > Example users are the mod_dav_fs lock database, mod_md's MD data store. > With an API & default, these can have hard-coded default paths so the > modules work without needing configuration. The proxy cache root could > count here too.
FWIW, part of the motivation here is being able to have a common security policy for this kind of data, e.g. for SELinux. When modules like mod_md/mod_dav want to drop data at $Root/$Random_Name it is hard/impossible to have SELinux policy which allows modules to work by default. If we have three categories of data separated into three directories: - run-time data: root-writable, temporary, readable by unprivileged children - log data: root-writable, *append-only* data (open fails w/o O_APPEND) - state data: unprivileged children have random access read/write we can have SELinux policy which "just works", without needing custom policy rules for mod_dav, and for mod_md, etc etc. Two patches attached: a) PoC implementation of StateDir/ap_state_dir_relative() b) patches showing how this can be used in modules/. Note this does move the hard-coded default MdStoreDir for 2.5.x I'll commit later in the week if there is no feedback. Regards, Joe
Index: Makefile.in =================================================================== --- Makefile.in (revision 1842598) +++ Makefile.in (working copy) @@ -218,6 +218,7 @@ install-other: @test -d $(DESTDIR)$(logfiledir) || $(MKINSTALLDIRS) $(DESTDIR)$(logfiledir) @test -d $(DESTDIR)$(runtimedir) || $(MKINSTALLDIRS) $(DESTDIR)$(runtimedir) + @test -d $(DESTDIR)$(statedir) || $(MKINSTALLDIRS) $(DESTDIR)$(statedir) @for ext in dll x; do \ file=apachecore.$$ext; \ if test -f $$file; then \ Index: acinclude.m4 =================================================================== --- acinclude.m4 (revision 1842598) +++ acinclude.m4 (working copy) @@ -45,7 +45,7 @@ APACHE_SUBST(installbuilddir) APACHE_SUBST(runtimedir) APACHE_SUBST(proxycachedir) - APACHE_SUBST(davlockdb) + APACHE_SUBST(statedir) APACHE_SUBST(other_targets) APACHE_SUBST(progname) APACHE_SUBST(prefix) @@ -876,7 +876,7 @@ APACHE_SUBST_EXPANDED_ARG(runtimedir) APACHE_SUBST_EXPANDED_ARG(logfiledir) APACHE_SUBST_EXPANDED_ARG(proxycachedir) - APACHE_SUBST_EXPANDED_ARG(davlockdb) + APACHE_SUBST_EXPANDED_ARG(statedir) ]) dnl Index: config.layout =================================================================== --- config.layout (revision 1842598) +++ config.layout (working copy) @@ -29,6 +29,7 @@ includedir: ${prefix}/include localstatedir: ${prefix} runtimedir: ${localstatedir}/logs + statedir: ${localstatedir}/state logfiledir: ${localstatedir}/logs proxycachedir: ${localstatedir}/proxy </Layout> @@ -54,6 +55,7 @@ includedir: ${prefix}/include+ localstatedir: ${prefix}/var+ runtimedir: ${localstatedir}/run + statedir: ${localstatedir}/state logfiledir: ${localstatedir}/log proxycachedir: ${localstatedir}/proxy </Layout> @@ -78,6 +80,7 @@ includedir: /System/Library/Frameworks/Apache.framework/Versions/2.0/Headers localstatedir: /var runtimedir: ${prefix}/Logs + statedir: ${prefix}/State logfiledir: ${prefix}/Logs proxycachedir: ${prefix}/ProxyCache </Layout> @@ -102,6 +105,7 @@ includedir: ${prefix}/include+ localstatedir: /var runtimedir: ${localstatedir}/run + statedir: ${localstatedir}/state logfiledir: ${localstatedir}/log+ proxycachedir: ${runtimedir}/proxy </Layout> @@ -126,6 +130,7 @@ includedir: ${prefix}/include/apache localstatedir: /var runtimedir: ${localstatedir}/run + statedir: ${localstatedir}/lib/httpd logfiledir: ${localstatedir}/log/httpd proxycachedir: ${localstatedir}/cache/httpd </Layout> @@ -151,6 +156,7 @@ includedir: ${prefix}/include/httpd runtimedir: /run/httpd logfiledir: ${localstatedir}/log/httpd + statedir: ${localstatedir}/lib/httpd proxycachedir: ${localstatedir}/cache/httpd/proxy </Layout> @@ -175,6 +181,7 @@ localstatedir: /var${prefix} runtimedir: ${localstatedir}/run logfiledir: ${localstatedir}/logs + statedir: ${localstatedir}/state proxycachedir: ${localstatedir}/proxy </Layout> @@ -197,6 +204,7 @@ cgidir: ${datadir}/cgi-bin includedir: ${prefix}/include/apache localstatedir: /var/lib/httpd + statedir: /var/lib/httpd runtimedir: /var/run logfiledir: /var/log/httpd proxycachedir: /var/cache/httpd @@ -223,6 +231,7 @@ localstatedir: /var runtimedir: ${localstatedir}/run logfiledir: ${localstatedir}/log/httpd + statedir: ${prefix}/state proxycachedir: ${localstatedir}/proxy </Layout> @@ -246,6 +255,7 @@ includedir: ${exec_prefix}/include localstatedir: ${prefix} runtimedir: /var/run + statedir: ${datadir}/state logfiledir: ${datadir}/logs proxycachedir: ${datadir}/proxy </Layout> @@ -271,6 +281,7 @@ localstatedir: ${prefix} runtimedir: ${prefix}/logs logfiledir: ${prefix}/logs + statedir: ${prefix}/state proxycachedir: ${prefix}/proxy </Layout> @@ -315,6 +326,7 @@ cgidir: ${prefix}/usr/lib/cgi-bin includedir: ${exec_prefix}/include/apache2 localstatedir: ${prefix}/var/lock/apache2 + statedir: ${prefix}/var/lib/apache2 runtimedir: ${prefix}/var/run/apache2 logfiledir: ${prefix}/var/log/apache2 proxycachedir: ${prefix}/var/cache/apache2/proxy @@ -343,6 +355,7 @@ manualdir: ${datadir}/manual cgidir: ${datadir}/cgi-bin runtimedir: ${localstatedir}/run + runtimedir: ${localstatedir}/lib/httpd logfiledir: ${localstatedir}/log/httpd proxycachedir: ${localstatedir}/cache/httpd/cache-root </Layout> @@ -366,6 +379,7 @@ manualdir: ${prefix}/manual includedir: ${prefix}/include localstatedir: /var/httpd + statedir: ${localstatedir}/state runtimedir: ${localstatedir}/run logfiledir: ${localstatedir}/logs proxycachedir: ${localstatedir}/proxy @@ -391,6 +405,7 @@ includedir: ${prefix}/include/httpd localstatedir: /var runtimedir: ${localstatedir}/run/httpd + statedir: ${localstatedir}/lib/httpd logfiledir: ${localstatedir}/log/httpd proxycachedir: ${localstatedir}/cache/httpd </Layout> Index: configure.in =================================================================== --- configure.in (revision 1842598) +++ configure.in (working copy) @@ -41,7 +41,7 @@ AC_PREFIX_DEFAULT(/usr/local/apache2) dnl Get the layout here, so we can pass the required variables to apr -APR_ENABLE_LAYOUT(Apache, [errordir iconsdir htdocsdir cgidir]) +APR_ENABLE_LAYOUT(Apache, [errordir iconsdir htdocsdir cgidir statedir]) dnl reparse the configure arguments. APR_PARSE_ARGUMENTS Index: include/ap_config_layout.h.in =================================================================== --- include/ap_config_layout.h.in (revision 1842598) +++ include/ap_config_layout.h.in (working copy) @@ -60,7 +60,7 @@ #define DEFAULT_REL_LOGFILEDIR "@rel_logfiledir@" #define DEFAULT_EXP_PROXYCACHEDIR "@exp_proxycachedir@" #define DEFAULT_REL_PROXYCACHEDIR "@rel_proxycachedir@" -#define DEFAULT_EXP_DAVLOCKDB "@exp_davlockdb@" -#define DEFAULT_REL_DAVLOCKDB "@rel_davlockdb@" +#define DEFAULT_EXP_STATEDIR "@exp_statedir@" +#define DEFAULT_REL_STATEDIR "@rel_statedir@" #endif /* AP_CONFIG_LAYOUT_H */ Index: include/ap_mmn.h =================================================================== --- include/ap_mmn.h (revision 1842598) +++ include/ap_mmn.h (working copy) @@ -607,6 +607,7 @@ * in ap_filter_t replace pending/bb/deferred_pool * fields by struct ap_filter_private *priv * 20180906.1 (2.5.1-dev) Don't export ap_filter_recycle() anymore + * 20180906.2 (2.5.1-dev) Add ap_state_dir_relative() */ #define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */ @@ -614,7 +615,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20180906 #endif -#define MODULE_MAGIC_NUMBER_MINOR 1 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 2 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a Index: include/http_config.h =================================================================== --- include/http_config.h (revision 1842598) +++ include/http_config.h (working copy) @@ -760,6 +760,14 @@ */ AP_DECLARE(char *) ap_runtime_dir_relative(apr_pool_t *p, const char *fname); +/** + * Compute the name of a persistent state file (e.g. a database or + * long-lived cache) relative to the appropriate state directory. + * Absolute paths are returned as-is. The state directory is + * configured via the DefaultStateDir directive or at build time. + */ +AP_DECLARE(char *) ap_state_dir_relative(apr_pool_t *p, const char *fname); + /* Finally, the hook for dynamically loading modules in... */ /** Index: modules/dav/fs/mod_dav_fs.c =================================================================== Index: modules/md/mod_md_config.c =================================================================== Index: server/core.c =================================================================== --- server/core.c (revision 1842598) +++ server/core.c (working copy) @@ -148,6 +148,8 @@ AP_DECLARE_DATA int ap_run_mode = AP_SQ_RM_UNKNOWN; AP_DECLARE_DATA int ap_config_generation = 0; +static const char *core_state_dir; + typedef struct { apr_ipsubnet_t *subnet; struct ap_logconf log; @@ -3275,6 +3277,24 @@ return NULL; } +static const char *set_state_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 ((apr_filepath_merge((char**)&core_state_dir, NULL, + ap_server_root_relative(cmd->temp_pool, arg), + APR_FILEPATH_TRUENAME, cmd->pool) != APR_SUCCESS) + || !ap_is_directory(cmd->temp_pool, core_state_dir)) { + return "DefaultStateDir must be a valid directory, absolute or relative to ServerRoot"; + } + + return NULL; +} + static const char *set_timeout(cmd_parms *cmd, void *dummy, const char *arg) { const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); @@ -4724,6 +4744,8 @@ "Common directory of server-related files (logs, confs, etc.)"), AP_INIT_TAKE1("DefaultRuntimeDir", set_runtime_dir, NULL, RSRC_CONF | EXEC_ON_READ, "Common directory for run-time files (shared memory, locks, etc.)"), +AP_INIT_TAKE1("DefaultStateDir", set_state_dir, NULL, RSRC_CONF | EXEC_ON_READ, + "Common directory for persistent state (databases, long-lived caches, etc.)"), AP_INIT_TAKE12("ErrorLog", set_errorlog, (void *)APR_OFFSETOF(server_rec, error_fname), RSRC_CONF, "The filename of the error log"), @@ -5557,6 +5579,28 @@ } } +AP_DECLARE(char *) ap_state_dir_relative(apr_pool_t *p, const char *file) +{ + char *newpath = NULL; + apr_status_t rv; + const char *state_dir; + + state_dir = core_state_dir + ? core_state_dir + : ap_server_root_relative(p, DEFAULT_REL_STATEDIR); + + rv = apr_filepath_merge(&newpath, state_dir, file, APR_FILEPATH_TRUENAME, p); + if (newpath && (rv == APR_SUCCESS || APR_STATUS_IS_EPATHWILD(rv) + || APR_STATUS_IS_ENOENT(rv) + || APR_STATUS_IS_ENOTDIR(rv))) { + return newpath; + } + else { + return NULL; + } +} + + #if !USE_APR_CRYPTO_PRNG static apr_random_t *rng = NULL; #if APR_HAS_THREADS
--- modules/dav/fs/mod_dav_fs.c (revision 1842598) +++ modules/dav/fs/mod_dav_fs.c (working copy) @@ -32,6 +32,10 @@ extern module AP_MODULE_DECLARE_DATA dav_fs_module; +#ifndef DEFAULT_DAV_LOCKDB +#define DEFAULT_DAV_LOCKDB "davlockdb" +#endif + const char *dav_get_lockdb_path(const request_rec *r) { dav_fs_server_conf *conf; @@ -43,13 +47,9 @@ static void *dav_fs_create_server_config(apr_pool_t *p, server_rec *s) { dav_fs_server_conf *conf = apr_pcalloc(p, sizeof(dav_fs_server_conf)); -#ifdef DEFAULT_EXP_DAVLOCKDB - conf->lockdb_path = DEFAULT_EXP_DAVLOCKDB; - if (*conf->lockdb_path == '\0') { - conf->lockdb_path = NULL; - } -#endif + conf->lockdb_path = ap_state_dir_relative(p, DEFAULT_DAV_LOCKDB); + return conf; } --- modules/md/mod_md_config.c (revision 1842598) +++ modules/md/mod_md_config.c (working copy) @@ -54,10 +54,18 @@ #define DEF_VAL (-1) +#ifndef MD_DEFAULT_BASE_DIR +#define MD_DEFAULT_BASE_DIR "md" +#endif + /* Default settings for the global conf */ static md_mod_conf_t defmc = { NULL, - "md", +#if AP_MODULE_MAGIC_AT_LEAST(20180906, 2) + NULL, /* apply default state-dir-relative */ +#else + MD_DEFAULT_BASE_DIR, +#endif NULL, NULL, 80, @@ -113,6 +121,10 @@ mod_md_config->mds = apr_array_make(pool, 5, sizeof(const md_t *)); mod_md_config->unused_names = apr_array_make(pool, 5, sizeof(const md_t *)); +#if AP_MODULE_MAGIC_AT_LEAST(20180906, 2) + mod_md_config->base_dir = ap_state_dir_relative(pool, MD_DEFAULT_BASE_DIR); +#endif + apr_pool_cleanup_register(pool, NULL, cleanup_mod_config, apr_pool_cleanup_null); }