diff options
author | Florian Obser <florian@cvs.openbsd.org> | 2023-07-15 10:42:55 +0000 |
---|---|---|
committer | Florian Obser <florian@cvs.openbsd.org> | 2023-07-15 10:42:55 +0000 |
commit | 665fc50f0a46f653db0a8ba9fa41e4495aa25294 (patch) | |
tree | 7677b071b4d0ccf1f44d1db777bc143bd6c8e3c3 /usr.bin/patch | |
parent | a87ba66d417527fd319d59a5e0e8a2714c1987ef (diff) |
Prevent patch(1) from scribbling all over the place.
Arguably the only sensible use of patch(1) is changing files in the
current working directory and subdirectories.
However, patch(1) has this anti-feature, or dare I say bug, where it
will happily follow "../" upwards and outside of the current working
directory to find files to change. All it takes is a line like
+++ ../../../../home/florian/.ssh/authorized_keys
in the patchfile.
patch(1) operates on untrusted input and it already pledge(2)'ed to
not execute arbitrary programs, but of course it needs to write
files.
A simple unveil(".", "rwc") restricts patch(1) to its current working
directory.
We also need to allow /tmp and potentially the output file and reject
file if given on the command line. But those paths are safe.
input op, deraadt
OK millert, sthen
Diffstat (limited to 'usr.bin/patch')
-rw-r--r-- | usr.bin/patch/patch.c | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/usr.bin/patch/patch.c b/usr.bin/patch/patch.c index a9740f09ef9..67da2bd23b3 100644 --- a/usr.bin/patch/patch.c +++ b/usr.bin/patch/patch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: patch.c,v 1.72 2023/07/12 11:26:13 tb Exp $ */ +/* $OpenBSD: patch.c,v 1.73 2023/07/15 10:42:54 florian Exp $ */ /* * patch - a program to apply diffs to original files @@ -149,7 +149,7 @@ main(int argc, char *argv[]) const char *tmpdir; char *v; - if (pledge("stdio rpath wpath cpath tmppath fattr", NULL) == -1) { + if (pledge("stdio rpath wpath cpath tmppath fattr unveil", NULL) == -1) { perror("pledge"); my_exit(2); } @@ -204,6 +204,38 @@ main(int argc, char *argv[]) Argc = argc; Argv = argv; get_some_switches(); + if (unveil(tmpdir, "rwc") == -1) { + perror("unveil"); + my_exit(2); + } + if (outname != NULL) + if (unveil(outname, "rwc") == -1) { + perror("unveil"); + my_exit(2); + } + if (filearg[0] != NULL) + if (unveil(filearg[0], "rwc") == -1) { + perror("unveil"); + my_exit(2); + } + if (filearg[1] != NULL) + if (unveil(filearg[1], "r") == -1) { + perror("unveil"); + my_exit(2); + } + if (unveil(".", "rwc") == -1) { + perror("unveil"); + my_exit(2); + } + if (*rejname != '\0') + if (unveil(rejname, "rwc") == -1) { + perror("unveil"); + my_exit(2); + } + if (pledge("stdio rpath wpath cpath tmppath fattr", NULL) == -1) { + perror("pledge"); + my_exit(2); + } if (backup_type == none) { if ((v = getenv("PATCH_VERSION_CONTROL")) == NULL) |