Commit 4382a79b authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'uaccess.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull misc uaccess updates from Al Viro:
 "Assorted uaccess patches for this cycle - the stuff that didn't fit
  into thematic series"

* 'uaccess.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  bpf: make bpf_check_uarg_tail_zero() use check_zeroed_user()
  x86: kvm_hv_set_msr(): use __put_user() instead of 32bit __clear_user()
  user_regset_copyout_zero(): use clear_user()
  TEST_ACCESS_OK _never_ had been checked anywhere
  x86: switch cp_stat64() to unsafe_put_user()
  binfmt_flat: don't use __put_user()
  binfmt_elf_fdpic: don't use __... uaccess primitives
  binfmt_elf: don't bother with __{put,copy_to}_user()
  pselect6() and friends: take handling the combined 6th/7th args into helper
parents 79ca035d b7e4b65f
...@@ -32,13 +32,6 @@ extern pmd_t initial_pg_pmd[]; ...@@ -32,13 +32,6 @@ extern pmd_t initial_pg_pmd[];
void paging_init(void); void paging_init(void);
void sync_initial_page_table(void); void sync_initial_page_table(void);
/*
* Define this if things work differently on an i386 and an i486:
* it will (on an i486) warn about kernel memory accesses that are
* done without a 'access_ok( ..)'
*/
#undef TEST_ACCESS_OK
#ifdef CONFIG_X86_PAE #ifdef CONFIG_X86_PAE
# include <asm/pgtable-3level.h> # include <asm/pgtable-3level.h>
#else #else
......
...@@ -135,26 +135,30 @@ static int cp_stat64(struct stat64 __user *ubuf, struct kstat *stat) ...@@ -135,26 +135,30 @@ static int cp_stat64(struct stat64 __user *ubuf, struct kstat *stat)
typeof(ubuf->st_gid) gid = 0; typeof(ubuf->st_gid) gid = 0;
SET_UID(uid, from_kuid_munged(current_user_ns(), stat->uid)); SET_UID(uid, from_kuid_munged(current_user_ns(), stat->uid));
SET_GID(gid, from_kgid_munged(current_user_ns(), stat->gid)); SET_GID(gid, from_kgid_munged(current_user_ns(), stat->gid));
if (!access_ok(ubuf, sizeof(struct stat64)) || if (!user_write_access_begin(ubuf, sizeof(struct stat64)))
__put_user(huge_encode_dev(stat->dev), &ubuf->st_dev) ||
__put_user(stat->ino, &ubuf->__st_ino) ||
__put_user(stat->ino, &ubuf->st_ino) ||
__put_user(stat->mode, &ubuf->st_mode) ||
__put_user(stat->nlink, &ubuf->st_nlink) ||
__put_user(uid, &ubuf->st_uid) ||
__put_user(gid, &ubuf->st_gid) ||
__put_user(huge_encode_dev(stat->rdev), &ubuf->st_rdev) ||
__put_user(stat->size, &ubuf->st_size) ||
__put_user(stat->atime.tv_sec, &ubuf->st_atime) ||
__put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec) ||
__put_user(stat->mtime.tv_sec, &ubuf->st_mtime) ||
__put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec) ||
__put_user(stat->ctime.tv_sec, &ubuf->st_ctime) ||
__put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec) ||
__put_user(stat->blksize, &ubuf->st_blksize) ||
__put_user(stat->blocks, &ubuf->st_blocks))
return -EFAULT; return -EFAULT;
unsafe_put_user(huge_encode_dev(stat->dev), &ubuf->st_dev, Efault);
unsafe_put_user(stat->ino, &ubuf->__st_ino, Efault);
unsafe_put_user(stat->ino, &ubuf->st_ino, Efault);
unsafe_put_user(stat->mode, &ubuf->st_mode, Efault);
unsafe_put_user(stat->nlink, &ubuf->st_nlink, Efault);
unsafe_put_user(uid, &ubuf->st_uid, Efault);
unsafe_put_user(gid, &ubuf->st_gid, Efault);
unsafe_put_user(huge_encode_dev(stat->rdev), &ubuf->st_rdev, Efault);
unsafe_put_user(stat->size, &ubuf->st_size, Efault);
unsafe_put_user(stat->atime.tv_sec, &ubuf->st_atime, Efault);
unsafe_put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec, Efault);
unsafe_put_user(stat->mtime.tv_sec, &ubuf->st_mtime, Efault);
unsafe_put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec, Efault);
unsafe_put_user(stat->ctime.tv_sec, &ubuf->st_ctime, Efault);
unsafe_put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec, Efault);
unsafe_put_user(stat->blksize, &ubuf->st_blksize, Efault);
unsafe_put_user(stat->blocks, &ubuf->st_blocks, Efault);
user_access_end();
return 0; return 0;
Efault:
user_write_access_end();
return -EFAULT;
} }
COMPAT_SYSCALL_DEFINE2(ia32_stat64, const char __user *, filename, COMPAT_SYSCALL_DEFINE2(ia32_stat64, const char __user *, filename,
......
...@@ -1252,7 +1252,7 @@ static int kvm_hv_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host) ...@@ -1252,7 +1252,7 @@ static int kvm_hv_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host)
* only, there can be valuable data in the rest which needs * only, there can be valuable data in the rest which needs
* to be preserved e.g. on migration. * to be preserved e.g. on migration.
*/ */
if (__clear_user((void __user *)addr, sizeof(u32))) if (__put_user(0, (u32 __user *)addr))
return 1; return 1;
hv_vcpu->hv_vapic = data; hv_vcpu->hv_vapic = data;
kvm_vcpu_mark_page_dirty(vcpu, gfn); kvm_vcpu_mark_page_dirty(vcpu, gfn);
......
...@@ -208,7 +208,7 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec, ...@@ -208,7 +208,7 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec,
size_t len = strlen(k_platform) + 1; size_t len = strlen(k_platform) + 1;
u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len); u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
if (__copy_to_user(u_platform, k_platform, len)) if (copy_to_user(u_platform, k_platform, len))
return -EFAULT; return -EFAULT;
} }
...@@ -221,7 +221,7 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec, ...@@ -221,7 +221,7 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec,
size_t len = strlen(k_base_platform) + 1; size_t len = strlen(k_base_platform) + 1;
u_base_platform = (elf_addr_t __user *)STACK_ALLOC(p, len); u_base_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
if (__copy_to_user(u_base_platform, k_base_platform, len)) if (copy_to_user(u_base_platform, k_base_platform, len))
return -EFAULT; return -EFAULT;
} }
...@@ -231,7 +231,7 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec, ...@@ -231,7 +231,7 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec,
get_random_bytes(k_rand_bytes, sizeof(k_rand_bytes)); get_random_bytes(k_rand_bytes, sizeof(k_rand_bytes));
u_rand_bytes = (elf_addr_t __user *) u_rand_bytes = (elf_addr_t __user *)
STACK_ALLOC(p, sizeof(k_rand_bytes)); STACK_ALLOC(p, sizeof(k_rand_bytes));
if (__copy_to_user(u_rand_bytes, k_rand_bytes, sizeof(k_rand_bytes))) if (copy_to_user(u_rand_bytes, k_rand_bytes, sizeof(k_rand_bytes)))
return -EFAULT; return -EFAULT;
/* Create the ELF interpreter info */ /* Create the ELF interpreter info */
...@@ -314,21 +314,21 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec, ...@@ -314,21 +314,21 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec,
return -EFAULT; return -EFAULT;
/* Now, let's put argc (and argv, envp if appropriate) on the stack */ /* Now, let's put argc (and argv, envp if appropriate) on the stack */
if (__put_user(argc, sp++)) if (put_user(argc, sp++))
return -EFAULT; return -EFAULT;
/* Populate list of argv pointers back to argv strings. */ /* Populate list of argv pointers back to argv strings. */
p = mm->arg_end = mm->arg_start; p = mm->arg_end = mm->arg_start;
while (argc-- > 0) { while (argc-- > 0) {
size_t len; size_t len;
if (__put_user((elf_addr_t)p, sp++)) if (put_user((elf_addr_t)p, sp++))
return -EFAULT; return -EFAULT;
len = strnlen_user((void __user *)p, MAX_ARG_STRLEN); len = strnlen_user((void __user *)p, MAX_ARG_STRLEN);
if (!len || len > MAX_ARG_STRLEN) if (!len || len > MAX_ARG_STRLEN)
return -EINVAL; return -EINVAL;
p += len; p += len;
} }
if (__put_user(0, sp++)) if (put_user(0, sp++))
return -EFAULT; return -EFAULT;
mm->arg_end = p; mm->arg_end = p;
...@@ -336,14 +336,14 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec, ...@@ -336,14 +336,14 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec,
mm->env_end = mm->env_start = p; mm->env_end = mm->env_start = p;
while (envc-- > 0) { while (envc-- > 0) {
size_t len; size_t len;
if (__put_user((elf_addr_t)p, sp++)) if (put_user((elf_addr_t)p, sp++))
return -EFAULT; return -EFAULT;
len = strnlen_user((void __user *)p, MAX_ARG_STRLEN); len = strnlen_user((void __user *)p, MAX_ARG_STRLEN);
if (!len || len > MAX_ARG_STRLEN) if (!len || len > MAX_ARG_STRLEN)
return -EINVAL; return -EINVAL;
p += len; p += len;
} }
if (__put_user(0, sp++)) if (put_user(0, sp++))
return -EFAULT; return -EFAULT;
mm->env_end = p; mm->env_end = p;
......
...@@ -536,7 +536,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, ...@@ -536,7 +536,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
platform_len = strlen(k_platform) + 1; platform_len = strlen(k_platform) + 1;
sp -= platform_len; sp -= platform_len;
u_platform = (char __user *) sp; u_platform = (char __user *) sp;
if (__copy_to_user(u_platform, k_platform, platform_len) != 0) if (copy_to_user(u_platform, k_platform, platform_len) != 0)
return -EFAULT; return -EFAULT;
} }
...@@ -551,7 +551,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, ...@@ -551,7 +551,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
platform_len = strlen(k_base_platform) + 1; platform_len = strlen(k_base_platform) + 1;
sp -= platform_len; sp -= platform_len;
u_base_platform = (char __user *) sp; u_base_platform = (char __user *) sp;
if (__copy_to_user(u_base_platform, k_base_platform, platform_len) != 0) if (copy_to_user(u_base_platform, k_base_platform, platform_len) != 0)
return -EFAULT; return -EFAULT;
} }
...@@ -603,11 +603,13 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, ...@@ -603,11 +603,13 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
/* put the ELF interpreter info on the stack */ /* put the ELF interpreter info on the stack */
#define NEW_AUX_ENT(id, val) \ #define NEW_AUX_ENT(id, val) \
do { \ do { \
struct { unsigned long _id, _val; } __user *ent; \ struct { unsigned long _id, _val; } __user *ent, v; \
\ \
ent = (void __user *) csp; \ ent = (void __user *) csp; \
__put_user((id), &ent[nr]._id); \ v._id = (id); \
__put_user((val), &ent[nr]._val); \ v._val = (val); \
if (copy_to_user(ent + nr, &v, sizeof(v))) \
return -EFAULT; \
nr++; \ nr++; \
} while (0) } while (0)
...@@ -674,7 +676,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, ...@@ -674,7 +676,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
/* stack argc */ /* stack argc */
csp -= sizeof(unsigned long); csp -= sizeof(unsigned long);
__put_user(bprm->argc, (unsigned long __user *) csp); if (put_user(bprm->argc, (unsigned long __user *) csp))
return -EFAULT;
BUG_ON(csp != sp); BUG_ON(csp != sp);
...@@ -688,25 +691,29 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, ...@@ -688,25 +691,29 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
p = (char __user *) current->mm->arg_start; p = (char __user *) current->mm->arg_start;
for (loop = bprm->argc; loop > 0; loop--) { for (loop = bprm->argc; loop > 0; loop--) {
__put_user((elf_caddr_t) p, argv++); if (put_user((elf_caddr_t) p, argv++))
return -EFAULT;
len = strnlen_user(p, MAX_ARG_STRLEN); len = strnlen_user(p, MAX_ARG_STRLEN);
if (!len || len > MAX_ARG_STRLEN) if (!len || len > MAX_ARG_STRLEN)
return -EINVAL; return -EINVAL;
p += len; p += len;
} }
__put_user(NULL, argv); if (put_user(NULL, argv))
return -EFAULT;
current->mm->arg_end = (unsigned long) p; current->mm->arg_end = (unsigned long) p;
/* fill in the envv[] array */ /* fill in the envv[] array */
current->mm->env_start = (unsigned long) p; current->mm->env_start = (unsigned long) p;
for (loop = bprm->envc; loop > 0; loop--) { for (loop = bprm->envc; loop > 0; loop--) {
__put_user((elf_caddr_t)(unsigned long) p, envp++); if (put_user((elf_caddr_t)(unsigned long) p, envp++))
return -EFAULT;
len = strnlen_user(p, MAX_ARG_STRLEN); len = strnlen_user(p, MAX_ARG_STRLEN);
if (!len || len > MAX_ARG_STRLEN) if (!len || len > MAX_ARG_STRLEN)
return -EINVAL; return -EINVAL;
p += len; p += len;
} }
__put_user(NULL, envp); if (put_user(NULL, envp))
return -EFAULT;
current->mm->env_end = (unsigned long) p; current->mm->env_end = (unsigned long) p;
mm->start_stack = (unsigned long) sp; mm->start_stack = (unsigned long) sp;
...@@ -848,8 +855,8 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params, ...@@ -848,8 +855,8 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
tmp = phdr->p_memsz / sizeof(Elf32_Dyn); tmp = phdr->p_memsz / sizeof(Elf32_Dyn);
dyn = (Elf32_Dyn __user *)params->dynamic_addr; dyn = (Elf32_Dyn __user *)params->dynamic_addr;
__get_user(d_tag, &dyn[tmp - 1].d_tag); if (get_user(d_tag, &dyn[tmp - 1].d_tag) ||
if (d_tag != 0) d_tag != 0)
goto dynamic_error; goto dynamic_error;
break; break;
} }
......
...@@ -138,35 +138,40 @@ static int create_flat_tables(struct linux_binprm *bprm, unsigned long arg_start ...@@ -138,35 +138,40 @@ static int create_flat_tables(struct linux_binprm *bprm, unsigned long arg_start
current->mm->start_stack = (unsigned long)sp & -FLAT_STACK_ALIGN; current->mm->start_stack = (unsigned long)sp & -FLAT_STACK_ALIGN;
sp = (unsigned long __user *)current->mm->start_stack; sp = (unsigned long __user *)current->mm->start_stack;
__put_user(bprm->argc, sp++); if (put_user(bprm->argc, sp++))
return -EFAULT;
if (IS_ENABLED(CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK)) { if (IS_ENABLED(CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK)) {
unsigned long argv, envp; unsigned long argv, envp;
argv = (unsigned long)(sp + 2); argv = (unsigned long)(sp + 2);
envp = (unsigned long)(sp + 2 + bprm->argc + 1); envp = (unsigned long)(sp + 2 + bprm->argc + 1);
__put_user(argv, sp++); if (put_user(argv, sp++) || put_user(envp, sp++))
__put_user(envp, sp++); return -EFAULT;
} }
current->mm->arg_start = (unsigned long)p; current->mm->arg_start = (unsigned long)p;
for (i = bprm->argc; i > 0; i--) { for (i = bprm->argc; i > 0; i--) {
__put_user((unsigned long)p, sp++); if (put_user((unsigned long)p, sp++))
return -EFAULT;
len = strnlen_user(p, MAX_ARG_STRLEN); len = strnlen_user(p, MAX_ARG_STRLEN);
if (!len || len > MAX_ARG_STRLEN) if (!len || len > MAX_ARG_STRLEN)
return -EINVAL; return -EINVAL;
p += len; p += len;
} }
__put_user(0, sp++); if (put_user(0, sp++))
return -EFAULT;
current->mm->arg_end = (unsigned long)p; current->mm->arg_end = (unsigned long)p;
current->mm->env_start = (unsigned long) p; current->mm->env_start = (unsigned long) p;
for (i = bprm->envc; i > 0; i--) { for (i = bprm->envc; i > 0; i--) {
__put_user((unsigned long)p, sp++); if (put_user((unsigned long)p, sp++))
return -EFAULT;
len = strnlen_user(p, MAX_ARG_STRLEN); len = strnlen_user(p, MAX_ARG_STRLEN);
if (!len || len > MAX_ARG_STRLEN) if (!len || len > MAX_ARG_STRLEN)
return -EINVAL; return -EINVAL;
p += len; p += len;
} }
__put_user(0, sp++); if (put_user(0, sp++))
return -EFAULT;
current->mm->env_end = (unsigned long)p; current->mm->env_end = (unsigned long)p;
return 0; return 0;
...@@ -996,7 +1001,8 @@ static int load_flat_binary(struct linux_binprm *bprm) ...@@ -996,7 +1001,8 @@ static int load_flat_binary(struct linux_binprm *bprm)
unsigned long __user *sp; unsigned long __user *sp;
current->mm->start_stack -= sizeof(unsigned long); current->mm->start_stack -= sizeof(unsigned long);
sp = (unsigned long __user *)current->mm->start_stack; sp = (unsigned long __user *)current->mm->start_stack;
__put_user(start_addr, sp); if (put_user(start_addr, sp))
return -EFAULT;
start_addr = libinfo.lib_list[i].entry; start_addr = libinfo.lib_list[i].entry;
} }
} }
......
...@@ -766,22 +766,38 @@ static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp, ...@@ -766,22 +766,38 @@ static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp,
* which has a pointer to the sigset_t itself followed by a size_t containing * which has a pointer to the sigset_t itself followed by a size_t containing
* the sigset size. * the sigset size.
*/ */
struct sigset_argpack {
sigset_t __user *p;
size_t size;
};
static inline int get_sigset_argpack(struct sigset_argpack *to,
struct sigset_argpack __user *from)
{
// the path is hot enough for overhead of copy_from_user() to matter
if (from) {
if (!user_read_access_begin(from, sizeof(*from)))
return -EFAULT;
unsafe_get_user(to->p, &from->p, Efault);
unsafe_get_user(to->size, &from->size, Efault);
user_read_access_end();
}
return 0;
Efault:
user_access_end();
return -EFAULT;
}
SYSCALL_DEFINE6(pselect6, int, n, fd_set __user *, inp, fd_set __user *, outp, SYSCALL_DEFINE6(pselect6, int, n, fd_set __user *, inp, fd_set __user *, outp,
fd_set __user *, exp, struct __kernel_timespec __user *, tsp, fd_set __user *, exp, struct __kernel_timespec __user *, tsp,
void __user *, sig) void __user *, sig)
{ {
size_t sigsetsize = 0; struct sigset_argpack x = {NULL, 0};
sigset_t __user *up = NULL;
if (get_sigset_argpack(&x, sig))
if (sig) { return -EFAULT;
if (!access_ok(sig, sizeof(void *)+sizeof(size_t))
|| __get_user(up, (sigset_t __user * __user *)sig)
|| __get_user(sigsetsize,
(size_t __user *)(sig+sizeof(void *))))
return -EFAULT;
}
return do_pselect(n, inp, outp, exp, tsp, up, sigsetsize, PT_TIMESPEC); return do_pselect(n, inp, outp, exp, tsp, x.p, x.size, PT_TIMESPEC);
} }
#if defined(CONFIG_COMPAT_32BIT_TIME) && !defined(CONFIG_64BIT) #if defined(CONFIG_COMPAT_32BIT_TIME) && !defined(CONFIG_64BIT)
...@@ -790,18 +806,12 @@ SYSCALL_DEFINE6(pselect6_time32, int, n, fd_set __user *, inp, fd_set __user *, ...@@ -790,18 +806,12 @@ SYSCALL_DEFINE6(pselect6_time32, int, n, fd_set __user *, inp, fd_set __user *,
fd_set __user *, exp, struct old_timespec32 __user *, tsp, fd_set __user *, exp, struct old_timespec32 __user *, tsp,
void __user *, sig) void __user *, sig)
{ {
size_t sigsetsize = 0; struct sigset_argpack x = {NULL, 0};
sigset_t __user *up = NULL;
if (get_sigset_argpack(&x, sig))
if (sig) { return -EFAULT;
if (!access_ok(sig, sizeof(void *)+sizeof(size_t))
|| __get_user(up, (sigset_t __user * __user *)sig)
|| __get_user(sigsetsize,
(size_t __user *)(sig+sizeof(void *))))
return -EFAULT;
}
return do_pselect(n, inp, outp, exp, tsp, up, sigsetsize, PT_OLD_TIMESPEC); return do_pselect(n, inp, outp, exp, tsp, x.p, x.size, PT_OLD_TIMESPEC);
} }
#endif #endif
...@@ -1325,24 +1335,37 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp, ...@@ -1325,24 +1335,37 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp,
return poll_select_finish(&end_time, tsp, type, ret); return poll_select_finish(&end_time, tsp, type, ret);
} }
struct compat_sigset_argpack {
compat_uptr_t p;
compat_size_t size;
};
static inline int get_compat_sigset_argpack(struct compat_sigset_argpack *to,
struct compat_sigset_argpack __user *from)
{
if (from) {
if (!user_read_access_begin(from, sizeof(*from)))
return -EFAULT;
unsafe_get_user(to->p, &from->p, Efault);
unsafe_get_user(to->size, &from->size, Efault);
user_read_access_end();
}
return 0;
Efault:
user_access_end();
return -EFAULT;
}
COMPAT_SYSCALL_DEFINE6(pselect6_time64, int, n, compat_ulong_t __user *, inp, COMPAT_SYSCALL_DEFINE6(pselect6_time64, int, n, compat_ulong_t __user *, inp,
compat_ulong_t __user *, outp, compat_ulong_t __user *, exp, compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
struct __kernel_timespec __user *, tsp, void __user *, sig) struct __kernel_timespec __user *, tsp, void __user *, sig)
{ {
compat_size_t sigsetsize = 0; struct compat_sigset_argpack x = {0, 0};
compat_uptr_t up = 0;
if (get_compat_sigset_argpack(&x, sig))
if (sig) { return -EFAULT;
if (!access_ok(sig,
sizeof(compat_uptr_t)+sizeof(compat_size_t)) ||
__get_user(up, (compat_uptr_t __user *)sig) ||
__get_user(sigsetsize,
(compat_size_t __user *)(sig+sizeof(up))))
return -EFAULT;
}
return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(up), return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(x.p),
sigsetsize, PT_TIMESPEC); x.size, PT_TIMESPEC);
} }
#if defined(CONFIG_COMPAT_32BIT_TIME) #if defined(CONFIG_COMPAT_32BIT_TIME)
...@@ -1351,20 +1374,13 @@ COMPAT_SYSCALL_DEFINE6(pselect6_time32, int, n, compat_ulong_t __user *, inp, ...@@ -1351,20 +1374,13 @@ COMPAT_SYSCALL_DEFINE6(pselect6_time32, int, n, compat_ulong_t __user *, inp,
compat_ulong_t __user *, outp, compat_ulong_t __user *, exp, compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
struct old_timespec32 __user *, tsp, void __user *, sig) struct old_timespec32 __user *, tsp, void __user *, sig)
{ {
compat_size_t sigsetsize = 0; struct compat_sigset_argpack x = {0, 0};
compat_uptr_t up = 0;
if (get_compat_sigset_argpack(&x, sig))
if (sig) { return -EFAULT;
if (!access_ok(sig,
sizeof(compat_uptr_t)+sizeof(compat_size_t)) ||
__get_user(up, (compat_uptr_t __user *)sig) ||
__get_user(sigsetsize,
(compat_size_t __user *)(sig+sizeof(up))))
return -EFAULT;
}
return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(up), return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(x.p),
sigsetsize, PT_OLD_TIMESPEC); x.size, PT_OLD_TIMESPEC);
} }
#endif #endif
......
...@@ -320,7 +320,7 @@ static inline int user_regset_copyout_zero(unsigned int *pos, ...@@ -320,7 +320,7 @@ static inline int user_regset_copyout_zero(unsigned int *pos,
if (*kbuf) { if (*kbuf) {
memset(*kbuf, 0, copy); memset(*kbuf, 0, copy);
*kbuf += copy; *kbuf += copy;
} else if (__clear_user(*ubuf, copy)) } else if (clear_user(*ubuf, copy))
return -EFAULT; return -EFAULT;
else else
*ubuf += copy; *ubuf += copy;
......
...@@ -74,32 +74,19 @@ int bpf_check_uarg_tail_zero(void __user *uaddr, ...@@ -74,32 +74,19 @@ int bpf_check_uarg_tail_zero(void __user *uaddr,
size_t expected_size, size_t expected_size,
size_t actual_size) size_t actual_size)
{ {
unsigned char __user *addr; unsigned char __user *addr = uaddr + expected_size;
unsigned char __user *end; int res;
unsigned char val;
int err;
if (unlikely(actual_size > PAGE_SIZE)) /* silly large */ if (unlikely(actual_size > PAGE_SIZE)) /* silly large */
return -E2BIG; return -E2BIG;
if (unlikely(!access_ok(uaddr, actual_size)))
return -EFAULT;
if (actual_size <= expected_size) if (actual_size <= expected_size)
return 0; return 0;
addr = uaddr + expected_size; res = check_zeroed_user(addr, actual_size - expected_size);
end = uaddr + actual_size; if (res < 0)
return res;
for (; addr < end; addr++) { return res ? 0 : -E2BIG;
err = get_user(val, addr);
if (err)
return err;
if (val)
return -E2BIG;
}
return 0;
} }
const struct bpf_map_ops bpf_map_offload_ops = { const struct bpf_map_ops bpf_map_offload_ops = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment