From: Sukadev Bhattiprolu <[EMAIL PROTECTED]>
Subject: [PATCH 3/3] Signal semantics for pid namespaces

With support for multiple pid namespaces, each pid namespace has a
separate child reaper and this process needs some special handling
of signals. 

        - The child reaper should appear like a normal process to other
          processes in its ancestor namespaces and so should be killable
          (or not) in the usual way.

        - The child reaper should receive, from processes in it's active
          and decendent namespaces, only those signals for which it has
          installed a signal handler.

        - System-wide signals (eg: kill signum -1) from within a child namespace
          should only affect processes within that namespace and descendant
          namespaces. They should not be posted to processes in ancestor or
          sibling namespaces.

        - If the sender of a signal does not have a pid_t in the receiver's
          namespace (eg: a process in init_pid_ns sends a signal to a process
          in a descendant namespace), the sender's pid and uid should appear
          as 0 in the signal's 'siginfo' structure.

        - Existing rules for SIGIO delivery still apply and a process can
          choose any other process in its namespace and descendant namespaces
          to receive the SIGIO signal.
          
          The following appears to be incorrect in the fcntl() man page for
          F_SETOWN.

              Sending a signal to  the  owner  process  (group)  specified  by
              F_SETOWN  is  subject  to  the  same  permissions  checks as are
              described for kill(2), where the sending process is the one that
              employs F_SETOWN (but see BUGS below).

        Current behavior is that the SIGIO signal is delivered on behalf of
        the process that caused the event (eg: made data available on the
        file) and not the process that called fcntl().

Changelog:
        - [Oleg Nesterov]: Used the interfaces, is_current_in_ancestor_pid_ns()
          and is_current_in_same_or_ancestor_pid_ns().
        - [Oleg Nesterov]: Clear info.si_uid also when masquerading sender.

Signed-off-by: Sukadev Bhattiprolu <[EMAIL PROTECTED]>
---
 kernel/signal.c |   28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

Index: 2.6.23-rc4-mm1/kernel/signal.c
===================================================================
--- 2.6.23-rc4-mm1.orig/kernel/signal.c 2007-09-10 18:42:16.000000000 -0700
+++ 2.6.23-rc4-mm1/kernel/signal.c      2007-09-10 18:42:16.000000000 -0700
@@ -25,6 +25,7 @@
 #include <linux/capability.h>
 #include <linux/freezer.h>
 #include <linux/pid_namespace.h>
+#include <linux/pid.h>
 #include <linux/nsproxy.h>
 #include <linux/hardirq.h>
 
@@ -45,7 +46,10 @@ static int sig_init_ignore(struct task_s
 
        // Currently this check is a bit racy with exec(),
        // we can _simplify_ de_thread and close the race.
-       if (likely(!is_global_init(tsk->group_leader)))
+       if (likely(!is_container_init(tsk->group_leader)))
+               return 0;
+
+       if (is_current_in_ancestor_pid_ns(tsk) && !in_interrupt())
                return 0;
 
        return 1;
@@ -681,6 +685,20 @@ static void handle_stop_signal(int sig, 
        }
 }
 
+static void masquerade_sender(struct task_struct *t, struct sigqueue *q)
+{
+       /*
+        * If the sender does not have a pid_t in the receiver's active
+        * pid namespace, set si_pid to 0 and pretend signal originated
+        * from the kernel.
+        */
+       if (!pid_ns_equal(t)) {
+               q->info.si_pid = 0;
+               q->info.si_uid = 0;
+               q->info.si_code = SI_KERNEL;
+       }
+}
+
 static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
                        struct sigpending *signals)
 {
@@ -732,6 +750,7 @@ static int send_signal(int sig, struct s
                        copy_siginfo(&q->info, info);
                        break;
                }
+               masquerade_sender(t, q);
        } else if (!is_si_special(info)) {
                if (sig >= SIGRTMIN && info->si_code != SI_USER)
                /*
@@ -1165,6 +1184,7 @@ EXPORT_SYMBOL_GPL(kill_pid_info_as_uid);
 static int kill_something_info(int sig, struct siginfo *info, int pid)
 {
        int ret;
+
        rcu_read_lock();
        if (!pid) {
                ret = kill_pgrp_info(sig, info, task_pgrp(current));
@@ -1174,6 +1194,12 @@ static int kill_something_info(int sig, 
 
                read_lock(&tasklist_lock);
                for_each_process(p) {
+                       /*
+                        * System-wide signals only apply to pid namespace
+                        * of sender.
+                        */
+                       if (!is_current_in_same_or_ancestor_pid_ns(p))
+                               continue;
                        if (p->pid > 1 && !same_thread_group(p, current)) {
                                int err = group_send_sig_info(sig, info, p);
                                ++count;
_______________________________________________
Containers mailing list
[EMAIL PROTECTED]
https://lists.linux-foundation.org/mailman/listinfo/containers

_______________________________________________
Devel mailing list
Devel@openvz.org
https://openvz.org/mailman/listinfo/devel

Reply via email to