#include #include #include #include #include struct caph { int version; int pid; }; struct capd { __u32 effective; __u32 permitted; __u32 inheritable; }; gid_t gid = 1000; uid_t uid = 1000; void printcap(char *str) { int ret; struct caph caph; struct capd capd; memset(&capd, 0, sizeof(capd)); caph.version = 0x19980330; caph.pid = getpid(); ret = capget(&caph, &capd); if (ret < 0) perror("capget"); printf("%s: ", str); printf("eff:%u perm:%u inh:%u\n", capd.effective, capd.permitted, capd.inheritable); } void lower_uid() { int ret; gid_t gidlist[1]; gidlist[0] = gid; ret = setgroups(1, gidlist); if (ret < 0) perror("setgroups"); if (setgid(gid)) perror("setgid"); if (setuid(uid)) perror("setuid"); } const char *bash[] = { "bash", NULL }; int main(int argc, char **argv) { int ret; struct caph caph; struct capd capd; if (argc == 3) { uid = strtoul(argv[1], NULL, 0); gid = strtoul(argv[2], NULL, 0); } else { printf("Usage: \"./program uid gid\" where uid & gid\n"); printf("are the ids you want to change to (then run bash)\n"); exit(1); } printcap("caps when started"); memset(&capd, 0, sizeof(capd)); caph.version = 0x19980330; caph.pid = getpid(); ret = capget(&caph, &capd); if (ret < 0) perror("capget"); capd.inheritable |= (1 << CAP_CHOWN); ret = capset(&caph, &capd); if (ret < 0) perror("capset"); printf("new inheritable mask: %u\n", capd.inheritable); ret = prctl(PR_SET_KEEPCAPS, 1); if (ret) perror("prctl"); lower_uid(); printcap("after setuid"); ret = execv("/bin/bash", bash); if (ret < 0) perror("execve"); return 0; }