aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/signal.c')
-rw-r--r--arch/s390/kernel/signal.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index c19755815e53..05a85bc14c98 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -117,8 +117,8 @@ static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
117 117
118 /* Copy a 'clean' PSW mask to the user to avoid leaking 118 /* Copy a 'clean' PSW mask to the user to avoid leaking
119 information about whether PER is currently on. */ 119 information about whether PER is currently on. */
120 user_sregs.regs.psw.mask = psw_user_bits | PSW_MASK_EA | PSW_MASK_BA | 120 user_sregs.regs.psw.mask = psw_user_bits |
121 (regs->psw.mask & PSW_MASK_USER); 121 (regs->psw.mask & PSW_MASK_USER);
122 user_sregs.regs.psw.addr = regs->psw.addr; 122 user_sregs.regs.psw.addr = regs->psw.addr;
123 memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs)); 123 memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs));
124 memcpy(&user_sregs.regs.acrs, current->thread.acrs, 124 memcpy(&user_sregs.regs.acrs, current->thread.acrs,
@@ -145,9 +145,13 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
145 err = __copy_from_user(&user_sregs, sregs, sizeof(_sigregs)); 145 err = __copy_from_user(&user_sregs, sregs, sizeof(_sigregs));
146 if (err) 146 if (err)
147 return err; 147 return err;
148 /* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */
148 regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | 149 regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
149 (user_sregs.regs.psw.mask & PSW_MASK_USER); 150 (user_sregs.regs.psw.mask & PSW_MASK_USER);
150 regs->psw.addr = PSW_ADDR_AMODE | user_sregs.regs.psw.addr; 151 /* Check for invalid amode */
152 if (regs->psw.mask & PSW_MASK_EA)
153 regs->psw.mask |= PSW_MASK_BA;
154 regs->psw.addr = user_sregs.regs.psw.addr;
151 memcpy(&regs->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs)); 155 memcpy(&regs->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs));
152 memcpy(&current->thread.acrs, &user_sregs.regs.acrs, 156 memcpy(&current->thread.acrs, &user_sregs.regs.acrs,
153 sizeof(sregs->regs.acrs)); 157 sizeof(sregs->regs.acrs));
@@ -290,6 +294,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
290 294
291 /* Set up registers for signal handler */ 295 /* Set up registers for signal handler */
292 regs->gprs[15] = (unsigned long) frame; 296 regs->gprs[15] = (unsigned long) frame;
297 regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */
293 regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; 298 regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
294 299
295 regs->gprs[2] = map_signal(sig); 300 regs->gprs[2] = map_signal(sig);
@@ -358,6 +363,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
358 363
359 /* Set up registers for signal handler */ 364 /* Set up registers for signal handler */
360 regs->gprs[15] = (unsigned long) frame; 365 regs->gprs[15] = (unsigned long) frame;
366 regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */
361 regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; 367 regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
362 368
363 regs->gprs[2] = map_signal(sig); 369 regs->gprs[2] = map_signal(sig);