C program to kill root processes

Hello,
First let me start by saying I have searched the forum and read all the SUID stuff but it is not in the neighborhood I am looking for.

 Here is the problem.  We want to grant a non super-user permission to kill root processes but only if the process matches certain criteria.  This particular userID is what we use to run several maintenance and data gathering scripts on our systems.  The approach we have been taking is to write a C program that is owned by root with the SUID bit set for the user we want to have access to kill root processes.  

  The program accepts a PID and hostname.  It then verifies the PID is owned by root and is a remsh to the given hostname.  If it is, it will send a signal to the PID to kill it.  I am on Solaris 9 and have tried usign both kill\(\) and sigsend\(\) with no success.

  I have been reading on the web and I realize there have been some security changes in this area in the last few years. I do not see anything that would prevent this from working if the effective user is super-user.

  Anyone have any ideas?  If you have something similar I would love to see some code snippets, especially if you are setting the UID in the program.  If anyone can give a reference stating this is not possible, that is cool to.  We will explore sudo if that is the case.

Thanks,
Tony

Well, I agree with you....if the effective uid is root it should work.

If you are finding that it doesn't work, you must have a bug in your program.

Thanks for the reality check. If I get it working I will post the important parts so others can use it.

Here is most of the code minus the logic specific to my case. It may not be the cleanest way, but it works for me. I have more includes then are needed but that is for other stuff I am doing in the same binary. chmod 4555 with this does what I wanted.

#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

main(int argc, char *argv[] )
{
  int kill_ret;
  int pid;
  char cmd[200]="ps -ef |grep stuff I am looking for";
  char buf[BUFSIZ];
  char *output;
  FILE *ptr;

  if (argc <= 2) {
  usage:
      printf("usage: killremsh pid host\n");
      exit(2);
  }
  if ((ptr = popen(cmd, "r")) != NULL)
    while (fgets(buf, BUFSIZ, ptr) != NULL)
    {
      pid=atoi(argv[1]);
      kill_ret=sigsend(P_PID, pid , 9);
    }  
    (void) pclose(ptr);

code tags added for readability -- Perderabo

Are you sure that your program is working properly? It looks like you're repeatedly killing the same pid. Shouldn't you be getting your pid's from the output you're reading via popen?

Hi Perderabo,
The while loop only executes once in my case as my cmd only finds 1 matching pid based on the "stuff I am looking for". I agree that if it found more then one match, it would try to kill the same pid multiple times. If I have time down the road, I hope to clean this up quite a bit by either parsing the data from popen or by using the one of the structs mentioned in proc(4), but it works for what we need it to do today.
Thanks,
Tony

Even if the while executes only once, the output from the ps|grep is not dependent on the pid supplied as argument 1.

Thus if the target program is running (as verified by the ps|grep), the program will then attempt to kill whatever was supplied as argument 1.

I am actually doing more then just grepping there. I am first using sed to remove all spaces, then I grep for a "root<PID>" to ensure the PID is running and is owned by root. I also grep for 'remsh', 'date', and the host that was supplied. If all those exist in the same line, I can be 100% confident I have the correct PID and kill it. There will either be 1 match or none. If there are none, the while loop does not execute and nothing is killed. If there is one match, only the PID passed is killed exactly one time. This solution is probably pretty specific to our site and as I mentioned, I do intent to clean it up in the future.

hi