]> gitweb.michael.orlitzky.com - apply-default-acl.git/blob - src/libadacl.c
libadacl.c: use O_PATH in safe_open() for added safety.
[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 */
9 #define _GNU_SOURCE
10
11 #include <errno.h> /* EINVAL, ELOOP, ENOTDIR, etc. */
12 #include <fcntl.h> /* openat() */
13 #include <libgen.h> /* basename(), dirname() */
14 #include <limits.h> /* PATH_MAX */
15 #include <stdbool.h> /* the "bool" type */
16 #include <stdio.h> /* perror(), snprintf() */
17 #include <stdlib.h> /* free() */
18 #include <string.h> /* strdup() */
19 #include <sys/stat.h> /* fstat() */
20 #include <unistd.h> /* get_current_dir_name() */
21
22 /* ACLs */
23 #include <acl/libacl.h> /* acl_get_perm, not portable */
24 #include <sys/acl.h> /* all other acl_foo functions */
25
26 #include "libadacl.h"
27
28
29 /* Even though most other library functions reliably return -1 for
30 * error, it feels a little wrong to re-use the ACL_ERROR constant.
31 */
32 #define CLOSE_ERROR -1
33 #define OPEN_ERROR -1
34 #define SNPRINTF_ERROR -1
35 #define STAT_ERROR -1
36
37
38 /**
39 * @brief The recursive portion of the @c safe_open function, used to
40 * open a file descriptor in a symlink-safe way when combined with
41 * the @c O_NOFOLLOW flag.
42 *
43 * @param at_fd
44 * A file descriptor relative to which @c pathname will be opened.
45 *
46 * @param pathname
47 * The path to the file/directory/whatever whose descriptor you want.
48 *
49 * @param flags
50 * File status flags to be passed to @c openat.
51 *
52 * @return a file descriptor for @c pathname if everything goes well,
53 * and @c OPEN_ERROR if not.
54 */
55 int safe_open_ex(int at_fd, char* pathname, int flags) {
56 if (pathname == NULL) {
57 errno = EINVAL;
58 perror("safe_open_ex (args)");
59 return OPEN_ERROR;
60 }
61
62 char* firstslash = strchr(pathname, '/');
63 if (firstslash == NULL) {
64 /* No more slashes, this is the base case. */
65 return openat(at_fd, pathname, flags);
66 }
67 else if (firstslash[1] == '\0') {
68 /* The first slash is the last character; ensure that we open
69 a directory. */
70 firstslash[0] = '\0';
71 return openat(at_fd, pathname, flags | O_DIRECTORY);
72 }
73
74 /* The first slash exists and isn't the last character in the path,
75 so we can split the path wherever that first slash lies and
76 recurse. */
77 *firstslash = '\0';
78 int fd = openat(at_fd, pathname, flags | O_DIRECTORY | O_PATH);
79 if (fd == OPEN_ERROR) {
80 if (errno != ENOTDIR) {
81 /* Don't output anything if we ignore a symlink */
82 perror("safe_open_ex (safe_open_ex)");
83 }
84 return OPEN_ERROR;
85 }
86
87 /* The +1 is safe because there needs to be at least one character
88 after the first slash (we checked this above). */
89 int result = safe_open_ex(fd, firstslash+1, flags);
90 if (close(fd) == CLOSE_ERROR) {
91 perror("safe_open_ex (close)");
92 return OPEN_ERROR;
93 }
94 return result;
95 }
96
97
98 /**
99 * @brief A version of @c open that is completely symlink-safe when
100 * used with the @c O_NOFOLLOW flag.
101 *
102 * The @c openat function exists to ensure that you can anchor one
103 * path to a particular directory while opening it; however, if you
104 * open "b/c/d" relative to "/a", then even the @c openat function will
105 * still follow symlinks in the "b" component. This can be exploited
106 * by an attacker to make you open the wrong path.
107 *
108 * To avoid that problem, this function uses a recursive
109 * implementation that opens every path from the root, one level at a
110 * time. So "a" is opened relative to "/", and then "b" is opened
111 * relative to "/a", and then "c" is opened relative to "/a/b",
112 * etc. When the @c O_NOFOLLOW flag is used, this approach ensures
113 * that no symlinks in any component are followed.
114 *
115 * @param pathname
116 * The path to the file/directory/whatever whose descriptor you want.
117 *
118 * @param flags
119 * File status flags to be passed to @c openat.
120 *
121 * @return a file descriptor for @c pathname if everything goes well,
122 * and @c OPEN_ERROR if not.
123 */
124 int safe_open(const char* pathname, int flags) {
125 if (pathname == NULL || strlen(pathname) == 0 || pathname[0] == '\0') {
126 errno = EINVAL;
127 perror("safe_open (args)");
128 return OPEN_ERROR;
129 }
130
131 char abspath[PATH_MAX];
132 int snprintf_result = 0;
133 if (strchr(pathname, '/') == pathname) {
134 /* pathname is already absolute; just copy it. */
135 snprintf_result = snprintf(abspath, PATH_MAX, "%s", pathname);
136 }
137 else {
138 /* Concatenate the current working directory and pathname into an
139 * absolute path. We use realpath() ONLY on the cwd part, and not
140 * on the pathname part, because realpath() resolves symlinks. And
141 * the whole point of all this crap is to avoid following symlinks
142 * in the pathname.
143 *
144 * Using realpath() on the cwd lets us operate on relative paths
145 * while we're sitting in a directory that happens to have a
146 * symlink in it; for example: cd /var/run && apply-default-acl foo.
147 */
148 char* cwd = get_current_dir_name();
149 if (cwd == NULL) {
150 perror("safe_open (get_current_dir_name)");
151 return OPEN_ERROR;
152 }
153
154 char abs_cwd[PATH_MAX];
155 if (realpath(cwd, abs_cwd) == NULL) {
156 perror("safe_open (realpath)");
157 free(cwd);
158 return OPEN_ERROR;
159 }
160 snprintf_result = snprintf(abspath, PATH_MAX, "%s/%s", abs_cwd, pathname);
161 free(cwd);
162 }
163 if (snprintf_result == SNPRINTF_ERROR || snprintf_result > PATH_MAX) {
164 perror("safe_open (snprintf)");
165 return OPEN_ERROR;
166 }
167
168 int fd = 0;
169 if (strcmp(abspath, "/") == 0) {
170 fd = open("/", flags | O_DIRECTORY);
171 }
172 else {
173 /* Use O_PATH for some added safety if "/" is not our target */
174 fd = open("/", flags | O_DIRECTORY | O_PATH);
175 }
176 if (fd == OPEN_ERROR) {
177 perror("safe_open (open)");
178 return OPEN_ERROR;
179 }
180
181 if (strcmp(abspath, "/") == 0) {
182 return fd;
183 }
184
185 int result = safe_open_ex(fd, abspath+1, flags);
186 if (close(fd) == CLOSE_ERROR) {
187 perror("safe_open (close)");
188 return OPEN_ERROR;
189 }
190 return result;
191 }
192
193
194
195
196 /**
197 * @brief Update (or create) an entry in an @b minimal ACL.
198 *
199 * This function will not work if @c aclp contains extended
200 * entries. This is fine for our purposes, since we call @c wipe_acls
201 * on each path before applying the default to it.
202 *
203 * The assumption that there are no extended entries makes things much
204 * simpler. For example, we only have to update the @c ACL_USER_OBJ,
205 * @c ACL_GROUP_OBJ, and @c ACL_OTHER entries -- all others can simply
206 * be created anew. This means we don't have to fool around comparing
207 * named-user/group entries.
208 *
209 * @param aclp
210 * A pointer to the acl_t structure whose entry we want to modify.
211 *
212 * @param entry
213 * The new entry. If @c entry contains a user/group/other entry, we
214 * update the existing one. Otherwise we create a new entry.
215 *
216 * @return If there is an unexpected library error, @c ACL_ERROR is
217 * returned. Otherwise, @c ACL_SUCCESS.
218 *
219 */
220 int acl_set_entry(acl_t* aclp, acl_entry_t entry) {
221 if (aclp == NULL || entry == NULL) {
222 errno = EINVAL;
223 perror("acl_set_entry (args)");
224 return ACL_ERROR;
225 }
226
227 acl_tag_t entry_tag;
228 if (acl_get_tag_type(entry, &entry_tag) == ACL_ERROR) {
229 perror("acl_set_entry (acl_get_tag_type)");
230 return ACL_ERROR;
231 }
232
233 acl_permset_t entry_permset;
234 if (acl_get_permset(entry, &entry_permset) == ACL_ERROR) {
235 perror("acl_set_entry (acl_get_permset)");
236 return ACL_ERROR;
237 }
238
239 acl_entry_t existing_entry;
240 /* Loop through the given ACL looking for matching entries. */
241 int result = acl_get_entry(*aclp, ACL_FIRST_ENTRY, &existing_entry);
242
243 while (result == ACL_SUCCESS) {
244 acl_tag_t existing_tag = ACL_UNDEFINED_TAG;
245
246 if (acl_get_tag_type(existing_entry, &existing_tag) == ACL_ERROR) {
247 perror("set_acl_tag_permset (acl_get_tag_type)");
248 return ACL_ERROR;
249 }
250
251 if (existing_tag == entry_tag) {
252 if (entry_tag == ACL_USER_OBJ ||
253 entry_tag == ACL_GROUP_OBJ ||
254 entry_tag == ACL_OTHER) {
255 /* Only update for these three since all other tags will have
256 been wiped. These three are guaranteed to exist, so if we
257 match one of them, we're allowed to return ACL_SUCCESS
258 below and bypass the rest of the function. */
259 acl_permset_t existing_permset;
260 if (acl_get_permset(existing_entry, &existing_permset) == ACL_ERROR) {
261 perror("acl_set_entry (acl_get_permset)");
262 return ACL_ERROR;
263 }
264
265 if (acl_set_permset(existing_entry, entry_permset) == ACL_ERROR) {
266 perror("acl_set_entry (acl_set_permset)");
267 return ACL_ERROR;
268 }
269
270 return ACL_SUCCESS;
271 }
272
273 }
274
275 result = acl_get_entry(*aclp, ACL_NEXT_ENTRY, &existing_entry);
276 }
277
278 /* This catches both the initial acl_get_entry and the ones at the
279 end of the loop. */
280 if (result == ACL_ERROR) {
281 perror("acl_set_entry (acl_get_entry)");
282 return ACL_ERROR;
283 }
284
285 /* If we've made it this far, we need to add a new entry to the
286 ACL. */
287 acl_entry_t new_entry;
288
289 /* The acl_create_entry() function can allocate new memory and/or
290 * change the location of the ACL structure entirely. When that
291 * happens, the value pointed to by aclp is updated, which means
292 * that a new acl_t gets "passed out" to our caller, eventually to
293 * be fed to acl_free(). In other words, we should still be freeing
294 * the right thing, even if the value pointed to by aclp changes.
295 */
296 if (acl_create_entry(aclp, &new_entry) == ACL_ERROR) {
297 perror("acl_set_entry (acl_create_entry)");
298 return ACL_ERROR;
299 }
300
301 if (acl_set_tag_type(new_entry, entry_tag) == ACL_ERROR) {
302 perror("acl_set_entry (acl_set_tag_type)");
303 return ACL_ERROR;
304 }
305
306 if (acl_set_permset(new_entry, entry_permset) == ACL_ERROR) {
307 perror("acl_set_entry (acl_set_permset)");
308 return ACL_ERROR;
309 }
310
311 if (entry_tag == ACL_USER || entry_tag == ACL_GROUP) {
312 /* We need to set the qualifier too. */
313 void* entry_qual = acl_get_qualifier(entry);
314 if (entry_qual == (void*)NULL) {
315 perror("acl_set_entry (acl_get_qualifier)");
316 return ACL_ERROR;
317 }
318
319 if (acl_set_qualifier(new_entry, entry_qual) == ACL_ERROR) {
320 perror("acl_set_entry (acl_set_qualifier)");
321 return ACL_ERROR;
322 }
323 }
324
325 return ACL_SUCCESS;
326 }
327
328
329
330 /**
331 * @brief Determine the number of entries in the given ACL.
332 *
333 * @param acl
334 * The ACL to inspect.
335 *
336 * @return Either the non-negative number of entries in @c acl, or
337 * @c ACL_ERROR on error.
338 */
339 int acl_entry_count(acl_t acl) {
340
341 acl_entry_t entry;
342 int entry_count = 0;
343 int result = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
344
345 while (result == ACL_SUCCESS) {
346 entry_count++;
347 result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
348 }
349
350 if (result == ACL_ERROR) {
351 perror("acl_entry_count (acl_get_entry)");
352 return ACL_ERROR;
353 }
354
355 return entry_count;
356 }
357
358
359
360 /**
361 * @brief Determine whether or not the given ACL is minimal.
362 *
363 * An ACL is minimal if it has fewer than four entries.
364 *
365 * @param acl
366 * The ACL whose minimality is in question.
367 *
368 * @return
369 * - @c ACL_SUCCESS - @c acl is minimal
370 * - @c ACL_FAILURE - @c acl is not minimal
371 * - @c ACL_ERROR - Unexpected library error
372 */
373 int acl_is_minimal(acl_t acl) {
374 if (acl == NULL) {
375 errno = EINVAL;
376 perror("acl_is_minimal (args)");
377 return ACL_ERROR;
378 }
379
380 int ec = acl_entry_count(acl);
381
382 if (ec == ACL_ERROR) {
383 perror("acl_is_minimal (acl_entry_count)");
384 return ACL_ERROR;
385 }
386
387 if (ec < 4) {
388 return ACL_SUCCESS;
389 }
390 else {
391 return ACL_FAILURE;
392 }
393 }
394
395
396
397 /**
398 * @brief Determine whether the given ACL's mask denies execute.
399 *
400 * @param acl
401 * The ACL whose mask we want to check.
402 *
403 * @return
404 * - @c ACL_SUCCESS - The @c acl has a mask which denies execute.
405 * - @c ACL_FAILURE - The @c acl has a mask which does not deny execute.
406 * - @c ACL_ERROR - Unexpected library error.
407 */
408 int acl_execute_masked(acl_t acl) {
409 if (acl == NULL) {
410 errno = EINVAL;
411 perror("acl_execute_masked (args)");
412 return ACL_ERROR;
413 }
414
415 acl_entry_t entry;
416 int ge_result = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
417
418 while (ge_result == ACL_SUCCESS) {
419 acl_tag_t tag = ACL_UNDEFINED_TAG;
420
421 if (acl_get_tag_type(entry, &tag) == ACL_ERROR) {
422 perror("acl_execute_masked (acl_get_tag_type)");
423 return ACL_ERROR;
424 }
425
426 if (tag == ACL_MASK) {
427 /* This is the mask entry, get its permissions, and see if
428 execute is specified. */
429 acl_permset_t permset;
430
431 if (acl_get_permset(entry, &permset) == ACL_ERROR) {
432 perror("acl_execute_masked (acl_get_permset)");
433 return ACL_ERROR;
434 }
435
436 int gp_result = acl_get_perm(permset, ACL_EXECUTE);
437 if (gp_result == ACL_ERROR) {
438 perror("acl_execute_masked (acl_get_perm)");
439 return ACL_ERROR;
440 }
441
442 if (gp_result == ACL_FAILURE) {
443 /* No execute bit set in the mask; execute not allowed. */
444 return ACL_SUCCESS;
445 }
446 }
447
448 ge_result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
449 }
450
451 return ACL_FAILURE;
452 }
453
454
455
456 /**
457 * @brief Determine whether @c fd is executable by anyone.
458 *
459 *
460 * This is used as part of the heuristic to determine whether or not
461 * we should mask the execute bit when inheriting an ACL. If @c fd
462 * describes a file, we check the @a effective permissions, contrary
463 * to what setfacl does.
464 *
465 * @param fd
466 * The file descriptor to check.
467 *
468 * @param sp
469 * A pointer to a stat structure for @c fd.
470 *
471 * @return
472 * - @c ACL_SUCCESS - Someone has effective execute permissions on @c fd.
473 * - @c ACL_FAILURE - Nobody can execute @c fd.
474 * - @c ACL_ERROR - Unexpected library error.
475 */
476 int any_can_execute(int fd, const struct stat* sp) {
477 if (sp == NULL) {
478 errno = EINVAL;
479 perror("any_can_execute (args)");
480 return ACL_ERROR;
481 }
482
483 acl_t acl = acl_get_fd(fd);
484
485 if (acl == (acl_t)NULL) {
486 perror("any_can_execute (acl_get_file)");
487 return ACL_ERROR;
488 }
489
490 /* Our return value. */
491 int result = ACL_FAILURE;
492
493 if (acl_is_minimal(acl)) {
494 if (sp->st_mode & (S_IXUSR | S_IXOTH | S_IXGRP)) {
495 result = ACL_SUCCESS;
496 goto cleanup;
497 }
498 else {
499 result = ACL_FAILURE;
500 goto cleanup;
501 }
502 }
503
504 acl_entry_t entry;
505 int ge_result = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
506
507 while (ge_result == ACL_SUCCESS) {
508 /* The first thing we do is check to see if this is a mask
509 entry. If it is, we skip it entirely. */
510 acl_tag_t tag = ACL_UNDEFINED_TAG;
511
512 if (acl_get_tag_type(entry, &tag) == ACL_ERROR) {
513 perror("any_can_execute_or (acl_get_tag_type)");
514 result = ACL_ERROR;
515 goto cleanup;
516 }
517
518 if (tag == ACL_MASK) {
519 ge_result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
520 continue;
521 }
522
523 /* Ok, so it's not a mask entry. Check the execute perms. */
524 acl_permset_t permset;
525
526 if (acl_get_permset(entry, &permset) == ACL_ERROR) {
527 perror("any_can_execute_or (acl_get_permset)");
528 result = ACL_ERROR;
529 goto cleanup;
530 }
531
532 int gp_result = acl_get_perm(permset, ACL_EXECUTE);
533 if (gp_result == ACL_ERROR) {
534 perror("any_can_execute (acl_get_perm)");
535 result = ACL_ERROR;
536 goto cleanup;
537 }
538
539 if (gp_result == ACL_SUCCESS) {
540 /* Only return ACL_SUCCESS if this execute bit is not masked. */
541 if (acl_execute_masked(acl) != ACL_SUCCESS) {
542 result = ACL_SUCCESS;
543 goto cleanup;
544 }
545 }
546
547 ge_result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
548 }
549
550 if (ge_result == ACL_ERROR) {
551 perror("any_can_execute (acl_get_entry)");
552 result = ACL_ERROR;
553 goto cleanup;
554 }
555
556 cleanup:
557 acl_free(acl);
558 return result;
559 }
560
561
562
563 /**
564 * @brief Set @c acl as the default ACL on @c path.
565 *
566 * This overwrites any existing default ACL on @c path. If @c path is
567 * not a directory, we return ACL_ERROR and @c errno is set.
568 *
569 * @param path
570 * The target directory whose ACL we wish to replace or create.
571 *
572 * @param acl
573 * The ACL to set as default on @c path.
574 *
575 * @return
576 * - @c ACL_SUCCESS - The default ACL was assigned successfully.
577 * - @c ACL_ERROR - Unexpected library error.
578 */
579 int assign_default_acl(const char* path, acl_t acl) {
580 if (path == NULL || acl == NULL) {
581 errno = EINVAL;
582 perror("assign_default_acl (args)");
583 return ACL_ERROR;
584 }
585
586 /* Our return value; success unless something bad happens. */
587 int result = ACL_SUCCESS;
588 acl_t path_acl = acl_dup(acl);
589
590 if (path_acl == (acl_t)NULL) {
591 perror("assign_default_acl (acl_dup)");
592 return ACL_ERROR; /* Nothing to clean up in this case. */
593 }
594
595 if (acl_set_file(path, ACL_TYPE_DEFAULT, path_acl) == ACL_ERROR) {
596 perror("assign_default_acl (acl_set_file)");
597 result = ACL_ERROR;
598 }
599
600 acl_free(path_acl);
601 return result;
602 }
603
604
605
606 /**
607 * @brief Remove all @c ACL_TYPE_ACCESS entries from the given file
608 * descriptor, leaving the UNIX permission bits.
609 *
610 * @param fd
611 * The file descriptor whose ACLs we want to wipe.
612 *
613 * @return
614 * - @c ACL_SUCCESS - The ACLs were wiped successfully, or none
615 * existed in the first place.
616 * - @c ACL_ERROR - Unexpected library error.
617 */
618 int wipe_acls(int fd) {
619 /* Initialize an empty ACL, and then overwrite the one on "fd" with it. */
620 acl_t empty_acl = acl_init(0);
621
622 if (empty_acl == (acl_t)NULL) {
623 perror("wipe_acls (acl_init)");
624 return ACL_ERROR;
625 }
626
627 if (acl_set_fd(fd, empty_acl) == ACL_ERROR) {
628 perror("wipe_acls (acl_set_fd)");
629 acl_free(empty_acl);
630 return ACL_ERROR;
631 }
632
633 acl_free(empty_acl);
634 return ACL_SUCCESS;
635 }
636
637
638
639 /**
640 * @brief Apply parent default ACL to a path.
641 *
642 * This overwrites any existing ACLs on @c path.
643 *
644 * @param path
645 * The path whose ACL we would like to reset to its default.
646 *
647 * @param sp
648 * A pointer to a stat structure for @c path, or @c NULL if you don't
649 * have one handy.
650 *
651 * @param no_exec_mask
652 * The value (either true or false) of the --no-exec-mask flag.
653 *
654 * @return
655 * - @c ACL_SUCCESS - The parent default ACL was inherited successfully.
656 * - @c ACL_FAILURE - If symlinks or hard links are encountered.
657 * - @c ACL_ERROR - Unexpected library error.
658 */
659 int apply_default_acl_ex(const char* path,
660 const struct stat* sp,
661 bool no_exec_mask) {
662
663 if (path == NULL) {
664 errno = EINVAL;
665 perror("apply_default_acl_ex (args)");
666 return ACL_ERROR;
667 }
668
669 /* Define these next three variables here because we may have to
670 * jump to the cleanup routine which expects them to exist.
671 */
672
673 /* Our return value. */
674 int result = ACL_SUCCESS;
675
676 /* The default ACL on path's parent directory */
677 acl_t defacl = (acl_t)NULL;
678
679 /* The file descriptor corresponding to "path" */
680 int fd = 0;
681
682 /* Get the parent directory of "path" with dirname(), which happens
683 * to murder its argument and necessitates a path_copy.
684 */
685 char* path_copy = strdup(path);
686 if (path_copy == NULL) {
687 perror("apply_default_acl_ex (strdup)");
688 return ACL_ERROR;
689 }
690 char* parent = dirname(path_copy);
691
692 fd = safe_open(path, O_NOFOLLOW);
693 if (fd == OPEN_ERROR) {
694 if (errno == ELOOP || errno == ENOTDIR) {
695 /* We hit a symlink, either in the last path component (ELOOP)
696 or higher up (ENOTDIR). */
697 result = ACL_FAILURE;
698 goto cleanup;
699 }
700 else {
701 perror("apply_default_acl_ex (open fd)");
702 result = ACL_ERROR;
703 goto cleanup;
704 }
705 }
706
707
708 /* Refuse to operate on hard links, which can be abused by an
709 * attacker to trick us into changing the ACL on a file we didn't
710 * intend to; namely the "target" of the hard link. There is TOCTOU
711 * race condition here, but the window is as small as possible
712 * between when we open the file descriptor (look above) and when we
713 * fstat it.
714 *
715 * Note: we only need to call fstat ourselves if we weren't passed a
716 * valid pointer to a stat structure (nftw does that).
717 */
718 if (sp == NULL) {
719 struct stat s;
720 if (fstat(fd, &s) == STAT_ERROR) {
721 perror("apply_default_acl_ex (fstat)");
722 goto cleanup;
723 }
724
725 sp = &s;
726 }
727
728 if (!S_ISDIR(sp->st_mode)) {
729 /* If it's not a directory, make sure it's a regular,
730 non-hard-linked file. */
731 if (!S_ISREG(sp->st_mode) || sp->st_nlink != 1) {
732 result = ACL_FAILURE;
733 goto cleanup;
734 }
735 }
736
737
738 /* Default to not masking the exec bit; i.e. applying the default
739 ACL literally. If --no-exec-mask was not specified, then we try
740 to "guess" whether or not to mask the exec bit. This behavior
741 is modeled after the capital 'X' perms of setfacl. */
742 bool allow_exec = true;
743
744 if (!no_exec_mask) {
745 /* Never mask the execute bit on directories. */
746 int ace_result = any_can_execute(fd,sp) || S_ISDIR(sp->st_mode);
747
748 if (ace_result == ACL_ERROR) {
749 perror("apply_default_acl_ex (any_can_execute)");
750 result = ACL_ERROR;
751 goto cleanup;
752 }
753
754 allow_exec = (bool)ace_result;
755 }
756
757 defacl = acl_get_file(parent, ACL_TYPE_DEFAULT);
758
759 if (defacl == (acl_t)NULL) {
760 perror("apply_default_acl_ex (acl_get_file)");
761 result = ACL_ERROR;
762 goto cleanup;
763 }
764
765 if (wipe_acls(fd) == ACL_ERROR) {
766 perror("apply_default_acl_ex (wipe_acls)");
767 result = ACL_ERROR;
768 goto cleanup;
769 }
770
771 /* Do this after wipe_acls(), otherwise we'll overwrite the wiped
772 ACL with this one. */
773 acl_t acl = acl_get_fd(fd);
774 if (acl == (acl_t)NULL) {
775 perror("apply_default_acl_ex (acl_get_fd)");
776 result = ACL_ERROR;
777 goto cleanup;
778 }
779
780 /* If it's a directory, inherit the parent's default. We sure hope
781 * that "path" still points to the same thing that "fd" and this
782 * "sp" describe. If not, we may wind up trying to set a default ACL
783 * on a file, and this will throw an error. I guess that's what we
784 * want to do?
785 */
786 if (S_ISDIR(sp->st_mode) && assign_default_acl(path, defacl) == ACL_ERROR) {
787 perror("apply_default_acl_ex (assign_default_acl)");
788 result = ACL_ERROR;
789 goto cleanup;
790 }
791
792 acl_entry_t entry;
793 int ge_result = acl_get_entry(defacl, ACL_FIRST_ENTRY, &entry);
794
795 while (ge_result == ACL_SUCCESS) {
796 acl_tag_t tag = ACL_UNDEFINED_TAG;
797
798 if (acl_get_tag_type(entry, &tag) == ACL_ERROR) {
799 perror("apply_default_acl_ex (acl_get_tag_type)");
800 result = ACL_ERROR;
801 goto cleanup;
802 }
803
804
805 /* We've got an entry/tag from the default ACL. Get its permset. */
806 acl_permset_t permset;
807 if (acl_get_permset(entry, &permset) == ACL_ERROR) {
808 perror("apply_default_acl_ex (acl_get_permset)");
809 result = ACL_ERROR;
810 goto cleanup;
811 }
812
813 /* If this is a default mask, fix it up. */
814 if (tag == ACL_MASK ||
815 tag == ACL_USER_OBJ ||
816 tag == ACL_GROUP_OBJ ||
817 tag == ACL_OTHER) {
818
819 if (!allow_exec) {
820 /* The mask doesn't affect acl_user_obj, acl_group_obj (in
821 minimal ACLs) or acl_other entries, so if execute should be
822 masked, we have to do it manually. */
823 if (acl_delete_perm(permset, ACL_EXECUTE) == ACL_ERROR) {
824 perror("apply_default_acl_ex (acl_delete_perm)");
825 result = ACL_ERROR;
826 goto cleanup;
827 }
828
829 if (acl_set_permset(entry, permset) == ACL_ERROR) {
830 perror("apply_default_acl_ex (acl_set_permset)");
831 result = ACL_ERROR;
832 goto cleanup;
833 }
834 }
835 }
836
837 /* Finally, add the permset to the access ACL. It's actually
838 * important that we pass in the address of "acl" here, and not
839 * "acl" itself. Why? The call to acl_create_entry() within
840 * acl_set_entry() can allocate new memory for the entry.
841 * Sometimes that can be done in-place, in which case everything
842 * is cool and the new memory gets released when we call
843 * acl_free(acl).
844 *
845 * But occasionally, the whole ACL structure will have to be moved
846 * in order to allocate the extra space. When that happens,
847 * acl_create_entry() modifies the pointer it was passed (in this
848 * case, &acl) to point to the new location. We want to call
849 * acl_free() on the new location, and since acl_free() gets
850 * called right here, we need acl_create_entry() to update the
851 * value of "acl". To do that, it needs the address of "acl".
852 */
853 if (acl_set_entry(&acl, entry) == ACL_ERROR) {
854 perror("apply_default_acl_ex (acl_set_entry)");
855 result = ACL_ERROR;
856 goto cleanup;
857 }
858
859 ge_result = acl_get_entry(defacl, ACL_NEXT_ENTRY, &entry);
860 }
861
862 /* Catches the first acl_get_entry as well as the ones at the end of
863 the loop. */
864 if (ge_result == ACL_ERROR) {
865 perror("apply_default_acl_ex (acl_get_entry)");
866 result = ACL_ERROR;
867 goto cleanup;
868 }
869
870 if (acl_set_fd(fd, acl) == ACL_ERROR) {
871 perror("apply_default_acl_ex (acl_set_fd)");
872 result = ACL_ERROR;
873 goto cleanup;
874 }
875
876 cleanup:
877 free(path_copy);
878 if (defacl != (acl_t)NULL) {
879 acl_free(defacl);
880 }
881 if (fd >= 0 && close(fd) == CLOSE_ERROR) {
882 perror("apply_default_acl_ex (close)");
883 result = ACL_ERROR;
884 }
885 return result;
886 }
887
888
889
890 /**
891 * @brief The friendly interface to @c apply_default_acl_ex.
892 *
893 * The @c apply_default_acl_ex function holds the real implementation
894 * of this function, but it takes a weird second argument that most
895 * people won't care about (a stat structure). But, we use that
896 * argument for the recursive mode of the CLI, so it's there.
897 *
898 * If you don't have a stat structure for your @c path, use this instead.
899 *
900 * @param path
901 * The path whose ACL we would like to reset to its default.
902 *
903 * @param no_exec_mask
904 * The value (either true or false) of the --no-exec-mask flag.
905 *
906 * @return
907 * - @c ACL_SUCCESS - The parent default ACL was inherited successfully.
908 * - @c ACL_FAILURE - If symlinks or hard links are encountered.
909 * or the parent of @c path is not a directory.
910 * - @c ACL_ERROR - Unexpected library error.
911 */
912 int apply_default_acl(const char* path, bool no_exec_mask) {
913 return apply_default_acl_ex(path, NULL, no_exec_mask);
914 }