summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/systemd/systemd/0001-tmpfiles-don-t-resolve-pathnames-when-traversing-rec.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-core/systemd/systemd/0001-tmpfiles-don-t-resolve-pathnames-when-traversing-rec.patch')
-rw-r--r--meta/recipes-core/systemd/systemd/0001-tmpfiles-don-t-resolve-pathnames-when-traversing-rec.patch643
1 files changed, 643 insertions, 0 deletions
diff --git a/meta/recipes-core/systemd/systemd/0001-tmpfiles-don-t-resolve-pathnames-when-traversing-rec.patch b/meta/recipes-core/systemd/systemd/0001-tmpfiles-don-t-resolve-pathnames-when-traversing-rec.patch
new file mode 100644
index 0000000000..108e4ad8b8
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/0001-tmpfiles-don-t-resolve-pathnames-when-traversing-rec.patch
@@ -0,0 +1,643 @@
1From 33dc9a280f952f503e5493ee29f6815bef29d551 Mon Sep 17 00:00:00 2001
2From: Franck Bui <fbui@suse.com>
3Date: Fri, 2 Mar 2018 17:19:32 +0100
4Subject: [PATCH] tmpfiles: don't resolve pathnames when traversing recursively
5 through directory trees
6
7Otherwise we can be fooled if one path component is replaced underneath us.
8
9The patch achieves that by always operating at file descriptor level (by using
10*at() helpers) and by making sure we do not any path resolution when traversing
11direcotry trees.
12
13However this is not always possible, for instance when listing the content of a
14directory or some operations don't provide the *at() helpers or others (such as
15fchmodat()) don't have the AT_EMPTY_PATH flag. In such cases we operate on
16/proc/self/fd/%i pseudo-symlink instead, which works the same for all kinds of
17objects and requires no checking of type beforehand.
18
19Also O_PATH flag is used when opening file objects in order to prevent
20undesired behaviors: device nodes from reacting, automounts from
21triggering, etc...
22
23Fixes: CVE-2018-6954
24
25Origin: upstream, https://github.com/systemd/systemd/commit/936f6bdb803c432578e2cdcc5f93f3bfff93aff0
26Bug: https://github.com/systemd/systemd/issues/7986
27
28Patch from:
29systemd_237-3ubuntu10.13.debian CVE-2018-6954.patch
30
31https://usn.ubuntu.com/3816-1/ states that CVE-2018-6954 doesn't
32affect Ubuntu 18.10 which uses the same version of systemd as thud
33(239).
34
35CVE: CVE-2018-6954
36Upstream-Status: Backport
37
38Signed-off-by: George McCollister <george.mccollister@gmail.com>
39---
40 src/tmpfiles/tmpfiles.c | 363 +++++++++++++++++++++++++++++++-----------------
41 1 file changed, 239 insertions(+), 124 deletions(-)
42
43diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
44index 88cc543f09..613d418eb3 100644
45--- a/src/tmpfiles/tmpfiles.c
46+++ b/src/tmpfiles/tmpfiles.c
47@@ -792,94 +792,105 @@ static bool hardlink_vulnerable(struct stat *st) {
48 return !S_ISDIR(st->st_mode) && st->st_nlink > 1 && dangerous_hardlinks();
49 }
50
51-static int path_set_perms(Item *i, const char *path) {
52- char fn[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
53- _cleanup_close_ int fd = -1;
54- struct stat st;
55+static int fd_set_perms(Item *i, int fd, const struct stat *st) {
56+ _cleanup_free_ char *path = NULL;
57+ int r;
58
59 assert(i);
60- assert(path);
61-
62- if (!i->mode_set && !i->uid_set && !i->gid_set)
63- goto shortcut;
64-
65- /* We open the file with O_PATH here, to make the operation
66- * somewhat atomic. Also there's unfortunately no fchmodat()
67- * with AT_SYMLINK_NOFOLLOW, hence we emulate it here via
68- * O_PATH. */
69-
70- fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
71- if (fd < 0) {
72- int level = LOG_ERR, r = -errno;
73+ assert(fd);
74
75- /* Option "e" operates only on existing objects. Do not
76- * print errors about non-existent files or directories */
77- if (i->type == EMPTY_DIRECTORY && errno == ENOENT) {
78- level = LOG_DEBUG;
79- r = 0;
80- }
81-
82- log_full_errno(level, errno, "Adjusting owner and mode for %s failed: %m", path);
83+ r = fd_get_path(fd, &path);
84+ if (r < 0)
85 return r;
86- }
87
88- if (fstatat(fd, "", &st, AT_EMPTY_PATH) < 0)
89- return log_error_errno(errno, "Failed to fstat() file %s: %m", path);
90+ if (!i->mode_set && !i->uid_set && !i->gid_set)
91+ goto shortcut;
92
93- if (hardlink_vulnerable(&st)) {
94+ if (hardlink_vulnerable(st)) {
95 log_error("Refusing to set permissions on hardlinked file %s while the fs.protected_hardlinks sysctl is turned off.", path);
96 return -EPERM;
97 }
98
99- xsprintf(fn, "/proc/self/fd/%i", fd);
100-
101 if (i->mode_set) {
102- if (S_ISLNK(st.st_mode))
103+ if (S_ISLNK(st->st_mode))
104 log_debug("Skipping mode fix for symlink %s.", path);
105 else {
106 mode_t m = i->mode;
107
108 if (i->mask_perms) {
109- if (!(st.st_mode & 0111))
110+ if (!(st->st_mode & 0111))
111 m &= ~0111;
112- if (!(st.st_mode & 0222))
113+ if (!(st->st_mode & 0222))
114 m &= ~0222;
115- if (!(st.st_mode & 0444))
116+ if (!(st->st_mode & 0444))
117 m &= ~0444;
118- if (!S_ISDIR(st.st_mode))
119+ if (!S_ISDIR(st->st_mode))
120 m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
121 }
122
123- if (m == (st.st_mode & 07777))
124- log_debug("\"%s\" has correct mode %o already.", path, st.st_mode);
125+ if (m == (st->st_mode & 07777))
126+ log_debug("\"%s\" has correct mode %o already.", path, st->st_mode);
127 else {
128+ char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
129+
130 log_debug("Changing \"%s\" to mode %o.", path, m);
131
132- if (chmod(fn, m) < 0)
133- return log_error_errno(errno, "chmod() of %s via %s failed: %m", path, fn);
134+ /* fchmodat() still doesn't have AT_EMPTY_PATH flag. */
135+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
136+
137+ if (chmod(procfs_path, m) < 0)
138+ return log_error_errno(errno, "chmod() of %s via %s failed: %m", path, procfs_path);
139 }
140 }
141 }
142
143- if ((i->uid_set && i->uid != st.st_uid) ||
144- (i->gid_set && i->gid != st.st_gid)) {
145+ if ((i->uid_set && i->uid != st->st_uid) ||
146+ (i->gid_set && i->gid != st->st_gid)) {
147 log_debug("Changing \"%s\" to owner "UID_FMT":"GID_FMT,
148 path,
149 i->uid_set ? i->uid : UID_INVALID,
150 i->gid_set ? i->gid : GID_INVALID);
151
152- if (chown(fn,
153- i->uid_set ? i->uid : UID_INVALID,
154- i->gid_set ? i->gid : GID_INVALID) < 0)
155- return log_error_errno(errno, "chown() of %s via %s failed: %m", path, fn);
156+ if (fchownat(fd,
157+ "",
158+ i->uid_set ? i->uid : UID_INVALID,
159+ i->gid_set ? i->gid : GID_INVALID,
160+ AT_EMPTY_PATH) < 0)
161+ return log_error_errno(errno, "fchownat() of %s failed: %m", path);
162 }
163
164- fd = safe_close(fd);
165-
166 shortcut:
167 return label_fix(path, false, false);
168 }
169
170+static int path_set_perms(Item *i, const char *path) {
171+ _cleanup_close_ int fd = -1;
172+ struct stat st;
173+
174+ assert(i);
175+ assert(path);
176+
177+ fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
178+ if (fd < 0) {
179+ int level = LOG_ERR, r = -errno;
180+
181+ /* Option "e" operates only on existing objects. Do not
182+ * print errors about non-existent files or directories */
183+ if (i->type == EMPTY_DIRECTORY && errno == ENOENT) {
184+ level = LOG_DEBUG;
185+ r = 0;
186+ }
187+
188+ log_full_errno(level, errno, "Adjusting owner and mode for %s failed: %m", path);
189+ return r;
190+ }
191+
192+ if (fstat(fd, &st) < 0)
193+ return log_error_errno(errno, "Failed to fstat() file %s: %m", path);
194+
195+ return fd_set_perms(i, fd, &st);
196+}
197+
198 static int parse_xattrs_from_arg(Item *i) {
199 const char *p;
200 int r;
201@@ -918,21 +929,43 @@ static int parse_xattrs_from_arg(Item *i) {
202 return 0;
203 }
204
205-static int path_set_xattrs(Item *i, const char *path) {
206+static int fd_set_xattrs(Item *i, int fd, const struct stat *st) {
207+ char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
208+ _cleanup_free_ char *path = NULL;
209 char **name, **value;
210+ int r;
211
212 assert(i);
213- assert(path);
214+ assert(fd);
215+
216+ r = fd_get_path(fd, &path);
217+ if (r < 0)
218+ return r;
219+
220+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
221
222 STRV_FOREACH_PAIR(name, value, i->xattrs) {
223 log_debug("Setting extended attribute '%s=%s' on %s.", *name, *value, path);
224- if (lsetxattr(path, *name, *value, strlen(*value), 0) < 0)
225+ if (setxattr(procfs_path, *name, *value, strlen(*value), 0) < 0)
226 return log_error_errno(errno, "Setting extended attribute %s=%s on %s failed: %m",
227 *name, *value, path);
228 }
229 return 0;
230 }
231
232+static int path_set_xattrs(Item *i, const char *path) {
233+ _cleanup_close_ int fd = -1;
234+
235+ assert(i);
236+ assert(path);
237+
238+ fd = open(path, O_CLOEXEC|O_NOFOLLOW|O_PATH);
239+ if (fd < 0)
240+ return log_error_errno(errno, "Cannot open '%s': %m", path);
241+
242+ return fd_set_xattrs(i, fd, NULL);
243+}
244+
245 static int parse_acls_from_arg(Item *item) {
246 #if HAVE_ACL
247 int r;
248@@ -998,52 +1031,71 @@ static int path_set_acl(const char *path, const char *pretty, acl_type_t type, a
249 }
250 #endif
251
252-static int path_set_acls(Item *item, const char *path) {
253+static int fd_set_acls(Item *item, int fd, const struct stat *st) {
254 int r = 0;
255 #if HAVE_ACL
256- char fn[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
257- _cleanup_close_ int fd = -1;
258- struct stat st;
259+ char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
260+ _cleanup_free_ char *path = NULL;
261
262 assert(item);
263- assert(path);
264-
265- fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
266- if (fd < 0)
267- return log_error_errno(errno, "Adjusting ACL of %s failed: %m", path);
268+ assert(fd);
269+ assert(st);
270
271- if (fstatat(fd, "", &st, AT_EMPTY_PATH) < 0)
272- return log_error_errno(errno, "Failed to fstat() file %s: %m", path);
273+ r = fd_get_path(fd, &path);
274+ if (r < 0)
275+ return r;
276
277- if (hardlink_vulnerable(&st)) {
278+ if (hardlink_vulnerable(st)) {
279 log_error("Refusing to set ACLs on hardlinked file %s while the fs.protected_hardlinks sysctl is turned off.", path);
280 return -EPERM;
281 }
282
283- if (S_ISLNK(st.st_mode)) {
284+ if (S_ISLNK(st->st_mode)) {
285 log_debug("Skipping ACL fix for symlink %s.", path);
286 return 0;
287 }
288
289- xsprintf(fn, "/proc/self/fd/%i", fd);
290+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
291
292 if (item->acl_access)
293- r = path_set_acl(fn, path, ACL_TYPE_ACCESS, item->acl_access, item->force);
294+ r = path_set_acl(procfs_path, path, ACL_TYPE_ACCESS, item->acl_access, item->force);
295
296 if (r == 0 && item->acl_default)
297- r = path_set_acl(fn, path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
298+ r = path_set_acl(procfs_path, path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
299
300 if (r > 0)
301 return -r; /* already warned */
302- else if (r == -EOPNOTSUPP) {
303+ if (r == -EOPNOTSUPP) {
304 log_debug_errno(r, "ACLs not supported by file system at %s", path);
305 return 0;
306- } else if (r < 0)
307- log_error_errno(r, "ACL operation on \"%s\" failed: %m", path);
308+ }
309+ if (r < 0)
310+ return log_error_errno(r, "ACL operation on \"%s\" failed: %m", path);
311 #endif
312 return r;
313 }
314
315+static int path_set_acls(Item *item, const char *path) {
316+ int r = 0;
317+#ifdef HAVE_ACL
318+ _cleanup_close_ int fd = -1;
319+ struct stat st;
320+
321+ assert(item);
322+ assert(path);
323+
324+ fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
325+ if (fd < 0)
326+ return log_error_errno(errno, "Adjusting ACL of %s failed: %m", path);
327+
328+ if (fstat(fd, &st) < 0)
329+ return log_error_errno(errno, "Failed to fstat() file %s: %m", path);
330+
331+ r = fd_set_acls(item, fd, &st);
332+ #endif
333+ return r;
334+ }
335+
336 #define ATTRIBUTES_ALL \
337 (FS_NOATIME_FL | \
338 FS_SYNC_FL | \
339@@ -1143,30 +1195,24 @@ static int parse_attribute_from_arg(Item *item) {
340 return 0;
341 }
342
343-static int path_set_attribute(Item *item, const char *path) {
344- _cleanup_close_ int fd = -1;
345- struct stat st;
346+static int fd_set_attribute(Item *item, int fd, const struct stat *st) {
347+ char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
348+ _cleanup_close_ int procfs_fd = -1;
349+ _cleanup_free_ char *path = NULL;
350 unsigned f;
351 int r;
352
353 if (!item->attribute_set || item->attribute_mask == 0)
354 return 0;
355
356- fd = open(path, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOATIME|O_NOFOLLOW);
357- if (fd < 0) {
358- if (errno == ELOOP)
359- return log_error_errno(errno, "Skipping file attributes adjustment on symlink %s.", path);
360-
361- return log_error_errno(errno, "Cannot open '%s': %m", path);
362- }
363-
364- if (fstat(fd, &st) < 0)
365- return log_error_errno(errno, "Cannot stat '%s': %m", path);
366+ r = fd_get_path(fd, &path);
367+ if (r < 0)
368+ return r;
369
370 /* Issuing the file attribute ioctls on device nodes is not
371 * safe, as that will be delivered to the drivers, not the
372 * file system containing the device node. */
373- if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
374+ if (!S_ISREG(st->st_mode) && !S_ISDIR(st->st_mode)) {
375 log_error("Setting file flags is only supported on regular files and directories, cannot set on '%s'.", path);
376 return -EINVAL;
377 }
378@@ -1174,10 +1220,16 @@ static int path_set_attribute(Item *item, const char *path) {
379 f = item->attribute_value & item->attribute_mask;
380
381 /* Mask away directory-specific flags */
382- if (!S_ISDIR(st.st_mode))
383+ if (!S_ISDIR(st->st_mode))
384 f &= ~FS_DIRSYNC_FL;
385
386- r = chattr_fd(fd, f, item->attribute_mask);
387+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
388+
389+ procfs_fd = open(procfs_path, O_RDONLY|O_CLOEXEC|O_NOATIME);
390+ if (procfs_fd < 0)
391+ return -errno;
392+
393+ r = chattr_fd(procfs_fd, f, item->attribute_mask);
394 if (r < 0)
395 log_full_errno(IN_SET(r, -ENOTTY, -EOPNOTSUPP) ? LOG_DEBUG : LOG_WARNING,
396 r,
397@@ -1187,6 +1239,23 @@ static int path_set_attribute(Item *item, const char *path) {
398 return 0;
399 }
400
401+static int path_set_attribute(Item *item, const char *path) {
402+ _cleanup_close_ int fd = -1;
403+ struct stat st;
404+
405+ if (!item->attribute_set || item->attribute_mask == 0)
406+ return 0;
407+
408+ fd = open(path, O_CLOEXEC|O_NOFOLLOW|O_PATH);
409+ if (fd < 0)
410+ return log_error_errno(errno, "Cannot open '%s': %m", path);
411+
412+ if (fstat(fd, &st) < 0)
413+ return log_error_errno(errno, "Cannot stat '%s': %m", path);
414+
415+ return fd_set_attribute(item, fd, &st);
416+}
417+
418 static int write_one_file(Item *i, const char *path) {
419 _cleanup_close_ int fd = -1;
420 int flags, r = 0;
421@@ -1251,48 +1320,58 @@ done:
422 }
423
424 typedef int (*action_t)(Item *, const char *);
425+typedef int (*fdaction_t)(Item *, int fd, const struct stat *st);
426
427-static int item_do_children(Item *i, const char *path, action_t action) {
428- _cleanup_closedir_ DIR *d;
429- struct dirent *de;
430- int r = 0;
431+static int item_do(Item *i, int fd, const struct stat *st, fdaction_t action) {
432+ int r = 0, q;
433
434 assert(i);
435- assert(path);
436+ assert(fd >= 0);
437+ assert(st);
438
439 /* This returns the first error we run into, but nevertheless
440 * tries to go on */
441+ r = action(i, fd, st);
442
443- d = opendir_nomod(path);
444- if (!d)
445- return IN_SET(errno, ENOENT, ENOTDIR, ELOOP) ? 0 : -errno;
446+ if (S_ISDIR(st->st_mode)) {
447+ char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
448+ _cleanup_closedir_ DIR *d = NULL;
449+ struct dirent *de;
450
451- FOREACH_DIRENT_ALL(de, d, r = -errno) {
452- _cleanup_free_ char *p = NULL;
453- int q;
454+ /* The passed 'fd' was opened with O_PATH. We need to convert
455+ * it into a 'regular' fd before reading the directory content. */
456+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
457
458- if (dot_or_dot_dot(de->d_name))
459- continue;
460+ d = opendir(procfs_path);
461+ if (!d) {
462+ r = r ?: -errno;
463+ goto finish;
464+ }
465
466- p = strjoin(path, "/", de->d_name);
467- if (!p)
468- return -ENOMEM;
469+ FOREACH_DIRENT_ALL(de, d, q = -errno; goto finish) {
470+ struct stat de_st;
471+ int de_fd;
472+
473+ if (dot_or_dot_dot(de->d_name))
474+ continue;
475
476- q = action(i, p);
477- if (q < 0 && q != -ENOENT && r == 0)
478- r = q;
479+ de_fd = openat(fd, de->d_name, O_NOFOLLOW|O_CLOEXEC|O_PATH);
480+ if (de_fd >= 0 && fstat(de_fd, &de_st) >= 0)
481+ /* pass ownership of dirent fd over */
482+ q = item_do(i, de_fd, &de_st, action);
483+ else
484+ q = -errno;
485
486- if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
487- q = item_do_children(i, p, action);
488 if (q < 0 && r == 0)
489 r = q;
490 }
491 }
492-
493+finish:
494+ safe_close(fd);
495 return r;
496 }
497
498-static int glob_item(Item *i, action_t action, bool recursive) {
499+static int glob_item(Item *i, action_t action) {
500 _cleanup_globfree_ glob_t g = {
501 #ifdef GLOB_ALTDIRFUNC
502 .gl_opendir = (void *(*)(const char *)) opendir_nomod,
503@@ -1309,12 +1388,48 @@ static int glob_item(Item *i, action_t action, bool recursive) {
504 k = action(i, *fn);
505 if (k < 0 && r == 0)
506 r = k;
507+ }
508
509- if (recursive) {
510- k = item_do_children(i, *fn, action);
511- if (k < 0 && r == 0)
512- r = k;
513+ return r;
514+}
515+
516+static int glob_item_recursively(Item *i, fdaction_t action) {
517+ _cleanup_globfree_ glob_t g = {
518+ .gl_opendir = (void *(*)(const char *)) opendir_nomod,
519+ };
520+ int r = 0, k;
521+ char **fn;
522+
523+ k = safe_glob(i->path, GLOB_NOSORT|GLOB_BRACE, &g);
524+ if (k < 0 && k != -ENOENT)
525+ return log_error_errno(k, "glob(%s) failed: %m", i->path);
526+
527+ STRV_FOREACH(fn, g.gl_pathv) {
528+ _cleanup_close_ int fd = -1;
529+ struct stat st;
530+
531+ /* Make sure we won't trigger/follow file object (such as
532+ * device nodes, automounts, ...) pointed out by 'fn' with
533+ * O_PATH. Note, when O_PATH is used, flags other than
534+ * O_CLOEXEC, O_DIRECTORY, and O_NOFOLLOW are ignored. */
535+
536+ fd = open(*fn, O_CLOEXEC|O_NOFOLLOW|O_PATH);
537+ if (fd < 0) {
538+ r = r ?: -errno;
539+ continue;
540+ }
541+
542+ if (fstat(fd, &st) < 0) {
543+ r = r ?: -errno;
544+ continue;
545 }
546+
547+ k = item_do(i, fd, &st, action);
548+ if (k < 0 && r == 0)
549+ r = k;
550+
551+ /* we passed fd ownership to the previous call */
552+ fd = -1;
553 }
554
555 return r;
556@@ -1403,7 +1518,7 @@ static int create_item(Item *i) {
557 break;
558
559 case WRITE_FILE:
560- r = glob_item(i, write_one_file, false);
561+ r = glob_item(i, write_one_file);
562 if (r < 0)
563 return r;
564
565@@ -1662,49 +1777,49 @@ static int create_item(Item *i) {
566
567 case ADJUST_MODE:
568 case RELABEL_PATH:
569- r = glob_item(i, path_set_perms, false);
570+ r = glob_item(i, path_set_perms);
571 if (r < 0)
572 return r;
573 break;
574
575 case RECURSIVE_RELABEL_PATH:
576- r = glob_item(i, path_set_perms, true);
577+ r = glob_item_recursively(i, fd_set_perms);
578 if (r < 0)
579 return r;
580 break;
581
582 case SET_XATTR:
583- r = glob_item(i, path_set_xattrs, false);
584+ r = glob_item(i, path_set_xattrs);
585 if (r < 0)
586 return r;
587 break;
588
589 case RECURSIVE_SET_XATTR:
590- r = glob_item(i, path_set_xattrs, true);
591+ r = glob_item_recursively(i, fd_set_xattrs);
592 if (r < 0)
593 return r;
594 break;
595
596 case SET_ACL:
597- r = glob_item(i, path_set_acls, false);
598+ r = glob_item(i, path_set_acls);
599 if (r < 0)
600 return r;
601 break;
602
603 case RECURSIVE_SET_ACL:
604- r = glob_item(i, path_set_acls, true);
605+ r = glob_item_recursively(i, fd_set_acls);
606 if (r < 0)
607 return r;
608 break;
609
610 case SET_ATTRIBUTE:
611- r = glob_item(i, path_set_attribute, false);
612+ r = glob_item(i, path_set_attribute);
613 if (r < 0)
614 return r;
615 break;
616
617 case RECURSIVE_SET_ATTRIBUTE:
618- r = glob_item(i, path_set_attribute, true);
619+ r = glob_item_recursively(i, fd_set_attribute);
620 if (r < 0)
621 return r;
622 break;
623@@ -1754,7 +1869,7 @@ static int remove_item(Item *i) {
624 case REMOVE_PATH:
625 case TRUNCATE_DIRECTORY:
626 case RECURSIVE_REMOVE_PATH:
627- return glob_item(i, remove_item_instance, false);
628+ return glob_item(i, remove_item_instance);
629
630 default:
631 return 0;
632@@ -1828,7 +1943,7 @@ static int clean_item(Item *i) {
633 return 0;
634 case EMPTY_DIRECTORY:
635 case IGNORE_DIRECTORY_PATH:
636- return glob_item(i, clean_item_instance, false);
637+ return glob_item(i, clean_item_instance);
638 default:
639 return 0;
640 }
641--
6422.11.0
643