From nobody  Wed Jan 28 03:16:42 1998
Received: (from nobody@localhost)
          by hub.freebsd.org (8.8.8/8.8.8) id DAA11874;
          Wed, 28 Jan 1998 03:16:42 -0800 (PST)
          (envelope-from nobody)
Message-Id: <199801281116.DAA11874@hub.freebsd.org>
Date: Wed, 28 Jan 1998 03:16:42 -0800 (PST)
From: paulo@fiscodata-pr.netpar.com.br
To: freebsd-gnats-submit@freebsd.org
Subject: Trouble with LD_PRELOAD environment variable and man pages
X-Send-Pr-Version: www-1.0

>Number:         5591
>Category:       bin
>Synopsis:       Trouble with LD_PRELOAD environment variable and man pages
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    jkoshy
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jan 28 03:20:01 PST 1998
>Closed-Date:    Tue Oct 14 17:38:03 PDT 2003
>Last-Modified:  Tue Oct 14 17:38:03 PDT 2003
>Originator:     Paulo Cesar Pereira de Andrade
>Release:        -CURRENT and -STABLE
>Organization:
Particular
>Environment:
FreeBSD fiscodata-pr.netpar.com.br 2.2.5-STABLE #0: Wed Dec 31 09:08:35 GMT 1997    root@fiscodata-pr.netpar.com.br:/usr/src/sys/compile/OTIMIZADO  i386
>Description:
While building a libXaw replacement, I found a problem with man, that
I think can be exploitable. When setting the LD_PRELOAD environment
variable to "./libXaw.so.6.0:/other/shared/libs" and typping:
% man XGetGeometry, the XGetGeometry man page is truncated to
zero lines. This can be done, I think, in any man page if it is
not in the <base>/man/cat?/ directory, by any user.
>How-To-Repeat:
% setenv LD_PRELOAD '/usr/X11R6/lib/libXaw.so.6.?'; man XGetGeometry
Formatting page, please wait...ld.so failed: Undefined symbol "_XtStrings" in groff:/usr/X11R6/lib/libXaw.so.6.1
<Other error messages>
% unsetenv LD_PRELOAD; man XGetGeometry
%
>Fix:

>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->analyzed 
State-Changed-By: jdp 
State-Changed-When: Wed Jan 28 09:13:58 PST 1998 
State-Changed-Why:  
Problem confirmed.  Any bogus value for LD_PRELOAD causes groff to 
fail, leaving a compressed empty "formatted" version of the man 
page in the "cat?" directory.  Subsequent invocations of man use the 
bad file, because it has a newer timestamp than the unformatted copy. 
The man command should take care to clean up the bad file if groff 
fails. 
Responsible-Changed-From-To: freebsd-bugs->jkoshy 
Responsible-Changed-By: jkoshy 
Responsible-Changed-When: Mon Aug 27 23:03:28 PDT 2001 
Responsible-Changed-Why:  
Am looking at this bug. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=5591 

