user/5015: gzip and 3.8 errata 2 do not mix - games/nethack suffers

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

user/5015: gzip and 3.8 errata 2 do not mix - games/nethack suffers

Joachim Schipper
>Number:         5015
>Category:       user
>Synopsis:       gzip and 3.8 errata 2 do not mix - games/nethack suffers
>Confidential:   yes
>Severity:       serious
>Priority:       medium
>Responsible:    bugs
>State:          open
>Quarter:        
>Keywords:      
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Feb 10 00:30:01 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Joachim Schipper
>Release:        3.8-errata 2 or 3.8-stable
>Organization:
net
>Environment:
        System      : OpenBSD 3.8
        Architecture: OpenBSD.i386
        Machine     : i386
>Description:
        When using games/nethack, I noticed that saving and loading games gave error messages: loading an earlier save gave me 'gzip: /dev/stdin: Operation not permitted' and 'Unable to uncompress save/XXXXjoach', and fails. Saving a game gives 'gzip: /dev/stdin: Operation not permitted' but does work, after a fashion; from a look at the directory /usr/local/lib/nethackdir-3.4.3/save, the game is not gzipped but otherwise saved fine.
        Loading the just-saved game gives no error message, and appears to work just fine. This is not surprising, as the game is not compressed and gzip is, therefore, not called.
        This install has worked for me before on this same 3.8 system, though it has been a while since I last started nethack.

        The more fundamental issue (and the reason for the relatively high priority) is that gzip opens /dev/stdin where this is not required, thus causing it to fail when being used by a s{u,g}id program (such as nethack) to compress data fed to it through a pipe. This worked fine prior to 3.8 errata 2, of course. For extra clarity, note that this applies even if the parent drops priviliges before execution - as nethack does - as this prohibition is passed to any children of a s{u,g}id process.
>How-To-Repeat:
        Start a new game (nethack - y) and save it (S - y); then load it (nethack). To reproduce the first error message, gzip the save file before attempting to load it.
        On a more fundamental note, call gzip from any sgid program without filename argument. Or copy gzip to a private place and set the sgid bit, then pipe something into it.
>Fix:
        A simple workaround is to undefine COMPRESS in nethack's includes/config.h, which I did not test as it is an ugly hack.
        The proper fix is to tell gzip not to open /dev/stdin, but execute what amounts to dup2(0, whateverfdgziplikes). I did not check whether or not this was already in the 3.9-beta tree, though a quick search on MARC suggested this may not be the case (but did turn up http://marc.theaimsgroup.com/?l=openbsd-cvs&m=105639771521166&w=2); if not, it would make sense to commit a change to that effect, since it's hard to believe that only nethack may rely on gzip working as normal in s{u,g}id situations.


>Release-Note:
>Audit-Trail:
>Unformatted:

Reply | Threaded
Open this post in threaded view
|

Re: user/5015: gzip and 3.8 errata 2 do not mix - games/nethack suffers

Otto Moerbeek
The following reply was made to PR user/5015; it has been noted by GNATS.

From: Otto Moerbeek <[hidden email]>
To: Joachim Schipper <[hidden email]>
Cc: [hidden email]
Subject: Re: user/5015: gzip and 3.8 errata 2 do not mix - games/nethack suffers
Date: Sat, 11 Feb 2006 09:33:13 +0100 (CET)

 On Fri, 10 Feb 2006, Joachim Schipper wrote:
 
 > >Number:         5015
 > >Category:       user
 > >Synopsis:       gzip and 3.8 errata 2 do not mix - games/nethack suffers
 
 Nethack does not drop effective privs. If a call to sete{u,g}uid is
 done before the set{u,g}uid, things should work out ok.
 
 Still, gzip using /dev/stdin is something that should be looked at.
 
  -Otto
 
 --- files.c.orig Sat Feb 11 09:31:55 2006
 +++ files.c Sat Feb 11 09:32:01 2006
 @@ -1153,7 +1153,9 @@ boolean uncomp;
  redirect(filename, RDBMODE, stdin, uncomp);
  redirect(cfn, WRBMODE, stdout, uncomp);
  }
 + (void) setegid(getgid());
  (void) setgid(getgid());
 + (void) seteuid(getuid());
  (void) setuid(getuid());
  (void) execv(args[0], (char *const *) args);
  perror((char *)0);