4 * @brief The adacl (apply default acl) shared library.
8 /* Enables get_current_dir_name() in unistd.h, the O_PATH flag, and
9 * the asprintf() function.
13 #include <dirent.h> /* readdir(), etc. */
14 #include <errno.h> /* EINVAL, ELOOP, ENOTDIR, etc. */
15 #include <fcntl.h> /* openat() */
16 #include <libgen.h> /* basename(), dirname() */
17 #include <stdbool.h> /* the "bool" type */
18 #include <stdio.h> /* perror(), asprintf() */
19 #include <stdlib.h> /* free() */
20 #include <string.h> /* strdup() */
21 #include <sys/stat.h> /* fstat() */
22 #include <sys/xattr.h> /* fgetxattr(), fsetxattr() */
23 #include <unistd.h> /* get_current_dir_name() */
26 #include <acl/libacl.h> /* acl_get_perm, not portable */
27 #include <sys/acl.h> /* all other acl_foo functions */
29 /* XATTR_NAME_POSIX_ACL_ACCESS and XATTR_NAME_POSIX_ACL_DEFAULT */
30 #include <linux/xattr.h>
35 /* Even though most other library functions reliably return -1 for
36 * error, it feels a little wrong to re-use the ACL_ERROR constant.
38 #define CLOSE_ERROR -1
40 #define ASPRINTF_ERROR -1
42 #define XATTR_ERROR -1
46 int safe_open_ex(int at_fd
, char* pathname
, int flags
);
47 int safe_open(const char* pathname
, int flags
);
48 int acl_update_entry(acl_t aclp
, acl_entry_t entry
);
49 int acl_entry_count(acl_t acl
);
50 int acl_is_minimal(acl_t acl
);
51 int acl_execute_masked(acl_t acl
);
52 int any_can_execute(int fd
, const struct stat
* sp
);
53 int acl_copy_xattr(int src_fd
,
57 int has_default_acl_fd(int fd
);
58 int apply_default_acl_fds(int parent_fd
, int fd
, bool recursive
);
59 int apply_default_acl(const char* path
, bool recursive
);
64 * @brief The recursive portion of the @c safe_open function, used to
65 * open a file descriptor in a symlink-safe way when combined with
66 * the @c O_NOFOLLOW flag.
69 * A file descriptor relative to which @c pathname will be opened.
72 * The path to the file/directory/whatever whose descriptor you want.
75 * File status flags to be passed to @c openat.
77 * @return a file descriptor for @c pathname if everything goes well,
78 * and @c OPEN_ERROR if not.
80 int safe_open_ex(int at_fd
, char* pathname
, int flags
) {
81 if (pathname
== NULL
) {
83 perror("safe_open_ex (args)");
87 char* firstslash
= strchr(pathname
, '/');
88 if (firstslash
== NULL
) {
89 /* No more slashes, this is the base case. */
90 return openat(at_fd
, pathname
, flags
);
92 if (firstslash
[1] == '\0') {
93 /* The first slash is the last character; ensure that we open
96 return openat(at_fd
, pathname
, flags
| O_DIRECTORY
);
99 /* The first slash exists and isn't the last character in the path,
100 so we can split the path wherever that first slash lies and
103 int fd
= openat(at_fd
, pathname
, flags
| O_DIRECTORY
| O_PATH
);
104 if (fd
== OPEN_ERROR
) {
105 if (errno
!= ENOTDIR
) {
106 /* Don't output anything if we ignore a symlink */
107 perror("safe_open_ex (safe_open_ex)");
112 /* The +1 is safe because there needs to be at least one character
113 after the first slash (we checked this above). */
114 int result
= safe_open_ex(fd
, firstslash
+1, flags
);
115 if (close(fd
) == CLOSE_ERROR
) {
116 perror("safe_open_ex (close)");
124 * @brief A version of @c open that is completely symlink-safe when
125 * used with the @c O_NOFOLLOW flag.
127 * The @c openat function exists to ensure that you can anchor one
128 * path to a particular directory while opening it; however, if you
129 * open "b/c/d" relative to "/a", then even the @c openat function will
130 * still follow symlinks in the "b" component. This can be exploited
131 * by an attacker to make you open the wrong path.
133 * To avoid that problem, this function uses a recursive
134 * implementation that opens every path from the root, one level at a
135 * time. So "a" is opened relative to "/", and then "b" is opened
136 * relative to "/a", and then "c" is opened relative to "/a/b",
137 * etc. When the @c O_NOFOLLOW flag is used, this approach ensures
138 * that no symlinks in any component are followed.
141 * The path to the file/directory/whatever whose descriptor you want.
144 * File status flags to be passed to @c openat.
146 * @return a file descriptor for @c pathname if everything goes well,
147 * and @c OPEN_ERROR if not.
149 int safe_open(const char* pathname
, int flags
) {
150 if (pathname
== NULL
) {
152 perror("safe_open (args)");
156 char* abspath
= NULL
;
157 int asprintf_result
= 0;
158 if (strchr(pathname
, '/') == pathname
) {
159 /* pathname is already absolute; just copy it. */
160 asprintf_result
= asprintf(&abspath
, "%s", pathname
);
163 /* Concatenate the current working directory and pathname into an
164 * absolute path. We use realpath() ONLY on the cwd part, and not
165 * on the pathname part, because realpath() resolves symlinks. And
166 * the whole point of all this crap is to avoid following symlinks
169 * Using realpath() on the cwd lets us operate on relative paths
170 * while we're sitting in a directory that happens to have a
171 * symlink in it; for example: cd /var/run && apply-default-acl foo.
173 char* cwd
= get_current_dir_name();
175 perror("safe_open (get_current_dir_name)");
179 char abs_cwd
[PATH_MAX
];
180 if (realpath(cwd
, abs_cwd
) == NULL
) {
181 perror("safe_open (realpath)");
185 asprintf_result
= asprintf(&abspath
, "%s/%s", abs_cwd
, pathname
);
188 if (asprintf_result
== ASPRINTF_ERROR
) {
189 perror("safe_open (asprintf)");
193 /* Beyond here, asprintf() worked, and we need to free abspath. */
194 int result
= OPEN_ERROR
;
196 bool abspath_is_root
= (strcmp(abspath
, "/") == 0);
197 int rootflags
= flags
| O_DIRECTORY
;
198 if (!abspath_is_root
) {
199 /* Use O_PATH for some added safety if "/" is not our target */
202 int rootfd
= open("/", rootflags
);
203 if (rootfd
== OPEN_ERROR
) {
204 perror("safe_open (open)");
209 if (abspath_is_root
) {
214 result
= safe_open_ex(rootfd
, abspath
+1, flags
);
215 if (close(rootfd
) == CLOSE_ERROR
) {
216 perror("safe_open (close)");
230 * @brief Update an entry in an @b minimal ACL.
233 * A pointer to the acl_t structure whose entry we want to update.
239 * - @c ACL_SUCCESS - If we update an existing entry.
240 * - @c ACL_FAILURE - If we don't find an entry to update.
241 * - @c ACL_ERROR - Unexpected library error.
243 int acl_update_entry(acl_t aclp
, acl_entry_t entry
) {
244 if (aclp
== NULL
|| entry
== NULL
) {
246 perror("acl_update_entry (args)");
251 if (acl_get_tag_type(entry
, &entry_tag
) == ACL_ERROR
) {
252 perror("acl_update_entry (acl_get_tag_type)");
256 acl_permset_t entry_permset
;
257 if (acl_get_permset(entry
, &entry_permset
) == ACL_ERROR
) {
258 perror("acl_update_entry (acl_get_permset)");
262 acl_entry_t existing_entry
;
263 /* Loop through the given ACL looking for matching entries. */
264 int result
= acl_get_entry(aclp
, ACL_FIRST_ENTRY
, &existing_entry
);
266 while (result
== ACL_SUCCESS
) {
267 acl_tag_t existing_tag
= ACL_UNDEFINED_TAG
;
269 if (acl_get_tag_type(existing_entry
, &existing_tag
) == ACL_ERROR
) {
270 perror("set_acl_tag_permset (acl_get_tag_type)");
274 if (existing_tag
== entry_tag
) {
275 /* If we update something, we're done and return ACL_SUCCESS */
276 if (acl_set_permset(existing_entry
, entry_permset
) == ACL_ERROR
) {
277 perror("acl_update_entry (acl_set_permset)");
284 result
= acl_get_entry(aclp
, ACL_NEXT_ENTRY
, &existing_entry
);
287 /* This catches both the initial acl_get_entry and the ones at the
289 if (result
== ACL_ERROR
) {
290 perror("acl_update_entry (acl_get_entry)");
300 * @brief Determine the number of entries in the given ACL.
303 * The ACL to inspect.
305 * @return Either the non-negative number of entries in @c acl, or
306 * @c ACL_ERROR on error.
308 int acl_entry_count(acl_t acl
) {
312 int result
= acl_get_entry(acl
, ACL_FIRST_ENTRY
, &entry
);
314 while (result
== ACL_SUCCESS
) {
316 result
= acl_get_entry(acl
, ACL_NEXT_ENTRY
, &entry
);
319 if (result
== ACL_ERROR
) {
320 perror("acl_entry_count (acl_get_entry)");
330 * @brief Determine whether or not the given ACL is minimal.
332 * An ACL is minimal if it has fewer than four entries.
335 * The ACL whose minimality is in question.
338 * - @c ACL_SUCCESS - @c acl is minimal
339 * - @c ACL_FAILURE - @c acl is not minimal
340 * - @c ACL_ERROR - Unexpected library error
342 int acl_is_minimal(acl_t acl
) {
345 perror("acl_is_minimal (args)");
349 int ec
= acl_entry_count(acl
);
351 if (ec
== ACL_ERROR
) {
352 perror("acl_is_minimal (acl_entry_count)");
367 * @brief Determine whether the given ACL's mask denies execute.
370 * The ACL whose mask we want to check.
373 * - @c ACL_SUCCESS - The @c acl has a mask which denies execute.
374 * - @c ACL_FAILURE - The @c acl has a mask which does not deny execute.
375 * - @c ACL_ERROR - Unexpected library error.
377 int acl_execute_masked(acl_t acl
) {
380 perror("acl_execute_masked (args)");
385 int ge_result
= acl_get_entry(acl
, ACL_FIRST_ENTRY
, &entry
);
387 while (ge_result
== ACL_SUCCESS
) {
388 acl_tag_t tag
= ACL_UNDEFINED_TAG
;
390 if (acl_get_tag_type(entry
, &tag
) == ACL_ERROR
) {
391 perror("acl_execute_masked (acl_get_tag_type)");
395 if (tag
== ACL_MASK
) {
396 /* This is the mask entry, get its permissions, and see if
397 execute is specified. */
398 acl_permset_t permset
;
400 if (acl_get_permset(entry
, &permset
) == ACL_ERROR
) {
401 perror("acl_execute_masked (acl_get_permset)");
405 int gp_result
= acl_get_perm(permset
, ACL_EXECUTE
);
406 if (gp_result
== ACL_ERROR
) {
407 perror("acl_execute_masked (acl_get_perm)");
411 if (gp_result
== ACL_FAILURE
) {
412 /* No execute bit set in the mask; execute not allowed. */
417 ge_result
= acl_get_entry(acl
, ACL_NEXT_ENTRY
, &entry
);
426 * @brief Determine whether @c fd is executable by anyone.
429 * This is used as part of the heuristic to determine whether or not
430 * we should mask the execute bit when inheriting an ACL. If @c fd
431 * describes a file, we check the @a effective permissions, contrary
432 * to what setfacl does.
435 * The file descriptor to check.
438 * A pointer to a stat structure for @c fd.
441 * - @c ACL_SUCCESS - Someone has effective execute permissions on @c fd.
442 * - @c ACL_FAILURE - Nobody can execute @c fd.
443 * - @c ACL_ERROR - Unexpected library error.
445 int any_can_execute(int fd
, const struct stat
* sp
) {
448 perror("any_can_execute (args)");
452 acl_t acl
= acl_get_fd(fd
);
454 if (acl
== (acl_t
)NULL
) {
455 perror("any_can_execute (acl_get_fd)");
459 /* Our return value. */
460 int result
= ACL_FAILURE
;
462 if (acl_is_minimal(acl
)) {
463 if (sp
->st_mode
& (S_IXUSR
| S_IXOTH
| S_IXGRP
)) {
464 result
= ACL_SUCCESS
;
468 result
= ACL_FAILURE
;
474 int ge_result
= acl_get_entry(acl
, ACL_FIRST_ENTRY
, &entry
);
476 while (ge_result
== ACL_SUCCESS
) {
477 /* The first thing we do is check to see if this is a mask
478 entry. If it is, we skip it entirely. */
479 acl_tag_t tag
= ACL_UNDEFINED_TAG
;
481 if (acl_get_tag_type(entry
, &tag
) == ACL_ERROR
) {
482 perror("any_can_execute_or (acl_get_tag_type)");
487 if (tag
== ACL_MASK
) {
488 ge_result
= acl_get_entry(acl
, ACL_NEXT_ENTRY
, &entry
);
492 /* Ok, so it's not a mask entry. Check the execute perms. */
493 acl_permset_t permset
;
495 if (acl_get_permset(entry
, &permset
) == ACL_ERROR
) {
496 perror("any_can_execute_or (acl_get_permset)");
501 int gp_result
= acl_get_perm(permset
, ACL_EXECUTE
);
502 if (gp_result
== ACL_ERROR
) {
503 perror("any_can_execute (acl_get_perm)");
508 if (gp_result
== ACL_SUCCESS
) {
509 /* Only return ACL_SUCCESS if this execute bit is not masked. */
510 if (acl_execute_masked(acl
) != ACL_SUCCESS
) {
511 result
= ACL_SUCCESS
;
516 ge_result
= acl_get_entry(acl
, ACL_NEXT_ENTRY
, &entry
);
519 if (ge_result
== ACL_ERROR
) {
520 perror("any_can_execute (acl_get_entry)");
533 * @brief Copy ACLs between file descriptors as xattrs, verbatim.
535 * There is a small deficiency in libacl, namely that there is no way
536 * to get or set default ACLs through file descriptors. The @c
537 * acl_get_file and @c acl_set_file functions can do it, but they use
538 * paths, and are vulnerable to symlink attacks.
540 * Fortunately, when inheriting an ACL, we don't really need to look
541 * at what it contains. That means that we can copy the on-disk xattrs
542 * from the source directory to the destination file/directory without
543 * passing through libacl, and this can be done with file descriptors
544 * through @c fgetxattr and @c fsetxattr. That's what this function
548 * The file descriptor from which the ACL will be copied.
551 * The type of ACL (either @c ACL_TYPE_ACCESS or @c ACL_TYPE_DEFAULT)
552 * to copy from @c src_fd.
555 * The file descriptor whose ACL will be overwritten with the one
559 * The type of ACL (either @c ACL_TYPE_ACCESS or @c ACL_TYPE_DEFAULT)
560 * to replace on @c dst_fd.
563 * - @c ACL_SUCCESS - The ACL was copied successfully.
564 * - @c ACL_FAILURE - There was no ACL on @c src_fd.
565 * - @c ACL_ERROR - Unexpected library error.
567 int acl_copy_xattr(int src_fd
,
570 acl_type_t dst_type
) {
572 const char* src_name
;
573 if (src_type
== ACL_TYPE_ACCESS
) {
574 src_name
= XATTR_NAME_POSIX_ACL_ACCESS
;
576 else if (src_type
== ACL_TYPE_DEFAULT
) {
577 src_name
= XATTR_NAME_POSIX_ACL_DEFAULT
;
581 perror("acl_copy_xattr (src type)");
585 const char* dst_name
;
586 if (dst_type
== ACL_TYPE_ACCESS
) {
587 dst_name
= XATTR_NAME_POSIX_ACL_ACCESS
;
589 else if (dst_type
== ACL_TYPE_DEFAULT
) {
590 dst_name
= XATTR_NAME_POSIX_ACL_DEFAULT
;
594 perror("acl_copy_xattr (dst type)");
598 ssize_t src_size_guess
= fgetxattr(src_fd
, src_name
, NULL
, 0);
599 if (src_size_guess
== XATTR_ERROR
) {
600 if (errno
== ENODATA
) {
601 /* A missing ACL isn't really an error. ENOATTR and ENODATA are
602 synonyms, but using ENODATA here lets us avoid another
603 "include" directive. */
606 perror("acl_copy_xattr (fgetxattr size guess)");
609 char* src_acl_p
= alloca(src_size_guess
);
610 /* The actual size may be smaller than our guess? I don't know. The
611 return value from fgetxattr() will either be nonnegative, or
612 XATTR_ERROR (which we've already ruled out), so it's safe to cast
613 it to an unsigned size_t here to avoid a compiler warning. */
614 ssize_t src_size
= fgetxattr(src_fd
,
617 (size_t)src_size_guess
);
618 if (src_size
== XATTR_ERROR
) {
619 if (errno
== ENODATA
) {
620 /* A missing ACL isn't an error. */
623 perror("acl_copy_xattr (fgetxattr)");
627 /* See above: src_size must be nonnegative at this point,so we cast
628 it to size_t to avoid a compiler warning. */
629 if (fsetxattr(dst_fd
,
635 perror("acl_copy_xattr (fsetxattr)");
644 * @brief Determine if a file descriptor has a default ACL.
647 * The file descriptor whose default ACL is in question.
650 * - @c ACL_SUCCESS - If @c fd has a default ACL.
651 * - @c ACL_FAILURE - If @c fd does not have a default ACL.
652 * - @c ACL_ERROR - Unexpected library error.
654 int has_default_acl_fd(int fd
) {
655 if (fgetxattr(fd
, XATTR_NAME_POSIX_ACL_DEFAULT
, NULL
, 0) == XATTR_ERROR
) {
656 if (errno
== ENODATA
) {
659 perror("has_default_acl_fd (fgetxattr)");
669 * @brief The recursive portion of @c apply_default_acl.
671 * The @c apply_default_acl function takes a path, but then opens file
672 * descriptors for the path and its parent. Afterwards, everything is
673 * done using file descriptors, including the recursive application on
674 * the path's children. This function encapsulates the portion of @c
675 * apply_default_acl that uses only file descriptors; for the
676 * recursion, this function ultimately calls itself.
678 * This overwrites any existing ACLs on @c fd and, if @c recursive is
679 * @c true, its children. When @c recursive is @c true, the "worst"
680 * result encountered is returned as the overall result.
683 * A file descriptor for the parent directory of @c fd.
686 * The file descriptor that should inherit its parent's default ACL.
689 * Should we recurse into subdirectories?
692 * - @c ACL_SUCCESS - The parent default ACLs were inherited successfully.
693 * - @c ACL_FAILURE - If symlinks or hard links are encountered.
694 * - @c ACL_ERROR - Unexpected library error.
696 int apply_default_acl_fds(int parent_fd
, int fd
, bool recursive
) {
697 int result
= ACL_SUCCESS
;
699 /* The new ACL for this path */
700 acl_t new_acl
= (acl_t
)NULL
;
702 /* A copy of new_acl, to be made before we begin mangling new_acl in
703 order to mask the execute bit. */
704 acl_t new_acl_unmasked
= (acl_t
)NULL
;
706 /* Refuse to operate on hard links, which can be abused by an
707 * attacker to trick us into changing the ACL on a file we didn't
708 * intend to; namely the "target" of the hard link. There is TOCTOU
709 * race condition here, but the window is as small as possible
710 * between when we open the file descriptor (look above) and when we
714 if (fstat(fd
, &s
) == STAT_ERROR
) {
715 perror("apply_default_acl_fds (fstat)");
716 /* We can't recurse without the stat struct for fd */
721 /* Check to make sure the parent descriptor actually has a default
722 ACL. If it doesn't, then we can "succeed" immediately, saving a
723 little work, particularly in any_can_execute(). Note that we
724 can't skip the fstat() above, because we need it in case we
726 if (has_default_acl_fd(parent_fd
) == ACL_FAILURE
) {
727 result
= ACL_SUCCESS
;
728 /* Just because this target can't inherit anything doesn't mean
729 that one of it's children can't. For example, if there's a
730 default on "c" in "a/b/c/d", then we don't want to skip all
736 if (!S_ISDIR(s
.st_mode
)) {
737 /* If it's not a directory, make sure it's a regular,
738 non-hard-linked file. */
739 if (!S_ISREG(s
.st_mode
) || s
.st_nlink
!= 1) {
740 result
= ACL_FAILURE
;
741 goto cleanup
; /* It's not a directory, so we can skip the recursion. */
746 /* Next We try to guess whether or not to strip the execute bits.
747 * This behavior is modeled after the capital 'X' perms of setfacl.
749 int ace_result
= any_can_execute(fd
, &s
);
751 if (ace_result
== ACL_ERROR
) {
752 perror("apply_default_acl_fds (any_can_execute)");
757 /* Never mask the execute bit on directories. */
758 bool allow_exec
= (bool)ace_result
|| S_ISDIR(s
.st_mode
);
761 /* If it's a directory, inherit the parent's default. */
762 if (S_ISDIR(s
.st_mode
)) {
763 if (acl_copy_xattr(parent_fd
,
766 ACL_TYPE_DEFAULT
) == ACL_ERROR
) {
767 perror("apply_default_acl_fds (acl_copy_xattr default)");
773 /* If it's anything, _apply_ the parent's default. */
774 if (acl_copy_xattr(parent_fd
,
777 ACL_TYPE_ACCESS
) == ACL_ERROR
) {
778 perror("apply_default_acl_fds (acl_copy_xattr access)");
783 /* There's a good reason why we saved the ACL above, even though
784 * we're about to read it back into memory and mess with it on the
785 * next line. The acl_copy_xattr() function is already a hack to let
786 * us copy default ACLs without resorting to path names; we simply
787 * have no way to read the parent's default ACL into memory using
788 * parent_fd. We can, however, copy the parent's ACL to a file (with
789 * acl_copy_xattr), and then read the ACL from a file using
790 * "fd". It's quite the circus, but it works and should be safe from
791 * sym/hardlink attacks.
794 /* Now we potentially need to mask the execute permissions in the
795 ACL on fd; or maybe not. */
797 /* Skip the mask code for this target, but don't skip its children! */
801 /* OK, we need to mask some execute permissions. First obtain the
803 new_acl
= acl_get_fd(fd
);
804 if (new_acl
== (acl_t
)NULL
) {
805 perror("apply_default_acl_fds (acl_get_fd)");
810 /* ...and now make a copy of it, because otherwise when we loop
811 below, some shit gets stuck (modifying the structure while
812 looping over it no worky). */
813 new_acl_unmasked
= acl_dup(new_acl
);
814 if (new_acl_unmasked
== (acl_t
)NULL
) {
815 perror("apply_default_acl_fds (acl_dup)");
821 int ge_result
= acl_get_entry(new_acl_unmasked
, ACL_FIRST_ENTRY
, &entry
);
823 while (ge_result
== ACL_SUCCESS
) {
824 acl_tag_t tag
= ACL_UNDEFINED_TAG
;
826 if (acl_get_tag_type(entry
, &tag
) == ACL_ERROR
) {
827 perror("apply_default_acl_fds (acl_get_tag_type)");
833 /* We've got an entry/tag from the default ACL. Get its permset. */
834 acl_permset_t permset
;
835 if (acl_get_permset(entry
, &permset
) == ACL_ERROR
) {
836 perror("apply_default_acl_fds (acl_get_permset)");
841 /* To mimic what the kernel does, I think we could drop
842 ACL_GROUP_OBJ from the list below? */
843 if (tag
== ACL_MASK
||
844 tag
== ACL_USER_OBJ
||
845 tag
== ACL_GROUP_OBJ
||
848 /* The mask doesn't affect acl_user_obj, acl_group_obj (in
849 minimal ACLs) or acl_other entries, so if execute should be
850 masked, we have to do it manually. */
851 if (acl_delete_perm(permset
, ACL_EXECUTE
) == ACL_ERROR
) {
852 perror("apply_default_acl_fds (acl_delete_perm)");
857 if (acl_set_permset(entry
, permset
) == ACL_ERROR
) {
858 perror("apply_default_acl_fds (acl_set_permset)");
864 if (acl_update_entry(new_acl
, entry
) == ACL_ERROR
) {
865 perror("apply_default_acl_fds (acl_update_entry)");
870 ge_result
= acl_get_entry(new_acl_unmasked
, ACL_NEXT_ENTRY
, &entry
);
873 /* Catches the first acl_get_entry as well as the ones at the end of
875 if (ge_result
== ACL_ERROR
) {
876 perror("apply_default_acl_fds (acl_get_entry)");
881 if (acl_set_fd(fd
, new_acl
) == ACL_ERROR
) {
882 perror("apply_default_acl_fds (acl_set_fd)");
888 if (recursive
&& S_ISDIR(s
.st_mode
)) {
889 /* Recurse into subdirectories. Don't call closedir() on d! It
890 closes the open file descriptor as well, and subsequent calls
891 to close() then throw errors. */
892 DIR* d
= fdopendir(fd
);
894 perror("apply_default_acl_fds (fdopendir)");
901 while ((de
= readdir(d
)) != NULL
) {
902 if (de
->d_type
!= DT_DIR
&& de
->d_type
!= DT_REG
) {
903 /* Hit a symlink or whatever. */
904 result
= ACL_FAILURE
;
907 if (strcmp(de
->d_name
, ".") == 0) { continue; }
908 if (strcmp(de
->d_name
, "..") == 0) { continue; }
910 /* Be careful not to "return" out of this loop and leave the
912 new_fd
= openat(fd
, de
->d_name
, O_NOFOLLOW
);
913 if (new_fd
== OPEN_ERROR
) {
914 if (errno
== ELOOP
|| errno
== ENOTDIR
) {
915 /* We hit a symlink, either in the last path component (ELOOP)
916 or higher up (ENOTDIR). */
917 if (result
== ACL_SUCCESS
) {
918 /* Don't overwrite an error result with success/failure. */
919 result
= ACL_FAILURE
;
924 perror("apply_default_acl_fds (openat)");
929 switch (apply_default_acl_fds(fd
, new_fd
, recursive
)) {
930 /* Don't overwrite an error result with success/failure. */
932 if (result
== ACL_SUCCESS
) {
933 result
= ACL_FAILURE
;
939 if (close(new_fd
) == CLOSE_ERROR
) {
940 perror("apply_default_acl_fds (close)");
949 acl_free(new_acl_unmasked
);
955 * @brief Apply parent default ACL to a path and optionally its children.
957 * This overwrites any existing ACLs on the target, and, if @c
958 * recursive is @c true, its children. When @c recursive is @c true,
959 * the "worst" result encountered is returned as the overall result.
962 * The path whose ACL we would like to reset to its default.
965 * Should we recurse into subdirectories?
968 * - @c ACL_SUCCESS - The parent default ACLs were inherited successfully.
969 * - @c ACL_FAILURE - If symlinks or hard links are encountered.
970 * - @c ACL_ERROR - Unexpected library error.
972 int apply_default_acl(const char* path
, bool recursive
) {
976 perror("apply_default_acl (args)");
980 /* Define these next three variables here because we may have to
981 * jump to the cleanup routine which expects them to exist.
984 /* Our return value. */
985 int result
= ACL_SUCCESS
;
987 /* The file descriptor corresponding to "path" */
990 /* The file descriptor for the directory containing "path" */
993 /* dirname() and basename() mangle their arguments, so we need
994 to make copies of "path" before using them. */
995 char* dirname_path_copy
= NULL
;
996 char* basename_path_copy
= NULL
;
998 /* Get the parent directory of "path" with dirname(), which happens
999 * to murder its argument and necessitates a path_copy. */
1000 dirname_path_copy
= strdup(path
);
1001 if (dirname_path_copy
== NULL
) {
1002 perror("apply_default_acl (strdup)");
1005 char* parent
= dirname(dirname_path_copy
);
1007 /* Just kidding, if the path is "." or "..", then dirname will do
1008 * the wrong thing and give us "." as its parent, too. So, we handle
1009 * those as special cases.
1011 bool path_is_dots
= strcmp(path
, ".") == 0 || strcmp(path
, "..") == 0;
1012 char dots_parent
[6] = "../";
1014 parent
= strcat(dots_parent
, path
);
1017 parent_fd
= safe_open(parent
, O_DIRECTORY
| O_NOFOLLOW
);
1019 if (parent_fd
== OPEN_ERROR
) {
1020 if (errno
== ELOOP
|| errno
== ENOTDIR
) {
1021 /* We hit a symlink, either in the last path component (ELOOP)
1022 or higher up (ENOTDIR). */
1023 result
= ACL_FAILURE
;
1027 perror("apply_default_acl (open parent fd)");
1033 /* We already obtained the parent fd safely, so if we use the
1034 basename of path here instead of the full thing, then we can get
1035 away with using openat() and spare ourselves the slowness of
1036 another safe_open(). */
1037 basename_path_copy
= strdup(path
);
1038 if (basename_path_copy
== NULL
) {
1039 perror("apply_default_acl (strdup)");
1044 /* If the basename is "." or "..", then we don't want to open it
1045 relative to the parent_fd, so we need another special case for
1048 fd
= open(path
, O_NOFOLLOW
);
1051 fd
= openat(parent_fd
, basename(basename_path_copy
), O_NOFOLLOW
);
1053 if (fd
== OPEN_ERROR
) {
1054 if (errno
== ELOOP
|| errno
== ENOTDIR
) {
1055 /* We hit a symlink, either in the last path component (ELOOP)
1056 or higher up (ENOTDIR). */
1057 result
= ACL_FAILURE
;
1061 perror("apply_default_acl (open fd)");
1067 result
= apply_default_acl_fds(parent_fd
, fd
, recursive
);
1070 free(dirname_path_copy
);
1071 free(basename_path_copy
);
1073 if (parent_fd
> 0 && close(parent_fd
) == CLOSE_ERROR
) {
1074 perror("apply_default_acl (close parent_fd)");
1077 if (fd
> 0 && close(fd
) == CLOSE_ERROR
) {
1078 perror("apply_default_acl (close fd)");