// SPDX-License-Identifier: GPL-2.0
#define _GNU_SOURCE
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <linux/types.h>
#include <sys/wait.h>
#include <sys/syscall.h>
#include <sys/user.h>
#include <sys/mman.h>

#include "linux/ptrace.h"

static int sys_rt_sigqueueinfo(pid_t tgid, int sig, siginfo_t *uinfo)
{
	return syscall(SYS_rt_sigqueueinfo, tgid, sig, uinfo);
}

static int sys_rt_tgsigqueueinfo(pid_t tgid, pid_t tid,
					int sig, siginfo_t *uinfo)
{
	return syscall(SYS_rt_tgsigqueueinfo, tgid, tid, sig, uinfo);
}

static int sys_ptrace(int request, pid_t pid, void *addr, void *data)
{
	return syscall(SYS_ptrace, request, pid, addr, data);
}

#define SIGNR 10
#define TEST_SICODE_PRIV	-1
#define TEST_SICODE_SHARE	-2

#ifndef PAGE_SIZE
#define PAGE_SIZE sysconf(_SC_PAGESIZE)
#endif

#define err(fmt, ...)						\
		fprintf(stderr,					\
			"Error (%s:%d): " fmt,			\
			__FILE__, __LINE__, ##__VA_ARGS__)

static int check_error_paths(pid_t child)
{
	struct ptrace_peeksiginfo_args arg;
	int ret, exit_code = -1;
	void *addr_rw, *addr_ro;

	/*
	 * Allocate two contiguous pages. The first one is for read-write,
	 * another is for read-only.
	 */
	addr_rw = mmap(NULL, 2 * PAGE_SIZE, PROT_READ | PROT_WRITE,
				MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
	if (addr_rw == MAP_FAILED) {
		err("mmap() failed: %m\n");
		return 1;
	}

	addr_ro = mmap(addr_rw + PAGE_SIZE, PAGE_SIZE, PROT_READ,
			MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
	if (addr_ro == MAP_FAILED) {
		err("mmap() failed: %m\n");
		goto out;
	}

	arg.nr = SIGNR;
	arg.off = 0;

	/* Unsupported flags */
	arg.flags = ~0;
	ret = sys_ptrace(PTRACE_PEEKSIGINFO, child, &arg, addr_rw);
	if (ret != -1 || errno != EINVAL) {
		err("sys_ptrace() returns %d (expected -1),"
				" errno %d (expected %d): %m\n",
				ret, errno, EINVAL);
		goto out;
	}
	arg.flags = 0;

	/* A part of the buffer is read-only */
	ret = sys_ptrace(PTRACE_PEEKSIGINFO, child, &arg,
					addr_ro - sizeof(siginfo_t) * 2);
	if (ret != 2) {
		err("sys_ptrace() returns %d (expected 2): %m\n", ret);
		goto out;
	}

	/* Read-only buffer */
	ret = sys_ptrace(PTRACE_PEEKSIGINFO, child, &arg, addr_ro);
	if (ret != -1 && errno != EFAULT) {
		err("sys_ptrace() returns %d (expected -1),"
				" errno %d (expected %d): %m\n",
				ret, errno, EFAULT);
		goto out;
	}

	exit_code = 0;
out:
	munmap(addr_rw, 2 * PAGE_SIZE);
	return exit_code;
}

int check_direct_path(pid_t child, int shared, int nr)
{
	struct ptrace_peeksiginfo_args arg = {.flags = 0, .nr = nr, .off = 0};
	int i, j, ret, exit_code = -1;
	siginfo_t siginfo[SIGNR];
	int si_code;

	if (shared == 1) {
		arg.flags = PTRACE_PEEKSIGINFO_SHARED;
		si_code = TEST_SICODE_SHARE;
	} else {
		arg.flags = 0;
		si_code = TEST_SICODE_PRIV;
	}

	for (i = 0; i < SIGNR; ) {
		arg.off = i;
		ret = sys_ptrace(PTRACE_PEEKSIGINFO, child, &arg, siginfo);
		if (ret == -1) {
			err("ptrace() failed: %m\n");
			goto out;
		}

		if (ret == 0)
			break;

		for (j = 0; j < ret; j++, i++) {
			if (siginfo[j].si_code == si_code &&
			    siginfo[j].si_int == i)
				continue;

			err("%d: Wrong siginfo i=%d si_code=%d si_int=%d\n",
			     shared, i, siginfo[j].si_code, siginfo[j].si_int);
			goto out;
		}
	}

	if (i != SIGNR) {
		err("Only %d signals were read\n", i);
		goto out;
	}

	exit_code = 0;
out:
	return exit_code;
}

int main(int argc, char *argv[])
{
	siginfo_t siginfo;
	int i, exit_code = 1;
	sigset_t blockmask;
	pid_t child;

	sigemptyset(&blockmask);
	sigaddset(&blockmask, SIGRTMIN);
	sigprocmask(SIG_BLOCK, &blockmask, NULL);

	child = fork();
	if (child == -1) {
		err("fork() failed: %m");
		return 1;
	} else if (child == 0) {
		pid_t ppid = getppid();
		while (1) {
			if (ppid != getppid())
				break;
			sleep(1);
		}
		return 1;
	}

	/* Send signals in process-wide and per-thread queues */
	for (i = 0; i < SIGNR; i++) {
		siginfo.si_code = TEST_SICODE_SHARE;
		siginfo.si_int = i;
		sys_rt_sigqueueinfo(child, SIGRTMIN, &siginfo);

		siginfo.si_code = TEST_SICODE_PRIV;
		siginfo.si_int = i;
		sys_rt_tgsigqueueinfo(child, child, SIGRTMIN, &siginfo);
	}

	if (sys_ptrace(PTRACE_ATTACH, child, NULL, NULL) == -1)
		return 1;

	waitpid(child, NULL, 0);

	/* Dump signals one by one*/
	if (check_direct_path(child, 0, 1))
		goto out;
	/* Dump all signals for one call */
	if (check_direct_path(child, 0, SIGNR))
		goto out;

	/*
	 * Dump signal from the process-wide queue.
	 * The number of signals is not multible to the buffer size
	 */
	if (check_direct_path(child, 1, 3))
		goto out;

	if (check_error_paths(child))
		goto out;

	printf("PASS\n");
	exit_code = 0;
out:
	if (sys_ptrace(PTRACE_KILL, child, NULL, NULL) == -1)
		return 1;

	waitpid(child, NULL, 0);

	return exit_code;
}
