Thread: Having issues with killing suid programs

  1. #1
    Banned
    Join Date
    May 2007
    Location
    Berkeley, CA
    Posts
    329

    Having issues with killing suid programs

    I have 2 processes called A and B. I currently kill the processes like the following

    Code:
    void
    kill_sessions(int count)
    {
      int i;
      int j;
      int max;
      max = 20;
    
      /*This does properly kill processes that forked suid programs*/
      for(i = (count-1); i > 0; i--){
        (void)kill(uinfo[i].pid, SIGHUP);
        /*if((kill(uinfo[i].pid, 0)) == -1 && errno == ESRCH)
          break;*/
      }
    }
    This is good if process A and process B only have a shell. The functions sends SIGHUP and the person gets logged off. However, if process B executes some kind of suid program, then the above function will kill the suid program. When this happens, process B will still have the shell.

    How would I find out all suid programs that process B executes when I don't have root privs? I figure if I know many many suid programs proces B executes, I could just kill each one of them, one by one.

  2. #2
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    The suid programs may run on a higher privilege level than you (if they suid to root). It shouldn't be possible to kill them.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  3. #3
    Banned
    Join Date
    May 2007
    Location
    Berkeley, CA
    Posts
    329
    Quote Originally Posted by CornedBee View Post
    The suid programs may run on a higher privilege level than you (if they suid to root). It shouldn't be possible to kill them.
    That doesn't answer my question....

    Here is the entire program. If a person has a regular user account on OpenBSD 4.1, then this program will kill programs that suid to root. I don't think this will compile on Linux or FreeBSD.

    Code:
    #include <sys/types.h>
    #include <sys/param.h>
    #include <sys/stat.h>
    #include <sys/sysctl.h>
    #include <sys/user.h>
    
    #include <utmp.h>
    #include <paths.h>
    #include <limits.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <pwd.h>
    #include <fcntl.h>
    #include <string.h>
    #include <time.h>
    #include <stdlib.h>
    #include <signal.h>
    
    /*If you get to this number, then you really shouldn't be using this program*/
    #define MAX_USERS 19
    
    typedef struct {
      uid_t uid; 
      dev_t dev;
      pid_t pid;
      struct utmp in_login;
    }uinfo_t;
    
    uinfo_t         uinfo[MAX_USERS];
         
    int get_user_info(char *);
    void get_uid(char *, uinfo_t *);
    int get_my_pid(uinfo_t *);
    struct passwd *get_my_name(void);
    int compare (const void *, const void *);
    void find_sessions_to_kill(int );
    void kill_sessions(int n);
    
    /*Fill in the login fields*/
    int 
    get_user_info(char *user)
    {
      static struct utmp logins;
      static int         fd;
      static char        tty[MAXPATHLEN];
      static int         n;
       
      n = 0;
    
      if(( fd = open(_PATH_UTMP, O_RDONLY)) < 0){
        return -1;
      }
    
      while(read(fd, &logins, sizeof(logins)) == sizeof(logins)) {
        if (strncmp(logins.ut_name, user, UT_NAMESIZE)) {
          continue;   
        }
    
        (void)snprintf(tty, sizeof(tty), "%s/%s", _PATH_DEV,  
                       logins.ut_line);
        uinfo[n].in_login = logins;
        get_uid(tty, &uinfo[n++]);
      }
      close(fd);
      return n; 
    }
    
    /*Fill in the uid field*/
    void 
    get_uid(char *tty, uinfo_t *uinfo)
    {
      static struct stat s;
      static int i;
    
      if(stat(tty, &s) < 0){
        fprintf(stderr, "no tty\n");
        return;
      } 
     
      uinfo->dev  = s.st_rdev;
      uinfo->uid  = s.st_uid;
    
      if(get_my_pid(&uinfo[i++])){
        fprintf(stderr, "can't get pids\n");
        return;
        } 
    
    }
    
    /*Fill in the pid field. */
    int
    get_my_pid(uinfo_t *tty)
    {
      int mib[4];
      static int        i;
      size_t            len;
      struct kinfo_proc *p;
    
      mib[0] = CTL_KERN;
      mib[1] = KERN_PROC;
      mib[2] = KERN_PROC_TTY;
      mib[3] = uinfo[i].dev;
    
      len = 0;
      if (sysctl(mib, sizeof(mib)/sizeof(int), NULL , &len, NULL, 0) == -1)
        {
          perror("sysctl test");
          return 1;
        }
        
      p =(struct kinfo_proc *)malloc(len);
      if (sysctl(mib, sizeof(mib)/sizeof(int), p, &len, NULL, 0) == -1)
        {
          perror("sysctl real");
          return 1;
        }
      
      uinfo[i++].pid = p->kp_proc.p_pid;
      free(p);
      return 0;
    }
    
    struct passwd *
    get_my_name(void)
    { 
      struct passwd *pw;
     
      /*I'm not that sure of the difference between guest and regular accounts.*/
      if((pw = getpwnam(getlogin()))== NULL ){
        return NULL; 
      }
      return pw;
    }
    
    int 
    compare (const void *a, const void *b)
    {
      /*const struct utmp *ma = *(const struct utmp *const*)a;
        const struct utmp *mb = *(const struct utmp *const*)b;*/
    
      const struct utmp *ma = a;
      const struct utmp *mb = b;
      int32_t time1, time2;
      time1 = ma->ut_time; 
      time2 = mb->ut_time;
     
      if(time1 < time2)
        return -1;
      else if(time1 > time2)
        return 1;
      else
        return 0;
    }
    
    void 
    print_session(int count)
    {
      int i;
      for(i = 0; i < count; i++)
        printf("name: %s, tty: %s\n", uinfo[i].in_login.ut_name, uinfo[i].in_login.ut_line);
    }
    
    void 
    find_sessions_to_kill(int count){
      qsort(uinfo,
            count,
            sizeof(struct utmp),
            compare
            );
      print_session(count);
      kill_sessions(count);
    }
    
    /*I only want to kill interactive sessions */
    void 
    kill_sessions(int count)
    {
      int i;
      int j;
      int max;
      max = 20;
    
      /*This does properly kill processes that forked suid programs*/
      for(i = (count-1); i > 0; i--){
        (void)kill(uinfo[i].pid, SIGHUP);
        /*if((kill(uinfo[i].pid, 0)) == -1 && errno == ESRCH)
          break;*/
    
      }
    }
    
    int 
    main(void)
    {
      /*add error checking later on */
      struct passwd *name;
      int n;
    
      if((name = get_my_name()) == NULL)
        exit(1);    
    
      if((n=get_user_info(name->pw_name)) < 0)
         exit(1);
      if(n == 1 || n > MAX_USERS)
        exit(1);
      
      find_sessions_to_kill(n);
    
      exit(0);   
    }
    Again, if process B would execute a suid program, how would I kill both the suid program and the shell? I'm assuming I would have to test if the process is still alive. Ie, use something like

    Code:
    if((kill(uinfo[i].pid, 0)) == -1 && errno == ESRCH)
    The problem is that I don't know how many suid programs process B would be executing at once.

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Killing the parent process should automatically kill any child processes held by that process. But a suid'd process runs as a different user, which means that you as a regular user may not be able to kill it. There's not much you can do about that - other than getting root privileges of your own. This is of course on purpose, so that regular users can't kill processes owned by other users.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. how bad is killing bugged programs?
    By carlorfeo in forum C++ Programming
    Replies: 3
    Last Post: 02-21-2008, 11:42 PM
  2. Recommend upgrade path for C programs
    By emanresu in forum C Programming
    Replies: 3
    Last Post: 11-22-2007, 07:32 AM
  3. Reroute where programs write to
    By willc0de4food in forum C Programming
    Replies: 7
    Last Post: 09-21-2005, 04:48 PM
  4. POSIX/DOS programs?
    By nickname_changed in forum C++ Programming
    Replies: 1
    Last Post: 02-28-2003, 05:42 AM
  5. executing c++ programs on the web
    By gulti01 in forum C++ Programming
    Replies: 4
    Last Post: 08-12-2002, 03:12 AM