mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 13:41:51 +00:00
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
This commit is contained in:
commit
4382a79b27
@ -32,13 +32,6 @@ extern pmd_t initial_pg_pmd[];
|
||||
void paging_init(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
|
||||
# include <asm/pgtable-3level.h>
|
||||
#else
|
||||
|
@ -135,26 +135,30 @@ static int cp_stat64(struct stat64 __user *ubuf, struct kstat *stat)
|
||||
typeof(ubuf->st_gid) gid = 0;
|
||||
SET_UID(uid, from_kuid_munged(current_user_ns(), stat->uid));
|
||||
SET_GID(gid, from_kgid_munged(current_user_ns(), stat->gid));
|
||||
if (!access_ok(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))
|
||||
if (!user_write_access_begin(ubuf, sizeof(struct stat64)))
|
||||
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;
|
||||
Efault:
|
||||
user_write_access_end();
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
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)
|
||||
* only, there can be valuable data in the rest which needs
|
||||
* to be preserved e.g. on migration.
|
||||
*/
|
||||
if (__clear_user((void __user *)addr, sizeof(u32)))
|
||||
if (__put_user(0, (u32 __user *)addr))
|
||||
return 1;
|
||||
hv_vcpu->hv_vapic = data;
|
||||
kvm_vcpu_mark_page_dirty(vcpu, gfn);
|
||||
|
@ -208,7 +208,7 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec,
|
||||
size_t len = strlen(k_platform) + 1;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -221,7 +221,7 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec,
|
||||
size_t len = strlen(k_base_platform) + 1;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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));
|
||||
u_rand_bytes = (elf_addr_t __user *)
|
||||
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;
|
||||
|
||||
/* Create the ELF interpreter info */
|
||||
@ -314,21 +314,21 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec,
|
||||
return -EFAULT;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Populate list of argv pointers back to argv strings. */
|
||||
p = mm->arg_end = mm->arg_start;
|
||||
while (argc-- > 0) {
|
||||
size_t len;
|
||||
if (__put_user((elf_addr_t)p, sp++))
|
||||
if (put_user((elf_addr_t)p, sp++))
|
||||
return -EFAULT;
|
||||
len = strnlen_user((void __user *)p, MAX_ARG_STRLEN);
|
||||
if (!len || len > MAX_ARG_STRLEN)
|
||||
return -EINVAL;
|
||||
p += len;
|
||||
}
|
||||
if (__put_user(0, sp++))
|
||||
if (put_user(0, sp++))
|
||||
return -EFAULT;
|
||||
mm->arg_end = p;
|
||||
|
||||
@ -336,14 +336,14 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec,
|
||||
mm->env_end = mm->env_start = p;
|
||||
while (envc-- > 0) {
|
||||
size_t len;
|
||||
if (__put_user((elf_addr_t)p, sp++))
|
||||
if (put_user((elf_addr_t)p, sp++))
|
||||
return -EFAULT;
|
||||
len = strnlen_user((void __user *)p, MAX_ARG_STRLEN);
|
||||
if (!len || len > MAX_ARG_STRLEN)
|
||||
return -EINVAL;
|
||||
p += len;
|
||||
}
|
||||
if (__put_user(0, sp++))
|
||||
if (put_user(0, sp++))
|
||||
return -EFAULT;
|
||||
mm->env_end = p;
|
||||
|
||||
|
@ -536,7 +536,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
|
||||
platform_len = strlen(k_platform) + 1;
|
||||
sp -= platform_len;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -551,7 +551,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
|
||||
platform_len = strlen(k_base_platform) + 1;
|
||||
sp -= platform_len;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -603,11 +603,13 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
|
||||
/* put the ELF interpreter info on the stack */
|
||||
#define NEW_AUX_ENT(id, val) \
|
||||
do { \
|
||||
struct { unsigned long _id, _val; } __user *ent; \
|
||||
struct { unsigned long _id, _val; } __user *ent, v; \
|
||||
\
|
||||
ent = (void __user *) csp; \
|
||||
__put_user((id), &ent[nr]._id); \
|
||||
__put_user((val), &ent[nr]._val); \
|
||||
v._id = (id); \
|
||||
v._val = (val); \
|
||||
if (copy_to_user(ent + nr, &v, sizeof(v))) \
|
||||
return -EFAULT; \
|
||||
nr++; \
|
||||
} while (0)
|
||||
|
||||
@ -674,7 +676,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
|
||||
|
||||
/* stack argc */
|
||||
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);
|
||||
|
||||
@ -688,25 +691,29 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
|
||||
|
||||
p = (char __user *) current->mm->arg_start;
|
||||
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);
|
||||
if (!len || len > MAX_ARG_STRLEN)
|
||||
return -EINVAL;
|
||||
p += len;
|
||||
}
|
||||
__put_user(NULL, argv);
|
||||
if (put_user(NULL, argv))
|
||||
return -EFAULT;
|
||||
current->mm->arg_end = (unsigned long) p;
|
||||
|
||||
/* fill in the envv[] array */
|
||||
current->mm->env_start = (unsigned long) p;
|
||||
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);
|
||||
if (!len || len > MAX_ARG_STRLEN)
|
||||
return -EINVAL;
|
||||
p += len;
|
||||
}
|
||||
__put_user(NULL, envp);
|
||||
if (put_user(NULL, envp))
|
||||
return -EFAULT;
|
||||
current->mm->env_end = (unsigned long) p;
|
||||
|
||||
mm->start_stack = (unsigned long) sp;
|
||||
@ -848,8 +855,8 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
|
||||
|
||||
tmp = phdr->p_memsz / sizeof(Elf32_Dyn);
|
||||
dyn = (Elf32_Dyn __user *)params->dynamic_addr;
|
||||
__get_user(d_tag, &dyn[tmp - 1].d_tag);
|
||||
if (d_tag != 0)
|
||||
if (get_user(d_tag, &dyn[tmp - 1].d_tag) ||
|
||||
d_tag != 0)
|
||||
goto dynamic_error;
|
||||
break;
|
||||
}
|
||||
|
@ -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;
|
||||
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)) {
|
||||
unsigned long argv, envp;
|
||||
argv = (unsigned long)(sp + 2);
|
||||
envp = (unsigned long)(sp + 2 + bprm->argc + 1);
|
||||
__put_user(argv, sp++);
|
||||
__put_user(envp, sp++);
|
||||
if (put_user(argv, sp++) || put_user(envp, sp++))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
current->mm->arg_start = (unsigned long)p;
|
||||
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);
|
||||
if (!len || len > MAX_ARG_STRLEN)
|
||||
return -EINVAL;
|
||||
p += len;
|
||||
}
|
||||
__put_user(0, sp++);
|
||||
if (put_user(0, sp++))
|
||||
return -EFAULT;
|
||||
current->mm->arg_end = (unsigned long)p;
|
||||
|
||||
current->mm->env_start = (unsigned long) p;
|
||||
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);
|
||||
if (!len || len > MAX_ARG_STRLEN)
|
||||
return -EINVAL;
|
||||
p += len;
|
||||
}
|
||||
__put_user(0, sp++);
|
||||
if (put_user(0, sp++))
|
||||
return -EFAULT;
|
||||
current->mm->env_end = (unsigned long)p;
|
||||
|
||||
return 0;
|
||||
@ -996,7 +1001,8 @@ static int load_flat_binary(struct linux_binprm *bprm)
|
||||
unsigned long __user *sp;
|
||||
current->mm->start_stack -= sizeof(unsigned long);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
104
fs/select.c
104
fs/select.c
@ -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
|
||||
* 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,
|
||||
fd_set __user *, exp, struct __kernel_timespec __user *, tsp,
|
||||
void __user *, sig)
|
||||
{
|
||||
size_t sigsetsize = 0;
|
||||
sigset_t __user *up = NULL;
|
||||
struct sigset_argpack x = {NULL, 0};
|
||||
|
||||
if (sig) {
|
||||
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;
|
||||
}
|
||||
if (get_sigset_argpack(&x, sig))
|
||||
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)
|
||||
@ -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,
|
||||
void __user *, sig)
|
||||
{
|
||||
size_t sigsetsize = 0;
|
||||
sigset_t __user *up = NULL;
|
||||
struct sigset_argpack x = {NULL, 0};
|
||||
|
||||
if (sig) {
|
||||
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;
|
||||
}
|
||||
if (get_sigset_argpack(&x, sig))
|
||||
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
|
||||
@ -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);
|
||||
}
|
||||
|
||||
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_ulong_t __user *, outp, compat_ulong_t __user *, exp,
|
||||
struct __kernel_timespec __user *, tsp, void __user *, sig)
|
||||
{
|
||||
compat_size_t sigsetsize = 0;
|
||||
compat_uptr_t up = 0;
|
||||
struct compat_sigset_argpack x = {0, 0};
|
||||
|
||||
if (sig) {
|
||||
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;
|
||||
}
|
||||
if (get_compat_sigset_argpack(&x, sig))
|
||||
return -EFAULT;
|
||||
|
||||
return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(up),
|
||||
sigsetsize, PT_TIMESPEC);
|
||||
return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(x.p),
|
||||
x.size, PT_TIMESPEC);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_COMPAT_32BIT_TIME)
|
||||
@ -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,
|
||||
struct old_timespec32 __user *, tsp, void __user *, sig)
|
||||
{
|
||||
compat_size_t sigsetsize = 0;
|
||||
compat_uptr_t up = 0;
|
||||
struct compat_sigset_argpack x = {0, 0};
|
||||
|
||||
if (sig) {
|
||||
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;
|
||||
}
|
||||
if (get_compat_sigset_argpack(&x, sig))
|
||||
return -EFAULT;
|
||||
|
||||
return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(up),
|
||||
sigsetsize, PT_OLD_TIMESPEC);
|
||||
return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(x.p),
|
||||
x.size, PT_OLD_TIMESPEC);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -320,7 +320,7 @@ static inline int user_regset_copyout_zero(unsigned int *pos,
|
||||
if (*kbuf) {
|
||||
memset(*kbuf, 0, copy);
|
||||
*kbuf += copy;
|
||||
} else if (__clear_user(*ubuf, copy))
|
||||
} else if (clear_user(*ubuf, copy))
|
||||
return -EFAULT;
|
||||
else
|
||||
*ubuf += copy;
|
||||
|
@ -74,32 +74,19 @@ int bpf_check_uarg_tail_zero(void __user *uaddr,
|
||||
size_t expected_size,
|
||||
size_t actual_size)
|
||||
{
|
||||
unsigned char __user *addr;
|
||||
unsigned char __user *end;
|
||||
unsigned char val;
|
||||
int err;
|
||||
unsigned char __user *addr = uaddr + expected_size;
|
||||
int res;
|
||||
|
||||
if (unlikely(actual_size > PAGE_SIZE)) /* silly large */
|
||||
return -E2BIG;
|
||||
|
||||
if (unlikely(!access_ok(uaddr, actual_size)))
|
||||
return -EFAULT;
|
||||
|
||||
if (actual_size <= expected_size)
|
||||
return 0;
|
||||
|
||||
addr = uaddr + expected_size;
|
||||
end = uaddr + actual_size;
|
||||
|
||||
for (; addr < end; addr++) {
|
||||
err = get_user(val, addr);
|
||||
if (err)
|
||||
return err;
|
||||
if (val)
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
return 0;
|
||||
res = check_zeroed_user(addr, actual_size - expected_size);
|
||||
if (res < 0)
|
||||
return res;
|
||||
return res ? 0 : -E2BIG;
|
||||
}
|
||||
|
||||
const struct bpf_map_ops bpf_map_offload_ops = {
|
||||
|
Loading…
Reference in New Issue
Block a user