compat_{get,put}_bitmap(): use unsafe_{get,put}_user()
unroll the inner loops, while we are at it Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
9a46903792
commit
1e1fc13348
|
@ -388,8 +388,7 @@ asmlinkage long compat_sys_wait4(compat_pid_t pid,
|
||||||
|
|
||||||
#define BITS_PER_COMPAT_LONG (8*sizeof(compat_long_t))
|
#define BITS_PER_COMPAT_LONG (8*sizeof(compat_long_t))
|
||||||
|
|
||||||
#define BITS_TO_COMPAT_LONGS(bits) \
|
#define BITS_TO_COMPAT_LONGS(bits) DIV_ROUND_UP(bits, BITS_PER_COMPAT_LONG)
|
||||||
(((bits)+BITS_PER_COMPAT_LONG-1)/BITS_PER_COMPAT_LONG)
|
|
||||||
|
|
||||||
long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
|
long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
|
||||||
unsigned long bitmap_size);
|
unsigned long bitmap_size);
|
||||||
|
|
|
@ -871,84 +871,59 @@ int get_compat_sigevent(struct sigevent *event,
|
||||||
long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
|
long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
|
||||||
unsigned long bitmap_size)
|
unsigned long bitmap_size)
|
||||||
{
|
{
|
||||||
int i, j;
|
|
||||||
unsigned long m;
|
|
||||||
compat_ulong_t um;
|
|
||||||
unsigned long nr_compat_longs;
|
unsigned long nr_compat_longs;
|
||||||
|
|
||||||
/* align bitmap up to nearest compat_long_t boundary */
|
/* align bitmap up to nearest compat_long_t boundary */
|
||||||
bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
|
bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
|
||||||
|
nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
|
||||||
|
|
||||||
if (!access_ok(VERIFY_READ, umask, bitmap_size / 8))
|
if (!access_ok(VERIFY_READ, umask, bitmap_size / 8))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
|
user_access_begin();
|
||||||
|
while (nr_compat_longs > 1) {
|
||||||
for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) {
|
compat_ulong_t l1, l2;
|
||||||
m = 0;
|
unsafe_get_user(l1, umask++, Efault);
|
||||||
|
unsafe_get_user(l2, umask++, Efault);
|
||||||
for (j = 0; j < sizeof(m)/sizeof(um); j++) {
|
*mask++ = ((unsigned long)l2 << BITS_PER_COMPAT_LONG) | l1;
|
||||||
/*
|
nr_compat_longs -= 2;
|
||||||
* We dont want to read past the end of the userspace
|
|
||||||
* bitmap. We must however ensure the end of the
|
|
||||||
* kernel bitmap is zeroed.
|
|
||||||
*/
|
|
||||||
if (nr_compat_longs) {
|
|
||||||
nr_compat_longs--;
|
|
||||||
if (__get_user(um, umask))
|
|
||||||
return -EFAULT;
|
|
||||||
} else {
|
|
||||||
um = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
umask++;
|
|
||||||
m |= (long)um << (j * BITS_PER_COMPAT_LONG);
|
|
||||||
}
|
|
||||||
*mask++ = m;
|
|
||||||
}
|
}
|
||||||
|
if (nr_compat_longs)
|
||||||
|
unsafe_get_user(*mask, umask++, Efault);
|
||||||
|
user_access_end();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
Efault:
|
||||||
|
user_access_end();
|
||||||
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
|
long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
|
||||||
unsigned long bitmap_size)
|
unsigned long bitmap_size)
|
||||||
{
|
{
|
||||||
int i, j;
|
|
||||||
unsigned long m;
|
|
||||||
compat_ulong_t um;
|
|
||||||
unsigned long nr_compat_longs;
|
unsigned long nr_compat_longs;
|
||||||
|
|
||||||
/* align bitmap up to nearest compat_long_t boundary */
|
/* align bitmap up to nearest compat_long_t boundary */
|
||||||
bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
|
bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
|
||||||
|
nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
|
||||||
|
|
||||||
if (!access_ok(VERIFY_WRITE, umask, bitmap_size / 8))
|
if (!access_ok(VERIFY_WRITE, umask, bitmap_size / 8))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
|
user_access_begin();
|
||||||
|
while (nr_compat_longs > 1) {
|
||||||
for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) {
|
unsigned long m = *mask++;
|
||||||
m = *mask++;
|
unsafe_put_user((compat_ulong_t)m, umask++, Efault);
|
||||||
|
unsafe_put_user(m >> BITS_PER_COMPAT_LONG, umask++, Efault);
|
||||||
for (j = 0; j < sizeof(m)/sizeof(um); j++) {
|
nr_compat_longs -= 2;
|
||||||
um = m;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We dont want to write past the end of the userspace
|
|
||||||
* bitmap.
|
|
||||||
*/
|
|
||||||
if (nr_compat_longs) {
|
|
||||||
nr_compat_longs--;
|
|
||||||
if (__put_user(um, umask))
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
umask++;
|
|
||||||
m >>= 4*sizeof(um);
|
|
||||||
m >>= 4*sizeof(um);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (nr_compat_longs)
|
||||||
|
unsafe_put_user((compat_ulong_t)*mask, umask++, Efault);
|
||||||
|
user_access_end();
|
||||||
return 0;
|
return 0;
|
||||||
|
Efault:
|
||||||
|
user_access_end();
|
||||||
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in New Issue