clinuxsusetuid

Linux C programming execute as user


I have an program which I run as root. I would like the program to execute another application as a normal user. I tried setgid() and it works, but I can't then go back to root or another user. The program for the time being is very simple;

 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>

 int main(int argc, char *argv[] )
 {
     if ( argc != 2) {
         printf("usage: %s command\n",argv[0]);
         exit(1);
     }
     setgid(100);
     setuid(1000);
     putenv("HOME=/home/caroline");
     putenv("DISPLAY=:0");
     system(argv[1]);
     seteuid(1001);
     putenv("HOME=/home/john");
     putenv("DISPLAY=:1");
     system(argv[1]);
     return 0;
 }

How can I do this? It's like the action of command su $user-c $command


Solution

  • If you use fork+exec you can change euid of the child process while staying as root in the parent. The code could look something like this:

     #include <stdio.h>
     #include <unistd.h>
     #include <stdlib.h>
    
     int runAs(int gid, int uid, char **env, char *command) {
       int status;
       int child = fork();
       if (child == 0) {
        setgid(gid);
         setuid(uid);
         do {
           putenv(*env);
           env++;
         } while (env != null);
         exec(command);
       } else if (child > 0) {
        waitpid(child,&status,WUNTRACED | WCONTINUED);
       } else {
         // Error: fork() failed!
       }
     }
           
    
     int main(int argc, char *argv[] )
     {
         char *env[3];
         if ( argc != 2) {
             printf("usage: %s command\n",argv[0]);
             exit(1);
         }
         env[0] = "HOME=/home/caroline";
         env[1] = "DISPLAY=:0";
         env[2] = NULL;
         runAs(100, 1000, env, argv[1]);
    
         env[0] = "HOME=/home/john";
         env[1] = "DISPLAY=:1";
         runAs(100, 1001, env, argv[1]);
         return 0;
     }