/* drop_gid.c - scaled down version of my [e|fs|s|][ug]id behavior checker */
/* su ; gcc -o dg drop_gid.c ; chmod 2555 dg ; su user ; ./dg */
/* The test is: can we recover some privileges after setgid() ? */
 
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#define LINUX
 
int
main (void) {
  uid_t uid, euid, suid, TARGETID;
  gid_t gid, egid, sgid;
  TARGETID=getgid();
				 
  printf("uid=%d, euid=%d, gid=%d, egid=%d\n", getuid(), geteuid(), getgid(), getegid());
#ifdef LINUX
  getresuid(&uid, &euid, &suid);
  getresgid(&gid, &egid, &sgid);
  printf("--> suid=%d and sgid=%d\n", suid, sgid);
#endif
  printf("Dropping privileges...\n");
  if (setgid(TARGETID))
    perror("setgid");
  if (setuid(TARGETID))
    perror("setuid");
  printf("Privileges dropped : uid=%d, euid=%d, gid=%d, egid=%d\n", getuid(), geteuid(), getgid(), getegid());
#ifdef LINUX
  if (getresuid(&uid, &euid, &suid))
    perror("getresuid");
  if (getresgid(&gid, &egid, &sgid))
    perror("getresgid");
  printf("--> suid=%d and sgid=%d\n", suid, sgid);
#endif
  if (setegid(0))
    perror("setegid");
  if (setfsgid(0))
    perror("setfsgid");
  if (setgid(0))
    perror("setgid");
																		 
  printf("After trying to recover here is what we've got: uid=%d, euid=%d, gid=%d, egid=%d\n", getuid(), geteuid(), getgid(), getegid());
  return 0;
}

