0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #undef NDEBUG
0019 #include <sys/syscall.h>
0020 #include <assert.h>
0021 #include <dirent.h>
0022 #include <limits.h>
0023 #include <stdio.h>
0024 #include <string.h>
0025 #include <sys/types.h>
0026 #include <sys/stat.h>
0027 #include <fcntl.h>
0028 #include <unistd.h>
0029
0030 #include "proc.h"
0031
0032 #define PF_KHTREAD 0x00200000
0033
0034
0035
0036
0037
0038
0039
0040 static int kernel_thread_fd(unsigned int pid)
0041 {
0042 unsigned int flags = 0;
0043 char buf[4096];
0044 int dir_fd, fd;
0045 ssize_t rv;
0046
0047 snprintf(buf, sizeof(buf), "/proc/%u", pid);
0048 dir_fd = open(buf, O_RDONLY|O_DIRECTORY);
0049 if (dir_fd == -1)
0050 return -1;
0051
0052
0053
0054
0055
0056 fd = openat(dir_fd, "stat", O_RDONLY);
0057 if (fd == -1) {
0058 close(dir_fd);
0059 return -1;
0060 }
0061 rv = read(fd, buf, sizeof(buf));
0062 close(fd);
0063 if (0 < rv && rv <= sizeof(buf)) {
0064 unsigned long long flags_ull;
0065 char *p, *end;
0066 int i;
0067
0068 assert(buf[rv - 1] == '\n');
0069 buf[rv - 1] = '\0';
0070
0071
0072 for (i = 0; i < 43; i++) {
0073 p = strrchr(buf, ' ');
0074 assert(p);
0075 *p = '\0';
0076 }
0077
0078 p = strrchr(buf, ' ');
0079 assert(p);
0080
0081 flags_ull = xstrtoull(p + 1, &end);
0082 assert(*end == '\0');
0083 assert(flags_ull == (unsigned int)flags_ull);
0084
0085 flags = flags_ull;
0086 }
0087
0088 fd = -1;
0089 if (flags & PF_KHTREAD) {
0090 fd = openat(dir_fd, "fd", O_RDONLY|O_DIRECTORY);
0091 }
0092 close(dir_fd);
0093 return fd;
0094 }
0095
0096 static void test_readdir(int fd)
0097 {
0098 DIR *d;
0099 struct dirent *de;
0100
0101 d = fdopendir(fd);
0102 assert(d);
0103
0104 de = xreaddir(d);
0105 assert(streq(de->d_name, "."));
0106 assert(de->d_type == DT_DIR);
0107
0108 de = xreaddir(d);
0109 assert(streq(de->d_name, ".."));
0110 assert(de->d_type == DT_DIR);
0111
0112 de = xreaddir(d);
0113 assert(!de);
0114 }
0115
0116 static inline int sys_statx(int dirfd, const char *pathname, int flags,
0117 unsigned int mask, void *stx)
0118 {
0119 return syscall(SYS_statx, dirfd, pathname, flags, mask, stx);
0120 }
0121
0122 static void test_lookup_fail(int fd, const char *pathname)
0123 {
0124 char stx[256] __attribute__((aligned(8)));
0125 int rv;
0126
0127 rv = sys_statx(fd, pathname, AT_SYMLINK_NOFOLLOW, 0, (void *)stx);
0128 assert(rv == -1 && errno == ENOENT);
0129 }
0130
0131 static void test_lookup(int fd)
0132 {
0133 char buf[64];
0134 unsigned int u;
0135 int i;
0136
0137 for (i = INT_MIN; i < INT_MIN + 1024; i++) {
0138 snprintf(buf, sizeof(buf), "%d", i);
0139 test_lookup_fail(fd, buf);
0140 }
0141 for (i = -1024; i < 1024; i++) {
0142 snprintf(buf, sizeof(buf), "%d", i);
0143 test_lookup_fail(fd, buf);
0144 }
0145 for (u = INT_MAX - 1024; u < (unsigned int)INT_MAX + 1024; u++) {
0146 snprintf(buf, sizeof(buf), "%u", u);
0147 test_lookup_fail(fd, buf);
0148 }
0149 for (u = UINT_MAX - 1024; u != 0; u++) {
0150 snprintf(buf, sizeof(buf), "%u", u);
0151 test_lookup_fail(fd, buf);
0152 }
0153 }
0154
0155 int main(void)
0156 {
0157 unsigned int pid;
0158 int fd;
0159
0160
0161
0162
0163
0164
0165
0166 pid = 2;
0167 while ((fd = kernel_thread_fd(pid)) == -1 && pid < 1024) {
0168 pid++;
0169 }
0170
0171 if (pid >= 1024)
0172 return 1;
0173
0174 test_readdir(fd);
0175 test_lookup(fd);
0176
0177 return 0;
0178 }