0

I have a project thant i want to use root to execute a program as a normal user.

first i have a normal user fgo whoes uid and gid is 501.

id fgo
[root@cpera test]# id fgo
uid=501(fgo) gid=501(fgo) groups=501(fgo)

here's the sample code

#define _GNU_SOURCE
#include <sched.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/capability.h>
#include <sys/resource.h>
#include <unistd.h> 
#include<stdlib.h>
#include <stdio.h>
#include <string.h>
int main( int argc,char *argv[]){ 
    while(setgid(501)!=0) sleep(1);
    while(setuid(501)!=0) sleep(1);
    printf("start to exec\n");
    execvp("/bin/sh",NULL);
}

compile and execute

gcc a.c && ./a.out

the output is:

[root@cpera test]# ./a.out 
start to exec
[fgo@cpera test]$ id
uid=501(fgo) gid=501(fgo) groups=501(fgo),0(root)

i googled it and find that the groups from id is called supplementary group inherited from the parent process.GID, current, primary, supplementary, effective and real group IDs?

how can i make root not in the groups of the sub process?

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
laughing
  • 13
  • 3
  • 1
    `while(setgid(501)!=0) sleep(1);` is wrong. If they return an error, it is most unlikely they will succeed for the next try with identical parameters. – too honest for this site Aug 01 '17 at 11:57
  • See (probably amongst others) [Is it legal to pass a null program argument vector to `execve()`?](https://stackoverflow.com/questions/45430087/is-it-legal-to-pass-a-null-program-argument-vector-to-execve). Granted, you're using `execvp()` and not `execve()`, but the discussion is essentially the same. You are invoking undefined behaviour and anything may happen (including "it seems to work OK"). – Jonathan Leffler Aug 01 '17 at 14:11
  • The `while` loops in the code are weird. If the first call to `setgid()` fails, every call will fail, and the program will sleep repeatedly until you kill it, or the machine stops running. Ditto the `setuid()` call. You should test the result of the `setgid()` and `setuid()` calls, but should report an error and exit if they fail. – Jonathan Leffler Aug 01 '17 at 14:14
  • the `while` is used to make the sample code short and concise. dont bother with that. – laughing Aug 02 '17 at 02:37

1 Answers1

1

Use setgroups() to reset the supplementary groups:

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

int main (int argc, char *argv[])
{ 
    if (setgroups (0, NULL) != 0) {
        perror ("setgroups");
        exit (1);
    }

    if (setgid (501) != 0) {
        perror ("setgid");
        exit (1);
    }

    if (setuid (501) != 0) {
        perror ("setuid");
        exit (1);
    }

    printf ("start to exec\n");

    if (execl ("/bin/sh", NULL) != 0) {
        perror ("execl");
    }

    return 1;
}
Erki Aring
  • 2,032
  • 13
  • 15