aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2007-07-30 17:09:28 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-10-12 17:55:01 -0400
commit93cf9b909efb773f74b5d87659d41f957ccbce7e (patch)
tree9cb682bb70c73aed99ecddf94f0136566fe3ce7e
parent4326ed0be93574dac5b5e475713015159108bd88 (diff)
USB: avoid urb->pipe in usbfs
This patch (as948) removes most of the references to urb->pipe from the usbfs routines in devio.c. The one tricky aspect is in snoop_urb(), which can be called before the URB is submitted and which uses usb_urb_dir_in(). For this to work properly, the URB's direction flag must be set manually in proc_do_submiturb(). The patch also fixes a minor bug; the wValue, wIndex, and wLength fields were snooped in proc_do_submiturb() without conversion from le16 to CPU-byte-ordering. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/core/devio.c69
1 files changed, 41 insertions, 28 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 927a181120a9..b9f1edd6af53 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -289,10 +289,8 @@ static void snoop_urb(struct urb *urb, void __user *userurb)
289 if (!usbfs_snoop) 289 if (!usbfs_snoop)
290 return; 290 return;
291 291
292 if (urb->pipe & USB_DIR_IN) 292 dev_info(&urb->dev->dev, "direction=%s\n",
293 dev_info(&urb->dev->dev, "direction=IN\n"); 293 usb_urb_dir_in(urb) ? "IN" : "OUT");
294 else
295 dev_info(&urb->dev->dev, "direction=OUT\n");
296 dev_info(&urb->dev->dev, "userurb=%p\n", userurb); 294 dev_info(&urb->dev->dev, "userurb=%p\n", userurb);
297 dev_info(&urb->dev->dev, "transfer_buffer_length=%d\n", 295 dev_info(&urb->dev->dev, "transfer_buffer_length=%d\n",
298 urb->transfer_buffer_length); 296 urb->transfer_buffer_length);
@@ -910,6 +908,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
910 struct usb_ctrlrequest *dr = NULL; 908 struct usb_ctrlrequest *dr = NULL;
911 unsigned int u, totlen, isofrmlen; 909 unsigned int u, totlen, isofrmlen;
912 int ret, ifnum = -1; 910 int ret, ifnum = -1;
911 int is_in;
913 912
914 if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK| 913 if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
915 URB_NO_FSBR|URB_ZERO_PACKET)) 914 URB_NO_FSBR|URB_ZERO_PACKET))
@@ -924,16 +923,18 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
924 if ((ret = checkintf(ps, ifnum))) 923 if ((ret = checkintf(ps, ifnum)))
925 return ret; 924 return ret;
926 } 925 }
927 if ((uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0) 926 if ((uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0) {
928 ep = ps->dev->ep_in [uurb->endpoint & USB_ENDPOINT_NUMBER_MASK]; 927 is_in = 1;
929 else 928 ep = ps->dev->ep_in[uurb->endpoint & USB_ENDPOINT_NUMBER_MASK];
930 ep = ps->dev->ep_out [uurb->endpoint & USB_ENDPOINT_NUMBER_MASK]; 929 } else {
930 is_in = 0;
931 ep = ps->dev->ep_out[uurb->endpoint & USB_ENDPOINT_NUMBER_MASK];
932 }
931 if (!ep) 933 if (!ep)
932 return -ENOENT; 934 return -ENOENT;
933 switch(uurb->type) { 935 switch(uurb->type) {
934 case USBDEVFS_URB_TYPE_CONTROL: 936 case USBDEVFS_URB_TYPE_CONTROL:
935 if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 937 if (!usb_endpoint_xfer_control(&ep->desc))
936 != USB_ENDPOINT_XFER_CONTROL)
937 return -EINVAL; 938 return -EINVAL;
938 /* min 8 byte setup packet, max 8 byte setup plus an arbitrary data stage */ 939 /* min 8 byte setup packet, max 8 byte setup plus an arbitrary data stage */
939 if (uurb->buffer_length < 8 || uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE)) 940 if (uurb->buffer_length < 8 || uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE))
@@ -952,23 +953,32 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
952 kfree(dr); 953 kfree(dr);
953 return ret; 954 return ret;
954 } 955 }
955 uurb->endpoint = (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) | (dr->bRequestType & USB_ENDPOINT_DIR_MASK);
956 uurb->number_of_packets = 0; 956 uurb->number_of_packets = 0;
957 uurb->buffer_length = le16_to_cpup(&dr->wLength); 957 uurb->buffer_length = le16_to_cpup(&dr->wLength);
958 uurb->buffer += 8; 958 uurb->buffer += 8;
959 if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length)) { 959 if ((dr->bRequestType & USB_DIR_IN) && uurb->buffer_length) {
960 is_in = 1;
961 uurb->endpoint |= USB_DIR_IN;
962 } else {
963 is_in = 0;
964 uurb->endpoint &= ~USB_DIR_IN;
965 }
966 if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
967 uurb->buffer, uurb->buffer_length)) {
960 kfree(dr); 968 kfree(dr);
961 return -EFAULT; 969 return -EFAULT;
962 } 970 }
963 snoop(&ps->dev->dev, "control urb: bRequest=%02x " 971 snoop(&ps->dev->dev, "control urb: bRequest=%02x "
964 "bRrequestType=%02x wValue=%04x " 972 "bRrequestType=%02x wValue=%04x "
965 "wIndex=%04x wLength=%04x\n", 973 "wIndex=%04x wLength=%04x\n",
966 dr->bRequest, dr->bRequestType, dr->wValue, 974 dr->bRequest, dr->bRequestType,
967 dr->wIndex, dr->wLength); 975 __le16_to_cpup(&dr->wValue),
976 __le16_to_cpup(&dr->wIndex),
977 __le16_to_cpup(&dr->wLength));
968 break; 978 break;
969 979
970 case USBDEVFS_URB_TYPE_BULK: 980 case USBDEVFS_URB_TYPE_BULK:
971 switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { 981 switch (usb_endpoint_type(&ep->desc)) {
972 case USB_ENDPOINT_XFER_CONTROL: 982 case USB_ENDPOINT_XFER_CONTROL:
973 case USB_ENDPOINT_XFER_ISOC: 983 case USB_ENDPOINT_XFER_ISOC:
974 return -EINVAL; 984 return -EINVAL;
@@ -977,7 +987,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
977 uurb->number_of_packets = 0; 987 uurb->number_of_packets = 0;
978 if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) 988 if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
979 return -EINVAL; 989 return -EINVAL;
980 if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length)) 990 if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
991 uurb->buffer, uurb->buffer_length))
981 return -EFAULT; 992 return -EFAULT;
982 snoop(&ps->dev->dev, "bulk urb\n"); 993 snoop(&ps->dev->dev, "bulk urb\n");
983 break; 994 break;
@@ -986,8 +997,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
986 /* arbitrary limit */ 997 /* arbitrary limit */
987 if (uurb->number_of_packets < 1 || uurb->number_of_packets > 128) 998 if (uurb->number_of_packets < 1 || uurb->number_of_packets > 128)
988 return -EINVAL; 999 return -EINVAL;
989 if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 1000 if (!usb_endpoint_xfer_isoc(&ep->desc))
990 != USB_ENDPOINT_XFER_ISOC)
991 return -EINVAL; 1001 return -EINVAL;
992 isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets; 1002 isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets;
993 if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL))) 1003 if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
@@ -1014,12 +1024,12 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
1014 1024
1015 case USBDEVFS_URB_TYPE_INTERRUPT: 1025 case USBDEVFS_URB_TYPE_INTERRUPT:
1016 uurb->number_of_packets = 0; 1026 uurb->number_of_packets = 0;
1017 if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 1027 if (!usb_endpoint_xfer_int(&ep->desc))
1018 != USB_ENDPOINT_XFER_INT)
1019 return -EINVAL; 1028 return -EINVAL;
1020 if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) 1029 if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
1021 return -EINVAL; 1030 return -EINVAL;
1022 if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length)) 1031 if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
1032 uurb->buffer, uurb->buffer_length))
1023 return -EFAULT; 1033 return -EFAULT;
1024 snoop(&ps->dev->dev, "interrupt urb\n"); 1034 snoop(&ps->dev->dev, "interrupt urb\n");
1025 break; 1035 break;
@@ -1039,8 +1049,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
1039 return -ENOMEM; 1049 return -ENOMEM;
1040 } 1050 }
1041 as->urb->dev = ps->dev; 1051 as->urb->dev = ps->dev;
1042 as->urb->pipe = (uurb->type << 30) | __create_pipe(ps->dev, uurb->endpoint & 0xf) | (uurb->endpoint & USB_DIR_IN); 1052 as->urb->pipe = (uurb->type << 30) |
1043 as->urb->transfer_flags = uurb->flags; 1053 __create_pipe(ps->dev, uurb->endpoint & 0xf) |
1054 (uurb->endpoint & USB_DIR_IN);
1055 as->urb->transfer_flags = uurb->flags |
1056 (is_in ? URB_DIR_IN : URB_DIR_OUT);
1044 as->urb->transfer_buffer_length = uurb->buffer_length; 1057 as->urb->transfer_buffer_length = uurb->buffer_length;
1045 as->urb->setup_packet = (unsigned char*)dr; 1058 as->urb->setup_packet = (unsigned char*)dr;
1046 as->urb->start_frame = uurb->start_frame; 1059 as->urb->start_frame = uurb->start_frame;
@@ -1070,13 +1083,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
1070 as->uid = current->uid; 1083 as->uid = current->uid;
1071 as->euid = current->euid; 1084 as->euid = current->euid;
1072 security_task_getsecid(current, &as->secid); 1085 security_task_getsecid(current, &as->secid);
1073 if (!(uurb->endpoint & USB_DIR_IN)) { 1086 if (!is_in) {
1074 if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, as->urb->transfer_buffer_length)) { 1087 if (copy_from_user(as->urb->transfer_buffer, uurb->buffer,
1088 as->urb->transfer_buffer_length)) {
1075 free_async(as); 1089 free_async(as);
1076 return -EFAULT; 1090 return -EFAULT;
1077 } 1091 }
1078 } 1092 }
1079 snoop(&as->urb->dev->dev, "submit urb\n");
1080 snoop_urb(as->urb, as->userurb); 1093 snoop_urb(as->urb, as->userurb);
1081 async_newpending(as); 1094 async_newpending(as);
1082 if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) { 1095 if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) {
@@ -1126,7 +1139,7 @@ static int processcompl(struct async *as, void __user * __user *arg)
1126 if (put_user(urb->error_count, &userurb->error_count)) 1139 if (put_user(urb->error_count, &userurb->error_count))
1127 return -EFAULT; 1140 return -EFAULT;
1128 1141
1129 if (usb_pipeisoc(urb->pipe)) { 1142 if (usb_endpoint_xfer_isoc(&urb->ep->desc)) {
1130 for (i = 0; i < urb->number_of_packets; i++) { 1143 for (i = 0; i < urb->number_of_packets; i++) {
1131 if (put_user(urb->iso_frame_desc[i].actual_length, 1144 if (put_user(urb->iso_frame_desc[i].actual_length,
1132 &userurb->iso_frame_desc[i].actual_length)) 1145 &userurb->iso_frame_desc[i].actual_length))
@@ -1240,7 +1253,7 @@ static int processcompl_compat(struct async *as, void __user * __user *arg)
1240 if (put_user(urb->error_count, &userurb->error_count)) 1253 if (put_user(urb->error_count, &userurb->error_count))
1241 return -EFAULT; 1254 return -EFAULT;
1242 1255
1243 if (usb_pipeisoc(urb->pipe)) { 1256 if (usb_endpoint_xfer_isoc(&urb->ep->desc)) {
1244 for (i = 0; i < urb->number_of_packets; i++) { 1257 for (i = 0; i < urb->number_of_packets; i++) {
1245 if (put_user(urb->iso_frame_desc[i].actual_length, 1258 if (put_user(urb->iso_frame_desc[i].actual_length,
1246 &userurb->iso_frame_desc[i].actual_length)) 1259 &userurb->iso_frame_desc[i].actual_length))