diff options
Diffstat (limited to 'drivers/usb/core/devio.c')
-rw-r--r-- | drivers/usb/core/devio.c | 69 |
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)) |