lkml.org 
[lkml]   [2008]   [Dec]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[RFC][PATCH] Notify init when processes are reparented to it
Allow the init daemon to be notified by signal when processes are
reparented to it. The signal has the same form as SIGCHLD except that
the si_status field contains the original parent proecss id.

Notification is enabled/disabled by prctl().

Signed-off-by: Scott James Remnant <scott@canonical.com>
---
fs/exec.c | 2 ++
include/linux/prctl.h | 4 ++++
include/linux/sched.h | 2 ++
kernel/exit.c | 3 +++
kernel/signal.c | 37 +++++++++++++++++++++++++++++++++++++
kernel/sys.c | 10 ++++++++++
security/commoncap.c | 1 +
security/selinux/hooks.c | 4 +++-
8 files changed, 62 insertions(+), 1 deletions(-)

diff --git a/fs/exec.c b/fs/exec.c
index c5f1a92..07a8782 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1011,6 +1011,7 @@ int flush_old_exec(struct linux_binprm * bprm)
suid_keys(current);
set_dumpable(current->mm, suid_dumpable);
current->pdeath_signal = 0;
+ current->adopt_signal = 0;
} else if (file_permission(bprm->file, MAY_READ) ||
(bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) {
suid_keys(current);
@@ -1099,6 +1100,7 @@ void compute_creds(struct linux_binprm *bprm)
if (bprm->e_uid != current->uid) {
suid_keys(current);
current->pdeath_signal = 0;
+ current->adopt_signal = 0;
}
exec_keys(current);

diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index 48d887e..1fa1b75 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -85,4 +85,8 @@
#define PR_SET_TIMERSLACK 29
#define PR_GET_TIMERSLACK 30

+/* Set/get notification of adoption by signal */
+#define PR_SET_ADOPTSIG 31 /* Second arg is a signal */
+#define PR_GET_ADOPTSIG 32 /* Second arg is a ptr to return the signal */
+
#endif /* _LINUX_PRCTL_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 55e30d1..bcd2af3 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1133,6 +1133,7 @@ struct task_struct {
int exit_state;
int exit_code, exit_signal;
int pdeath_signal; /* The signal sent when the parent dies */
+ int adopt_signal; /* The signal sent when a process is reparented */
/* ??? */
unsigned int personality;
unsigned did_exec:1;
@@ -1829,6 +1830,7 @@ extern int kill_pgrp(struct pid *pid, int sig, int priv);
extern int kill_pid(struct pid *pid, int sig, int priv);
extern int kill_proc_info(int, struct siginfo *, pid_t);
extern int do_notify_parent(struct task_struct *, int);
+extern void do_notify_parent_adopted(struct task_struct *, struct task_struct *);
extern void force_sig(int, struct task_struct *);
extern void force_sig_specific(int, struct task_struct *);
extern int send_sig(int, struct task_struct *, int);
diff --git a/kernel/exit.c b/kernel/exit.c
index 2d8be7e..813a232 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -813,6 +813,9 @@ static void reparent_thread(struct task_struct *p, struct task_struct *father)
/* We already hold the tasklist_lock here. */
group_send_sig_info(p->pdeath_signal, SEND_SIG_NOINFO, p);

+ if (p->real_parent->adopt_signal)
+ do_notify_parent_adopted(p, father);
+
list_move_tail(&p->sibling, &p->real_parent->children);

/* If this is a threaded reparent there is no need to
diff --git a/kernel/signal.c b/kernel/signal.c
index 4530fc6..40228e2 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1474,6 +1474,43 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, int why)
spin_unlock_irqrestore(&sighand->siglock, flags);
}

+/* Let init know that it has adopted a new child */
+void do_notify_parent_adopted(struct task_struct *tsk, struct task_struct *father)
+{
+ struct siginfo info;
+ unsigned long flags;
+ struct task_struct *reaper;
+ struct sighand_struct *sighand;
+ int ret;
+
+ reaper = tsk->real_parent;
+
+ memset (&info, 0, sizeof info);
+ info.si_signo = reaper->adopt_signal;
+ /*
+ * set code to the same range as SIGCHLD so the right bits of
+ * siginfo_t get copied, to userspace this will appear as si_code=0
+ */
+ info.si_code = __SI_CHLD;
+ /*
+ * see comment in do_notify_parent() about the following 4 lines
+ */
+ rcu_read_lock();
+ info.si_pid = task_pid_nr_ns(tsk, reaper->nsproxy->pid_ns);
+ info.si_status = task_pid_nr_ns(father, reaper->nsproxy->pid_ns);
+ rcu_read_unlock();
+
+ info.si_uid = tsk->uid;
+
+ info.si_utime = cputime_to_clock_t(tsk->utime);
+ info.si_stime = cputime_to_clock_t(tsk->stime);
+
+ sighand = reaper->sighand;
+ spin_lock_irqsave(&sighand->siglock, flags);
+ __group_send_sig_info(reaper->adopt_signal, &info, reaper);
+ spin_unlock_irqrestore(&sighand->siglock, flags);
+}
+
static inline int may_ptrace_stop(void)
{
if (!likely(current->ptrace & PT_PTRACED))
diff --git a/kernel/sys.c b/kernel/sys.c
index 31deba8..1720053 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1726,6 +1726,16 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
else
current->timer_slack_ns = arg2;
break;
+ case PR_SET_ADOPTSIG:
+ if (!valid_signal(arg2)) {
+ error = -EINVAL;
+ break;
+ }
+ current->adopt_signal = arg2;
+ break;
+ case PR_GET_ADOPTSIG:
+ error = put_user(current->adopt_signal, (int __user *)arg2);
+ break;
default:
error = -EINVAL;
break;
diff --git a/security/commoncap.c b/security/commoncap.c
index 6cbec11..a2da3ab 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -365,6 +365,7 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
current->cap_permitted)) {
set_dumpable(current->mm, suid_dumpable);
current->pdeath_signal = 0;
+ current->adopt_signal = 0;

if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
if (!capable(CAP_SETUID)) {
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 75777cb..8f089c8 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2280,8 +2280,10 @@ static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
spin_unlock_irq(&current->sighand->siglock);
}

- /* Always clear parent death signal on SID transitions. */
+ /* Always clear parent death signal and adoption notification
+ * on SID transitions. */
current->pdeath_signal = 0;
+ current->adopt_signal = 0;

/* Check whether the new SID can inherit resource limits
from the old SID. If not, reset all soft limits to
--
1.6.0.5


\
 
 \ /
  Last update: 2008-12-27 13:23    [W:0.060 / U:21.128 seconds]
©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site