aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
authorKees Cook <kees@kernel.org>2024-11-29 20:06:55 -0800
committerKees Cook <kees@kernel.org>2024-12-16 16:53:00 -0800
commit3a3f61ce5e0b4bcf730acc09c1af91012d241f85 (patch)
treefb789240fafc051aeb40f066152bcae0adf2cc14 /fs/exec.c
parentfa1bdca98d74472dcdb79cb948b54f63b5886c04 (diff)
downloadnet-3a3f61ce5e0b4bcf730acc09c1af91012d241f85.tar.gz
exec: Make sure task->comm is always NUL-terminated
Using strscpy() meant that the final character in task->comm may be non-NUL for a moment before the "string too long" truncation happens. Instead of adding a new use of the ambiguous strncpy(), we'd want to use memtostr_pad() which enforces being able to check at compile time that sizes are sensible, but this requires being able to see string buffer lengths. Instead of trying to inline __set_task_comm() (which needs to call trace and perf functions), just open-code it. But to make sure we're always safe, add compile-time checking like we already do for get_task_comm(). Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> Suggested-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Kees Cook <kees@kernel.org>
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/fs/exec.c b/fs/exec.c
index e0435b31a811af..5f16500ac3253d 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1200,16 +1200,16 @@ char *__get_task_comm(char *buf, size_t buf_size, struct task_struct *tsk)
EXPORT_SYMBOL_GPL(__get_task_comm);
/*
- * These functions flushes out all traces of the currently running executable
- * so that a new one can be started
+ * This is unlocked -- the string will always be NUL-terminated, but
+ * may show overlapping contents if racing concurrent reads.
*/
-
void __set_task_comm(struct task_struct *tsk, const char *buf, bool exec)
{
- task_lock(tsk);
+ size_t len = min(strlen(buf), sizeof(tsk->comm) - 1);
+
trace_task_rename(tsk, buf);
- strscpy_pad(tsk->comm, buf, sizeof(tsk->comm));
- task_unlock(tsk);
+ memcpy(tsk->comm, buf, len);
+ memset(&tsk->comm[len], 0, sizeof(tsk->comm) - len);
perf_event_comm(tsk, exec);
}