Kernel threads have empty /proc/PID/cmdline and some userland tools including ps(1) and older versions of systemd use this to detect kernel threads. However, any userland program can emulate the behavior by making its argvs unavailable and trick the affected tools into thinking that the task is a kernel thread. Linus's reproducer follows. #include <sys/prctl.h> #include <sys/mman.h> int main(void) { char empty[16384]; unsigned long ptr; asm volatile("" :"=r" (ptr) : "0" (empty):"memory"); ptr = (ptr+4095) & ~4095; munmap((void *)ptr, 32768); sleep(1000); return 0; } Compiling the above program into nullcmdline and running it on an unpatche kernel shows the following behavior. $ ./nullcmdline & [1] 2382031 [devbig577 ~/tmp]$ hexdump -C /proc/2382031/comm 00000000 6e 75 6c 6c 63 6d 64 6c 69 6e 65 0a |nullcmdline.| 0000000c $ hexdump -C /proc/2382031/cmdline $ ps 2382031 PID TTY STAT TIME COMMAND 2382031 pts/2 S 0:00 [nullcmdline] The empty cmdline makes ps(1) think that nullcmdline is a kernel thread and put brackets around its name (comm), which is mostly a nuisance but it's possible that this confusion can lead to more harmful confusions. This patch fixes the issue by making proc_pid_cmdline_read() never return empty string for user tasks. If the result is empty for whatever reason, comm string is returned. Even when the comm string is empty, it still returns the null termnation character. On a patched kernel, running the same command as above gives us. $ ./nullcmdline & [1] 2317 [test ~]# hexdump -C /proc/2317/comm 00000000 6e 75 6c 6c 63 6d 64 6c 69 6e 65 0a |nullcmdline.| 0000000c $ hexdump -C /proc/2317/cmdline 00000000 6e 75 6c 6c 63 6d 64 6c 69 6e 65 00 |nullcmdline.| 0000000c $ ps 2317 PID TTY STAT TIME COMMAND 2317 pts/0 S 0:00 nullcmdline Note that cmdline is a dup of comm and ps(1) is no longer confused. Signed-off-by: Tejun Heo <tj@xxxxxxxxxx> Suggested-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> --- fs/proc/base.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 1b2ede6..2eee4d7 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -224,9 +224,10 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf, if (!tsk) return -ESRCH; mm = get_task_mm(tsk); - put_task_struct(tsk); - if (!mm) - return 0; + if (!mm) { + rv = 0; + goto out_put_task; + } /* Check if process spawned far enough to have cmdline. */ if (!mm->env_end) { rv = 0; @@ -367,8 +368,23 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf, free_page((unsigned long)page); out_mmput: mmput(mm); +out_put_task: + /* + * Some userland tools use empty cmdline to distinguish kthreads. + * Avoid empty cmdline for user tasks by returning tsk->comm with + * \0 termination when empty. + */ + if (*pos == 0 && rv == 0 && !(tsk->flags & PF_KTHREAD)) { + char tcomm[TASK_COMM_LEN]; + + get_task_comm(tcomm, tsk); + rv = min(strlen(tcomm) + 1, count); + if (copy_to_user(buf, tsk->comm, rv)) + rv = -EFAULT; + } if (rv > 0) *pos += rv; + put_task_struct(tsk); return rv; } -- 2.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-api" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html