Use paths specified from environment variables for /etc configuration files
Some configuration files that need updates are directly under in /etc. To update them atomically, we need write access to /etc. For Ubuntu Core this is an issue as /etc is not writable. Only a selection of subdirectories can be writable. The general solution is symlinks or bind mounts to writable places. But for atomic writes in /etc, that does not work. So Ubuntu has had a patch for that that did not age well. Instead we would like to introduce some environment variables for alternate paths. * SYSTEMD_ETC_HOSTNAME: /etc/hostname * SYSTEMD_ETC_MACHINE_INFO: /etc/machine-info * SYSTEMD_ETC_LOCALTIME: /etc/localtime * SYSTEMD_ETC_LOCALE_CONF: /etc/locale.conf * SYSTEMD_ETC_VCONSOLE_CONF: /etc/vconsole.conf * SYSTEMD_ETC_ADJTIME: /etc/adjtime While it is for now expected that there is a symlink from the standard, we still try to read them from that alternate path. This is important for `/etc/localtime`, which is a symlink, so we cannot have an indirect symlink or bind mount for it. Since machine-id is typically written only once and not updated. This commit does not cover it. An initrd can properly create it and bind mount it.
This commit is contained in:
committed by
Lennart Poettering
parent
fa34fda2eb
commit
0dc39dffbd
@@ -0,0 +1,36 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "env-file.h"
|
||||
#include "env-file-label.h"
|
||||
#include "locale-setup.h"
|
||||
#include "selinux-util.h"
|
||||
|
||||
int write_env_file_label(int dir_fd, const char *fname, char **headers, char **l) {
|
||||
int r;
|
||||
|
||||
r = mac_selinux_create_file_prepare(fname, S_IFREG);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = write_env_file(dir_fd, fname, headers, l);
|
||||
|
||||
mac_selinux_create_file_clear();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int write_vconsole_conf_label(char **l) {
|
||||
int r;
|
||||
|
||||
r = mac_selinux_create_file_prepare(etc_vconsole_conf(), S_IFREG);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = write_vconsole_conf(AT_FDCWD, etc_vconsole_conf(), l);
|
||||
|
||||
mac_selinux_create_file_clear();
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -139,7 +139,7 @@ int read_etc_hostname(const char *path, bool substitute_wildcards, char **ret) {
|
||||
assert(ret);
|
||||
|
||||
if (!path)
|
||||
path = "/etc/hostname";
|
||||
path = etc_hostname();
|
||||
|
||||
f = fopen(path, "re");
|
||||
if (!f)
|
||||
|
||||
@@ -67,7 +67,7 @@ static int locale_context_load_conf(LocaleContext *c, LocaleLoadFlag flag) {
|
||||
if (!FLAGS_SET(flag, LOCALE_LOAD_LOCALE_CONF))
|
||||
return 0;
|
||||
|
||||
fd = RET_NERRNO(open("/etc/locale.conf", O_CLOEXEC | O_PATH));
|
||||
fd = RET_NERRNO(open(etc_locale_conf(), O_CLOEXEC | O_PATH));
|
||||
if (fd == -ENOENT)
|
||||
return 0;
|
||||
if (fd < 0)
|
||||
@@ -83,7 +83,7 @@ static int locale_context_load_conf(LocaleContext *c, LocaleLoadFlag flag) {
|
||||
c->st = st;
|
||||
locale_context_clear(c);
|
||||
|
||||
r = parse_env_file_fd(fd, "/etc/locale.conf",
|
||||
r = parse_env_file_fd(fd, etc_locale_conf(),
|
||||
"LANG", &c->locale[VARIABLE_LANG],
|
||||
"LANGUAGE", &c->locale[VARIABLE_LANGUAGE],
|
||||
"LC_CTYPE", &c->locale[VARIABLE_LC_CTYPE],
|
||||
@@ -199,7 +199,7 @@ int locale_context_save(LocaleContext *c, char ***ret_set, char ***ret_unset) {
|
||||
return r;
|
||||
|
||||
if (strv_isempty(set)) {
|
||||
if (unlink("/etc/locale.conf") < 0)
|
||||
if (unlink(etc_locale_conf()) < 0)
|
||||
return errno == ENOENT ? 0 : -errno;
|
||||
|
||||
c->st = (struct stat) {};
|
||||
@@ -213,14 +213,14 @@ int locale_context_save(LocaleContext *c, char ***ret_set, char ***ret_unset) {
|
||||
|
||||
r = write_env_file(
|
||||
AT_FDCWD,
|
||||
"/etc/locale.conf",
|
||||
etc_locale_conf(),
|
||||
/* headers= */ NULL,
|
||||
set,
|
||||
WRITE_ENV_FILE_LABEL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (stat("/etc/locale.conf", &c->st) < 0)
|
||||
if (stat(etc_locale_conf(), &c->st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (ret_set)
|
||||
@@ -300,3 +300,21 @@ int locale_setup(char ***environment) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* etc_locale_conf(void) {
|
||||
static const char *cached = NULL;
|
||||
|
||||
if (!cached)
|
||||
cached = secure_getenv("SYSTEMD_ETC_LOCALE_CONF") ?: "/etc/locale.conf";
|
||||
|
||||
return cached;
|
||||
}
|
||||
|
||||
const char* etc_vconsole_conf(void) {
|
||||
static const char *cached = NULL;
|
||||
|
||||
if (!cached)
|
||||
cached = secure_getenv("SYSTEMD_ETC_VCONSOLE_CONF") ?: "/etc/vconsole.conf";
|
||||
|
||||
return cached;
|
||||
}
|
||||
|
||||
@@ -28,3 +28,6 @@ void locale_context_take(LocaleContext *c, char *l[_VARIABLE_LC_MAX]);
|
||||
bool locale_context_equal(const LocaleContext *c, char *l[_VARIABLE_LC_MAX]);
|
||||
|
||||
int locale_setup(char ***environment);
|
||||
|
||||
const char* etc_locale_conf(void);
|
||||
const char* etc_vconsole_conf(void);
|
||||
|
||||
Reference in New Issue
Block a user