TITLE: Make xconsole work (v.02) LFS VERSION: all AUTHOR: Matthias S. Benkmann SYNOPSIS: xconsole gave me a lot of trouble. It wouldn't work when started as a normal user, even when made setuid root. And when reading from /dev/console (default) it intercepted keystrokes intended for xterm windows. If you have the same problems, read this hint. HINT: I checked out a SuSE system and saw that they did not have xconsole read from /dev/console. Instead is was set up to read from a FIFO /dev/xconsole that was fed by syslogd. This has the advantage that you can use syslog.conf to control exactly which messages you want to be displayed by xconsole. To set it up like this do the following: 1. Create the /dev/xconsole FIFO mkfifo /dev/xconsole chmod 640 /dev/xconsole chown root.tty /dev/xconsole 2. Tell syslogd to write messages to /dev/xconsole by adding a line like the following to /etc/syslog.conf *.err;auth,authpriv.none |/dev/xconsole This will write all messages with priority err or higher to /dev/xconsole, with the exception of auth and authpriv messages (because these may contain secret data). Now you can start xconsole like this xconsole -file /dev/xconsole and it will use the FIFO. The above fixes the strange keystroke-grabbing problems. There still remains the problem that xconsole only works when started by root. Neither making it setuid root nor setgid tty will help. A look at the source code reveals the reason for this. xconsole uses the access() function to test if it can access the file it's told to read from. Unfortunately access() only checks the real uid and not the effective uid of the process, and setuid root only changes the effective uid. The reason for this is probably that otherwise a setuid root xconsole could be used to spy on other users. To work around this issue I wrote the following program: ------------------- begin startxconsole.c ----------------------------------- #include #include #include #include #include #include #include #include #include int main() { int i, fd; struct passwd* pw; char* xauth; char* env[32]; /* set XAUTHORITY to real home directory of user instead of allowing user to specify something */ pw=getpwuid(getuid()); if (pw==NULL) {perror("getpwuid"); return 1;}; xauth=malloc(strlen(pw->pw_dir)+128); if (xauth==NULL) {perror("malloc"); return 1;}; strcpy(xauth,"XAUTHORITY="); strcat(xauth,pw->pw_dir); strcat(xauth,"/.Xauthority"); /* empty environment (except for std path, DISPLAY and XAUTHORITY) */ env[0]="PATH=/bin:/usr/bin"; env[1]="DISPLAY=:0.0"; env[2]=xauth; env[3]=NULL; /* reset signal handlers to default */ for (i = 1; i < NSIG; i++) signal (i, SIG_DFL); /* stdin="/dev/null" (to prevent users from passing insecure data) */ close(0); if ( open("/dev/null",O_RDONLY) != 0 ) { fprintf(stderr,"Unable to redirect /dev/null -> stdin\n"); return 1; }; /* close all fds except stdin,stdout,stderr (just for paranoia) */ i = getdtablesize (); for (fd = 3; fd < i; ++fd) close (fd); /* set real ids to effective ids */ setreuid(geteuid(),geteuid()); setregid(getegid(),getegid()); execle("/usr/X11R6/bin/xconsole","xconsole","-file","/dev/xconsole", "-notify","-verbose","-geometry","-0-0",NULL,env); perror("/usr/X11R6/bin/xconsole"); return 1; }; ------------------- end startxconsole.c ----------------------------------- Compile it with gcc -W -Wall -O2 -o startxconsole startxconsole.c startxconsole makes setuid and setgid behave as expected. So you can do the following: chgrp tty startxconsole chmod g+s startxconsole and you can call startxconsole as a normal user (you should probably put it into xinitrc) and it will start up xconsole. Note that for security reasons, startxconsole has the command line for xconsole hardwired. That way users can't pass their own arguments to xconsole. If they were allowed to pass their own arguments they could specify some other user's tty device as -file to spy on this user. In addition to this startxconsole always sets the location of the .Xauthority file (via the XAUTHORITY environment variable) to /.Xauthority where is the home directory of the calling user. This makes sure that a user can't use XAUTHORITY to cause a read access to a file not belonging to him. DISPLAY is always set to :0.0. All other environment variables are removed (or rather, not passed to xconsole), signal handlers are reset to the default, stdin is set to /dev/null and all other file descriptors except for stdout and stderr are closed. This should eliminate every possibility for the user to pass insecure data to xconsole.