// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright 2022 Google LLC
 */
#define _GNU_SOURCE
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <sys/wait.h>
#include <unistd.h>
#include <asm-generic/unistd.h>
#include "vm_util.h"
#include "../kselftest.h"

#define MB(x) (x << 20)
#define MAX_SIZE_MB 1024

static int alloc_noexit(unsigned long nr_pages, int pipefd)
{
	int ppid = getppid();
	int timeout = 10; /* 10sec timeout to get killed */
	unsigned long i;
	char *buf;

	buf = (char *)mmap(NULL, nr_pages * psize(), PROT_READ | PROT_WRITE,
			   MAP_PRIVATE | MAP_ANON, 0, 0);
	if (buf == MAP_FAILED) {
		perror("mmap failed, halting the test");
		return KSFT_FAIL;
	}

	for (i = 0; i < nr_pages; i++)
		*((unsigned long *)(buf + (i * psize()))) = i;

	/* Signal the parent that the child is ready */
	if (write(pipefd, "", 1) < 0) {
		perror("write");
		return KSFT_FAIL;
	}

	/* Wait to be killed (when reparenting happens) */
	while (getppid() == ppid && timeout > 0) {
		sleep(1);
		timeout--;
	}

	munmap(buf, nr_pages * psize());

	return (timeout > 0) ? KSFT_PASS : KSFT_FAIL;
}

/* The process_mrelease calls in this test are expected to fail */
static void run_negative_tests(int pidfd)
{
	int res;
	/* Test invalid flags. Expect to fail with EINVAL error code. */
	if (!syscall(__NR_process_mrelease, pidfd, (unsigned int)-1) ||
			errno != EINVAL) {
		res = (errno == ENOSYS ? KSFT_SKIP : KSFT_FAIL);
		perror("process_mrelease with wrong flags");
		exit(res);
	}
	/*
	 * Test reaping while process is alive with no pending SIGKILL.
	 * Expect to fail with EINVAL error code.
	 */
	if (!syscall(__NR_process_mrelease, pidfd, 0) || errno != EINVAL) {
		res = (errno == ENOSYS ? KSFT_SKIP : KSFT_FAIL);
		perror("process_mrelease on a live process");
		exit(res);
	}
}

static int child_main(int pipefd[], size_t size)
{
	int res;

	/* Allocate and fault-in memory and wait to be killed */
	close(pipefd[0]);
	res = alloc_noexit(MB(size) / psize(), pipefd[1]);
	close(pipefd[1]);
	return res;
}

int main(void)
{
	int pipefd[2], pidfd;
	bool success, retry;
	size_t size;
	pid_t pid;
	char byte;
	int res;

	/* Test a wrong pidfd */
	if (!syscall(__NR_process_mrelease, -1, 0) || errno != EBADF) {
		res = (errno == ENOSYS ? KSFT_SKIP : KSFT_FAIL);
		perror("process_mrelease with wrong pidfd");
		exit(res);
	}

	/* Start the test with 1MB child memory allocation */
	size = 1;
retry:
	/*
	 * Pipe for the child to signal when it's done allocating
	 * memory
	 */
	if (pipe(pipefd)) {
		perror("pipe");
		exit(KSFT_FAIL);
	}
	pid = fork();
	if (pid < 0) {
		perror("fork");
		close(pipefd[0]);
		close(pipefd[1]);
		exit(KSFT_FAIL);
	}

	if (pid == 0) {
		/* Child main routine */
		res = child_main(pipefd, size);
		exit(res);
	}

	/*
	 * Parent main routine:
	 * Wait for the child to finish allocations, then kill and reap
	 */
	close(pipefd[1]);
	/* Block until the child is ready */
	res = read(pipefd[0], &byte, 1);
	close(pipefd[0]);
	if (res < 0) {
		perror("read");
		if (!kill(pid, SIGKILL))
			waitpid(pid, NULL, 0);
		exit(KSFT_FAIL);
	}

	pidfd = syscall(__NR_pidfd_open, pid, 0);
	if (pidfd < 0) {
		perror("pidfd_open");
		if (!kill(pid, SIGKILL))
			waitpid(pid, NULL, 0);
		exit(KSFT_FAIL);
	}

	/* Run negative tests which require a live child */
	run_negative_tests(pidfd);

	if (kill(pid, SIGKILL)) {
		res = (errno == ENOSYS ? KSFT_SKIP : KSFT_FAIL);
		perror("kill");
		exit(res);
	}

	success = (syscall(__NR_process_mrelease, pidfd, 0) == 0);
	if (!success) {
		/*
		 * If we failed to reap because the child exited too soon,
		 * before we could call process_mrelease. Double child's memory
		 * which causes it to spend more time on cleanup and increases
		 * our chances of reaping its memory before it exits.
		 * Retry until we succeed or reach MAX_SIZE_MB.
		 */
		if (errno == ESRCH) {
			retry = (size <= MAX_SIZE_MB);
		} else {
			res = (errno == ENOSYS ? KSFT_SKIP : KSFT_FAIL);
			perror("process_mrelease");
			waitpid(pid, NULL, 0);
			exit(res);
		}
	}

	/* Cleanup to prevent zombies */
	if (waitpid(pid, NULL, 0) < 0) {
		perror("waitpid");
		exit(KSFT_FAIL);
	}
	close(pidfd);

	if (!success) {
		if (retry) {
			size *= 2;
			goto retry;
		}
		printf("All process_mrelease attempts failed!\n");
		exit(KSFT_FAIL);
	}

	printf("Success reaping a child with %zuMB of memory allocations\n",
	       size);
	return KSFT_PASS;
}
