From 336bd62ba24c023807040b5fd72818bfd2e3f6d4 Mon Sep 17 00:00:00 2001 From: Michael Kerrisk Date: Sun, 14 Feb 2021 23:04:45 +0100 Subject: [PATCH] close_range.2: Include a better example program The current example program can't really be used to demonstrate the effect of close_range(). Replace it by a program that does show the effect of this system call. Signed-off-by: Michael Kerrisk --- man2/close_range.2 | 112 ++++++++++++++++++++++++++++++++------------- 1 file changed, 79 insertions(+), 33 deletions(-) diff --git a/man2/close_range.2 b/man2/close_range.2 index f02926bce..5871a46f3 100644 --- a/man2/close_range.2 +++ b/man2/close_range.2 @@ -1,4 +1,5 @@ .\" Copyright (c) 2020 Stephen Kitt +.\" and Copyright (c) 2021 Michael Kerrisk .\" .\" %%%LICENSE_START(VERBATIM) .\" Permission is granted to make and distribute verbatim copies of this @@ -174,63 +175,108 @@ and the profile can control access to .BR close_range () without affecting the calling process. .SH EXAMPLES -The following program executes the command given on its command-line, -after opening the files listed after the command and then using +The program shown below opens the files named in its command-line arguments, +displays the list of files that it has opened +(by iterating through the entries in +.IR /proc/PID/fd ), +uses .BR close_range () -to close them: +to close all file descriptors greater than or equal to 3, +and then once more displays the process's list of open files. +The following example demonstrates the use of the program: .PP .in +4n .EX -/* close_range.c */ - +$ \fBtouch /tmp/a /tmp/b /tmp/c\fP +$ \fB./a.out /tmp/a /tmp/b /tmp/c\fP +/tmp/a opened as FD 3 +/tmp/b opened as FD 4 +/tmp/c opened as FD 5 +/proc/self/fd/0 ==> /dev/pts/1 +/proc/self/fd/1 ==> /dev/pts/1 +/proc/self/fd/2 ==> /dev/pts/1 +/proc/self/fd/3 ==> /tmp/a +/proc/self/fd/4 ==> /tmp/b +/proc/self/fd/5 ==> /tmp/b +/proc/self/fd/6 ==> /proc/9005/fd +========= About to call close_range() ======= +/proc/self/fd/0 ==> /dev/pts/1 +/proc/self/fd/1 ==> /dev/pts/1 +/proc/self/fd/2 ==> /dev/pts/1 +/proc/self/fd/3 ==> /proc/9005/fd +.EE +.in +.PP +Note that the lines showing the pathname +.I /proc/9005/fd +result from the calls to +.BR opendir (3). +.SS Program source +\& +.EX +#define _GNU_SOURCE #include #include #include #include -#include #include -#include +#include #include +#include + +/* Show the contents of the symbolic links in /proc/self/fd */ + +static void +show_fds(void) +{ + DIR *dirp = opendir("/proc/self/fd"); + if (dirp == NULL) { + perror("opendir"); + exit(EXIT_FAILURE); + } + + for (;;) { + struct dirent *dp = readdir(dirp); + if (dp == NULL) + break; + + if (dp\->d_type == DT_LNK) { + char path[PATH_MAX], target[PATH_MAX]; + snprintf(path, sizeof(path), "/proc/self/fd/%s", + dp\->d_name); + + ssize_t len = readlink(path, target, sizeof(target)); + printf("%s ==> %.*s\en", path, (int) len, target); + } + } + + closedir(dirp); +} int main(int argc, char *argv[]) { - char *newargv[] = { NULL }; - char *newenviron[] = { NULL }; - - if (argc < 3) { - fprintf(stderr, "Usage: %s ...\en", argv[0]); - exit(EXIT_FAILURE); - } - - for (int i = 2; i < argc; i++) { - if (open(argv[i], O_RDONLY) == \-1) { - perror(argv[i]); + for (int j = 1; j < argc; j++) { + int fd = open(argv[j], O_RDONLY); + if (fd == \-1) { + perror(argv[j]); exit(EXIT_FAILURE); } + printf("%s opened as FD %d\en", argv[j], fd); } - if (syscall(__NR_close_range, 3, ~0U, 0) == \-1) { + show_fds(); + + printf("========= About to call close_range() =======\en"); + + if (syscall(__NR_close_range, 3, \(ti0U, 0) == \-1) { perror("close_range"); exit(EXIT_FAILURE); } - execve(argv[1], newargv, newenviron); - perror("execve"); + show_fds(); exit(EXIT_FAILURE); } .EE -.in -.PP -Running any program with the above, with files to open: -.PP -.in +4n -.EX -.RB "$" " ./close_range " " /dev/null /dev/zero" -.EE -.in -.PP -and inspecting the open files in the resulting process will show that -the files have indeed been closed. .SH SEE ALSO .BR close (2)