aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index cba193ceda0d..50c992643771 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1193,6 +1193,40 @@ kill_proc_info(int sig, struct siginfo *info, pid_t pid)
1193 return error; 1193 return error;
1194} 1194}
1195 1195
1196/* like kill_proc_info(), but doesn't use uid/euid of "current" */
1197int kill_proc_info_as_uid(int sig, struct siginfo *info, pid_t pid,
1198 uid_t uid, uid_t euid)
1199{
1200 int ret = -EINVAL;
1201 struct task_struct *p;
1202
1203 if (!valid_signal(sig))
1204 return ret;
1205
1206 read_lock(&tasklist_lock);
1207 p = find_task_by_pid(pid);
1208 if (!p) {
1209 ret = -ESRCH;
1210 goto out_unlock;
1211 }
1212 if ((!info || ((unsigned long)info != 1 &&
1213 (unsigned long)info != 2 && SI_FROMUSER(info)))
1214 && (euid != p->suid) && (euid != p->uid)
1215 && (uid != p->suid) && (uid != p->uid)) {
1216 ret = -EPERM;
1217 goto out_unlock;
1218 }
1219 if (sig && p->sighand) {
1220 unsigned long flags;
1221 spin_lock_irqsave(&p->sighand->siglock, flags);
1222 ret = __group_send_sig_info(sig, info, p);
1223 spin_unlock_irqrestore(&p->sighand->siglock, flags);
1224 }
1225out_unlock:
1226 read_unlock(&tasklist_lock);
1227 return ret;
1228}
1229EXPORT_SYMBOL_GPL(kill_proc_info_as_uid);
1196 1230
1197/* 1231/*
1198 * kill_something_info() interprets pid in interesting ways just like kill(2). 1232 * kill_something_info() interprets pid in interesting ways just like kill(2).