diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2017-07-16 23:05:57 -0400 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2018-07-21 11:43:12 -0400 |
commit | 019191342fecce4a461978a7191a43f313e19e86 (patch) | |
tree | b256a747d10ad9b2b674a5466f366b5109cc6509 /fs/fcntl.c | |
parent | 6883f81aac6f44e7df70a6af189b3689ff52cbfb (diff) |
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 <oleg@redhat.com>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r-- | fs/fcntl.c | 54 |
1 files changed, 32 insertions, 22 deletions
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) | |||
116 | struct pid *pid = NULL; | 116 | struct pid *pid = NULL; |
117 | int who = arg, ret = 0; | 117 | int who = arg, ret = 0; |
118 | 118 | ||
119 | type = PIDTYPE_PID; | 119 | type = PIDTYPE_TGID; |
120 | if (who < 0) { | 120 | if (who < 0) { |
121 | /* avoid overflow below */ | 121 | /* avoid overflow below */ |
122 | if (who == INT_MIN) | 122 | if (who == INT_MIN) |
@@ -143,7 +143,7 @@ EXPORT_SYMBOL(f_setown); | |||
143 | 143 | ||
144 | void f_delown(struct file *filp) | 144 | void f_delown(struct file *filp) |
145 | { | 145 | { |
146 | f_modown(filp, NULL, PIDTYPE_PID, 1); | 146 | f_modown(filp, NULL, PIDTYPE_TGID, 1); |
147 | } | 147 | } |
148 | 148 | ||
149 | pid_t f_getown(struct file *filp) | 149 | pid_t f_getown(struct file *filp) |
@@ -171,11 +171,11 @@ static int f_setown_ex(struct file *filp, unsigned long arg) | |||
171 | 171 | ||
172 | switch (owner.type) { | 172 | switch (owner.type) { |
173 | case F_OWNER_TID: | 173 | case F_OWNER_TID: |
174 | type = PIDTYPE_MAX; | 174 | type = PIDTYPE_PID; |
175 | break; | 175 | break; |
176 | 176 | ||
177 | case F_OWNER_PID: | 177 | case F_OWNER_PID: |
178 | type = PIDTYPE_PID; | 178 | type = PIDTYPE_TGID; |
179 | break; | 179 | break; |
180 | 180 | ||
181 | case F_OWNER_PGRP: | 181 | case F_OWNER_PGRP: |
@@ -206,11 +206,11 @@ static int f_getown_ex(struct file *filp, unsigned long arg) | |||
206 | read_lock(&filp->f_owner.lock); | 206 | read_lock(&filp->f_owner.lock); |
207 | owner.pid = pid_vnr(filp->f_owner.pid); | 207 | owner.pid = pid_vnr(filp->f_owner.pid); |
208 | switch (filp->f_owner.pid_type) { | 208 | switch (filp->f_owner.pid_type) { |
209 | case PIDTYPE_MAX: | 209 | case PIDTYPE_PID: |
210 | owner.type = F_OWNER_TID; | 210 | owner.type = F_OWNER_TID; |
211 | break; | 211 | break; |
212 | 212 | ||
213 | case PIDTYPE_PID: | 213 | case PIDTYPE_TGID: |
214 | owner.type = F_OWNER_PID; | 214 | owner.type = F_OWNER_PID; |
215 | break; | 215 | break; |
216 | 216 | ||
@@ -785,20 +785,25 @@ void send_sigio(struct fown_struct *fown, int fd, int band) | |||
785 | read_lock(&fown->lock); | 785 | read_lock(&fown->lock); |
786 | 786 | ||
787 | type = fown->pid_type; | 787 | type = fown->pid_type; |
788 | if (type == PIDTYPE_MAX) { | 788 | if (type == PIDTYPE_PID) |
789 | group = 0; | 789 | group = 0; |
790 | type = PIDTYPE_PID; | ||
791 | } | ||
792 | 790 | ||
793 | pid = fown->pid; | 791 | pid = fown->pid; |
794 | if (!pid) | 792 | if (!pid) |
795 | goto out_unlock_fown; | 793 | goto out_unlock_fown; |
796 | 794 | ||
797 | read_lock(&tasklist_lock); | 795 | if (type <= PIDTYPE_TGID) { |
798 | do_each_pid_task(pid, type, p) { | 796 | rcu_read_lock(); |
797 | p = pid_task(pid, PIDTYPE_PID); | ||
799 | send_sigio_to_task(p, fown, fd, band, group); | 798 | send_sigio_to_task(p, fown, fd, band, group); |
800 | } while_each_pid_task(pid, type, p); | 799 | rcu_read_unlock(); |
801 | read_unlock(&tasklist_lock); | 800 | } else { |
801 | read_lock(&tasklist_lock); | ||
802 | do_each_pid_task(pid, type, p) { | ||
803 | send_sigio_to_task(p, fown, fd, band, group); | ||
804 | } while_each_pid_task(pid, type, p); | ||
805 | read_unlock(&tasklist_lock); | ||
806 | } | ||
802 | out_unlock_fown: | 807 | out_unlock_fown: |
803 | read_unlock(&fown->lock); | 808 | read_unlock(&fown->lock); |
804 | } | 809 | } |
@@ -821,22 +826,27 @@ int send_sigurg(struct fown_struct *fown) | |||
821 | read_lock(&fown->lock); | 826 | read_lock(&fown->lock); |
822 | 827 | ||
823 | type = fown->pid_type; | 828 | type = fown->pid_type; |
824 | if (type == PIDTYPE_MAX) { | 829 | if (type == PIDTYPE_PID) |
825 | group = 0; | 830 | group = 0; |
826 | type = PIDTYPE_PID; | ||
827 | } | ||
828 | 831 | ||
829 | pid = fown->pid; | 832 | pid = fown->pid; |
830 | if (!pid) | 833 | if (!pid) |
831 | goto out_unlock_fown; | 834 | goto out_unlock_fown; |
832 | 835 | ||
833 | ret = 1; | 836 | ret = 1; |
834 | 837 | ||
835 | read_lock(&tasklist_lock); | 838 | if (type <= PIDTYPE_TGID) { |
836 | do_each_pid_task(pid, type, p) { | 839 | rcu_read_lock(); |
840 | p = pid_task(pid, PIDTYPE_PID); | ||
837 | send_sigurg_to_task(p, fown, group); | 841 | send_sigurg_to_task(p, fown, group); |
838 | } while_each_pid_task(pid, type, p); | 842 | rcu_read_unlock(); |
839 | read_unlock(&tasklist_lock); | 843 | } else { |
844 | read_lock(&tasklist_lock); | ||
845 | do_each_pid_task(pid, type, p) { | ||
846 | send_sigurg_to_task(p, fown, group); | ||
847 | } while_each_pid_task(pid, type, p); | ||
848 | read_unlock(&tasklist_lock); | ||
849 | } | ||
840 | out_unlock_fown: | 850 | out_unlock_fown: |
841 | read_unlock(&fown->lock); | 851 | read_unlock(&fown->lock); |
842 | return ret; | 852 | return ret; |