From 7a36094d61bfe9843de5484ff0140227983ac5d5 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 26 Sep 2017 12:45:33 -0500 Subject: pids: Compute task_tgid using signal->leader_pid The cost is the the same and this removes the need to worry about complications that come from de_thread and group_leader changing. __task_pid_nr_ns has been updated to take advantage of this change. Signed-off-by: "Eric W. Biederman" --- drivers/platform/x86/thinkpad_acpi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index cae9b0595692..d556e95c532c 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 019191342fecce4a461978a7191a43f313e19e86 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 16 Jul 2017 22:05:57 -0500 Subject: signal: Use PIDTYPE_TGID to clearly store where file signals will be sent When f_setown is called a pid and a pid type are stored. Replace the use of PIDTYPE_PID with PIDTYPE_TGID as PIDTYPE_TGID goes to the entire thread group. Replace the use of PIDTYPE_MAX with PIDTYPE_PID as PIDTYPE_PID now is only for a thread. Update the users of __f_setown to use PIDTYPE_TGID instead of PIDTYPE_PID. For now the code continues to capture task_pid (when task_tgid would really be appropriate), and iterate on PIDTYPE_PID (even when type == PIDTYPE_TGID) out of an abundance of caution to preserve existing behavior. Oleg Nesterov suggested using the test to ensure we use PIDTYPE_PID for tgid lookup also be used to avoid taking the tasklist lock. Suggested-by: Oleg Nesterov Signed-off-by: "Eric W. Biederman" --- drivers/net/tun.c | 2 +- drivers/tty/tty_io.c | 2 +- fs/fcntl.c | 54 +++++++++++++++++++++++++++------------------ fs/locks.c | 2 +- fs/notify/dnotify/dnotify.c | 3 ++- 5 files changed, 37 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index a192a017cc68..9958b70ac1b0 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -3216,7 +3216,7 @@ static int tun_chr_fasync(int fd, struct file *file, int on) goto out; if (on) { - __f_setown(file, task_pid(current), PIDTYPE_PID, 0); + __f_setown(file, task_pid(current), PIDTYPE_TGID, 0); tfile->flags |= TUN_FASYNC; } else tfile->flags &= ~TUN_FASYNC; diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index aba59521ad48..090fb7e78eea 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2122,7 +2122,7 @@ static int __tty_fasync(int fd, struct file *filp, int on) type = PIDTYPE_PGID; } else { pid = task_pid(current); - type = PIDTYPE_PID; + type = PIDTYPE_TGID; } get_pid(pid); spin_unlock_irqrestore(&tty->ctrl_lock, flags); diff --git a/fs/fcntl.c b/fs/fcntl.c index 12273b6ea56d..1523588fd759 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -116,7 +116,7 @@ int f_setown(struct file *filp, unsigned long arg, int force) struct pid *pid = NULL; int who = arg, ret = 0; - type = PIDTYPE_PID; + type = PIDTYPE_TGID; if (who < 0) { /* avoid overflow below */ if (who == INT_MIN) @@ -143,7 +143,7 @@ EXPORT_SYMBOL(f_setown); void f_delown(struct file *filp) { - f_modown(filp, NULL, PIDTYPE_PID, 1); + f_modown(filp, NULL, PIDTYPE_TGID, 1); } pid_t f_getown(struct file *filp) @@ -171,11 +171,11 @@ static int f_setown_ex(struct file *filp, unsigned long arg) switch (owner.type) { case F_OWNER_TID: - type = PIDTYPE_MAX; + type = PIDTYPE_PID; break; case F_OWNER_PID: - type = PIDTYPE_PID; + type = PIDTYPE_TGID; break; case F_OWNER_PGRP: @@ -206,11 +206,11 @@ static int f_getown_ex(struct file *filp, unsigned long arg) read_lock(&filp->f_owner.lock); owner.pid = pid_vnr(filp->f_owner.pid); switch (filp->f_owner.pid_type) { - case PIDTYPE_MAX: + case PIDTYPE_PID: owner.type = F_OWNER_TID; break; - case PIDTYPE_PID: + case PIDTYPE_TGID: owner.type = F_OWNER_PID; break; @@ -785,20 +785,25 @@ void send_sigio(struct fown_struct *fown, int fd, int band) read_lock(&fown->lock); type = fown->pid_type; - if (type == PIDTYPE_MAX) { + if (type == PIDTYPE_PID) group = 0; - type = PIDTYPE_PID; - } pid = fown->pid; if (!pid) goto out_unlock_fown; - - read_lock(&tasklist_lock); - do_each_pid_task(pid, type, p) { + + if (type <= PIDTYPE_TGID) { + rcu_read_lock(); + p = pid_task(pid, PIDTYPE_PID); send_sigio_to_task(p, fown, fd, band, group); - } while_each_pid_task(pid, type, p); - read_unlock(&tasklist_lock); + rcu_read_unlock(); + } else { + read_lock(&tasklist_lock); + do_each_pid_task(pid, type, p) { + send_sigio_to_task(p, fown, fd, band, group); + } while_each_pid_task(pid, type, p); + read_unlock(&tasklist_lock); + } out_unlock_fown: read_unlock(&fown->lock); } @@ -821,22 +826,27 @@ int send_sigurg(struct fown_struct *fown) read_lock(&fown->lock); type = fown->pid_type; - if (type == PIDTYPE_MAX) { + if (type == PIDTYPE_PID) group = 0; - type = PIDTYPE_PID; - } pid = fown->pid; if (!pid) goto out_unlock_fown; ret = 1; - - read_lock(&tasklist_lock); - do_each_pid_task(pid, type, p) { + + if (type <= PIDTYPE_TGID) { + rcu_read_lock(); + p = pid_task(pid, PIDTYPE_PID); send_sigurg_to_task(p, fown, group); - } while_each_pid_task(pid, type, p); - read_unlock(&tasklist_lock); + rcu_read_unlock(); + } else { + read_lock(&tasklist_lock); + do_each_pid_task(pid, type, p) { + send_sigurg_to_task(p, fown, group); + } while_each_pid_task(pid, type, p); + read_unlock(&tasklist_lock); + } out_unlock_fown: read_unlock(&fown->lock); return ret; diff --git a/fs/locks.c b/fs/locks.c index db7b6917d9c5..cfc059bda8ea 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -546,7 +546,7 @@ lease_setup(struct file_lock *fl, void **priv) if (!fasync_insert_entry(fa->fa_fd, filp, &fl->fl_fasync, fa)) *priv = NULL; - __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); + __f_setown(filp, task_pid(current), PIDTYPE_TGID, 0); } static const struct lock_manager_operations lease_manager_ops = { diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index e2bea2ac5dfb..484f2c3a33bb 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -353,7 +354,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) goto out; } - __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); + __f_setown(filp, task_pid(current), PIDTYPE_TGID, 0); error = attach_dn(dn, dn_mark, id, fd, filp, mask); /* !error means that we attached the dn to the dn_mark, so don't free it */ -- cgit v1.2.3 From 40b3b02535621027f56d248139e0e467573c3098 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sat, 21 Jul 2018 10:45:15 -0500 Subject: signal: Pass pid type into do_send_sig_info This passes the information we already have at the call sight into do_send_sig_info. Ultimately allowing for better handling of signals sent to a group of processes during fork. Signed-off-by: "Eric W. Biederman" --- drivers/tty/sysrq.c | 2 +- fs/fcntl.c | 6 +++--- include/linux/signal.h | 2 +- kernel/signal.c | 10 +++++----- mm/oom_kill.c | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 6364890575ec..06ed20dd01ba 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -348,7 +348,7 @@ static void send_sig_all(int sig) if (is_global_init(p)) continue; - do_send_sig_info(sig, SEND_SIG_FORCED, p, true); + do_send_sig_info(sig, SEND_SIG_FORCED, p, PIDTYPE_MAX); } read_unlock(&tasklist_lock); } diff --git a/fs/fcntl.c b/fs/fcntl.c index 5d596a00f40b..a04accf6847f 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -767,11 +767,11 @@ static void send_sigio_to_task(struct task_struct *p, else si.si_band = mangle_poll(band_table[reason - POLL_IN]); si.si_fd = fd; - if (!do_send_sig_info(signum, &si, p, type != PIDTYPE_PID)) + if (!do_send_sig_info(signum, &si, p, type)) break; /* fall-through: fall back on the old plain SIGIO signal */ case 0: - do_send_sig_info(SIGIO, SEND_SIG_PRIV, p, type != PIDTYPE_PID); + do_send_sig_info(SIGIO, SEND_SIG_PRIV, p, type); } } @@ -808,7 +808,7 @@ static void send_sigurg_to_task(struct task_struct *p, struct fown_struct *fown, enum pid_type type) { if (sigio_perm(p, fown, SIGURG)) - do_send_sig_info(SIGURG, SEND_SIG_PRIV, p, type != PIDTYPE_PID); + do_send_sig_info(SIGURG, SEND_SIG_PRIV, p, type); } int send_sigurg(struct fown_struct *fown) diff --git a/include/linux/signal.h b/include/linux/signal.h index d8f2bf3d41e6..fe125b0335f7 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -258,7 +258,7 @@ enum pid_type; extern int next_signal(struct sigpending *pending, sigset_t *mask); extern int do_send_sig_info(int sig, struct siginfo *info, - struct task_struct *p, bool group); + struct task_struct *p, enum pid_type type); extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p, enum pid_type type); extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *); diff --git a/kernel/signal.c b/kernel/signal.c index c7527338fe9d..2c09e6143dd8 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1161,13 +1161,13 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t) } int do_send_sig_info(int sig, struct siginfo *info, struct task_struct *p, - bool group) + enum pid_type type) { unsigned long flags; int ret = -ESRCH; if (lock_task_sighand(p, &flags)) { - ret = send_signal(sig, info, p, group); + ret = send_signal(sig, info, p, type != PIDTYPE_PID); unlock_task_sighand(p, &flags); } @@ -1284,7 +1284,7 @@ int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p, rcu_read_unlock(); if (!ret && sig) - ret = do_send_sig_info(sig, info, p, true); + ret = do_send_sig_info(sig, info, p, type); return ret; } @@ -1448,7 +1448,7 @@ int send_sig_info(int sig, struct siginfo *info, struct task_struct *p) if (!valid_signal(sig)) return -EINVAL; - return do_send_sig_info(sig, info, p, false); + return do_send_sig_info(sig, info, p, PIDTYPE_PID); } #define __si_special(priv) \ @@ -3199,7 +3199,7 @@ do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info) * probe. No signal is actually delivered. */ if (!error && sig) { - error = do_send_sig_info(sig, info, p, false); + error = do_send_sig_info(sig, info, p, PIDTYPE_PID); /* * If lock_task_sighand() failed we pretend the task * dies after receiving the signal. The window is tiny, diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 84081e77bc51..2cc9b238368f 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -920,7 +920,7 @@ static void oom_kill_process(struct oom_control *oc, const char *message) * in order to prevent the OOM victim from depleting the memory * reserves from the user space under its control. */ - do_send_sig_info(SIGKILL, SEND_SIG_FORCED, victim, true); + do_send_sig_info(SIGKILL, SEND_SIG_FORCED, victim, PIDTYPE_TGID); mark_oom_victim(victim); pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB\n", task_pid_nr(victim), victim->comm, K(victim->mm->total_vm), @@ -958,7 +958,7 @@ static void oom_kill_process(struct oom_control *oc, const char *message) */ if (unlikely(p->flags & PF_KTHREAD)) continue; - do_send_sig_info(SIGKILL, SEND_SIG_FORCED, p, true); + do_send_sig_info(SIGKILL, SEND_SIG_FORCED, p, PIDTYPE_TGID); } rcu_read_unlock(); -- cgit v1.2.3