blob: 581c26270dfceb73955ce40718b4c010035f0813 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
#define _GNU_SOURCE
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/prctl.h>
#include <sys/user.h>
#include <sys/uio.h>
#include <asm/unistd.h>
#include "asm/process_vm_exec.h"
#include "linux/process_vm_exec.h"
#include "../kselftest.h"
#include "log.h"
#ifndef __NR_process_vm_exec
#define __NR_process_vm_exec 441
#endif
#ifndef PROCESS_VM_EXEC_SYSCALL
#define PROCESS_VM_EXEC_SYSCALL 0x1
#endif
#define TEST_VAL 0x1e511e51
int test_val = TEST_VAL;
int main(int argc, char **argv)
{
struct process_vm_exec_context ctx = {
.version = PROCESS_VM_EXEC_GOOGLE_V1,
};
unsigned long long sigmask;
int ret, p[2], val;
siginfo_t siginfo = {};
pid_t pid;
ksft_set_plan(1);
pid = fork();
if (pid < 0)
return pr_perror("fork");
if (pid == 0) {
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
kill(getpid(), SIGSTOP);
return 0;
}
test_val = 0;
if (pipe(p))
return pr_perror("pipe");
#if defined(__x86_64__)
ctx.sigctx.rax = __NR_write;
ctx.sigctx.rdi = p[1];
ctx.sigctx.rsi = (unsigned long) &test_val;
ctx.sigctx.rdx = sizeof(test_val);
ctx.sigctx.r10 = 0;
ctx.sigctx.r8 = 0;
ctx.sigctx.r9 = 0;
#elif defined(__aarch64__)
ctx.sigctx.regs[8] = __NR_write;
ctx.sigctx.regs[0] = p[1];
ctx.sigctx.regs[1] = (unsigned long) &test_val;
ctx.sigctx.regs[2] = sizeof(test_val);
ctx.sigctx.regs[3] = 0;
ctx.sigctx.regs[4] = 0;
ctx.sigctx.regs[5] = 0;
#endif
sigmask = 0xffffffff;
ret = syscall(__NR_process_vm_exec, pid, &ctx, PROCESS_VM_EXEC_SYSCALL,
&siginfo, &sigmask, 8);
if (ret != 0)
return pr_perror("process_vm_exec");
if (siginfo.si_signo != 0)
return pr_fail("unexpected signal: %d", siginfo.si_signo);
#if defined(__x86_64__)
if (ctx.sigctx.rax != sizeof(test_val))
pr_fail("unexpected rax: %lx", ctx.sigctx.rax);
#elif defined(__aarch64__)
if (ctx.sigctx.regs[0] != sizeof(test_val))
pr_fail("unexpected r0: %lx", ctx.sigctx.regs[0]);
#endif
if (kill(pid, SIGKILL))
return pr_perror("kill");
if (wait(NULL) != pid)
return pr_perror("kill");
if (read(p[0], &val, sizeof(val)) != sizeof(val))
pr_perror("read");
if (val != TEST_VAL)
pr_fail("unexpected data: %x", val);
ksft_test_result_pass("process_vm_exec(..., PROCESS_VM_EXEC_SYSCALL, ...) \n");
ksft_exit_pass();
return 0;
}