Question

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

Was it helpful?

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(100);
     setuid(1000);
     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;
 }

OTHER TIPS

If you want to do one thing as a normal user and another as root then you can always fork and setuid in the child process that you want to not have root privileges while retaining them for the other part of your program.

From setuid manual: [if caller was root] it is impossible for the program to regain root privileges.

What are you trying to do? You could set SUID-bit to your program and run it as user - then you could use seteuid to temporary drop root priveleges and become calling user, then reset privileges again. If you really have to run it as root - my guess is that you should fork(), leaving one process as root, and another as setuid().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top