Skip to content

Instantly share code, notes, and snippets.

@andrewg-felinemenace
Created July 15, 2011 04:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrewg-felinemenace/1084042 to your computer and use it in GitHub Desktop.
Save andrewg-felinemenace/1084042 to your computer and use it in GitHub Desktop.
Per-thread user ids and capabilities
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/syscall.h>
/*
* This can be used to demonstrate a grsecurity chroot_findtask bug, recent glibc cross thread
* signalling on set*id, and or native per-thread privilege ids if using a non glibc or non
* recent glibc.
*
* use /tmp/repro anything to test via raw syscall() to see how glibc changes things.
*
* ubuntu 11.04, just for qemu folks :)
*
* # /tmp/r
* dropping via libc setuid/setgid
* --> modern glibc will apply to all threads
* [main] my [ug]id is 100/100
* [thread] my [ug]id is 100/100
* # /tmp/r proof
* dropping via raw syscall setgid/setuid
* [main] my [ug]id is 100/100
* [thread] my [ug]id is 0/0
*/
// recent glibc, chroot_findtask = 1
// # /tmp/repro
// [main] my [ug]id is 100/100
// [thread] my [ug]id is 0/0
// recent glibc, chroot_findtask = 0
// # /tmp/repro
// [main] my [ug]id is 100/100
// [thread] my [ug]id is 100/100
// uclibc, chroot_findtask = 1
// # ./repro
// [main] my [ug]id is 100/100
// [thread] my [ug]id is 0/0
// uclibc, chroot_findtask = 0
// # ./repro
// [main] my [ug]id is 100/100
// [thread] my [ug]id is 0/0
int run; // trivial spin lock. lazy, I know.
int raw_syscall;
void *dumpprivs(void *arg)
{
while(! run);
printf("[thread] my [ug]id is %d/%d\n", getuid(), getgid());
exit(1);
}
int main(int argc, char **argv)
{
int rc;
pthread_t id;
raw_syscall = argc > 1;
pthread_create(&id, NULL, dumpprivs, NULL);
chroot("/var/empty");
if(raw_syscall) {
printf("dropping via raw syscall setgid/setuid\n");
syscall(SYS_setgid, 100);
syscall(SYS_setuid, 100);
} else {
printf("dropping via libc setuid/setgid\n");
printf("--> modern glibc will apply to all threads\n");
setgid(100);
setuid(100);
}
printf("[main] my [ug]id is %d/%d\n", getuid(), getgid());
run = 1;
while(run);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment