aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/usb/cdc_ncm.c102
1 files changed, 47 insertions, 55 deletions
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index f8f194658412..7adc9f6b0ea1 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -71,13 +71,10 @@
71 71
72/* 72/*
73 * Maximum amount of datagrams in NCM Datagram Pointer Table, not counting 73 * Maximum amount of datagrams in NCM Datagram Pointer Table, not counting
74 * the last NULL entry. Any additional datagrams in NTB would be discarded. 74 * the last NULL entry.
75 */ 75 */
76#define CDC_NCM_DPT_DATAGRAMS_MAX 40 76#define CDC_NCM_DPT_DATAGRAMS_MAX 40
77 77
78/* Maximum amount of IN datagrams in NTB */
79#define CDC_NCM_DPT_DATAGRAMS_IN_MAX 0 /* unlimited */
80
81/* Restart the timer, if amount of datagrams is less than given value */ 78/* Restart the timer, if amount of datagrams is less than given value */
82#define CDC_NCM_RESTART_TIMER_DATAGRAM_CNT 3 79#define CDC_NCM_RESTART_TIMER_DATAGRAM_CNT 3
83#define CDC_NCM_TIMER_PENDING_CNT 2 80#define CDC_NCM_TIMER_PENDING_CNT 2
@@ -95,7 +92,6 @@ struct cdc_ncm_data {
95}; 92};
96 93
97struct cdc_ncm_ctx { 94struct cdc_ncm_ctx {
98 struct cdc_ncm_data rx_ncm;
99 struct cdc_ncm_data tx_ncm; 95 struct cdc_ncm_data tx_ncm;
100 struct usb_cdc_ncm_ntb_parameters ncm_parm; 96 struct usb_cdc_ncm_ntb_parameters ncm_parm;
101 struct hrtimer tx_timer; 97 struct hrtimer tx_timer;
@@ -135,6 +131,7 @@ struct cdc_ncm_ctx {
135 u16 tx_modulus; 131 u16 tx_modulus;
136 u16 tx_ndp_modulus; 132 u16 tx_ndp_modulus;
137 u16 tx_seq; 133 u16 tx_seq;
134 u16 rx_seq;
138 u16 connected; 135 u16 connected;
139}; 136};
140 137
@@ -956,108 +953,103 @@ error:
956static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in) 953static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
957{ 954{
958 struct sk_buff *skb; 955 struct sk_buff *skb;
959 struct cdc_ncm_ctx *ctx; 956 struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
960 int sumlen; 957 int len;
961 int actlen;
962 int temp;
963 int nframes; 958 int nframes;
964 int x; 959 int x;
965 int offset; 960 int offset;
961 struct usb_cdc_ncm_nth16 *nth16;
962 struct usb_cdc_ncm_ndp16 *ndp16;
963 struct usb_cdc_ncm_dpe16 *dpe16;
966 964
967 ctx = (struct cdc_ncm_ctx *)dev->data[0];
968 if (ctx == NULL) 965 if (ctx == NULL)
969 goto error; 966 goto error;
970 967
971 actlen = skb_in->len; 968 if (skb_in->len < (sizeof(struct usb_cdc_ncm_nth16) +
972 sumlen = CDC_NCM_NTB_MAX_SIZE_RX; 969 sizeof(struct usb_cdc_ncm_ndp16))) {
973
974 if (actlen < (sizeof(ctx->rx_ncm.nth16) + sizeof(ctx->rx_ncm.ndp16))) {
975 pr_debug("frame too short\n"); 970 pr_debug("frame too short\n");
976 goto error; 971 goto error;
977 } 972 }
978 973
979 memcpy(&(ctx->rx_ncm.nth16), ((u8 *)skb_in->data), 974 nth16 = (struct usb_cdc_ncm_nth16 *)skb_in->data;
980 sizeof(ctx->rx_ncm.nth16));
981 975
982 if (le32_to_cpu(ctx->rx_ncm.nth16.dwSignature) != 976 if (le32_to_cpu(nth16->dwSignature) != USB_CDC_NCM_NTH16_SIGN) {
983 USB_CDC_NCM_NTH16_SIGN) {
984 pr_debug("invalid NTH16 signature <%u>\n", 977 pr_debug("invalid NTH16 signature <%u>\n",
985 le32_to_cpu(ctx->rx_ncm.nth16.dwSignature)); 978 le32_to_cpu(nth16->dwSignature));
986 goto error; 979 goto error;
987 } 980 }
988 981
989 temp = le16_to_cpu(ctx->rx_ncm.nth16.wBlockLength); 982 len = le16_to_cpu(nth16->wBlockLength);
990 if (temp > sumlen) { 983 if (len > ctx->rx_max) {
991 pr_debug("unsupported NTB block length %u/%u\n", temp, sumlen); 984 pr_debug("unsupported NTB block length %u/%u\n", len,
985 ctx->rx_max);
992 goto error; 986 goto error;
993 } 987 }
994 988
995 temp = le16_to_cpu(ctx->rx_ncm.nth16.wNdpIndex); 989 if ((ctx->rx_seq + 1) != le16_to_cpu(nth16->wSequence) &&
996 if ((temp + sizeof(ctx->rx_ncm.ndp16)) > actlen) { 990 (ctx->rx_seq || le16_to_cpu(nth16->wSequence)) &&
997 pr_debug("invalid DPT16 index\n"); 991 !((ctx->rx_seq == 0xffff) && !le16_to_cpu(nth16->wSequence))) {
992 pr_debug("sequence number glitch prev=%d curr=%d\n",
993 ctx->rx_seq, le16_to_cpu(nth16->wSequence));
994 }
995 ctx->rx_seq = le16_to_cpu(nth16->wSequence);
996
997 len = le16_to_cpu(nth16->wNdpIndex);
998 if ((len + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) {
999 pr_debug("invalid DPT16 index <%u>\n",
1000 le16_to_cpu(nth16->wNdpIndex));
998 goto error; 1001 goto error;
999 } 1002 }
1000 1003
1001 memcpy(&(ctx->rx_ncm.ndp16), ((u8 *)skb_in->data) + temp, 1004 ndp16 = (struct usb_cdc_ncm_ndp16 *)(((u8 *)skb_in->data) + len);
1002 sizeof(ctx->rx_ncm.ndp16));
1003 1005
1004 if (le32_to_cpu(ctx->rx_ncm.ndp16.dwSignature) != 1006 if (le32_to_cpu(ndp16->dwSignature) != USB_CDC_NCM_NDP16_NOCRC_SIGN) {
1005 USB_CDC_NCM_NDP16_NOCRC_SIGN) {
1006 pr_debug("invalid DPT16 signature <%u>\n", 1007 pr_debug("invalid DPT16 signature <%u>\n",
1007 le32_to_cpu(ctx->rx_ncm.ndp16.dwSignature)); 1008 le32_to_cpu(ndp16->dwSignature));
1008 goto error; 1009 goto error;
1009 } 1010 }
1010 1011
1011 if (le16_to_cpu(ctx->rx_ncm.ndp16.wLength) < 1012 if (le16_to_cpu(ndp16->wLength) < USB_CDC_NCM_NDP16_LENGTH_MIN) {
1012 USB_CDC_NCM_NDP16_LENGTH_MIN) {
1013 pr_debug("invalid DPT16 length <%u>\n", 1013 pr_debug("invalid DPT16 length <%u>\n",
1014 le32_to_cpu(ctx->rx_ncm.ndp16.dwSignature)); 1014 le32_to_cpu(ndp16->dwSignature));
1015 goto error; 1015 goto error;
1016 } 1016 }
1017 1017
1018 nframes = ((le16_to_cpu(ctx->rx_ncm.ndp16.wLength) - 1018 nframes = ((le16_to_cpu(ndp16->wLength) -
1019 sizeof(struct usb_cdc_ncm_ndp16)) / 1019 sizeof(struct usb_cdc_ncm_ndp16)) /
1020 sizeof(struct usb_cdc_ncm_dpe16)); 1020 sizeof(struct usb_cdc_ncm_dpe16));
1021 nframes--; /* we process NDP entries except for the last one */ 1021 nframes--; /* we process NDP entries except for the last one */
1022 1022
1023 pr_debug("nframes = %u\n", nframes); 1023 len += sizeof(struct usb_cdc_ncm_ndp16);
1024 1024
1025 temp += sizeof(ctx->rx_ncm.ndp16); 1025 if ((len + nframes * (sizeof(struct usb_cdc_ncm_dpe16))) >
1026 1026 skb_in->len) {
1027 if ((temp + nframes * (sizeof(struct usb_cdc_ncm_dpe16))) > actlen) {
1028 pr_debug("Invalid nframes = %d\n", nframes); 1027 pr_debug("Invalid nframes = %d\n", nframes);
1029 goto error; 1028 goto error;
1030 } 1029 }
1031 1030
1032 if (nframes > CDC_NCM_DPT_DATAGRAMS_MAX) { 1031 dpe16 = (struct usb_cdc_ncm_dpe16 *)(((u8 *)skb_in->data) + len);
1033 pr_debug("Truncating number of frames from %u to %u\n",
1034 nframes, CDC_NCM_DPT_DATAGRAMS_MAX);
1035 nframes = CDC_NCM_DPT_DATAGRAMS_MAX;
1036 }
1037
1038 memcpy(&(ctx->rx_ncm.dpe16), ((u8 *)skb_in->data) + temp,
1039 nframes * (sizeof(struct usb_cdc_ncm_dpe16)));
1040 1032
1041 for (x = 0; x < nframes; x++) { 1033 for (x = 0; x < nframes; x++, dpe16++) {
1042 offset = le16_to_cpu(ctx->rx_ncm.dpe16[x].wDatagramIndex); 1034 offset = le16_to_cpu(dpe16->wDatagramIndex);
1043 temp = le16_to_cpu(ctx->rx_ncm.dpe16[x].wDatagramLength); 1035 len = le16_to_cpu(dpe16->wDatagramLength);
1044 1036
1045 /* 1037 /*
1046 * CDC NCM ch. 3.7 1038 * CDC NCM ch. 3.7
1047 * All entries after first NULL entry are to be ignored 1039 * All entries after first NULL entry are to be ignored
1048 */ 1040 */
1049 if ((offset == 0) || (temp == 0)) { 1041 if ((offset == 0) || (len == 0)) {
1050 if (!x) 1042 if (!x)
1051 goto error; /* empty NTB */ 1043 goto error; /* empty NTB */
1052 break; 1044 break;
1053 } 1045 }
1054 1046
1055 /* sanity checking */ 1047 /* sanity checking */
1056 if (((offset + temp) > actlen) || 1048 if (((offset + len) > skb_in->len) ||
1057 (temp > CDC_NCM_MAX_DATAGRAM_SIZE) || (temp < ETH_HLEN)) { 1049 (len > ctx->rx_max) || (len < ETH_HLEN)) {
1058 pr_debug("invalid frame detected (ignored)" 1050 pr_debug("invalid frame detected (ignored)"
1059 "offset[%u]=%u, length=%u, skb=%p\n", 1051 "offset[%u]=%u, length=%u, skb=%p\n",
1060 x, offset, temp, skb_in); 1052 x, offset, len, skb_in);
1061 if (!x) 1053 if (!x)
1062 goto error; 1054 goto error;
1063 break; 1055 break;
@@ -1066,9 +1058,9 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
1066 skb = skb_clone(skb_in, GFP_ATOMIC); 1058 skb = skb_clone(skb_in, GFP_ATOMIC);
1067 if (!skb) 1059 if (!skb)
1068 goto error; 1060 goto error;
1069 skb->len = temp; 1061 skb->len = len;
1070 skb->data = ((u8 *)skb_in->data) + offset; 1062 skb->data = ((u8 *)skb_in->data) + offset;
1071 skb_set_tail_pointer(skb, temp); 1063 skb_set_tail_pointer(skb, len);
1072 usbnet_skb_return(dev, skb); 1064 usbnet_skb_return(dev, skb);
1073 } 1065 }
1074 } 1066 }