[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: gs shouldn't depend on svgalib



> 
> I've cc'd this to debian-devel more for the final comment about
> security, but suggestions about the other issues are of course welcome
> [..]
> >(BTW, I'm alson adding "-dSAFER" if I detect gs being setuid,
> >for security resons).
> 
> My initial reaction to that is `please don't' as svgalib-compatible gs
> has to be setuid to work at all.  If gs is setuid then it should call
> surrender the root permissions after doing what is necessary (vga_init
> does this; if you implement code that doesn't call it manually you
> must do it yourself fairly early on.)

I'm rather reluctant to modify gs itself. What I basically wanted
to do was to say
  /usr/bin/gs should not be setuid -- but if you locally decide that
  you really really want svgalib easily accessable, and don't want to
  make a complete mockery of security, you can make it setuid, and
  the /usr/bin/gs wrapper will add -dSAFER to gs's command line 
  arguments if it thinks you need the setuid, or surrender the root
  privileges if it thinks you don't need them (see code below).

I'm sure this doens't make gs completely safe if you decided to make it
setuid yourself (as I will clearly document), but the default way I'll
make gs install it self is WITHOUT setuid, so usually, no such problems
will occur.

However, if it proves to be really easy to modify the gs svga code,
I'll make it give up it's setuid root privileges there (that would
be best, but also the most work (if any work is needed in the first
place -- maybe the code already does this)).

> 
> What we really need is some kernel support for graphics cards...
We've got X, of cource -- I see svgalib only for the die-hards.


Anyway, here is the code that I have at the moment (not tested as yet):

/* Description: wrapper of gs to correct papersize (/etc/papersize).
   Copyright: GPL
   Author: joost witteveen, joostje@debian.org


   Security concerns:
    those using svgalib often, will want to make /usr/bin/gs setuid --
    This isn't very wise in a multy user environment, but this wrapper
    adds "-dSAFER" to the beginning of the argument list, wich
    will close the most obvious security holes, see gs(1).
    I'm not sure wether a user is able to override this, or wether
    "-dSAFER" is enough to make things safe.

   If this wrapper assesses that no setuid root privilages are needed,
   it gives them up. This will not protect against local holigans,
   but it will protect you against for example web sites with
   malicious ps files.
  */
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include "papersize.h"

#define BINARY "/usr/bin/gs-papersize"
char unpaper[]="Warning: unknown papersize in /etc/papersize\n";
char no_exec[]="Could not exec " BINARY;
char no_suid[]=
"You're trying to run gs on a linux console, presumably using\n"
"the vga libaries. For this to work, /usr/bin/gs needs to be\n"
"setuid root (\"chmod u+s /usr/bin/gs\"); see for security\n"
"issues /usr/doc/gs/setuid\n";

void add_argument(char ***as,char *s){  
  int l;
  char **a=*as;
  for(l=0;a&&a[l];l++);
  *as=(char **) malloc(sizeof(char *)*(l+2));
  (*as)[0]=a[0];
  (*as)[1]=s;
  (*as)[l+1]=NULL;
  while(--l)
    (*as)[l+1]=a[l];
  /*  free(a);*/
}

void main (int argc, char ** argv){
  int f,l=-1;
  char b[100];
  char *s;
  int need_setuid=0;
  
  /*check value of /etc/papersize */
  if((f=open("/etc/papersize",O_RDONLY))){
    if((l=read(f,b,sizeof(b)-1))>1){
      b[l]=0;
      if((s=strchr(b,'\n')))
	*s=0;
      for(l=0;papersizes[l]&&strcasecmp(papersizes[l],b);l++);
      if(papersizes[l]){
	strcpy(b,"-sPAPERSIZE=");
	strcat(b,papersizes[l]);
	add_argument(&argv,b);
      }
      else
	write(2,unpaper,strlen(unpaper));
    }
  }
  /*if running on console, prepare gs for it*/
  if(!strcmp("linux",getenv("TERM"))){
    for(l=1;argv[l];l++)
      if(strncmp(argv[l],"-sDEVICE=",9)){
	if(strcmp(argv[l],"-sDEVICE=lvga256")&&
	   strcmp(argv[l],"-sDEVICE=vgalib"))
	  break;
	else
	  need_setuid=1;
      }
    }
    if(!argv[l])
      need_setuid=1;
  }
  if(need_setuid){
    if(!geteuid()&&(getuid())){
      add_argument(&argv,"-dSAFER"); 
    }
    if(!geteuid()&&getuid())
      write(2,no_suid,strlen(no_suid));
  }
  else
    seteuid(getuid());
  
  /*
  for(l=0;argv[l];l++)
    printf("ARGUMENT %i =\"%s\"\n",l,argv[l]);
  printf("Effective uid=%i, uid=%i\n",geteuid(),getuid());
  */
  execv(BINARY,argv);
  write(2,no_exec,strlen(no_exec));
}



-- 
joost witteveen
            joost@rulcmc.leidenuniv.nl
          joostje@debian.org
--
Use Debian Linux!


Reply to: