tty_kref_put() has two callsites in copy_process() paths, 1. if copy_process() suceeds it is called before we copy signal->tty from parent 2. otherwise it is called from __cleanup_signal() under bad_fork_cleanup_signal: label In both cases tty_kref_put() is not right and unneeded because we don't have the balancing tty_kref_get(). Fortunately, this is harmless because this can only happen without CLONE_THREAD, and in this case signal->tty must be NULL. Remove tty_kref_put() from copy_process() and __cleanup_signal(), and change another caller of __cleanup_signal(), __exit_signal(), to call tty_kref_put() by hand. I hope this change makes sense by itself, but it is also needed to make ->signal refcountable.
Unified · Split
| @@ -149,6 +149,7 @@ static void __exit_signal(struct task_struct *tsk) · 148 unmodified lines | |||
| 149 | * see account_group_exec_runtime(). | 149 | * see account_group_exec_runtime(). |
| 150 | */ | 150 | */ |
| 151 | task_rq_unlock_wait(tsk); | 151 | task_rq_unlock_wait(tsk); |
| 152 | tty_kref_put(sig->tty); | ||
| 152 | __cleanup_signal(sig); | 153 | __cleanup_signal(sig); |
| 153 | } | 154 | } |
| 154 | } | 155 | } |
| @@ -892,7 +892,6 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) · 891 unmodified lines | |||
| 892 | void __cleanup_signal(struct signal_struct *sig) | 892 | void __cleanup_signal(struct signal_struct *sig) |
| 893 | { | 893 | { |
| 894 | thread_group_cputime_free(sig); | 894 | thread_group_cputime_free(sig); |
| 895 | tty_kref_put(sig->tty); | ||
| 896 | kmem_cache_free(signal_cachep, sig); | 895 | kmem_cache_free(signal_cachep, sig); |
| 897 | } | 896 | } |
| 898 | 897 | ||
| @@ -1263,7 +1262,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, · 364 unmodified lines | |||
| 1263 | p->nsproxy->pid_ns->child_reaper = p; | 1262 | p->nsproxy->pid_ns->child_reaper = p; |
| 1264 | 1263 | ||
| 1265 | p->signal->leader_pid = pid; | 1264 | p->signal->leader_pid = pid; |
| 1266 | tty_kref_put(p->signal->tty); | ||
| 1267 | p->signal->tty = tty_kref_get(current->signal->tty); | 1265 | p->signal->tty = tty_kref_get(current->signal->tty); |
| 1268 | attach_pid(p, PIDTYPE_PGID, task_pgrp(current)); | 1266 | attach_pid(p, PIDTYPE_PGID, task_pgrp(current)); |
| 1269 | attach_pid(p, PIDTYPE_SID, task_session(current)); | 1267 | attach_pid(p, PIDTYPE_SID, task_session(current)); |