From: jkoshy@FreeBSD.ORG (Joseph Koshy)
To: freebsd-gnats-submit@FreeBSD.ORG
Cc:  
Subject: Re: bin/5591: Trouble with LD_PRELOAD environment variable and man pages
Date: Mon, 27 Aug 2001 23:03:16 -0700 (PDT)

 In function `make_cat_file' in ".../man/man.c", the code constructs
 a complex pipe command and hands it off to `popen()'.  
 
  trying command: (cd /usr/local/man ; /usr/bin/zcat /usr/local/man/man1/bzip2.1.gz 
  | /usr/bin/tbl | /usr/bin/groff -S -Wall -mtty-char -man -Tascii | /usr/bin/col | 
  /usr/bin/gzip -c)
 
 One of the processes in the middle of pipe command is failing, but
 `pclose()' checks the exit status of the LAST process in the pipe.
 
    "/usr/src/gnu/usr.bin/man/man.c"
    1258         if (!f || ((s = pclose(pp)) == -1)) {
    1259           s = errno;
    1260           fprintf(stderr, "Failed.\n");
    1261           errno = s;
    1262           perror("pclose");
    1263           unlink(temp);
    1264           restore_sigs();
    1265           fclose(fp);
    1266           return 0;
    1267         }
 
 The last process happens to be "/usr/bin/gzip" which is perfectly happy
 reading zero bytes from its input.  There is an additional check whether
 non-zero bytes were read from the input pipe: however, this check fails
 to catch the error because "gzip" will always write out a 20 byte header
 to standard output.
 
    "/usr/src/gnu/usr.bin/man/man.c"
    1253         f = 0;
    1254         while ((s = getc(pp)) != EOF) {
    1255           putc(s, fp); f++;
    1256         }
 
 Complex pipelines are not a good idea.
 
 Koshy
 <jkoshy@freebsd.org>
 

From: jkoshy@FreeBSD.ORG (Joseph Koshy)
To: freebsd-gnats-submit@freebsd.org
Cc:  
Subject: Re: bin/5591: Trouble with LD_PRELOAD environment variable and man 
 pages
Date: Mon, 13 Oct 2003 23:14:23 -0700 (PDT)

 This is a multipart MIME message.
 
 --==_Exmh_-5409410690
 Content-Type: text/plain
 
 
 The following patch to "/usr/bin/man" separates the compression
 and text formatting stages of the man page formatting pipeline,
 with the intention of making the error checking more robust.
 
 
 
 --==_Exmh_-5409410690
 Content-Type: text/x-patch ; name="p"
 Content-Description: fix for bin/5591
 Content-Disposition: attachment; filename="p"
 
 Index: man.c
 ===================================================================
 RCS file: /cvs/FreeBSD/src/gnu/usr.bin/man/man/man.c,v
 retrieving revision 1.59
 diff -u -r1.59 man.c
 --- man.c	30 Sep 2002 11:00:03 -0000	1.59
 +++ man.c	14 Oct 2003 11:26:12 -0000
 @@ -1179,7 +1179,12 @@
       register char *cat_file;
  {
    int s, f;
 -  FILE *fp, *pp;
 +  FILE *pp;
 +#if defined(HAVE_LIBZ) && defined(DO_COMPRESS)
 +  gzFile fp;
 +#else
 +  FILE *fp;
 +#endif
    char *roff_command;
    char command[FILENAME_MAX];
  
 @@ -1188,7 +1193,12 @@
        return 0;
  
    snprintf(temp, sizeof(temp), "%s.tmpXXXXXX", cat_file);
 -  if ((f = mkstemp(temp)) >= 0 && (fp = fdopen(f, "w")) != NULL)
 +  if ((f = mkstemp(temp)) >= 0 && 
 +#if defined(HAVE_LIBZ) && defined(DO_COMPRESS)
 +      (fp = gzdopen(f, "w")) != NULL)
 +#else
 +      (fp = fdopen(f, "w")) != NULL)
 +#endif
      {
        set_sigs();
  
 @@ -1201,13 +1211,9 @@
        } else if (debug)
  	fprintf (stderr, "mode of %s is now %o\n", temp, CATMODE);
  
 -#ifdef DO_COMPRESS
 -      snprintf (command, sizeof(command), "(cd %s ; %s | %s)", path,
 -		roff_command, COMPRESSOR);
 -#else
        snprintf (command, sizeof(command), "(cd %s ; %s)", path,
  		roff_command);
 -#endif
 +
        fprintf (stderr, "Formatting page, please wait...");
        fflush(stderr);
  
 @@ -1230,7 +1236,11 @@
  #endif
  	  unlink(temp);
  	  restore_sigs();
 +#if defined(HAVE_LIBZ) && defined(DO_COMPRESS)
 +	  gzclose(fp);
 +#else
  	  fclose(fp);
 +#endif
  	  return 0;
  	}
  #ifdef SETUID
 @@ -1240,17 +1250,27 @@
  
  	f = 0;
  	while ((s = getc(pp)) != EOF) {
 -	  putc(s, fp); f++;
 +#if defined(HAVE_LIBZ) && defined(DO_COMPRESS)
 +	  gzputc(fp, s);
 +#else
 +	  putc(s, fp);
 +#endif
 +	  f++;
  	}
  
  	if (!f || ((s = pclose(pp)) == -1)) {
  	  s = errno;
  	  fprintf(stderr, "Failed.\n");
  	  errno = s;
 -	  perror("pclose");
 +	  if (f)
 +	    perror("pclose");
  	  unlink(temp);
  	  restore_sigs();
 +#if defined(HAVE_LIBZ) && defined(DO_COMPRESS)
 +	  gzclose(fp);
 +#else
  	  fclose(fp);
 +#endif
  	  return 0;
  	}
  
 @@ -1259,7 +1279,11 @@
  	  gripe_system_command(s);
  	  unlink(temp);
  	  restore_sigs();
 +#if defined(HAVE_LIBZ) && defined(DO_COMPRESS)
 +	  gzclose(fp);
 +#else
  	  fclose(fp);
 +#endif
  	  return 0;
  	}
        }
 @@ -1275,12 +1299,20 @@
  	perror("rename");
  	unlink(temp);
  	restore_sigs();
 +#if defined(HAVE_LIBZ) && defined(DO_COMPRESS)
 +	gzclose(fp);
 +#else
  	fclose(fp);
 +#endif
  	return 0;
        }
        restore_sigs();
  
 +#if defined(HAVE_LIBZ) && defined(DO_COMPRESS)
 +      if (gzclose(fp)) {
 +#else
        if (fclose(fp)) {
 +#endif
  	s = errno;
  	if (!debug)
  	  unlink(cat_file);
 
 --==_Exmh_-5409410690--
 
 
State-Changed-From-To: analyzed->closed 
State-Changed-By: jkoshy 
State-Changed-When: Tue Oct 14 17:37:06 PDT 2003 
State-Changed-Why:  
Fixed in rev 1.60 of "src/gnu/usr.bin/man/man/man.c". 

http://www.freebsd.org/cgi/query-pr.cgi?pr=5591 
>Unformatted:
