From: Sukadev Bhattiprolu <[EMAIL PROTECTED]>

get_signal_to_deliver() checks to ensure that /sbin/init does not
receive any unwanted signals. With implementation of multiple pid
namespaces, we need to extend this check for all "container-init"
processes (processes with pid == 1 in the pid namespace)
IOW, A container-init process, must not receive unwanted signals from
within the container.  However, the container-init must receive and
honor any signals it receives from an ancestor pid namespace (i.e it
must appear like a normal process in its parent namespace).

i.e for correct processing of the signal, either:

        - the recepient of the signal (in get_signal_to_deliver()) must
          have some information (such as pid namespace) of the sender
- or the sender of the signal (in send_signal()) should know
          whether the signal is an "unwanted" signal from the recepient's
          POV.

This patch provides a simple mechanism, to pass additional information from
the sender to the recepient (from send_signal() to get_signal_to_deliver()).

This patch is just a helper and a follow-on patch will use this infrastructure
to actually pass in information about the sender.

Implementation note:

        Most signal interfaces in the kernel operate on 'siginfo_t' data
        structure which is user-visible and cannot be easily modified/
        extended. So this patch defines a wrapper, 'struct kern_siginfo',
        around the 'siginfo_t' and allows extending this wrapper for future
        needs.

TODO:   This is more an exploratory patch and modifies only interfaces
        necessary to implement correct signal semantics in pid namespaces.
        
        If the approach is feasible, we could consistently use 'kern_siginfo'
        in other signal interfaces and possibly in 'struct sigqueue'.

        We could modify dequeue_signal() to directly work with 'kern_siginfo'
        and remove dequeue_signal_kern_info().

Signed-off-by: Sukadev Bhattiprolu <[EMAIL PROTECTED]>

---

include/linux/signal.h |    7 +++++++
kernel/signal.c        |   38 +++++++++++++++++++++++++++++++-------
2 files changed, 38 insertions(+), 7 deletions(-)

diff -upr linux-2.6.23-rc1-mm1.orig/include/linux/signal.h 
linux-2.6.23-rc1-mm1-7/include/linux/signal.h
--- linux-2.6.23-rc1-mm1.orig/include/linux/signal.h    2007-07-26 
16:34:45.000000000 +0400
+++ linux-2.6.23-rc1-mm1-7/include/linux/signal.h       2007-07-26 
16:36:37.000000000 +0400
@@ -7,6 +7,13 @@
#ifdef __KERNEL__
#include <linux/list.h>

+struct kern_siginfo {
+       siginfo_t *info;
+       int flags;
+};
+
+#define KERN_SIGINFO_CINIT     0x1     /* True iff signalling container-init */
+
/*
 * Real Time signals may be queued.
 */
diff -upr linux-2.6.23-rc1-mm1.orig/kernel/signal.c 
linux-2.6.23-rc1-mm1-7/kernel/signal.c
--- linux-2.6.23-rc1-mm1.orig/kernel/signal.c   2007-07-26 16:34:45.000000000 
+0400
+++ linux-2.6.23-rc1-mm1-7/kernel/signal.c      2007-07-26 16:36:37.000000000 
+0400
@@ -299,10 +299,12 @@ unblock_all_signals(void)
        spin_unlock_irqrestore(&current->sighand->siglock, flags);
}

-static int collect_signal(int sig, struct sigpending *list, siginfo_t *info)
+static int collect_signal(int sig, struct sigpending *list,
+               struct kern_siginfo *kinfo)
{
        struct sigqueue *q, *first = NULL;
        int still_pending = 0;
+       siginfo_t *info = kinfo->info;

        if (unlikely(!sigismember(&list->signal, sig)))
                return 0;
@@ -343,7 +348,7 @@ static int collect_signal(int sig, struc
}

static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
-                       siginfo_t *info)
+                       struct kern_siginfo *kinfo)
{
        int sig = next_signal(pending, mask);

@@ -357,7 +364,7 @@ static int __dequeue_signal(struct sigpe
                        }
                }

-               if (!collect_signal(sig, pending, info))
+               if (!collect_signal(sig, pending, kinfo))
                        sig = 0;
        }

@@ -370,18 +377,20 @@ static int __dequeue_signal(struct sigpe
 *
 * All callers have to hold the siglock.
 */
-int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
+int dequeue_signal_kern_info(struct task_struct *tsk, sigset_t *mask,
+               struct kern_siginfo *kinfo)
{
        int signr = 0;
+       siginfo_t *info = kinfo->info;

        /* We only dequeue private signals from ourselves, we don't let
         * signalfd steal them
         */
        if (tsk == current)
-               signr = __dequeue_signal(&tsk->pending, mask, info);
+               signr = __dequeue_signal(&tsk->pending, mask, kinfo);
        if (!signr) {
                signr = __dequeue_signal(&tsk->signal->shared_pending,
-                                        mask, info);
+                                        mask, kinfo);
                /*
                 * itimer signal ?
                 *
@@ -441,6 +450,22 @@ int dequeue_signal(struct task_struct *t
}

/*
+ * Dequeue a signal and return the element to the caller, which is
+ * expected to free it.
+ *
+ * All callers have to hold the siglock.
+ */
+int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
+{
+       struct kern_siginfo kinfo;
+
+       kinfo.info = info;
+       kinfo.flags = 0;
+
+       return dequeue_signal_kern_info(tsk, mask, &kinfo);
+}
+
+/*
 * Tell a process that it has a new active signal..
 *
 * NOTE! we rely on the previous spin_lock to
@@ -1779,6 +1873,10 @@ int get_signal_to_deliver(siginfo_t *inf
{
        sigset_t *mask = &current->blocked;
        int signr = 0;
+       struct kern_siginfo kinfo;
+
+       kinfo.info = info;
+       kinfo.flags = 0;

        try_to_freeze();

@@ -1791,7 +1889,7 @@ relock:
                    handle_group_stop())
                        goto relock;

-               signr = dequeue_signal(current, mask, info);
+               signr = dequeue_signal_kern_info(current, mask, &kinfo);

                if (!signr)
                        break; /* will return 0 */

_______________________________________________
Devel mailing list
[email protected]
https://openvz.org/mailman/listinfo/devel

Reply via email to