lkml.org 
[lkml]   [2021]   [Oct]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH 7/7] selftests: proc: Make sure wchan works when it exists
From: Kees Cook <keescook@chromium.org>

This makes sure that wchan contains a sensible symbol when a process is
blocked. Specifically this calls the sleep() syscall, and expects the
architecture to have called schedule() from a function that has "sleep"
somewhere in its name. For example, on the architectures I tested
(x86_64, arm64, arm, mips, and powerpc) this is "hrtimer_nanosleep":

$ tools/testing/selftests/proc/proc-pid-wchan
ok: found 'sleep' in wchan 'hrtimer_nanosleep'

Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/20211008235504.2957528-1-keescook@chromium.org
---
tools/testing/selftests/proc/Makefile | 1
tools/testing/selftests/proc/proc-pid-wchan.c | 69 ++++++++++++++++++++++++++
2 files changed, 70 insertions(+)
create mode 100644 tools/testing/selftests/proc/proc-pid-wchan.c

--- a/tools/testing/selftests/proc/Makefile
+++ b/tools/testing/selftests/proc/Makefile
@@ -8,6 +8,7 @@ TEST_GEN_PROGS += fd-002-posix-eq
TEST_GEN_PROGS += fd-003-kthread
TEST_GEN_PROGS += proc-loadavg-001
TEST_GEN_PROGS += proc-pid-vm
+TEST_GEN_PROGS += proc-pid-wchan
TEST_GEN_PROGS += proc-self-map-files-001
TEST_GEN_PROGS += proc-self-map-files-002
TEST_GEN_PROGS += proc-self-syscall
--- /dev/null
+++ b/tools/testing/selftests/proc/proc-pid-wchan.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Make sure that wchan returns a reasonable symbol when blocked.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#define perror_exit(str) do { perror(str); _exit(1); } while (0)
+
+int main(void)
+{
+ char buf[64];
+ pid_t child;
+ int sync[2], fd;
+
+ if (pipe(sync) < 0)
+ perror_exit("pipe");
+
+ child = fork();
+ if (child < 0)
+ perror_exit("fork");
+ if (child == 0) {
+ /* Child */
+ if (close(sync[0]) < 0)
+ perror_exit("child close sync[0]");
+ if (close(sync[1]) < 0)
+ perror_exit("child close sync[1]");
+ sleep(10);
+ _exit(0);
+ }
+ /* Parent */
+ if (close(sync[1]) < 0)
+ perror_exit("parent close sync[1]");
+ if (read(sync[0], buf, 1) != 0)
+ perror_exit("parent read sync[0]");
+
+ snprintf(buf, sizeof(buf), "/proc/%d/wchan", child);
+ fd = open(buf, O_RDONLY);
+ if (fd < 0) {
+ if (errno == ENOENT)
+ return 4;
+ perror_exit(buf);
+ }
+
+ memset(buf, 0, sizeof(buf));
+ if (read(fd, buf, sizeof(buf) - 1) < 1)
+ perror_exit(buf);
+ if (strstr(buf, "sleep") == NULL) {
+ fprintf(stderr, "FAIL: did not find 'sleep' in wchan '%s'\n", buf);
+ return 1;
+ }
+ printf("ok: found 'sleep' in wchan '%s'\n", buf);
+
+ if (kill(child, SIGKILL) < 0)
+ perror_exit("kill");
+ if (waitpid(child, NULL, 0) != child) {
+ fprintf(stderr, "waitpid: got the wrong child!?\n");
+ return 1;
+ }
+
+ return 0;
+}

\
 
 \ /
  Last update: 2021-10-22 17:29    [W:0.135 / U:1.068 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site