mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-09 07:23:14 +00:00
saner copy_mount_options()
don't bother with the byte-by-byte loops, etc. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
324282c025
commit
12efec5602
@ -2979,39 +2979,10 @@ static void shrink_submounts(struct mount *mnt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Some copy_from_user() implementations do not return the exact number of
|
|
||||||
* bytes remaining to copy on a fault. But copy_mount_options() requires that.
|
|
||||||
* Note that this function differs from copy_from_user() in that it will oops
|
|
||||||
* on bad values of `to', rather than returning a short copy.
|
|
||||||
*/
|
|
||||||
static long exact_copy_from_user(void *to, const void __user * from,
|
|
||||||
unsigned long n)
|
|
||||||
{
|
|
||||||
char *t = to;
|
|
||||||
const char __user *f = from;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
if (!access_ok(from, n))
|
|
||||||
return n;
|
|
||||||
|
|
||||||
while (n) {
|
|
||||||
if (__get_user(c, f)) {
|
|
||||||
memset(t, 0, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*t++ = c;
|
|
||||||
f++;
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *copy_mount_options(const void __user * data)
|
void *copy_mount_options(const void __user * data)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
unsigned long size;
|
|
||||||
char *copy;
|
char *copy;
|
||||||
|
unsigned size;
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -3020,22 +2991,16 @@ void *copy_mount_options(const void __user * data)
|
|||||||
if (!copy)
|
if (!copy)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
/* We only care that *some* data at the address the user
|
size = PAGE_SIZE - offset_in_page(data);
|
||||||
* gave us is valid. Just in case, we'll zero
|
|
||||||
* the remainder of the page.
|
|
||||||
*/
|
|
||||||
/* copy_from_user cannot cross TASK_SIZE ! */
|
|
||||||
size = TASK_SIZE - (unsigned long)untagged_addr(data);
|
|
||||||
if (size > PAGE_SIZE)
|
|
||||||
size = PAGE_SIZE;
|
|
||||||
|
|
||||||
i = size - exact_copy_from_user(copy, data, size);
|
if (copy_from_user(copy, data, size)) {
|
||||||
if (!i) {
|
|
||||||
kfree(copy);
|
kfree(copy);
|
||||||
return ERR_PTR(-EFAULT);
|
return ERR_PTR(-EFAULT);
|
||||||
}
|
}
|
||||||
if (i != PAGE_SIZE)
|
if (size != PAGE_SIZE) {
|
||||||
memset(copy + i, 0, PAGE_SIZE - i);
|
if (copy_from_user(copy + size, data + size, PAGE_SIZE - size))
|
||||||
|
memset(copy + size, 0, PAGE_SIZE - size);
|
||||||
|
}
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user