Merge remote-tracking branch 'sm8250/lineage-20' into lineage-23.2
* sm8250/lineage-20: UPSTREAM: arm64: Implement copy_thread_tls UPSTREAM: clone3: validate stack arguments UPSTREAM: clone3: switch to copy_struct_from_user() Change-Id: I5580578220cbf78c7bf0b79cdadc548633bc9976
This commit is contained in:
3 files changed
+45
-33
No files matched your search
@@ -133,6 +133,7 @@ config ARM64
|
|||||||
select HAVE_CMPXCHG_DOUBLE
|
select HAVE_CMPXCHG_DOUBLE
|
||||||
select HAVE_CMPXCHG_LOCAL
|
select HAVE_CMPXCHG_LOCAL
|
||||||
select HAVE_CONTEXT_TRACKING
|
select HAVE_CONTEXT_TRACKING
|
||||||
|
select HAVE_COPY_THREAD_TLS
|
||||||
select HAVE_DEBUG_BUGVERBOSE
|
select HAVE_DEBUG_BUGVERBOSE
|
||||||
select HAVE_DEBUG_KMEMLEAK
|
select HAVE_DEBUG_KMEMLEAK
|
||||||
select HAVE_DMA_CONTIGUOUS
|
select HAVE_DMA_CONTIGUOUS
|
||||||
|
|||||||
@@ -394,8 +394,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
|
|||||||
|
|
||||||
asmlinkage void ret_from_fork(void) asm("ret_from_fork");
|
asmlinkage void ret_from_fork(void) asm("ret_from_fork");
|
||||||
|
|
||||||
int copy_thread(unsigned long clone_flags, unsigned long stack_start,
|
int copy_thread_tls(unsigned long clone_flags, unsigned long stack_start,
|
||||||
unsigned long stk_sz, struct task_struct *p)
|
unsigned long stk_sz, struct task_struct *p, unsigned long tls)
|
||||||
{
|
{
|
||||||
struct pt_regs *childregs = task_pt_regs(p);
|
struct pt_regs *childregs = task_pt_regs(p);
|
||||||
|
|
||||||
@@ -428,11 +428,11 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If a TLS pointer was passed to clone (4th argument), use it
|
* If a TLS pointer was passed to clone, use it for the new
|
||||||
* for the new thread.
|
* thread.
|
||||||
*/
|
*/
|
||||||
if (clone_flags & CLONE_SETTLS)
|
if (clone_flags & CLONE_SETTLS)
|
||||||
p->thread.uw.tp_value = childregs->regs[3];
|
p->thread.uw.tp_value = tls;
|
||||||
} else {
|
} else {
|
||||||
memset(childregs, 0, sizeof(struct pt_regs));
|
memset(childregs, 0, sizeof(struct pt_regs));
|
||||||
childregs->pstate = PSR_MODE_EL1h;
|
childregs->pstate = PSR_MODE_EL1h;
|
||||||
|
|||||||
+39
-28
@@ -2561,40 +2561,20 @@ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
|
|||||||
#ifdef __ARCH_WANT_SYS_CLONE3
|
#ifdef __ARCH_WANT_SYS_CLONE3
|
||||||
noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
|
noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
|
||||||
struct clone_args __user *uargs,
|
struct clone_args __user *uargs,
|
||||||
size_t size)
|
size_t usize)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
struct clone_args args;
|
struct clone_args args;
|
||||||
pid_t *kset_tid = kargs->set_tid;
|
pid_t *kset_tid = kargs->set_tid;
|
||||||
|
|
||||||
if (unlikely(size > PAGE_SIZE))
|
if (unlikely(usize > PAGE_SIZE))
|
||||||
return -E2BIG;
|
return -E2BIG;
|
||||||
|
if (unlikely(usize < CLONE_ARGS_SIZE_VER0))
|
||||||
if (unlikely(size < sizeof(struct clone_args)))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (unlikely(!access_ok(VERIFY_READ, uargs, size)))
|
err = copy_struct_from_user(&args, sizeof(args), uargs, usize);
|
||||||
return -EFAULT;
|
if (err)
|
||||||
|
return err;
|
||||||
if (size > sizeof(struct clone_args)) {
|
|
||||||
unsigned char __user *addr;
|
|
||||||
unsigned char __user *end;
|
|
||||||
unsigned char val;
|
|
||||||
|
|
||||||
addr = (void __user *)uargs + sizeof(struct clone_args);
|
|
||||||
end = (void __user *)uargs + size;
|
|
||||||
|
|
||||||
for (; addr < end; addr++) {
|
|
||||||
if (get_user(val, addr))
|
|
||||||
return -EFAULT;
|
|
||||||
if (val)
|
|
||||||
return -E2BIG;
|
|
||||||
}
|
|
||||||
|
|
||||||
size = sizeof(struct clone_args);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (copy_from_user(&args, uargs, size))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
if (unlikely(args.set_tid_size > MAX_PID_NS_LEVEL))
|
if (unlikely(args.set_tid_size > MAX_PID_NS_LEVEL))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -2635,7 +2615,35 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool clone3_args_valid(const struct kernel_clone_args *kargs)
|
/**
|
||||||
|
* clone3_stack_valid - check and prepare stack
|
||||||
|
* @kargs: kernel clone args
|
||||||
|
*
|
||||||
|
* Verify that the stack arguments userspace gave us are sane.
|
||||||
|
* In addition, set the stack direction for userspace since it's easy for us to
|
||||||
|
* determine.
|
||||||
|
*/
|
||||||
|
static inline bool clone3_stack_valid(struct kernel_clone_args *kargs)
|
||||||
|
{
|
||||||
|
if (kargs->stack == 0) {
|
||||||
|
if (kargs->stack_size > 0)
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (kargs->stack_size == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!access_ok(VERIFY_WRITE, (void __user *)kargs->stack, kargs->stack_size))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#if !defined(CONFIG_STACK_GROWSUP) && !defined(CONFIG_IA64)
|
||||||
|
kargs->stack += kargs->stack_size;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool clone3_args_valid(struct kernel_clone_args *kargs)
|
||||||
{
|
{
|
||||||
/* Verify that no unknown flags are passed along. */
|
/* Verify that no unknown flags are passed along. */
|
||||||
if (kargs->flags & ~(CLONE_LEGACY_FLAGS | CLONE_CLEAR_SIGHAND))
|
if (kargs->flags & ~(CLONE_LEGACY_FLAGS | CLONE_CLEAR_SIGHAND))
|
||||||
@@ -2656,6 +2664,9 @@ static bool clone3_args_valid(const struct kernel_clone_args *kargs)
|
|||||||
kargs->exit_signal)
|
kargs->exit_signal)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!clone3_stack_valid(kargs))
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user