If we checkpoint a task that has a pending signal with si_code < 0
(easily caused by raising a blocked signal) we hit the BUG() in
fill_siginfo.  In this case, we should checkpoint and restore si_pid,
si_uid, and the members of the si_val union.

Signed-off-by: Nathan Lynch <[email protected]>
---
 kernel/signal.c |   40 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/kernel/signal.c b/kernel/signal.c
index 85757e1..cc7aee9 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2920,6 +2920,25 @@ static void fill_siginfo(struct ckpt_siginfo *si, const 
siginfo_t *info)
        si->csi_code = info->si_code;
 
        /* TODO: convert info->si_uid to uid_objref */
+       if (info->si_code < 0) {
+               switch(info->si_code) {
+               case SI_QUEUE:
+               case SI_TIMER:
+               case SI_MESGQ:
+               case SI_ASYNCIO:
+               case SI_SIGIO:
+               case SI_TKILL:
+               case SI_DETHREAD:
+                       si->csi_pid = info->si_pid;
+                       si->csi_uid = info->si_uid;
+                       si->csi_ptr = (unsigned long)info->si_ptr;
+                       si->csi_int = info->si_int;
+                       break;
+               default:
+                       BUG();
+               }
+               return;
+       }
 
        switch (info->si_code & __SI_MASK) {
        case __SI_KILL:
@@ -2972,6 +2991,27 @@ static int load_siginfo(siginfo_t *info, const struct 
ckpt_siginfo *si)
        info->si_code = si->csi_code;
 
        /* TODO: validate remaining signal fields */
+       if (info->si_code < 0) {
+               switch(info->si_code) {
+               case SI_QUEUE:
+               case SI_TIMER:
+               case SI_MESGQ:
+               case SI_ASYNCIO:
+               case SI_SIGIO:
+               case SI_TKILL:
+               case SI_DETHREAD:
+                       info->si_pid = si->csi_pid;
+                       info->si_uid = si->csi_uid;
+                       info->si_ptr = (void __user *)
+                               (unsigned long)si->csi_ptr;
+                       info->si_int = si->csi_int;
+                       break;
+               default:
+                       return -EINVAL;
+                       break;
+               }
+               return 0;
+       }
 
        switch (info->si_code & __SI_MASK) {
        case __SI_KILL:
-- 
1.7.1.1

_______________________________________________
Containers mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/containers

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

Reply via email to