]> gitweb.michael.orlitzky.com - apply-default-acl.git/blob - src/libadacl.c
Replace nftw() with manual recursion in apply_default_acl().
[apply-default-acl.git] / src / libadacl.c
1 /**
2 * @file libadacl.c
3 *
4 * @brief The adacl (apply default acl) shared library.
5 *
6 */
7
8 /* Enables get_current_dir_name() in unistd.h and the O_PATH flag. */
9 #define _GNU_SOURCE
10
11 #include <dirent.h> /* readdir(), etc. */
12 #include <errno.h> /* EINVAL, ELOOP, ENOTDIR, etc. */
13 #include <fcntl.h> /* openat() */
14 #include <libgen.h> /* basename(), dirname() */
15 #include <limits.h> /* PATH_MAX */
16 #include <stdbool.h> /* the "bool" type */
17 #include <stdio.h> /* perror(), snprintf() */
18 #include <stdlib.h> /* free() */
19 #include <string.h> /* strdup() */
20 #include <sys/stat.h> /* fstat() */
21 #include <sys/xattr.h> /* fgetxattr(), fsetxattr() */
22 #include <unistd.h> /* get_current_dir_name() */
23
24 /* ACLs */
25 #include <acl/libacl.h> /* acl_get_perm, not portable */
26 #include <sys/acl.h> /* all other acl_foo functions */
27
28 /* XATTR_NAME_POSIX_ACL_ACCESS and XATTR_NAME_POSIX_ACL_DEFAULT */
29 #include <linux/xattr.h>
30
31 #include "libadacl.h"
32
33
34 /* Even though most other library functions reliably return -1 for
35 * error, it feels a little wrong to re-use the ACL_ERROR constant.
36 */
37 #define CLOSE_ERROR -1
38 #define OPEN_ERROR -1
39 #define SNPRINTF_ERROR -1
40 #define STAT_ERROR -1
41 #define XATTR_ERROR -1
42
43
44 /**
45 * @brief The recursive portion of the @c safe_open function, used to
46 * open a file descriptor in a symlink-safe way when combined with
47 * the @c O_NOFOLLOW flag.
48 *
49 * @param at_fd
50 * A file descriptor relative to which @c pathname will be opened.
51 *
52 * @param pathname
53 * The path to the file/directory/whatever whose descriptor you want.
54 *
55 * @param flags
56 * File status flags to be passed to @c openat.
57 *
58 * @return a file descriptor for @c pathname if everything goes well,
59 * and @c OPEN_ERROR if not.
60 */
61 int safe_open_ex(int at_fd, char* pathname, int flags) {
62 if (pathname == NULL) {
63 errno = EINVAL;
64 perror("safe_open_ex (args)");
65 return OPEN_ERROR;
66 }
67
68 char* firstslash = strchr(pathname, '/');
69 if (firstslash == NULL) {
70 /* No more slashes, this is the base case. */
71 return openat(at_fd, pathname, flags);
72 }
73 if (firstslash[1] == '\0') {
74 /* The first slash is the last character; ensure that we open
75 a directory. */
76 firstslash[0] = '\0';
77 return openat(at_fd, pathname, flags | O_DIRECTORY);
78 }
79
80 /* The first slash exists and isn't the last character in the path,
81 so we can split the path wherever that first slash lies and
82 recurse. */
83 *firstslash = '\0';
84 int fd = openat(at_fd, pathname, flags | O_DIRECTORY | O_PATH);
85 if (fd == OPEN_ERROR) {
86 if (errno != ENOTDIR) {
87 /* Don't output anything if we ignore a symlink */
88 perror("safe_open_ex (safe_open_ex)");
89 }
90 return OPEN_ERROR;
91 }
92
93 /* The +1 is safe because there needs to be at least one character
94 after the first slash (we checked this above). */
95 int result = safe_open_ex(fd, firstslash+1, flags);
96 if (close(fd) == CLOSE_ERROR) {
97 perror("safe_open_ex (close)");
98 return OPEN_ERROR;
99 }
100 return result;
101 }
102
103
104 /**
105 * @brief A version of @c open that is completely symlink-safe when
106 * used with the @c O_NOFOLLOW flag.
107 *
108 * The @c openat function exists to ensure that you can anchor one
109 * path to a particular directory while opening it; however, if you
110 * open "b/c/d" relative to "/a", then even the @c openat function will
111 * still follow symlinks in the "b" component. This can be exploited
112 * by an attacker to make you open the wrong path.
113 *
114 * To avoid that problem, this function uses a recursive
115 * implementation that opens every path from the root, one level at a
116 * time. So "a" is opened relative to "/", and then "b" is opened
117 * relative to "/a", and then "c" is opened relative to "/a/b",
118 * etc. When the @c O_NOFOLLOW flag is used, this approach ensures
119 * that no symlinks in any component are followed.
120 *
121 * @param pathname
122 * The path to the file/directory/whatever whose descriptor you want.
123 *
124 * @param flags
125 * File status flags to be passed to @c openat.
126 *
127 * @return a file descriptor for @c pathname if everything goes well,
128 * and @c OPEN_ERROR if not.
129 */
130 int safe_open(const char* pathname, int flags) {
131 if (pathname == NULL) {
132 errno = EINVAL;
133 perror("safe_open (args)");
134 return OPEN_ERROR;
135 }
136
137 char abspath[PATH_MAX];
138 int snprintf_result = 0;
139 if (strchr(pathname, '/') == pathname) {
140 /* pathname is already absolute; just copy it. */
141 snprintf_result = snprintf(abspath, PATH_MAX, "%s", pathname);
142 }
143 else {
144 /* Concatenate the current working directory and pathname into an
145 * absolute path. We use realpath() ONLY on the cwd part, and not
146 * on the pathname part, because realpath() resolves symlinks. And
147 * the whole point of all this crap is to avoid following symlinks
148 * in the pathname.
149 *
150 * Using realpath() on the cwd lets us operate on relative paths
151 * while we're sitting in a directory that happens to have a
152 * symlink in it; for example: cd /var/run && apply-default-acl foo.
153 */
154 char* cwd = get_current_dir_name();
155 if (cwd == NULL) {
156 perror("safe_open (get_current_dir_name)");
157 return OPEN_ERROR;
158 }
159
160 char abs_cwd[PATH_MAX];
161 if (realpath(cwd, abs_cwd) == NULL) {
162 perror("safe_open (realpath)");
163 free(cwd);
164 return OPEN_ERROR;
165 }
166 snprintf_result = snprintf(abspath, PATH_MAX, "%s/%s", abs_cwd, pathname);
167 free(cwd);
168 }
169 if (snprintf_result == SNPRINTF_ERROR || snprintf_result > PATH_MAX) {
170 perror("safe_open (snprintf)");
171 return OPEN_ERROR;
172 }
173
174 bool abspath_is_root = (strcmp(abspath, "/") == 0);
175 int rootflags = flags | O_DIRECTORY;
176 if (!abspath_is_root) {
177 /* Use O_PATH for some added safety if "/" is not our target */
178 rootflags |= O_PATH;
179 }
180 int rootfd = open("/", rootflags);
181 if (rootfd == OPEN_ERROR) {
182 perror("safe_open (open)");
183 return OPEN_ERROR;
184 }
185
186 if (abspath_is_root) {
187 return rootfd;
188 }
189
190 int result = safe_open_ex(rootfd, abspath+1, flags);
191 if (close(rootfd) == CLOSE_ERROR) {
192 perror("safe_open (close)");
193 return OPEN_ERROR;
194 }
195 return result;
196 }
197
198
199
200
201 /**
202 * @brief Update an entry in an @b minimal ACL.
203 *
204 * @param aclp
205 * A pointer to the acl_t structure whose entry we want to update.
206 *
207 * @param entry
208 * The new entry.
209 *
210 * @return
211 * - @c ACL_SUCCESS - If we update an existing entry.
212 * - @c ACL_FAILURE - If we don't find an entry to update.
213 * - @c ACL_ERROR - Unexpected library error.
214 */
215 int acl_update_entry(acl_t aclp, acl_entry_t entry) {
216 if (aclp == NULL || entry == NULL) {
217 errno = EINVAL;
218 perror("acl_update_entry (args)");
219 return ACL_ERROR;
220 }
221
222 acl_tag_t entry_tag;
223 if (acl_get_tag_type(entry, &entry_tag) == ACL_ERROR) {
224 perror("acl_update_entry (acl_get_tag_type)");
225 return ACL_ERROR;
226 }
227
228 acl_permset_t entry_permset;
229 if (acl_get_permset(entry, &entry_permset) == ACL_ERROR) {
230 perror("acl_update_entry (acl_get_permset)");
231 return ACL_ERROR;
232 }
233
234 acl_entry_t existing_entry;
235 /* Loop through the given ACL looking for matching entries. */
236 int result = acl_get_entry(aclp, ACL_FIRST_ENTRY, &existing_entry);
237
238 while (result == ACL_SUCCESS) {
239 acl_tag_t existing_tag = ACL_UNDEFINED_TAG;
240
241 if (acl_get_tag_type(existing_entry, &existing_tag) == ACL_ERROR) {
242 perror("set_acl_tag_permset (acl_get_tag_type)");
243 return ACL_ERROR;
244 }
245
246 if (existing_tag == entry_tag) {
247 /* If we update something, we're done and return ACL_SUCCESS */
248 if (acl_set_permset(existing_entry, entry_permset) == ACL_ERROR) {
249 perror("acl_update_entry (acl_set_permset)");
250 return ACL_ERROR;
251 }
252
253 return ACL_SUCCESS;
254 }
255
256 result = acl_get_entry(aclp, ACL_NEXT_ENTRY, &existing_entry);
257 }
258
259 /* This catches both the initial acl_get_entry and the ones at the
260 end of the loop. */
261 if (result == ACL_ERROR) {
262 perror("acl_update_entry (acl_get_entry)");
263 return ACL_ERROR;
264 }
265
266 return ACL_FAILURE;
267 }
268
269
270
271 /**
272 * @brief Determine the number of entries in the given ACL.
273 *
274 * @param acl
275 * The ACL to inspect.
276 *
277 * @return Either the non-negative number of entries in @c acl, or
278 * @c ACL_ERROR on error.
279 */
280 int acl_entry_count(acl_t acl) {
281
282 acl_entry_t entry;
283 int entry_count = 0;
284 int result = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
285
286 while (result == ACL_SUCCESS) {
287 entry_count++;
288 result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
289 }
290
291 if (result == ACL_ERROR) {
292 perror("acl_entry_count (acl_get_entry)");
293 return ACL_ERROR;
294 }
295
296 return entry_count;
297 }
298
299
300
301 /**
302 * @brief Determine whether or not the given ACL is minimal.
303 *
304 * An ACL is minimal if it has fewer than four entries.
305 *
306 * @param acl
307 * The ACL whose minimality is in question.
308 *
309 * @return
310 * - @c ACL_SUCCESS - @c acl is minimal
311 * - @c ACL_FAILURE - @c acl is not minimal
312 * - @c ACL_ERROR - Unexpected library error
313 */
314 int acl_is_minimal(acl_t acl) {
315 if (acl == NULL) {
316 errno = EINVAL;
317 perror("acl_is_minimal (args)");
318 return ACL_ERROR;
319 }
320
321 int ec = acl_entry_count(acl);
322
323 if (ec == ACL_ERROR) {
324 perror("acl_is_minimal (acl_entry_count)");
325 return ACL_ERROR;
326 }
327
328 if (ec < 4) {
329 return ACL_SUCCESS;
330 }
331 else {
332 return ACL_FAILURE;
333 }
334 }
335
336
337
338 /**
339 * @brief Determine whether the given ACL's mask denies execute.
340 *
341 * @param acl
342 * The ACL whose mask we want to check.
343 *
344 * @return
345 * - @c ACL_SUCCESS - The @c acl has a mask which denies execute.
346 * - @c ACL_FAILURE - The @c acl has a mask which does not deny execute.
347 * - @c ACL_ERROR - Unexpected library error.
348 */
349 int acl_execute_masked(acl_t acl) {
350 if (acl == NULL) {
351 errno = EINVAL;
352 perror("acl_execute_masked (args)");
353 return ACL_ERROR;
354 }
355
356 acl_entry_t entry;
357 int ge_result = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
358
359 while (ge_result == ACL_SUCCESS) {
360 acl_tag_t tag = ACL_UNDEFINED_TAG;
361
362 if (acl_get_tag_type(entry, &tag) == ACL_ERROR) {
363 perror("acl_execute_masked (acl_get_tag_type)");
364 return ACL_ERROR;
365 }
366
367 if (tag == ACL_MASK) {
368 /* This is the mask entry, get its permissions, and see if
369 execute is specified. */
370 acl_permset_t permset;
371
372 if (acl_get_permset(entry, &permset) == ACL_ERROR) {
373 perror("acl_execute_masked (acl_get_permset)");
374 return ACL_ERROR;
375 }
376
377 int gp_result = acl_get_perm(permset, ACL_EXECUTE);
378 if (gp_result == ACL_ERROR) {
379 perror("acl_execute_masked (acl_get_perm)");
380 return ACL_ERROR;
381 }
382
383 if (gp_result == ACL_FAILURE) {
384 /* No execute bit set in the mask; execute not allowed. */
385 return ACL_SUCCESS;
386 }
387 }
388
389 ge_result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
390 }
391
392 return ACL_FAILURE;
393 }
394
395
396
397 /**
398 * @brief Determine whether @c fd is executable by anyone.
399 *
400 *
401 * This is used as part of the heuristic to determine whether or not
402 * we should mask the execute bit when inheriting an ACL. If @c fd
403 * describes a file, we check the @a effective permissions, contrary
404 * to what setfacl does.
405 *
406 * @param fd
407 * The file descriptor to check.
408 *
409 * @param sp
410 * A pointer to a stat structure for @c fd.
411 *
412 * @return
413 * - @c ACL_SUCCESS - Someone has effective execute permissions on @c fd.
414 * - @c ACL_FAILURE - Nobody can execute @c fd.
415 * - @c ACL_ERROR - Unexpected library error.
416 */
417 int any_can_execute(int fd, const struct stat* sp) {
418 if (sp == NULL) {
419 errno = EINVAL;
420 perror("any_can_execute (args)");
421 return ACL_ERROR;
422 }
423
424 acl_t acl = acl_get_fd(fd);
425
426 if (acl == (acl_t)NULL) {
427 perror("any_can_execute (acl_get_fd)");
428 return ACL_ERROR;
429 }
430
431 /* Our return value. */
432 int result = ACL_FAILURE;
433
434 if (acl_is_minimal(acl)) {
435 if (sp->st_mode & (S_IXUSR | S_IXOTH | S_IXGRP)) {
436 result = ACL_SUCCESS;
437 goto cleanup;
438 }
439 else {
440 result = ACL_FAILURE;
441 goto cleanup;
442 }
443 }
444
445 acl_entry_t entry;
446 int ge_result = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
447
448 while (ge_result == ACL_SUCCESS) {
449 /* The first thing we do is check to see if this is a mask
450 entry. If it is, we skip it entirely. */
451 acl_tag_t tag = ACL_UNDEFINED_TAG;
452
453 if (acl_get_tag_type(entry, &tag) == ACL_ERROR) {
454 perror("any_can_execute_or (acl_get_tag_type)");
455 result = ACL_ERROR;
456 goto cleanup;
457 }
458
459 if (tag == ACL_MASK) {
460 ge_result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
461 continue;
462 }
463
464 /* Ok, so it's not a mask entry. Check the execute perms. */
465 acl_permset_t permset;
466
467 if (acl_get_permset(entry, &permset) == ACL_ERROR) {
468 perror("any_can_execute_or (acl_get_permset)");
469 result = ACL_ERROR;
470 goto cleanup;
471 }
472
473 int gp_result = acl_get_perm(permset, ACL_EXECUTE);
474 if (gp_result == ACL_ERROR) {
475 perror("any_can_execute (acl_get_perm)");
476 result = ACL_ERROR;
477 goto cleanup;
478 }
479
480 if (gp_result == ACL_SUCCESS) {
481 /* Only return ACL_SUCCESS if this execute bit is not masked. */
482 if (acl_execute_masked(acl) != ACL_SUCCESS) {
483 result = ACL_SUCCESS;
484 goto cleanup;
485 }
486 }
487
488 ge_result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
489 }
490
491 if (ge_result == ACL_ERROR) {
492 perror("any_can_execute (acl_get_entry)");
493 result = ACL_ERROR;
494 goto cleanup;
495 }
496
497 cleanup:
498 acl_free(acl);
499 return result;
500 }
501
502
503
504 /**
505 * @brief Copy ACLs between file descriptors as xattrs, verbatim.
506 *
507 * There is a small deficiency in libacl, namely that there is no way
508 * to get or set default ACLs through file descriptors. The @c
509 * acl_get_file and @c acl_set_file functions can do it, but they use
510 * paths, and are vulnerable to symlink attacks.
511 *
512 * Fortunately, when inheriting an ACL, we don't really need to look
513 * at what it contains. That means that we can copy the on-disk xattrs
514 * from the source directory to the destination file/directory without
515 * passing through libacl, and this can be done with file descriptors
516 * through @c fgetxattr and @c fsetxattr. That's what this function
517 * does.
518 *
519 * @param src_fd
520 * The file descriptor from which the ACL will be copied.
521 *
522 * @param src_type
523 * The type of ACL (either @c ACL_TYPE_ACCESS or @c ACL_TYPE_DEFAULT)
524 * to copy from @c src_fd.
525 *
526 * @param dst_fd
527 * The file descriptor whose ACL will be overwritten with the one
528 * from @c src_fd.
529 *
530 * @param dst_type
531 * The type of ACL (either @c ACL_TYPE_ACCESS or @c ACL_TYPE_DEFAULT)
532 * to replace on @c dst_fd.
533 *
534 * @return
535 * - @c ACL_SUCCESS - The ACL was copied successfully.
536 * - @c ACL_FAILURE - There was no ACL on @c src_fd.
537 * - @c ACL_ERROR - Unexpected library error.
538 */
539 int acl_copy_xattr(int src_fd,
540 acl_type_t src_type,
541 int dst_fd,
542 acl_type_t dst_type) {
543
544 const char* src_name;
545 if (src_type == ACL_TYPE_ACCESS) {
546 src_name = XATTR_NAME_POSIX_ACL_ACCESS;
547 }
548 else if (src_type == ACL_TYPE_DEFAULT) {
549 src_name = XATTR_NAME_POSIX_ACL_DEFAULT;
550 }
551 else {
552 errno = EINVAL;
553 perror("acl_copy_xattr (src type)");
554 return ACL_ERROR;
555 }
556
557 const char* dst_name;
558 if (dst_type == ACL_TYPE_ACCESS) {
559 dst_name = XATTR_NAME_POSIX_ACL_ACCESS;
560 }
561 else if (dst_type == ACL_TYPE_DEFAULT) {
562 dst_name = XATTR_NAME_POSIX_ACL_DEFAULT;
563 }
564 else {
565 errno = EINVAL;
566 perror("acl_copy_xattr (dst type)");
567 return ACL_ERROR;
568 }
569
570 ssize_t src_size_guess = fgetxattr(src_fd, src_name, NULL, 0);
571 if (src_size_guess == XATTR_ERROR) {
572 if (errno == ENODATA) {
573 /* A missing ACL isn't really an error. ENOATTR and ENODATA are
574 synonyms, but using ENODATA here lets us avoid another
575 "include" directive. */
576 return ACL_FAILURE;
577 }
578 perror("acl_copy_xattr (fgetxattr size guess)");
579 return ACL_ERROR;
580 }
581 char* src_acl_p = alloca(src_size_guess);
582 /* The actual size may be smaller than our guess? I don't know. */
583 ssize_t src_size = fgetxattr(src_fd, src_name, src_acl_p, src_size_guess);
584 if (src_size == XATTR_ERROR) {
585 if (errno == ENODATA) {
586 /* A missing ACL isn't an error. */
587 return ACL_FAILURE;
588 }
589 perror("acl_copy_xattr (fgetxattr)");
590 return ACL_ERROR;
591 }
592
593 if (fsetxattr(dst_fd, dst_name, src_acl_p, src_size, 0) == XATTR_ERROR) {
594 perror("acl_copy_xattr (fsetxattr)");
595 return ACL_ERROR;
596 }
597
598 return ACL_SUCCESS;
599 }
600
601
602 /**
603 * @brief Determine if a file descriptor has a default ACL.
604 *
605 * @param fd
606 * The file descriptor whose default ACL is in question.
607 *
608 * @return
609 * - @c ACL_SUCCESS - If @c fd has a default ACL.
610 * - @c ACL_FAILURE - If @c fd does not have a default ACL.
611 * - @c ACL_ERROR - Unexpected library error.
612 */
613 int has_default_acl_fd(int fd) {
614 if (fgetxattr(fd, XATTR_NAME_POSIX_ACL_DEFAULT, NULL, 0) == XATTR_ERROR) {
615 if (errno == ENODATA) {
616 return ACL_FAILURE;
617 }
618 perror("has_default_acl_fd (fgetxattr)");
619 return ACL_ERROR;
620 }
621
622 return ACL_SUCCESS;
623 }
624
625
626
627 /**
628 * @brief The recursive portion of @c apply_default_acl.
629 *
630 * The @c apply_default_acl function takes a path, but then opens file
631 * descriptors for the path and its parent. Afterwards, everything is
632 * done using file descriptors, including the recursive application on
633 * the path's children. This function encapsulates the portion of @c
634 * apply_default_acl that uses only file descriptors; for the
635 * recursion, this function ultimately calls itself.
636 *
637 * This overwrites any existing ACLs on @c fd and, if @c recursive is
638 * @c true, its children. When @c recursive is @c true, the "worst"
639 * result encountered is returned as the overall result.
640 *
641 * @param parent_fd
642 * A file descriptor for the parent directory of @c fd.
643 *
644 * @param fd
645 * The file descriptor that should inherit its parent's default ACL.
646 *
647 * @param no_exec_mask
648 * The value (either true or false) of the --no-exec-mask flag.
649 *
650 * @param recursive
651 * Should we recurse into subdirectories?
652 *
653 * @return
654 * - @c ACL_SUCCESS - The parent default ACLs were inherited successfully.
655 * - @c ACL_FAILURE - If symlinks or hard links are encountered.
656 * - @c ACL_ERROR - Unexpected library error.
657 */
658 int apply_default_acl_fds(int parent_fd,
659 int fd,
660 bool no_exec_mask,
661 bool recursive) {
662 int result = ACL_SUCCESS;
663
664 /* The new ACL for this path */
665 acl_t new_acl = (acl_t)NULL;
666
667 /* A copy of new_acl, to be made before we begin mangling new_acl in
668 order to mask the execute bit. */
669 acl_t new_acl_unmasked = (acl_t)NULL;
670
671 /* Refuse to operate on hard links, which can be abused by an
672 * attacker to trick us into changing the ACL on a file we didn't
673 * intend to; namely the "target" of the hard link. There is TOCTOU
674 * race condition here, but the window is as small as possible
675 * between when we open the file descriptor (look above) and when we
676 * fstat it.
677 */
678 struct stat s;
679 if (fstat(fd, &s) == STAT_ERROR) {
680 perror("apply_default_acl_fds (fstat)");
681 /* We can't recurse without the stat struct for fd */
682 goto cleanup;
683 }
684
685
686 /* Check to make sure the parent descriptor actually has a default
687 ACL. If it doesn't, then we can "succeed" immediately, saving a
688 little work, particularly in any_can_execute(). Note that we
689 can't skip the fstat() above, because we need it in case we
690 recurse. */
691 if (has_default_acl_fd(parent_fd) == ACL_FAILURE) {
692 result = ACL_SUCCESS;
693 /* Just because this target can't inherit anything doesn't mean
694 that one of it's children can't. For example, if there's a
695 default on "c" in "a/b/c/d", then we don't want to skip all
696 children of "a"! */
697 goto recurse;
698 }
699
700
701 if (!S_ISDIR(s.st_mode)) {
702 /* If it's not a directory, make sure it's a regular,
703 non-hard-linked file. */
704 if (!S_ISREG(s.st_mode) || s.st_nlink != 1) {
705 result = ACL_FAILURE;
706 goto cleanup; /* It's not a directory, so we can skip the recursion. */
707 }
708 }
709
710
711 /* Default to not masking the exec bit; i.e. applying the default
712 ACL literally. If --no-exec-mask was not specified, then we try
713 to "guess" whether or not to mask the exec bit. This behavior
714 is modeled after the capital 'X' perms of setfacl. */
715 bool allow_exec = true;
716
717 if (!no_exec_mask) {
718 /* Never mask the execute bit on directories. */
719 int ace_result = any_can_execute(fd,&s) || S_ISDIR(s.st_mode);
720
721 if (ace_result == ACL_ERROR) {
722 perror("apply_default_acl_fds (any_can_execute)");
723 result = ACL_ERROR;
724 goto cleanup;
725 }
726
727 allow_exec = (bool)ace_result;
728 }
729
730 /* If it's a directory, inherit the parent's default. */
731 if (S_ISDIR(s.st_mode)) {
732 if (acl_copy_xattr(parent_fd,
733 ACL_TYPE_DEFAULT,
734 fd,
735 ACL_TYPE_DEFAULT) == ACL_ERROR) {
736 perror("apply_default_acl_fds (acl_copy_xattr default)");
737 result = ACL_ERROR;
738 goto cleanup;
739 }
740 }
741
742 /* If it's anything, _apply_ the parent's default. */
743 if (acl_copy_xattr(parent_fd,
744 ACL_TYPE_DEFAULT,
745 fd,
746 ACL_TYPE_ACCESS) == ACL_ERROR) {
747 perror("apply_default_acl_fds (acl_copy_xattr access)");
748 result = ACL_ERROR;
749 goto cleanup;
750 }
751
752 /* There's a good reason why we saved the ACL above, even though
753 * we're about to read it back into memory and mess with it on the
754 * next line. The acl_copy_xattr() function is already a hack to let
755 * us copy default ACLs without resorting to path names; we simply
756 * have no way to read the parent's default ACL into memory using
757 * parent_fd. We can, however, copy the parent's ACL to a file (with
758 * acl_copy_xattr), and then read the ACL from a file using
759 * "fd". It's quite the circus, but it works and should be safe from
760 * sym/hardlink attacks.
761 */
762
763 /* Now we potentially need to mask the execute permissions in the
764 ACL on fd; or maybe not. */
765 if (allow_exec) {
766 /* Skip the mask code for this target, but don't skip its children! */
767 goto recurse;
768 }
769
770 /* OK, we need to mask some execute permissions. First obtain the
771 current ACL... */
772 new_acl = acl_get_fd(fd);
773 if (new_acl == (acl_t)NULL) {
774 perror("apply_default_acl_fds (acl_get_fd)");
775 result = ACL_ERROR;
776 goto cleanup;
777 }
778
779 /* ...and now make a copy of it, because otherwise when we loop
780 below, some shit gets stuck (modifying the structure while
781 looping over it no worky). */
782 new_acl_unmasked = acl_dup(new_acl);
783 if (new_acl_unmasked == (acl_t)NULL) {
784 perror("apply_default_acl_fds (acl_dup)");
785 result = ACL_ERROR;
786 goto cleanup;
787 }
788
789 acl_entry_t entry;
790 int ge_result = acl_get_entry(new_acl_unmasked, ACL_FIRST_ENTRY, &entry);
791
792 while (ge_result == ACL_SUCCESS) {
793 acl_tag_t tag = ACL_UNDEFINED_TAG;
794
795 if (acl_get_tag_type(entry, &tag) == ACL_ERROR) {
796 perror("apply_default_acl_fds (acl_get_tag_type)");
797 result = ACL_ERROR;
798 goto cleanup;
799 }
800
801
802 /* We've got an entry/tag from the default ACL. Get its permset. */
803 acl_permset_t permset;
804 if (acl_get_permset(entry, &permset) == ACL_ERROR) {
805 perror("apply_default_acl_fds (acl_get_permset)");
806 result = ACL_ERROR;
807 goto cleanup;
808 }
809
810 if (tag == ACL_MASK ||
811 tag == ACL_USER_OBJ ||
812 tag == ACL_GROUP_OBJ ||
813 tag == ACL_OTHER) {
814
815 /* The mask doesn't affect acl_user_obj, acl_group_obj (in
816 minimal ACLs) or acl_other entries, so if execute should be
817 masked, we have to do it manually. */
818 if (acl_delete_perm(permset, ACL_EXECUTE) == ACL_ERROR) {
819 perror("apply_default_acl_fds (acl_delete_perm)");
820 result = ACL_ERROR;
821 goto cleanup;
822 }
823
824 if (acl_set_permset(entry, permset) == ACL_ERROR) {
825 perror("apply_default_acl_fds (acl_set_permset)");
826 result = ACL_ERROR;
827 goto cleanup;
828 }
829 }
830
831 if (acl_update_entry(new_acl, entry) == ACL_ERROR) {
832 perror("apply_default_acl_fds (acl_update_entry)");
833 result = ACL_ERROR;
834 goto cleanup;
835 }
836
837 ge_result = acl_get_entry(new_acl_unmasked, ACL_NEXT_ENTRY, &entry);
838 }
839
840 /* Catches the first acl_get_entry as well as the ones at the end of
841 the loop. */
842 if (ge_result == ACL_ERROR) {
843 perror("apply_default_acl_fds (acl_get_entry)");
844 result = ACL_ERROR;
845 goto cleanup;
846 }
847
848 if (acl_set_fd(fd, new_acl) == ACL_ERROR) {
849 perror("apply_default_acl_fds (acl_set_fd)");
850 result = ACL_ERROR;
851 goto cleanup;
852 }
853
854 recurse:
855 if (recursive && S_ISDIR(s.st_mode)) {
856 /* Recurse into subdirectories. Don't call closedir() on d! It
857 closes the open file descriptor as well, and subsequent calls
858 to close() then throw errors. */
859 DIR* d = fdopendir(fd);
860 if (d == NULL) {
861 perror("apply_default_acl_fds (fdopendir)");
862 result = ACL_ERROR;
863 goto cleanup;
864 }
865
866 struct dirent* de;
867 int new_fd = 0;
868 while ((de = readdir(d)) != NULL) {
869 if (de->d_type != DT_DIR && de->d_type != DT_REG) {
870 /* Hit a symlink or whatever. */
871 result = ACL_FAILURE;
872 continue;
873 }
874 if (strcmp(de->d_name, ".") == 0) { continue; }
875 if (strcmp(de->d_name, "..") == 0) { continue; }
876
877 /* Be careful not to "return" out of this loop and leave the
878 new_fd open! */
879 new_fd = openat(fd, de->d_name, O_NOFOLLOW);
880 if (new_fd == OPEN_ERROR) {
881 if (errno == ELOOP || errno == ENOTDIR) {
882 /* We hit a symlink, either in the last path component (ELOOP)
883 or higher up (ENOTDIR). */
884 if (result == ACL_SUCCESS) {
885 /* Don't overwrite an error result with success/failure. */
886 result = ACL_FAILURE;
887 }
888 continue;
889 }
890 else {
891 perror("apply_default_acl_fds (openat)");
892 result = ACL_ERROR;
893 continue;
894 }
895 }
896 switch (apply_default_acl_fds(fd, new_fd, no_exec_mask, recursive)) {
897 /* Don't overwrite an error result with success/failure. */
898 case ACL_FAILURE:
899 if (result == ACL_SUCCESS) {
900 result = ACL_FAILURE;
901 }
902 case ACL_ERROR:
903 result = ACL_ERROR;
904 default:
905 if (close(new_fd) == CLOSE_ERROR) {
906 perror("apply_default_acl_fds (close)");
907 result = ACL_ERROR;
908 }
909 }
910 }
911 }
912
913 cleanup:
914 acl_free(new_acl);
915 acl_free(new_acl_unmasked);
916 return result;
917 }
918
919
920 /**
921 * @brief Apply parent default ACL to a path and optionally its children.
922 *
923 * This overwrites any existing ACLs on the target, and, if @c
924 * recursive is @c true, its children. When @c recursive is @c true,
925 * the "worst" result encountered is returned as the overall result.
926 *
927 * @param path
928 * The path whose ACL we would like to reset to its default.
929 *
930 * @param no_exec_mask
931 * The value (either true or false) of the --no-exec-mask flag.
932 *
933 * @param recursive
934 * Should we recurse into subdirectories?
935 *
936 * @return
937 * - @c ACL_SUCCESS - The parent default ACLs were inherited successfully.
938 * - @c ACL_FAILURE - If symlinks or hard links are encountered.
939 * - @c ACL_ERROR - Unexpected library error.
940 */
941 int apply_default_acl(const char* path, bool no_exec_mask, bool recursive) {
942
943 if (path == NULL) {
944 errno = EINVAL;
945 perror("apply_default_acl (args)");
946 return ACL_ERROR;
947 }
948
949 /* Define these next three variables here because we may have to
950 * jump to the cleanup routine which expects them to exist.
951 */
952
953 /* Our return value. */
954 int result = ACL_SUCCESS;
955
956 /* The file descriptor corresponding to "path" */
957 int fd = 0;
958
959 /* The file descriptor for the directory containing "path" */
960 int parent_fd = 0;
961
962 /* dirname() and basename() mangle their arguments, so we need
963 to make copies of "path" before using them. */
964 char* dirname_path_copy = NULL;
965 char* basename_path_copy = NULL;
966
967 /* Get the parent directory of "path" with dirname(), which happens
968 * to murder its argument and necessitates a path_copy. */
969 dirname_path_copy = strdup(path);
970 if (dirname_path_copy == NULL) {
971 perror("apply_default_acl (strdup)");
972 return ACL_ERROR;
973 }
974 char* parent = dirname(dirname_path_copy);
975 parent_fd = safe_open(parent, O_DIRECTORY | O_NOFOLLOW);
976 if (parent_fd == OPEN_ERROR) {
977 if (errno == ELOOP || errno == ENOTDIR) {
978 /* We hit a symlink, either in the last path component (ELOOP)
979 or higher up (ENOTDIR). */
980 result = ACL_FAILURE;
981 goto cleanup;
982 }
983 else {
984 perror("apply_default_acl (open parent fd)");
985 result = ACL_ERROR;
986 goto cleanup;
987 }
988 }
989
990 /* We already obtained the parent fd safely, so if we use the
991 basename of path here instead of the full thing, then we can get
992 away with using openat() and spare ourselves the slowness of
993 another safe_open(). */
994 basename_path_copy = strdup(path);
995 if (basename_path_copy == NULL) {
996 perror("apply_default_acl (strdup)");
997 return ACL_ERROR;
998 }
999 fd = openat(parent_fd, basename(basename_path_copy), O_NOFOLLOW);
1000 if (fd == OPEN_ERROR) {
1001 if (errno == ELOOP || errno == ENOTDIR) {
1002 /* We hit a symlink, either in the last path component (ELOOP)
1003 or higher up (ENOTDIR). */
1004 result = ACL_FAILURE;
1005 goto cleanup;
1006 }
1007 else {
1008 perror("apply_default_acl (open fd)");
1009 result = ACL_ERROR;
1010 goto cleanup;
1011 }
1012 }
1013
1014 result = apply_default_acl_fds(parent_fd, fd, no_exec_mask, recursive);
1015
1016 cleanup:
1017 free(dirname_path_copy);
1018 free(basename_path_copy);
1019
1020 if (parent_fd > 0 && close(parent_fd) == CLOSE_ERROR) {
1021 perror("apply_default_acl (close parent_fd)");
1022 result = ACL_ERROR;
1023 }
1024 if (fd > 0 && close(fd) == CLOSE_ERROR) {
1025 perror("apply_default_acl (close fd)");
1026 result = ACL_ERROR;
1027 }
1028 return result;
1029 }