diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2006-10-04 14:01:58 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2006-10-04 14:01:58 -0400 |
commit | b05e37035298148b6c311eccf06ac50fd389f0b2 (patch) | |
tree | 8ff9dbbc71d7ef9b5ef025d98784bb6b2c1f30c0 /arch | |
parent | aa97b102527ff94fe04930a660f897ef2bafb2a8 (diff) |
[S390] user-copy optimization fallout.
Fix new restore_sigregs function. It copies the user space copy of the
old psw without correcting the psw.mask and the psw.addr high order bit.
While we are at it, simplify save_sigregs a bit.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/s390/kernel/signal.c | 17 |
1 files changed, 7 insertions, 10 deletions
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index 642095ec7c07..4392a77cbae8 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c | |||
@@ -113,17 +113,15 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | |||
113 | /* Returns non-zero on fault. */ | 113 | /* Returns non-zero on fault. */ |
114 | static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs) | 114 | static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs) |
115 | { | 115 | { |
116 | unsigned long old_mask = regs->psw.mask; | ||
117 | _sigregs user_sregs; | 116 | _sigregs user_sregs; |
118 | 117 | ||
119 | save_access_regs(current->thread.acrs); | 118 | save_access_regs(current->thread.acrs); |
120 | 119 | ||
121 | /* Copy a 'clean' PSW mask to the user to avoid leaking | 120 | /* Copy a 'clean' PSW mask to the user to avoid leaking |
122 | information about whether PER is currently on. */ | 121 | information about whether PER is currently on. */ |
123 | regs->psw.mask = PSW_MASK_MERGE(PSW_USER_BITS, regs->psw.mask); | 122 | user_sregs.regs.psw.mask = PSW_MASK_MERGE(PSW_USER_BITS, regs->psw.mask); |
124 | memcpy(&user_sregs.regs.psw, ®s->psw, sizeof(sregs->regs.psw) + | 123 | user_sregs.regs.psw.addr = regs->psw.addr; |
125 | sizeof(sregs->regs.gprs)); | 124 | memcpy(&user_sregs.regs.gprs, ®s->gprs, sizeof(sregs->regs.gprs)); |
126 | regs->psw.mask = old_mask; | ||
127 | memcpy(&user_sregs.regs.acrs, current->thread.acrs, | 125 | memcpy(&user_sregs.regs.acrs, current->thread.acrs, |
128 | sizeof(sregs->regs.acrs)); | 126 | sizeof(sregs->regs.acrs)); |
129 | /* | 127 | /* |
@@ -139,7 +137,6 @@ static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs) | |||
139 | /* Returns positive number on error */ | 137 | /* Returns positive number on error */ |
140 | static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs) | 138 | static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs) |
141 | { | 139 | { |
142 | unsigned long old_mask = regs->psw.mask; | ||
143 | int err; | 140 | int err; |
144 | _sigregs user_sregs; | 141 | _sigregs user_sregs; |
145 | 142 | ||
@@ -147,12 +144,12 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs) | |||
147 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 144 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
148 | 145 | ||
149 | err = __copy_from_user(&user_sregs, sregs, sizeof(_sigregs)); | 146 | err = __copy_from_user(&user_sregs, sregs, sizeof(_sigregs)); |
150 | regs->psw.mask = PSW_MASK_MERGE(old_mask, regs->psw.mask); | ||
151 | regs->psw.addr |= PSW_ADDR_AMODE; | ||
152 | if (err) | 147 | if (err) |
153 | return err; | 148 | return err; |
154 | memcpy(®s->psw, &user_sregs.regs.psw, sizeof(sregs->regs.psw) + | 149 | regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask, |
155 | sizeof(sregs->regs.gprs)); | 150 | user_sregs.regs.psw.mask); |
151 | regs->psw.addr = PSW_ADDR_AMODE | user_sregs.regs.psw.addr; | ||
152 | memcpy(®s->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs)); | ||
156 | memcpy(¤t->thread.acrs, &user_sregs.regs.acrs, | 153 | memcpy(¤t->thread.acrs, &user_sregs.regs.acrs, |
157 | sizeof(sregs->regs.acrs)); | 154 | sizeof(sregs->regs.acrs)); |
158 | restore_access_regs(current->thread.acrs); | 155 | restore_access_regs(current->thread.acrs); |