Commit c4b92fc112f7be5cce308128236ff75cc98535c3

Authored by Eric W. Biederman
Committed by Linus Torvalds
1 parent 558cb32548

[PATCH] pid: implement signal functions that take a struct pid *

Currently the signal functions all either take a task or a pid_t argument.
This patch implements variants that take a struct pid *.  After all of the
users have been update it is my intention to remove the variants that take a
pid_t as using pid_t can be more work (an extra hash table lookup) and
difficult to get right in the presence of multiple pid namespaces.

There are two kinds of functions introduced in this patch.  The are the
general use functions kill_pgrp and kill_pid which take a priv argument that
is ultimately used to create the appropriate siginfo information, Then there
are _kill_pgrp_info, kill_pgrp_info, kill_pid_info the internal implementation
helpers that take an explicit siginfo.

The distinction is made because filling out an explcit siginfo is tricky, and
will be even more tricky when pid namespaces are introduced.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 2 changed files with 52 additions and 10 deletions Side-by-side Diff

include/linux/sched.h
... ... @@ -1267,6 +1267,11 @@
1267 1267 extern int send_group_sig_info(int, struct siginfo *, struct task_struct *);
1268 1268 extern int force_sigsegv(int, struct task_struct *);
1269 1269 extern int force_sig_info(int, struct siginfo *, struct task_struct *);
  1270 +extern int __kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp);
  1271 +extern int kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp);
  1272 +extern int kill_pid_info(int sig, struct siginfo *info, struct pid *pid);
  1273 +extern int kill_pgrp(struct pid *pid, int sig, int priv);
  1274 +extern int kill_pid(struct pid *pid, int sig, int priv);
1270 1275 extern int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp);
1271 1276 extern int kill_pg_info(int, struct siginfo *, pid_t);
1272 1277 extern int kill_proc_info(int, struct siginfo *, pid_t);
... ... @@ -1055,28 +1055,44 @@
1055 1055 }
1056 1056  
1057 1057 /*
1058   - * kill_pg_info() sends a signal to a process group: this is what the tty
  1058 + * kill_pgrp_info() sends a signal to a process group: this is what the tty
1059 1059 * control characters do (^C, ^Z etc)
1060 1060 */
1061 1061  
1062   -int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp)
  1062 +int __kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp)
1063 1063 {
1064 1064 struct task_struct *p = NULL;
1065 1065 int retval, success;
1066 1066  
1067   - if (pgrp <= 0)
1068   - return -EINVAL;
1069   -
1070 1067 success = 0;
1071 1068 retval = -ESRCH;
1072   - do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
  1069 + do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
1073 1070 int err = group_send_sig_info(sig, info, p);
1074 1071 success |= !err;
1075 1072 retval = err;
1076   - } while_each_task_pid(pgrp, PIDTYPE_PGID, p);
  1073 + } while_each_pid_task(pgrp, PIDTYPE_PGID, p);
1077 1074 return success ? 0 : retval;
1078 1075 }
1079 1076  
  1077 +int kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp)
  1078 +{
  1079 + int retval;
  1080 +
  1081 + read_lock(&tasklist_lock);
  1082 + retval = __kill_pgrp_info(sig, info, pgrp);
  1083 + read_unlock(&tasklist_lock);
  1084 +
  1085 + return retval;
  1086 +}
  1087 +
  1088 +int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp)
  1089 +{
  1090 + if (pgrp <= 0)
  1091 + return -EINVAL;
  1092 +
  1093 + return __kill_pgrp_info(sig, info, find_pid(pgrp));
  1094 +}
  1095 +
1080 1096 int
1081 1097 kill_pg_info(int sig, struct siginfo *info, pid_t pgrp)
1082 1098 {
... ... @@ -1089,8 +1105,7 @@
1089 1105 return retval;
1090 1106 }
1091 1107  
1092   -int
1093   -kill_proc_info(int sig, struct siginfo *info, pid_t pid)
  1108 +int kill_pid_info(int sig, struct siginfo *info, struct pid *pid)
1094 1109 {
1095 1110 int error;
1096 1111 int acquired_tasklist_lock = 0;
... ... @@ -1101,7 +1116,7 @@
1101 1116 read_lock(&tasklist_lock);
1102 1117 acquired_tasklist_lock = 1;
1103 1118 }
1104   - p = find_task_by_pid(pid);
  1119 + p = pid_task(pid, PIDTYPE_PID);
1105 1120 error = -ESRCH;
1106 1121 if (p)
1107 1122 error = group_send_sig_info(sig, info, p);
... ... @@ -1111,6 +1126,16 @@
1111 1126 return error;
1112 1127 }
1113 1128  
  1129 +int
  1130 +kill_proc_info(int sig, struct siginfo *info, pid_t pid)
  1131 +{
  1132 + int error;
  1133 + rcu_read_lock();
  1134 + error = kill_pid_info(sig, info, find_pid(pid));
  1135 + rcu_read_unlock();
  1136 + return error;
  1137 +}
  1138 +
1114 1139 /* like kill_proc_info(), but doesn't use uid/euid of "current" */
1115 1140 int kill_proc_info_as_uid(int sig, struct siginfo *info, pid_t pid,
1116 1141 uid_t uid, uid_t euid, u32 secid)
... ... @@ -1263,6 +1288,18 @@
1263 1288 force_sig(SIGSEGV, p);
1264 1289 return 0;
1265 1290 }
  1291 +
  1292 +int kill_pgrp(struct pid *pid, int sig, int priv)
  1293 +{
  1294 + return kill_pgrp_info(sig, __si_special(priv), pid);
  1295 +}
  1296 +EXPORT_SYMBOL(kill_pgrp);
  1297 +
  1298 +int kill_pid(struct pid *pid, int sig, int priv)
  1299 +{
  1300 + return kill_pid_info(sig, __si_special(priv), pid);
  1301 +}
  1302 +EXPORT_SYMBOL(kill_pid);
1266 1303  
1267 1304 int
1268 1305 kill_pg(pid_t pgrp, int sig, int priv)