~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/proc/fd-001-lookup.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Copyright © 2018 Alexey Dobriyan <adobriyan@gmail.com>
  3  *
  4  * Permission to use, copy, modify, and distribute this software for any
  5  * purpose with or without fee is hereby granted, provided that the above
  6  * copyright notice and this permission notice appear in all copies.
  7  *
  8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 15  */
 16 // Test /proc/*/fd lookup.
 17 
 18 #undef NDEBUG
 19 #include <assert.h>
 20 #include <dirent.h>
 21 #include <errno.h>
 22 #include <limits.h>
 23 #include <sched.h>
 24 #include <stdio.h>
 25 #include <unistd.h>
 26 #include <sys/types.h>
 27 #include <sys/stat.h>
 28 #include <fcntl.h>
 29 
 30 #include "proc.h"
 31 
 32 /* lstat(2) has more "coverage" in case non-symlink pops up somehow. */
 33 static void test_lookup_pass(const char *pathname)
 34 {
 35         struct stat st;
 36         ssize_t rv;
 37 
 38         memset(&st, 0, sizeof(struct stat));
 39         rv = lstat(pathname, &st);
 40         assert(rv == 0);
 41         assert(S_ISLNK(st.st_mode));
 42 }
 43 
 44 static void test_lookup_fail(const char *pathname)
 45 {
 46         struct stat st;
 47         ssize_t rv;
 48 
 49         rv = lstat(pathname, &st);
 50         assert(rv == -1 && errno == ENOENT);
 51 }
 52 
 53 static void test_lookup(unsigned int fd)
 54 {
 55         char buf[64];
 56         unsigned int c;
 57         unsigned int u;
 58         int i;
 59 
 60         snprintf(buf, sizeof(buf), "/proc/self/fd/%u", fd);
 61         test_lookup_pass(buf);
 62 
 63         /* leading junk */
 64         for (c = 1; c <= 255; c++) {
 65                 if (c == '/')
 66                         continue;
 67                 snprintf(buf, sizeof(buf), "/proc/self/fd/%c%u", c, fd);
 68                 test_lookup_fail(buf);
 69         }
 70 
 71         /* trailing junk */
 72         for (c = 1; c <= 255; c++) {
 73                 if (c == '/')
 74                         continue;
 75                 snprintf(buf, sizeof(buf), "/proc/self/fd/%u%c", fd, c);
 76                 test_lookup_fail(buf);
 77         }
 78 
 79         for (i = INT_MIN; i < INT_MIN + 1024; i++) {
 80                 snprintf(buf, sizeof(buf), "/proc/self/fd/%d", i);
 81                 test_lookup_fail(buf);
 82         }
 83         for (i = -1024; i < 0; i++) {
 84                 snprintf(buf, sizeof(buf), "/proc/self/fd/%d", i);
 85                 test_lookup_fail(buf);
 86         }
 87         for (u = INT_MAX - 1024; u <= (unsigned int)INT_MAX + 1024; u++) {
 88                 snprintf(buf, sizeof(buf), "/proc/self/fd/%u", u);
 89                 test_lookup_fail(buf);
 90         }
 91         for (u = UINT_MAX - 1024; u != 0; u++) {
 92                 snprintf(buf, sizeof(buf), "/proc/self/fd/%u", u);
 93                 test_lookup_fail(buf);
 94         }
 95 
 96 
 97 }
 98 
 99 int main(void)
100 {
101         struct dirent *de;
102         unsigned int fd, target_fd;
103 
104         if (unshare(CLONE_FILES) == -1)
105                 return 1;
106 
107         /* Wipe fdtable. */
108         do {
109                 DIR *d;
110 
111                 d = opendir("/proc/self/fd");
112                 if (!d)
113                         return 1;
114 
115                 de = xreaddir(d);
116                 assert(de->d_type == DT_DIR);
117                 assert(streq(de->d_name, "."));
118 
119                 de = xreaddir(d);
120                 assert(de->d_type == DT_DIR);
121                 assert(streq(de->d_name, ".."));
122 next:
123                 de = xreaddir(d);
124                 if (de) {
125                         unsigned long long fd_ull;
126                         unsigned int fd;
127                         char *end;
128 
129                         assert(de->d_type == DT_LNK);
130 
131                         fd_ull = xstrtoull(de->d_name, &end);
132                         assert(*end == '\0');
133                         assert(fd_ull == (unsigned int)fd_ull);
134 
135                         fd = fd_ull;
136                         if (fd == dirfd(d))
137                                 goto next;
138                         close(fd);
139                 }
140 
141                 closedir(d);
142         } while (de);
143 
144         /* Now fdtable is clean. */
145 
146         fd = open("/", O_PATH|O_DIRECTORY);
147         assert(fd == 0);
148         test_lookup(fd);
149         close(fd);
150 
151         /* Clean again! */
152 
153         fd = open("/", O_PATH|O_DIRECTORY);
154         assert(fd == 0);
155         /* Default RLIMIT_NOFILE-1 */
156         target_fd = 1023;
157         while (target_fd > 0) {
158                 if (dup2(fd, target_fd) == target_fd)
159                         break;
160                 target_fd /= 2;
161         }
162         assert(target_fd > 0);
163         close(fd);
164         test_lookup(target_fd);
165         close(target_fd);
166 
167         return 0;
168 }
169 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php