Skip to content

Instantly share code, notes, and snippets.

@sitano
Created September 18, 2023 09:35
Show Gist options
  • Save sitano/1faa57899abdf84bcb19bedf284a5cd8 to your computer and use it in GitHub Desktop.
Save sitano/1faa57899abdf84bcb19bedf284a5cd8 to your computer and use it in GitHub Desktop.
setuidgid playground but keeping caps
// $ clang -lcap -Wall -O2 ./setuidgid.c
#include <getopt.h>
#include <stdio.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <stdlib.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#include <linux/capability.h>
#include <sys/syscall.h>
#include <sys/capability.h>
void print_status(const char *a) {
printf("%s\n", a);
char str[1024];
FILE *ptr = fopen("/proc/self/status", "r");
while (fgets(str, 1024, ptr) != 0)
if (str[0] == 'C' && str[1] == 'a')
printf("%s", str);
fclose(ptr);
}
int
main (int argc, char **argv)
{
uid_t uid = 1000;
gid_t gids[1] = {1001};
const cap_value_t cap_list[1] = {CAP_SYS_ADMIN};
print_status("before setgroups()");
if (setgroups (1, gids))
fprintf (stderr, "failed to set supplemental group(s): %d\n", errno);
print_status("before setgid()");
if (setgid (gids[0]))
fprintf (stderr, "cannot set group-ID: %d\n", errno);
print_status("before before setuid()");
if (cap_setuid (uid))
fprintf (stderr, "cannot set user-ID: %d\n", errno);
print_status("before cap_set_proc()");
cap_t caps = cap_get_proc();
cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_list, CAP_SET);
cap_set_flag(caps, CAP_INHERITABLE, 1, cap_list, CAP_SET);
cap_set_proc(caps);
cap_free(caps);
cap_set_ambient(CAP_SYS_ADMIN, CAP_SET);
print_status("before execv()");
{
char **cmd = argv + 1;
int exit_status;
execvp (*cmd, cmd);
exit_status = errno;
fprintf (stderr, "failed to run command %s: %d\n", *cmd, errno);
exit (exit_status);
}
}
@sitano
Copy link
Author

sitano commented Sep 18, 2023

a drop of the inheritable caps also drops ambient. test with:

  caps = cap_get_proc();
  cap_set_flag(caps, CAP_INHERITABLE, 1, cap_list, CAP_CLEAR);
  cap_set_proc(caps);
  cap_free(caps);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment