1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2015 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include "alloc-util.h"
23 #include "conf-parser.h"
24 #include "nspawn-network.h"
25 #include "nspawn-settings.h"
26 #include "parse-util.h"
27 #include "process-util.h"
28 #include "socket-util.h"
29 #include "string-util.h"
31 #include "user-util.h"
34 int settings_load(FILE *f
, const char *path
, Settings
**ret
) {
35 _cleanup_(settings_freep
) Settings
*s
= NULL
;
41 s
= new0(Settings
, 1);
45 s
->start_mode
= _START_MODE_INVALID
;
46 s
->personality
= PERSONALITY_INVALID
;
47 s
->userns_mode
= _USER_NAMESPACE_MODE_INVALID
;
48 s
->uid_shift
= UID_INVALID
;
49 s
->uid_range
= UID_INVALID
;
52 s
->volatile_mode
= _VOLATILE_MODE_INVALID
;
55 s
->private_network
= -1;
58 r
= config_parse(NULL
, path
, f
,
62 config_item_perf_lookup
, nspawn_gperf_lookup
,
68 /* Make sure that if userns_mode is set, userns_chown is set to something appropriate, and vice versa. Either
69 * both fields shall be initialized or neither. */
70 if (s
->userns_mode
== USER_NAMESPACE_PICK
)
71 s
->userns_chown
= true;
72 else if (s
->userns_mode
!= _USER_NAMESPACE_MODE_INVALID
&& s
->userns_chown
< 0)
73 s
->userns_chown
= false;
75 if (s
->userns_chown
>= 0 && s
->userns_mode
== _USER_NAMESPACE_MODE_INVALID
)
76 s
->userns_mode
= USER_NAMESPACE_NO
;
84 Settings
* settings_free(Settings
*s
) {
89 strv_free(s
->parameters
);
90 strv_free(s
->environment
);
92 free(s
->pivot_root_new
);
93 free(s
->pivot_root_old
);
94 free(s
->working_directory
);
95 strv_free(s
->syscall_whitelist
);
96 strv_free(s
->syscall_blacklist
);
98 strv_free(s
->network_interfaces
);
99 strv_free(s
->network_macvlan
);
100 strv_free(s
->network_ipvlan
);
101 strv_free(s
->network_veth_extra
);
102 free(s
->network_bridge
);
103 free(s
->network_zone
);
104 expose_port_free_all(s
->expose_ports
);
106 custom_mount_free_all(s
->custom_mounts
, s
->n_custom_mounts
);
110 bool settings_private_network(Settings
*s
) {
114 s
->private_network
> 0 ||
115 s
->network_veth
> 0 ||
118 s
->network_interfaces
||
119 s
->network_macvlan
||
121 s
->network_veth_extra
;
124 bool settings_network_veth(Settings
*s
) {
128 s
->network_veth
> 0 ||
133 DEFINE_CONFIG_PARSE_ENUM(config_parse_volatile_mode
, volatile_mode
, VolatileMode
, "Failed to parse volatile mode");
135 int config_parse_expose_port(
137 const char *filename
,
140 unsigned section_line
,
154 r
= expose_port_parse(&s
->expose_ports
, rvalue
);
156 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Duplicate port specification, ignoring: %s", rvalue
);
160 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse host port %s: %m", rvalue
);
167 int config_parse_capability(
169 const char *filename
,
172 unsigned section_line
,
179 uint64_t u
= 0, *result
= data
;
187 _cleanup_free_
char *word
= NULL
;
190 r
= extract_first_word(&rvalue
, &word
, NULL
, 0);
192 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract capability string, ignoring: %s", rvalue
);
198 cap
= capability_from_name(word
);
200 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse capability, ignoring: %s", word
);
204 u
|= UINT64_C(1) << cap
;
214 int config_parse_id128(
216 const char *filename
,
219 unsigned section_line
,
226 sd_id128_t t
, *result
= data
;
233 r
= sd_id128_from_string(rvalue
, &t
);
235 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse 128bit ID/UUID, ignoring: %s", rvalue
);
243 int config_parse_pivot_root(
245 const char *filename
,
248 unsigned section_line
,
255 Settings
*settings
= data
;
262 r
= pivot_root_parse(&settings
->pivot_root_new
, &settings
->pivot_root_old
, rvalue
);
264 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid pivot root mount specification %s: %m", rvalue
);
271 int config_parse_bind(
273 const char *filename
,
276 unsigned section_line
,
283 Settings
*settings
= data
;
290 r
= bind_mount_parse(&settings
->custom_mounts
, &settings
->n_custom_mounts
, rvalue
, ltype
);
292 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid bind mount specification %s: %m", rvalue
);
299 int config_parse_tmpfs(
301 const char *filename
,
304 unsigned section_line
,
311 Settings
*settings
= data
;
318 r
= tmpfs_mount_parse(&settings
->custom_mounts
, &settings
->n_custom_mounts
, rvalue
);
320 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid temporary file system specification %s: %m", rvalue
);
327 int config_parse_overlay(
329 const char *filename
,
332 unsigned section_line
,
339 Settings
*settings
= data
;
346 r
= overlay_mount_parse(&settings
->custom_mounts
, &settings
->n_custom_mounts
, rvalue
, ltype
);
348 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid overlay file system specification %s, ignoring: %m", rvalue
);
353 int config_parse_veth_extra(
355 const char *filename
,
358 unsigned section_line
,
365 Settings
*settings
= data
;
372 r
= veth_extra_parse(&settings
->network_veth_extra
, rvalue
);
374 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Invalid extra virtual Ethernet link specification %s: %m", rvalue
);
381 int config_parse_network_zone(
383 const char *filename
,
386 unsigned section_line
,
393 Settings
*settings
= data
;
394 _cleanup_free_
char *j
= NULL
;
400 j
= strappend("vz-", rvalue
);
401 if (!ifname_valid(j
)) {
402 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid network zone name %s, ignoring: %m", rvalue
);
406 free(settings
->network_zone
);
407 settings
->network_zone
= j
;
413 int config_parse_boot(
415 const char *filename
,
418 unsigned section_line
,
425 Settings
*settings
= data
;
432 r
= parse_boolean(rvalue
);
434 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse Boot= parameter %s, ignoring: %m", rvalue
);
439 if (settings
->start_mode
== START_PID2
)
442 settings
->start_mode
= START_BOOT
;
444 if (settings
->start_mode
== START_BOOT
)
447 if (settings
->start_mode
< 0)
448 settings
->start_mode
= START_PID1
;
454 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Conflicting Boot= or ProcessTwo= setting found. Ignoring.");
458 int config_parse_pid2(
460 const char *filename
,
463 unsigned section_line
,
470 Settings
*settings
= data
;
477 r
= parse_boolean(rvalue
);
479 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse ProcessTwo= parameter %s, ignoring: %m", rvalue
);
484 if (settings
->start_mode
== START_BOOT
)
487 settings
->start_mode
= START_PID2
;
489 if (settings
->start_mode
== START_PID2
)
492 if (settings
->start_mode
< 0)
493 settings
->start_mode
= START_PID1
;
499 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Conflicting Boot= or ProcessTwo= setting found. Ignoring.");
503 int config_parse_private_users(
505 const char *filename
,
508 unsigned section_line
,
515 Settings
*settings
= data
;
522 r
= parse_boolean(rvalue
);
524 /* no: User namespacing off */
525 settings
->userns_mode
= USER_NAMESPACE_NO
;
526 settings
->uid_shift
= UID_INVALID
;
527 settings
->uid_range
= UINT32_C(0x10000);
529 /* yes: User namespacing on, UID range is read from root dir */
530 settings
->userns_mode
= USER_NAMESPACE_FIXED
;
531 settings
->uid_shift
= UID_INVALID
;
532 settings
->uid_range
= UINT32_C(0x10000);
533 } else if (streq(rvalue
, "pick")) {
534 /* pick: User namespacing on, UID range is picked randomly */
535 settings
->userns_mode
= USER_NAMESPACE_PICK
;
536 settings
->uid_shift
= UID_INVALID
;
537 settings
->uid_range
= UINT32_C(0x10000);
539 const char *range
, *shift
;
542 /* anything else: User namespacing on, UID range is explicitly configured */
544 range
= strchr(rvalue
, ':');
546 shift
= strndupa(rvalue
, range
- rvalue
);
549 r
= safe_atou32(range
, &rn
);
550 if (r
< 0 || rn
<= 0) {
551 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "UID/GID range invalid, ignoring: %s", range
);
556 rn
= UINT32_C(0x10000);
559 r
= parse_uid(shift
, &sh
);
561 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "UID/GID shift invalid, ignoring: %s", range
);
565 settings
->userns_mode
= USER_NAMESPACE_FIXED
;
566 settings
->uid_shift
= sh
;
567 settings
->uid_range
= rn
;
573 int config_parse_syscall_filter(
575 const char *filename
,
578 unsigned section_line
,
585 Settings
*settings
= data
;
594 negative
= rvalue
[0] == '~';
595 items
= negative
? rvalue
+ 1 : rvalue
;
598 _cleanup_free_
char *word
= NULL
;
600 r
= extract_first_word(&items
, &word
, NULL
, 0);
606 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse SystemCallFilter= parameter %s, ignoring: %m", rvalue
);
611 r
= strv_extend(&settings
->syscall_blacklist
, word
);
613 r
= strv_extend(&settings
->syscall_whitelist
, word
);