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