nspawn: split out merging of settings object

Let's separate the loading of the settings object and the merging into
our arg_xyz fields into two.

This will become particularly useful when we eventually are able to load
settings from OCI runtime files in addition to .nspawn files.
This commit is contained in:
Lennart Poettering 2018-05-07 21:57:00 +02:00
parent d107bb7d63
commit 5d9614077d

View file

@ -3174,12 +3174,212 @@ static int setup_sd_notify_parent(sd_event *event, int fd, pid_t *inner_child_pi
return 0;
}
static int merge_settings(Settings *settings, const char *path) {
int rl;
assert(settings);
assert(path);
/* Copy over bits from the settings, unless they have been explicitly masked by command line switches. Note
* that this steals the fields of the Settings* structure, and hence modifies it. */
if ((arg_settings_mask & SETTING_START_MODE) == 0 &&
settings->start_mode >= 0) {
arg_start_mode = settings->start_mode;
strv_free_and_replace(arg_parameters, settings->parameters);
}
if ((arg_settings_mask & SETTING_PIVOT_ROOT) == 0 &&
settings->pivot_root_new) {
free_and_replace(arg_pivot_root_new, settings->pivot_root_new);
free_and_replace(arg_pivot_root_old, settings->pivot_root_old);
}
if ((arg_settings_mask & SETTING_WORKING_DIRECTORY) == 0 &&
settings->working_directory)
free_and_replace(arg_chdir, settings->working_directory);
if ((arg_settings_mask & SETTING_ENVIRONMENT) == 0 &&
settings->environment)
strv_free_and_replace(arg_setenv, settings->environment);
if ((arg_settings_mask & SETTING_USER) == 0 &&
settings->user)
free_and_replace(arg_user, settings->user);
if ((arg_settings_mask & SETTING_CAPABILITY) == 0) {
uint64_t plus;
plus = settings->capability;
if (settings_private_network(settings))
plus |= (1ULL << CAP_NET_ADMIN);
if (!arg_settings_trusted && plus != 0) {
if (settings->capability != 0)
log_warning("Ignoring Capability= setting, file %s is not trusted.", path);
} else
arg_caps_retain |= plus;
arg_caps_retain &= ~settings->drop_capability;
}
if ((arg_settings_mask & SETTING_KILL_SIGNAL) == 0 &&
settings->kill_signal > 0)
arg_kill_signal = settings->kill_signal;
if ((arg_settings_mask & SETTING_PERSONALITY) == 0 &&
settings->personality != PERSONALITY_INVALID)
arg_personality = settings->personality;
if ((arg_settings_mask & SETTING_MACHINE_ID) == 0 &&
!sd_id128_is_null(settings->machine_id)) {
if (!arg_settings_trusted)
log_warning("Ignoring MachineID= setting, file %s is not trusted.", path);
else
arg_uuid = settings->machine_id;
}
if ((arg_settings_mask & SETTING_READ_ONLY) == 0 &&
settings->read_only >= 0)
arg_read_only = settings->read_only;
if ((arg_settings_mask & SETTING_VOLATILE_MODE) == 0 &&
settings->volatile_mode != _VOLATILE_MODE_INVALID)
arg_volatile_mode = settings->volatile_mode;
if ((arg_settings_mask & SETTING_CUSTOM_MOUNTS) == 0 &&
settings->n_custom_mounts > 0) {
if (!arg_settings_trusted)
log_warning("Ignoring TemporaryFileSystem=, Bind= and BindReadOnly= settings, file %s is not trusted.", path);
else {
custom_mount_free_all(arg_custom_mounts, arg_n_custom_mounts);
arg_custom_mounts = TAKE_PTR(settings->custom_mounts);
arg_n_custom_mounts = settings->n_custom_mounts;
settings->n_custom_mounts = 0;
}
}
if ((arg_settings_mask & SETTING_NETWORK) == 0 &&
(settings->private_network >= 0 ||
settings->network_veth >= 0 ||
settings->network_bridge ||
settings->network_zone ||
settings->network_interfaces ||
settings->network_macvlan ||
settings->network_ipvlan ||
settings->network_veth_extra)) {
if (!arg_settings_trusted)
log_warning("Ignoring network settings, file %s is not trusted.", path);
else {
arg_network_veth = settings_network_veth(settings);
arg_private_network = settings_private_network(settings);
strv_free_and_replace(arg_network_interfaces, settings->network_interfaces);
strv_free_and_replace(arg_network_macvlan, settings->network_macvlan);
strv_free_and_replace(arg_network_ipvlan, settings->network_ipvlan);
strv_free_and_replace(arg_network_veth_extra, settings->network_veth_extra);
free_and_replace(arg_network_bridge, settings->network_bridge);
free_and_replace(arg_network_zone, settings->network_zone);
}
}
if ((arg_settings_mask & SETTING_EXPOSE_PORTS) == 0 &&
settings->expose_ports) {
if (!arg_settings_trusted)
log_warning("Ignoring Port= setting, file %s is not trusted.", path);
else {
expose_port_free_all(arg_expose_ports);
arg_expose_ports = TAKE_PTR(settings->expose_ports);
}
}
if ((arg_settings_mask & SETTING_USERNS) == 0 &&
settings->userns_mode != _USER_NAMESPACE_MODE_INVALID) {
if (!arg_settings_trusted)
log_warning("Ignoring PrivateUsers= and PrivateUsersChown= settings, file %s is not trusted.", path);
else {
arg_userns_mode = settings->userns_mode;
arg_uid_shift = settings->uid_shift;
arg_uid_range = settings->uid_range;
arg_userns_chown = settings->userns_chown;
}
}
if ((arg_settings_mask & SETTING_NOTIFY_READY) == 0)
arg_notify_ready = settings->notify_ready;
if ((arg_settings_mask & SETTING_SYSCALL_FILTER) == 0) {
if (!arg_settings_trusted && !strv_isempty(arg_syscall_whitelist))
log_warning("Ignoring SystemCallFilter= settings, file %s is not trusted.", path);
else {
strv_free_and_replace(arg_syscall_whitelist, settings->syscall_whitelist);
strv_free_and_replace(arg_syscall_blacklist, settings->syscall_blacklist);
}
}
for (rl = 0; rl < _RLIMIT_MAX; rl ++) {
if ((arg_settings_mask & (SETTING_RLIMIT_FIRST << rl)))
continue;
if (!settings->rlimit[rl])
continue;
if (!arg_settings_trusted) {
log_warning("Ignoring Limit%s= setting, file '%s' is not trusted.", rlimit_to_string(rl), path);
continue;
}
free_and_replace(arg_rlimit[rl], settings->rlimit[rl]);
}
if ((arg_settings_mask & SETTING_HOSTNAME) == 0 &&
settings->hostname)
free_and_replace(arg_hostname, settings->hostname);
if ((arg_settings_mask & SETTING_NO_NEW_PRIVILEGES) == 0 &&
settings->no_new_privileges >= 0)
arg_no_new_privileges = settings->no_new_privileges;
if ((arg_settings_mask & SETTING_OOM_SCORE_ADJUST) == 0 &&
settings->oom_score_adjust_set) {
if (!arg_settings_trusted)
log_warning("Ignoring OOMScoreAdjust= setting, file '%s' is not trusted.", path);
else {
arg_oom_score_adjust = settings->oom_score_adjust;
arg_oom_score_adjust_set = true;
}
}
if ((arg_settings_mask & SETTING_CPU_AFFINITY) == 0 &&
settings->cpuset) {
if (!arg_settings_trusted)
log_warning("Ignoring CPUAffinity= setting, file '%s' is not trusted.", path);
else {
if (arg_cpuset)
CPU_FREE(arg_cpuset);
arg_cpuset = TAKE_PTR(settings->cpuset);
arg_cpuset_ncpus = settings->cpuset_ncpus;
}
}
return 0;
}
static int load_settings(void) {
_cleanup_(settings_freep) Settings *settings = NULL;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *p = NULL;
const char *fn, *i;
int r, rl;
int r;
/* If all settings are masked, there's no point in looking for
* the settings file */
@ -3245,198 +3445,7 @@ static int load_settings(void) {
if (r < 0)
return r;
/* Copy over bits from the settings, unless they have been
* explicitly masked by command line switches. */
if ((arg_settings_mask & SETTING_START_MODE) == 0 &&
settings->start_mode >= 0) {
arg_start_mode = settings->start_mode;
strv_free_and_replace(arg_parameters, settings->parameters);
}
if ((arg_settings_mask & SETTING_PIVOT_ROOT) == 0 &&
settings->pivot_root_new) {
free_and_replace(arg_pivot_root_new, settings->pivot_root_new);
free_and_replace(arg_pivot_root_old, settings->pivot_root_old);
}
if ((arg_settings_mask & SETTING_WORKING_DIRECTORY) == 0 &&
settings->working_directory)
free_and_replace(arg_chdir, settings->working_directory);
if ((arg_settings_mask & SETTING_ENVIRONMENT) == 0 &&
settings->environment)
strv_free_and_replace(arg_setenv, settings->environment);
if ((arg_settings_mask & SETTING_USER) == 0 &&
settings->user)
free_and_replace(arg_user, settings->user);
if ((arg_settings_mask & SETTING_CAPABILITY) == 0) {
uint64_t plus;
plus = settings->capability;
if (settings_private_network(settings))
plus |= (1ULL << CAP_NET_ADMIN);
if (!arg_settings_trusted && plus != 0) {
if (settings->capability != 0)
log_warning("Ignoring Capability= setting, file %s is not trusted.", p);
} else
arg_caps_retain |= plus;
arg_caps_retain &= ~settings->drop_capability;
}
if ((arg_settings_mask & SETTING_KILL_SIGNAL) == 0 &&
settings->kill_signal > 0)
arg_kill_signal = settings->kill_signal;
if ((arg_settings_mask & SETTING_PERSONALITY) == 0 &&
settings->personality != PERSONALITY_INVALID)
arg_personality = settings->personality;
if ((arg_settings_mask & SETTING_MACHINE_ID) == 0 &&
!sd_id128_is_null(settings->machine_id)) {
if (!arg_settings_trusted)
log_warning("Ignoring MachineID= setting, file %s is not trusted.", p);
else
arg_uuid = settings->machine_id;
}
if ((arg_settings_mask & SETTING_READ_ONLY) == 0 &&
settings->read_only >= 0)
arg_read_only = settings->read_only;
if ((arg_settings_mask & SETTING_VOLATILE_MODE) == 0 &&
settings->volatile_mode != _VOLATILE_MODE_INVALID)
arg_volatile_mode = settings->volatile_mode;
if ((arg_settings_mask & SETTING_CUSTOM_MOUNTS) == 0 &&
settings->n_custom_mounts > 0) {
if (!arg_settings_trusted)
log_warning("Ignoring TemporaryFileSystem=, Bind= and BindReadOnly= settings, file %s is not trusted.", p);
else {
custom_mount_free_all(arg_custom_mounts, arg_n_custom_mounts);
arg_custom_mounts = TAKE_PTR(settings->custom_mounts);
arg_n_custom_mounts = settings->n_custom_mounts;
settings->n_custom_mounts = 0;
}
}
if ((arg_settings_mask & SETTING_NETWORK) == 0 &&
(settings->private_network >= 0 ||
settings->network_veth >= 0 ||
settings->network_bridge ||
settings->network_zone ||
settings->network_interfaces ||
settings->network_macvlan ||
settings->network_ipvlan ||
settings->network_veth_extra)) {
if (!arg_settings_trusted)
log_warning("Ignoring network settings, file %s is not trusted.", p);
else {
arg_network_veth = settings_network_veth(settings);
arg_private_network = settings_private_network(settings);
strv_free_and_replace(arg_network_interfaces, settings->network_interfaces);
strv_free_and_replace(arg_network_macvlan, settings->network_macvlan);
strv_free_and_replace(arg_network_ipvlan, settings->network_ipvlan);
strv_free_and_replace(arg_network_veth_extra, settings->network_veth_extra);
free_and_replace(arg_network_bridge, settings->network_bridge);
free_and_replace(arg_network_zone, settings->network_zone);
}
}
if ((arg_settings_mask & SETTING_EXPOSE_PORTS) == 0 &&
settings->expose_ports) {
if (!arg_settings_trusted)
log_warning("Ignoring Port= setting, file %s is not trusted.", p);
else {
expose_port_free_all(arg_expose_ports);
arg_expose_ports = TAKE_PTR(settings->expose_ports);
}
}
if ((arg_settings_mask & SETTING_USERNS) == 0 &&
settings->userns_mode != _USER_NAMESPACE_MODE_INVALID) {
if (!arg_settings_trusted)
log_warning("Ignoring PrivateUsers= and PrivateUsersChown= settings, file %s is not trusted.", p);
else {
arg_userns_mode = settings->userns_mode;
arg_uid_shift = settings->uid_shift;
arg_uid_range = settings->uid_range;
arg_userns_chown = settings->userns_chown;
}
}
if ((arg_settings_mask & SETTING_NOTIFY_READY) == 0)
arg_notify_ready = settings->notify_ready;
if ((arg_settings_mask & SETTING_SYSCALL_FILTER) == 0) {
if (!arg_settings_trusted && !strv_isempty(arg_syscall_whitelist))
log_warning("Ignoring SystemCallFilter= settings, file %s is not trusted.", p);
else {
strv_free_and_replace(arg_syscall_whitelist, settings->syscall_whitelist);
strv_free_and_replace(arg_syscall_blacklist, settings->syscall_blacklist);
}
}
for (rl = 0; rl < _RLIMIT_MAX; rl ++) {
if ((arg_settings_mask & (SETTING_RLIMIT_FIRST << rl)))
continue;
if (!settings->rlimit[rl])
continue;
if (!arg_settings_trusted) {
log_warning("Ignoring Limit%s= setting, file '%s' is not trusted.", rlimit_to_string(rl), p);
continue;
}
free_and_replace(arg_rlimit[rl], settings->rlimit[rl]);
}
if ((arg_settings_mask & SETTING_HOSTNAME) == 0 &&
settings->hostname)
free_and_replace(arg_hostname, settings->hostname);
if ((arg_settings_mask & SETTING_NO_NEW_PRIVILEGES) == 0 &&
settings->no_new_privileges >= 0)
arg_no_new_privileges = settings->no_new_privileges;
if ((arg_settings_mask & SETTING_OOM_SCORE_ADJUST) == 0 &&
settings->oom_score_adjust_set) {
if (!arg_settings_trusted)
log_warning("Ignoring OOMScoreAdjust= setting, file '%s' is not trusted.", p);
else {
arg_oom_score_adjust = settings->oom_score_adjust;
arg_oom_score_adjust_set = true;
}
}
if ((arg_settings_mask & SETTING_CPU_AFFINITY) == 0 &&
settings->cpuset) {
if (!arg_settings_trusted)
log_warning("Ignoring CPUAffinity= setting, file '%s' is not trusted.", p);
else {
if (arg_cpuset)
CPU_FREE(arg_cpuset);
arg_cpuset = TAKE_PTR(settings->cpuset);
arg_cpuset_ncpus = settings->cpuset_ncpus;
}
}
return 0;
return merge_settings(settings, p);
}
static int run(int master,