]>
Commit | Line | Data |
---|---|---|
85b8a2cb A |
1 | // |
2 | // Copyright (c) 2020 Apple Inc. All rights reserved. | |
3 | // | |
4 | ||
5 | #include <err.h> | |
6 | #include <errno.h> | |
7 | #include <fcntl.h> | |
8 | #include <paths.h> | |
9 | #include <stdbool.h> | |
10 | #include <stdio.h> | |
11 | #include <stdlib.h> | |
12 | #include <sys/types.h> | |
13 | #include <sys/acl.h> | |
14 | #include <sys/attr.h> | |
15 | #include <sys/stat.h> | |
16 | #include <sys/time.h> | |
17 | #include <sys/xattr.h> | |
18 | #include <unistd.h> | |
19 | #include "readonly_fd_test.h" | |
20 | #include "test_utils.h" | |
21 | ||
22 | ||
23 | static | |
24 | bool test_readonly_fd_metadata(const char *basedir) | |
25 | { | |
26 | char filename[] = ".readonly-ops-XXXXXX"; | |
27 | bool created = false; | |
28 | bool success = true; | |
29 | int dirfd = -1; | |
30 | int tmpfd = -1; | |
31 | int fd = -1; | |
32 | acl_t acl = NULL; | |
33 | ||
34 | static const char test_name[] = "readonly_fd_metadata"; | |
35 | printf("START [%s]\n", test_name); | |
36 | ||
37 | assert_with_errno((dirfd = open(basedir, O_RDONLY | O_DIRECTORY)) != -1); | |
38 | assert_with_errno((tmpfd = mkstempsat_np(dirfd, filename, 0)) != -1); | |
39 | created = true; | |
40 | ||
41 | assert_with_errno((fd = openat(dirfd, filename, O_RDONLY)) != -1); | |
42 | close(tmpfd); | |
43 | tmpfd = -1; | |
44 | ||
45 | // confirm that writes are disallowed | |
46 | const char data[] = "failure"; | |
47 | assert(write(fd, data, sizeof(data) - 1) == -1); | |
48 | ||
49 | // check fchown() | |
50 | const uid_t uid = geteuid(); | |
51 | const gid_t gid = getegid(); | |
52 | assert_no_err(fchown(fd, uid, gid)); | |
53 | ||
54 | // check fchmod() | |
55 | assert_no_err(fchmod(fd, 0644)); | |
56 | assert_no_err(fchmod(fd, 0600)); | |
57 | ||
58 | // check fchflags() | |
59 | assert_no_err(fchflags(fd, UF_HIDDEN)); | |
60 | ||
61 | // check setting timestamps with fsetattrlist | |
62 | const time_t mtime = 978307200; | |
63 | const time_t atime = mtime + 1; | |
64 | ||
65 | struct timeval matimes_usec[] = {{mtime, 0}, {atime, 0}}; | |
66 | assert_no_err(futimes(fd, matimes_usec)); | |
67 | ||
68 | struct attrlist attrlist = { | |
69 | .bitmapcount = ATTR_BIT_MAP_COUNT, | |
70 | .commonattr = ATTR_CMN_MODTIME | ATTR_CMN_ACCTIME, | |
71 | }; | |
72 | struct { | |
73 | struct timespec mtime; | |
74 | struct timespec atime; | |
75 | } matimes_nsec = {{mtime, 0}, {atime, 0}}; | |
76 | assert_no_err(fsetattrlist(fd, &attrlist, &matimes_nsec, sizeof(matimes_nsec), 0)); | |
77 | ||
78 | // check adding and removing xattrs | |
79 | static const char key[] = "local.test-xattr"; | |
80 | static const char value[] = "local.test-xattr.value"; | |
81 | assert_no_err(fsetxattr(fd, key, value, sizeof(value)-1, 0, 0)); | |
82 | assert_no_err(fremovexattr(fd, key, 0)); | |
83 | ||
84 | // check setting ACLs | |
85 | assert_with_errno((acl = acl_init(1)) != NULL); | |
86 | assert_no_err(acl_set_fd(fd, acl)); | |
87 | ||
88 | // log pass/fail before cleanup | |
89 | if (success) { | |
90 | printf("PASS [%s]\n", test_name); | |
91 | } else { | |
92 | printf("FAIL [%s]\n", test_name); | |
93 | } | |
94 | ||
95 | // clean up resources | |
96 | if (acl) { | |
97 | acl_free(acl); | |
98 | } | |
99 | if (fd != -1) { | |
100 | close(fd); | |
101 | } | |
102 | if (tmpfd != -1) { | |
103 | close(tmpfd); | |
104 | } | |
105 | if (created) { | |
106 | unlinkat(dirfd, filename, 0); | |
107 | } | |
108 | if (dirfd != -1) { | |
109 | close(dirfd); | |
110 | } | |
111 | ||
112 | return success; | |
113 | } | |
114 | ||
115 | ||
116 | bool do_readonly_fd_test(const char *apfs_test_directory, size_t block_size __unused) | |
117 | { | |
118 | // These tests verify the underlying calls needed for COPYFILE_METADATA | |
119 | // operations are safe with O_RDONLY file descriptors. If this fails, | |
120 | // expect <rdar://60074298> to cause many other copyfile() failures. | |
121 | bool success = true; | |
122 | success = success && test_readonly_fd_metadata(apfs_test_directory); | |
123 | return !success; // caller expects nonzero to mean failure | |
124 | } |