diff options
Diffstat (limited to 'arch/s390/kernel/signal.c')
-rw-r--r-- | arch/s390/kernel/signal.c | 14 |
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, ®s->gprs, sizeof(sregs->regs.gprs)); | 123 | memcpy(&user_sregs.regs.gprs, ®s->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(®s->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs)); | 155 | memcpy(®s->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs)); |
152 | memcpy(¤t->thread.acrs, &user_sregs.regs.acrs, | 156 | memcpy(¤t->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); |