[SSI] openssi/kernel/fs compat_ioctl.c,1.2,1.3
John Hughes <[email protected]> Fri, 19 Feb 2010 11:59:38 +0000
| Newsgroups | gmane.linux.cluster.ssic.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/ssic-linux/openssi/kernel/fs
In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv23914
Modified Files:
compat_ioctl.c
Log Message:
Base on 2.6.11 version instead of incorrectly imported 2.6.12 version
Index: compat_ioctl.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/fs/compat_ioctl.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- compat_ioctl.c 18 Feb 2010 17:04:25 -0000 1.2
+++ compat_ioctl.c 19 Feb 2010 11:59:36 -0000 1.3
@@ -1281,9 +1281,35 @@
};
#define MTIOCPOS32 _IOR('m', 3, struct mtpos32)
+struct mtconfiginfo32 {
+ compat_long_t mt_type;
+ compat_long_t ifc_type;
+ unsigned short irqnr;
+ unsigned short dmanr;
+ unsigned short port;
+ compat_ulong_t debug;
+ compat_uint_t have_dens:1;
+ compat_uint_t have_bsf:1;
+ compat_uint_t have_fsr:1;
+ compat_uint_t have_bsr:1;
+ compat_uint_t have_eod:1;
+ compat_uint_t have_seek:1;
+ compat_uint_t have_tell:1;
+ compat_uint_t have_ras1:1;
+ compat_uint_t have_ras2:1;
+ compat_uint_t have_ras3:1;
+ compat_uint_t have_qfa:1;
+ compat_uint_t pad1:5;
+ char reserved[10];
+};
+#define MTIOCGETCONFIG32 _IOR('m', 4, struct mtconfiginfo32)
+#define MTIOCSETCONFIG32 _IOW('m', 5, struct mtconfiginfo32)
+
static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
{
mm_segment_t old_fs = get_fs();
+ struct mtconfiginfo info;
+ struct mtconfiginfo32 __user *uinfo32;
struct mtget get;
struct mtget32 __user *umget32;
struct mtpos pos;
@@ -1301,6 +1327,27 @@
kcmd = MTIOCGET;
karg = &get;
break;
+ case MTIOCGETCONFIG32:
+ kcmd = MTIOCGETCONFIG;
+ karg = &info;
+ break;
+ case MTIOCSETCONFIG32:
+ kcmd = MTIOCSETCONFIG;
+ karg = &info;
+ uinfo32 = compat_ptr(arg);
+ err = __get_user(info.mt_type, &uinfo32->mt_type);
+ err |= __get_user(info.ifc_type, &uinfo32->ifc_type);
+ err |= __get_user(info.irqnr, &uinfo32->irqnr);
+ err |= __get_user(info.dmanr, &uinfo32->dmanr);
+ err |= __get_user(info.port, &uinfo32->port);
+ err |= __get_user(info.debug, &uinfo32->debug);
+ err |= __copy_from_user((char *)&info.debug
+ + sizeof(info.debug),
+ (char __user *)&uinfo32->debug
+ + sizeof(uinfo32->debug), sizeof(__u32));
+ if (err)
+ return -EFAULT;
+ break;
default:
do {
static int count;
@@ -1331,6 +1378,20 @@
err |= __put_user(get.mt_fileno, &umget32->mt_fileno);
err |= __put_user(get.mt_blkno, &umget32->mt_blkno);
break;
+ case MTIOCGETCONFIG32:
+ uinfo32 = compat_ptr(arg);
+ err = __put_user(info.mt_type, &uinfo32->mt_type);
+ err |= __put_user(info.ifc_type, &uinfo32->ifc_type);
+ err |= __put_user(info.irqnr, &uinfo32->irqnr);
+ err |= __put_user(info.dmanr, &uinfo32->dmanr);
+ err |= __put_user(info.port, &uinfo32->port);
+ err |= __put_user(info.debug, &uinfo32->debug);
+ err |= __copy_to_user((char __user *)&uinfo32->debug
+ + sizeof(uinfo32->debug),
+ (char *)&info.debug + sizeof(info.debug), sizeof(__u32));
+ break;
+ case MTIOCSETCONFIG32:
+ break;
}
return err ? -EFAULT: 0;
}
@@ -1565,7 +1626,7 @@
get_user(data, &user_cfd->chardata))
return -EFAULT;
op.data = compat_ptr(data);
- return con_font_op(vc_cons[fg_console].d, &op);
+ return con_font_op(fg_console, &op);
case GIO_FONTX:
op.op = KD_FONT_OP_GET;
op.flags = 0;
@@ -1577,7 +1638,7 @@
if (!data)
return 0;
op.data = compat_ptr(data);
- i = con_font_op(vc_cons[fg_console].d, &op);
+ i = con_font_op(fg_console, &op);
if (i)
return i;
if (put_user(op.height, &user_cfd->charheight) ||
@@ -1603,7 +1664,7 @@
struct console_font_op op;
struct console_font_op32 __user *fontop = compat_ptr(arg);
int perm = vt_check(file), i;
- struct vc_data *vc;
+ struct vt_struct *vt;
if (perm < 0) return perm;
@@ -1613,10 +1674,9 @@
return -EPERM;
op.data = compat_ptr(((struct console_font_op32 *)&op)->data);
op.flags |= KD_FONT_FLAG_OLD;
- vc = ((struct tty_struct *)file->private_data)->driver_data;
- i = con_font_op(vc, &op);
- if (i)
- return i;
+ vt = (struct vt_struct *)((struct tty_struct *)file->private_data)->driver_data;
+ i = con_font_op(vt->vc_num, &op);
+ if (i) return i;
((struct console_font_op32 *)&op)->data = (unsigned long)op.data;
if (copy_to_user(fontop, &op, sizeof(struct console_font_op32)))
return -EFAULT;
@@ -1640,9 +1700,9 @@
switch (cmd) {
case PIO_UNIMAP:
if (!perm) return -EPERM;
- return con_set_unimap(vc_cons[fg_console].d, tmp.entry_ct, compat_ptr(tmp.entries));
+ return con_set_unimap(fg_console, tmp.entry_ct, compat_ptr(tmp.entries));
case GIO_UNIMAP:
- return con_get_unimap(vc_cons[fg_console].d, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries));
+ return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries));
}
return 0;
}
@@ -2288,8 +2348,11 @@
static long
put_dirent32 (struct dirent *d, struct compat_dirent __user *d32)
{
- if (!access_ok(VERIFY_WRITE, d32, sizeof(struct compat_dirent)))
- return -EFAULT;
+ int ret;
+
+ if ((ret = verify_area(VERIFY_WRITE, d32,
+ sizeof(struct compat_dirent))))
+ return ret;
__put_user(d->d_ino, &d32->d_ino);
__put_user(d->d_off, &d32->d_off);
@@ -2297,7 +2360,7 @@
if (__copy_to_user(d32->d_name, d->d_name, d->d_reclen))
return -EFAULT;
- return 0;
+ return ret;
}
static int vfat_ioctl32(unsigned fd, unsigned cmd, unsigned long arg)
@@ -2348,8 +2411,9 @@
{
int ret;
- if (!access_ok(VERIFY_READ, user_req, sizeof(struct raw32_config_request)))
- return -EFAULT;
+ if ((ret = verify_area(VERIFY_READ, user_req,
+ sizeof(struct raw32_config_request))))
+ return ret;
ret = __get_user(req->raw_minor, &user_req->raw_minor);
ret |= __get_user(req->block_major, &user_req->block_major);
@@ -2362,8 +2426,9 @@
{
int ret;
- if (!access_ok(VERIFY_WRITE, user_req, sizeof(struct raw32_config_request)))
- return -EFAULT;
+ if ((ret = verify_area(VERIFY_WRITE, user_req,
+ sizeof(struct raw32_config_request))))
+ return ret;
ret = __put_user(req->raw_minor, &user_req->raw_minor);
ret |= __put_user(req->block_major, &user_req->block_major);
@@ -2435,7 +2500,7 @@
__u32 udata;
if (cmd == TIOCSSERIAL) {
- if (!access_ok(VERIFY_READ, ss32, sizeof(SS32)))
+ if (verify_area(VERIFY_READ, ss32, sizeof(SS32)))
return -EFAULT;
if (__copy_from_user(&ss, ss32, offsetof(SS32, iomem_base)))
return -EFAULT;
@@ -2449,7 +2514,7 @@
err = sys_ioctl(fd,cmd,(unsigned long)(&ss));
set_fs(oldseg);
if (cmd == TIOCGSERIAL && err >= 0) {
- if (!access_ok(VERIFY_WRITE, ss32, sizeof(SS32)))
+ if (verify_area(VERIFY_WRITE, ss32, sizeof(SS32)))
return -EFAULT;
if (__copy_to_user(ss32,&ss,offsetof(SS32,iomem_base)))
return -EFAULT;
@@ -2516,11 +2581,229 @@
return sys_ioctl(fd, USBDEVFS_BULK, (unsigned long)p);
}
-
-/*
- * USBDEVFS_SUBMITURB, USBDEVFS_REAPURB and USBDEVFS_REAPURBNDELAY
- * are handled in usbdevfs core. -Christopher Li
+/* This needs more work before we can enable it. Unfortunately
+ * because of the fancy asynchronous way URB status/error is written
+ * back to userspace, we'll need to fiddle with USB devio internals
+ * and/or reimplement entirely the frontend of it ourselves. -DaveM
+ *
+ * The issue is:
+ *
+ * When an URB is submitted via usbdevicefs it is put onto an
+ * asynchronous queue. When the URB completes, it may be reaped
+ * via another ioctl. During this reaping the status is written
+ * back to userspace along with the length of the transfer.
+ *
+ * We must translate into 64-bit kernel types so we pass in a kernel
+ * space copy of the usbdevfs_urb structure. This would mean that we
+ * must do something to deal with the async entry reaping. First we
+ * have to deal somehow with this transitory memory we've allocated.
+ * This is problematic since there are many call sites from which the
+ * async entries can be destroyed (and thus when we'd need to free up
+ * this kernel memory). One of which is the close() op of usbdevicefs.
+ * To handle that we'd need to make our own file_operations struct which
+ * overrides usbdevicefs's release op with our own which runs usbdevicefs's
+ * real release op then frees up the kernel memory.
+ *
+ * But how to keep track of these kernel buffers? We'd need to either
+ * keep track of them in some table _or_ know about usbdevicefs internals
+ * (ie. the exact layout of its file private, which is actually defined
+ * in linux/usbdevice_fs.h, the layout of the async queues are private to
+ * devio.c)
+ *
+ * There is one possible other solution I considered, also involving knowledge
+ * of usbdevicefs internals:
+ *
+ * After an URB is submitted, we "fix up" the address back to the user
+ * space one. This would work if the status/length fields written back
+ * by the async URB completion lines up perfectly in the 32-bit type with
+ * the 64-bit kernel type. Unfortunately, it does not because the iso
+ * frame descriptors, at the end of the struct, can be written back.
+ *
+ * I think we'll just need to simply duplicate the devio URB engine here.
*/
+#if 0
+struct usbdevfs_urb32 {
+ unsigned char type;
+ unsigned char endpoint;
+ compat_int_t status;
+ compat_uint_t flags;
+ compat_caddr_t buffer;
+ compat_int_t buffer_length;
+ compat_int_t actual_length;
+ compat_int_t start_frame;
+ compat_int_t number_of_packets;
+ compat_int_t error_count;
+ compat_uint_t signr;
+ compat_caddr_t usercontext; /* unused */
+ struct usbdevfs_iso_packet_desc iso_frame_desc[0];
+};
+
+#define USBDEVFS_SUBMITURB32 _IOR('U', 10, struct usbdevfs_urb32)
+
+static int get_urb32(struct usbdevfs_urb *kurb,
+ struct usbdevfs_urb32 *uurb)
+{
+ if (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))
+ return -EFAULT;
+
+ kurb->usercontext = 0; /* unused currently */
+
+ return 0;
+}
+
+/* Just put back the values which usbdevfs actually changes. */
+static int put_urb32(struct usbdevfs_urb *kurb,
+ struct usbdevfs_urb32 *uurb)
+{
+ if (put_user(kurb->status, &uurb->status) ||
+ __put_user(kurb->actual_length, &uurb->actual_length) ||
+ __put_user(kurb->error_count, &uurb->error_count))
+ return -EFAULT;
+
+ if (kurb->number_of_packets != 0) {
+ int i;
+
+ for (i = 0; i < kurb->number_of_packets; i++) {
+ if (__put_user(kurb->iso_frame_desc[i].actual_length,
+ &uurb->iso_frame_desc[i].actual_length) ||
+ __put_user(kurb->iso_frame_desc[i].status,
+ &uurb->iso_frame_desc[i].status))
+ return -EFAULT;
+ }
+ }
+
+ return 0;
+}
+
+static int get_urb32_isoframes(struct usbdevfs_urb *kurb,
+ struct usbdevfs_urb32 *uurb)
+{
+ unsigned int totlen;
+ int i;
+
+ if (kurb->type != USBDEVFS_URB_TYPE_ISO) {
+ kurb->number_of_packets = 0;
+ return 0;
+ }
+
+ if (kurb->number_of_packets < 1 ||
+ kurb->number_of_packets > 128)
+ return -EINVAL;
+
+ if (copy_from_user(&kurb->iso_frame_desc[0],
+ &uurb->iso_frame_desc[0],
+ sizeof(struct usbdevfs_iso_packet_desc) *
+ kurb->number_of_packets))
+ return -EFAULT;
+
+ totlen = 0;
+ for (i = 0; i < kurb->number_of_packets; i++) {
+ unsigned int this_len;
+
+ this_len = kurb->iso_frame_desc[i].length;
+ if (this_len > 1023)
+ return -EINVAL;
+
+ totlen += this_len;
+ }
+
+ if (totlen > 32768)
+ return -EINVAL;
+
+ kurb->buffer_length = totlen;
+
+ return 0;
+}
+
+static int do_usbdevfs_urb(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ struct usbdevfs_urb *kurb;
+ struct usbdevfs_urb32 *uurb;
+ mm_segment_t old_fs;
+ __u32 udata;
+ void *uptr, *kptr;
+ unsigned int buflen;
+ int err;
+
+ uurb = compat_ptr(arg);
+
+ err = -ENOMEM;
+ kurb = kmalloc(sizeof(struct usbdevfs_urb) +
+ (sizeof(struct usbdevfs_iso_packet_desc) * 128),
+ GFP_KERNEL);
+ if (!kurb)
+ goto out;
+
+ err = -EFAULT;
+ if (get_urb32(kurb, uurb))
+ goto out;
+
+ err = get_urb32_isoframes(kurb, uurb);
+ if (err)
+ goto out;
+
+ err = -EFAULT;
+ if (__get_user(udata, &uurb->buffer))
+ goto out;
+ uptr = compat_ptr(udata);
+
+ buflen = kurb->buffer_length;
+ err = verify_area(VERIFY_WRITE, uptr, buflen);
+ if (err)
+ goto out;
+
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ err = sys_ioctl(fd, USBDEVFS_SUBMITURB, (unsigned long) kurb);
+ set_fs(old_fs);
+
+ if (err >= 0) {
+ /* RED-PEN Shit, this doesn't work for async URBs :-( XXX */
+ if (put_urb32(kurb, uurb)) {
+ err = -EFAULT;
+ }
+ }
+
+out:
+ kfree(kurb);
+ return err;
+}
+#endif
+
+#define USBDEVFS_REAPURB32 _IOW('U', 12, u32)
+#define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, u32)
+
+static int do_usbdevfs_reapurb(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ mm_segment_t old_fs;
+ void *kptr;
+ int err;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ err = sys_ioctl(fd,
+ (cmd == USBDEVFS_REAPURB32 ?
+ USBDEVFS_REAPURB :
+ USBDEVFS_REAPURBNDELAY),
+ (unsigned long) &kptr);
+ set_fs(old_fs);
+
+ if (err >= 0 &&
+ put_user((u32)(u64)kptr, (u32 __user *)compat_ptr(arg)))
+ err = -EFAULT;
+
+ return err;
+}
struct usbdevfs_disconnectsignal32 {
compat_int_t signr;
@@ -2626,11 +2909,11 @@
tdata = compat_alloc_user_space(sizeof(*tdata));
if (tdata == NULL)
return -ENOMEM;
- if (!access_ok(VERIFY_WRITE, tdata, sizeof(*tdata)))
+ if (verify_area(VERIFY_WRITE, tdata, sizeof(*tdata)))
return -EFAULT;
udata = compat_ptr(arg);
- if (!access_ok(VERIFY_READ, udata, sizeof(*udata)))
+ if (verify_area(VERIFY_READ, udata, sizeof(*udata)))
return -EFAULT;
if (__copy_in_user(&tdata->read_write, &udata->read_write, 2 * sizeof(u8)))
@@ -2667,7 +2950,7 @@
iwp = &iwr->u.data;
- if (!access_ok(VERIFY_WRITE, iwr, sizeof(*iwr)))
+ if (verify_area(VERIFY_WRITE, iwr, sizeof(*iwr)))
return -EFAULT;
if (__copy_in_user(&iwr->ifr_ifrn.ifrn_name[0],
@@ -2982,6 +3265,8 @@
HANDLE_IOCTL(PPPIOCSACTIVE32, ppp_sock_fprog_ioctl_trans)
HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans)
HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
+HANDLE_IOCTL(MTIOCGETCONFIG32, mt_ioctl_trans)
+HANDLE_IOCTL(MTIOCSETCONFIG32, mt_ioctl_trans)
HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans)
HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans)
HANDLE_IOCTL(LOOP_SET_STATUS, loop_status)
@@ -3052,6 +3337,9 @@
/* Usbdevfs */
HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control)
HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk)
+/*HANDLE_IOCTL(USBDEVFS_SUBMITURB32, do_usbdevfs_urb)*/
+HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb)
+HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb)
HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal)
/* i2c */
HANDLE_IOCTL(I2C_FUNCS, w_long)
------------------------------------------------------------------------------
Download Intel® Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev