Skip to content

Commit 6776f85

Browse files
laoarakpm00
authored andcommitted
get rid of __get_task_comm()
Patch series "Improve the copy of task comm", v8. Using {memcpy,strncpy,strcpy,kstrdup} to copy the task comm relies on the length of task comm. Changes in the task comm could result in a destination string that is overflow. Therefore, we should explicitly ensure the destination string is always NUL-terminated, regardless of the task comm. This approach will facilitate future extensions to the task comm. As suggested by Linus [0], we can identify all relevant code with the following git grep command: git grep 'memcpy.*->comm\>' git grep 'kstrdup.*->comm\>' git grep 'strncpy.*->comm\>' git grep 'strcpy.*->comm\>' PATCH #2~#4: memcpy PATCH #5~#6: kstrdup PATCH #7: strcpy Please note that strncpy() is not included in this series as it is being tracked by another effort. [1] This patch (of 7): We want to eliminate the use of __get_task_comm() for the following reasons: - The task_lock() is unnecessary Quoted from Linus [0]: : Since user space can randomly change their names anyway, using locking : was always wrong for readers (for writers it probably does make sense : to have some lock - although practically speaking nobody cares there : either, but at least for a writer some kind of race could have : long-term mixed results Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Link: https://lore.kernel.org/all/CAHk-=wivfrF0_zvf+oj6==Sh=-npJooP8chLPEfaFV0oNYTTBA@mail.gmail.com [0] Link: https://lore.kernel.org/all/CAHk-=whWtUC-AjmGJveAETKOMeMFSTwKwu99v7+b6AyHMmaDFA@mail.gmail.com/ Link: https://lore.kernel.org/all/CAHk-=wjAmmHUg6vho1KjzQi2=psR30+CogFd4aXrThr2gsiS4g@mail.gmail.com/ [0] Link: KSPP#90 [1] Signed-off-by: Yafang Shao <[email protected]> Suggested-by: Linus Torvalds <[email protected]> Cc: Alexander Viro <[email protected]> Cc: Christian Brauner <[email protected]> Cc: Jan Kara <[email protected]> Cc: Eric Biederman <[email protected]> Cc: Kees Cook <[email protected]> Cc: Alexei Starovoitov <[email protected]> Cc: Matus Jokay <[email protected]> Cc: Alejandro Colomar <[email protected]> Cc: "Serge E. Hallyn" <[email protected]> Cc: Catalin Marinas <[email protected]> Cc: Justin Stitt <[email protected]> Cc: Steven Rostedt (Google) <[email protected]> Cc: Tetsuo Handa <[email protected]> Cc: Andy Shevchenko <[email protected]> Cc: Daniel Vetter <[email protected]> Cc: David Airlie <[email protected]> Cc: Eric Paris <[email protected]> Cc: James Morris <[email protected]> Cc: Maarten Lankhorst <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Maxime Ripard <[email protected]> Cc: Ondrej Mosnacek <[email protected]> Cc: Paul Moore <[email protected]> Cc: Quentin Monnet <[email protected]> Cc: Simon Horman <[email protected]> Cc: Stephen Smalley <[email protected]> Cc: Thomas Zimmermann <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 3268b75 commit 6776f85

File tree

4 files changed

+24
-18
lines changed

4 files changed

+24
-18
lines changed

fs/exec.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,16 +1189,6 @@ static int unshare_sighand(struct task_struct *me)
11891189
return 0;
11901190
}
11911191

1192-
char *__get_task_comm(char *buf, size_t buf_size, struct task_struct *tsk)
1193-
{
1194-
task_lock(tsk);
1195-
/* Always NUL terminated and zero-padded */
1196-
strscpy_pad(buf, tsk->comm, buf_size);
1197-
task_unlock(tsk);
1198-
return buf;
1199-
}
1200-
EXPORT_SYMBOL_GPL(__get_task_comm);
1201-
12021192
/*
12031193
* These functions flushes out all traces of the currently running executable
12041194
* so that a new one can be started

fs/proc/array.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ void proc_task_name(struct seq_file *m, struct task_struct *p, bool escape)
109109
else if (p->flags & PF_KTHREAD)
110110
get_kthread_comm(tcomm, sizeof(tcomm), p);
111111
else
112-
__get_task_comm(tcomm, sizeof(tcomm), p);
112+
get_task_comm(tcomm, p);
113113

114114
if (escape)
115115
seq_escape_str(m, tcomm, ESCAPE_SPACE | ESCAPE_SPECIAL, "\n\\");

include/linux/sched.h

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,9 +1121,12 @@ struct task_struct {
11211121
/*
11221122
* executable name, excluding path.
11231123
*
1124-
* - normally initialized setup_new_exec()
1125-
* - access it with [gs]et_task_comm()
1126-
* - lock it with task_lock()
1124+
* - normally initialized begin_new_exec()
1125+
* - set it with set_task_comm()
1126+
* - strscpy_pad() to ensure it is always NUL-terminated and
1127+
* zero-padded
1128+
* - task_lock() to ensure the operation is atomic and the name is
1129+
* fully updated.
11271130
*/
11281131
char comm[TASK_COMM_LEN];
11291132

@@ -1938,10 +1941,23 @@ static inline void set_task_comm(struct task_struct *tsk, const char *from)
19381941
__set_task_comm(tsk, from, false);
19391942
}
19401943

1941-
extern char *__get_task_comm(char *to, size_t len, struct task_struct *tsk);
1944+
/*
1945+
* - Why not use task_lock()?
1946+
* User space can randomly change their names anyway, so locking for readers
1947+
* doesn't make sense. For writers, locking is probably necessary, as a race
1948+
* condition could lead to long-term mixed results.
1949+
* The strscpy_pad() in __set_task_comm() can ensure that the task comm is
1950+
* always NUL-terminated and zero-padded. Therefore the race condition between
1951+
* reader and writer is not an issue.
1952+
*
1953+
* - BUILD_BUG_ON() can help prevent the buf from being truncated.
1954+
* Since the callers don't perform any return value checks, this safeguard is
1955+
* necessary.
1956+
*/
19421957
#define get_task_comm(buf, tsk) ({ \
1943-
BUILD_BUG_ON(sizeof(buf) != TASK_COMM_LEN); \
1944-
__get_task_comm(buf, sizeof(buf), tsk); \
1958+
BUILD_BUG_ON(sizeof(buf) < TASK_COMM_LEN); \
1959+
strscpy_pad(buf, (tsk)->comm); \
1960+
buf; \
19451961
})
19461962

19471963
#ifdef CONFIG_SMP

kernel/kthread.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ void get_kthread_comm(char *buf, size_t buf_size, struct task_struct *tsk)
101101
struct kthread *kthread = to_kthread(tsk);
102102

103103
if (!kthread || !kthread->full_name) {
104-
__get_task_comm(buf, buf_size, tsk);
104+
strscpy(buf, tsk->comm, buf_size);
105105
return;
106106
}
107107

0 commit comments

Comments
 (0)