#include #include #include #include #include #include #include #include #include #include #include #define UID 65534 int adjust_priority() { struct sched_param sp; sp.sched_priority = sched_get_priority_max(SCHED_FIFO); if (sched_setscheduler(0, SCHED_FIFO, &sp) != -1) { printf("running as SCHED_FIFO, priority %d\n", sp.sched_priority); return 1; } else { puts("could not set SCHED_FIFO"); return 0; } } int change_uid() { if (setuid(UID)) { int err = errno; printf("setuid() failed: %s\n", strerror(err)); return 0; } printf("UID set to %d\n", UID); return 1; } void print_usage() { printf( "This program attempts to illustrate a way by which a process can hang and\n" "become unkillable:\n" "1. run as root\n" "2. set SCHED_FIFO\n" "3. change to a user with no realtime CPU share allocated\n" "\n" "The following kernel options must be set:\n" "CONFIG_GROUP_SCHED=y\n" "CONFIG_RT_GROUP_SCHED=y\n" "CONFIG_USER_SCHED=y\n" "\n" "Warning: do not try this under Linux 2.6.28. Due to a bug, you will not be\n" "able to write to cpu_rt_runtime:\n" "http://lkml.org/lkml/2009/1/14/113\n" "This appears to have been fixed in 2.6.29-rc2, but not yet in 2.6.28.5\n" "\n" "If you're running a 2.6.29-rc kernel, you should lower root's\n" "cpu_rt_runtime first:\n" "# echo 900000 > /sys/kernel/uids/0/cpu_rt_runtime\n" "\n" "usage: ./hangme [arg1 ...]\n" "example: ./hangme /bin/bash\n" "\n" "The executable specified should take some time to run, otherwise it may\n" "complete and exit normally within the current time slice (I assume).\n" "Running a shell is ideal.\n" ); } void print_msg() { printf( "\n" "I am now going to change my UID. See if I hang.\n" "If I do, try to kill me:\n" "# kill -9 %d\n" "Once you're ready to make me unhang:\n" "# echo 10000 > /sys/kernel/uids/%d/cpu_rt_runtime\n" "\n" "Note: if you get an \"Invalid argument\" error with 2.6.29-rc kernels,\n" "try lowering root's runtime like this:\n" "# echo 900000 > /sys/kernel/uids/0/cpu_rt_runtime\n" "...but it doesn't seem to work once this program is running!\n" "Is that another bug or do I misunderstand?\n" "\n" , getpid(), UID); } int main(int argc, char **argv) { if (argc <= 1) { print_usage(); return 2; } if (getuid()) { printf("this test only works when run as root\n"); return 2; } if (!adjust_priority()) { return 1; } print_msg(); if (! change_uid()) { return 1; } ++argv; printf("going to exec: %s\n", argv[0]); execv(argv[0], argv); printf("exec failed\n"); return 1; }