Loading kernel/signal.c +46 −61 Original line number Diff line number Diff line Loading @@ -3113,78 +3113,68 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact) } static int do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long sp) do_sigaltstack (const stack_t *ss, stack_t *oss, unsigned long sp) { stack_t oss; int error; struct task_struct *t = current; oss.ss_sp = (void __user *) current->sas_ss_sp; oss.ss_size = current->sas_ss_size; oss.ss_flags = sas_ss_flags(sp) | if (oss) { memset(oss, 0, sizeof(stack_t)); oss->ss_sp = (void __user *) t->sas_ss_sp; oss->ss_size = t->sas_ss_size; oss->ss_flags = sas_ss_flags(sp) | (current->sas_ss_flags & SS_FLAG_BITS); } if (uss) { void __user *ss_sp; size_t ss_size; unsigned ss_flags; if (ss) { void __user *ss_sp = ss->ss_sp; size_t ss_size = ss->ss_size; unsigned ss_flags = ss->ss_flags; int ss_mode; error = -EFAULT; if (!access_ok(VERIFY_READ, uss, sizeof(*uss))) goto out; error = __get_user(ss_sp, &uss->ss_sp) | __get_user(ss_flags, &uss->ss_flags) | __get_user(ss_size, &uss->ss_size); if (error) goto out; error = -EPERM; if (on_sig_stack(sp)) goto out; if (unlikely(on_sig_stack(sp))) return -EPERM; ss_mode = ss_flags & ~SS_FLAG_BITS; error = -EINVAL; if (ss_mode != SS_DISABLE && ss_mode != SS_ONSTACK && ss_mode != 0) goto out; if (unlikely(ss_mode != SS_DISABLE && ss_mode != SS_ONSTACK && ss_mode != 0)) return -EINVAL; if (ss_mode == SS_DISABLE) { ss_size = 0; ss_sp = NULL; } else { error = -ENOMEM; if (ss_size < MINSIGSTKSZ) goto out; if (unlikely(ss_size < MINSIGSTKSZ)) return -ENOMEM; } current->sas_ss_sp = (unsigned long) ss_sp; current->sas_ss_size = ss_size; current->sas_ss_flags = ss_flags; t->sas_ss_sp = (unsigned long) ss_sp; t->sas_ss_size = ss_size; t->sas_ss_flags = ss_flags; } error = 0; if (uoss) { error = -EFAULT; if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss))) goto out; error = __put_user(oss.ss_sp, &uoss->ss_sp) | __put_user(oss.ss_size, &uoss->ss_size) | __put_user(oss.ss_flags, &uoss->ss_flags); return 0; } out: return error; } SYSCALL_DEFINE2(sigaltstack,const stack_t __user *,uss, stack_t __user *,uoss) { return do_sigaltstack(uss, uoss, current_user_stack_pointer()); stack_t new, old; int err; if (uss && copy_from_user(&new, uss, sizeof(stack_t))) return -EFAULT; err = do_sigaltstack(uss ? &new : NULL, uoss ? &old : NULL, current_user_stack_pointer()); if (!err && uoss && copy_to_user(uoss, &old, sizeof(stack_t))) err = -EFAULT; return err; } int restore_altstack(const stack_t __user *uss) { int err = do_sigaltstack(uss, NULL, current_user_stack_pointer()); stack_t new; if (copy_from_user(&new, uss, sizeof(stack_t))) return -EFAULT; (void)do_sigaltstack(&new, NULL, current_user_stack_pointer()); /* squash all but EFAULT for now */ return err == -EFAULT ? err : 0; return 0; } int __save_altstack(stack_t __user *uss, unsigned long sp) Loading @@ -3207,29 +3197,24 @@ COMPAT_SYSCALL_DEFINE2(sigaltstack, { stack_t uss, uoss; int ret; mm_segment_t seg; if (uss_ptr) { compat_stack_t uss32; memset(&uss, 0, sizeof(stack_t)); if (copy_from_user(&uss32, uss_ptr, sizeof(compat_stack_t))) return -EFAULT; uss.ss_sp = compat_ptr(uss32.ss_sp); uss.ss_flags = uss32.ss_flags; uss.ss_size = uss32.ss_size; } seg = get_fs(); set_fs(KERNEL_DS); ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL), (stack_t __force __user *) &uoss, ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, compat_user_stack_pointer()); set_fs(seg); if (ret >= 0 && uoss_ptr) { if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(compat_stack_t)) || __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) || __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) || __put_user(uoss.ss_size, &uoss_ptr->ss_size)) compat_stack_t old; memset(&old, 0, sizeof(old)); old.ss_sp = ptr_to_compat(uoss.ss_sp); old.ss_flags = uoss.ss_flags; old.ss_size = uoss.ss_size; if (copy_to_user(uoss_ptr, &old, sizeof(compat_stack_t))) ret = -EFAULT; } return ret; Loading Loading
kernel/signal.c +46 −61 Original line number Diff line number Diff line Loading @@ -3113,78 +3113,68 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact) } static int do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long sp) do_sigaltstack (const stack_t *ss, stack_t *oss, unsigned long sp) { stack_t oss; int error; struct task_struct *t = current; oss.ss_sp = (void __user *) current->sas_ss_sp; oss.ss_size = current->sas_ss_size; oss.ss_flags = sas_ss_flags(sp) | if (oss) { memset(oss, 0, sizeof(stack_t)); oss->ss_sp = (void __user *) t->sas_ss_sp; oss->ss_size = t->sas_ss_size; oss->ss_flags = sas_ss_flags(sp) | (current->sas_ss_flags & SS_FLAG_BITS); } if (uss) { void __user *ss_sp; size_t ss_size; unsigned ss_flags; if (ss) { void __user *ss_sp = ss->ss_sp; size_t ss_size = ss->ss_size; unsigned ss_flags = ss->ss_flags; int ss_mode; error = -EFAULT; if (!access_ok(VERIFY_READ, uss, sizeof(*uss))) goto out; error = __get_user(ss_sp, &uss->ss_sp) | __get_user(ss_flags, &uss->ss_flags) | __get_user(ss_size, &uss->ss_size); if (error) goto out; error = -EPERM; if (on_sig_stack(sp)) goto out; if (unlikely(on_sig_stack(sp))) return -EPERM; ss_mode = ss_flags & ~SS_FLAG_BITS; error = -EINVAL; if (ss_mode != SS_DISABLE && ss_mode != SS_ONSTACK && ss_mode != 0) goto out; if (unlikely(ss_mode != SS_DISABLE && ss_mode != SS_ONSTACK && ss_mode != 0)) return -EINVAL; if (ss_mode == SS_DISABLE) { ss_size = 0; ss_sp = NULL; } else { error = -ENOMEM; if (ss_size < MINSIGSTKSZ) goto out; if (unlikely(ss_size < MINSIGSTKSZ)) return -ENOMEM; } current->sas_ss_sp = (unsigned long) ss_sp; current->sas_ss_size = ss_size; current->sas_ss_flags = ss_flags; t->sas_ss_sp = (unsigned long) ss_sp; t->sas_ss_size = ss_size; t->sas_ss_flags = ss_flags; } error = 0; if (uoss) { error = -EFAULT; if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss))) goto out; error = __put_user(oss.ss_sp, &uoss->ss_sp) | __put_user(oss.ss_size, &uoss->ss_size) | __put_user(oss.ss_flags, &uoss->ss_flags); return 0; } out: return error; } SYSCALL_DEFINE2(sigaltstack,const stack_t __user *,uss, stack_t __user *,uoss) { return do_sigaltstack(uss, uoss, current_user_stack_pointer()); stack_t new, old; int err; if (uss && copy_from_user(&new, uss, sizeof(stack_t))) return -EFAULT; err = do_sigaltstack(uss ? &new : NULL, uoss ? &old : NULL, current_user_stack_pointer()); if (!err && uoss && copy_to_user(uoss, &old, sizeof(stack_t))) err = -EFAULT; return err; } int restore_altstack(const stack_t __user *uss) { int err = do_sigaltstack(uss, NULL, current_user_stack_pointer()); stack_t new; if (copy_from_user(&new, uss, sizeof(stack_t))) return -EFAULT; (void)do_sigaltstack(&new, NULL, current_user_stack_pointer()); /* squash all but EFAULT for now */ return err == -EFAULT ? err : 0; return 0; } int __save_altstack(stack_t __user *uss, unsigned long sp) Loading @@ -3207,29 +3197,24 @@ COMPAT_SYSCALL_DEFINE2(sigaltstack, { stack_t uss, uoss; int ret; mm_segment_t seg; if (uss_ptr) { compat_stack_t uss32; memset(&uss, 0, sizeof(stack_t)); if (copy_from_user(&uss32, uss_ptr, sizeof(compat_stack_t))) return -EFAULT; uss.ss_sp = compat_ptr(uss32.ss_sp); uss.ss_flags = uss32.ss_flags; uss.ss_size = uss32.ss_size; } seg = get_fs(); set_fs(KERNEL_DS); ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL), (stack_t __force __user *) &uoss, ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, compat_user_stack_pointer()); set_fs(seg); if (ret >= 0 && uoss_ptr) { if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(compat_stack_t)) || __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) || __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) || __put_user(uoss.ss_size, &uoss_ptr->ss_size)) compat_stack_t old; memset(&old, 0, sizeof(old)); old.ss_sp = ptr_to_compat(uoss.ss_sp); old.ss_flags = uoss.ss_flags; old.ss_size = uoss.ss_size; if (copy_to_user(uoss_ptr, &old, sizeof(compat_stack_t))) ret = -EFAULT; } return ret; Loading