On Sun, Oct 08, 2023 at 12:18:34AM -0400, George Koehler wrote: > On Fri, 8 Jul 2022 16:04:47 +0000 > Guilherme Janczak <guilherme.janc...@yandex.com> wrote: > > > gzip violates wpath if you tell it to extract stdin and restore the > > original filename. > > More than a year ago, Guilherme Janczak reported that OpenBSD's > "gzip -dN <rc.gz" crashes by pledge and crashes, and sent a diff to > skip the 2nd pledge call. I put the diff in one of my src trees and > forgot about it until today. > > I observe that "gzip -dN <rc.gz" doesn't crash with the pledge-skip > diff, but "zcat -N rc.gz" still crashes. (The diff works with an > implicit -c from reading stdin, but not with an explicit "gzip -c" or > "zcat".) > > In other systems (I tried GNU gzip 1.12 and NetBSD gzip 20170803), > -c overrides -N, so "gzip -dN <rc.gz" and "zcat -N rc.gz" both ignore > the -N and cat to stdout. In OpenBSD, -N overrides -c, so these > commands try to write "rc" (the stored filename), but crash like, > 'gzip[11955]: pledge "wpath", syscall 5'.
FWIW, archivers/pigz aka. pigz(1) pledges like base gzip(1) but works, i.e. 'pigz -Nd < rc.gz' drops to "stdio rpath" and succeeds, so it must have ignored -N. > > The pledge-skip diff is in > https://marc.info/?l=openbsd-tech&m=165729624913806&w=2 I think I'd make sense to also add the original diff's regress test to cover this missing case. > > I made a new diff for -c overrides -N, is this better? > --gkoehler That diff reads OK to me and regress stays happy. > > Index: main.c > =================================================================== > RCS file: /cvs/src/usr.bin/compress/main.c,v > retrieving revision 1.105 > diff -u -p -r1.105 main.c > --- main.c 11 Aug 2023 04:45:05 -0000 1.105 > +++ main.c 8 Oct 2023 04:00:57 -0000 > @@ -699,7 +699,8 @@ dodecompress(const char *in, char *out, > close (ifd); > return (FAILURE); > } > - if (storename && oldname[0] != '\0') { > + /* Do -N only if not -c. */ /* -c overrides -N. */ would read a tad better, imho. > + if (storename && !cat && oldname[0] != '\0') { > const char *oldbase = basename(oldname); > char *cp = strrchr(out, '/'); > if (cp != NULL) { > @@ -707,7 +708,6 @@ dodecompress(const char *in, char *out, > strlcat(out, oldbase, PATH_MAX); > } else > strlcpy(out, oldbase, PATH_MAX); > - cat = 0; /* XXX should -c override? */ > } > > if (testmode) { >