From: gisle@ifi.uio.no (Gisle Hannemyr)
Newsgroups: comp.unix.questions
Subject: Summary: Protecting against SIGKILL (kill -9).
Date: 17 Aug 92 17:33:53 GMT
Organization: gisle@ifi.uio.no
Originator: gisle@gyda.ifi.uio.no

Some time ago I posted the following question to comp.unix questions:

> Is there a way to protect a process from being killed by the user
> who started it in a hostile environment.  I.e. is it possible to
> create a program that can be started by anyone, but only killed
> by root.

I received responses from the following 17 programmers:

	graham@castle.edinburgh.ac.uk
	leo@ine.philips.nl
	warren@itexjct.jct.ac.il (Warren Burstein)
	cedman@714-725-3177.nts.uci.edu (Carl Edman)
	Barry Margolin <barmar@Think.COM>
	dvsc-a@minster.york.ac.uk
	hello@cs.utwente.nl (Ronald Hello)
	<rthomas@hakatac.almanac.bc.ca>
	Robin Pickering <rob@inmos.co.uk>
	matthews@oberon.umd.edu (Mike Matthews)
	bof@midget.saar.de (John Bof)
	amf@amfent.gwinnett.com (Andy Feibus)
	Paul Foster <pfoster@gucis.cit.gu.edu.au>
	fazc016@hq.dla.mil (Don Costello)
	baur@mdcbbs.com
	bjst@sth.frontec.se (Bjorn Stenberg)
	bar@bbma.uucp (Joachim Bartsch)

Thank you very much!

Most noted this could be accomplished by having both the real and
effective user ID of the process set to a different uid than the
invoking user.  How you actually do this depends on what flavour
of Unix you are running.

Below is the simplest method that worked on SunOS 4.1.1:

1) Install signal handlers for all trappable signals.  This
   only leaves SIGKILL to be dealt with specially.
2) Make the program call setuid(3) to set the real user ID equal to
   the effective user ID.
3) Install the program setuid to user "daemon" (this will make
   it run with the effective user id "daemon").

-----cut here-----------------------------------------------------------
/* batman.c
+-----------------------------------------------------------------------
| Abstract:
|    Example of program that can't be killed by invoking user.
|    If installed setuid, this program can only be terminated by root
|    sending SIGTERM ( # kill -TERM batman ).
|
| Environment:
|    Tested on SunOS 4.1.1.  Portability unknown.
|
| Compilation:
|    # gcc -o batman batman.c
|    # chown daemon.daemon batman
|    # chmod 4755 batman
+---------------------------------------------------------------------*/

#include <stdio.h>
#include <signal.h>

int signalhandler(int signo, int code, struct sigcontext *scp, char *addr)
{
    signal(signo, SIG_IGN); /* disable */
    switch (signo) {
      case SIGHUP:
	fputs("Hup!!\n", stderr);
	break;
      case SIGINT:
	fputs("Ouch!\n", stderr);
	break;
      case SIGQUIT:
	fputs("It hurts!\n", stderr);
	break;
      default:
	fprintf(stderr,"*** Unexpected SIG: %d %d\n",signo, code);
    } /* switch */
    (void) signal(signo, signalhandler);
    return (0);
} /* signalhandler */


main()
{
    int uid, eid, oid;
    char buffer[3];

    oid = getuid();
    eid = geteuid();
    if (setuid(eid)) fputs("*** setuid failed\n", stderr);
    uid = getuid();
    eid = geteuid();

    signal(SIGHUP,  signalhandler);	/* install handler */
    signal(SIGINT,  signalhandler);	/* install handler */
    signal(SIGQUIT, signalhandler);	/* install handler */

    printf("Started by user %d, \
now real id = %d, effective id = %d\n", oid, uid, eid);

    fputs("Hah Joker -- can you kill me?\n", stdout);
    for (;;) {
	sleep(5);
	fputs("... I'm waiting for you ...\n", stderr);
    } /* forever */
    /* NOTREACHED */
} /* main */

/* EOF */
--
Disclaimer: My employer seldom even LISTENS to my opinion.
 
- gisle hannemyr  (Norsk Regnesentral)
  OSI:   C=no;PRMD=uninett;O=nr;S=Hannemyr;G=Gisle (X.400 SA format)
         gisle.hannemyr@nr.no                      (RFC-822  format)
  Inet:  gisle@ifi.uio.no
  UUCP:  ...!mcsun!ifi!gisle
------------------------------------------------