https://github.com/msantos/closefrom
close(2) a range of file descriptors before exec(2)
https://github.com/msantos/closefrom
closefrom exec fd
Last synced: 6 months ago
JSON representation
close(2) a range of file descriptors before exec(2)
- Host: GitHub
- URL: https://github.com/msantos/closefrom
- Owner: msantos
- License: isc
- Created: 2020-08-28T11:56:04.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2024-11-27T12:27:38.000Z (7 months ago)
- Last Synced: 2024-11-27T13:27:31.522Z (7 months ago)
- Topics: closefrom, exec, fd
- Language: C
- Homepage:
- Size: 25.4 KB
- Stars: 1
- Watchers: 3
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# SYNOPSIS
closefrom *fd* *cmd* *arg* *...*
# DESCRIPTION
closefrom - close(2) a range of file descriptors before exec(2)
`closefrom` closes all file descriptors numbered fd and higher before
executing a program.`exec(2)`ing a file can unintentionally leak file descriptors to
the new process image. These file descriptors may provide unexpected
[capabilities](https://www.freebsd.org/cgi/man.cgi?capsicum(4)) to
the process.`closefrom` is run as a part of an exec chain, closing many descriptors
similar to the [closefrom(2)](https://man.openbsd.org/closefrom) system
call, before executing the target process.# EXAMPLES
## [ucspi-unix](https://github.com/bruceg/ucspi-unix)
`ucspi-unix` is an example of the "Defer to Kernel"
privilege separation model in [Secure Design
Patterns](https://resources.sei.cmu.edu/asset_files/TechnicalReport/2009_005_001_15110.pdf).The guarantees are broken because `ucspi-unix` [leaks the listening
socket](https://github.com/bruceg/ucspi-unix/pull/2) to the application
subprocess. The application subprocess can race the server in accepting
new connections and bypass unix socket permissions and socket credential
checks.```C
#include
#include#include
#include
#include
#include/* cc -g -Wall -o accept accept.c */
int main(int argc, char *argv[]) {
int fd;
struct sockaddr_un addr;
socklen_t addrlen = sizeof(addr);for (;;) {
fd = accept(3, (struct sockaddr *)&addr, &addrlen);
if (fd < 0) {
warn("accept");
continue;
}
(void)write(fd, "12345678\n", 9);
(void)close(fd);
}
}
``````
# run unixserver as root
sudo unixserver -m 077 /tmp/test.sock -- setuidgid nobody ./accept# connect to the socket
$ sudo nc -U /tmp/test.sock
$ sudo nc -U /tmp/test.sock
$ sudo nc -U /tmp/test.sock
12345678# with closefrom
sudo unixserver -m 077 /tmp/test.sock -- closefrom 3 setuidgid nobody ./accept
accept: accept: Bad file descriptor
```## shell
This example opens and leaks a file descriptor to `cat(1)`:
```shell
#!/bin/bashexec 9 /dev/pts/19
lrwx------. 1 msantos msantos 64 Aug 28 09:28 1 -> /dev/pts/19
lrwx------. 1 msantos msantos 64 Aug 28 09:28 2 -> /dev/pts/19
lr-x------. 1 msantos msantos 64 Aug 28 09:28 3 -> /proc/32048/fd
lr-x------. 1 msantos msantos 64 Aug 28 09:28 9 -> /dev/null$ leakfd closefrom 3 ls -al /proc/self/fd
total 0
dr-x------. 2 msantos msantos 0 Aug 28 09:29 .
dr-xr-xr-x. 9 msantos msantos 0 Aug 28 09:29 ..
lrwx------. 1 msantos msantos 64 Aug 28 09:29 0 -> /dev/pts/19
lrwx------. 1 msantos msantos 64 Aug 28 09:29 1 -> /dev/pts/19
lrwx------. 1 msantos msantos 64 Aug 28 09:29 2 -> /dev/pts/19
lr-x------. 1 msantos msantos 64 Aug 28 09:29 3 -> /proc/32058/fd
```# OPTIONS
None.
# BUILDING
```
make# statically linked executable
./musl-make# some versions of glibc support closefrom(2)
CLOSEFROM_CFLAGS="-DHAVE_CLOSEFROM" make# run tests
make clean all test
```# ALTERNATIVES
* bash
```shell
#!/bin/bashset -o errexit
set -o nounset
set -o pipefailshopt -s failglob
LOWFD="$1"
shift
for pathfd in /dev/fd/[0-9]*; do
fd="${pathfd##*/}"
[ "$fd" -ge "$LOWFD" ] || continue
eval "exec $fd>&-"
done
exec "$@"
```* [fdclose](http://skarnet.org./software/execline/fdclose.html)
# SEE ALSO
*close*(2), *closefrom(2)*, *exec(3)*