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; > +}