18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2020 Bernd Edlinger <bernd.edlinger@hotmail.de>
48c2ecf20Sopenharmony_ci * All rights reserved.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Check whether /proc/$pid/mem can be accessed without causing deadlocks
78c2ecf20Sopenharmony_ci * when de_thread is blocked with ->cred_guard_mutex held.
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include "../kselftest_harness.h"
118c2ecf20Sopenharmony_ci#include <stdio.h>
128c2ecf20Sopenharmony_ci#include <fcntl.h>
138c2ecf20Sopenharmony_ci#include <pthread.h>
148c2ecf20Sopenharmony_ci#include <signal.h>
158c2ecf20Sopenharmony_ci#include <unistd.h>
168c2ecf20Sopenharmony_ci#include <sys/ptrace.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_cistatic void *thread(void *arg)
198c2ecf20Sopenharmony_ci{
208c2ecf20Sopenharmony_ci	ptrace(PTRACE_TRACEME, 0, 0L, 0L);
218c2ecf20Sopenharmony_ci	return NULL;
228c2ecf20Sopenharmony_ci}
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ciTEST(vmaccess)
258c2ecf20Sopenharmony_ci{
268c2ecf20Sopenharmony_ci	int f, pid = fork();
278c2ecf20Sopenharmony_ci	char mm[64];
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	if (!pid) {
308c2ecf20Sopenharmony_ci		pthread_t pt;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci		pthread_create(&pt, NULL, thread, NULL);
338c2ecf20Sopenharmony_ci		pthread_join(pt, NULL);
348c2ecf20Sopenharmony_ci		execlp("true", "true", NULL);
358c2ecf20Sopenharmony_ci	}
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	sleep(1);
388c2ecf20Sopenharmony_ci	sprintf(mm, "/proc/%d/mem", pid);
398c2ecf20Sopenharmony_ci	f = open(mm, O_RDONLY);
408c2ecf20Sopenharmony_ci	ASSERT_GE(f, 0);
418c2ecf20Sopenharmony_ci	close(f);
428c2ecf20Sopenharmony_ci	f = kill(pid, SIGCONT);
438c2ecf20Sopenharmony_ci	ASSERT_EQ(f, 0);
448c2ecf20Sopenharmony_ci}
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ciTEST(attach)
478c2ecf20Sopenharmony_ci{
488c2ecf20Sopenharmony_ci	int s, k, pid = fork();
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	if (!pid) {
518c2ecf20Sopenharmony_ci		pthread_t pt;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci		pthread_create(&pt, NULL, thread, NULL);
548c2ecf20Sopenharmony_ci		pthread_join(pt, NULL);
558c2ecf20Sopenharmony_ci		execlp("sleep", "sleep", "2", NULL);
568c2ecf20Sopenharmony_ci	}
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	sleep(1);
598c2ecf20Sopenharmony_ci	k = ptrace(PTRACE_ATTACH, pid, 0L, 0L);
608c2ecf20Sopenharmony_ci	ASSERT_EQ(errno, EAGAIN);
618c2ecf20Sopenharmony_ci	ASSERT_EQ(k, -1);
628c2ecf20Sopenharmony_ci	k = waitpid(-1, &s, WNOHANG);
638c2ecf20Sopenharmony_ci	ASSERT_NE(k, -1);
648c2ecf20Sopenharmony_ci	ASSERT_NE(k, 0);
658c2ecf20Sopenharmony_ci	ASSERT_NE(k, pid);
668c2ecf20Sopenharmony_ci	ASSERT_EQ(WIFEXITED(s), 1);
678c2ecf20Sopenharmony_ci	ASSERT_EQ(WEXITSTATUS(s), 0);
688c2ecf20Sopenharmony_ci	sleep(1);
698c2ecf20Sopenharmony_ci	k = ptrace(PTRACE_ATTACH, pid, 0L, 0L);
708c2ecf20Sopenharmony_ci	ASSERT_EQ(k, 0);
718c2ecf20Sopenharmony_ci	k = waitpid(-1, &s, 0);
728c2ecf20Sopenharmony_ci	ASSERT_EQ(k, pid);
738c2ecf20Sopenharmony_ci	ASSERT_EQ(WIFSTOPPED(s), 1);
748c2ecf20Sopenharmony_ci	ASSERT_EQ(WSTOPSIG(s), SIGSTOP);
758c2ecf20Sopenharmony_ci	k = ptrace(PTRACE_DETACH, pid, 0L, 0L);
768c2ecf20Sopenharmony_ci	ASSERT_EQ(k, 0);
778c2ecf20Sopenharmony_ci	k = waitpid(-1, &s, 0);
788c2ecf20Sopenharmony_ci	ASSERT_EQ(k, pid);
798c2ecf20Sopenharmony_ci	ASSERT_EQ(WIFEXITED(s), 1);
808c2ecf20Sopenharmony_ci	ASSERT_EQ(WEXITSTATUS(s), 0);
818c2ecf20Sopenharmony_ci	k = waitpid(-1, NULL, 0);
828c2ecf20Sopenharmony_ci	ASSERT_EQ(k, -1);
838c2ecf20Sopenharmony_ci	ASSERT_EQ(errno, ECHILD);
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ciTEST_HARNESS_MAIN
87