summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-08-21 13:47:29 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-08-21 13:47:29 -0700
commit0214f46b3a0383d6e33c297e7706216b6a550e4b (patch)
tree98f94fa818963d4c2b5ad2a16cd97ec19d036dce /fs
parent40fafdcbcd7a74e80ab0229b35bf6e497831e28f (diff)
parent84fe4cc09abc1a5ef3a282db3ed10f4d3f1e6a0b (diff)
Merge branch 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
Pull core signal handling updates from Eric Biederman: "It was observed that a periodic timer in combination with a sufficiently expensive fork could prevent fork from every completing. This contains the changes to remove the need for that restart. This set of changes is split into several parts: - The first part makes PIDTYPE_TGID a proper pid type instead something only for very special cases. The part starts using PIDTYPE_TGID enough so that in __send_signal where signals are actually delivered we know if the signal is being sent to a a group of processes or just a single process. - With that prep work out of the way the logic in fork is modified so that fork logically makes signals received while it is running appear to be received after the fork completes" * 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: (22 commits) signal: Don't send signals to tasks that don't exist signal: Don't restart fork when signals come in. fork: Have new threads join on-going signal group stops fork: Skip setting TIF_SIGPENDING in ptrace_init_task signal: Add calculate_sigpending() fork: Unconditionally exit if a fatal signal is pending fork: Move and describe why the code examines PIDNS_ADDING signal: Push pid type down into complete_signal. signal: Push pid type down into __send_signal signal: Push pid type down into send_signal signal: Pass pid type into do_send_sig_info signal: Pass pid type into send_sigio_to_task & send_sigurg_to_task signal: Pass pid type into group_send_sig_info signal: Pass pid and pid type into send_sigqueue posix-timers: Noralize good_sigevent signal: Use PIDTYPE_TGID to clearly store where file signals will be sent pid: Implement PIDTYPE_TGID pids: Move the pgrp and session pid pointers from task_struct to signal_struct kvm: Don't open code task_pid in kvm_vcpu_ioctl pids: Compute task_tgid using signal->leader_pid ...
Diffstat (limited to 'fs')
-rw-r--r--fs/autofs/autofs_i.h1
-rw-r--r--fs/exec.c1
-rw-r--r--fs/fcntl.c74
-rw-r--r--fs/fuse/file.c1
-rw-r--r--fs/locks.c2
-rw-r--r--fs/notify/dnotify/dnotify.c3
-rw-r--r--fs/notify/fanotify/fanotify.c1
7 files changed, 46 insertions, 37 deletions
diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
index 9400a9f6318a..502812289850 100644
--- a/fs/autofs/autofs_i.h
+++ b/fs/autofs/autofs_i.h
@@ -18,6 +18,7 @@
#include <linux/string.h>
#include <linux/wait.h>
#include <linux/sched.h>
+#include <linux/sched/signal.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/uaccess.h>
diff --git a/fs/exec.c b/fs/exec.c
index bdd0eacefdf5..1ebf6e5a521d 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1145,6 +1145,7 @@ static int de_thread(struct task_struct *tsk)
*/
tsk->pid = leader->pid;
change_pid(tsk, PIDTYPE_PID, task_pid(leader));
+ transfer_pid(leader, tsk, PIDTYPE_TGID);
transfer_pid(leader, tsk, PIDTYPE_PGID);
transfer_pid(leader, tsk, PIDTYPE_SID);
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 12273b6ea56d..4137d96534a6 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;
@@ -723,7 +723,7 @@ static inline int sigio_perm(struct task_struct *p,
static void send_sigio_to_task(struct task_struct *p,
struct fown_struct *fown,
- int fd, int reason, int group)
+ int fd, int reason, enum pid_type type)
{
/*
* F_SETSIG can change ->signum lockless in parallel, make
@@ -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, group))
+ 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, group);
+ do_send_sig_info(SIGIO, SEND_SIG_PRIV, p, type);
}
}
@@ -780,34 +780,36 @@ void send_sigio(struct fown_struct *fown, int fd, int band)
struct task_struct *p;
enum pid_type type;
struct pid *pid;
- int group = 1;
read_lock(&fown->lock);
type = fown->pid_type;
- if (type == PIDTYPE_MAX) {
- 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) {
- send_sigio_to_task(p, fown, fd, band, group);
- } while_each_pid_task(pid, type, p);
- read_unlock(&tasklist_lock);
+
+ if (type <= PIDTYPE_TGID) {
+ rcu_read_lock();
+ p = pid_task(pid, PIDTYPE_PID);
+ if (p)
+ send_sigio_to_task(p, fown, fd, band, type);
+ rcu_read_unlock();
+ } else {
+ read_lock(&tasklist_lock);
+ do_each_pid_task(pid, type, p) {
+ send_sigio_to_task(p, fown, fd, band, type);
+ } while_each_pid_task(pid, type, p);
+ read_unlock(&tasklist_lock);
+ }
out_unlock_fown:
read_unlock(&fown->lock);
}
static void send_sigurg_to_task(struct task_struct *p,
- struct fown_struct *fown, int group)
+ struct fown_struct *fown, enum pid_type type)
{
if (sigio_perm(p, fown, SIGURG))
- do_send_sig_info(SIGURG, SEND_SIG_PRIV, p, group);
+ do_send_sig_info(SIGURG, SEND_SIG_PRIV, p, type);
}
int send_sigurg(struct fown_struct *fown)
@@ -815,28 +817,30 @@ int send_sigurg(struct fown_struct *fown)
struct task_struct *p;
enum pid_type type;
struct pid *pid;
- int group = 1;
int ret = 0;
read_lock(&fown->lock);
type = fown->pid_type;
- if (type == PIDTYPE_MAX) {
- 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) {
- send_sigurg_to_task(p, fown, group);
- } while_each_pid_task(pid, type, p);
- read_unlock(&tasklist_lock);
+
+ if (type <= PIDTYPE_TGID) {
+ rcu_read_lock();
+ p = pid_task(pid, PIDTYPE_PID);
+ if (p)
+ send_sigurg_to_task(p, fown, type);
+ rcu_read_unlock();
+ } else {
+ read_lock(&tasklist_lock);
+ do_each_pid_task(pid, type, p) {
+ send_sigurg_to_task(p, fown, type);
+ } while_each_pid_task(pid, type, p);
+ read_unlock(&tasklist_lock);
+ }
out_unlock_fown:
read_unlock(&fown->lock);
return ret;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index a201fb0ac64f..b00a3f126a89 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/sched/signal.h>
#include <linux/module.h>
#include <linux/compat.h>
#include <linux/swap.h>
diff --git a/fs/locks.c b/fs/locks.c
index bc047a7edc47..5086bde5a18e 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -542,7 +542,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 a6365e6bc047..58d77dc696eb 100644
--- a/fs/notify/dnotify/dnotify.c
+++ b/fs/notify/dnotify/dnotify.c
@@ -19,6 +19,7 @@
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/sched.h>
+#include <linux/sched/signal.h>
#include <linux/dnotify.h>
#include <linux/init.h>
#include <linux/spinlock.h>
@@ -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 */
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index eb4e75175cfb..94b52157bf8d 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -8,6 +8,7 @@
#include <linux/mount.h>
#include <linux/sched.h>
#include <linux/sched/user.h>
+#include <linux/sched/signal.h>
#include <linux/types.h>
#include <linux/wait.h>
#include <linux/audit.h>