[PATCH v8 4/6] sched: Extend task command name with TASK_COMM_EXT_LEN
From: André Almeida
Date: Fri Oct 30 2026 - 17:44:32 EST
Command name has been restrict to only 16 bytes, which is too limiting,
specially when debugging and tracing complex software with thousands of
threads and the need to differentiate them.
Just as it was done with kthreads in commit 6b59808bfe48 ("workqueue:
Show the latest workqueue name in /proc/PID/{comm,stat,status}"), support
long names for userspace threads as well.
To avoid buffer overflows, cap all existing userspace APIs to
TASK_COMM_LEN, and leave the full extended name for a new interface.
Callers of set_task_comm() are responsible of having a valid string in
their argument buffers. A caller of set_task_comm() that passes a string
shorter than TASK_COMM_EXT_LEN without a null terminator will cause a
out-of-bounds read in set_task_comm().
Signed-off-by: André Almeida <andrealmeid@xxxxxxxxxx>
---
Changes from v5:
- Fix blktrace buffer size
- Fix i915 buffer size
---
drivers/gpu/drm/i915/display/intel_display_driver.c | 4 ++--
drivers/gpu/drm/i915/gem/i915_gem_context.c | 4 ++--
fs/proc/array.c | 2 +-
include/linux/sched.h | 5 +++--
kernel/sys.c | 10 +++++-----
kernel/trace/blktrace.c | 6 ++++--
6 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c
index 204810a11e46..005c49902259 100644
--- a/drivers/gpu/drm/i915/display/intel_display_driver.c
+++ b/drivers/gpu/drm/i915/display/intel_display_driver.c
@@ -436,8 +436,8 @@ void intel_display_driver_resume_access(struct intel_display *display)
*/
bool intel_display_driver_check_access(struct intel_display *display)
{
- char current_task[TASK_COMM_LEN + 16];
- char allowed_task[TASK_COMM_LEN + 16] = "none";
+ char current_task[TASK_COMM_EXT_LEN + 16];
+ char allowed_task[TASK_COMM_EXT_LEN + 16] = "none";
if (display->access.any_task_allowed ||
display->access.allowed_task == current)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index c58ffa5a8fa6..b62b82c6de04 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -1730,8 +1730,8 @@ static void gem_context_register(struct i915_gem_context *ctx,
ctx->pid = get_task_pid(current, PIDTYPE_PID);
ctx->client = i915_drm_client_get(fpriv->client);
- snprintf(ctx->name, sizeof(ctx->name), "%s[%d]",
- current->comm, pid_nr(ctx->pid));
+ snprintf(ctx->name, sizeof(ctx->name), "%.*s[%d]",
+ TASK_COMM_LEN - 1, current->comm, pid_nr(ctx->pid));
spin_lock(&ctx->client->ctx_lock);
list_add_tail_rcu(&ctx->client_link, &ctx->client->ctx_list);
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 8ebb7cf1a7b0..0d70b21c803c 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -110,7 +110,7 @@ void proc_task_name(struct seq_file *m, struct task_struct *p, bool escape)
else if (p->flags & PF_KTHREAD)
get_kthread_comm(tcomm, sizeof(tcomm), p);
else
- strscpy_pad(tcomm, p->comm);
+ strscpy_pad(tcomm, p->comm, TASK_COMM_LEN);
if (escape)
seq_escape_str(m, tcomm, ESCAPE_SPACE | ESCAPE_SPECIAL, "\n\\");
diff --git a/include/linux/sched.h b/include/linux/sched.h
index db529a93525d..5e02bce749b8 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -323,6 +323,7 @@ struct user_event_mm;
*/
enum {
TASK_COMM_LEN = 16,
+ TASK_COMM_EXT_LEN = 64,
};
extern void sched_tick(void);
@@ -1192,7 +1193,7 @@ struct task_struct {
* - set it with set_task_comm() to ensure it is always
* NUL-terminated and zero-padded
*/
- char comm[TASK_COMM_LEN];
+ char comm[TASK_COMM_EXT_LEN];
struct nameidata *nameidata;
@@ -2048,7 +2049,7 @@ extern void __set_task_comm(struct task_struct *tsk, const char *from, bool exec
static __always_inline void copy_task_comm(char *dst, struct task_struct *tsk, size_t len)
{
const char *_src = tsk->comm;
- size_t _len = min(len, TASK_COMM_LEN);
+ size_t _len = min(len, TASK_COMM_EXT_LEN);
if (!_len)
return;
diff --git a/kernel/sys.c b/kernel/sys.c
index 31eef656dbd6..6a72c7e644e7 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -2538,7 +2538,7 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
unsigned long, arg4, unsigned long, arg5)
{
struct task_struct *me = current;
- unsigned char comm[sizeof(me->comm)];
+ unsigned char comm[TASK_COMM_LEN];
long error;
error = security_task_prctl(option, arg2, arg3, arg4, arg5);
@@ -2604,16 +2604,16 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
error = -EINVAL;
break;
case PR_SET_NAME:
- comm[sizeof(me->comm) - 1] = 0;
+ comm[TASK_COMM_LEN - 1] = 0;
if (strncpy_from_user(comm, (char __user *)arg2,
- sizeof(me->comm) - 1) < 0)
+ TASK_COMM_LEN - 1) < 0)
return -EFAULT;
set_task_comm(me, comm);
proc_comm_connector(me);
break;
case PR_GET_NAME:
- strscpy_pad(comm, me->comm);
- if (copy_to_user((char __user *)arg2, comm, sizeof(comm)))
+ strscpy_pad(comm, me->comm, TASK_COMM_LEN);
+ if (copy_to_user((char __user *)arg2, comm, TASK_COMM_LEN))
return -EFAULT;
break;
case PR_GET_ENDIAN:
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index 8cd2520b4c99..edc1377c3e3c 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -214,12 +214,14 @@ static void trace_note_tsk(struct task_struct *tsk)
{
unsigned long flags;
struct blk_trace *bt;
+ char comm[TASK_COMM_LEN];
tsk->btrace_seq = blktrace_seq;
raw_spin_lock_irqsave(&running_trace_lock, flags);
list_for_each_entry(bt, &running_trace_list, running_list) {
- trace_note(bt, tsk->pid, BLK_TN_PROCESS, tsk->comm,
- sizeof(tsk->comm), 0);
+ strscpy_pad(comm, tsk->comm);
+ trace_note(bt, tsk->pid, BLK_TN_PROCESS, comm,
+ sizeof(comm), 0);
}
raw_spin_unlock_irqrestore(&running_trace_lock, flags);
}
--
2.56.0