Skip to content

Commit 0658a09

Browse files
fweimer-rhtorvalds
authored andcommitted
procfs: do not list TID 0 in /proc/<pid>/task
If a task exits concurrently, task_pid_nr_ns may return 0. [[email protected]: coding style tweaks] [[email protected]: test that /proc/*/task doesn't contain "0"] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Florian Weimer <[email protected]> Signed-off-by: Alexey Dobriyan <[email protected]> Acked-by: Christian Brauner <[email protected]> Reviewed-by: Alexey Dobriyan <[email protected]> Cc: Kees Cook <[email protected]> Cc: "Eric W. Biederman" <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 83c1fd7 commit 0658a09

File tree

4 files changed

+87
-0
lines changed

4 files changed

+87
-0
lines changed

fs/proc/base.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3799,7 +3799,10 @@ static int proc_task_readdir(struct file *file, struct dir_context *ctx)
37993799
task = next_tid(task), ctx->pos++) {
38003800
char name[10 + 1];
38013801
unsigned int len;
3802+
38023803
tid = task_pid_nr_ns(task, ns);
3804+
if (!tid)
3805+
continue; /* The task has just exited. */
38033806
len = snprintf(name, sizeof(name), "%u", tid);
38043807
if (!proc_fill_cache(file, ctx, name, len,
38053808
proc_task_instantiate, task, NULL)) {

tools/testing/selftests/proc/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
/proc-self-syscall
1212
/proc-self-wchan
1313
/proc-subset-pid
14+
/proc-tid0
1415
/proc-uptime-001
1516
/proc-uptime-002
1617
/read

tools/testing/selftests/proc/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22
CFLAGS += -Wall -O2 -Wno-unused-function
33
CFLAGS += -D_GNU_SOURCE
4+
LDFLAGS += -pthread
45

56
TEST_GEN_PROGS :=
67
TEST_GEN_PROGS += fd-001-lookup
@@ -13,6 +14,7 @@ TEST_GEN_PROGS += proc-self-map-files-002
1314
TEST_GEN_PROGS += proc-self-syscall
1415
TEST_GEN_PROGS += proc-self-wchan
1516
TEST_GEN_PROGS += proc-subset-pid
17+
TEST_GEN_PROGS += proc-tid0
1618
TEST_GEN_PROGS += proc-uptime-001
1719
TEST_GEN_PROGS += proc-uptime-002
1820
TEST_GEN_PROGS += read
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright (c) 2021 Alexey Dobriyan <[email protected]>
3+
*
4+
* Permission to use, copy, modify, and distribute this software for any
5+
* purpose with or without fee is hereby granted, provided that the above
6+
* copyright notice and this permission notice appear in all copies.
7+
*
8+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15+
*/
16+
// Test that /proc/*/task never contains "0".
17+
#include <sys/types.h>
18+
#include <dirent.h>
19+
#include <signal.h>
20+
#include <stdio.h>
21+
#include <stdlib.h>
22+
#include <string.h>
23+
#include <unistd.h>
24+
#include <pthread.h>
25+
26+
static pid_t pid = -1;
27+
28+
static void atexit_hook(void)
29+
{
30+
if (pid > 0) {
31+
kill(pid, SIGKILL);
32+
}
33+
}
34+
35+
static void *f(void *_)
36+
{
37+
return NULL;
38+
}
39+
40+
static void sigalrm(int _)
41+
{
42+
exit(0);
43+
}
44+
45+
int main(void)
46+
{
47+
pid = fork();
48+
if (pid == 0) {
49+
/* child */
50+
while (1) {
51+
pthread_t pth;
52+
pthread_create(&pth, NULL, f, NULL);
53+
pthread_join(pth, NULL);
54+
}
55+
} else if (pid > 0) {
56+
/* parent */
57+
atexit(atexit_hook);
58+
59+
char buf[64];
60+
snprintf(buf, sizeof(buf), "/proc/%u/task", pid);
61+
62+
signal(SIGALRM, sigalrm);
63+
alarm(1);
64+
65+
while (1) {
66+
DIR *d = opendir(buf);
67+
struct dirent *de;
68+
while ((de = readdir(d))) {
69+
if (strcmp(de->d_name, "0") == 0) {
70+
exit(1);
71+
}
72+
}
73+
closedir(d);
74+
}
75+
76+
return 0;
77+
} else {
78+
perror("fork");
79+
return 1;
80+
}
81+
}

0 commit comments

Comments
 (0)