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 * @brief The recursive portion of the @c safe_open function, used to
47 * open a file descriptor in a symlink-safe way when combined with
48 * the @c O_NOFOLLOW flag.
51 * A file descriptor relative to which @c pathname will be opened.
54 * The path to the file/directory/whatever whose descriptor you want.
57 * File status flags to be passed to @c openat.
59 * @return a file descriptor for @c pathname if everything goes well,
60 * and @c OPEN_ERROR if not.
62 int safe_open_ex(int at_fd
, char* pathname
, int flags
) {
63 if (pathname
== NULL
) {
65 perror("safe_open_ex (args)");
69 char* firstslash
= strchr(pathname
, '/');
70 if (firstslash
== NULL
) {
71 /* No more slashes, this is the base case. */
72 return openat(at_fd
, pathname
, flags
);
74 if (firstslash
[1] == '\0') {
75 /* The first slash is the last character; ensure that we open
78 return openat(at_fd
, pathname
, flags
| O_DIRECTORY
);
81 /* The first slash exists and isn't the last character in the path,
82 so we can split the path wherever that first slash lies and
85 int fd
= openat(at_fd
, pathname
, flags
| O_DIRECTORY
| O_PATH
);
86 if (fd
== OPEN_ERROR
) {
87 if (errno
!= ENOTDIR
) {
88 /* Don't output anything if we ignore a symlink */
89 perror("safe_open_ex (safe_open_ex)");
94 /* The +1 is safe because there needs to be at least one character
95 after the first slash (we checked this above). */
96 int result
= safe_open_ex(fd
, firstslash
+1, flags
);
97 if (close(fd
) == CLOSE_ERROR
) {
98 perror("safe_open_ex (close)");
106 * @brief A version of @c open that is completely symlink-safe when
107 * used with the @c O_NOFOLLOW flag.
109 * The @c openat function exists to ensure that you can anchor one
110 * path to a particular directory while opening it; however, if you
111 * open "b/c/d" relative to "/a", then even the @c openat function will
112 * still follow symlinks in the "b" component. This can be exploited
113 * by an attacker to make you open the wrong path.
115 * To avoid that problem, this function uses a recursive
116 * implementation that opens every path from the root, one level at a
117 * time. So "a" is opened relative to "/", and then "b" is opened
118 * relative to "/a", and then "c" is opened relative to "/a/b",
119 * etc. When the @c O_NOFOLLOW flag is used, this approach ensures
120 * that no symlinks in any component are followed.
123 * The path to the file/directory/whatever whose descriptor you want.
126 * File status flags to be passed to @c openat.
128 * @return a file descriptor for @c pathname if everything goes well,
129 * and @c OPEN_ERROR if not.
131 int safe_open(const char* pathname
, int flags
) {
132 if (pathname
== NULL
) {
134 perror("safe_open (args)");
138 char* abspath
= NULL
;
139 int asprintf_result
= 0;
140 if (strchr(pathname
, '/') == pathname
) {
141 /* pathname is already absolute; just copy it. */
142 asprintf_result
= asprintf(&abspath
, "%s", pathname
);
145 /* Concatenate the current working directory and pathname into an
146 * absolute path. We use realpath() ONLY on the cwd part, and not
147 * on the pathname part, because realpath() resolves symlinks. And
148 * the whole point of all this crap is to avoid following symlinks
151 * Using realpath() on the cwd lets us operate on relative paths
152 * while we're sitting in a directory that happens to have a
153 * symlink in it; for example: cd /var/run && apply-default-acl foo.
155 char* cwd
= get_current_dir_name();
157 perror("safe_open (get_current_dir_name)");
161 char abs_cwd
[PATH_MAX
];
162 if (realpath(cwd
, abs_cwd
) == NULL
) {
163 perror("safe_open (realpath)");
167 asprintf_result
= asprintf(&abspath
, "%s/%s", abs_cwd
, pathname
);
170 if (asprintf_result
== ASPRINTF_ERROR
) {
171 perror("safe_open (asprintf)");
175 /* Beyond here, asprintf() worked, and we need to free abspath. */
176 int result
= OPEN_ERROR
;
178 bool abspath_is_root
= (strcmp(abspath
, "/") == 0);
179 int rootflags
= flags
| O_DIRECTORY
;
180 if (!abspath_is_root
) {
181 /* Use O_PATH for some added safety if "/" is not our target */
184 int rootfd
= open("/", rootflags
);
185 if (rootfd
== OPEN_ERROR
) {
186 perror("safe_open (open)");
191 if (abspath_is_root
) {
196 result
= safe_open_ex(rootfd
, abspath
+1, flags
);
197 if (close(rootfd
) == CLOSE_ERROR
) {
198 perror("safe_open (close)");
212 * @brief Update an entry in an @b minimal ACL.
215 * A pointer to the acl_t structure whose entry we want to update.
221 * - @c ACL_SUCCESS - If we update an existing entry.
222 * - @c ACL_FAILURE - If we don't find an entry to update.
223 * - @c ACL_ERROR - Unexpected library error.
225 int acl_update_entry(acl_t aclp
, acl_entry_t entry
) {
226 if (aclp
== NULL
|| entry
== NULL
) {
228 perror("acl_update_entry (args)");
233 if (acl_get_tag_type(entry
, &entry_tag
) == ACL_ERROR
) {
234 perror("acl_update_entry (acl_get_tag_type)");
238 acl_permset_t entry_permset
;
239 if (acl_get_permset(entry
, &entry_permset
) == ACL_ERROR
) {
240 perror("acl_update_entry (acl_get_permset)");
244 acl_entry_t existing_entry
;
245 /* Loop through the given ACL looking for matching entries. */
246 int result
= acl_get_entry(aclp
, ACL_FIRST_ENTRY
, &existing_entry
);
248 while (result
== ACL_SUCCESS
) {
249 acl_tag_t existing_tag
= ACL_UNDEFINED_TAG
;
251 if (acl_get_tag_type(existing_entry
, &existing_tag
) == ACL_ERROR
) {
252 perror("set_acl_tag_permset (acl_get_tag_type)");
256 if (existing_tag
== entry_tag
) {
257 /* If we update something, we're done and return ACL_SUCCESS */
258 if (acl_set_permset(existing_entry
, entry_permset
) == ACL_ERROR
) {
259 perror("acl_update_entry (acl_set_permset)");
266 result
= acl_get_entry(aclp
, ACL_NEXT_ENTRY
, &existing_entry
);
269 /* This catches both the initial acl_get_entry and the ones at the
271 if (result
== ACL_ERROR
) {
272 perror("acl_update_entry (acl_get_entry)");
282 * @brief Determine the number of entries in the given ACL.
285 * The ACL to inspect.
287 * @return Either the non-negative number of entries in @c acl, or
288 * @c ACL_ERROR on error.
290 int acl_entry_count(acl_t acl
) {
294 int result
= acl_get_entry(acl
, ACL_FIRST_ENTRY
, &entry
);
296 while (result
== ACL_SUCCESS
) {
298 result
= acl_get_entry(acl
, ACL_NEXT_ENTRY
, &entry
);
301 if (result
== ACL_ERROR
) {
302 perror("acl_entry_count (acl_get_entry)");
312 * @brief Determine whether or not the given ACL is minimal.
314 * An ACL is minimal if it has fewer than four entries.
317 * The ACL whose minimality is in question.
320 * - @c ACL_SUCCESS - @c acl is minimal
321 * - @c ACL_FAILURE - @c acl is not minimal
322 * - @c ACL_ERROR - Unexpected library error
324 int acl_is_minimal(acl_t acl
) {
327 perror("acl_is_minimal (args)");
331 int ec
= acl_entry_count(acl
);
333 if (ec
== ACL_ERROR
) {
334 perror("acl_is_minimal (acl_entry_count)");
349 * @brief Determine whether the given ACL's mask denies execute.
352 * The ACL whose mask we want to check.
355 * - @c ACL_SUCCESS - The @c acl has a mask which denies execute.
356 * - @c ACL_FAILURE - The @c acl has a mask which does not deny execute.
357 * - @c ACL_ERROR - Unexpected library error.
359 int acl_execute_masked(acl_t acl
) {
362 perror("acl_execute_masked (args)");
367 int ge_result
= acl_get_entry(acl
, ACL_FIRST_ENTRY
, &entry
);
369 while (ge_result
== ACL_SUCCESS
) {
370 acl_tag_t tag
= ACL_UNDEFINED_TAG
;
372 if (acl_get_tag_type(entry
, &tag
) == ACL_ERROR
) {
373 perror("acl_execute_masked (acl_get_tag_type)");
377 if (tag
== ACL_MASK
) {
378 /* This is the mask entry, get its permissions, and see if
379 execute is specified. */
380 acl_permset_t permset
;
382 if (acl_get_permset(entry
, &permset
) == ACL_ERROR
) {
383 perror("acl_execute_masked (acl_get_permset)");
387 int gp_result
= acl_get_perm(permset
, ACL_EXECUTE
);
388 if (gp_result
== ACL_ERROR
) {
389 perror("acl_execute_masked (acl_get_perm)");
393 if (gp_result
== ACL_FAILURE
) {
394 /* No execute bit set in the mask; execute not allowed. */
399 ge_result
= acl_get_entry(acl
, ACL_NEXT_ENTRY
, &entry
);
408 * @brief Determine whether @c fd is executable by anyone.
411 * This is used as part of the heuristic to determine whether or not
412 * we should mask the execute bit when inheriting an ACL. If @c fd
413 * describes a file, we check the @a effective permissions, contrary
414 * to what setfacl does.
417 * The file descriptor to check.
420 * A pointer to a stat structure for @c fd.
423 * - @c ACL_SUCCESS - Someone has effective execute permissions on @c fd.
424 * - @c ACL_FAILURE - Nobody can execute @c fd.
425 * - @c ACL_ERROR - Unexpected library error.
427 int any_can_execute(int fd
, const struct stat
* sp
) {
430 perror("any_can_execute (args)");
434 acl_t acl
= acl_get_fd(fd
);
436 if (acl
== (acl_t
)NULL
) {
437 perror("any_can_execute (acl_get_fd)");
441 /* Our return value. */
442 int result
= ACL_FAILURE
;
444 if (acl_is_minimal(acl
)) {
445 if (sp
->st_mode
& (S_IXUSR
| S_IXOTH
| S_IXGRP
)) {
446 result
= ACL_SUCCESS
;
450 result
= ACL_FAILURE
;
456 int ge_result
= acl_get_entry(acl
, ACL_FIRST_ENTRY
, &entry
);
458 while (ge_result
== ACL_SUCCESS
) {
459 /* The first thing we do is check to see if this is a mask
460 entry. If it is, we skip it entirely. */
461 acl_tag_t tag
= ACL_UNDEFINED_TAG
;
463 if (acl_get_tag_type(entry
, &tag
) == ACL_ERROR
) {
464 perror("any_can_execute_or (acl_get_tag_type)");
469 if (tag
== ACL_MASK
) {
470 ge_result
= acl_get_entry(acl
, ACL_NEXT_ENTRY
, &entry
);
474 /* Ok, so it's not a mask entry. Check the execute perms. */
475 acl_permset_t permset
;
477 if (acl_get_permset(entry
, &permset
) == ACL_ERROR
) {
478 perror("any_can_execute_or (acl_get_permset)");
483 int gp_result
= acl_get_perm(permset
, ACL_EXECUTE
);
484 if (gp_result
== ACL_ERROR
) {
485 perror("any_can_execute (acl_get_perm)");
490 if (gp_result
== ACL_SUCCESS
) {
491 /* Only return ACL_SUCCESS if this execute bit is not masked. */
492 if (acl_execute_masked(acl
) != ACL_SUCCESS
) {
493 result
= ACL_SUCCESS
;
498 ge_result
= acl_get_entry(acl
, ACL_NEXT_ENTRY
, &entry
);
501 if (ge_result
== ACL_ERROR
) {
502 perror("any_can_execute (acl_get_entry)");
515 * @brief Copy ACLs between file descriptors as xattrs, verbatim.
517 * There is a small deficiency in libacl, namely that there is no way
518 * to get or set default ACLs through file descriptors. The @c
519 * acl_get_file and @c acl_set_file functions can do it, but they use
520 * paths, and are vulnerable to symlink attacks.
522 * Fortunately, when inheriting an ACL, we don't really need to look
523 * at what it contains. That means that we can copy the on-disk xattrs
524 * from the source directory to the destination file/directory without
525 * passing through libacl, and this can be done with file descriptors
526 * through @c fgetxattr and @c fsetxattr. That's what this function
530 * The file descriptor from which the ACL will be copied.
533 * The type of ACL (either @c ACL_TYPE_ACCESS or @c ACL_TYPE_DEFAULT)
534 * to copy from @c src_fd.
537 * The file descriptor whose ACL will be overwritten with the one
541 * The type of ACL (either @c ACL_TYPE_ACCESS or @c ACL_TYPE_DEFAULT)
542 * to replace on @c dst_fd.
545 * - @c ACL_SUCCESS - The ACL was copied successfully.
546 * - @c ACL_FAILURE - There was no ACL on @c src_fd.
547 * - @c ACL_ERROR - Unexpected library error.
549 int acl_copy_xattr(int src_fd
,
552 acl_type_t dst_type
) {
554 const char* src_name
;
555 if (src_type
== ACL_TYPE_ACCESS
) {
556 src_name
= XATTR_NAME_POSIX_ACL_ACCESS
;
558 else if (src_type
== ACL_TYPE_DEFAULT
) {
559 src_name
= XATTR_NAME_POSIX_ACL_DEFAULT
;
563 perror("acl_copy_xattr (src type)");
567 const char* dst_name
;
568 if (dst_type
== ACL_TYPE_ACCESS
) {
569 dst_name
= XATTR_NAME_POSIX_ACL_ACCESS
;
571 else if (dst_type
== ACL_TYPE_DEFAULT
) {
572 dst_name
= XATTR_NAME_POSIX_ACL_DEFAULT
;
576 perror("acl_copy_xattr (dst type)");
580 ssize_t src_size_guess
= fgetxattr(src_fd
, src_name
, NULL
, 0);
581 if (src_size_guess
== XATTR_ERROR
) {
582 if (errno
== ENODATA
) {
583 /* A missing ACL isn't really an error. ENOATTR and ENODATA are
584 synonyms, but using ENODATA here lets us avoid another
585 "include" directive. */
588 perror("acl_copy_xattr (fgetxattr size guess)");
591 char* src_acl_p
= alloca(src_size_guess
);
592 /* The actual size may be smaller than our guess? I don't know. */
593 ssize_t src_size
= fgetxattr(src_fd
, src_name
, src_acl_p
, src_size_guess
);
594 if (src_size
== XATTR_ERROR
) {
595 if (errno
== ENODATA
) {
596 /* A missing ACL isn't an error. */
599 perror("acl_copy_xattr (fgetxattr)");
603 if (fsetxattr(dst_fd
, dst_name
, src_acl_p
, src_size
, 0) == XATTR_ERROR
) {
604 perror("acl_copy_xattr (fsetxattr)");
613 * @brief Determine if a file descriptor has a default ACL.
616 * The file descriptor whose default ACL is in question.
619 * - @c ACL_SUCCESS - If @c fd has a default ACL.
620 * - @c ACL_FAILURE - If @c fd does not have a default ACL.
621 * - @c ACL_ERROR - Unexpected library error.
623 int has_default_acl_fd(int fd
) {
624 if (fgetxattr(fd
, XATTR_NAME_POSIX_ACL_DEFAULT
, NULL
, 0) == XATTR_ERROR
) {
625 if (errno
== ENODATA
) {
628 perror("has_default_acl_fd (fgetxattr)");
638 * @brief The recursive portion of @c apply_default_acl.
640 * The @c apply_default_acl function takes a path, but then opens file
641 * descriptors for the path and its parent. Afterwards, everything is
642 * done using file descriptors, including the recursive application on
643 * the path's children. This function encapsulates the portion of @c
644 * apply_default_acl that uses only file descriptors; for the
645 * recursion, this function ultimately calls itself.
647 * This overwrites any existing ACLs on @c fd and, if @c recursive is
648 * @c true, its children. When @c recursive is @c true, the "worst"
649 * result encountered is returned as the overall result.
652 * A file descriptor for the parent directory of @c fd.
655 * The file descriptor that should inherit its parent's default ACL.
658 * Should we recurse into subdirectories?
661 * - @c ACL_SUCCESS - The parent default ACLs were inherited successfully.
662 * - @c ACL_FAILURE - If symlinks or hard links are encountered.
663 * - @c ACL_ERROR - Unexpected library error.
665 int apply_default_acl_fds(int parent_fd
,
668 int result
= ACL_SUCCESS
;
670 /* The new ACL for this path */
671 acl_t new_acl
= (acl_t
)NULL
;
673 /* A copy of new_acl, to be made before we begin mangling new_acl in
674 order to mask the execute bit. */
675 acl_t new_acl_unmasked
= (acl_t
)NULL
;
677 /* Refuse to operate on hard links, which can be abused by an
678 * attacker to trick us into changing the ACL on a file we didn't
679 * intend to; namely the "target" of the hard link. There is TOCTOU
680 * race condition here, but the window is as small as possible
681 * between when we open the file descriptor (look above) and when we
685 if (fstat(fd
, &s
) == STAT_ERROR
) {
686 perror("apply_default_acl_fds (fstat)");
687 /* We can't recurse without the stat struct for fd */
692 /* Check to make sure the parent descriptor actually has a default
693 ACL. If it doesn't, then we can "succeed" immediately, saving a
694 little work, particularly in any_can_execute(). Note that we
695 can't skip the fstat() above, because we need it in case we
697 if (has_default_acl_fd(parent_fd
) == ACL_FAILURE
) {
698 result
= ACL_SUCCESS
;
699 /* Just because this target can't inherit anything doesn't mean
700 that one of it's children can't. For example, if there's a
701 default on "c" in "a/b/c/d", then we don't want to skip all
707 if (!S_ISDIR(s
.st_mode
)) {
708 /* If it's not a directory, make sure it's a regular,
709 non-hard-linked file. */
710 if (!S_ISREG(s
.st_mode
) || s
.st_nlink
!= 1) {
711 result
= ACL_FAILURE
;
712 goto cleanup
; /* It's not a directory, so we can skip the recursion. */
717 /* Next We try to guess whether or not to strip the execute bits.
718 * This behavior is modeled after the capital 'X' perms of setfacl.
720 int ace_result
= any_can_execute(fd
, &s
);
722 if (ace_result
== ACL_ERROR
) {
723 perror("apply_default_acl_fds (any_can_execute)");
728 /* Never mask the execute bit on directories. */
729 bool allow_exec
= (bool)ace_result
|| S_ISDIR(s
.st_mode
);
732 /* If it's a directory, inherit the parent's default. */
733 if (S_ISDIR(s
.st_mode
)) {
734 if (acl_copy_xattr(parent_fd
,
737 ACL_TYPE_DEFAULT
) == ACL_ERROR
) {
738 perror("apply_default_acl_fds (acl_copy_xattr default)");
744 /* If it's anything, _apply_ the parent's default. */
745 if (acl_copy_xattr(parent_fd
,
748 ACL_TYPE_ACCESS
) == ACL_ERROR
) {
749 perror("apply_default_acl_fds (acl_copy_xattr access)");
754 /* There's a good reason why we saved the ACL above, even though
755 * we're about to read it back into memory and mess with it on the
756 * next line. The acl_copy_xattr() function is already a hack to let
757 * us copy default ACLs without resorting to path names; we simply
758 * have no way to read the parent's default ACL into memory using
759 * parent_fd. We can, however, copy the parent's ACL to a file (with
760 * acl_copy_xattr), and then read the ACL from a file using
761 * "fd". It's quite the circus, but it works and should be safe from
762 * sym/hardlink attacks.
765 /* Now we potentially need to mask the execute permissions in the
766 ACL on fd; or maybe not. */
768 /* Skip the mask code for this target, but don't skip its children! */
772 /* OK, we need to mask some execute permissions. First obtain the
774 new_acl
= acl_get_fd(fd
);
775 if (new_acl
== (acl_t
)NULL
) {
776 perror("apply_default_acl_fds (acl_get_fd)");
781 /* ...and now make a copy of it, because otherwise when we loop
782 below, some shit gets stuck (modifying the structure while
783 looping over it no worky). */
784 new_acl_unmasked
= acl_dup(new_acl
);
785 if (new_acl_unmasked
== (acl_t
)NULL
) {
786 perror("apply_default_acl_fds (acl_dup)");
792 int ge_result
= acl_get_entry(new_acl_unmasked
, ACL_FIRST_ENTRY
, &entry
);
794 while (ge_result
== ACL_SUCCESS
) {
795 acl_tag_t tag
= ACL_UNDEFINED_TAG
;
797 if (acl_get_tag_type(entry
, &tag
) == ACL_ERROR
) {
798 perror("apply_default_acl_fds (acl_get_tag_type)");
804 /* We've got an entry/tag from the default ACL. Get its permset. */
805 acl_permset_t permset
;
806 if (acl_get_permset(entry
, &permset
) == ACL_ERROR
) {
807 perror("apply_default_acl_fds (acl_get_permset)");
812 /* To mimic what the kernel does, I think we could drop
813 ACL_GROUP_OBJ from the list below? */
814 if (tag
== ACL_MASK
||
815 tag
== ACL_USER_OBJ
||
816 tag
== ACL_GROUP_OBJ
||
819 /* The mask doesn't affect acl_user_obj, acl_group_obj (in
820 minimal ACLs) or acl_other entries, so if execute should be
821 masked, we have to do it manually. */
822 if (acl_delete_perm(permset
, ACL_EXECUTE
) == ACL_ERROR
) {
823 perror("apply_default_acl_fds (acl_delete_perm)");
828 if (acl_set_permset(entry
, permset
) == ACL_ERROR
) {
829 perror("apply_default_acl_fds (acl_set_permset)");
835 if (acl_update_entry(new_acl
, entry
) == ACL_ERROR
) {
836 perror("apply_default_acl_fds (acl_update_entry)");
841 ge_result
= acl_get_entry(new_acl_unmasked
, ACL_NEXT_ENTRY
, &entry
);
844 /* Catches the first acl_get_entry as well as the ones at the end of
846 if (ge_result
== ACL_ERROR
) {
847 perror("apply_default_acl_fds (acl_get_entry)");
852 if (acl_set_fd(fd
, new_acl
) == ACL_ERROR
) {
853 perror("apply_default_acl_fds (acl_set_fd)");
859 if (recursive
&& S_ISDIR(s
.st_mode
)) {
860 /* Recurse into subdirectories. Don't call closedir() on d! It
861 closes the open file descriptor as well, and subsequent calls
862 to close() then throw errors. */
863 DIR* d
= fdopendir(fd
);
865 perror("apply_default_acl_fds (fdopendir)");
872 while ((de
= readdir(d
)) != NULL
) {
873 if (de
->d_type
!= DT_DIR
&& de
->d_type
!= DT_REG
) {
874 /* Hit a symlink or whatever. */
875 result
= ACL_FAILURE
;
878 if (strcmp(de
->d_name
, ".") == 0) { continue; }
879 if (strcmp(de
->d_name
, "..") == 0) { continue; }
881 /* Be careful not to "return" out of this loop and leave the
883 new_fd
= openat(fd
, de
->d_name
, O_NOFOLLOW
);
884 if (new_fd
== OPEN_ERROR
) {
885 if (errno
== ELOOP
|| errno
== ENOTDIR
) {
886 /* We hit a symlink, either in the last path component (ELOOP)
887 or higher up (ENOTDIR). */
888 if (result
== ACL_SUCCESS
) {
889 /* Don't overwrite an error result with success/failure. */
890 result
= ACL_FAILURE
;
895 perror("apply_default_acl_fds (openat)");
900 switch (apply_default_acl_fds(fd
, new_fd
, recursive
)) {
901 /* Don't overwrite an error result with success/failure. */
903 if (result
== ACL_SUCCESS
) {
904 result
= ACL_FAILURE
;
910 if (close(new_fd
) == CLOSE_ERROR
) {
911 perror("apply_default_acl_fds (close)");
920 acl_free(new_acl_unmasked
);
926 * @brief Apply parent default ACL to a path and optionally its children.
928 * This overwrites any existing ACLs on the target, and, if @c
929 * recursive is @c true, its children. When @c recursive is @c true,
930 * the "worst" result encountered is returned as the overall result.
933 * The path whose ACL we would like to reset to its default.
936 * Should we recurse into subdirectories?
939 * - @c ACL_SUCCESS - The parent default ACLs were inherited successfully.
940 * - @c ACL_FAILURE - If symlinks or hard links are encountered.
941 * - @c ACL_ERROR - Unexpected library error.
943 int apply_default_acl(const char* path
, bool recursive
) {
947 perror("apply_default_acl (args)");
951 /* Define these next three variables here because we may have to
952 * jump to the cleanup routine which expects them to exist.
955 /* Our return value. */
956 int result
= ACL_SUCCESS
;
958 /* The file descriptor corresponding to "path" */
961 /* The file descriptor for the directory containing "path" */
964 /* dirname() and basename() mangle their arguments, so we need
965 to make copies of "path" before using them. */
966 char* dirname_path_copy
= NULL
;
967 char* basename_path_copy
= NULL
;
969 /* Get the parent directory of "path" with dirname(), which happens
970 * to murder its argument and necessitates a path_copy. */
971 dirname_path_copy
= strdup(path
);
972 if (dirname_path_copy
== NULL
) {
973 perror("apply_default_acl (strdup)");
976 char* parent
= dirname(dirname_path_copy
);
977 parent_fd
= safe_open(parent
, O_DIRECTORY
| O_NOFOLLOW
);
978 if (parent_fd
== OPEN_ERROR
) {
979 if (errno
== ELOOP
|| errno
== ENOTDIR
) {
980 /* We hit a symlink, either in the last path component (ELOOP)
981 or higher up (ENOTDIR). */
982 result
= ACL_FAILURE
;
986 perror("apply_default_acl (open parent fd)");
992 /* We already obtained the parent fd safely, so if we use the
993 basename of path here instead of the full thing, then we can get
994 away with using openat() and spare ourselves the slowness of
995 another safe_open(). */
996 basename_path_copy
= strdup(path
);
997 if (basename_path_copy
== NULL
) {
998 perror("apply_default_acl (strdup)");
1001 fd
= openat(parent_fd
, basename(basename_path_copy
), O_NOFOLLOW
);
1002 if (fd
== OPEN_ERROR
) {
1003 if (errno
== ELOOP
|| errno
== ENOTDIR
) {
1004 /* We hit a symlink, either in the last path component (ELOOP)
1005 or higher up (ENOTDIR). */
1006 result
= ACL_FAILURE
;
1010 perror("apply_default_acl (open fd)");
1016 result
= apply_default_acl_fds(parent_fd
, fd
, recursive
);
1019 free(dirname_path_copy
);
1020 free(basename_path_copy
);
1022 if (parent_fd
> 0 && close(parent_fd
) == CLOSE_ERROR
) {
1023 perror("apply_default_acl (close parent_fd)");
1026 if (fd
> 0 && close(fd
) == CLOSE_ERROR
) {
1027 perror("apply_default_acl (close fd)");