mirror of
https://github.com/t2linux/kernel.git
synced 2026-04-30 13:48:59 -07:00
Merge branch 'misc.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull misc compat stuff updates from Al Viro:
"This part is basically untangling various compat stuff. Compat
syscalls moved to their native counterparts, getting rid of quite a
bit of double-copying and/or set_fs() uses. A lot of field-by-field
copyin/copyout killed off.
- kernel/compat.c is much closer to containing just the
copyin/copyout of compat structs. Not all compat syscalls are gone
from it yet, but it's getting there.
- ipc/compat_mq.c killed off completely.
- block/compat_ioctl.c cleaned up; floppy compat ioctls moved to
drivers/block/floppy.c where they belong. Yes, there are several
drivers that implement some of the same ioctls. Some are m68k and
one is 32bit-only pmac. drivers/block/floppy.c is the only one in
that bunch that can be built on biarch"
* 'misc.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
mqueue: move compat syscalls to native ones
usbdevfs: get rid of field-by-field copyin
compat_hdio_ioctl: get rid of set_fs()
take floppy compat ioctls to sodding floppy.c
ipmi: get rid of field-by-field __get_user()
ipmi: get COMPAT_IPMICTL_RECEIVE_MSG in sync with the native one
rt_sigtimedwait(): move compat to native
select: switch compat_{get,put}_fd_set() to compat_{get,put}_bitmap()
put_compat_rusage(): switch to copy_to_user()
sigpending(): move compat to native
getrlimit()/setrlimit(): move compat to native
times(2): move compat to native
compat_{get,put}_bitmap(): use unsafe_{get,put}_user()
fb_get_fscreeninfo(): don't bother with do_fb_ioctl()
do_sigaltstack(): lift copying to/from userland into callers
take compat_sys_old_getrlimit() to native syscall
trim __ARCH_WANT_SYS_OLD_GETRLIMIT
This commit is contained in:
@@ -10,7 +10,6 @@
|
||||
#define __ARCH_WANT_SYS_GETHOSTNAME
|
||||
#define __ARCH_WANT_SYS_FADVISE64
|
||||
#define __ARCH_WANT_SYS_GETPGRP
|
||||
#define __ARCH_WANT_SYS_OLD_GETRLIMIT
|
||||
#define __ARCH_WANT_SYS_OLDUMOUNT
|
||||
#define __ARCH_WANT_SYS_SIGPENDING
|
||||
#define __ARCH_WANT_SYS_FORK
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#define __ARCH_WANT_SYS_FADVISE64
|
||||
#define __ARCH_WANT_SYS_GETPGRP
|
||||
#define __ARCH_WANT_SYS_LLSEEK
|
||||
#define __ARCH_WANT_SYS_OLD_GETRLIMIT /*will be unused*/
|
||||
#define __ARCH_WANT_SYS_OLDUMOUNT
|
||||
#define __ARCH_WANT_SYS_CLONE
|
||||
#define __ARCH_WANT_SYS_FORK
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#define __ARCH_WANT_SYS_GETPGRP
|
||||
#define __ARCH_WANT_SYS_LLSEEK
|
||||
#define __ARCH_WANT_SYS_NICE
|
||||
#define __ARCH_WANT_SYS_OLD_GETRLIMIT
|
||||
#define __ARCH_WANT_SYS_OLD_UNAME
|
||||
#define __ARCH_WANT_SYS_OLDUMOUNT
|
||||
#define __ARCH_WANT_SYS_SIGPENDING
|
||||
|
||||
@@ -156,7 +156,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
|
||||
#define __ARCH_WANT_SYS_GETPGRP
|
||||
#define __ARCH_WANT_SYS_LLSEEK
|
||||
#define __ARCH_WANT_SYS_NICE
|
||||
#define __ARCH_WANT_SYS_OLD_GETRLIMIT
|
||||
#define __ARCH_WANT_SYS_OLDUMOUNT
|
||||
#define __ARCH_WANT_SYS_SIGPENDING
|
||||
#define __ARCH_WANT_SYS_SIGPROCMASK
|
||||
|
||||
@@ -109,7 +109,6 @@ struct compat_statfs {
|
||||
int f_spare[4];
|
||||
};
|
||||
|
||||
#define COMPAT_RLIM_OLD_INFINITY 0x7fffffff
|
||||
#define COMPAT_RLIM_INFINITY 0xffffffff
|
||||
|
||||
typedef u32 compat_old_sigset_t;
|
||||
|
||||
@@ -178,7 +178,6 @@ struct compat_statfs64 {
|
||||
u32 f_spare[4];
|
||||
};
|
||||
|
||||
#define COMPAT_RLIM_OLD_INFINITY 0x7fffffff
|
||||
#define COMPAT_RLIM_INFINITY 0xffffffff
|
||||
|
||||
typedef u32 compat_old_sigset_t; /* at least 32 bits */
|
||||
|
||||
@@ -116,7 +116,6 @@ struct compat_statfs {
|
||||
int f_spare[4];
|
||||
};
|
||||
|
||||
#define COMPAT_RLIM_OLD_INFINITY 0x7fffffff
|
||||
#define COMPAT_RLIM_INFINITY 0xffffffff
|
||||
|
||||
typedef u32 compat_old_sigset_t; /* at least 32 bits */
|
||||
|
||||
+6
-349
@@ -4,7 +4,6 @@
|
||||
#include <linux/cdrom.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/elevator.h>
|
||||
#include <linux/fd.h>
|
||||
#include <linux/hdreg.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/syscalls.h>
|
||||
@@ -80,19 +79,16 @@ static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev,
|
||||
static int compat_hdio_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
mm_segment_t old_fs = get_fs();
|
||||
unsigned long kval;
|
||||
unsigned int __user *uvp;
|
||||
unsigned long *__user p;
|
||||
int error;
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
p = compat_alloc_user_space(sizeof(unsigned long));
|
||||
error = __blkdev_driver_ioctl(bdev, mode,
|
||||
cmd, (unsigned long)(&kval));
|
||||
set_fs(old_fs);
|
||||
|
||||
cmd, (unsigned long)p);
|
||||
if (error == 0) {
|
||||
uvp = compat_ptr(arg);
|
||||
if (put_user(kval, uvp))
|
||||
unsigned int __user *uvp = compat_ptr(arg);
|
||||
unsigned long v;
|
||||
if (get_user(v, p) || put_user(v, uvp))
|
||||
error = -EFAULT;
|
||||
}
|
||||
return error;
|
||||
@@ -209,318 +205,6 @@ static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
#define BLKBSZSET_32 _IOW(0x12, 113, int)
|
||||
#define BLKGETSIZE64_32 _IOR(0x12, 114, int)
|
||||
|
||||
struct compat_floppy_drive_params {
|
||||
char cmos;
|
||||
compat_ulong_t max_dtr;
|
||||
compat_ulong_t hlt;
|
||||
compat_ulong_t hut;
|
||||
compat_ulong_t srt;
|
||||
compat_ulong_t spinup;
|
||||
compat_ulong_t spindown;
|
||||
unsigned char spindown_offset;
|
||||
unsigned char select_delay;
|
||||
unsigned char rps;
|
||||
unsigned char tracks;
|
||||
compat_ulong_t timeout;
|
||||
unsigned char interleave_sect;
|
||||
struct floppy_max_errors max_errors;
|
||||
char flags;
|
||||
char read_track;
|
||||
short autodetect[8];
|
||||
compat_int_t checkfreq;
|
||||
compat_int_t native_format;
|
||||
};
|
||||
|
||||
struct compat_floppy_drive_struct {
|
||||
signed char flags;
|
||||
compat_ulong_t spinup_date;
|
||||
compat_ulong_t select_date;
|
||||
compat_ulong_t first_read_date;
|
||||
short probed_format;
|
||||
short track;
|
||||
short maxblock;
|
||||
short maxtrack;
|
||||
compat_int_t generation;
|
||||
compat_int_t keep_data;
|
||||
compat_int_t fd_ref;
|
||||
compat_int_t fd_device;
|
||||
compat_int_t last_checked;
|
||||
compat_caddr_t dmabuf;
|
||||
compat_int_t bufblocks;
|
||||
};
|
||||
|
||||
struct compat_floppy_fdc_state {
|
||||
compat_int_t spec1;
|
||||
compat_int_t spec2;
|
||||
compat_int_t dtr;
|
||||
unsigned char version;
|
||||
unsigned char dor;
|
||||
compat_ulong_t address;
|
||||
unsigned int rawcmd:2;
|
||||
unsigned int reset:1;
|
||||
unsigned int need_configure:1;
|
||||
unsigned int perp_mode:2;
|
||||
unsigned int has_fifo:1;
|
||||
unsigned int driver_version;
|
||||
unsigned char track[4];
|
||||
};
|
||||
|
||||
struct compat_floppy_write_errors {
|
||||
unsigned int write_errors;
|
||||
compat_ulong_t first_error_sector;
|
||||
compat_int_t first_error_generation;
|
||||
compat_ulong_t last_error_sector;
|
||||
compat_int_t last_error_generation;
|
||||
compat_uint_t badness;
|
||||
};
|
||||
|
||||
#define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct)
|
||||
#define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct)
|
||||
#define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params)
|
||||
#define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params)
|
||||
#define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct)
|
||||
#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct)
|
||||
#define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state)
|
||||
#define FDWERRORGET32 _IOR(2, 0x17, struct compat_floppy_write_errors)
|
||||
|
||||
static struct {
|
||||
unsigned int cmd32;
|
||||
unsigned int cmd;
|
||||
} fd_ioctl_trans_table[] = {
|
||||
{ FDSETPRM32, FDSETPRM },
|
||||
{ FDDEFPRM32, FDDEFPRM },
|
||||
{ FDGETPRM32, FDGETPRM },
|
||||
{ FDSETDRVPRM32, FDSETDRVPRM },
|
||||
{ FDGETDRVPRM32, FDGETDRVPRM },
|
||||
{ FDGETDRVSTAT32, FDGETDRVSTAT },
|
||||
{ FDPOLLDRVSTAT32, FDPOLLDRVSTAT },
|
||||
{ FDGETFDCSTAT32, FDGETFDCSTAT },
|
||||
{ FDWERRORGET32, FDWERRORGET }
|
||||
};
|
||||
|
||||
#define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table)
|
||||
|
||||
static int compat_fd_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
mm_segment_t old_fs = get_fs();
|
||||
void *karg = NULL;
|
||||
unsigned int kcmd = 0;
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < NR_FD_IOCTL_TRANS; i++)
|
||||
if (cmd == fd_ioctl_trans_table[i].cmd32) {
|
||||
kcmd = fd_ioctl_trans_table[i].cmd;
|
||||
break;
|
||||
}
|
||||
if (!kcmd)
|
||||
return -EINVAL;
|
||||
|
||||
switch (cmd) {
|
||||
case FDSETPRM32:
|
||||
case FDDEFPRM32:
|
||||
case FDGETPRM32:
|
||||
{
|
||||
compat_uptr_t name;
|
||||
struct compat_floppy_struct __user *uf;
|
||||
struct floppy_struct *f;
|
||||
|
||||
uf = compat_ptr(arg);
|
||||
f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL);
|
||||
if (!karg)
|
||||
return -ENOMEM;
|
||||
if (cmd == FDGETPRM32)
|
||||
break;
|
||||
err = __get_user(f->size, &uf->size);
|
||||
err |= __get_user(f->sect, &uf->sect);
|
||||
err |= __get_user(f->head, &uf->head);
|
||||
err |= __get_user(f->track, &uf->track);
|
||||
err |= __get_user(f->stretch, &uf->stretch);
|
||||
err |= __get_user(f->gap, &uf->gap);
|
||||
err |= __get_user(f->rate, &uf->rate);
|
||||
err |= __get_user(f->spec1, &uf->spec1);
|
||||
err |= __get_user(f->fmt_gap, &uf->fmt_gap);
|
||||
err |= __get_user(name, &uf->name);
|
||||
f->name = compat_ptr(name);
|
||||
if (err) {
|
||||
err = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FDSETDRVPRM32:
|
||||
case FDGETDRVPRM32:
|
||||
{
|
||||
struct compat_floppy_drive_params __user *uf;
|
||||
struct floppy_drive_params *f;
|
||||
|
||||
uf = compat_ptr(arg);
|
||||
f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL);
|
||||
if (!karg)
|
||||
return -ENOMEM;
|
||||
if (cmd == FDGETDRVPRM32)
|
||||
break;
|
||||
err = __get_user(f->cmos, &uf->cmos);
|
||||
err |= __get_user(f->max_dtr, &uf->max_dtr);
|
||||
err |= __get_user(f->hlt, &uf->hlt);
|
||||
err |= __get_user(f->hut, &uf->hut);
|
||||
err |= __get_user(f->srt, &uf->srt);
|
||||
err |= __get_user(f->spinup, &uf->spinup);
|
||||
err |= __get_user(f->spindown, &uf->spindown);
|
||||
err |= __get_user(f->spindown_offset, &uf->spindown_offset);
|
||||
err |= __get_user(f->select_delay, &uf->select_delay);
|
||||
err |= __get_user(f->rps, &uf->rps);
|
||||
err |= __get_user(f->tracks, &uf->tracks);
|
||||
err |= __get_user(f->timeout, &uf->timeout);
|
||||
err |= __get_user(f->interleave_sect, &uf->interleave_sect);
|
||||
err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors));
|
||||
err |= __get_user(f->flags, &uf->flags);
|
||||
err |= __get_user(f->read_track, &uf->read_track);
|
||||
err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect));
|
||||
err |= __get_user(f->checkfreq, &uf->checkfreq);
|
||||
err |= __get_user(f->native_format, &uf->native_format);
|
||||
if (err) {
|
||||
err = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FDGETDRVSTAT32:
|
||||
case FDPOLLDRVSTAT32:
|
||||
karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL);
|
||||
if (!karg)
|
||||
return -ENOMEM;
|
||||
break;
|
||||
case FDGETFDCSTAT32:
|
||||
karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL);
|
||||
if (!karg)
|
||||
return -ENOMEM;
|
||||
break;
|
||||
case FDWERRORGET32:
|
||||
karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL);
|
||||
if (!karg)
|
||||
return -ENOMEM;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
set_fs(KERNEL_DS);
|
||||
err = __blkdev_driver_ioctl(bdev, mode, kcmd, (unsigned long)karg);
|
||||
set_fs(old_fs);
|
||||
if (err)
|
||||
goto out;
|
||||
switch (cmd) {
|
||||
case FDGETPRM32:
|
||||
{
|
||||
struct floppy_struct *f = karg;
|
||||
struct compat_floppy_struct __user *uf = compat_ptr(arg);
|
||||
|
||||
err = __put_user(f->size, &uf->size);
|
||||
err |= __put_user(f->sect, &uf->sect);
|
||||
err |= __put_user(f->head, &uf->head);
|
||||
err |= __put_user(f->track, &uf->track);
|
||||
err |= __put_user(f->stretch, &uf->stretch);
|
||||
err |= __put_user(f->gap, &uf->gap);
|
||||
err |= __put_user(f->rate, &uf->rate);
|
||||
err |= __put_user(f->spec1, &uf->spec1);
|
||||
err |= __put_user(f->fmt_gap, &uf->fmt_gap);
|
||||
err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name);
|
||||
break;
|
||||
}
|
||||
case FDGETDRVPRM32:
|
||||
{
|
||||
struct compat_floppy_drive_params __user *uf;
|
||||
struct floppy_drive_params *f = karg;
|
||||
|
||||
uf = compat_ptr(arg);
|
||||
err = __put_user(f->cmos, &uf->cmos);
|
||||
err |= __put_user(f->max_dtr, &uf->max_dtr);
|
||||
err |= __put_user(f->hlt, &uf->hlt);
|
||||
err |= __put_user(f->hut, &uf->hut);
|
||||
err |= __put_user(f->srt, &uf->srt);
|
||||
err |= __put_user(f->spinup, &uf->spinup);
|
||||
err |= __put_user(f->spindown, &uf->spindown);
|
||||
err |= __put_user(f->spindown_offset, &uf->spindown_offset);
|
||||
err |= __put_user(f->select_delay, &uf->select_delay);
|
||||
err |= __put_user(f->rps, &uf->rps);
|
||||
err |= __put_user(f->tracks, &uf->tracks);
|
||||
err |= __put_user(f->timeout, &uf->timeout);
|
||||
err |= __put_user(f->interleave_sect, &uf->interleave_sect);
|
||||
err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors));
|
||||
err |= __put_user(f->flags, &uf->flags);
|
||||
err |= __put_user(f->read_track, &uf->read_track);
|
||||
err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect));
|
||||
err |= __put_user(f->checkfreq, &uf->checkfreq);
|
||||
err |= __put_user(f->native_format, &uf->native_format);
|
||||
break;
|
||||
}
|
||||
case FDGETDRVSTAT32:
|
||||
case FDPOLLDRVSTAT32:
|
||||
{
|
||||
struct compat_floppy_drive_struct __user *uf;
|
||||
struct floppy_drive_struct *f = karg;
|
||||
|
||||
uf = compat_ptr(arg);
|
||||
err = __put_user(f->flags, &uf->flags);
|
||||
err |= __put_user(f->spinup_date, &uf->spinup_date);
|
||||
err |= __put_user(f->select_date, &uf->select_date);
|
||||
err |= __put_user(f->first_read_date, &uf->first_read_date);
|
||||
err |= __put_user(f->probed_format, &uf->probed_format);
|
||||
err |= __put_user(f->track, &uf->track);
|
||||
err |= __put_user(f->maxblock, &uf->maxblock);
|
||||
err |= __put_user(f->maxtrack, &uf->maxtrack);
|
||||
err |= __put_user(f->generation, &uf->generation);
|
||||
err |= __put_user(f->keep_data, &uf->keep_data);
|
||||
err |= __put_user(f->fd_ref, &uf->fd_ref);
|
||||
err |= __put_user(f->fd_device, &uf->fd_device);
|
||||
err |= __put_user(f->last_checked, &uf->last_checked);
|
||||
err |= __put_user((u64)f->dmabuf, &uf->dmabuf);
|
||||
err |= __put_user((u64)f->bufblocks, &uf->bufblocks);
|
||||
break;
|
||||
}
|
||||
case FDGETFDCSTAT32:
|
||||
{
|
||||
struct compat_floppy_fdc_state __user *uf;
|
||||
struct floppy_fdc_state *f = karg;
|
||||
|
||||
uf = compat_ptr(arg);
|
||||
err = __put_user(f->spec1, &uf->spec1);
|
||||
err |= __put_user(f->spec2, &uf->spec2);
|
||||
err |= __put_user(f->dtr, &uf->dtr);
|
||||
err |= __put_user(f->version, &uf->version);
|
||||
err |= __put_user(f->dor, &uf->dor);
|
||||
err |= __put_user(f->address, &uf->address);
|
||||
err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address),
|
||||
(char *)&f->address + sizeof(f->address), sizeof(int));
|
||||
err |= __put_user(f->driver_version, &uf->driver_version);
|
||||
err |= __copy_to_user(uf->track, f->track, sizeof(f->track));
|
||||
break;
|
||||
}
|
||||
case FDWERRORGET32:
|
||||
{
|
||||
struct compat_floppy_write_errors __user *uf;
|
||||
struct floppy_write_errors *f = karg;
|
||||
|
||||
uf = compat_ptr(arg);
|
||||
err = __put_user(f->write_errors, &uf->write_errors);
|
||||
err |= __put_user(f->first_error_sector, &uf->first_error_sector);
|
||||
err |= __put_user(f->first_error_generation, &uf->first_error_generation);
|
||||
err |= __put_user(f->last_error_sector, &uf->last_error_sector);
|
||||
err |= __put_user(f->last_error_generation, &uf->last_error_generation);
|
||||
err |= __put_user(f->badness, &uf->badness);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (err)
|
||||
err = -EFAULT;
|
||||
|
||||
out:
|
||||
kfree(karg);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
unsigned cmd, unsigned long arg)
|
||||
{
|
||||
@@ -537,16 +221,6 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
case HDIO_GET_ADDRESS:
|
||||
case HDIO_GET_BUSSTATE:
|
||||
return compat_hdio_ioctl(bdev, mode, cmd, arg);
|
||||
case FDSETPRM32:
|
||||
case FDDEFPRM32:
|
||||
case FDGETPRM32:
|
||||
case FDSETDRVPRM32:
|
||||
case FDGETDRVPRM32:
|
||||
case FDGETDRVSTAT32:
|
||||
case FDPOLLDRVSTAT32:
|
||||
case FDGETFDCSTAT32:
|
||||
case FDWERRORGET32:
|
||||
return compat_fd_ioctl(bdev, mode, cmd, arg);
|
||||
case CDROMREADAUDIO:
|
||||
return compat_cdrom_read_audio(bdev, mode, cmd, arg);
|
||||
case CDROM_SEND_PACKET:
|
||||
@@ -566,23 +240,6 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
case HDIO_DRIVE_CMD:
|
||||
/* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */
|
||||
case 0x330:
|
||||
/* 0x02 -- Floppy ioctls */
|
||||
case FDMSGON:
|
||||
case FDMSGOFF:
|
||||
case FDSETEMSGTRESH:
|
||||
case FDFLUSH:
|
||||
case FDWERRORCLR:
|
||||
case FDSETMAXERRS:
|
||||
case FDGETMAXERRS:
|
||||
case FDGETDRVTYP:
|
||||
case FDEJECT:
|
||||
case FDCLRPRM:
|
||||
case FDFMTBEG:
|
||||
case FDFMTEND:
|
||||
case FDRESET:
|
||||
case FDTWADDLE:
|
||||
case FDFMTTRK:
|
||||
case FDRAWCMD:
|
||||
/* CDROM stuff */
|
||||
case CDROMPAUSE:
|
||||
case CDROMRESUME:
|
||||
|
||||
@@ -192,6 +192,7 @@ static int print_unex = 1;
|
||||
#include <linux/io.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/async.h>
|
||||
#include <linux/compat.h>
|
||||
|
||||
/*
|
||||
* PS/2 floppies have much slower step rates than regular floppies.
|
||||
@@ -3568,6 +3569,330 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
||||
struct compat_floppy_drive_params {
|
||||
char cmos;
|
||||
compat_ulong_t max_dtr;
|
||||
compat_ulong_t hlt;
|
||||
compat_ulong_t hut;
|
||||
compat_ulong_t srt;
|
||||
compat_ulong_t spinup;
|
||||
compat_ulong_t spindown;
|
||||
unsigned char spindown_offset;
|
||||
unsigned char select_delay;
|
||||
unsigned char rps;
|
||||
unsigned char tracks;
|
||||
compat_ulong_t timeout;
|
||||
unsigned char interleave_sect;
|
||||
struct floppy_max_errors max_errors;
|
||||
char flags;
|
||||
char read_track;
|
||||
short autodetect[8];
|
||||
compat_int_t checkfreq;
|
||||
compat_int_t native_format;
|
||||
};
|
||||
|
||||
struct compat_floppy_drive_struct {
|
||||
signed char flags;
|
||||
compat_ulong_t spinup_date;
|
||||
compat_ulong_t select_date;
|
||||
compat_ulong_t first_read_date;
|
||||
short probed_format;
|
||||
short track;
|
||||
short maxblock;
|
||||
short maxtrack;
|
||||
compat_int_t generation;
|
||||
compat_int_t keep_data;
|
||||
compat_int_t fd_ref;
|
||||
compat_int_t fd_device;
|
||||
compat_int_t last_checked;
|
||||
compat_caddr_t dmabuf;
|
||||
compat_int_t bufblocks;
|
||||
};
|
||||
|
||||
struct compat_floppy_fdc_state {
|
||||
compat_int_t spec1;
|
||||
compat_int_t spec2;
|
||||
compat_int_t dtr;
|
||||
unsigned char version;
|
||||
unsigned char dor;
|
||||
compat_ulong_t address;
|
||||
unsigned int rawcmd:2;
|
||||
unsigned int reset:1;
|
||||
unsigned int need_configure:1;
|
||||
unsigned int perp_mode:2;
|
||||
unsigned int has_fifo:1;
|
||||
unsigned int driver_version;
|
||||
unsigned char track[4];
|
||||
};
|
||||
|
||||
struct compat_floppy_write_errors {
|
||||
unsigned int write_errors;
|
||||
compat_ulong_t first_error_sector;
|
||||
compat_int_t first_error_generation;
|
||||
compat_ulong_t last_error_sector;
|
||||
compat_int_t last_error_generation;
|
||||
compat_uint_t badness;
|
||||
};
|
||||
|
||||
#define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct)
|
||||
#define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct)
|
||||
#define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params)
|
||||
#define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params)
|
||||
#define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct)
|
||||
#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct)
|
||||
#define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state)
|
||||
#define FDWERRORGET32 _IOR(2, 0x17, struct compat_floppy_write_errors)
|
||||
|
||||
static int compat_set_geometry(struct block_device *bdev, fmode_t mode, unsigned int cmd,
|
||||
struct compat_floppy_struct __user *arg)
|
||||
{
|
||||
struct floppy_struct v;
|
||||
int drive, type;
|
||||
int err;
|
||||
|
||||
BUILD_BUG_ON(offsetof(struct floppy_struct, name) !=
|
||||
offsetof(struct compat_floppy_struct, name));
|
||||
|
||||
if (!(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL)))
|
||||
return -EPERM;
|
||||
|
||||
memset(&v, 0, sizeof(struct floppy_struct));
|
||||
if (copy_from_user(&v, arg, offsetof(struct floppy_struct, name)))
|
||||
return -EFAULT;
|
||||
|
||||
mutex_lock(&floppy_mutex);
|
||||
drive = (long)bdev->bd_disk->private_data;
|
||||
type = ITYPE(UDRS->fd_device);
|
||||
err = set_geometry(cmd == FDSETPRM32 ? FDSETPRM : FDDEFPRM,
|
||||
&v, drive, type, bdev);
|
||||
mutex_unlock(&floppy_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int compat_get_prm(int drive,
|
||||
struct compat_floppy_struct __user *arg)
|
||||
{
|
||||
struct compat_floppy_struct v;
|
||||
struct floppy_struct *p;
|
||||
int err;
|
||||
|
||||
memset(&v, 0, sizeof(v));
|
||||
mutex_lock(&floppy_mutex);
|
||||
err = get_floppy_geometry(drive, ITYPE(UDRS->fd_device), &p);
|
||||
if (err) {
|
||||
mutex_unlock(&floppy_mutex);
|
||||
return err;
|
||||
}
|
||||
memcpy(&v, p, offsetof(struct floppy_struct, name));
|
||||
mutex_unlock(&floppy_mutex);
|
||||
if (copy_to_user(arg, &v, sizeof(struct compat_floppy_struct)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compat_setdrvprm(int drive,
|
||||
struct compat_floppy_drive_params __user *arg)
|
||||
{
|
||||
struct compat_floppy_drive_params v;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
if (copy_from_user(&v, arg, sizeof(struct compat_floppy_drive_params)))
|
||||
return -EFAULT;
|
||||
mutex_lock(&floppy_mutex);
|
||||
UDP->cmos = v.cmos;
|
||||
UDP->max_dtr = v.max_dtr;
|
||||
UDP->hlt = v.hlt;
|
||||
UDP->hut = v.hut;
|
||||
UDP->srt = v.srt;
|
||||
UDP->spinup = v.spinup;
|
||||
UDP->spindown = v.spindown;
|
||||
UDP->spindown_offset = v.spindown_offset;
|
||||
UDP->select_delay = v.select_delay;
|
||||
UDP->rps = v.rps;
|
||||
UDP->tracks = v.tracks;
|
||||
UDP->timeout = v.timeout;
|
||||
UDP->interleave_sect = v.interleave_sect;
|
||||
UDP->max_errors = v.max_errors;
|
||||
UDP->flags = v.flags;
|
||||
UDP->read_track = v.read_track;
|
||||
memcpy(UDP->autodetect, v.autodetect, sizeof(v.autodetect));
|
||||
UDP->checkfreq = v.checkfreq;
|
||||
UDP->native_format = v.native_format;
|
||||
mutex_unlock(&floppy_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compat_getdrvprm(int drive,
|
||||
struct compat_floppy_drive_params __user *arg)
|
||||
{
|
||||
struct compat_floppy_drive_params v;
|
||||
|
||||
memset(&v, 0, sizeof(struct compat_floppy_drive_params));
|
||||
mutex_lock(&floppy_mutex);
|
||||
v.cmos = UDP->cmos;
|
||||
v.max_dtr = UDP->max_dtr;
|
||||
v.hlt = UDP->hlt;
|
||||
v.hut = UDP->hut;
|
||||
v.srt = UDP->srt;
|
||||
v.spinup = UDP->spinup;
|
||||
v.spindown = UDP->spindown;
|
||||
v.spindown_offset = UDP->spindown_offset;
|
||||
v.select_delay = UDP->select_delay;
|
||||
v.rps = UDP->rps;
|
||||
v.tracks = UDP->tracks;
|
||||
v.timeout = UDP->timeout;
|
||||
v.interleave_sect = UDP->interleave_sect;
|
||||
v.max_errors = UDP->max_errors;
|
||||
v.flags = UDP->flags;
|
||||
v.read_track = UDP->read_track;
|
||||
memcpy(v.autodetect, UDP->autodetect, sizeof(v.autodetect));
|
||||
v.checkfreq = UDP->checkfreq;
|
||||
v.native_format = UDP->native_format;
|
||||
mutex_unlock(&floppy_mutex);
|
||||
|
||||
if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_params)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compat_getdrvstat(int drive, bool poll,
|
||||
struct compat_floppy_drive_struct __user *arg)
|
||||
{
|
||||
struct compat_floppy_drive_struct v;
|
||||
|
||||
memset(&v, 0, sizeof(struct compat_floppy_drive_struct));
|
||||
mutex_lock(&floppy_mutex);
|
||||
|
||||
if (poll) {
|
||||
if (lock_fdc(drive))
|
||||
goto Eintr;
|
||||
if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR)
|
||||
goto Eintr;
|
||||
process_fd_request();
|
||||
}
|
||||
v.spinup_date = UDRS->spinup_date;
|
||||
v.select_date = UDRS->select_date;
|
||||
v.first_read_date = UDRS->first_read_date;
|
||||
v.probed_format = UDRS->probed_format;
|
||||
v.track = UDRS->track;
|
||||
v.maxblock = UDRS->maxblock;
|
||||
v.maxtrack = UDRS->maxtrack;
|
||||
v.generation = UDRS->generation;
|
||||
v.keep_data = UDRS->keep_data;
|
||||
v.fd_ref = UDRS->fd_ref;
|
||||
v.fd_device = UDRS->fd_device;
|
||||
v.last_checked = UDRS->last_checked;
|
||||
v.dmabuf = (uintptr_t)UDRS->dmabuf;
|
||||
v.bufblocks = UDRS->bufblocks;
|
||||
mutex_unlock(&floppy_mutex);
|
||||
|
||||
if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_struct)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
Eintr:
|
||||
mutex_unlock(&floppy_mutex);
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
static int compat_getfdcstat(int drive,
|
||||
struct compat_floppy_fdc_state __user *arg)
|
||||
{
|
||||
struct compat_floppy_fdc_state v32;
|
||||
struct floppy_fdc_state v;
|
||||
|
||||
mutex_lock(&floppy_mutex);
|
||||
v = *UFDCS;
|
||||
mutex_unlock(&floppy_mutex);
|
||||
|
||||
memset(&v32, 0, sizeof(struct compat_floppy_fdc_state));
|
||||
v32.spec1 = v.spec1;
|
||||
v32.spec2 = v.spec2;
|
||||
v32.dtr = v.dtr;
|
||||
v32.version = v.version;
|
||||
v32.dor = v.dor;
|
||||
v32.address = v.address;
|
||||
v32.rawcmd = v.rawcmd;
|
||||
v32.reset = v.reset;
|
||||
v32.need_configure = v.need_configure;
|
||||
v32.perp_mode = v.perp_mode;
|
||||
v32.has_fifo = v.has_fifo;
|
||||
v32.driver_version = v.driver_version;
|
||||
memcpy(v32.track, v.track, 4);
|
||||
if (copy_to_user(arg, &v32, sizeof(struct compat_floppy_fdc_state)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compat_werrorget(int drive,
|
||||
struct compat_floppy_write_errors __user *arg)
|
||||
{
|
||||
struct compat_floppy_write_errors v32;
|
||||
struct floppy_write_errors v;
|
||||
|
||||
memset(&v32, 0, sizeof(struct compat_floppy_write_errors));
|
||||
mutex_lock(&floppy_mutex);
|
||||
v = *UDRWE;
|
||||
mutex_unlock(&floppy_mutex);
|
||||
v32.write_errors = v.write_errors;
|
||||
v32.first_error_sector = v.first_error_sector;
|
||||
v32.first_error_generation = v.first_error_generation;
|
||||
v32.last_error_sector = v.last_error_sector;
|
||||
v32.last_error_generation = v.last_error_generation;
|
||||
v32.badness = v.badness;
|
||||
if (copy_to_user(arg, &v32, sizeof(struct compat_floppy_write_errors)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fd_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
|
||||
unsigned long param)
|
||||
{
|
||||
int drive = (long)bdev->bd_disk->private_data;
|
||||
switch (cmd) {
|
||||
case FDMSGON:
|
||||
case FDMSGOFF:
|
||||
case FDSETEMSGTRESH:
|
||||
case FDFLUSH:
|
||||
case FDWERRORCLR:
|
||||
case FDEJECT:
|
||||
case FDCLRPRM:
|
||||
case FDFMTBEG:
|
||||
case FDRESET:
|
||||
case FDTWADDLE:
|
||||
return fd_ioctl(bdev, mode, cmd, param);
|
||||
case FDSETMAXERRS:
|
||||
case FDGETMAXERRS:
|
||||
case FDGETDRVTYP:
|
||||
case FDFMTEND:
|
||||
case FDFMTTRK:
|
||||
case FDRAWCMD:
|
||||
return fd_ioctl(bdev, mode, cmd,
|
||||
(unsigned long)compat_ptr(param));
|
||||
case FDSETPRM32:
|
||||
case FDDEFPRM32:
|
||||
return compat_set_geometry(bdev, mode, cmd, compat_ptr(param));
|
||||
case FDGETPRM32:
|
||||
return compat_get_prm(drive, compat_ptr(param));
|
||||
case FDSETDRVPRM32:
|
||||
return compat_setdrvprm(drive, compat_ptr(param));
|
||||
case FDGETDRVPRM32:
|
||||
return compat_getdrvprm(drive, compat_ptr(param));
|
||||
case FDPOLLDRVSTAT32:
|
||||
return compat_getdrvstat(drive, true, compat_ptr(param));
|
||||
case FDGETDRVSTAT32:
|
||||
return compat_getdrvstat(drive, false, compat_ptr(param));
|
||||
case FDGETFDCSTAT32:
|
||||
return compat_getfdcstat(drive, compat_ptr(param));
|
||||
case FDWERRORGET32:
|
||||
return compat_werrorget(drive, compat_ptr(param));
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void __init config_types(void)
|
||||
{
|
||||
bool has_drive = false;
|
||||
@@ -3885,6 +4210,9 @@ static const struct block_device_operations floppy_fops = {
|
||||
.getgeo = fd_getgeo,
|
||||
.check_events = floppy_check_events,
|
||||
.revalidate_disk = floppy_revalidate,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = fd_compat_ioctl,
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+151
-182
@@ -231,6 +231,102 @@ static int handle_send_req(ipmi_user_t user,
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int handle_recv(struct ipmi_file_private *priv,
|
||||
bool trunc, struct ipmi_recv *rsp,
|
||||
int (*copyout)(struct ipmi_recv *, void __user *),
|
||||
void __user *to)
|
||||
{
|
||||
int addr_len;
|
||||
struct list_head *entry;
|
||||
struct ipmi_recv_msg *msg;
|
||||
unsigned long flags;
|
||||
int rv = 0;
|
||||
|
||||
/* We claim a mutex because we don't want two
|
||||
users getting something from the queue at a time.
|
||||
Since we have to release the spinlock before we can
|
||||
copy the data to the user, it's possible another
|
||||
user will grab something from the queue, too. Then
|
||||
the messages might get out of order if something
|
||||
fails and the message gets put back onto the
|
||||
queue. This mutex prevents that problem. */
|
||||
mutex_lock(&priv->recv_mutex);
|
||||
|
||||
/* Grab the message off the list. */
|
||||
spin_lock_irqsave(&(priv->recv_msg_lock), flags);
|
||||
if (list_empty(&(priv->recv_msgs))) {
|
||||
spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
|
||||
rv = -EAGAIN;
|
||||
goto recv_err;
|
||||
}
|
||||
entry = priv->recv_msgs.next;
|
||||
msg = list_entry(entry, struct ipmi_recv_msg, link);
|
||||
list_del(entry);
|
||||
spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
|
||||
|
||||
addr_len = ipmi_addr_length(msg->addr.addr_type);
|
||||
if (rsp->addr_len < addr_len)
|
||||
{
|
||||
rv = -EINVAL;
|
||||
goto recv_putback_on_err;
|
||||
}
|
||||
|
||||
if (copy_to_user(rsp->addr, &(msg->addr), addr_len)) {
|
||||
rv = -EFAULT;
|
||||
goto recv_putback_on_err;
|
||||
}
|
||||
rsp->addr_len = addr_len;
|
||||
|
||||
rsp->recv_type = msg->recv_type;
|
||||
rsp->msgid = msg->msgid;
|
||||
rsp->msg.netfn = msg->msg.netfn;
|
||||
rsp->msg.cmd = msg->msg.cmd;
|
||||
|
||||
if (msg->msg.data_len > 0) {
|
||||
if (rsp->msg.data_len < msg->msg.data_len) {
|
||||
rv = -EMSGSIZE;
|
||||
if (trunc)
|
||||
msg->msg.data_len = rsp->msg.data_len;
|
||||
else
|
||||
goto recv_putback_on_err;
|
||||
}
|
||||
|
||||
if (copy_to_user(rsp->msg.data,
|
||||
msg->msg.data,
|
||||
msg->msg.data_len))
|
||||
{
|
||||
rv = -EFAULT;
|
||||
goto recv_putback_on_err;
|
||||
}
|
||||
rsp->msg.data_len = msg->msg.data_len;
|
||||
} else {
|
||||
rsp->msg.data_len = 0;
|
||||
}
|
||||
|
||||
rv = copyout(rsp, to);
|
||||
if (rv)
|
||||
goto recv_putback_on_err;
|
||||
|
||||
mutex_unlock(&priv->recv_mutex);
|
||||
ipmi_free_recv_msg(msg);
|
||||
return 0;
|
||||
|
||||
recv_putback_on_err:
|
||||
/* If we got an error, put the message back onto
|
||||
the head of the queue. */
|
||||
spin_lock_irqsave(&(priv->recv_msg_lock), flags);
|
||||
list_add(entry, &(priv->recv_msgs));
|
||||
spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
|
||||
recv_err:
|
||||
mutex_unlock(&priv->recv_mutex);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int copyout_recv(struct ipmi_recv *rsp, void __user *to)
|
||||
{
|
||||
return copy_to_user(to, rsp, sizeof(struct ipmi_recv)) ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
static int ipmi_ioctl(struct file *file,
|
||||
unsigned int cmd,
|
||||
unsigned long data)
|
||||
@@ -277,100 +373,12 @@ static int ipmi_ioctl(struct file *file,
|
||||
case IPMICTL_RECEIVE_MSG_TRUNC:
|
||||
{
|
||||
struct ipmi_recv rsp;
|
||||
int addr_len;
|
||||
struct list_head *entry;
|
||||
struct ipmi_recv_msg *msg;
|
||||
unsigned long flags;
|
||||
|
||||
|
||||
rv = 0;
|
||||
if (copy_from_user(&rsp, arg, sizeof(rsp))) {
|
||||
if (copy_from_user(&rsp, arg, sizeof(rsp)))
|
||||
rv = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* We claim a mutex because we don't want two
|
||||
users getting something from the queue at a time.
|
||||
Since we have to release the spinlock before we can
|
||||
copy the data to the user, it's possible another
|
||||
user will grab something from the queue, too. Then
|
||||
the messages might get out of order if something
|
||||
fails and the message gets put back onto the
|
||||
queue. This mutex prevents that problem. */
|
||||
mutex_lock(&priv->recv_mutex);
|
||||
|
||||
/* Grab the message off the list. */
|
||||
spin_lock_irqsave(&(priv->recv_msg_lock), flags);
|
||||
if (list_empty(&(priv->recv_msgs))) {
|
||||
spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
|
||||
rv = -EAGAIN;
|
||||
goto recv_err;
|
||||
}
|
||||
entry = priv->recv_msgs.next;
|
||||
msg = list_entry(entry, struct ipmi_recv_msg, link);
|
||||
list_del(entry);
|
||||
spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
|
||||
|
||||
addr_len = ipmi_addr_length(msg->addr.addr_type);
|
||||
if (rsp.addr_len < addr_len)
|
||||
{
|
||||
rv = -EINVAL;
|
||||
goto recv_putback_on_err;
|
||||
}
|
||||
|
||||
if (copy_to_user(rsp.addr, &(msg->addr), addr_len)) {
|
||||
rv = -EFAULT;
|
||||
goto recv_putback_on_err;
|
||||
}
|
||||
rsp.addr_len = addr_len;
|
||||
|
||||
rsp.recv_type = msg->recv_type;
|
||||
rsp.msgid = msg->msgid;
|
||||
rsp.msg.netfn = msg->msg.netfn;
|
||||
rsp.msg.cmd = msg->msg.cmd;
|
||||
|
||||
if (msg->msg.data_len > 0) {
|
||||
if (rsp.msg.data_len < msg->msg.data_len) {
|
||||
rv = -EMSGSIZE;
|
||||
if (cmd == IPMICTL_RECEIVE_MSG_TRUNC) {
|
||||
msg->msg.data_len = rsp.msg.data_len;
|
||||
} else {
|
||||
goto recv_putback_on_err;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_to_user(rsp.msg.data,
|
||||
msg->msg.data,
|
||||
msg->msg.data_len))
|
||||
{
|
||||
rv = -EFAULT;
|
||||
goto recv_putback_on_err;
|
||||
}
|
||||
rsp.msg.data_len = msg->msg.data_len;
|
||||
} else {
|
||||
rsp.msg.data_len = 0;
|
||||
}
|
||||
|
||||
if (copy_to_user(arg, &rsp, sizeof(rsp))) {
|
||||
rv = -EFAULT;
|
||||
goto recv_putback_on_err;
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->recv_mutex);
|
||||
ipmi_free_recv_msg(msg);
|
||||
break;
|
||||
|
||||
recv_putback_on_err:
|
||||
/* If we got an error, put the message back onto
|
||||
the head of the queue. */
|
||||
spin_lock_irqsave(&(priv->recv_msg_lock), flags);
|
||||
list_add(entry, &(priv->recv_msgs));
|
||||
spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
|
||||
mutex_unlock(&priv->recv_mutex);
|
||||
break;
|
||||
|
||||
recv_err:
|
||||
mutex_unlock(&priv->recv_mutex);
|
||||
else
|
||||
rv = handle_recv(priv, cmd == IPMICTL_RECEIVE_MSG_TRUNC,
|
||||
&rsp, copyout_recv, arg);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -696,85 +704,56 @@ struct compat_ipmi_req_settime {
|
||||
/*
|
||||
* Define some helper functions for copying IPMI data
|
||||
*/
|
||||
static long get_compat_ipmi_msg(struct ipmi_msg *p64,
|
||||
struct compat_ipmi_msg __user *p32)
|
||||
static void get_compat_ipmi_msg(struct ipmi_msg *p64,
|
||||
struct compat_ipmi_msg *p32)
|
||||
{
|
||||
compat_uptr_t tmp;
|
||||
|
||||
if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
|
||||
__get_user(p64->netfn, &p32->netfn) ||
|
||||
__get_user(p64->cmd, &p32->cmd) ||
|
||||
__get_user(p64->data_len, &p32->data_len) ||
|
||||
__get_user(tmp, &p32->data))
|
||||
return -EFAULT;
|
||||
p64->data = compat_ptr(tmp);
|
||||
return 0;
|
||||
p64->netfn = p32->netfn;
|
||||
p64->cmd = p32->cmd;
|
||||
p64->data_len = p32->data_len;
|
||||
p64->data = compat_ptr(p32->data);
|
||||
}
|
||||
|
||||
static long put_compat_ipmi_msg(struct ipmi_msg *p64,
|
||||
struct compat_ipmi_msg __user *p32)
|
||||
static void get_compat_ipmi_req(struct ipmi_req *p64,
|
||||
struct compat_ipmi_req *p32)
|
||||
{
|
||||
if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
|
||||
__put_user(p64->netfn, &p32->netfn) ||
|
||||
__put_user(p64->cmd, &p32->cmd) ||
|
||||
__put_user(p64->data_len, &p32->data_len))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
p64->addr = compat_ptr(p32->addr);
|
||||
p64->addr_len = p32->addr_len;
|
||||
p64->msgid = p32->msgid;
|
||||
get_compat_ipmi_msg(&p64->msg, &p32->msg);
|
||||
}
|
||||
|
||||
static long get_compat_ipmi_req(struct ipmi_req *p64,
|
||||
struct compat_ipmi_req __user *p32)
|
||||
static void get_compat_ipmi_req_settime(struct ipmi_req_settime *p64,
|
||||
struct compat_ipmi_req_settime *p32)
|
||||
{
|
||||
|
||||
compat_uptr_t tmp;
|
||||
|
||||
if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
|
||||
__get_user(tmp, &p32->addr) ||
|
||||
__get_user(p64->addr_len, &p32->addr_len) ||
|
||||
__get_user(p64->msgid, &p32->msgid) ||
|
||||
get_compat_ipmi_msg(&p64->msg, &p32->msg))
|
||||
return -EFAULT;
|
||||
p64->addr = compat_ptr(tmp);
|
||||
return 0;
|
||||
get_compat_ipmi_req(&p64->req, &p32->req);
|
||||
p64->retries = p32->retries;
|
||||
p64->retry_time_ms = p32->retry_time_ms;
|
||||
}
|
||||
|
||||
static long get_compat_ipmi_req_settime(struct ipmi_req_settime *p64,
|
||||
struct compat_ipmi_req_settime __user *p32)
|
||||
static void get_compat_ipmi_recv(struct ipmi_recv *p64,
|
||||
struct compat_ipmi_recv *p32)
|
||||
{
|
||||
if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
|
||||
get_compat_ipmi_req(&p64->req, &p32->req) ||
|
||||
__get_user(p64->retries, &p32->retries) ||
|
||||
__get_user(p64->retry_time_ms, &p32->retry_time_ms))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
memset(p64, 0, sizeof(struct ipmi_recv));
|
||||
p64->recv_type = p32->recv_type;
|
||||
p64->addr = compat_ptr(p32->addr);
|
||||
p64->addr_len = p32->addr_len;
|
||||
p64->msgid = p32->msgid;
|
||||
get_compat_ipmi_msg(&p64->msg, &p32->msg);
|
||||
}
|
||||
|
||||
static long get_compat_ipmi_recv(struct ipmi_recv *p64,
|
||||
struct compat_ipmi_recv __user *p32)
|
||||
static int copyout_recv32(struct ipmi_recv *p64, void __user *to)
|
||||
{
|
||||
compat_uptr_t tmp;
|
||||
|
||||
if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
|
||||
__get_user(p64->recv_type, &p32->recv_type) ||
|
||||
__get_user(tmp, &p32->addr) ||
|
||||
__get_user(p64->addr_len, &p32->addr_len) ||
|
||||
__get_user(p64->msgid, &p32->msgid) ||
|
||||
get_compat_ipmi_msg(&p64->msg, &p32->msg))
|
||||
return -EFAULT;
|
||||
p64->addr = compat_ptr(tmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long put_compat_ipmi_recv(struct ipmi_recv *p64,
|
||||
struct compat_ipmi_recv __user *p32)
|
||||
{
|
||||
if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
|
||||
__put_user(p64->recv_type, &p32->recv_type) ||
|
||||
__put_user(p64->addr_len, &p32->addr_len) ||
|
||||
__put_user(p64->msgid, &p32->msgid) ||
|
||||
put_compat_ipmi_msg(&p64->msg, &p32->msg))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
struct compat_ipmi_recv v32;
|
||||
memset(&v32, 0, sizeof(struct compat_ipmi_recv));
|
||||
v32.recv_type = p64->recv_type;
|
||||
v32.addr = ptr_to_compat(p64->addr);
|
||||
v32.addr_len = p64->addr_len;
|
||||
v32.msgid = p64->msgid;
|
||||
v32.msg.netfn = p64->msg.netfn;
|
||||
v32.msg.cmd = p64->msg.cmd;
|
||||
v32.msg.data_len = p64->msg.data_len;
|
||||
v32.msg.data = ptr_to_compat(p64->msg.data);
|
||||
return copy_to_user(to, &v32, sizeof(v32)) ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -783,17 +762,19 @@ static long put_compat_ipmi_recv(struct ipmi_recv *p64,
|
||||
static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
int rc;
|
||||
struct ipmi_file_private *priv = filep->private_data;
|
||||
|
||||
switch(cmd) {
|
||||
case COMPAT_IPMICTL_SEND_COMMAND:
|
||||
{
|
||||
struct ipmi_req rp;
|
||||
struct compat_ipmi_req r32;
|
||||
|
||||
if (get_compat_ipmi_req(&rp, compat_ptr(arg)))
|
||||
if (copy_from_user(&r32, compat_ptr(arg), sizeof(r32)))
|
||||
return -EFAULT;
|
||||
|
||||
get_compat_ipmi_req(&rp, &r32);
|
||||
|
||||
return handle_send_req(priv->user, &rp,
|
||||
priv->default_retries,
|
||||
priv->default_retry_time_ms);
|
||||
@@ -801,42 +782,30 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
|
||||
case COMPAT_IPMICTL_SEND_COMMAND_SETTIME:
|
||||
{
|
||||
struct ipmi_req_settime sp;
|
||||
struct compat_ipmi_req_settime sp32;
|
||||
|
||||
if (get_compat_ipmi_req_settime(&sp, compat_ptr(arg)))
|
||||
if (copy_from_user(&sp32, compat_ptr(arg), sizeof(sp32)))
|
||||
return -EFAULT;
|
||||
|
||||
get_compat_ipmi_req_settime(&sp, &sp32);
|
||||
|
||||
return handle_send_req(priv->user, &sp.req,
|
||||
sp.retries, sp.retry_time_ms);
|
||||
}
|
||||
case COMPAT_IPMICTL_RECEIVE_MSG:
|
||||
case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC:
|
||||
{
|
||||
struct ipmi_recv __user *precv64;
|
||||
struct ipmi_recv recv64;
|
||||
struct compat_ipmi_recv recv32;
|
||||
|
||||
memset(&recv64, 0, sizeof(recv64));
|
||||
if (get_compat_ipmi_recv(&recv64, compat_ptr(arg)))
|
||||
if (copy_from_user(&recv32, compat_ptr(arg), sizeof(recv32)))
|
||||
return -EFAULT;
|
||||
|
||||
precv64 = compat_alloc_user_space(sizeof(recv64));
|
||||
if (copy_to_user(precv64, &recv64, sizeof(recv64)))
|
||||
return -EFAULT;
|
||||
get_compat_ipmi_recv(&recv64, &recv32);
|
||||
|
||||
rc = ipmi_ioctl(filep,
|
||||
((cmd == COMPAT_IPMICTL_RECEIVE_MSG)
|
||||
? IPMICTL_RECEIVE_MSG
|
||||
: IPMICTL_RECEIVE_MSG_TRUNC),
|
||||
(unsigned long) precv64);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
if (copy_from_user(&recv64, precv64, sizeof(recv64)))
|
||||
return -EFAULT;
|
||||
|
||||
if (put_compat_ipmi_recv(&recv64, compat_ptr(arg)))
|
||||
return -EFAULT;
|
||||
|
||||
return rc;
|
||||
return handle_recv(priv,
|
||||
cmd == COMPAT_IPMICTL_RECEIVE_MSG_TRUNC,
|
||||
&recv64, copyout_recv32, compat_ptr(arg));
|
||||
}
|
||||
default:
|
||||
return ipmi_ioctl(filep, cmd, arg);
|
||||
|
||||
+19
-29
@@ -1966,27 +1966,21 @@ static int proc_disconnectsignal_compat(struct usb_dev_state *ps, void __user *a
|
||||
static int get_urb32(struct usbdevfs_urb *kurb,
|
||||
struct usbdevfs_urb32 __user *uurb)
|
||||
{
|
||||
__u32 uptr;
|
||||
if (!access_ok(VERIFY_READ, uurb, sizeof(*uurb)) ||
|
||||
__get_user(kurb->type, &uurb->type) ||
|
||||
__get_user(kurb->endpoint, &uurb->endpoint) ||
|
||||
__get_user(kurb->status, &uurb->status) ||
|
||||
__get_user(kurb->flags, &uurb->flags) ||
|
||||
__get_user(kurb->buffer_length, &uurb->buffer_length) ||
|
||||
__get_user(kurb->actual_length, &uurb->actual_length) ||
|
||||
__get_user(kurb->start_frame, &uurb->start_frame) ||
|
||||
__get_user(kurb->number_of_packets, &uurb->number_of_packets) ||
|
||||
__get_user(kurb->error_count, &uurb->error_count) ||
|
||||
__get_user(kurb->signr, &uurb->signr))
|
||||
struct usbdevfs_urb32 urb32;
|
||||
if (copy_from_user(&urb32, uurb, sizeof(*uurb)))
|
||||
return -EFAULT;
|
||||
|
||||
if (__get_user(uptr, &uurb->buffer))
|
||||
return -EFAULT;
|
||||
kurb->buffer = compat_ptr(uptr);
|
||||
if (__get_user(uptr, &uurb->usercontext))
|
||||
return -EFAULT;
|
||||
kurb->usercontext = compat_ptr(uptr);
|
||||
|
||||
kurb->type = urb32.type;
|
||||
kurb->endpoint = urb32.endpoint;
|
||||
kurb->status = urb32.status;
|
||||
kurb->flags = urb32.flags;
|
||||
kurb->buffer = compat_ptr(urb32.buffer);
|
||||
kurb->buffer_length = urb32.buffer_length;
|
||||
kurb->actual_length = urb32.actual_length;
|
||||
kurb->start_frame = urb32.start_frame;
|
||||
kurb->number_of_packets = urb32.number_of_packets;
|
||||
kurb->error_count = urb32.error_count;
|
||||
kurb->signr = urb32.signr;
|
||||
kurb->usercontext = compat_ptr(urb32.usercontext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2198,18 +2192,14 @@ static int proc_ioctl_default(struct usb_dev_state *ps, void __user *arg)
|
||||
#ifdef CONFIG_COMPAT
|
||||
static int proc_ioctl_compat(struct usb_dev_state *ps, compat_uptr_t arg)
|
||||
{
|
||||
struct usbdevfs_ioctl32 __user *uioc;
|
||||
struct usbdevfs_ioctl32 ioc32;
|
||||
struct usbdevfs_ioctl ctrl;
|
||||
u32 udata;
|
||||
|
||||
uioc = compat_ptr((long)arg);
|
||||
if (!access_ok(VERIFY_READ, uioc, sizeof(*uioc)) ||
|
||||
__get_user(ctrl.ifno, &uioc->ifno) ||
|
||||
__get_user(ctrl.ioctl_code, &uioc->ioctl_code) ||
|
||||
__get_user(udata, &uioc->data))
|
||||
if (copy_from_user(&ioc32, compat_ptr(arg), sizeof(ioc32)))
|
||||
return -EFAULT;
|
||||
ctrl.data = compat_ptr(udata);
|
||||
|
||||
ctrl.ifno = ioc32.ifno;
|
||||
ctrl.ioctl_code = ioc32.ioctl_code;
|
||||
ctrl.data = compat_ptr(ioc32.data);
|
||||
return proc_ioctl(ps, &ctrl);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1331,22 +1331,13 @@ static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix,
|
||||
static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
mm_segment_t old_fs;
|
||||
struct fb_fix_screeninfo fix;
|
||||
struct fb_fix_screeninfo32 __user *fix32;
|
||||
int err;
|
||||
|
||||
fix32 = compat_ptr(arg);
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
err = do_fb_ioctl(info, cmd, (unsigned long) &fix);
|
||||
set_fs(old_fs);
|
||||
|
||||
if (!err)
|
||||
err = do_fscreeninfo_to_user(&fix, fix32);
|
||||
|
||||
return err;
|
||||
if (!lock_fb_info(info))
|
||||
return -ENODEV;
|
||||
fix = info->fix;
|
||||
unlock_fb_info(info);
|
||||
return do_fscreeninfo_to_user(&fix, compat_ptr(arg));
|
||||
}
|
||||
|
||||
static long fb_compat_ioctl(struct file *file, unsigned int cmd,
|
||||
|
||||
+5
-39
@@ -1161,59 +1161,25 @@ static
|
||||
int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
|
||||
unsigned long *fdset)
|
||||
{
|
||||
nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);
|
||||
if (ufdset) {
|
||||
unsigned long odd;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, ufdset, nr*sizeof(compat_ulong_t)))
|
||||
return -EFAULT;
|
||||
|
||||
odd = nr & 1UL;
|
||||
nr &= ~1UL;
|
||||
while (nr) {
|
||||
unsigned long h, l;
|
||||
if (__get_user(l, ufdset) || __get_user(h, ufdset+1))
|
||||
return -EFAULT;
|
||||
ufdset += 2;
|
||||
*fdset++ = h << 32 | l;
|
||||
nr -= 2;
|
||||
}
|
||||
if (odd && __get_user(*fdset, ufdset))
|
||||
return -EFAULT;
|
||||
return compat_get_bitmap(fdset, ufdset, nr);
|
||||
} else {
|
||||
/* Tricky, must clear full unsigned long in the
|
||||
* kernel fdset at the end, this makes sure that
|
||||
* kernel fdset at the end, ALIGN makes sure that
|
||||
* actually happens.
|
||||
*/
|
||||
memset(fdset, 0, ((nr + 1) & ~1)*sizeof(compat_ulong_t));
|
||||
memset(fdset, 0, ALIGN(nr, BITS_PER_LONG));
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
|
||||
unsigned long *fdset)
|
||||
{
|
||||
unsigned long odd;
|
||||
nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);
|
||||
|
||||
if (!ufdset)
|
||||
return 0;
|
||||
|
||||
odd = nr & 1UL;
|
||||
nr &= ~1UL;
|
||||
while (nr) {
|
||||
unsigned long h, l;
|
||||
l = *fdset++;
|
||||
h = l >> 32;
|
||||
if (__put_user(l, ufdset) || __put_user(h, ufdset+1))
|
||||
return -EFAULT;
|
||||
ufdset += 2;
|
||||
nr -= 2;
|
||||
}
|
||||
if (odd && __put_user(*fdset, ufdset))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
return compat_put_bitmap(ufdset, fdset, nr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -402,8 +402,7 @@ asmlinkage long compat_sys_wait4(compat_pid_t pid,
|
||||
|
||||
#define BITS_PER_COMPAT_LONG (8*sizeof(compat_long_t))
|
||||
|
||||
#define BITS_TO_COMPAT_LONGS(bits) \
|
||||
(((bits)+BITS_PER_COMPAT_LONG-1)/BITS_PER_COMPAT_LONG)
|
||||
#define BITS_TO_COMPAT_LONGS(bits) DIV_ROUND_UP(bits, BITS_PER_COMPAT_LONG)
|
||||
|
||||
long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
|
||||
unsigned long bitmap_size);
|
||||
|
||||
@@ -243,8 +243,6 @@ extern int do_send_sig_info(int sig, struct siginfo *info,
|
||||
struct task_struct *p, bool group);
|
||||
extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p);
|
||||
extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
|
||||
extern int do_sigtimedwait(const sigset_t *, siginfo_t *,
|
||||
const struct timespec *);
|
||||
extern int sigprocmask(int, sigset_t *, sigset_t *);
|
||||
extern void set_current_blocked(sigset_t *);
|
||||
extern void __set_current_blocked(const sigset_t *);
|
||||
|
||||
@@ -650,7 +650,7 @@ asmlinkage long sys_olduname(struct oldold_utsname __user *);
|
||||
|
||||
asmlinkage long sys_getrlimit(unsigned int resource,
|
||||
struct rlimit __user *rlim);
|
||||
#if defined(COMPAT_RLIM_OLD_INFINITY) || !(defined(CONFIG_IA64))
|
||||
#ifdef __ARCH_WANT_SYS_OLD_GETRLIMIT
|
||||
asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit __user *rlim);
|
||||
#endif
|
||||
asmlinkage long sys_setrlimit(unsigned int resource,
|
||||
|
||||
@@ -180,9 +180,6 @@ extern int do_getitimer(int which, struct itimerval *value);
|
||||
|
||||
extern long do_utimes(int dfd, const char __user *filename, struct timespec *times, int flags);
|
||||
|
||||
struct tms;
|
||||
extern void do_sys_times(struct tms *);
|
||||
|
||||
/*
|
||||
* Similar to the struct tm in userspace <time.h>, but it needs to be here so
|
||||
* that the kernel source is self contained.
|
||||
|
||||
+1
-2
@@ -5,8 +5,7 @@
|
||||
obj-$(CONFIG_SYSVIPC_COMPAT) += compat.o
|
||||
obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o syscall.o
|
||||
obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o
|
||||
obj_mq-$(CONFIG_COMPAT) += compat_mq.o
|
||||
obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y)
|
||||
obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o
|
||||
obj-$(CONFIG_IPC_NS) += namespace.o
|
||||
obj-$(CONFIG_POSIX_MQUEUE_SYSCTL) += mq_sysctl.o
|
||||
|
||||
|
||||
-138
@@ -1,138 +0,0 @@
|
||||
/*
|
||||
* ipc/compat_mq.c
|
||||
* 32 bit emulation for POSIX message queue system calls
|
||||
*
|
||||
* Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation
|
||||
* Author: Arnd Bergmann <arnd@arndb.de>
|
||||
*/
|
||||
|
||||
#include <linux/compat.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mqueue.h>
|
||||
#include <linux/syscalls.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
struct compat_mq_attr {
|
||||
compat_long_t mq_flags; /* message queue flags */
|
||||
compat_long_t mq_maxmsg; /* maximum number of messages */
|
||||
compat_long_t mq_msgsize; /* maximum message size */
|
||||
compat_long_t mq_curmsgs; /* number of messages currently queued */
|
||||
compat_long_t __reserved[4]; /* ignored for input, zeroed for output */
|
||||
};
|
||||
|
||||
static inline int get_compat_mq_attr(struct mq_attr *attr,
|
||||
const struct compat_mq_attr __user *uattr)
|
||||
{
|
||||
if (!access_ok(VERIFY_READ, uattr, sizeof *uattr))
|
||||
return -EFAULT;
|
||||
|
||||
return __get_user(attr->mq_flags, &uattr->mq_flags)
|
||||
| __get_user(attr->mq_maxmsg, &uattr->mq_maxmsg)
|
||||
| __get_user(attr->mq_msgsize, &uattr->mq_msgsize)
|
||||
| __get_user(attr->mq_curmsgs, &uattr->mq_curmsgs);
|
||||
}
|
||||
|
||||
static inline int put_compat_mq_attr(const struct mq_attr *attr,
|
||||
struct compat_mq_attr __user *uattr)
|
||||
{
|
||||
if (clear_user(uattr, sizeof *uattr))
|
||||
return -EFAULT;
|
||||
|
||||
return __put_user(attr->mq_flags, &uattr->mq_flags)
|
||||
| __put_user(attr->mq_maxmsg, &uattr->mq_maxmsg)
|
||||
| __put_user(attr->mq_msgsize, &uattr->mq_msgsize)
|
||||
| __put_user(attr->mq_curmsgs, &uattr->mq_curmsgs);
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE4(mq_open, const char __user *, u_name,
|
||||
int, oflag, compat_mode_t, mode,
|
||||
struct compat_mq_attr __user *, u_attr)
|
||||
{
|
||||
void __user *p = NULL;
|
||||
if (u_attr && oflag & O_CREAT) {
|
||||
struct mq_attr attr;
|
||||
|
||||
memset(&attr, 0, sizeof(attr));
|
||||
|
||||
p = compat_alloc_user_space(sizeof(attr));
|
||||
if (get_compat_mq_attr(&attr, u_attr) ||
|
||||
copy_to_user(p, &attr, sizeof(attr)))
|
||||
return -EFAULT;
|
||||
}
|
||||
return sys_mq_open(u_name, oflag, mode, p);
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes,
|
||||
const char __user *, u_msg_ptr,
|
||||
compat_size_t, msg_len, unsigned int, msg_prio,
|
||||
const struct compat_timespec __user *, u_abs_timeout)
|
||||
{
|
||||
struct timespec __user *u_ts;
|
||||
|
||||
if (compat_convert_timespec(&u_ts, u_abs_timeout))
|
||||
return -EFAULT;
|
||||
|
||||
return sys_mq_timedsend(mqdes, u_msg_ptr, msg_len,
|
||||
msg_prio, u_ts);
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes,
|
||||
char __user *, u_msg_ptr,
|
||||
compat_size_t, msg_len, unsigned int __user *, u_msg_prio,
|
||||
const struct compat_timespec __user *, u_abs_timeout)
|
||||
{
|
||||
struct timespec __user *u_ts;
|
||||
|
||||
if (compat_convert_timespec(&u_ts, u_abs_timeout))
|
||||
return -EFAULT;
|
||||
|
||||
return sys_mq_timedreceive(mqdes, u_msg_ptr, msg_len,
|
||||
u_msg_prio, u_ts);
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes,
|
||||
const struct compat_sigevent __user *, u_notification)
|
||||
{
|
||||
struct sigevent __user *p = NULL;
|
||||
if (u_notification) {
|
||||
struct sigevent n;
|
||||
p = compat_alloc_user_space(sizeof(*p));
|
||||
if (get_compat_sigevent(&n, u_notification))
|
||||
return -EFAULT;
|
||||
if (n.sigev_notify == SIGEV_THREAD)
|
||||
n.sigev_value.sival_ptr = compat_ptr(n.sigev_value.sival_int);
|
||||
if (copy_to_user(p, &n, sizeof(*p)))
|
||||
return -EFAULT;
|
||||
}
|
||||
return sys_mq_notify(mqdes, p);
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes,
|
||||
const struct compat_mq_attr __user *, u_mqstat,
|
||||
struct compat_mq_attr __user *, u_omqstat)
|
||||
{
|
||||
struct mq_attr mqstat;
|
||||
struct mq_attr __user *p = compat_alloc_user_space(2 * sizeof(*p));
|
||||
long ret;
|
||||
|
||||
memset(&mqstat, 0, sizeof(mqstat));
|
||||
|
||||
if (u_mqstat) {
|
||||
if (get_compat_mq_attr(&mqstat, u_mqstat) ||
|
||||
copy_to_user(p, &mqstat, sizeof(mqstat)))
|
||||
return -EFAULT;
|
||||
}
|
||||
ret = sys_mq_getsetattr(mqdes,
|
||||
u_mqstat ? p : NULL,
|
||||
u_omqstat ? p + 1 : NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (u_omqstat) {
|
||||
if (copy_from_user(&mqstat, p + 1, sizeof(mqstat)) ||
|
||||
put_compat_mq_attr(&mqstat, u_omqstat))
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+262
-89
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user