Thread (6 messages) flat view 6 messages, 3 authors, 2021-11-13

Re: [PATCH] kthread: dynamically allocate memory to store kthread's full name

From: Yafang Shao <hidden>
Date: 2021-11-13 15:48:25
Also in: bpf, linux-fsdevel, linux-mm, linux-perf-users, lkml

On Fri, Nov 12, 2021 at 11:34 PM Petr Mladek [off-list ref] wrote:
On Mon 2021-11-08 08:41:42, Yafang Shao wrote:
quoted
When I was implementing a new per-cpu kthread cfs_migration, I found the
comm of it "cfs_migration/%u" is truncated due to the limitation of
TASK_COMM_LEN. For example, the comm of the percpu thread on CPU10~19 are
all with the same name "cfs_migration/1", which will confuse the user. This
issue is not critical, because we can get the corresponding CPU from the
task's Cpus_allowed. But for kthreads correspoinding to other hardware
devices, it is not easy to get the detailed device info from task comm,
for example,

After this change, the full name of these truncated kthreads will be
displayed via /proc/[pid]/comm:
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -102,6 +103,8 @@ void proc_task_name(struct seq_file *m, struct task_struct *p, bool escape)

      if (p->flags & PF_WQ_WORKER)
              wq_worker_comm(tcomm, sizeof(tcomm), p);
Just for record. I though that this patch obsoleted wq_worker_comm()
but it did not. wq_worker_comm() returns different values
depending on the last proceed work item and has to stay.
Right. worker comm is changed dynamically, which is combined by
(task_comm+worker_desc) or (task_comm-worker_desc).
I planned to remove the whole worker->desc and set it dynamically to
the new kthread full_name but I found it may not be a good idea.

quoted
+     else if (p->flags & PF_KTHREAD)
+             get_kthread_comm(tcomm, sizeof(tcomm), p);
      else
              __get_task_comm(tcomm, sizeof(tcomm), p);
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -121,6 +135,7 @@ void free_kthread_struct(struct task_struct *k)
Hmm, there is the following comment:

        /*
         * Can be NULL if this kthread was created by kernel_thread()
         * or if kmalloc() in kthread() failed.
         */
        kthread = to_kthread(k);

And indeed, set_kthread_struct() is called only by kthread()
and init_idle().

For example, call_usermodehelper_exec_sync() calls kernel_thread()
but given @fn does not call set_kthread_struct(). Also init_idle()
continues even when the allocation failed.
Yes, it really can be NULL.
quoted
 #ifdef CONFIG_BLK_CGROUP
      WARN_ON_ONCE(kthread && kthread->blkcg_css);
 #endif
+     kfree(kthread->full_name);
Hence, we have to make sure that it is not NULL here. I suggest
something like:
Agreed.  I will do it.
void free_kthread_struct(struct task_struct *k)
{
        struct kthread *kthread;

        /*
         * Can be NULL if this kthread was created by kernel_thread()
         * or if kmalloc() in kthread() failed.
         */
        kthread = to_kthread(k);
        if (!kthread)
                return;

#ifdef CONFIG_BLK_CGROUP
        WARN_ON_ONCE(kthread->blkcg_css);
#endif
        kfree(kthread->full_name);
        kfree(kthread);
}


Side note: The possible NULL pointer looks dangerous to
    me. to_kthread() is dereferenced without any check on
    several locations.

    For example, kthread_create_on_cpu() looks safe. It is a kthread
    crated by kthread(). It will exists only when the allocation
    succeeded.

    kthread_stop() is probably safe only because it used only for
    the classic kthreads created by kthread(). But the API
    is not safe.

    kthread_use_mm() is probably used only by classic kthreads as
    well. But it is less clear to me.

    All this unsafe APIs looks like a ticking bomb to me. But
    it is beyond this patchset.
I will analyze it in depth and try to dismantle this ticking bomb.


-- 
Thanks
Yafang
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help