]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/tmpfiles/tmpfiles.c
tree-wide: fix a couple of typos
[thirdparty/systemd.git] / src / tmpfiles / tmpfiles.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <fnmatch.h>
6 #include <getopt.h>
7 #include <limits.h>
8 #include <linux/fs.h>
9 #include <stdbool.h>
10 #include <stddef.h>
11 #include <stdlib.h>
12 #include <sys/file.h>
13 #include <sys/xattr.h>
14 #include <sysexits.h>
15 #include <time.h>
16 #include <unistd.h>
17
18 #include "sd-path.h"
19
20 #include "acl-util.h"
21 #include "alloc-util.h"
22 #include "btrfs-util.h"
23 #include "build.h"
24 #include "capability-util.h"
25 #include "chase.h"
26 #include "chattr-util.h"
27 #include "conf-files.h"
28 #include "constants.h"
29 #include "copy.h"
30 #include "creds-util.h"
31 #include "devnum-util.h"
32 #include "dirent-util.h"
33 #include "dissect-image.h"
34 #include "env-util.h"
35 #include "errno-util.h"
36 #include "escape.h"
37 #include "fd-util.h"
38 #include "fileio.h"
39 #include "format-util.h"
40 #include "fs-util.h"
41 #include "glob-util.h"
42 #include "hexdecoct.h"
43 #include "io-util.h"
44 #include "label-util.h"
45 #include "log.h"
46 #include "macro.h"
47 #include "main-func.h"
48 #include "missing_stat.h"
49 #include "missing_syscall.h"
50 #include "mkdir-label.h"
51 #include "mount-util.h"
52 #include "mountpoint-util.h"
53 #include "nulstr-util.h"
54 #include "offline-passwd.h"
55 #include "pager.h"
56 #include "parse-argument.h"
57 #include "parse-util.h"
58 #include "path-lookup.h"
59 #include "path-util.h"
60 #include "pretty-print.h"
61 #include "rlimit-util.h"
62 #include "rm-rf.h"
63 #include "selinux-util.h"
64 #include "set.h"
65 #include "sort-util.h"
66 #include "specifier.h"
67 #include "stdio-util.h"
68 #include "string-table.h"
69 #include "string-util.h"
70 #include "strv.h"
71 #include "terminal-util.h"
72 #include "umask-util.h"
73 #include "user-util.h"
74 #include "virt.h"
75
76 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
77 * them in the file system. This is intended to be used to create
78 * properly owned directories beneath /tmp, /var/tmp, /run, which are
79 * volatile and hence need to be recreated on bootup. */
80
81 typedef enum OperationMask {
82 OPERATION_CREATE = 1 << 0,
83 OPERATION_REMOVE = 1 << 1,
84 OPERATION_CLEAN = 1 << 2,
85 } OperationMask;
86
87 typedef enum ItemType {
88 /* These ones take file names */
89 CREATE_FILE = 'f',
90 TRUNCATE_FILE = 'F', /* deprecated: use f+ */
91 CREATE_DIRECTORY = 'd',
92 TRUNCATE_DIRECTORY = 'D',
93 CREATE_SUBVOLUME = 'v',
94 CREATE_SUBVOLUME_INHERIT_QUOTA = 'q',
95 CREATE_SUBVOLUME_NEW_QUOTA = 'Q',
96 CREATE_FIFO = 'p',
97 CREATE_SYMLINK = 'L',
98 CREATE_CHAR_DEVICE = 'c',
99 CREATE_BLOCK_DEVICE = 'b',
100 COPY_FILES = 'C',
101
102 /* These ones take globs */
103 WRITE_FILE = 'w',
104 EMPTY_DIRECTORY = 'e',
105 SET_XATTR = 't',
106 RECURSIVE_SET_XATTR = 'T',
107 SET_ACL = 'a',
108 RECURSIVE_SET_ACL = 'A',
109 SET_ATTRIBUTE = 'h',
110 RECURSIVE_SET_ATTRIBUTE = 'H',
111 IGNORE_PATH = 'x',
112 IGNORE_DIRECTORY_PATH = 'X',
113 REMOVE_PATH = 'r',
114 RECURSIVE_REMOVE_PATH = 'R',
115 RELABEL_PATH = 'z',
116 RECURSIVE_RELABEL_PATH = 'Z',
117 ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */
118 } ItemType;
119
120 typedef enum AgeBy {
121 AGE_BY_ATIME = 1 << 0,
122 AGE_BY_BTIME = 1 << 1,
123 AGE_BY_CTIME = 1 << 2,
124 AGE_BY_MTIME = 1 << 3,
125
126 /* All file timestamp types are checked by default. */
127 AGE_BY_DEFAULT_FILE = AGE_BY_ATIME | AGE_BY_BTIME | AGE_BY_CTIME | AGE_BY_MTIME,
128 AGE_BY_DEFAULT_DIR = AGE_BY_ATIME | AGE_BY_BTIME | AGE_BY_MTIME,
129 } AgeBy;
130
131 typedef struct Item {
132 ItemType type;
133
134 char *path;
135 char *argument;
136 void *binary_argument; /* set if binary data, in which case it takes precedence over 'argument' */
137 size_t binary_argument_size;
138 char **xattrs;
139 #if HAVE_ACL
140 acl_t acl_access;
141 acl_t acl_access_exec;
142 acl_t acl_default;
143 #endif
144 uid_t uid;
145 gid_t gid;
146 mode_t mode;
147 usec_t age;
148 AgeBy age_by_file, age_by_dir;
149
150 dev_t major_minor;
151 unsigned attribute_value;
152 unsigned attribute_mask;
153
154 bool uid_set:1;
155 bool gid_set:1;
156 bool mode_set:1;
157 bool uid_only_create:1;
158 bool gid_only_create:1;
159 bool mode_only_create:1;
160 bool age_set:1;
161 bool mask_perms:1;
162 bool attribute_set:1;
163
164 bool keep_first_level:1;
165
166 bool append_or_force:1;
167
168 bool allow_failure:1;
169
170 bool try_replace:1;
171
172 OperationMask done;
173 } Item;
174
175 typedef struct ItemArray {
176 Item *items;
177 size_t n_items;
178
179 struct ItemArray *parent;
180 Set *children;
181 } ItemArray;
182
183 typedef enum DirectoryType {
184 DIRECTORY_RUNTIME,
185 DIRECTORY_STATE,
186 DIRECTORY_CACHE,
187 DIRECTORY_LOGS,
188 _DIRECTORY_TYPE_MAX,
189 } DirectoryType;
190
191 typedef enum {
192 CREATION_NORMAL,
193 CREATION_EXISTING,
194 CREATION_FORCE,
195 _CREATION_MODE_MAX,
196 _CREATION_MODE_INVALID = -EINVAL,
197 } CreationMode;
198
199 static bool arg_cat_config = false;
200 static RuntimeScope arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
201 static OperationMask arg_operation = 0;
202 static bool arg_boot = false;
203 static bool arg_graceful = false;
204 static PagerFlags arg_pager_flags = 0;
205
206 static char **arg_include_prefixes = NULL;
207 static char **arg_exclude_prefixes = NULL;
208 static char *arg_root = NULL;
209 static char *arg_image = NULL;
210 static char *arg_replace = NULL;
211 static ImagePolicy *arg_image_policy = NULL;
212
213 #define MAX_DEPTH 256
214
215 static OrderedHashmap *items = NULL, *globs = NULL;
216 static Set *unix_sockets = NULL;
217
218 STATIC_DESTRUCTOR_REGISTER(items, ordered_hashmap_freep);
219 STATIC_DESTRUCTOR_REGISTER(globs, ordered_hashmap_freep);
220 STATIC_DESTRUCTOR_REGISTER(unix_sockets, set_freep);
221 STATIC_DESTRUCTOR_REGISTER(arg_include_prefixes, freep);
222 STATIC_DESTRUCTOR_REGISTER(arg_exclude_prefixes, freep);
223 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
224 STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
225 STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
226
227 static const char *const creation_mode_verb_table[_CREATION_MODE_MAX] = {
228 [CREATION_NORMAL] = "Created",
229 [CREATION_EXISTING] = "Found existing",
230 [CREATION_FORCE] = "Created replacement",
231 };
232
233 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(creation_mode_verb, CreationMode);
234
235 /* Different kinds of errors that mean that information is not available in the environment. */
236 static inline bool ERRNO_IS_NOINFO(int r) {
237 return IN_SET(abs(r),
238 EUNATCH, /* os-release or machine-id missing */
239 ENOMEDIUM, /* machine-id or another file empty */
240 ENXIO); /* env var is unset */
241 }
242
243 static int specifier_directory(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
244 struct table_entry {
245 uint64_t type;
246 const char *suffix;
247 };
248
249 static const struct table_entry paths_system[] = {
250 [DIRECTORY_RUNTIME] = { SD_PATH_SYSTEM_RUNTIME },
251 [DIRECTORY_STATE] = { SD_PATH_SYSTEM_STATE_PRIVATE },
252 [DIRECTORY_CACHE] = { SD_PATH_SYSTEM_STATE_CACHE },
253 [DIRECTORY_LOGS] = { SD_PATH_SYSTEM_STATE_LOGS },
254 };
255
256 static const struct table_entry paths_user[] = {
257 [DIRECTORY_RUNTIME] = { SD_PATH_USER_RUNTIME },
258 [DIRECTORY_STATE] = { SD_PATH_USER_CONFIGURATION },
259 [DIRECTORY_CACHE] = { SD_PATH_USER_STATE_CACHE },
260 [DIRECTORY_LOGS] = { SD_PATH_USER_CONFIGURATION, "log" },
261 };
262
263 const struct table_entry *paths;
264 _cleanup_free_ char *p = NULL;
265 unsigned i;
266 int r;
267
268 assert_cc(ELEMENTSOF(paths_system) == ELEMENTSOF(paths_user));
269 paths = arg_runtime_scope == RUNTIME_SCOPE_USER ? paths_user : paths_system;
270
271 i = PTR_TO_UINT(data);
272 assert(i < ELEMENTSOF(paths_system));
273
274 r = sd_path_lookup(paths[i].type, paths[i].suffix, &p);
275 if (r < 0)
276 return r;
277
278 if (arg_root) {
279 _cleanup_free_ char *j = NULL;
280
281 j = path_join(arg_root, p);
282 if (!j)
283 return -ENOMEM;
284
285 *ret = TAKE_PTR(j);
286 } else
287 *ret = TAKE_PTR(p);
288
289 return 0;
290 }
291
292 static int log_unresolvable_specifier(const char *filename, unsigned line) {
293 static bool notified = false;
294
295 /* In system mode, this is called when /etc is not fully initialized and some specifiers are
296 * unresolvable. In user mode, this is called when some variables are not defined. These cases are
297 * not considered a fatal error, so log at LOG_NOTICE only for the first time and then downgrade this
298 * to LOG_DEBUG for the rest.
299 *
300 * If we're running in a chroot (--root was used or sd_booted() reports that systemd is not running),
301 * always use LOG_DEBUG. We may be called to initialize a chroot before booting and there is no
302 * expectation that machine-id and other files will be populated.
303 */
304
305 int log_level = notified || arg_root || running_in_chroot() > 0 ?
306 LOG_DEBUG : LOG_NOTICE;
307
308 log_syntax(NULL,
309 log_level,
310 filename, line, 0,
311 "Failed to resolve specifier: %s, skipping.",
312 arg_runtime_scope == RUNTIME_SCOPE_USER ? "Required $XDG_... variable not defined" : "uninitialized /etc/ detected");
313
314 if (!notified)
315 log_full(log_level,
316 "All rules containing unresolvable specifiers will be skipped.");
317
318 notified = true;
319 return 0;
320 }
321
322 static int user_config_paths(char*** ret) {
323 _cleanup_strv_free_ char **config_dirs = NULL, **data_dirs = NULL;
324 _cleanup_free_ char *persistent_config = NULL, *runtime_config = NULL, *data_home = NULL;
325 _cleanup_strv_free_ char **res = NULL;
326 int r;
327
328 r = xdg_user_dirs(&config_dirs, &data_dirs);
329 if (r < 0)
330 return r;
331
332 r = xdg_user_config_dir(&persistent_config, "/user-tmpfiles.d");
333 if (r < 0 && !ERRNO_IS_NOINFO(r))
334 return r;
335
336 r = xdg_user_runtime_dir(&runtime_config, "/user-tmpfiles.d");
337 if (r < 0 && !ERRNO_IS_NOINFO(r))
338 return r;
339
340 r = xdg_user_data_dir(&data_home, "/user-tmpfiles.d");
341 if (r < 0 && !ERRNO_IS_NOINFO(r))
342 return r;
343
344 r = strv_extend_strv_concat(&res, config_dirs, "/user-tmpfiles.d");
345 if (r < 0)
346 return r;
347
348 r = strv_extend(&res, persistent_config);
349 if (r < 0)
350 return r;
351
352 r = strv_extend(&res, runtime_config);
353 if (r < 0)
354 return r;
355
356 r = strv_extend(&res, data_home);
357 if (r < 0)
358 return r;
359
360 r = strv_extend_strv_concat(&res, data_dirs, "/user-tmpfiles.d");
361 if (r < 0)
362 return r;
363
364 r = path_strv_make_absolute_cwd(res);
365 if (r < 0)
366 return r;
367
368 *ret = TAKE_PTR(res);
369 return 0;
370 }
371
372 static bool needs_glob(ItemType t) {
373 return IN_SET(t,
374 WRITE_FILE,
375 IGNORE_PATH,
376 IGNORE_DIRECTORY_PATH,
377 REMOVE_PATH,
378 RECURSIVE_REMOVE_PATH,
379 EMPTY_DIRECTORY,
380 ADJUST_MODE,
381 RELABEL_PATH,
382 RECURSIVE_RELABEL_PATH,
383 SET_XATTR,
384 RECURSIVE_SET_XATTR,
385 SET_ACL,
386 RECURSIVE_SET_ACL,
387 SET_ATTRIBUTE,
388 RECURSIVE_SET_ATTRIBUTE);
389 }
390
391 static bool takes_ownership(ItemType t) {
392 return IN_SET(t,
393 CREATE_FILE,
394 TRUNCATE_FILE,
395 CREATE_DIRECTORY,
396 EMPTY_DIRECTORY,
397 TRUNCATE_DIRECTORY,
398 CREATE_SUBVOLUME,
399 CREATE_SUBVOLUME_INHERIT_QUOTA,
400 CREATE_SUBVOLUME_NEW_QUOTA,
401 CREATE_FIFO,
402 CREATE_SYMLINK,
403 CREATE_CHAR_DEVICE,
404 CREATE_BLOCK_DEVICE,
405 COPY_FILES,
406 WRITE_FILE,
407 IGNORE_PATH,
408 IGNORE_DIRECTORY_PATH,
409 REMOVE_PATH,
410 RECURSIVE_REMOVE_PATH);
411 }
412
413 static struct Item* find_glob(OrderedHashmap *h, const char *match) {
414 ItemArray *j;
415
416 ORDERED_HASHMAP_FOREACH(j, h) {
417 size_t n;
418
419 for (n = 0; n < j->n_items; n++) {
420 Item *item = j->items + n;
421
422 if (fnmatch(item->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
423 return item;
424 }
425 }
426
427 return NULL;
428 }
429
430 static int load_unix_sockets(void) {
431 _cleanup_set_free_ Set *sockets = NULL;
432 _cleanup_fclose_ FILE *f = NULL;
433 int r;
434
435 if (unix_sockets)
436 return 0;
437
438 /* We maintain a cache of the sockets we found in /proc/net/unix to speed things up a little. */
439
440 f = fopen("/proc/net/unix", "re");
441 if (!f)
442 return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
443 "Failed to open /proc/net/unix, ignoring: %m");
444
445 /* Skip header */
446 r = read_line(f, LONG_LINE_MAX, NULL);
447 if (r < 0)
448 return log_warning_errno(r, "Failed to skip /proc/net/unix header line: %m");
449 if (r == 0)
450 return log_warning_errno(SYNTHETIC_ERRNO(EIO), "Premature end of file reading /proc/net/unix.");
451
452 for (;;) {
453 _cleanup_free_ char *line = NULL;
454 char *p;
455
456 r = read_line(f, LONG_LINE_MAX, &line);
457 if (r < 0)
458 return log_warning_errno(r, "Failed to read /proc/net/unix line, ignoring: %m");
459 if (r == 0) /* EOF */
460 break;
461
462 p = strchr(line, ':');
463 if (!p)
464 continue;
465
466 if (strlen(p) < 37)
467 continue;
468
469 p += 37;
470 p += strspn(p, WHITESPACE);
471 p += strcspn(p, WHITESPACE); /* skip one more word */
472 p += strspn(p, WHITESPACE);
473
474 if (!path_is_absolute(p))
475 continue;
476
477 r = set_put_strdup_full(&sockets, &path_hash_ops_free, p);
478 if (r < 0)
479 return log_warning_errno(r, "Failed to add AF_UNIX socket to set, ignoring: %m");
480 }
481
482 unix_sockets = TAKE_PTR(sockets);
483 return 1;
484 }
485
486 static bool unix_socket_alive(const char *fn) {
487 assert(fn);
488
489 if (load_unix_sockets() < 0)
490 return true; /* We don't know, so assume yes */
491
492 return set_contains(unix_sockets, fn);
493 }
494
495 /* Accessors for the argument in binary format */
496 static const void* item_binary_argument(const Item *i) {
497 assert(i);
498 return i->binary_argument ?: i->argument;
499 }
500
501 static size_t item_binary_argument_size(const Item *i) {
502 assert(i);
503 return i->binary_argument ? i->binary_argument_size : strlen_ptr(i->argument);
504 }
505
506 static DIR* xopendirat_nomod(int dirfd, const char *path) {
507 DIR *dir;
508
509 dir = xopendirat(dirfd, path, O_NOFOLLOW|O_NOATIME);
510 if (dir)
511 return dir;
512
513 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m", dirfd == AT_FDCWD ? "" : "sub", path);
514 if (errno != EPERM)
515 return NULL;
516
517 dir = xopendirat(dirfd, path, O_NOFOLLOW);
518 if (!dir)
519 log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m", dirfd == AT_FDCWD ? "" : "sub", path);
520
521 return dir;
522 }
523
524 static DIR* opendir_nomod(const char *path) {
525 return xopendirat_nomod(AT_FDCWD, path);
526 }
527
528 static inline nsec_t load_statx_timestamp_nsec(const struct statx_timestamp *ts) {
529 assert(ts);
530
531 if (ts->tv_sec < 0)
532 return NSEC_INFINITY;
533
534 if ((nsec_t) ts->tv_sec >= (UINT64_MAX - ts->tv_nsec) / NSEC_PER_SEC)
535 return NSEC_INFINITY;
536
537 return ts->tv_sec * NSEC_PER_SEC + ts->tv_nsec;
538 }
539
540 static bool needs_cleanup(
541 nsec_t atime,
542 nsec_t btime,
543 nsec_t ctime,
544 nsec_t mtime,
545 nsec_t cutoff,
546 const char *sub_path,
547 AgeBy age_by,
548 bool is_dir) {
549
550 if (FLAGS_SET(age_by, AGE_BY_MTIME) && mtime != NSEC_INFINITY && mtime >= cutoff) {
551 /* Follows spelling in stat(1). */
552 log_debug("%s \"%s\": modify time %s is too new.",
553 is_dir ? "Directory" : "File",
554 sub_path,
555 FORMAT_TIMESTAMP_STYLE(mtime / NSEC_PER_USEC, TIMESTAMP_US));
556
557 return false;
558 }
559
560 if (FLAGS_SET(age_by, AGE_BY_ATIME) && atime != NSEC_INFINITY && atime >= cutoff) {
561 log_debug("%s \"%s\": access time %s is too new.",
562 is_dir ? "Directory" : "File",
563 sub_path,
564 FORMAT_TIMESTAMP_STYLE(atime / NSEC_PER_USEC, TIMESTAMP_US));
565
566 return false;
567 }
568
569 /*
570 * Note: Unless explicitly specified by the user, "ctime" is ignored
571 * by default for directories, because we change it when deleting.
572 */
573 if (FLAGS_SET(age_by, AGE_BY_CTIME) && ctime != NSEC_INFINITY && ctime >= cutoff) {
574 log_debug("%s \"%s\": change time %s is too new.",
575 is_dir ? "Directory" : "File",
576 sub_path,
577 FORMAT_TIMESTAMP_STYLE(ctime / NSEC_PER_USEC, TIMESTAMP_US));
578
579 return false;
580 }
581
582 if (FLAGS_SET(age_by, AGE_BY_BTIME) && btime != NSEC_INFINITY && btime >= cutoff) {
583 log_debug("%s \"%s\": birth time %s is too new.",
584 is_dir ? "Directory" : "File",
585 sub_path,
586 FORMAT_TIMESTAMP_STYLE(btime / NSEC_PER_USEC, TIMESTAMP_US));
587
588 return false;
589 }
590
591 return true;
592 }
593
594 static int dir_cleanup(
595 Item *i,
596 const char *p,
597 DIR *d,
598 nsec_t self_atime_nsec,
599 nsec_t self_mtime_nsec,
600 nsec_t cutoff_nsec,
601 dev_t rootdev_major,
602 dev_t rootdev_minor,
603 bool mountpoint,
604 int maxdepth,
605 bool keep_this_level,
606 AgeBy age_by_file,
607 AgeBy age_by_dir) {
608
609 bool deleted = false;
610 int r = 0;
611
612 FOREACH_DIRENT_ALL(de, d, break) {
613 _cleanup_free_ char *sub_path = NULL;
614 nsec_t atime_nsec, mtime_nsec, ctime_nsec, btime_nsec;
615
616 if (dot_or_dot_dot(de->d_name))
617 continue;
618
619 /* If statx() is supported, use it. It's preferable over fstatat() since it tells us
620 * explicitly where we are looking at a mount point, for free as side information. Determining
621 * the same information without statx() is hard, see the complexity of path_is_mount_point(),
622 * and also much slower as it requires a number of syscalls instead of just one. Hence, when
623 * we have modern statx() we use it instead of fstat() and do proper mount point checks,
624 * while on older kernels's well do traditional st_dev based detection of mount points.
625 *
626 * Using statx() for detecting mount points also has the benfit that we handle weird file
627 * systems such as overlayfs better where each file is originating from a different
628 * st_dev. */
629
630 STRUCT_STATX_DEFINE(sx);
631
632 r = statx_fallback(
633 dirfd(d), de->d_name,
634 AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT,
635 STATX_TYPE|STATX_MODE|STATX_UID|STATX_ATIME|STATX_MTIME|STATX_CTIME|STATX_BTIME,
636 &sx);
637 if (r == -ENOENT)
638 continue;
639 if (r < 0) {
640 /* FUSE, NFS mounts, SELinux might return EACCES */
641 r = log_full_errno(r == -EACCES ? LOG_DEBUG : LOG_ERR, r,
642 "statx(%s/%s) failed: %m", p, de->d_name);
643 continue;
644 }
645
646 if (FLAGS_SET(sx.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT)) {
647 /* Yay, we have the mount point API, use it */
648 if (FLAGS_SET(sx.stx_attributes, STATX_ATTR_MOUNT_ROOT)) {
649 log_debug("Ignoring \"%s/%s\": different mount points.", p, de->d_name);
650 continue;
651 }
652 } else {
653 /* So we might have statx() but the STATX_ATTR_MOUNT_ROOT flag is not supported, fall
654 * back to traditional stx_dev checking. */
655 if (sx.stx_dev_major != rootdev_major ||
656 sx.stx_dev_minor != rootdev_minor) {
657 log_debug("Ignoring \"%s/%s\": different filesystem.", p, de->d_name);
658 continue;
659 }
660
661 /* Try to detect bind mounts of the same filesystem instance; they do not differ in device
662 * major/minors. This type of query is not supported on all kernels or filesystem types
663 * though. */
664 if (S_ISDIR(sx.stx_mode)) {
665 int q;
666
667 q = fd_is_mount_point(dirfd(d), de->d_name, 0);
668 if (q < 0)
669 log_debug_errno(q, "Failed to determine whether \"%s/%s\" is a mount point, ignoring: %m", p, de->d_name);
670 else if (q > 0) {
671 log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.", p, de->d_name);
672 continue;
673 }
674 }
675 }
676
677 atime_nsec = FLAGS_SET(sx.stx_mask, STATX_ATIME) ? load_statx_timestamp_nsec(&sx.stx_atime) : 0;
678 mtime_nsec = FLAGS_SET(sx.stx_mask, STATX_MTIME) ? load_statx_timestamp_nsec(&sx.stx_mtime) : 0;
679 ctime_nsec = FLAGS_SET(sx.stx_mask, STATX_CTIME) ? load_statx_timestamp_nsec(&sx.stx_ctime) : 0;
680 btime_nsec = FLAGS_SET(sx.stx_mask, STATX_BTIME) ? load_statx_timestamp_nsec(&sx.stx_btime) : 0;
681
682 sub_path = path_join(p, de->d_name);
683 if (!sub_path) {
684 r = log_oom();
685 goto finish;
686 }
687
688 /* Is there an item configured for this path? */
689 if (ordered_hashmap_get(items, sub_path)) {
690 log_debug("Ignoring \"%s\": a separate entry exists.", sub_path);
691 continue;
692 }
693
694 if (find_glob(globs, sub_path)) {
695 log_debug("Ignoring \"%s\": a separate glob exists.", sub_path);
696 continue;
697 }
698
699 if (S_ISDIR(sx.stx_mode)) {
700 _cleanup_closedir_ DIR *sub_dir = NULL;
701
702 if (mountpoint &&
703 streq(de->d_name, "lost+found") &&
704 sx.stx_uid == 0) {
705 log_debug("Ignoring directory \"%s\".", sub_path);
706 continue;
707 }
708
709 if (maxdepth <= 0)
710 log_warning("Reached max depth on \"%s\".", sub_path);
711 else {
712 int q;
713
714 sub_dir = xopendirat_nomod(dirfd(d), de->d_name);
715 if (!sub_dir) {
716 if (errno != ENOENT)
717 r = log_warning_errno(errno, "Opening directory \"%s\" failed, ignoring: %m", sub_path);
718
719 continue;
720 }
721
722 if (flock(dirfd(sub_dir), LOCK_EX|LOCK_NB) < 0) {
723 log_debug_errno(errno, "Couldn't acquire shared BSD lock on directory \"%s\", skipping: %m", p);
724 continue;
725 }
726
727 q = dir_cleanup(i,
728 sub_path, sub_dir,
729 atime_nsec, mtime_nsec, cutoff_nsec,
730 rootdev_major, rootdev_minor,
731 false, maxdepth-1, false,
732 age_by_file, age_by_dir);
733 if (q < 0)
734 r = q;
735 }
736
737 /* Note: if you are wondering why we don't support the sticky bit for excluding
738 * directories from cleaning like we do it for other file system objects: well, the
739 * sticky bit already has a meaning for directories, so we don't want to overload
740 * that. */
741
742 if (keep_this_level) {
743 log_debug("Keeping directory \"%s\".", sub_path);
744 continue;
745 }
746
747 /*
748 * Check the file timestamps of an entry against the
749 * given cutoff time; delete if it is older.
750 */
751 if (!needs_cleanup(atime_nsec, btime_nsec, ctime_nsec, mtime_nsec,
752 cutoff_nsec, sub_path, age_by_dir, true))
753 continue;
754
755 log_debug("Removing directory \"%s\".", sub_path);
756 if (unlinkat(dirfd(d), de->d_name, AT_REMOVEDIR) < 0)
757 if (!IN_SET(errno, ENOENT, ENOTEMPTY))
758 r = log_warning_errno(errno, "Failed to remove directory \"%s\", ignoring: %m", sub_path);
759
760 } else {
761 _cleanup_close_ int fd = -EBADF;
762
763 /* Skip files for which the sticky bit is set. These are semantics we define, and are
764 * unknown elsewhere. See XDG_RUNTIME_DIR specification for details. */
765 if (sx.stx_mode & S_ISVTX) {
766 log_debug("Skipping \"%s\": sticky bit set.", sub_path);
767 continue;
768 }
769
770 if (mountpoint &&
771 S_ISREG(sx.stx_mode) &&
772 sx.stx_uid == 0 &&
773 STR_IN_SET(de->d_name,
774 ".journal",
775 "aquota.user",
776 "aquota.group")) {
777 log_debug("Skipping \"%s\".", sub_path);
778 continue;
779 }
780
781 /* Ignore sockets that are listed in /proc/net/unix */
782 if (S_ISSOCK(sx.stx_mode) && unix_socket_alive(sub_path)) {
783 log_debug("Skipping \"%s\": live socket.", sub_path);
784 continue;
785 }
786
787 /* Ignore device nodes */
788 if (S_ISCHR(sx.stx_mode) || S_ISBLK(sx.stx_mode)) {
789 log_debug("Skipping \"%s\": a device.", sub_path);
790 continue;
791 }
792
793 /* Keep files on this level around if this is requested */
794 if (keep_this_level) {
795 log_debug("Keeping \"%s\".", sub_path);
796 continue;
797 }
798
799 if (!needs_cleanup(atime_nsec, btime_nsec, ctime_nsec, mtime_nsec,
800 cutoff_nsec, sub_path, age_by_file, false))
801 continue;
802
803 fd = xopenat(dirfd(d),
804 de->d_name,
805 O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME,
806 /* xopen_flags = */ 0,
807 /* mode = */ 0);
808 if (fd < 0 && fd != -ENOENT)
809 log_warning_errno(fd, "Opening file \"%s\" failed, ignoring: %m", sub_path);
810 if (fd >= 0 && flock(fd, LOCK_EX|LOCK_NB) < 0 && errno == EAGAIN) {
811 log_debug_errno(errno, "Couldn't acquire shared BSD lock on file \"%s\", skipping: %m", p);
812 continue;
813 }
814
815 log_debug("Removing \"%s\".", sub_path);
816 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
817 if (errno != ENOENT)
818 r = log_warning_errno(errno, "Failed to remove \"%s\", ignoring: %m", sub_path);
819
820 deleted = true;
821 }
822 }
823
824 finish:
825 if (deleted) {
826 struct timespec ts[2];
827
828 log_debug("Restoring access and modification time on \"%s\": %s, %s",
829 p,
830 FORMAT_TIMESTAMP_STYLE(self_atime_nsec / NSEC_PER_USEC, TIMESTAMP_US),
831 FORMAT_TIMESTAMP_STYLE(self_mtime_nsec / NSEC_PER_USEC, TIMESTAMP_US));
832
833 timespec_store_nsec(ts + 0, self_atime_nsec);
834 timespec_store_nsec(ts + 1, self_mtime_nsec);
835
836 /* Restore original directory timestamps */
837 if (futimens(dirfd(d), ts) < 0)
838 log_warning_errno(errno, "Failed to revert timestamps of '%s', ignoring: %m", p);
839 }
840
841 return r;
842 }
843
844 static bool dangerous_hardlinks(void) {
845 _cleanup_free_ char *value = NULL;
846 static int cached = -1;
847 int r;
848
849 /* Check whether the fs.protected_hardlinks sysctl is on. If we can't determine it we assume its off, as that's
850 * what the upstream default is. */
851
852 if (cached >= 0)
853 return cached;
854
855 r = read_one_line_file("/proc/sys/fs/protected_hardlinks", &value);
856 if (r < 0) {
857 log_debug_errno(r, "Failed to read fs.protected_hardlinks sysctl: %m");
858 return true;
859 }
860
861 r = parse_boolean(value);
862 if (r < 0) {
863 log_debug_errno(r, "Failed to parse fs.protected_hardlinks sysctl: %m");
864 return true;
865 }
866
867 cached = r == 0;
868 return cached;
869 }
870
871 static bool hardlink_vulnerable(const struct stat *st) {
872 assert(st);
873
874 return !S_ISDIR(st->st_mode) && st->st_nlink > 1 && dangerous_hardlinks();
875 }
876
877 static mode_t process_mask_perms(mode_t mode, mode_t current) {
878
879 if ((current & 0111) == 0)
880 mode &= ~0111;
881 if ((current & 0222) == 0)
882 mode &= ~0222;
883 if ((current & 0444) == 0)
884 mode &= ~0444;
885 if (!S_ISDIR(current))
886 mode &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
887
888 return mode;
889 }
890
891 static int fd_set_perms(
892 Item *i,
893 int fd,
894 const char *path,
895 const struct stat *st,
896 CreationMode creation) {
897
898 bool do_chown, do_chmod;
899 struct stat stbuf;
900 mode_t new_mode;
901 uid_t new_uid;
902 gid_t new_gid;
903 int r;
904
905 assert(i);
906 assert(fd >= 0);
907 assert(path);
908
909 if (!i->mode_set && !i->uid_set && !i->gid_set)
910 goto shortcut;
911
912 if (!st) {
913 if (fstat(fd, &stbuf) < 0)
914 return log_error_errno(errno, "fstat(%s) failed: %m", path);
915 st = &stbuf;
916 }
917
918 if (hardlink_vulnerable(st))
919 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
920 "Refusing to set permissions on hardlinked file %s while the fs.protected_hardlinks sysctl is turned off.",
921 path);
922 new_uid = i->uid_set && (creation != CREATION_EXISTING || !i->uid_only_create) ? i->uid : st->st_uid;
923 new_gid = i->gid_set && (creation != CREATION_EXISTING || !i->gid_only_create) ? i->gid : st->st_gid;
924
925 /* Do we need a chown()? */
926 do_chown = (new_uid != st->st_uid) || (new_gid != st->st_gid);
927
928 /* Calculate the mode to apply */
929 new_mode = i->mode_set && (creation != CREATION_EXISTING || !i->mode_only_create) ?
930 (i->mask_perms ? process_mask_perms(i->mode, st->st_mode) : i->mode) :
931 (st->st_mode & 07777);
932
933 do_chmod = ((new_mode ^ st->st_mode) & 07777) != 0;
934
935 if (do_chmod && do_chown) {
936 /* Before we issue the chmod() let's reduce the access mode to the common bits of the old and
937 * the new mode. That way there's no time window where the file exists under the old owner
938 * with more than the old access modes — and not under the new owner with more than the new
939 * access modes either. */
940
941 if (S_ISLNK(st->st_mode))
942 log_debug("Skipping temporary mode fix for symlink %s.", path);
943 else {
944 mode_t m = new_mode & st->st_mode; /* Mask new mode by old mode */
945
946 if (((m ^ st->st_mode) & 07777) == 0)
947 log_debug("\"%s\" matches temporary mode %o already.", path, m);
948 else {
949 log_debug("Temporarily changing \"%s\" to mode %o.", path, m);
950 r = fchmod_opath(fd, m);
951 if (r < 0)
952 return log_error_errno(r, "fchmod() of %s failed: %m", path);
953 }
954 }
955 }
956
957 if (do_chown) {
958 log_debug("Changing \"%s\" to owner "UID_FMT":"GID_FMT, path, new_uid, new_gid);
959
960 if (fchownat(fd, "",
961 new_uid != st->st_uid ? new_uid : UID_INVALID,
962 new_gid != st->st_gid ? new_gid : GID_INVALID,
963 AT_EMPTY_PATH) < 0)
964 return log_error_errno(errno, "fchownat() of %s failed: %m", path);
965 }
966
967 /* Now, apply the final mode. We do this in two cases: when the user set a mode explicitly, or after a
968 * chown(), since chown()'s mangle the access mode in regards to sgid/suid in some conditions. */
969 if (do_chmod || do_chown) {
970 if (S_ISLNK(st->st_mode))
971 log_debug("Skipping mode fix for symlink %s.", path);
972 else {
973 log_debug("Changing \"%s\" to mode %o.", path, new_mode);
974 r = fchmod_opath(fd, new_mode);
975 if (r < 0)
976 return log_error_errno(r, "fchmod() of %s failed: %m", path);
977 }
978 }
979
980 shortcut:
981 return label_fix_full(fd, /* inode_path= */ NULL, /* label_path= */ path, 0);
982 }
983
984 static int path_open_parent_safe(const char *path, bool allow_failure) {
985 _cleanup_free_ char *dn = NULL;
986 int r, fd;
987
988 if (!path_is_normalized(path))
989 return log_full_errno(allow_failure ? LOG_INFO : LOG_ERR,
990 SYNTHETIC_ERRNO(EINVAL),
991 "Failed to open parent of '%s': path not normalized%s.",
992 path,
993 allow_failure ? ", ignoring" : "");
994
995 r = path_extract_directory(path, &dn);
996 if (r < 0)
997 return log_full_errno(allow_failure ? LOG_INFO : LOG_ERR,
998 r,
999 "Unable to determine parent directory of '%s'%s: %m",
1000 path,
1001 allow_failure ? ", ignoring" : "");
1002
1003 r = chase(dn, arg_root, allow_failure ? CHASE_SAFE : CHASE_SAFE|CHASE_WARN, NULL, &fd);
1004 if (r == -ENOLINK) /* Unsafe symlink: already covered by CHASE_WARN */
1005 return r;
1006 if (r < 0)
1007 return log_full_errno(allow_failure ? LOG_INFO : LOG_ERR,
1008 r,
1009 "Failed to open path '%s'%s: %m",
1010 dn,
1011 allow_failure ? ", ignoring" : "");
1012
1013 return fd;
1014 }
1015
1016 static int path_open_safe(const char *path) {
1017 int r, fd;
1018
1019 /* path_open_safe() returns a file descriptor opened with O_PATH after
1020 * verifying that the path doesn't contain unsafe transitions, except
1021 * for its final component as the function does not follow symlink. */
1022
1023 assert(path);
1024
1025 if (!path_is_normalized(path))
1026 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to open invalid path '%s'.", path);
1027
1028 r = chase(path, arg_root, CHASE_SAFE|CHASE_WARN|CHASE_NOFOLLOW, NULL, &fd);
1029 if (r == -ENOLINK)
1030 return r; /* Unsafe symlink: already covered by CHASE_WARN */
1031 if (r < 0)
1032 return log_error_errno(r, "Failed to open path %s: %m", path);
1033
1034 return fd;
1035 }
1036
1037 static int path_set_perms(
1038 Item *i,
1039 const char *path,
1040 CreationMode creation) {
1041
1042 _cleanup_close_ int fd = -EBADF;
1043
1044 assert(i);
1045 assert(path);
1046
1047 fd = path_open_safe(path);
1048 if (fd < 0)
1049 return fd;
1050
1051 return fd_set_perms(i, fd, path, /* st= */ NULL, creation);
1052 }
1053
1054 static int parse_xattrs_from_arg(Item *i) {
1055 const char *p;
1056 int r;
1057
1058 assert(i);
1059
1060 assert_se(p = i->argument);
1061 for (;;) {
1062 _cleanup_free_ char *name = NULL, *value = NULL, *xattr = NULL;
1063
1064 r = extract_first_word(&p, &xattr, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE);
1065 if (r < 0)
1066 log_warning_errno(r, "Failed to parse extended attribute '%s', ignoring: %m", p);
1067 if (r <= 0)
1068 break;
1069
1070 r = split_pair(xattr, "=", &name, &value);
1071 if (r < 0) {
1072 log_warning_errno(r, "Failed to parse extended attribute, ignoring: %s", xattr);
1073 continue;
1074 }
1075
1076 if (isempty(name) || isempty(value)) {
1077 log_warning("Malformed extended attribute found, ignoring: %s", xattr);
1078 continue;
1079 }
1080
1081 if (strv_push_pair(&i->xattrs, name, value) < 0)
1082 return log_oom();
1083
1084 name = value = NULL;
1085 }
1086
1087 return 0;
1088 }
1089
1090 static int fd_set_xattrs(
1091 Item *i,
1092 int fd,
1093 const char *path,
1094 const struct stat *st,
1095 CreationMode creation) {
1096
1097 assert(i);
1098 assert(fd >= 0);
1099 assert(path);
1100
1101 STRV_FOREACH_PAIR(name, value, i->xattrs) {
1102 log_debug("Setting extended attribute '%s=%s' on %s.", *name, *value, path);
1103 if (setxattr(FORMAT_PROC_FD_PATH(fd), *name, *value, strlen(*value), 0) < 0)
1104 return log_error_errno(errno, "Setting extended attribute %s=%s on %s failed: %m",
1105 *name, *value, path);
1106 }
1107 return 0;
1108 }
1109
1110 static int path_set_xattrs(
1111 Item *i,
1112 const char *path,
1113 CreationMode creation) {
1114
1115 _cleanup_close_ int fd = -EBADF;
1116
1117 assert(i);
1118 assert(path);
1119
1120 fd = path_open_safe(path);
1121 if (fd < 0)
1122 return fd;
1123
1124 return fd_set_xattrs(i, fd, path, /* st = */ NULL, creation);
1125 }
1126
1127 static int parse_acls_from_arg(Item *item) {
1128 #if HAVE_ACL
1129 int r;
1130
1131 assert(item);
1132
1133 /* If append_or_force (= modify) is set, we will not modify the acl
1134 * afterwards, so the mask can be added now if necessary. */
1135
1136 r = parse_acl(item->argument, &item->acl_access, &item->acl_access_exec,
1137 &item->acl_default, !item->append_or_force);
1138 if (r < 0)
1139 log_full_errno(arg_graceful && IN_SET(r, -ENOENT, -ESRCH) ? LOG_DEBUG : LOG_WARNING,
1140 r, "Failed to parse ACL \"%s\", ignoring: %m", item->argument);
1141 #else
1142 log_warning("ACLs are not supported, ignoring.");
1143 #endif
1144
1145 return 0;
1146 }
1147
1148 #if HAVE_ACL
1149 static int parse_acl_cond_exec(
1150 const char *path,
1151 acl_t access, /* could be empty (NULL) */
1152 acl_t cond_exec,
1153 const struct stat *st,
1154 bool append,
1155 acl_t *ret) {
1156
1157 _cleanup_(acl_freep) acl_t parsed = NULL;
1158 acl_entry_t entry;
1159 acl_permset_t permset;
1160 bool has_exec;
1161 int r;
1162
1163 assert(path);
1164 assert(ret);
1165 assert(st);
1166
1167 parsed = access ? acl_dup(access) : acl_init(0);
1168 if (!parsed)
1169 return -errno;
1170
1171 /* Since we substitute 'X' with 'x' in parse_acl(), we just need to copy the entries over
1172 * for directories */
1173 if (S_ISDIR(st->st_mode)) {
1174 for (r = acl_get_entry(cond_exec, ACL_FIRST_ENTRY, &entry);
1175 r > 0;
1176 r = acl_get_entry(cond_exec, ACL_NEXT_ENTRY, &entry)) {
1177
1178 acl_entry_t parsed_entry;
1179
1180 if (acl_create_entry(&parsed, &parsed_entry) < 0)
1181 return -errno;
1182
1183 if (acl_copy_entry(parsed_entry, entry) < 0)
1184 return -errno;
1185 }
1186 if (r < 0)
1187 return -errno;
1188
1189 goto finish;
1190 }
1191
1192 has_exec = st->st_mode & S_IXUSR;
1193
1194 if (!has_exec && append) {
1195 _cleanup_(acl_freep) acl_t old = NULL;
1196
1197 old = acl_get_file(path, ACL_TYPE_ACCESS);
1198 if (!old)
1199 return -errno;
1200
1201 for (r = acl_get_entry(old, ACL_FIRST_ENTRY, &entry);
1202 r > 0;
1203 r = acl_get_entry(old, ACL_NEXT_ENTRY, &entry)) {
1204
1205 if (acl_get_permset(entry, &permset) < 0)
1206 return -errno;
1207
1208 r = acl_get_perm(permset, ACL_EXECUTE);
1209 if (r < 0)
1210 return -errno;
1211 if (r > 0) {
1212 has_exec = true;
1213 break;
1214 }
1215 }
1216 if (r < 0)
1217 return -errno;
1218 }
1219
1220 /* Check if we're about to set the execute bit in acl_access */
1221 if (!has_exec && access) {
1222 for (r = acl_get_entry(access, ACL_FIRST_ENTRY, &entry);
1223 r > 0;
1224 r = acl_get_entry(access, ACL_NEXT_ENTRY, &entry)) {
1225
1226 if (acl_get_permset(entry, &permset) < 0)
1227 return -errno;
1228
1229 r = acl_get_perm(permset, ACL_EXECUTE);
1230 if (r < 0)
1231 return -errno;
1232 if (r > 0) {
1233 has_exec = true;
1234 break;
1235 }
1236 }
1237 if (r < 0)
1238 return -errno;
1239 }
1240
1241 for (r = acl_get_entry(cond_exec, ACL_FIRST_ENTRY, &entry);
1242 r > 0;
1243 r = acl_get_entry(cond_exec, ACL_NEXT_ENTRY, &entry)) {
1244
1245 acl_entry_t parsed_entry;
1246
1247 if (acl_create_entry(&parsed, &parsed_entry) < 0)
1248 return -errno;
1249
1250 if (acl_copy_entry(parsed_entry, entry) < 0)
1251 return -errno;
1252
1253 if (!has_exec) {
1254 if (acl_get_permset(parsed_entry, &permset) < 0)
1255 return -errno;
1256
1257 if (acl_delete_perm(permset, ACL_EXECUTE) < 0)
1258 return -errno;
1259 }
1260 }
1261 if (r < 0)
1262 return -errno;
1263
1264 finish:
1265 if (!append) { /* want_mask = true */
1266 r = calc_acl_mask_if_needed(&parsed);
1267 if (r < 0)
1268 return r;
1269 }
1270
1271 *ret = TAKE_PTR(parsed);
1272
1273 return 0;
1274 }
1275
1276 static int path_set_acl(
1277 const char *path,
1278 const char *pretty,
1279 acl_type_t type,
1280 acl_t acl,
1281 bool modify) {
1282
1283 _cleanup_(acl_free_charpp) char *t = NULL;
1284 _cleanup_(acl_freep) acl_t dup = NULL;
1285 int r;
1286
1287 /* Returns 0 for success, positive error if already warned,
1288 * negative error otherwise. */
1289
1290 if (modify) {
1291 r = acls_for_file(path, type, acl, &dup);
1292 if (r < 0)
1293 return r;
1294
1295 r = calc_acl_mask_if_needed(&dup);
1296 if (r < 0)
1297 return r;
1298 } else {
1299 dup = acl_dup(acl);
1300 if (!dup)
1301 return -errno;
1302
1303 /* the mask was already added earlier if needed */
1304 }
1305
1306 r = add_base_acls_if_needed(&dup, path);
1307 if (r < 0)
1308 return r;
1309
1310 t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
1311 log_debug("Setting %s ACL %s on %s.",
1312 type == ACL_TYPE_ACCESS ? "access" : "default",
1313 strna(t), pretty);
1314
1315 r = acl_set_file(path, type, dup);
1316 if (r < 0) {
1317 if (ERRNO_IS_NOT_SUPPORTED(errno))
1318 /* No error if filesystem doesn't support ACLs. Return negative. */
1319 return -errno;
1320 else
1321 /* Return positive to indicate we already warned */
1322 return -log_error_errno(errno,
1323 "Setting %s ACL \"%s\" on %s failed: %m",
1324 type == ACL_TYPE_ACCESS ? "access" : "default",
1325 strna(t), pretty);
1326 }
1327 return 0;
1328 }
1329 #endif
1330
1331 static int fd_set_acls(
1332 Item *item,
1333 int fd,
1334 const char *path,
1335 const struct stat *st,
1336 CreationMode creation) {
1337
1338 int r = 0;
1339 #if HAVE_ACL
1340 _cleanup_(acl_freep) acl_t access_with_exec_parsed = NULL;
1341 struct stat stbuf;
1342
1343 assert(item);
1344 assert(fd >= 0);
1345 assert(path);
1346
1347 if (!st) {
1348 if (fstat(fd, &stbuf) < 0)
1349 return log_error_errno(errno, "fstat(%s) failed: %m", path);
1350 st = &stbuf;
1351 }
1352
1353 if (hardlink_vulnerable(st))
1354 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
1355 "Refusing to set ACLs on hardlinked file %s while the fs.protected_hardlinks sysctl is turned off.",
1356 path);
1357
1358 if (S_ISLNK(st->st_mode)) {
1359 log_debug("Skipping ACL fix for symlink %s.", path);
1360 return 0;
1361 }
1362
1363 if (item->acl_access_exec) {
1364 r = parse_acl_cond_exec(FORMAT_PROC_FD_PATH(fd),
1365 item->acl_access,
1366 item->acl_access_exec,
1367 st,
1368 item->append_or_force,
1369 &access_with_exec_parsed);
1370 if (r < 0)
1371 return log_error_errno(r, "Failed to parse conditionalized execute bit for \"%s\": %m", path);
1372
1373 r = path_set_acl(FORMAT_PROC_FD_PATH(fd), path, ACL_TYPE_ACCESS, access_with_exec_parsed, item->append_or_force);
1374 } else if (item->acl_access)
1375 r = path_set_acl(FORMAT_PROC_FD_PATH(fd), path, ACL_TYPE_ACCESS, item->acl_access, item->append_or_force);
1376
1377 /* set only default acls to folders */
1378 if (r == 0 && item->acl_default && S_ISDIR(st->st_mode))
1379 r = path_set_acl(FORMAT_PROC_FD_PATH(fd), path, ACL_TYPE_DEFAULT, item->acl_default, item->append_or_force);
1380
1381 if (ERRNO_IS_NOT_SUPPORTED(r)) {
1382 log_debug_errno(r, "ACLs not supported by file system at %s", path);
1383 return 0;
1384 }
1385
1386 if (r > 0)
1387 return -r; /* already warned in path_set_acl */
1388
1389 /* The above procfs paths don't work if /proc is not mounted. */
1390 if (r == -ENOENT && proc_mounted() == 0)
1391 r = -ENOSYS;
1392
1393 if (r < 0)
1394 return log_error_errno(r, "ACL operation on \"%s\" failed: %m", path);
1395 #endif
1396 return r;
1397 }
1398
1399 static int path_set_acls(Item *item, const char *path, CreationMode creation) {
1400 int r = 0;
1401 #if HAVE_ACL
1402 _cleanup_close_ int fd = -EBADF;
1403
1404 assert(item);
1405 assert(path);
1406
1407 fd = path_open_safe(path);
1408 if (fd < 0)
1409 return fd;
1410
1411 r = fd_set_acls(item, fd, path, /* st= */ NULL, creation);
1412 #endif
1413 return r;
1414 }
1415
1416 static int parse_attribute_from_arg(Item *item) {
1417
1418 static const struct {
1419 char character;
1420 unsigned value;
1421 } attributes[] = {
1422 { 'A', FS_NOATIME_FL }, /* do not update atime */
1423 { 'S', FS_SYNC_FL }, /* Synchronous updates */
1424 { 'D', FS_DIRSYNC_FL }, /* dirsync behaviour (directories only) */
1425 { 'a', FS_APPEND_FL }, /* writes to file may only append */
1426 { 'c', FS_COMPR_FL }, /* Compress file */
1427 { 'd', FS_NODUMP_FL }, /* do not dump file */
1428 { 'e', FS_EXTENT_FL }, /* Extents */
1429 { 'i', FS_IMMUTABLE_FL }, /* Immutable file */
1430 { 'j', FS_JOURNAL_DATA_FL }, /* Reserved for ext3 */
1431 { 's', FS_SECRM_FL }, /* Secure deletion */
1432 { 'u', FS_UNRM_FL }, /* Undelete */
1433 { 't', FS_NOTAIL_FL }, /* file tail should not be merged */
1434 { 'T', FS_TOPDIR_FL }, /* Top of directory hierarchies */
1435 { 'C', FS_NOCOW_FL }, /* Do not cow file */
1436 { 'P', FS_PROJINHERIT_FL }, /* Inherit the quota project ID */
1437 };
1438
1439 enum {
1440 MODE_ADD,
1441 MODE_DEL,
1442 MODE_SET
1443 } mode = MODE_ADD;
1444
1445 unsigned value = 0, mask = 0;
1446 const char *p;
1447
1448 assert(item);
1449
1450 p = item->argument;
1451 if (p) {
1452 if (*p == '+') {
1453 mode = MODE_ADD;
1454 p++;
1455 } else if (*p == '-') {
1456 mode = MODE_DEL;
1457 p++;
1458 } else if (*p == '=') {
1459 mode = MODE_SET;
1460 p++;
1461 }
1462 }
1463
1464 if (isempty(p) && mode != MODE_SET)
1465 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1466 "Setting file attribute on '%s' needs an attribute specification.",
1467 item->path);
1468
1469 for (; p && *p ; p++) {
1470 unsigned i, v;
1471
1472 for (i = 0; i < ELEMENTSOF(attributes); i++)
1473 if (*p == attributes[i].character)
1474 break;
1475
1476 if (i >= ELEMENTSOF(attributes))
1477 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1478 "Unknown file attribute '%c' on '%s'.",
1479 *p, item->path);
1480
1481 v = attributes[i].value;
1482
1483 SET_FLAG(value, v, IN_SET(mode, MODE_ADD, MODE_SET));
1484
1485 mask |= v;
1486 }
1487
1488 if (mode == MODE_SET)
1489 mask |= CHATTR_ALL_FL;
1490
1491 assert(mask != 0);
1492
1493 item->attribute_mask = mask;
1494 item->attribute_value = value;
1495 item->attribute_set = true;
1496
1497 return 0;
1498 }
1499
1500 static int fd_set_attribute(
1501 Item *item,
1502 int fd,
1503 const char *path,
1504 const struct stat *st,
1505 CreationMode creation) {
1506
1507 _cleanup_close_ int procfs_fd = -EBADF;
1508 struct stat stbuf;
1509 unsigned f;
1510 int r;
1511
1512 assert(item);
1513 assert(fd >= 0);
1514 assert(path);
1515
1516 if (!item->attribute_set || item->attribute_mask == 0)
1517 return 0;
1518
1519 if (!st) {
1520 if (fstat(fd, &stbuf) < 0)
1521 return log_error_errno(errno, "fstat(%s) failed: %m", path);
1522 st = &stbuf;
1523 }
1524
1525 /* Issuing the file attribute ioctls on device nodes is not safe, as that will be delivered to the
1526 * drivers, not the file system containing the device node. */
1527 if (!S_ISREG(st->st_mode) && !S_ISDIR(st->st_mode))
1528 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1529 "Setting file flags is only supported on regular files and directories, cannot set on '%s'.",
1530 path);
1531
1532 f = item->attribute_value & item->attribute_mask;
1533
1534 /* Mask away directory-specific flags */
1535 if (!S_ISDIR(st->st_mode))
1536 f &= ~FS_DIRSYNC_FL;
1537
1538 procfs_fd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_NOATIME);
1539 if (procfs_fd < 0)
1540 return log_error_errno(procfs_fd, "Failed to re-open '%s': %m", path);
1541
1542 unsigned previous, current;
1543 r = chattr_full(procfs_fd, NULL, f, item->attribute_mask, &previous, &current, CHATTR_FALLBACK_BITWISE);
1544 if (r == -ENOANO)
1545 log_warning("Cannot set file attributes for '%s', maybe due to incompatibility in specified attributes, "
1546 "previous=0x%08x, current=0x%08x, expected=0x%08x, ignoring.",
1547 path, previous, current, (previous & ~item->attribute_mask) | (f & item->attribute_mask));
1548 else if (r < 0)
1549 log_full_errno(ERRNO_IS_NOT_SUPPORTED(r) ? LOG_DEBUG : LOG_WARNING, r,
1550 "Cannot set file attributes for '%s', value=0x%08x, mask=0x%08x, ignoring: %m",
1551 path, item->attribute_value, item->attribute_mask);
1552
1553 return 0;
1554 }
1555
1556 static int path_set_attribute(Item *item, const char *path, CreationMode creation) {
1557 _cleanup_close_ int fd = -EBADF;
1558
1559 if (!item->attribute_set || item->attribute_mask == 0)
1560 return 0;
1561
1562 fd = path_open_safe(path);
1563 if (fd < 0)
1564 return fd;
1565
1566 return fd_set_attribute(item, fd, path, /* st= */ NULL, creation);
1567 }
1568
1569 static int write_argument_data(Item *i, int fd, const char *path) {
1570 int r;
1571
1572 assert(i);
1573 assert(fd >= 0);
1574 assert(path);
1575
1576 if (item_binary_argument_size(i) == 0)
1577 return 0;
1578
1579 assert(item_binary_argument(i));
1580
1581 log_debug("Writing to \"%s\".", path);
1582
1583 r = loop_write(fd, item_binary_argument(i), item_binary_argument_size(i), /* do_poll= */ false);
1584 if (r < 0)
1585 return log_error_errno(r, "Failed to write file \"%s\": %m", path);
1586
1587 return 0;
1588 }
1589
1590 static int write_one_file(Item *i, const char *path, CreationMode creation) {
1591 _cleanup_close_ int fd = -EBADF, dir_fd = -EBADF;
1592 _cleanup_free_ char *bn = NULL;
1593 int r;
1594
1595 assert(i);
1596 assert(path);
1597 assert(i->type == WRITE_FILE);
1598
1599 r = path_extract_filename(path, &bn);
1600 if (r < 0)
1601 return log_error_errno(r, "Failed to extract filename from path '%s': %m", path);
1602 if (r == O_DIRECTORY)
1603 return log_error_errno(SYNTHETIC_ERRNO(EISDIR), "Cannot open path '%s' for writing, is a directory.", path);
1604
1605 /* Validate the path and keep the fd on the directory for opening the file so we're sure that it
1606 * can't be changed behind our back. */
1607 dir_fd = path_open_parent_safe(path, i->allow_failure);
1608 if (dir_fd < 0)
1609 return dir_fd;
1610
1611 /* Follows symlinks */
1612 fd = openat(dir_fd, bn,
1613 O_NONBLOCK|O_CLOEXEC|O_WRONLY|O_NOCTTY|(i->append_or_force ? O_APPEND : 0),
1614 i->mode);
1615 if (fd < 0) {
1616 if (errno == ENOENT) {
1617 log_debug_errno(errno, "Not writing missing file \"%s\": %m", path);
1618 return 0;
1619 }
1620
1621 if (i->allow_failure)
1622 return log_debug_errno(errno, "Failed to open file \"%s\", ignoring: %m", path);
1623
1624 return log_error_errno(errno, "Failed to open file \"%s\": %m", path);
1625 }
1626
1627 /* 'w' is allowed to write into any kind of files. */
1628
1629 r = write_argument_data(i, fd, path);
1630 if (r < 0)
1631 return r;
1632
1633 return fd_set_perms(i, fd, path, NULL, creation);
1634 }
1635
1636 static int create_file(Item *i, const char *path) {
1637 _cleanup_close_ int fd = -EBADF, dir_fd = -EBADF;
1638 _cleanup_free_ char *bn = NULL;
1639 struct stat stbuf, *st = NULL;
1640 CreationMode creation;
1641 int r = 0;
1642
1643 assert(i);
1644 assert(path);
1645 assert(i->type == CREATE_FILE);
1646
1647 /* 'f' operates on regular files exclusively. */
1648
1649 r = path_extract_filename(path, &bn);
1650 if (r < 0)
1651 return log_error_errno(r, "Failed to extract filename from path '%s': %m", path);
1652 if (r == O_DIRECTORY)
1653 return log_error_errno(SYNTHETIC_ERRNO(EISDIR), "Cannot open path '%s' for writing, is a directory.", path);
1654
1655 /* Validate the path and keep the fd on the directory for opening the file so we're sure that it
1656 * can't be changed behind our back. */
1657 dir_fd = path_open_parent_safe(path, i->allow_failure);
1658 if (dir_fd < 0)
1659 return dir_fd;
1660
1661 WITH_UMASK(0000) {
1662 mac_selinux_create_file_prepare(path, S_IFREG);
1663 fd = RET_NERRNO(openat(dir_fd, bn, O_CREAT|O_EXCL|O_NOFOLLOW|O_NONBLOCK|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode));
1664 mac_selinux_create_file_clear();
1665 }
1666
1667 if (fd < 0) {
1668 /* Even on a read-only filesystem, open(2) returns EEXIST if the file already exists. It
1669 * returns EROFS only if it needs to create the file. */
1670 if (fd != -EEXIST)
1671 return log_error_errno(fd, "Failed to create file %s: %m", path);
1672
1673 /* Re-open the file. At that point it must exist since open(2) failed with EEXIST. We still
1674 * need to check if the perms/mode need to be changed. For read-only filesystems, we let
1675 * fd_set_perms() report the error if the perms need to be modified. */
1676 fd = openat(dir_fd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH, i->mode);
1677 if (fd < 0)
1678 return log_error_errno(errno, "Failed to re-open file %s: %m", path);
1679
1680 if (fstat(fd, &stbuf) < 0)
1681 return log_error_errno(errno, "stat(%s) failed: %m", path);
1682
1683 if (!S_ISREG(stbuf.st_mode))
1684 return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
1685 "%s exists and is not a regular file.",
1686 path);
1687
1688 st = &stbuf;
1689 creation = CREATION_EXISTING;
1690 } else {
1691 r = write_argument_data(i, fd, path);
1692 if (r < 0)
1693 return r;
1694
1695 creation = CREATION_NORMAL;
1696 }
1697
1698 return fd_set_perms(i, fd, path, st, creation);
1699 }
1700
1701 static int truncate_file(Item *i, const char *path) {
1702 _cleanup_close_ int fd = -EBADF, dir_fd = -EBADF;
1703 _cleanup_free_ char *bn = NULL;
1704 struct stat stbuf, *st = NULL;
1705 CreationMode creation;
1706 bool erofs = false;
1707 int r = 0;
1708
1709 assert(i);
1710 assert(path);
1711 assert(i->type == TRUNCATE_FILE || (i->type == CREATE_FILE && i->append_or_force));
1712
1713 /* We want to operate on regular file exclusively especially since O_TRUNC is unspecified if the file
1714 * is neither a regular file nor a fifo nor a terminal device. Therefore we first open the file and
1715 * make sure it's a regular one before truncating it. */
1716
1717 r = path_extract_filename(path, &bn);
1718 if (r < 0)
1719 return log_error_errno(r, "Failed to extract filename from path '%s': %m", path);
1720 if (r == O_DIRECTORY)
1721 return log_error_errno(SYNTHETIC_ERRNO(EISDIR), "Cannot open path '%s' for truncation, is a directory.", path);
1722
1723 /* Validate the path and keep the fd on the directory for opening the file so we're sure that it
1724 * can't be changed behind our back. */
1725 dir_fd = path_open_parent_safe(path, i->allow_failure);
1726 if (dir_fd < 0)
1727 return dir_fd;
1728
1729 creation = CREATION_EXISTING;
1730 fd = RET_NERRNO(openat(dir_fd, bn, O_NOFOLLOW|O_NONBLOCK|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode));
1731 if (fd == -ENOENT) {
1732 creation = CREATION_NORMAL; /* Didn't work without O_CREATE, try again with */
1733
1734 WITH_UMASK(0000) {
1735 mac_selinux_create_file_prepare(path, S_IFREG);
1736 fd = RET_NERRNO(openat(dir_fd, bn, O_CREAT|O_NOFOLLOW|O_NONBLOCK|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode));
1737 mac_selinux_create_file_clear();
1738 }
1739 }
1740
1741 if (fd < 0) {
1742 if (fd != -EROFS)
1743 return log_error_errno(fd, "Failed to open/create file %s: %m", path);
1744
1745 /* On a read-only filesystem, we don't want to fail if the target is already empty and the
1746 * perms are set. So we still proceed with the sanity checks and let the remaining operations
1747 * fail with EROFS if they try to modify the target file. */
1748
1749 fd = openat(dir_fd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH, i->mode);
1750 if (fd < 0) {
1751 if (errno == ENOENT)
1752 return log_error_errno(SYNTHETIC_ERRNO(EROFS),
1753 "Cannot create file %s on a read-only file system.",
1754 path);
1755
1756 return log_error_errno(errno, "Failed to re-open file %s: %m", path);
1757 }
1758
1759 erofs = true;
1760 creation = CREATION_EXISTING;
1761 }
1762
1763 if (fstat(fd, &stbuf) < 0)
1764 return log_error_errno(errno, "stat(%s) failed: %m", path);
1765
1766 if (!S_ISREG(stbuf.st_mode))
1767 return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
1768 "%s exists and is not a regular file.",
1769 path);
1770
1771 if (stbuf.st_size > 0) {
1772 if (ftruncate(fd, 0) < 0) {
1773 r = erofs ? -EROFS : -errno;
1774 return log_error_errno(r, "Failed to truncate file %s: %m", path);
1775 }
1776 } else
1777 st = &stbuf;
1778
1779 log_debug("\"%s\" has been created.", path);
1780
1781 if (item_binary_argument(i)) {
1782 r = write_argument_data(i, fd, path);
1783 if (r < 0)
1784 return r;
1785 }
1786
1787 return fd_set_perms(i, fd, path, st, creation);
1788 }
1789
1790 static int copy_files(Item *i) {
1791 _cleanup_close_ int dfd = -EBADF, fd = -EBADF;
1792 _cleanup_free_ char *bn = NULL;
1793 struct stat st, a;
1794 int r;
1795
1796 log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path);
1797
1798 r = path_extract_filename(i->path, &bn);
1799 if (r < 0)
1800 return log_error_errno(r, "Failed to extract filename from path '%s': %m", i->path);
1801
1802 /* Validate the path and use the returned directory fd for copying the target so we're sure that the
1803 * path can't be changed behind our back. */
1804 dfd = path_open_parent_safe(i->path, i->allow_failure);
1805 if (dfd < 0)
1806 return dfd;
1807
1808 r = copy_tree_at(AT_FDCWD, i->argument,
1809 dfd, bn,
1810 i->uid_set ? i->uid : UID_INVALID,
1811 i->gid_set ? i->gid : GID_INVALID,
1812 COPY_REFLINK | ((i->append_or_force) ? COPY_MERGE : COPY_MERGE_EMPTY) | COPY_MAC_CREATE | COPY_HARDLINKS,
1813 NULL);
1814
1815 fd = openat(dfd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH);
1816 if (fd < 0) {
1817 if (r < 0) /* Look at original error first */
1818 return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
1819
1820 return log_error_errno(errno, "Failed to openat(%s): %m", i->path);
1821 }
1822
1823 if (fstat(fd, &st) < 0)
1824 return log_error_errno(errno, "Failed to fstat(%s): %m", i->path);
1825
1826 if (stat(i->argument, &a) < 0)
1827 return log_error_errno(errno, "Failed to stat(%s): %m", i->argument);
1828
1829 if (((st.st_mode ^ a.st_mode) & S_IFMT) != 0) {
1830 log_debug("Can't copy to %s, file exists already and is of different type", i->path);
1831 return 0;
1832 }
1833
1834 return fd_set_perms(i, fd, i->path, &st, _CREATION_MODE_INVALID);
1835 }
1836
1837 static int create_directory_or_subvolume(
1838 const char *path,
1839 mode_t mode,
1840 bool subvol,
1841 bool allow_failure,
1842 struct stat *ret_st,
1843 CreationMode *ret_creation) {
1844
1845 _cleanup_free_ char *bn = NULL;
1846 _cleanup_close_ int pfd = -EBADF;
1847 CreationMode creation;
1848 struct stat st;
1849 int r, fd;
1850
1851 assert(path);
1852
1853 r = path_extract_filename(path, &bn);
1854 if (r < 0)
1855 return log_error_errno(r, "Failed to extract filename from path '%s': %m", path);
1856
1857 pfd = path_open_parent_safe(path, allow_failure);
1858 if (pfd < 0)
1859 return pfd;
1860
1861 if (subvol) {
1862 r = getenv_bool("SYSTEMD_TMPFILES_FORCE_SUBVOL");
1863 if (r < 0) {
1864 if (r != -ENXIO) /* env var is unset */
1865 log_warning_errno(r, "Cannot parse value of $SYSTEMD_TMPFILES_FORCE_SUBVOL, ignoring.");
1866 r = btrfs_is_subvol(empty_to_root(arg_root)) > 0;
1867 }
1868 if (r == 0)
1869 /* Don't create a subvolume unless the root directory is one, too. We do this under
1870 * the assumption that if the root directory is just a plain directory (i.e. very
1871 * light-weight), we shouldn't try to split it up into subvolumes (i.e. more
1872 * heavy-weight). Thus, chroot() environments and suchlike will get a full brtfs
1873 * subvolume set up below their tree only if they specifically set up a btrfs
1874 * subvolume for the root dir too. */
1875
1876 subvol = false;
1877 else {
1878 WITH_UMASK((~mode) & 0777)
1879 r = btrfs_subvol_make_fd(pfd, bn);
1880 }
1881 } else
1882 r = 0;
1883
1884 if (!subvol || ERRNO_IS_NOT_SUPPORTED(r))
1885 WITH_UMASK(0000)
1886 r = mkdirat_label(pfd, bn, mode);
1887
1888 creation = r >= 0 ? CREATION_NORMAL : CREATION_EXISTING;
1889
1890 fd = openat(pfd, bn, O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY|O_PATH);
1891 if (fd < 0) {
1892 /* We couldn't open it because it is not actually a directory? */
1893 if (errno == ENOTDIR)
1894 return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "\"%s\" already exists and is not a directory.", path);
1895
1896 /* Then look at the original error */
1897 if (r < 0)
1898 return log_full_errno(allow_failure ? LOG_INFO : LOG_ERR,
1899 r,
1900 "Failed to create directory or subvolume \"%s\"%s: %m",
1901 path,
1902 allow_failure ? ", ignoring" : "");
1903
1904 return log_error_errno(errno, "Failed to open directory/subvolume we just created '%s': %m", path);
1905 }
1906
1907 if (fstat(fd, &st) < 0)
1908 return log_error_errno(errno, "Failed to fstat(%s): %m", path);
1909
1910 assert(S_ISDIR(st.st_mode)); /* we used O_DIRECTORY above */
1911
1912 log_debug("%s directory \"%s\".", creation_mode_verb_to_string(creation), path);
1913
1914 if (ret_st)
1915 *ret_st = st;
1916 if (ret_creation)
1917 *ret_creation = creation;
1918
1919 return fd;
1920 }
1921
1922 static int create_directory(Item *i, const char *path) {
1923 _cleanup_close_ int fd = -EBADF;
1924 CreationMode creation;
1925 struct stat st;
1926
1927 assert(i);
1928 assert(IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY));
1929
1930 fd = create_directory_or_subvolume(path, i->mode, /* subvol= */ false, i->allow_failure, &st, &creation);
1931 if (fd == -EEXIST)
1932 return 0;
1933 if (fd < 0)
1934 return fd;
1935
1936 return fd_set_perms(i, fd, path, &st, creation);
1937 }
1938
1939 static int create_subvolume(Item *i, const char *path) {
1940 _cleanup_close_ int fd = -EBADF;
1941 CreationMode creation;
1942 struct stat st;
1943 int r, q = 0;
1944
1945 assert(i);
1946 assert(IN_SET(i->type, CREATE_SUBVOLUME, CREATE_SUBVOLUME_NEW_QUOTA, CREATE_SUBVOLUME_INHERIT_QUOTA));
1947
1948 fd = create_directory_or_subvolume(path, i->mode, /* subvol = */ true, i->allow_failure, &st, &creation);
1949 if (fd == -EEXIST)
1950 return 0;
1951 if (fd < 0)
1952 return fd;
1953
1954 if (creation == CREATION_NORMAL &&
1955 IN_SET(i->type, CREATE_SUBVOLUME_NEW_QUOTA, CREATE_SUBVOLUME_INHERIT_QUOTA)) {
1956 r = btrfs_subvol_auto_qgroup_fd(fd, 0, i->type == CREATE_SUBVOLUME_NEW_QUOTA);
1957 if (r == -ENOTTY)
1958 log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (unsupported fs or dir not a subvolume): %m", i->path);
1959 else if (r == -EROFS)
1960 log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (fs is read-only).", i->path);
1961 else if (r == -ENOTCONN)
1962 log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (quota support is disabled).", i->path);
1963 else if (r < 0)
1964 q = log_error_errno(r, "Failed to adjust quota for subvolume \"%s\": %m", i->path);
1965 else if (r > 0)
1966 log_debug("Adjusted quota for subvolume \"%s\".", i->path);
1967 else if (r == 0)
1968 log_debug("Quota for subvolume \"%s\" already in place, no change made.", i->path);
1969 }
1970
1971 r = fd_set_perms(i, fd, path, &st, creation);
1972 if (q < 0) /* prefer the quota change error from above */
1973 return q;
1974
1975 return r;
1976 }
1977
1978 static int empty_directory(Item *i, const char *path, CreationMode creation) {
1979 _cleanup_close_ int fd = -EBADF;
1980 struct stat st;
1981 int r;
1982
1983 assert(i);
1984 assert(i->type == EMPTY_DIRECTORY);
1985
1986 r = chase(path, arg_root, CHASE_SAFE|CHASE_WARN, NULL, &fd);
1987 if (r == -ENOLINK) /* Unsafe symlink: already covered by CHASE_WARN */
1988 return r;
1989 if (r == -ENOENT) {
1990 /* Option "e" operates only on existing objects. Do not print errors about non-existent files
1991 * or directories */
1992 log_debug_errno(r, "Skipping missing directory: %s", path);
1993 return 0;
1994 }
1995 if (r < 0)
1996 return log_error_errno(r, "Failed to open directory '%s': %m", path);
1997
1998 if (fstat(fd, &st) < 0)
1999 return log_error_errno(errno, "Failed to fstat(%s): %m", path);
2000 if (!S_ISDIR(st.st_mode)) {
2001 log_warning("'%s' already exists and is not a directory.", path);
2002 return 0;
2003 }
2004
2005 return fd_set_perms(i, fd, path, &st, creation);
2006 }
2007
2008 static int create_device(Item *i, mode_t file_type) {
2009 _cleanup_close_ int dfd = -EBADF, fd = -EBADF;
2010 _cleanup_free_ char *bn = NULL;
2011 CreationMode creation;
2012 struct stat st;
2013 int r;
2014
2015 assert(i);
2016 assert(IN_SET(i->type, CREATE_BLOCK_DEVICE, CREATE_CHAR_DEVICE));
2017 assert(IN_SET(file_type, S_IFBLK, S_IFCHR));
2018
2019 r = path_extract_filename(i->path, &bn);
2020 if (r < 0)
2021 return log_error_errno(r, "Failed to extract filename from path '%s': %m", i->path);
2022 if (r == O_DIRECTORY)
2023 return log_error_errno(SYNTHETIC_ERRNO(EISDIR), "Cannot open path '%s' for creating device node, is a directory.", i->path);
2024
2025 /* Validate the path and use the returned directory fd for copying the target so we're sure that the
2026 * path can't be changed behind our back. */
2027 dfd = path_open_parent_safe(i->path, i->allow_failure);
2028 if (dfd < 0)
2029 return dfd;
2030
2031 WITH_UMASK(0000) {
2032 mac_selinux_create_file_prepare(i->path, file_type);
2033 r = RET_NERRNO(mknodat(dfd, bn, i->mode | file_type, i->major_minor));
2034 mac_selinux_create_file_clear();
2035 }
2036 creation = r >= 0 ? CREATION_NORMAL : CREATION_EXISTING;
2037
2038 /* Try to open the inode via O_PATH, regardless if we could create it or not. Maybe everything is in
2039 * order anyway and we hence can ignore the error to create the device node */
2040 fd = openat(dfd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH);
2041 if (fd < 0) {
2042 /* OK, so opening the inode failed, let's look at the original error then. */
2043
2044 if (r < 0) {
2045 if (ERRNO_IS_PRIVILEGE(r))
2046 goto handle_privilege;
2047
2048 return log_error_errno(r, "Failed to create device node '%s': %m", i->path);
2049 }
2050
2051 return log_error_errno(errno, "Failed to open device node '%s' we just created: %m", i->path);
2052 }
2053
2054 if (fstat(fd, &st) < 0)
2055 return log_error_errno(errno, "Failed to fstat(%s): %m", i->path);
2056
2057 if (((st.st_mode ^ file_type) & S_IFMT) != 0) {
2058
2059 if (i->append_or_force) {
2060 fd = safe_close(fd);
2061
2062 WITH_UMASK(0000) {
2063 mac_selinux_create_file_prepare(i->path, file_type);
2064 r = mknodat_atomic(dfd, bn, i->mode | file_type, i->major_minor);
2065 mac_selinux_create_file_clear();
2066 }
2067 if (ERRNO_IS_PRIVILEGE(r))
2068 goto handle_privilege;
2069 if (IN_SET(r, -EISDIR, -EEXIST, -ENOTEMPTY)) {
2070 r = rm_rf_child(dfd, bn, REMOVE_PHYSICAL);
2071 if (r < 0)
2072 return log_error_errno(r, "rm -rf %s failed: %m", i->path);
2073
2074 mac_selinux_create_file_prepare(i->path, file_type);
2075 r = RET_NERRNO(mknodat(dfd, bn, i->mode | file_type, i->major_minor));
2076 mac_selinux_create_file_clear();
2077 }
2078 if (r < 0)
2079 return log_error_errno(r, "Failed to create device node '%s': %m", i->path);
2080
2081 fd = openat(dfd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH);
2082 if (fd < 0)
2083 return log_error_errno(errno, "Failed to open device node we just created '%s': %m", i->path);
2084
2085 /* Validate type before change ownership below */
2086 if (fstat(fd, &st) < 0)
2087 return log_error_errno(errno, "Failed to fstat(%s): %m", i->path);
2088
2089 if (((st.st_mode ^ file_type) & S_IFMT) != 0)
2090 return log_error_errno(SYNTHETIC_ERRNO(EBADF), "Device node we just created is not a device node, refusing.");
2091
2092 creation = CREATION_FORCE;
2093 } else {
2094 log_warning("\"%s\" already exists and is not a device node.", i->path);
2095 return 0;
2096 }
2097 }
2098
2099 log_debug("%s %s device node \"%s\" %u:%u.",
2100 creation_mode_verb_to_string(creation),
2101 i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
2102 i->path, major(i->mode), minor(i->mode));
2103
2104 return fd_set_perms(i, fd, i->path, &st, creation);
2105
2106 handle_privilege:
2107 log_debug_errno(r,
2108 "We lack permissions, possibly because of cgroup configuration; "
2109 "skipping creation of device node '%s'.", i->path);
2110 return 0;
2111 }
2112
2113 static int create_fifo(Item *i) {
2114 _cleanup_close_ int pfd = -EBADF, fd = -EBADF;
2115 _cleanup_free_ char *bn = NULL;
2116 CreationMode creation;
2117 struct stat st;
2118 int r;
2119
2120 assert(i);
2121 assert(i->type == CREATE_FIFO);
2122
2123 r = path_extract_filename(i->path, &bn);
2124 if (r < 0)
2125 return log_error_errno(r, "Failed to extract filename from path '%s': %m", i->path);
2126 if (r == O_DIRECTORY)
2127 return log_error_errno(SYNTHETIC_ERRNO(EISDIR), "Cannot open path '%s' for creating FIFO, is a directory.", i->path);
2128
2129 pfd = path_open_parent_safe(i->path, i->allow_failure);
2130 if (pfd < 0)
2131 return pfd;
2132
2133 WITH_UMASK(0000) {
2134 mac_selinux_create_file_prepare(i->path, S_IFIFO);
2135 r = RET_NERRNO(mkfifoat(pfd, bn, i->mode));
2136 mac_selinux_create_file_clear();
2137 }
2138
2139 creation = r >= 0 ? CREATION_NORMAL : CREATION_EXISTING;
2140
2141 /* Open the inode via O_PATH, regardless if we managed to create it or not. Maybe it is already the FIFO we want */
2142 fd = openat(pfd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH);
2143 if (fd < 0) {
2144 if (r < 0)
2145 return log_error_errno(r, "Failed to create FIFO %s: %m", i->path); /* original error! */
2146
2147 return log_error_errno(errno, "Failed to open FIFO we just created %s: %m", i->path);
2148 }
2149
2150 if (fstat(fd, &st) < 0)
2151 return log_error_errno(errno, "Failed to fstat(%s): %m", i->path);
2152
2153 if (!S_ISFIFO(st.st_mode)) {
2154
2155 if (i->append_or_force) {
2156 fd = safe_close(fd);
2157
2158 WITH_UMASK(0000) {
2159 mac_selinux_create_file_prepare(i->path, S_IFIFO);
2160 r = mkfifoat_atomic(pfd, bn, i->mode);
2161 mac_selinux_create_file_clear();
2162 }
2163 if (IN_SET(r, -EISDIR, -EEXIST, -ENOTEMPTY)) {
2164 r = rm_rf_child(pfd, bn, REMOVE_PHYSICAL);
2165 if (r < 0)
2166 return log_error_errno(r, "rm -rf %s failed: %m", i->path);
2167
2168 mac_selinux_create_file_prepare(i->path, S_IFIFO);
2169 r = RET_NERRNO(mkfifoat(pfd, bn, i->mode));
2170 mac_selinux_create_file_clear();
2171 }
2172 if (r < 0)
2173 return log_error_errno(r, "Failed to create FIFO %s: %m", i->path);
2174
2175 fd = openat(pfd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH);
2176 if (fd < 0)
2177 return log_error_errno(errno, "Failed to open FIFO we just created '%s': %m", i->path);
2178
2179 /* Validate type before change ownership below */
2180 if (fstat(fd, &st) < 0)
2181 return log_error_errno(errno, "Failed to fstat(%s): %m", i->path);
2182
2183 if (!S_ISFIFO(st.st_mode))
2184 return log_error_errno(SYNTHETIC_ERRNO(EBADF), "FIFO inode we just created is not a FIFO, refusing.");
2185
2186 creation = CREATION_FORCE;
2187 } else {
2188 log_warning("\"%s\" already exists and is not a FIFO.", i->path);
2189 return 0;
2190 }
2191 }
2192
2193 log_debug("%s fifo \"%s\".", creation_mode_verb_to_string(creation), i->path);
2194
2195 return fd_set_perms(i, fd, i->path, &st, creation);
2196 }
2197
2198 static int create_symlink(Item *i) {
2199 _cleanup_close_ int pfd = -EBADF, fd = -EBADF;
2200 _cleanup_free_ char *bn = NULL;
2201 CreationMode creation;
2202 struct stat st;
2203 bool good = false;
2204 int r;
2205
2206 assert(i);
2207
2208 r = path_extract_filename(i->path, &bn);
2209 if (r < 0)
2210 return log_error_errno(r, "Failed to extract filename from path '%s': %m", i->path);
2211 if (r == O_DIRECTORY)
2212 return log_error_errno(SYNTHETIC_ERRNO(EISDIR), "Cannot open path '%s' for creating FIFO, is a directory.", i->path);
2213
2214 pfd = path_open_parent_safe(i->path, i->allow_failure);
2215 if (pfd < 0)
2216 return pfd;
2217
2218 mac_selinux_create_file_prepare(i->path, S_IFLNK);
2219 r = RET_NERRNO(symlinkat(i->argument, pfd, bn));
2220 mac_selinux_create_file_clear();
2221
2222 creation = r >= 0 ? CREATION_NORMAL : CREATION_EXISTING;
2223
2224 fd = openat(pfd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH);
2225 if (fd < 0) {
2226 if (r < 0)
2227 return log_error_errno(r, "Failed to create symlink '%s': %m", i->path); /* original error! */
2228
2229 return log_error_errno(errno, "Failed to open symlink we just created '%s': %m", i->path);
2230 }
2231
2232 if (fstat(fd, &st) < 0)
2233 return log_error_errno(errno, "Failed to fstat(%s): %m", i->path);
2234
2235 if (S_ISLNK(st.st_mode)) {
2236 _cleanup_free_ char *x = NULL;
2237
2238 r = readlinkat_malloc(fd, "", &x);
2239 if (r < 0)
2240 return log_error_errno(r, "readlinkat(%s) failed: %m", i->path);
2241
2242 good = streq(x, i->argument);
2243 } else
2244 good = false;
2245
2246 if (!good) {
2247 if (!i->append_or_force) {
2248 log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
2249 return 0;
2250 }
2251
2252 fd = safe_close(fd);
2253
2254 mac_selinux_create_file_prepare(i->path, S_IFLNK);
2255 r = symlinkat_atomic_full(i->argument, pfd, bn, /* make_relative= */ false);
2256 mac_selinux_create_file_clear();
2257 if (IN_SET(r, -EISDIR, -EEXIST, -ENOTEMPTY)) {
2258 r = rm_rf_child(pfd, bn, REMOVE_PHYSICAL);
2259 if (r < 0)
2260 return log_error_errno(r, "rm -rf %s failed: %m", i->path);
2261
2262 mac_selinux_create_file_prepare(i->path, S_IFLNK);
2263 r = RET_NERRNO(symlinkat(i->argument, pfd, i->path));
2264 mac_selinux_create_file_clear();
2265 }
2266 if (r < 0)
2267 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
2268
2269 fd = openat(pfd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH);
2270 if (fd < 0)
2271 return log_error_errno(errno, "Failed to open symlink we just created '%s': %m", i->path);
2272
2273 /* Validate type before change ownership below */
2274 if (fstat(fd, &st) < 0)
2275 return log_error_errno(errno, "Failed to fstat(%s): %m", i->path);
2276
2277 if (!S_ISLNK(st.st_mode))
2278 return log_error_errno(SYNTHETIC_ERRNO(EBADF), "Symlink we just created is not a symlink, refusing.");
2279
2280 creation = CREATION_FORCE;
2281 }
2282
2283 log_debug("%s symlink \"%s\".", creation_mode_verb_to_string(creation), i->path);
2284 return fd_set_perms(i, fd, i->path, &st, creation);
2285 }
2286
2287 typedef int (*action_t)(Item *i, const char *path, CreationMode creation);
2288 typedef int (*fdaction_t)(Item *i, int fd, const char *path, const struct stat *st, CreationMode creation);
2289
2290 static int item_do(
2291 Item *i,
2292 int fd,
2293 const char *path,
2294 CreationMode creation,
2295 fdaction_t action) {
2296
2297 struct stat st;
2298 int r = 0, q;
2299
2300 assert(i);
2301 assert(path);
2302 assert(fd >= 0);
2303
2304 if (fstat(fd, &st) < 0) {
2305 r = log_error_errno(errno, "fstat() on file failed: %m");
2306 goto finish;
2307 }
2308
2309 /* This returns the first error we run into, but nevertheless tries to go on */
2310 r = action(i, fd, path, &st, creation);
2311
2312 if (S_ISDIR(st.st_mode)) {
2313 _cleanup_closedir_ DIR *d = NULL;
2314
2315 /* The passed 'fd' was opened with O_PATH. We need to convert it into a 'regular' fd before
2316 * reading the directory content. */
2317 d = opendir(FORMAT_PROC_FD_PATH(fd));
2318 if (!d) {
2319 log_error_errno(errno, "Failed to opendir() '%s': %m", FORMAT_PROC_FD_PATH(fd));
2320 if (r == 0)
2321 r = -errno;
2322 goto finish;
2323 }
2324
2325 FOREACH_DIRENT_ALL(de, d, q = -errno; goto finish) {
2326 int de_fd;
2327
2328 if (dot_or_dot_dot(de->d_name))
2329 continue;
2330
2331 de_fd = openat(fd, de->d_name, O_NOFOLLOW|O_CLOEXEC|O_PATH);
2332 if (de_fd < 0)
2333 q = log_error_errno(errno, "Failed to open() file '%s': %m", de->d_name);
2334 else {
2335 _cleanup_free_ char *de_path = NULL;
2336
2337 de_path = path_join(path, de->d_name);
2338 if (!de_path)
2339 q = log_oom();
2340 else
2341 /* Pass ownership of dirent fd over */
2342 q = item_do(i, de_fd, de_path, CREATION_EXISTING, action);
2343 }
2344
2345 if (q < 0 && r == 0)
2346 r = q;
2347 }
2348 }
2349 finish:
2350 safe_close(fd);
2351 return r;
2352 }
2353
2354 static int glob_item(Item *i, action_t action) {
2355 _cleanup_globfree_ glob_t g = {
2356 .gl_opendir = (void *(*)(const char *)) opendir_nomod,
2357 };
2358 int r = 0, k;
2359
2360 k = safe_glob(i->path, GLOB_NOSORT|GLOB_BRACE, &g);
2361 if (k < 0 && k != -ENOENT)
2362 return log_error_errno(k, "glob(%s) failed: %m", i->path);
2363
2364 STRV_FOREACH(fn, g.gl_pathv) {
2365 /* We pass CREATION_EXISTING here, since if we are globbing for it, it always has to exist */
2366 k = action(i, *fn, CREATION_EXISTING);
2367 if (k < 0 && r == 0)
2368 r = k;
2369 }
2370
2371 return r;
2372 }
2373
2374 static int glob_item_recursively(Item *i, fdaction_t action) {
2375 _cleanup_globfree_ glob_t g = {
2376 .gl_opendir = (void *(*)(const char *)) opendir_nomod,
2377 };
2378 int r = 0, k;
2379
2380 k = safe_glob(i->path, GLOB_NOSORT|GLOB_BRACE, &g);
2381 if (k < 0 && k != -ENOENT)
2382 return log_error_errno(k, "glob(%s) failed: %m", i->path);
2383
2384 STRV_FOREACH(fn, g.gl_pathv) {
2385 _cleanup_close_ int fd = -EBADF;
2386
2387 /* Make sure we won't trigger/follow file object (such as
2388 * device nodes, automounts, ...) pointed out by 'fn' with
2389 * O_PATH. Note, when O_PATH is used, flags other than
2390 * O_CLOEXEC, O_DIRECTORY, and O_NOFOLLOW are ignored. */
2391
2392 fd = open(*fn, O_CLOEXEC|O_NOFOLLOW|O_PATH);
2393 if (fd < 0) {
2394 log_error_errno(errno, "Opening '%s' failed: %m", *fn);
2395 if (r == 0)
2396 r = -errno;
2397 continue;
2398 }
2399
2400 k = item_do(i, fd, *fn, CREATION_EXISTING, action);
2401 if (k < 0 && r == 0)
2402 r = k;
2403
2404 /* we passed fd ownership to the previous call */
2405 fd = -EBADF;
2406 }
2407
2408 return r;
2409 }
2410
2411 static int rm_if_wrong_type_safe(
2412 mode_t mode,
2413 int parent_fd,
2414 const struct stat *parent_st, /* Only used if follow_links below is true. */
2415 const char *name,
2416 int flags) {
2417 _cleanup_free_ char *parent_name = NULL;
2418 bool follow_links = !FLAGS_SET(flags, AT_SYMLINK_NOFOLLOW);
2419 struct stat st;
2420 int r;
2421
2422 assert(name);
2423 assert((mode & ~S_IFMT) == 0);
2424 assert(!follow_links || parent_st);
2425 assert((flags & ~AT_SYMLINK_NOFOLLOW) == 0);
2426
2427 if (!filename_is_valid(name))
2428 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "\"%s\" is not a valid filename.", name);
2429
2430 r = fstatat_harder(parent_fd, name, &st, flags, REMOVE_CHMOD | REMOVE_CHMOD_RESTORE);
2431 if (r < 0) {
2432 (void) fd_get_path(parent_fd, &parent_name);
2433 return log_full_errno(r == -ENOENT? LOG_DEBUG : LOG_ERR, r,
2434 "Failed to stat \"%s\" at \"%s\": %m", name, strna(parent_name));
2435 }
2436
2437 /* Fail before removing anything if this is an unsafe transition. */
2438 if (follow_links && unsafe_transition(parent_st, &st)) {
2439 (void) fd_get_path(parent_fd, &parent_name);
2440 return log_error_errno(SYNTHETIC_ERRNO(ENOLINK),
2441 "Unsafe transition from \"%s\" to \"%s\".", parent_name, name);
2442 }
2443
2444 if ((st.st_mode & S_IFMT) == mode)
2445 return 0;
2446
2447 (void) fd_get_path(parent_fd, &parent_name);
2448 log_notice("Wrong file type 0o%o; rm -rf \"%s/%s\"", st.st_mode & S_IFMT, strna(parent_name), name);
2449
2450 /* If the target of the symlink was the wrong type, the link needs to be removed instead of the
2451 * target, so make sure it is identified as a link and not a directory. */
2452 if (follow_links) {
2453 r = fstatat_harder(parent_fd, name, &st, AT_SYMLINK_NOFOLLOW, REMOVE_CHMOD | REMOVE_CHMOD_RESTORE);
2454 if (r < 0)
2455 return log_error_errno(r, "Failed to stat \"%s\" at \"%s\": %m", name, strna(parent_name));
2456 }
2457
2458 /* Do not remove mount points. */
2459 r = fd_is_mount_point(parent_fd, name, follow_links ? AT_SYMLINK_FOLLOW : 0);
2460 if (r < 0)
2461 (void) log_warning_errno(r, "Failed to check if \"%s/%s\" is a mount point: %m; Continuing",
2462 strna(parent_name), name);
2463 else if (r > 0)
2464 return log_error_errno(SYNTHETIC_ERRNO(EBUSY),
2465 "Not removing \"%s/%s\" because it is a mount point.", strna(parent_name), name);
2466
2467 if ((st.st_mode & S_IFMT) == S_IFDIR) {
2468 _cleanup_close_ int child_fd = -EBADF;
2469
2470 child_fd = openat(parent_fd, name, O_NOCTTY | O_CLOEXEC | O_DIRECTORY);
2471 if (child_fd < 0)
2472 return log_error_errno(errno, "Failed to open \"%s\" at \"%s\": %m", name, strna(parent_name));
2473
2474 r = rm_rf_children(TAKE_FD(child_fd), REMOVE_ROOT|REMOVE_SUBVOLUME|REMOVE_PHYSICAL, &st);
2475 if (r < 0)
2476 return log_error_errno(r, "Failed to remove contents of \"%s\" at \"%s\": %m", name, strna(parent_name));
2477
2478 r = unlinkat_harder(parent_fd, name, AT_REMOVEDIR, REMOVE_CHMOD | REMOVE_CHMOD_RESTORE);
2479 } else
2480 r = unlinkat_harder(parent_fd, name, 0, REMOVE_CHMOD | REMOVE_CHMOD_RESTORE);
2481 if (r < 0)
2482 return log_error_errno(r, "Failed to remove \"%s\" at \"%s\": %m", name, strna(parent_name));
2483
2484 /* This is covered by the log_notice "Wrong file type..." It is logged earlier because it gives
2485 * context to other error messages that might follow. */
2486 return -ENOENT;
2487 }
2488
2489 /* If child_mode is non-zero, rm_if_wrong_type_safe will be executed for the last path component. */
2490 static int mkdir_parents_rm_if_wrong_type(mode_t child_mode, const char *path) {
2491 _cleanup_close_ int parent_fd = -EBADF;
2492 struct stat parent_st;
2493 size_t path_len;
2494 int r;
2495
2496 assert(path);
2497 assert((child_mode & ~S_IFMT) == 0);
2498
2499 path_len = strlen(path);
2500
2501 if (!is_path(path))
2502 /* rm_if_wrong_type_safe already logs errors. */
2503 return child_mode != 0 ? rm_if_wrong_type_safe(child_mode, AT_FDCWD, NULL, path, AT_SYMLINK_NOFOLLOW) : 0;
2504
2505 if (child_mode != 0 && endswith(path, "/"))
2506 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2507 "Trailing path separators are only allowed if child_mode is not set; got \"%s\"", path);
2508
2509 /* Get the parent_fd and stat. */
2510 parent_fd = openat(AT_FDCWD, path_is_absolute(path) ? "/" : ".", O_NOCTTY | O_CLOEXEC | O_DIRECTORY);
2511 if (parent_fd < 0)
2512 return log_error_errno(errno, "Failed to open root: %m");
2513
2514 if (fstat(parent_fd, &parent_st) < 0)
2515 return log_error_errno(errno, "Failed to stat root: %m");
2516
2517 /* Check every parent directory in the path, except the last component */
2518 for (const char *e = path;;) {
2519 _cleanup_close_ int next_fd = -EBADF;
2520 char t[path_len + 1];
2521 const char *s;
2522
2523 /* Find the start of the next path component. */
2524 s = e + strspn(e, "/");
2525 /* Find the end of the next path component. */
2526 e = s + strcspn(s, "/");
2527
2528 /* Copy the path component to t so it can be a null terminated string. */
2529 *((char*) mempcpy(t, s, e - s)) = 0;
2530
2531 /* Is this the last component? If so, then check the type */
2532 if (*e == 0)
2533 return child_mode != 0 ? rm_if_wrong_type_safe(child_mode, parent_fd, &parent_st, t, AT_SYMLINK_NOFOLLOW) : 0;
2534
2535 r = rm_if_wrong_type_safe(S_IFDIR, parent_fd, &parent_st, t, 0);
2536 /* Remove dangling symlinks. */
2537 if (r == -ENOENT)
2538 r = rm_if_wrong_type_safe(S_IFDIR, parent_fd, &parent_st, t, AT_SYMLINK_NOFOLLOW);
2539 if (r == -ENOENT) {
2540 WITH_UMASK(0000)
2541 r = mkdirat_label(parent_fd, t, 0755);
2542 if (r < 0) {
2543 _cleanup_free_ char *parent_name = NULL;
2544
2545 (void) fd_get_path(parent_fd, &parent_name);
2546 return log_error_errno(r, "Failed to mkdir \"%s\" at \"%s\": %m", t, strnull(parent_name));
2547 }
2548 } else if (r < 0)
2549 /* rm_if_wrong_type_safe already logs errors. */
2550 return r;
2551
2552 next_fd = RET_NERRNO(openat(parent_fd, t, O_NOCTTY | O_CLOEXEC | O_DIRECTORY));
2553 if (next_fd < 0) {
2554 _cleanup_free_ char *parent_name = NULL;
2555
2556 (void) fd_get_path(parent_fd, &parent_name);
2557 return log_error_errno(next_fd, "Failed to open \"%s\" at \"%s\": %m", t, strnull(parent_name));
2558 }
2559 r = RET_NERRNO(fstat(next_fd, &parent_st));
2560 if (r < 0) {
2561 _cleanup_free_ char *parent_name = NULL;
2562
2563 (void) fd_get_path(parent_fd, &parent_name);
2564 return log_error_errno(r, "Failed to stat \"%s\" at \"%s\": %m", t, strnull(parent_name));
2565 }
2566
2567 close_and_replace(parent_fd, next_fd);
2568 }
2569 }
2570
2571 static int mkdir_parents_item(Item *i, mode_t child_mode) {
2572 int r;
2573 if (i->try_replace) {
2574 r = mkdir_parents_rm_if_wrong_type(child_mode, i->path);
2575 if (r < 0 && r != -ENOENT)
2576 return r;
2577 } else
2578 WITH_UMASK(0000)
2579 (void) mkdir_parents_label(i->path, 0755);
2580
2581 return 0;
2582 }
2583
2584 static int create_item(Item *i) {
2585 int r;
2586
2587 assert(i);
2588
2589 log_debug("Running create action for entry %c %s", (char) i->type, i->path);
2590
2591 switch (i->type) {
2592
2593 case IGNORE_PATH:
2594 case IGNORE_DIRECTORY_PATH:
2595 case REMOVE_PATH:
2596 case RECURSIVE_REMOVE_PATH:
2597 return 0;
2598
2599 case TRUNCATE_FILE:
2600 case CREATE_FILE:
2601 r = mkdir_parents_item(i, S_IFREG);
2602 if (r < 0)
2603 return r;
2604
2605 if ((i->type == CREATE_FILE && i->append_or_force) || i->type == TRUNCATE_FILE)
2606 r = truncate_file(i, i->path);
2607 else
2608 r = create_file(i, i->path);
2609 if (r < 0)
2610 return r;
2611 break;
2612
2613 case COPY_FILES:
2614 r = mkdir_parents_item(i, 0);
2615 if (r < 0)
2616 return r;
2617
2618 r = copy_files(i);
2619 if (r < 0)
2620 return r;
2621 break;
2622
2623 case WRITE_FILE:
2624 r = glob_item(i, write_one_file);
2625 if (r < 0)
2626 return r;
2627
2628 break;
2629
2630 case CREATE_DIRECTORY:
2631 case TRUNCATE_DIRECTORY:
2632 r = mkdir_parents_item(i, S_IFDIR);
2633 if (r < 0)
2634 return r;
2635
2636 r = create_directory(i, i->path);
2637 if (r < 0)
2638 return r;
2639 break;
2640
2641 case CREATE_SUBVOLUME:
2642 case CREATE_SUBVOLUME_INHERIT_QUOTA:
2643 case CREATE_SUBVOLUME_NEW_QUOTA:
2644 r = mkdir_parents_item(i, S_IFDIR);
2645 if (r < 0)
2646 return r;
2647
2648 r = create_subvolume(i, i->path);
2649 if (r < 0)
2650 return r;
2651 break;
2652
2653 case EMPTY_DIRECTORY:
2654 r = glob_item(i, empty_directory);
2655 if (r < 0)
2656 return r;
2657 break;
2658
2659 case CREATE_FIFO:
2660 r = mkdir_parents_item(i, S_IFIFO);
2661 if (r < 0)
2662 return r;
2663
2664 r = create_fifo(i);
2665 if (r < 0)
2666 return r;
2667 break;
2668
2669 case CREATE_SYMLINK:
2670 r = mkdir_parents_item(i, S_IFLNK);
2671 if (r < 0)
2672 return r;
2673
2674 r = create_symlink(i);
2675 if (r < 0)
2676 return r;
2677
2678 break;
2679
2680 case CREATE_BLOCK_DEVICE:
2681 case CREATE_CHAR_DEVICE:
2682 if (have_effective_cap(CAP_MKNOD) <= 0) {
2683 /* In a container we lack CAP_MKNOD. We shouldn't attempt to create the device node in that
2684 * case to avoid noise, and we don't support virtualized devices in containers anyway. */
2685
2686 log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
2687 return 0;
2688 }
2689
2690 r = mkdir_parents_item(i, i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR);
2691 if (r < 0)
2692 return r;
2693
2694 r = create_device(i, i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR);
2695 if (r < 0)
2696 return r;
2697
2698 break;
2699
2700 case ADJUST_MODE:
2701 case RELABEL_PATH:
2702 r = glob_item(i, path_set_perms);
2703 if (r < 0)
2704 return r;
2705 break;
2706
2707 case RECURSIVE_RELABEL_PATH:
2708 r = glob_item_recursively(i, fd_set_perms);
2709 if (r < 0)
2710 return r;
2711 break;
2712
2713 case SET_XATTR:
2714 r = glob_item(i, path_set_xattrs);
2715 if (r < 0)
2716 return r;
2717 break;
2718
2719 case RECURSIVE_SET_XATTR:
2720 r = glob_item_recursively(i, fd_set_xattrs);
2721 if (r < 0)
2722 return r;
2723 break;
2724
2725 case SET_ACL:
2726 r = glob_item(i, path_set_acls);
2727 if (r < 0)
2728 return r;
2729 break;
2730
2731 case RECURSIVE_SET_ACL:
2732 r = glob_item_recursively(i, fd_set_acls);
2733 if (r < 0)
2734 return r;
2735 break;
2736
2737 case SET_ATTRIBUTE:
2738 r = glob_item(i, path_set_attribute);
2739 if (r < 0)
2740 return r;
2741 break;
2742
2743 case RECURSIVE_SET_ATTRIBUTE:
2744 r = glob_item_recursively(i, fd_set_attribute);
2745 if (r < 0)
2746 return r;
2747 break;
2748 }
2749
2750 return 0;
2751 }
2752
2753 static int remove_item_instance(Item *i, const char *instance, CreationMode creation) {
2754 int r;
2755
2756 assert(i);
2757
2758 switch (i->type) {
2759
2760 case REMOVE_PATH:
2761 if (remove(instance) < 0 && errno != ENOENT)
2762 return log_error_errno(errno, "rm(%s): %m", instance);
2763
2764 break;
2765
2766 case RECURSIVE_REMOVE_PATH:
2767 /* FIXME: we probably should use dir_cleanup() here instead of rm_rf() so that 'x' is honoured. */
2768 log_debug("rm -rf \"%s\"", instance);
2769 r = rm_rf(instance, REMOVE_ROOT|REMOVE_SUBVOLUME|REMOVE_PHYSICAL);
2770 if (r < 0 && r != -ENOENT)
2771 return log_error_errno(r, "rm_rf(%s): %m", instance);
2772
2773 break;
2774
2775 default:
2776 assert_not_reached();
2777 }
2778
2779 return 0;
2780 }
2781
2782 static int remove_item(Item *i) {
2783 int r;
2784
2785 assert(i);
2786
2787 log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
2788
2789 switch (i->type) {
2790
2791 case TRUNCATE_DIRECTORY:
2792 /* FIXME: we probably should use dir_cleanup() here instead of rm_rf() so that 'x' is honoured. */
2793 log_debug("rm -rf \"%s\"", i->path);
2794 r = rm_rf(i->path, REMOVE_PHYSICAL);
2795 if (r < 0 && r != -ENOENT)
2796 return log_error_errno(r, "rm_rf(%s): %m", i->path);
2797
2798 return 0;
2799
2800 case REMOVE_PATH:
2801 case RECURSIVE_REMOVE_PATH:
2802 return glob_item(i, remove_item_instance);
2803
2804 default:
2805 return 0;
2806 }
2807 }
2808
2809 static char *age_by_to_string(AgeBy ab, bool is_dir) {
2810 static const char ab_map[] = { 'a', 'b', 'c', 'm' };
2811 size_t j = 0;
2812 char *ret;
2813
2814 ret = new(char, ELEMENTSOF(ab_map) + 1);
2815 if (!ret)
2816 return NULL;
2817
2818 for (size_t i = 0; i < ELEMENTSOF(ab_map); i++)
2819 if (FLAGS_SET(ab, 1U << i))
2820 ret[j++] = is_dir ? ascii_toupper(ab_map[i]) : ab_map[i];
2821
2822 ret[j] = 0;
2823 return ret;
2824 }
2825
2826 static int clean_item_instance(
2827 Item *i,
2828 const char* instance,
2829 CreationMode creation) {
2830
2831 _cleanup_closedir_ DIR *d = NULL;
2832 STRUCT_STATX_DEFINE(sx);
2833 int mountpoint, r;
2834 usec_t cutoff, n;
2835
2836 assert(i);
2837
2838 if (!i->age_set)
2839 return 0;
2840
2841 n = now(CLOCK_REALTIME);
2842 if (n < i->age)
2843 return 0;
2844
2845 cutoff = n - i->age;
2846
2847 d = opendir_nomod(instance);
2848 if (!d) {
2849 if (IN_SET(errno, ENOENT, ENOTDIR)) {
2850 log_debug_errno(errno, "Directory \"%s\": %m", instance);
2851 return 0;
2852 }
2853
2854 return log_error_errno(errno, "Failed to open directory %s: %m", instance);
2855 }
2856
2857 r = statx_fallback(dirfd(d), "", AT_EMPTY_PATH, STATX_MODE|STATX_INO|STATX_ATIME|STATX_MTIME, &sx);
2858 if (r < 0)
2859 return log_error_errno(r, "statx(%s) failed: %m", instance);
2860
2861 if (FLAGS_SET(sx.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT))
2862 mountpoint = FLAGS_SET(sx.stx_attributes, STATX_ATTR_MOUNT_ROOT);
2863 else {
2864 struct stat ps;
2865
2866 if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
2867 return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
2868
2869 mountpoint =
2870 sx.stx_dev_major != major(ps.st_dev) ||
2871 sx.stx_dev_minor != minor(ps.st_dev) ||
2872 sx.stx_ino != ps.st_ino;
2873 }
2874
2875 if (DEBUG_LOGGING) {
2876 _cleanup_free_ char *ab_f = NULL, *ab_d = NULL;
2877
2878 ab_f = age_by_to_string(i->age_by_file, false);
2879 if (!ab_f)
2880 return log_oom();
2881
2882 ab_d = age_by_to_string(i->age_by_dir, true);
2883 if (!ab_d)
2884 return log_oom();
2885
2886 log_debug("Cleanup threshold for %s \"%s\" is %s; age-by: %s%s",
2887 mountpoint ? "mount point" : "directory",
2888 instance,
2889 FORMAT_TIMESTAMP_STYLE(cutoff, TIMESTAMP_US),
2890 ab_f, ab_d);
2891 }
2892
2893 return dir_cleanup(i, instance, d,
2894 load_statx_timestamp_nsec(&sx.stx_atime),
2895 load_statx_timestamp_nsec(&sx.stx_mtime),
2896 cutoff * NSEC_PER_USEC,
2897 sx.stx_dev_major, sx.stx_dev_minor, mountpoint,
2898 MAX_DEPTH, i->keep_first_level,
2899 i->age_by_file, i->age_by_dir);
2900 }
2901
2902 static int clean_item(Item *i) {
2903 assert(i);
2904
2905 log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
2906
2907 switch (i->type) {
2908 case CREATE_DIRECTORY:
2909 case CREATE_SUBVOLUME:
2910 case CREATE_SUBVOLUME_INHERIT_QUOTA:
2911 case CREATE_SUBVOLUME_NEW_QUOTA:
2912 case TRUNCATE_DIRECTORY:
2913 case IGNORE_PATH:
2914 case COPY_FILES:
2915 clean_item_instance(i, i->path, CREATION_EXISTING);
2916 return 0;
2917 case EMPTY_DIRECTORY:
2918 case IGNORE_DIRECTORY_PATH:
2919 return glob_item(i, clean_item_instance);
2920 default:
2921 return 0;
2922 }
2923 }
2924
2925 static int process_item(Item *i, OperationMask operation) {
2926 OperationMask todo;
2927 _cleanup_free_ char *_path = NULL;
2928 const char *path;
2929 int r, q, p;
2930
2931 assert(i);
2932
2933 todo = operation & ~i->done;
2934 if (todo == 0) /* Everything already done? */
2935 return 0;
2936
2937 i->done |= operation;
2938
2939 path = i->path;
2940 if (string_is_glob(path)) {
2941 /* We can't easily check whether a glob matches any autofs path, so let's do the check only
2942 * for the non-glob part. */
2943
2944 r = glob_non_glob_prefix(path, &_path);
2945 if (r < 0 && r != -ENOENT)
2946 return log_debug_errno(r, "Failed to deglob path: %m");
2947 if (r >= 0)
2948 path = _path;
2949 }
2950
2951 r = chase(path, arg_root, CHASE_NO_AUTOFS|CHASE_NONEXISTENT|CHASE_WARN, NULL, NULL);
2952 if (r == -EREMOTE) {
2953 log_notice_errno(r, "Skipping %s", i->path); /* We log the configured path, to not confuse the user. */
2954 return 0;
2955 }
2956 if (r < 0)
2957 log_debug_errno(r, "Failed to determine whether '%s' is below autofs, ignoring: %m", i->path);
2958
2959 r = FLAGS_SET(operation, OPERATION_CREATE) ? create_item(i) : 0;
2960 /* Failure can only be tolerated for create */
2961 if (i->allow_failure)
2962 r = 0;
2963
2964 q = FLAGS_SET(operation, OPERATION_REMOVE) ? remove_item(i) : 0;
2965 p = FLAGS_SET(operation, OPERATION_CLEAN) ? clean_item(i) : 0;
2966
2967 return r < 0 ? r :
2968 q < 0 ? q :
2969 p;
2970 }
2971
2972 static int process_item_array(ItemArray *array, OperationMask operation) {
2973 int r = 0;
2974 size_t n;
2975
2976 assert(array);
2977
2978 /* Create any parent first. */
2979 if (FLAGS_SET(operation, OPERATION_CREATE) && array->parent)
2980 r = process_item_array(array->parent, operation & OPERATION_CREATE);
2981
2982 /* Clean up all children first */
2983 if ((operation & (OPERATION_REMOVE|OPERATION_CLEAN)) && !set_isempty(array->children)) {
2984 ItemArray *c;
2985
2986 SET_FOREACH(c, array->children) {
2987 int k;
2988
2989 k = process_item_array(c, operation & (OPERATION_REMOVE|OPERATION_CLEAN));
2990 if (k < 0 && r == 0)
2991 r = k;
2992 }
2993 }
2994
2995 for (n = 0; n < array->n_items; n++) {
2996 int k;
2997
2998 k = process_item(array->items + n, operation);
2999 if (k < 0 && r == 0)
3000 r = k;
3001 }
3002
3003 return r;
3004 }
3005
3006 static void item_free_contents(Item *i) {
3007 assert(i);
3008 free(i->path);
3009 free(i->argument);
3010 free(i->binary_argument);
3011 strv_free(i->xattrs);
3012
3013 #if HAVE_ACL
3014 if (i->acl_access)
3015 acl_free(i->acl_access);
3016
3017 if (i->acl_access_exec)
3018 acl_free(i->acl_access_exec);
3019
3020 if (i->acl_default)
3021 acl_free(i->acl_default);
3022 #endif
3023 }
3024
3025 static ItemArray* item_array_free(ItemArray *a) {
3026 size_t n;
3027
3028 if (!a)
3029 return NULL;
3030
3031 for (n = 0; n < a->n_items; n++)
3032 item_free_contents(a->items + n);
3033
3034 set_free(a->children);
3035 free(a->items);
3036 return mfree(a);
3037 }
3038
3039 static int item_compare(const Item *a, const Item *b) {
3040 /* Make sure that the ownership taking item is put first, so
3041 * that we first create the node, and then can adjust it */
3042
3043 if (takes_ownership(a->type) && !takes_ownership(b->type))
3044 return -1;
3045 if (!takes_ownership(a->type) && takes_ownership(b->type))
3046 return 1;
3047
3048 return CMP(a->type, b->type);
3049 }
3050
3051 static bool item_compatible(const Item *a, const Item *b) {
3052 assert(a);
3053 assert(b);
3054 assert(streq(a->path, b->path));
3055
3056 if (takes_ownership(a->type) && takes_ownership(b->type))
3057 /* check if the items are the same */
3058 return memcmp_nn(item_binary_argument(a), item_binary_argument_size(a),
3059 item_binary_argument(b), item_binary_argument_size(b)) == 0 &&
3060
3061 a->uid_set == b->uid_set &&
3062 a->uid == b->uid &&
3063 a->uid_only_create == b->uid_only_create &&
3064
3065 a->gid_set == b->gid_set &&
3066 a->gid == b->gid &&
3067 a->gid_only_create == b->gid_only_create &&
3068
3069 a->mode_set == b->mode_set &&
3070 a->mode == b->mode &&
3071 a->mode_only_create == b->mode_only_create &&
3072
3073 a->age_set == b->age_set &&
3074 a->age == b->age &&
3075
3076 a->age_by_file == b->age_by_file &&
3077 a->age_by_dir == b->age_by_dir &&
3078
3079 a->mask_perms == b->mask_perms &&
3080
3081 a->keep_first_level == b->keep_first_level &&
3082
3083 a->major_minor == b->major_minor;
3084
3085 return true;
3086 }
3087
3088 static bool should_include_path(const char *path) {
3089 STRV_FOREACH(prefix, arg_exclude_prefixes)
3090 if (path_startswith(path, *prefix)) {
3091 log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
3092 path, *prefix);
3093 return false;
3094 }
3095
3096 STRV_FOREACH(prefix, arg_include_prefixes)
3097 if (path_startswith(path, *prefix)) {
3098 log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
3099 return true;
3100 }
3101
3102 /* no matches, so we should include this path only if we have no allow list at all */
3103 if (strv_isempty(arg_include_prefixes))
3104 return true;
3105
3106 log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
3107 return false;
3108 }
3109
3110 static int specifier_expansion_from_arg(const Specifier *specifier_table, Item *i) {
3111 int r;
3112
3113 assert(i);
3114
3115 if (!i->argument)
3116 return 0;
3117
3118 switch (i->type) {
3119 case COPY_FILES:
3120 case CREATE_SYMLINK:
3121 case CREATE_FILE:
3122 case TRUNCATE_FILE:
3123 case WRITE_FILE: {
3124 _cleanup_free_ char *unescaped = NULL, *resolved = NULL;
3125 ssize_t l;
3126
3127 l = cunescape(i->argument, 0, &unescaped);
3128 if (l < 0)
3129 return log_error_errno(l, "Failed to unescape parameter to write: %s", i->argument);
3130
3131 r = specifier_printf(unescaped, PATH_MAX-1, specifier_table, arg_root, NULL, &resolved);
3132 if (r < 0)
3133 return r;
3134
3135 return free_and_replace(i->argument, resolved);
3136 }
3137 case SET_XATTR:
3138 case RECURSIVE_SET_XATTR:
3139 STRV_FOREACH(xattr, i->xattrs) {
3140 _cleanup_free_ char *resolved = NULL;
3141
3142 r = specifier_printf(*xattr, SIZE_MAX, specifier_table, arg_root, NULL, &resolved);
3143 if (r < 0)
3144 return r;
3145
3146 free_and_replace(*xattr, resolved);
3147 }
3148 return 0;
3149
3150 default:
3151 return 0;
3152 }
3153 }
3154
3155 static int patch_var_run(const char *fname, unsigned line, char **path) {
3156 const char *k;
3157 char *n;
3158
3159 assert(path);
3160 assert(*path);
3161
3162 /* Optionally rewrites lines referencing /var/run/, to use /run/ instead. Why bother? tmpfiles merges lines in
3163 * some cases and detects conflicts in others. If files/directories are specified through two equivalent lines
3164 * this is problematic as neither case will be detected. Ideally we'd detect these cases by resolving symlinks
3165 * early, but that's precisely not what we can do here as this code very likely is running very early on, at a
3166 * time where the paths in question are not available yet, or even more importantly, our own tmpfiles rules
3167 * might create the paths that are intermediary to the listed paths. We can't really cover the generic case,
3168 * but the least we can do is cover the specific case of /var/run vs. /run, as /var/run is a legacy name for
3169 * /run only, and we explicitly document that and require that on systemd systems the former is a symlink to
3170 * the latter. Moreover files below this path are by far the primary usecase for tmpfiles.d/. */
3171
3172 k = path_startswith(*path, "/var/run/");
3173 if (isempty(k)) /* Don't complain about other paths than /var/run, and not about /var/run itself either. */
3174 return 0;
3175
3176 n = path_join("/run", k);
3177 if (!n)
3178 return log_oom();
3179
3180 /* Also log about this briefly. We do so at LOG_NOTICE level, as we fixed up the situation automatically, hence
3181 * there's no immediate need for action by the user. However, in the interest of making things less confusing
3182 * to the user, let's still inform the user that these snippets should really be updated. */
3183 log_syntax(NULL, LOG_NOTICE, fname, line, 0,
3184 "Line references path below legacy directory /var/run/, updating %s → %s; please update the tmpfiles.d/ drop-in file accordingly.",
3185 *path, n);
3186
3187 free_and_replace(*path, n);
3188
3189 return 0;
3190 }
3191
3192 static int find_uid(const char *user, uid_t *ret_uid, Hashmap **cache) {
3193 int r;
3194
3195 assert(user);
3196 assert(ret_uid);
3197
3198 /* First: parse as numeric UID string */
3199 r = parse_uid(user, ret_uid);
3200 if (r >= 0)
3201 return r;
3202
3203 /* Second: pass to NSS if we are running "online" */
3204 if (!arg_root)
3205 return get_user_creds(&user, ret_uid, NULL, NULL, NULL, 0);
3206
3207 /* Third, synthesize "root" unconditionally */
3208 if (streq(user, "root")) {
3209 *ret_uid = 0;
3210 return 0;
3211 }
3212
3213 /* Fourth: use fgetpwent() to read /etc/passwd directly, if we are "offline" */
3214 return name_to_uid_offline(arg_root, user, ret_uid, cache);
3215 }
3216
3217 static int find_gid(const char *group, gid_t *ret_gid, Hashmap **cache) {
3218 int r;
3219
3220 assert(group);
3221 assert(ret_gid);
3222
3223 /* First: parse as numeric GID string */
3224 r = parse_gid(group, ret_gid);
3225 if (r >= 0)
3226 return r;
3227
3228 /* Second: pass to NSS if we are running "online" */
3229 if (!arg_root)
3230 return get_group_creds(&group, ret_gid, 0);
3231
3232 /* Third, synthesize "root" unconditionally */
3233 if (streq(group, "root")) {
3234 *ret_gid = 0;
3235 return 0;
3236 }
3237
3238 /* Fourth: use fgetgrent() to read /etc/group directly, if we are "offline" */
3239 return name_to_gid_offline(arg_root, group, ret_gid, cache);
3240 }
3241
3242 static int parse_age_by_from_arg(const char *age_by_str, Item *item) {
3243 AgeBy ab_f = 0, ab_d = 0;
3244
3245 static const struct {
3246 char age_by_chr;
3247 AgeBy age_by_flag;
3248 } age_by_types[] = {
3249 { 'a', AGE_BY_ATIME },
3250 { 'b', AGE_BY_BTIME },
3251 { 'c', AGE_BY_CTIME },
3252 { 'm', AGE_BY_MTIME },
3253 };
3254
3255 assert(age_by_str);
3256 assert(item);
3257
3258 if (isempty(age_by_str))
3259 return -EINVAL;
3260
3261 for (const char *s = age_by_str; *s != 0; s++) {
3262 size_t i;
3263
3264 /* Ignore whitespace. */
3265 if (strchr(WHITESPACE, *s))
3266 continue;
3267
3268 for (i = 0; i < ELEMENTSOF(age_by_types); i++) {
3269 /* Check lower-case for files, upper-case for directories. */
3270 if (*s == age_by_types[i].age_by_chr) {
3271 ab_f |= age_by_types[i].age_by_flag;
3272 break;
3273 } else if (*s == ascii_toupper(age_by_types[i].age_by_chr)) {
3274 ab_d |= age_by_types[i].age_by_flag;
3275 break;
3276 }
3277 }
3278
3279 /* Invalid character. */
3280 if (i >= ELEMENTSOF(age_by_types))
3281 return -EINVAL;
3282 }
3283
3284 /* No match. */
3285 if (ab_f == 0 && ab_d == 0)
3286 return -EINVAL;
3287
3288 item->age_by_file = ab_f > 0 ? ab_f : AGE_BY_DEFAULT_FILE;
3289 item->age_by_dir = ab_d > 0 ? ab_d : AGE_BY_DEFAULT_DIR;
3290
3291 return 0;
3292 }
3293
3294 static bool is_duplicated_item(ItemArray *existing, const Item *i) {
3295
3296 assert(existing);
3297 assert(i);
3298
3299 for (size_t n = 0; n < existing->n_items; n++) {
3300 const Item *e = existing->items + n;
3301
3302 if (item_compatible(e, i))
3303 continue;
3304
3305 /* Only multiple 'w+' lines for the same path are allowed. */
3306 if (e->type != WRITE_FILE || !e->append_or_force ||
3307 i->type != WRITE_FILE || !i->append_or_force)
3308 return true;
3309 }
3310
3311 return false;
3312 }
3313
3314 static int parse_line(
3315 const char *fname,
3316 unsigned line,
3317 const char *buffer,
3318 bool *invalid_config,
3319 Hashmap **uid_cache,
3320 Hashmap **gid_cache) {
3321
3322 _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
3323 _cleanup_(item_free_contents) Item i = {
3324 /* The "age-by" argument considers all file timestamp types by default. */
3325 .age_by_file = AGE_BY_DEFAULT_FILE,
3326 .age_by_dir = AGE_BY_DEFAULT_DIR,
3327 };
3328 ItemArray *existing;
3329 OrderedHashmap *h;
3330 int r, pos;
3331 bool append_or_force = false, boot = false, allow_failure = false, try_replace = false,
3332 unbase64 = false, from_cred = false, missing_user_or_group = false;
3333
3334 assert(fname);
3335 assert(line >= 1);
3336 assert(buffer);
3337
3338 const Specifier specifier_table[] = {
3339 { 'a', specifier_architecture, NULL },
3340 { 'b', specifier_boot_id, NULL },
3341 { 'B', specifier_os_build_id, NULL },
3342 { 'H', specifier_hostname, NULL },
3343 { 'l', specifier_short_hostname, NULL },
3344 { 'm', specifier_machine_id, NULL },
3345 { 'o', specifier_os_id, NULL },
3346 { 'v', specifier_kernel_release, NULL },
3347 { 'w', specifier_os_version_id, NULL },
3348 { 'W', specifier_os_variant_id, NULL },
3349
3350 { 'h', specifier_user_home, NULL },
3351
3352 { 'C', specifier_directory, UINT_TO_PTR(DIRECTORY_CACHE) },
3353 { 'L', specifier_directory, UINT_TO_PTR(DIRECTORY_LOGS) },
3354 { 'S', specifier_directory, UINT_TO_PTR(DIRECTORY_STATE) },
3355 { 't', specifier_directory, UINT_TO_PTR(DIRECTORY_RUNTIME) },
3356
3357 COMMON_CREDS_SPECIFIERS(arg_runtime_scope),
3358 COMMON_TMP_SPECIFIERS,
3359 {}
3360 };
3361
3362 r = extract_many_words(
3363 &buffer,
3364 NULL,
3365 EXTRACT_UNQUOTE | EXTRACT_CUNESCAPE,
3366 &action,
3367 &path,
3368 &mode,
3369 &user,
3370 &group,
3371 &age,
3372 NULL);
3373 if (r < 0) {
3374 if (IN_SET(r, -EINVAL, -EBADSLT))
3375 /* invalid quoting and such or an unknown specifier */
3376 *invalid_config = true;
3377 return log_syntax(NULL, LOG_ERR, fname, line, r, "Failed to parse line: %m");
3378 } else if (r < 2) {
3379 *invalid_config = true;
3380 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG), "Syntax error.");
3381 }
3382
3383 if (!empty_or_dash(buffer)) {
3384 i.argument = strdup(buffer);
3385 if (!i.argument)
3386 return log_oom();
3387 }
3388
3389 if (isempty(action)) {
3390 *invalid_config = true;
3391 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG), "Command too short '%s'.", action);
3392 }
3393
3394 for (pos = 1; action[pos]; pos++) {
3395 if (action[pos] == '!' && !boot)
3396 boot = true;
3397 else if (action[pos] == '+' && !append_or_force)
3398 append_or_force = true;
3399 else if (action[pos] == '-' && !allow_failure)
3400 allow_failure = true;
3401 else if (action[pos] == '=' && !try_replace)
3402 try_replace = true;
3403 else if (action[pos] == '~' && !unbase64)
3404 unbase64 = true;
3405 else if (action[pos] == '^' && !from_cred)
3406 from_cred = true;
3407 else {
3408 *invalid_config = true;
3409 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG), "Unknown modifiers in command '%s'", action);
3410 }
3411 }
3412
3413 if (boot && !arg_boot) {
3414 log_syntax(NULL, LOG_DEBUG, fname, line, 0, "Ignoring entry %s \"%s\" because --boot is not specified.", action, path);
3415 return 0;
3416 }
3417
3418 i.type = action[0];
3419 i.append_or_force = append_or_force;
3420 i.allow_failure = allow_failure;
3421 i.try_replace = try_replace;
3422
3423 r = specifier_printf(path, PATH_MAX-1, specifier_table, arg_root, NULL, &i.path);
3424 if (ERRNO_IS_NOINFO(r))
3425 return log_unresolvable_specifier(fname, line);
3426 if (r < 0) {
3427 if (IN_SET(r, -EINVAL, -EBADSLT))
3428 *invalid_config = true;
3429 return log_syntax(NULL, LOG_ERR, fname, line, r, "Failed to replace specifiers in '%s': %m", path);
3430 }
3431
3432 r = patch_var_run(fname, line, &i.path);
3433 if (r < 0)
3434 return r;
3435
3436 if (!path_is_absolute(i.path)) {
3437 *invalid_config = true;
3438 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG),
3439 "Path '%s' not absolute.", i.path);
3440 }
3441
3442 path_simplify(i.path);
3443
3444 switch (i.type) {
3445
3446 case CREATE_DIRECTORY:
3447 case CREATE_SUBVOLUME:
3448 case CREATE_SUBVOLUME_INHERIT_QUOTA:
3449 case CREATE_SUBVOLUME_NEW_QUOTA:
3450 case EMPTY_DIRECTORY:
3451 case TRUNCATE_DIRECTORY:
3452 case CREATE_FIFO:
3453 case IGNORE_PATH:
3454 case IGNORE_DIRECTORY_PATH:
3455 case REMOVE_PATH:
3456 case RECURSIVE_REMOVE_PATH:
3457 case ADJUST_MODE:
3458 case RELABEL_PATH:
3459 case RECURSIVE_RELABEL_PATH:
3460 if (i.argument)
3461 log_syntax(NULL,
3462 LOG_WARNING,
3463 fname,
3464 line,
3465 0,
3466 "%c lines don't take argument fields, ignoring.",
3467 (char) i.type);
3468
3469 break;
3470
3471 case CREATE_FILE:
3472 case TRUNCATE_FILE:
3473 break;
3474
3475 case CREATE_SYMLINK:
3476 if (unbase64) {
3477 *invalid_config = true;
3478 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG), "base64 decoding not supported for symlink targets.");
3479 }
3480 break;
3481
3482 case WRITE_FILE:
3483 if (!i.argument) {
3484 *invalid_config = true;
3485 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG), "Write file requires argument.");
3486 }
3487 break;
3488
3489 case COPY_FILES:
3490 if (unbase64) {
3491 *invalid_config = true;
3492 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG), "base64 decoding not supported for copy sources.");
3493 }
3494 break;
3495
3496 case CREATE_CHAR_DEVICE:
3497 case CREATE_BLOCK_DEVICE:
3498 if (unbase64) {
3499 *invalid_config = true;
3500 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG), "base64 decoding not supported for device node creation.");
3501 }
3502
3503 if (!i.argument) {
3504 *invalid_config = true;
3505 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG), "Device file requires argument.");
3506 }
3507
3508 r = parse_devnum(i.argument, &i.major_minor);
3509 if (r < 0) {
3510 *invalid_config = true;
3511 return log_syntax(NULL, LOG_ERR, fname, line, r, "Can't parse device file major/minor '%s'.", i.argument);
3512 }
3513
3514 break;
3515
3516 case SET_XATTR:
3517 case RECURSIVE_SET_XATTR:
3518 if (unbase64) {
3519 *invalid_config = true;
3520 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG), "base64 decoding not supported for extended attributes.");
3521 }
3522 if (!i.argument) {
3523 *invalid_config = true;
3524 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG),
3525 "Set extended attribute requires argument.");
3526 }
3527 r = parse_xattrs_from_arg(&i);
3528 if (r < 0)
3529 return r;
3530 break;
3531
3532 case SET_ACL:
3533 case RECURSIVE_SET_ACL:
3534 if (unbase64) {
3535 *invalid_config = true;
3536 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG), "base64 decoding not supported for ACLs.");
3537 }
3538 if (!i.argument) {
3539 *invalid_config = true;
3540 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG),
3541 "Set ACLs requires argument.");
3542 }
3543 r = parse_acls_from_arg(&i);
3544 if (r < 0)
3545 return r;
3546 break;
3547
3548 case SET_ATTRIBUTE:
3549 case RECURSIVE_SET_ATTRIBUTE:
3550 if (unbase64) {
3551 *invalid_config = true;
3552 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG), "base64 decoding not supported for file attributes.");
3553 }
3554 if (!i.argument) {
3555 *invalid_config = true;
3556 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG),
3557 "Set file attribute requires argument.");
3558 }
3559 r = parse_attribute_from_arg(&i);
3560 if (IN_SET(r, -EINVAL, -EBADSLT))
3561 *invalid_config = true;
3562 if (r < 0)
3563 return r;
3564 break;
3565
3566 default:
3567 *invalid_config = true;
3568 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG),
3569 "Unknown command type '%c'.", (char) i.type);
3570 }
3571
3572 if (!should_include_path(i.path))
3573 return 0;
3574
3575 if (!unbase64) {
3576 /* Do specifier expansion except if base64 mode is enabled */
3577 r = specifier_expansion_from_arg(specifier_table, &i);
3578 if (ERRNO_IS_NOINFO(r))
3579 return log_unresolvable_specifier(fname, line);
3580 if (r < 0) {
3581 if (IN_SET(r, -EINVAL, -EBADSLT))
3582 *invalid_config = true;
3583 return log_syntax(NULL, LOG_ERR, fname, line, r, "Failed to substitute specifiers in argument: %m");
3584 }
3585 }
3586
3587 switch (i.type) {
3588 case CREATE_SYMLINK:
3589 if (!i.argument) {
3590 i.argument = path_join("/usr/share/factory", i.path);
3591 if (!i.argument)
3592 return log_oom();
3593 }
3594 break;
3595
3596 case COPY_FILES:
3597 if (!i.argument) {
3598 i.argument = path_join("/usr/share/factory", i.path);
3599 if (!i.argument)
3600 return log_oom();
3601 } else if (!path_is_absolute(i.argument)) {
3602 *invalid_config = true;
3603 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG), "Source path '%s' is not absolute.", i.argument);
3604
3605 }
3606
3607 if (!empty_or_root(arg_root)) {
3608 char *p;
3609
3610 p = path_join(arg_root, i.argument);
3611 if (!p)
3612 return log_oom();
3613 free_and_replace(i.argument, p);
3614 }
3615
3616 path_simplify(i.argument);
3617
3618 if (laccess(i.argument, F_OK) == -ENOENT) {
3619 /* Silently skip over lines where the source file is missing. */
3620 log_syntax(NULL, LOG_DEBUG, fname, line, 0, "Copy source path '%s' does not exist, skipping line.", i.argument);
3621 return 0;
3622 }
3623
3624 break;
3625
3626 default:
3627 break;
3628 }
3629
3630 if (from_cred) {
3631 if (!i.argument)
3632 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EINVAL), "Reading from credential requested, but no credential name specified.");
3633 if (!credential_name_valid(i.argument))
3634 return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EINVAL), "Credential name not valid: %s", i.argument);
3635
3636 r = read_credential(i.argument, &i.binary_argument, &i.binary_argument_size);
3637 if (IN_SET(r, -ENXIO, -ENOENT)) {
3638 /* Silently skip over lines that have no credentials passed */
3639 log_syntax(NULL, LOG_DEBUG, fname, line, 0,
3640 "Credential '%s' not specified, skipping line.", i.argument);
3641 return 0;
3642 }
3643 if (r < 0)
3644 return log_error_errno(r, "Failed to read credential '%s': %m", i.argument);
3645 }
3646
3647 /* If base64 decoding is requested, do so now */
3648 if (unbase64 && item_binary_argument(&i)) {
3649 _cleanup_free_ void *data = NULL;
3650 size_t data_size = 0;
3651
3652 r = unbase64mem(item_binary_argument(&i), item_binary_argument_size(&i), &data, &data_size);
3653 if (r < 0)
3654 return log_syntax(NULL, LOG_ERR, fname, line, r, "Failed to base64 decode specified argument '%s': %m", i.argument);
3655
3656 free_and_replace(i.binary_argument, data);
3657 i.binary_argument_size = data_size;
3658 }
3659
3660 if (!empty_or_root(arg_root)) {
3661 char *p;
3662
3663 p = path_join(arg_root, i.path);
3664 if (!p)
3665 return log_oom();
3666 free_and_replace(i.path, p);
3667 }
3668
3669 if (!empty_or_dash(user)) {
3670 const char *u;
3671
3672 u = startswith(user, ":");
3673 if (u)
3674 i.uid_only_create = true;
3675 else
3676 u = user;
3677
3678 r = find_uid(u, &i.uid, uid_cache);
3679 if (r == -ESRCH && arg_graceful) {
3680 log_syntax(NULL, LOG_DEBUG, fname, line, r,
3681 "%s: user '%s' not found, not adjusting ownership.", i.path, u);
3682 missing_user_or_group = true;
3683 } else if (r < 0) {
3684 *invalid_config = true;
3685 return log_syntax(NULL, LOG_ERR, fname, line, r, "Failed to resolve user '%s': %m", u);
3686 } else
3687 i.uid_set = true;
3688 }
3689
3690 if (!empty_or_dash(group)) {
3691 const char *g;
3692
3693 g = startswith(group, ":");
3694 if (g)
3695 i.gid_only_create = true;
3696 else
3697 g = group;
3698
3699 r = find_gid(g, &i.gid, gid_cache);
3700 if (r == -ESRCH && arg_graceful) {
3701 log_syntax(NULL, LOG_DEBUG, fname, line, r,
3702 "%s: group '%s' not found, not adjusting ownership.", i.path, g);
3703 missing_user_or_group = true;
3704 } else if (r < 0) {
3705 *invalid_config = true;
3706 return log_syntax(NULL, LOG_ERR, fname, line, r, "Failed to resolve group '%s': %m", g);
3707 } else
3708 i.gid_set = true;
3709 }
3710
3711 if (!empty_or_dash(mode)) {
3712 const char *mm;
3713 unsigned m;
3714
3715 for (mm = mode;; mm++) {
3716 if (*mm == '~')
3717 i.mask_perms = true;
3718 else if (*mm == ':')
3719 i.mode_only_create = true;
3720 else
3721 break;
3722 }
3723
3724 r = parse_mode(mm, &m);
3725 if (r < 0) {
3726 *invalid_config = true;
3727 return log_syntax(NULL, LOG_ERR, fname, line, r, "Invalid mode '%s'.", mode);
3728 }
3729
3730 i.mode = m;
3731 i.mode_set = true;
3732 } else
3733 i.mode = IN_SET(i.type,
3734 CREATE_DIRECTORY,
3735 TRUNCATE_DIRECTORY,
3736 CREATE_SUBVOLUME,
3737 CREATE_SUBVOLUME_INHERIT_QUOTA,
3738 CREATE_SUBVOLUME_NEW_QUOTA) ? 0755 : 0644;
3739
3740 if (missing_user_or_group && (i.mode & ~0777) != 0) {
3741 /* Refuse any special bits for nodes where we couldn't resolve the ownership properly. */
3742 mode_t adjusted = i.mode & 0777;
3743 log_syntax(NULL, LOG_INFO, fname, line, 0,
3744 "Changing mode 0%o to 0%o because of changed ownership.", i.mode, adjusted);
3745 i.mode = adjusted;
3746 }
3747
3748 if (!empty_or_dash(age)) {
3749 const char *a = age;
3750 _cleanup_free_ char *seconds = NULL, *age_by = NULL;
3751
3752 if (*a == '~') {
3753 i.keep_first_level = true;
3754 a++;
3755 }
3756
3757 /* Format: "age-by:age"; where age-by is "[abcmABCM]+". */
3758 r = split_pair(a, ":", &age_by, &seconds);
3759 if (r == -ENOMEM)
3760 return log_oom();
3761 if (r < 0 && r != -EINVAL)
3762 return log_error_errno(r, "Failed to parse age-by for '%s': %m", age);
3763 if (r >= 0) {
3764 /* We found a ":", parse the "age-by" part. */
3765 r = parse_age_by_from_arg(age_by, &i);
3766 if (r == -ENOMEM)
3767 return log_oom();
3768 if (r < 0) {
3769 *invalid_config = true;
3770 return log_syntax(NULL, LOG_ERR, fname, line, r, "Invalid age-by '%s'.", age_by);
3771 }
3772
3773 /* For parsing the "age" part, after the ":". */
3774 a = seconds;
3775 }
3776
3777 r = parse_sec(a, &i.age);
3778 if (r < 0) {
3779 *invalid_config = true;
3780 return log_syntax(NULL, LOG_ERR, fname, line, r, "Invalid age '%s'.", a);
3781 }
3782
3783 i.age_set = true;
3784 }
3785
3786 h = needs_glob(i.type) ? globs : items;
3787
3788 existing = ordered_hashmap_get(h, i.path);
3789 if (existing) {
3790 if (is_duplicated_item(existing, &i)) {
3791 log_syntax(NULL, LOG_NOTICE, fname, line, 0,
3792 "Duplicate line for path \"%s\", ignoring.", i.path);
3793 return 0;
3794 }
3795 } else {
3796 existing = new0(ItemArray, 1);
3797 if (!existing)
3798 return log_oom();
3799
3800 r = ordered_hashmap_put(h, i.path, existing);
3801 if (r < 0) {
3802 free(existing);
3803 return log_oom();
3804 }
3805 }
3806
3807 if (!GREEDY_REALLOC(existing->items, existing->n_items + 1))
3808 return log_oom();
3809
3810 existing->items[existing->n_items++] = TAKE_STRUCT(i);
3811
3812 /* Sort item array, to enforce stable ordering of application */
3813 typesafe_qsort(existing->items, existing->n_items, item_compare);
3814
3815 return 0;
3816 }
3817
3818 static int cat_config(char **config_dirs, char **args) {
3819 _cleanup_strv_free_ char **files = NULL;
3820 int r;
3821
3822 r = conf_files_list_with_replacement(arg_root, config_dirs, arg_replace, &files, NULL);
3823 if (r < 0)
3824 return r;
3825
3826 return cat_files(NULL, files, 0);
3827 }
3828
3829 static int exclude_default_prefixes(void) {
3830 int r;
3831
3832 /* Provide an easy way to exclude virtual/memory file systems from what we do here. Useful in
3833 * combination with --root= where we probably don't want to apply stuff to these dirs as they are
3834 * likely over-mounted if the root directory is actually used, and it wouldbe less than ideal to have
3835 * all kinds of files created/adjusted underneath these mount points. */
3836
3837 r = strv_extend_strv(
3838 &arg_exclude_prefixes,
3839 STRV_MAKE("/dev",
3840 "/proc",
3841 "/run",
3842 "/sys"),
3843 true);
3844 if (r < 0)
3845 return log_oom();
3846
3847 return 0;
3848 }
3849
3850 static int help(void) {
3851 _cleanup_free_ char *link = NULL;
3852 int r;
3853
3854 r = terminal_urlify_man("systemd-tmpfiles", "8", &link);
3855 if (r < 0)
3856 return log_oom();
3857
3858 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n"
3859 "\n%sCreates, deletes and cleans up volatile and temporary files and directories.%s\n\n"
3860 " -h --help Show this help\n"
3861 " --user Execute user configuration\n"
3862 " --version Show package version\n"
3863 " --cat-config Show configuration files\n"
3864 " --create Create marked files/directories\n"
3865 " --clean Clean up marked directories\n"
3866 " --remove Remove marked files/directories\n"
3867 " --boot Execute actions only safe at boot\n"
3868 " --graceful Quietly ignore unknown users or groups\n"
3869 " --prefix=PATH Only apply rules with the specified prefix\n"
3870 " --exclude-prefix=PATH Ignore rules with the specified prefix\n"
3871 " -E Ignore rules prefixed with /dev, /proc, /run, /sys\n"
3872 " --root=PATH Operate on an alternate filesystem root\n"
3873 " --image=PATH Operate on disk image as filesystem root\n"
3874 " --image-policy=POLICY Specify disk image dissection policy\n"
3875 " --replace=PATH Treat arguments as replacement for PATH\n"
3876 " --no-pager Do not pipe output into a pager\n"
3877 "\nSee the %s for details.\n",
3878 program_invocation_short_name,
3879 ansi_highlight(),
3880 ansi_normal(),
3881 link);
3882
3883 return 0;
3884 }
3885
3886 static int parse_argv(int argc, char *argv[]) {
3887
3888 enum {
3889 ARG_VERSION = 0x100,
3890 ARG_CAT_CONFIG,
3891 ARG_USER,
3892 ARG_CREATE,
3893 ARG_CLEAN,
3894 ARG_REMOVE,
3895 ARG_BOOT,
3896 ARG_GRACEFUL,
3897 ARG_PREFIX,
3898 ARG_EXCLUDE_PREFIX,
3899 ARG_ROOT,
3900 ARG_IMAGE,
3901 ARG_IMAGE_POLICY,
3902 ARG_REPLACE,
3903 ARG_NO_PAGER,
3904 };
3905
3906 static const struct option options[] = {
3907 { "help", no_argument, NULL, 'h' },
3908 { "user", no_argument, NULL, ARG_USER },
3909 { "version", no_argument, NULL, ARG_VERSION },
3910 { "cat-config", no_argument, NULL, ARG_CAT_CONFIG },
3911 { "create", no_argument, NULL, ARG_CREATE },
3912 { "clean", no_argument, NULL, ARG_CLEAN },
3913 { "remove", no_argument, NULL, ARG_REMOVE },
3914 { "boot", no_argument, NULL, ARG_BOOT },
3915 { "graceful", no_argument, NULL, ARG_GRACEFUL },
3916 { "prefix", required_argument, NULL, ARG_PREFIX },
3917 { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
3918 { "root", required_argument, NULL, ARG_ROOT },
3919 { "image", required_argument, NULL, ARG_IMAGE },
3920 { "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
3921 { "replace", required_argument, NULL, ARG_REPLACE },
3922 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
3923 {}
3924 };
3925
3926 int c, r;
3927
3928 assert(argc >= 0);
3929 assert(argv);
3930
3931 while ((c = getopt_long(argc, argv, "hE", options, NULL)) >= 0)
3932
3933 switch (c) {
3934
3935 case 'h':
3936 return help();
3937
3938 case ARG_VERSION:
3939 return version();
3940
3941 case ARG_CAT_CONFIG:
3942 arg_cat_config = true;
3943 break;
3944
3945 case ARG_USER:
3946 arg_runtime_scope = RUNTIME_SCOPE_USER;
3947 break;
3948
3949 case ARG_CREATE:
3950 arg_operation |= OPERATION_CREATE;
3951 break;
3952
3953 case ARG_CLEAN:
3954 arg_operation |= OPERATION_CLEAN;
3955 break;
3956
3957 case ARG_REMOVE:
3958 arg_operation |= OPERATION_REMOVE;
3959 break;
3960
3961 case ARG_BOOT:
3962 arg_boot = true;
3963 break;
3964
3965 case ARG_GRACEFUL:
3966 arg_graceful = true;
3967 break;
3968
3969 case ARG_PREFIX:
3970 if (strv_push(&arg_include_prefixes, optarg) < 0)
3971 return log_oom();
3972 break;
3973
3974 case ARG_EXCLUDE_PREFIX:
3975 if (strv_push(&arg_exclude_prefixes, optarg) < 0)
3976 return log_oom();
3977 break;
3978
3979 case ARG_ROOT:
3980 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_root);
3981 if (r < 0)
3982 return r;
3983 break;
3984
3985 case ARG_IMAGE:
3986 #ifdef STANDALONE
3987 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3988 "This systemd-tmpfiles version is compiled without support for --image=.");
3989 #else
3990 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image);
3991 if (r < 0)
3992 return r;
3993 #endif
3994 /* Imply -E here since it makes little sense to create files persistently in the /run mountpoint of a disk image */
3995 _fallthrough_;
3996
3997 case 'E':
3998 r = exclude_default_prefixes();
3999 if (r < 0)
4000 return r;
4001
4002 break;
4003
4004 case ARG_IMAGE_POLICY:
4005 r = parse_image_policy_argument(optarg, &arg_image_policy);
4006 if (r < 0)
4007 return r;
4008 break;
4009
4010 case ARG_REPLACE:
4011 if (!path_is_absolute(optarg) ||
4012 !endswith(optarg, ".conf"))
4013 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
4014 "The argument to --replace= must an absolute path to a config file");
4015
4016 arg_replace = optarg;
4017 break;
4018
4019 case ARG_NO_PAGER:
4020 arg_pager_flags |= PAGER_DISABLE;
4021 break;
4022
4023 case '?':
4024 return -EINVAL;
4025
4026 default:
4027 assert_not_reached();
4028 }
4029
4030 if (arg_operation == 0 && !arg_cat_config)
4031 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
4032 "You need to specify at least one of --clean, --create or --remove.");
4033
4034 if (arg_replace && arg_cat_config)
4035 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
4036 "Option --replace= is not supported with --cat-config");
4037
4038 if (arg_replace && optind >= argc)
4039 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
4040 "When --replace= is given, some configuration items must be specified");
4041
4042 if (arg_root && arg_runtime_scope == RUNTIME_SCOPE_USER)
4043 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
4044 "Combination of --user and --root= is not supported.");
4045
4046 if (arg_image && arg_root)
4047 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported.");
4048
4049 return 1;
4050 }
4051
4052 static int read_config_file(
4053 char **config_dirs,
4054 const char *fn,
4055 bool ignore_enoent,
4056 bool *invalid_config) {
4057
4058 _cleanup_hashmap_free_ Hashmap *uid_cache = NULL, *gid_cache = NULL;
4059 _cleanup_fclose_ FILE *_f = NULL;
4060 _cleanup_free_ char *pp = NULL;
4061 unsigned v = 0;
4062 FILE *f;
4063 ItemArray *ia;
4064 int r = 0;
4065
4066 assert(fn);
4067
4068 if (streq(fn, "-")) {
4069 log_debug("Reading config from stdin%s", special_glyph(SPECIAL_GLYPH_ELLIPSIS));
4070 fn = "<stdin>";
4071 f = stdin;
4072 } else {
4073 r = search_and_fopen(fn, "re", arg_root, (const char**) config_dirs, &_f, &pp);
4074 if (r < 0) {
4075 if (ignore_enoent && r == -ENOENT) {
4076 log_debug_errno(r, "Failed to open \"%s\", ignoring: %m", fn);
4077 return 0;
4078 }
4079
4080 return log_error_errno(r, "Failed to open '%s': %m", fn);
4081 }
4082
4083 log_debug("Reading config file \"%s\"%s", pp, special_glyph(SPECIAL_GLYPH_ELLIPSIS));
4084 fn = pp;
4085 f = _f;
4086 }
4087
4088 for (;;) {
4089 _cleanup_free_ char *line = NULL;
4090 bool invalid_line = false;
4091 char *l;
4092 int k;
4093
4094 k = read_line(f, LONG_LINE_MAX, &line);
4095 if (k < 0)
4096 return log_error_errno(k, "Failed to read '%s': %m", fn);
4097 if (k == 0)
4098 break;
4099
4100 v++;
4101
4102 l = strstrip(line);
4103 if (IN_SET(*l, 0, '#'))
4104 continue;
4105
4106 k = parse_line(fn, v, l, &invalid_line, &uid_cache, &gid_cache);
4107 if (k < 0) {
4108 if (invalid_line)
4109 /* Allow reporting with a special code if the caller requested this */
4110 *invalid_config = true;
4111 else if (r == 0)
4112 /* The first error becomes our return value */
4113 r = k;
4114 }
4115 }
4116
4117 /* we have to determine age parameter for each entry of type X */
4118 ORDERED_HASHMAP_FOREACH(ia, globs)
4119 for (size_t ni = 0; ni < ia->n_items; ni++) {
4120 ItemArray *ja;
4121 Item *i = ia->items + ni, *candidate_item = NULL;
4122
4123 if (i->type != IGNORE_DIRECTORY_PATH)
4124 continue;
4125
4126 ORDERED_HASHMAP_FOREACH(ja, items)
4127 for (size_t nj = 0; nj < ja->n_items; nj++) {
4128 Item *j = ja->items + nj;
4129
4130 if (!IN_SET(j->type, CREATE_DIRECTORY,
4131 TRUNCATE_DIRECTORY,
4132 CREATE_SUBVOLUME,
4133 CREATE_SUBVOLUME_INHERIT_QUOTA,
4134 CREATE_SUBVOLUME_NEW_QUOTA))
4135 continue;
4136
4137 if (path_equal(j->path, i->path)) {
4138 candidate_item = j;
4139 break;
4140 }
4141
4142 if (candidate_item
4143 ? (path_startswith(j->path, candidate_item->path) && fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)
4144 : path_startswith(i->path, j->path) != NULL)
4145 candidate_item = j;
4146 }
4147
4148 if (candidate_item && candidate_item->age_set) {
4149 i->age = candidate_item->age;
4150 i->age_set = true;
4151 }
4152 }
4153
4154 if (ferror(f)) {
4155 log_error_errno(errno, "Failed to read from file %s: %m", fn);
4156 if (r == 0)
4157 r = -EIO;
4158 }
4159
4160 return r;
4161 }
4162
4163 static int parse_arguments(char **config_dirs, char **args, bool *invalid_config) {
4164 int r;
4165
4166 STRV_FOREACH(arg, args) {
4167 r = read_config_file(config_dirs, *arg, false, invalid_config);
4168 if (r < 0)
4169 return r;
4170 }
4171
4172 return 0;
4173 }
4174
4175 static int read_config_files(char **config_dirs, char **args, bool *invalid_config) {
4176 _cleanup_strv_free_ char **files = NULL;
4177 _cleanup_free_ char *p = NULL;
4178 int r;
4179
4180 r = conf_files_list_with_replacement(arg_root, config_dirs, arg_replace, &files, &p);
4181 if (r < 0)
4182 return r;
4183
4184 STRV_FOREACH(f, files)
4185 if (p && path_equal(*f, p)) {
4186 log_debug("Parsing arguments at position \"%s\"%s", *f, special_glyph(SPECIAL_GLYPH_ELLIPSIS));
4187
4188 r = parse_arguments(config_dirs, args, invalid_config);
4189 if (r < 0)
4190 return r;
4191 } else
4192 /* Just warn, ignore result otherwise.
4193 * read_config_file() has some debug output, so no need to print anything. */
4194 (void) read_config_file(config_dirs, *f, true, invalid_config);
4195
4196 return 0;
4197 }
4198
4199 static int read_credential_lines(bool *invalid_config) {
4200 _cleanup_free_ char *j = NULL;
4201 const char *d;
4202 int r;
4203
4204 r = get_credentials_dir(&d);
4205 if (r == -ENXIO)
4206 return 0;
4207 if (r < 0)
4208 return log_error_errno(r, "Failed to get credentials directory: %m");
4209
4210 j = path_join(d, "tmpfiles.extra");
4211 if (!j)
4212 return log_oom();
4213
4214 (void) read_config_file(/* config_dirs= */ NULL, j, /* ignore_enoent= */ true, invalid_config);
4215 return 0;
4216 }
4217
4218 static int link_parent(ItemArray *a) {
4219 const char *path;
4220 char *prefix;
4221 int r;
4222
4223 assert(a);
4224
4225 /* Finds the closest "parent" item array for the specified item array. Then registers the specified item array
4226 * as child of it, and fills the parent in, linking them both ways. This allows us to later create parents
4227 * before their children, and clean up/remove children before their parents. */
4228
4229 if (a->n_items <= 0)
4230 return 0;
4231
4232 path = a->items[0].path;
4233 prefix = newa(char, strlen(path) + 1);
4234 PATH_FOREACH_PREFIX(prefix, path) {
4235 ItemArray *j;
4236
4237 j = ordered_hashmap_get(items, prefix);
4238 if (!j)
4239 j = ordered_hashmap_get(globs, prefix);
4240 if (j) {
4241 r = set_ensure_put(&j->children, NULL, a);
4242 if (r < 0)
4243 return log_oom();
4244
4245 a->parent = j;
4246 return 1;
4247 }
4248 }
4249
4250 return 0;
4251 }
4252
4253 DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(item_array_hash_ops, char, string_hash_func, string_compare_func,
4254 ItemArray, item_array_free);
4255
4256 static int run(int argc, char *argv[]) {
4257 #ifndef STANDALONE
4258 _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
4259 _cleanup_(umount_and_freep) char *mounted_dir = NULL;
4260 #endif
4261 _cleanup_strv_free_ char **config_dirs = NULL;
4262 bool invalid_config = false;
4263 ItemArray *a;
4264 enum {
4265 PHASE_REMOVE_AND_CLEAN,
4266 PHASE_CREATE,
4267 _PHASE_MAX
4268 } phase;
4269 int r, k;
4270
4271 r = parse_argv(argc, argv);
4272 if (r <= 0)
4273 return r;
4274
4275 log_setup();
4276
4277 /* We require /proc/ for a lot of our operations, i.e. for adjusting access modes, for anything
4278 * SELinux related, for recursive operation, for xattr, acl and chattr handling, for btrfs stuff and
4279 * a lot more. It's probably the majority of invocations where /proc/ is required. Since people
4280 * apparently invoke it without anyway and are surprised about the failures, let's catch this early
4281 * and output a nice and friendly warning. */
4282 if (proc_mounted() == 0)
4283 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
4284 "/proc/ is not mounted, but required for successful operation of systemd-tmpfiles. "
4285 "Please mount /proc/. Alternatively, consider using the --root= or --image= switches.");
4286
4287 /* Descending down file system trees might take a lot of fds */
4288 (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
4289
4290 switch (arg_runtime_scope) {
4291
4292 case RUNTIME_SCOPE_USER:
4293 r = user_config_paths(&config_dirs);
4294 if (r < 0)
4295 return log_error_errno(r, "Failed to initialize configuration directory list: %m");
4296 break;
4297
4298 case RUNTIME_SCOPE_SYSTEM:
4299 config_dirs = strv_split_nulstr(CONF_PATHS_NULSTR("tmpfiles.d"));
4300 if (!config_dirs)
4301 return log_oom();
4302 break;
4303
4304 default:
4305 assert_not_reached();
4306 }
4307
4308 if (DEBUG_LOGGING) {
4309 _cleanup_free_ char *t = NULL;
4310
4311 STRV_FOREACH(i, config_dirs) {
4312 _cleanup_free_ char *j = NULL;
4313
4314 j = path_join(arg_root, *i);
4315 if (!j)
4316 return log_oom();
4317
4318 if (!strextend(&t, "\n\t", j))
4319 return log_oom();
4320 }
4321
4322 log_debug("Looking for configuration files in (higher priority first):%s", t);
4323 }
4324
4325 if (arg_cat_config) {
4326 pager_open(arg_pager_flags);
4327
4328 return cat_config(config_dirs, argv + optind);
4329 }
4330
4331 umask(0022);
4332
4333 r = mac_init();
4334 if (r < 0)
4335 return r;
4336
4337 #ifndef STANDALONE
4338 if (arg_image) {
4339 assert(!arg_root);
4340
4341 r = mount_image_privately_interactively(
4342 arg_image,
4343 arg_image_policy,
4344 DISSECT_IMAGE_GENERIC_ROOT |
4345 DISSECT_IMAGE_REQUIRE_ROOT |
4346 DISSECT_IMAGE_VALIDATE_OS |
4347 DISSECT_IMAGE_RELAX_VAR_CHECK |
4348 DISSECT_IMAGE_FSCK |
4349 DISSECT_IMAGE_GROWFS,
4350 &mounted_dir,
4351 /* ret_dir_fd= */ NULL,
4352 &loop_device);
4353 if (r < 0)
4354 return r;
4355
4356 arg_root = strdup(mounted_dir);
4357 if (!arg_root)
4358 return log_oom();
4359 }
4360 #else
4361 assert(!arg_image);
4362 #endif
4363
4364 items = ordered_hashmap_new(&item_array_hash_ops);
4365 globs = ordered_hashmap_new(&item_array_hash_ops);
4366 if (!items || !globs)
4367 return log_oom();
4368
4369 /* If command line arguments are specified along with --replace, read all
4370 * configuration files and insert the positional arguments at the specified
4371 * place. Otherwise, if command line arguments are specified, execute just
4372 * them, and finally, without --replace= or any positional arguments, just
4373 * read configuration and execute it.
4374 */
4375 if (arg_replace || optind >= argc)
4376 r = read_config_files(config_dirs, argv + optind, &invalid_config);
4377 else
4378 r = parse_arguments(config_dirs, argv + optind, &invalid_config);
4379 if (r < 0)
4380 return r;
4381
4382 r = read_credential_lines(&invalid_config);
4383 if (r < 0)
4384 return r;
4385
4386 /* Let's now link up all child/parent relationships */
4387 ORDERED_HASHMAP_FOREACH(a, items) {
4388 r = link_parent(a);
4389 if (r < 0)
4390 return r;
4391 }
4392 ORDERED_HASHMAP_FOREACH(a, globs) {
4393 r = link_parent(a);
4394 if (r < 0)
4395 return r;
4396 }
4397
4398 /* If multiple operations are requested, let's first run the remove/clean operations, and only then the create
4399 * operations. i.e. that we first clean out the platform we then build on. */
4400 for (phase = 0; phase < _PHASE_MAX; phase++) {
4401 OperationMask op;
4402
4403 if (phase == PHASE_REMOVE_AND_CLEAN)
4404 op = arg_operation & (OPERATION_REMOVE|OPERATION_CLEAN);
4405 else if (phase == PHASE_CREATE)
4406 op = arg_operation & OPERATION_CREATE;
4407 else
4408 assert_not_reached();
4409
4410 if (op == 0) /* Nothing requested in this phase */
4411 continue;
4412
4413 /* The non-globbing ones usually create things, hence we apply them first */
4414 ORDERED_HASHMAP_FOREACH(a, items) {
4415 k = process_item_array(a, op);
4416 if (k < 0 && r >= 0)
4417 r = k;
4418 }
4419
4420 /* The globbing ones usually alter things, hence we apply them second. */
4421 ORDERED_HASHMAP_FOREACH(a, globs) {
4422 k = process_item_array(a, op);
4423 if (k < 0 && r >= 0)
4424 r = k;
4425 }
4426 }
4427
4428 if (ERRNO_IS_RESOURCE(r))
4429 return r;
4430 if (invalid_config)
4431 return EX_DATAERR;
4432 if (r < 0)
4433 return EX_CANTCREAT;
4434 return 0;
4435 }
4436
4437 DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);