2 This file is part of systemd.
4 Copyright 2015 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include "alloc-util.h"
22 #include "conf-parser.h"
23 #include "nspawn-network.h"
24 #include "nspawn-settings.h"
25 #include "parse-util.h"
26 #include "process-util.h"
27 #include "socket-util.h"
28 #include "string-util.h"
30 #include "user-util.h"
33 int settings_load(FILE *f
, const char *path
, Settings
**ret
) {
34 _cleanup_(settings_freep
) Settings
*s
= NULL
;
40 s
= new0(Settings
, 1);
44 s
->start_mode
= _START_MODE_INVALID
;
45 s
->personality
= PERSONALITY_INVALID
;
46 s
->userns_mode
= _USER_NAMESPACE_MODE_INVALID
;
47 s
->uid_shift
= UID_INVALID
;
48 s
->uid_range
= UID_INVALID
;
51 s
->volatile_mode
= _VOLATILE_MODE_INVALID
;
54 s
->private_network
= -1;
57 r
= config_parse(NULL
, path
, f
,
61 config_item_perf_lookup
, nspawn_gperf_lookup
,
69 /* Make sure that if userns_mode is set, userns_chown is set to something appropriate, and vice versa. Either
70 * both fields shall be initialized or neither. */
71 if (s
->userns_mode
== USER_NAMESPACE_PICK
)
72 s
->userns_chown
= true;
73 else if (s
->userns_mode
!= _USER_NAMESPACE_MODE_INVALID
&& s
->userns_chown
< 0)
74 s
->userns_chown
= false;
76 if (s
->userns_chown
>= 0 && s
->userns_mode
== _USER_NAMESPACE_MODE_INVALID
)
77 s
->userns_mode
= USER_NAMESPACE_NO
;
85 Settings
* settings_free(Settings
*s
) {
90 strv_free(s
->parameters
);
91 strv_free(s
->environment
);
93 free(s
->pivot_root_new
);
94 free(s
->pivot_root_old
);
95 free(s
->working_directory
);
96 strv_free(s
->syscall_whitelist
);
97 strv_free(s
->syscall_blacklist
);
99 strv_free(s
->network_interfaces
);
100 strv_free(s
->network_macvlan
);
101 strv_free(s
->network_ipvlan
);
102 strv_free(s
->network_veth_extra
);
103 free(s
->network_bridge
);
104 free(s
->network_zone
);
105 expose_port_free_all(s
->expose_ports
);
107 custom_mount_free_all(s
->custom_mounts
, s
->n_custom_mounts
);
111 bool settings_private_network(Settings
*s
) {
115 s
->private_network
> 0 ||
116 s
->network_veth
> 0 ||
119 s
->network_interfaces
||
120 s
->network_macvlan
||
122 s
->network_veth_extra
;
125 bool settings_network_veth(Settings
*s
) {
129 s
->network_veth
> 0 ||
134 DEFINE_CONFIG_PARSE_ENUM(config_parse_volatile_mode
, volatile_mode
, VolatileMode
, "Failed to parse volatile mode");
136 int config_parse_expose_port(
138 const char *filename
,
141 unsigned section_line
,
155 r
= expose_port_parse(&s
->expose_ports
, rvalue
);
157 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Duplicate port specification, ignoring: %s", rvalue
);
161 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse host port %s: %m", rvalue
);
168 int config_parse_capability(
170 const char *filename
,
173 unsigned section_line
,
180 uint64_t u
= 0, *result
= data
;
188 _cleanup_free_
char *word
= NULL
;
191 r
= extract_first_word(&rvalue
, &word
, NULL
, 0);
193 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract capability string, ignoring: %s", rvalue
);
199 cap
= capability_from_name(word
);
201 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse capability, ignoring: %s", word
);
205 u
|= UINT64_C(1) << cap
;
215 int config_parse_id128(
217 const char *filename
,
220 unsigned section_line
,
227 sd_id128_t t
, *result
= data
;
234 r
= sd_id128_from_string(rvalue
, &t
);
236 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse 128bit ID/UUID, ignoring: %s", rvalue
);
244 int config_parse_pivot_root(
246 const char *filename
,
249 unsigned section_line
,
256 Settings
*settings
= data
;
263 r
= pivot_root_parse(&settings
->pivot_root_new
, &settings
->pivot_root_old
, rvalue
);
265 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid pivot root mount specification %s: %m", rvalue
);
272 int config_parse_bind(
274 const char *filename
,
277 unsigned section_line
,
284 Settings
*settings
= data
;
291 r
= bind_mount_parse(&settings
->custom_mounts
, &settings
->n_custom_mounts
, rvalue
, ltype
);
293 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid bind mount specification %s: %m", rvalue
);
300 int config_parse_tmpfs(
302 const char *filename
,
305 unsigned section_line
,
312 Settings
*settings
= data
;
319 r
= tmpfs_mount_parse(&settings
->custom_mounts
, &settings
->n_custom_mounts
, rvalue
);
321 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid temporary file system specification %s: %m", rvalue
);
328 int config_parse_overlay(
330 const char *filename
,
333 unsigned section_line
,
340 Settings
*settings
= data
;
347 r
= overlay_mount_parse(&settings
->custom_mounts
, &settings
->n_custom_mounts
, rvalue
, ltype
);
349 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid overlay file system specification %s, ignoring: %m", rvalue
);
354 int config_parse_veth_extra(
356 const char *filename
,
359 unsigned section_line
,
366 Settings
*settings
= data
;
373 r
= veth_extra_parse(&settings
->network_veth_extra
, rvalue
);
375 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid extra virtual Ethernet link specification %s: %m", rvalue
);
382 int config_parse_network_zone(
384 const char *filename
,
387 unsigned section_line
,
394 Settings
*settings
= data
;
395 _cleanup_free_
char *j
= NULL
;
401 j
= strappend("vz-", rvalue
);
402 if (!ifname_valid(j
)) {
403 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid network zone name %s, ignoring: %m", rvalue
);
407 free(settings
->network_zone
);
408 settings
->network_zone
= j
;
414 int config_parse_boot(
416 const char *filename
,
419 unsigned section_line
,
426 Settings
*settings
= data
;
433 r
= parse_boolean(rvalue
);
435 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse Boot= parameter %s, ignoring: %m", rvalue
);
440 if (settings
->start_mode
== START_PID2
)
443 settings
->start_mode
= START_BOOT
;
445 if (settings
->start_mode
== START_BOOT
)
448 if (settings
->start_mode
< 0)
449 settings
->start_mode
= START_PID1
;
455 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Conflicting Boot= or ProcessTwo= setting found. Ignoring.");
459 int config_parse_pid2(
461 const char *filename
,
464 unsigned section_line
,
471 Settings
*settings
= data
;
478 r
= parse_boolean(rvalue
);
480 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse ProcessTwo= parameter %s, ignoring: %m", rvalue
);
485 if (settings
->start_mode
== START_BOOT
)
488 settings
->start_mode
= START_PID2
;
490 if (settings
->start_mode
== START_PID2
)
493 if (settings
->start_mode
< 0)
494 settings
->start_mode
= START_PID1
;
500 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Conflicting Boot= or ProcessTwo= setting found. Ignoring.");
504 int config_parse_private_users(
506 const char *filename
,
509 unsigned section_line
,
516 Settings
*settings
= data
;
523 r
= parse_boolean(rvalue
);
525 /* no: User namespacing off */
526 settings
->userns_mode
= USER_NAMESPACE_NO
;
527 settings
->uid_shift
= UID_INVALID
;
528 settings
->uid_range
= UINT32_C(0x10000);
530 /* yes: User namespacing on, UID range is read from root dir */
531 settings
->userns_mode
= USER_NAMESPACE_FIXED
;
532 settings
->uid_shift
= UID_INVALID
;
533 settings
->uid_range
= UINT32_C(0x10000);
534 } else if (streq(rvalue
, "pick")) {
535 /* pick: User namespacing on, UID range is picked randomly */
536 settings
->userns_mode
= USER_NAMESPACE_PICK
;
537 settings
->uid_shift
= UID_INVALID
;
538 settings
->uid_range
= UINT32_C(0x10000);
540 const char *range
, *shift
;
543 /* anything else: User namespacing on, UID range is explicitly configured */
545 range
= strchr(rvalue
, ':');
547 shift
= strndupa(rvalue
, range
- rvalue
);
550 r
= safe_atou32(range
, &rn
);
551 if (r
< 0 || rn
<= 0) {
552 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "UID/GID range invalid, ignoring: %s", range
);
557 rn
= UINT32_C(0x10000);
560 r
= parse_uid(shift
, &sh
);
562 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "UID/GID shift invalid, ignoring: %s", range
);
566 settings
->userns_mode
= USER_NAMESPACE_FIXED
;
567 settings
->uid_shift
= sh
;
568 settings
->uid_range
= rn
;
574 int config_parse_syscall_filter(
576 const char *filename
,
579 unsigned section_line
,
586 Settings
*settings
= data
;
595 negative
= rvalue
[0] == '~';
596 items
= negative
? rvalue
+ 1 : rvalue
;
599 _cleanup_free_
char *word
= NULL
;
601 r
= extract_first_word(&items
, &word
, NULL
, 0);
607 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse SystemCallFilter= parameter %s, ignoring: %m", rvalue
);
612 r
= strv_extend(&settings
->syscall_blacklist
, word
);
614 r
= strv_extend(&settings
->syscall_whitelist
, word
);