Thread (10 messages) 10 messages, 4 authors, 2021-10-22

Re: [PATCH] selftests: proc: Make sure wchan works when it exists

From: Alexey Dobriyan <hidden>
Date: 2021-10-09 12:52:20
Also in: linux-fsdevel, linux-hardening, linux-kselftest, lkml

On Fri, Oct 08, 2021 at 04:55:04PM -0700, Kees Cook wrote:
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.
This exposes internal kernel symbol to userspace.
Why would want to test that?

Doing s/sleep/SLEEP/g doesn't change kernel but now the test is broken.
For example, on the architectures I tested
(x86_64, arm64, arm, mips, and powerpc) this is "hrtimer_nanosleep":
+/*
+ * Make sure that wchan returns a reasonable symbol when blocked.
+ */
Test should be "contains C identifier" then?
+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]");
Redundant close().
+		sleep(10);
+		_exit(0);
+	}
+	/* Parent */
+	if (close(sync[1]) < 0)
+		perror_exit("parent close sync[1]");
Redundant close().
+	if (read(sync[0], buf, 1) != 0)
+		perror_exit("parent read sync[0]");
Racy if child is scheduled out after first close in the child.
+	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;
+}
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help