ath9k: range checking issues in htc_hst.c
PATCH 2/9 ath9k: range checking issues in htc_hst.c
The original code had ENDPOINT_MAX and HST_ENDPOINT_MAX switched.
Also the first loop was off by one, it started past the end of the array and went down to 1 instead of going down to 0. The test at the end of the loop to see if we exited via a break wasn't right because "tmp_endpoint" is always non-null here.
drivers/net/wireless/ath/ath9k/htc_hst.c +5 -5
@@ -116,7 +116,7 @@ static void htc_process_conn_rsp(struct htc_target *target, max_msglen =be16_to_cpu (svc_rspmsg->max_msg_len); endpoint = &target->endpoint[epid]; -for (tepid =ENDPOINT_MAX ; tepid >ENDPOINT0 ; tepid--) { +for (tepid =HST_ENDPOINT_MAX -1 ; tepid >=ENDPOINT0 ; tepid--) { tmp_endpoint = &target->endpoint[tepid];if (tmp_endpoint->service_id == service_id) { tmp_endpoint->service_id =0 ;
@@ -124,7 +124,7 @@ static void htc_process_conn_rsp(struct htc_target *target, } } -if (!tmp_endpoint) +if (tepid <ENDPOINT0 )return ; endpoint->service_id = service_id;
@@ -297,7 +297,7 @@ void htc_stop(struct htc_target *target)enum htc_endpoint_id epid;struct htc_endpoint *endpoint; -for (epid =ENDPOINT0 ; epid <=ENDPOINT_MAX ; epid++) { +for (epid =ENDPOINT0 ; epid <HST_ENDPOINT_MAX ; epid++) { endpoint = &target->endpoint[epid];if (endpoint->service_id !=0 ) target->hif->stop (target->hif_dev, endpoint->ul_pipeid);
@@ -309,7 +309,7 @@ void htc_start(struct htc_target *target)enum htc_endpoint_id epid;struct htc_endpoint *endpoint; -for (epid =ENDPOINT0 ; epid <=ENDPOINT_MAX ; epid++) { +for (epid =ENDPOINT0 ; epid <HST_ENDPOINT_MAX ; epid++) { endpoint = &target->endpoint[epid];if (endpoint->service_id !=0 ) target->hif->start(target->hif_dev,
@@ -377,7 +377,7 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle, htc_hdr = (struct htc_frame_hdr *) skb->data; epid = htc_hdr->endpoint_id; -if (epid >=ENDPOINT_MAX ) { +if (epid >=HST_ENDPOINT_MAX ) {if (pipe_id !=USB_REG_IN_PIPE )dev_kfree_skb_any (skb);else
PATCH 2/9 ath9k: range checking issues in htc_hst.c
Quoted 1 line · Dan Carpenter
The original code had
ENDPOINT_MAXandHST_ENDPOINT_MAXswitched.
Hm, no.
Quoted 12 lines
Also the first loop was off by one, it started past the end of the array and went down to 1 instead of going down to 0. The test at the end of the loop to see if we exited via a break wasn't right because "
tmp_endpoint" is always non-null here.Signed-off-by Dan Carpenter <[email protected]>drivers/net/wireless/ath/ath9k/htc_hst.c +0
-0
drivers/net/wireless/ath/ath9k/htc_hst.c static void htc_process_conn_rsp(struct htc_target *target, · line 119
Quoted 5 lines
drivers/net/wireless/ath/ath9k/htc_hst.c +1
-1@@ -116,7 +116,7 @@ static void htc_process_conn_rsp(struct htc_target *target, max_msglen =be16_to_cpu (svc_rspmsg->max_msg_len); endpoint = &target->endpoint[epid]; -for (tepid =ENDPOINT_MAX ; tepid >ENDPOINT0 ; tepid--) { +for (tepid =HST_ENDPOINT_MAX -1 ; tepid >=ENDPOINT0 ; tepid--) {
This should be (tepid = (ENDPOINT_MAX - 1); tepid > ENDPOINT0; tepid--), and the NULL check below can be retained.
This is because ENDPOINT0 is reserved.
Quoted 13 lines
drivers/net/wireless/ath/ath9k/htc_hst.c +1
-1tmp_endpoint = &target->endpoint[tepid];if (tmp_endpoint->service_id == service_id) { tmp_endpoint->service_id =0 ;@@ -124,7 +124,7 @@ static void htc_process_conn_rsp(struct htc_target *target, } } -if (!tmp_endpoint) +if (tepid <ENDPOINT0 )return ; endpoint->service_id = service_id;
drivers/net/wireless/ath/ath9k/htc_hst.c void htc_stop(struct htc_target *target) · line 300
Quoted 5 lines
drivers/net/wireless/ath/ath9k/htc_hst.c +1
-1@@ -297,7 +297,7 @@ void htc_stop(struct htc_target *target)enum htc_endpoint_id epid;struct htc_endpoint *endpoint; -for (epid =ENDPOINT0 ; epid <=ENDPOINT_MAX ; epid++) { +for (epid =ENDPOINT0 ; epid <HST_ENDPOINT_MAX ; epid++) {
ENDPOINT_MAX should be used here, but '<=' should be replaced by '<'.
drivers/net/wireless/ath/ath9k/htc_hst.c void htc_start(struct htc_target *target) · line 313
Quoted 10 lines
drivers/net/wireless/ath/ath9k/htc_hst.c +1
-1endpoint = &target->endpoint[epid];if (endpoint->service_id !=0 ) target->hif->stop (target->hif_dev, endpoint->ul_pipeid);@@ -309,7 +309,7 @@ void htc_start(struct htc_target *target)enum htc_endpoint_id epid;struct htc_endpoint *endpoint; -for (epid =ENDPOINT0 ; epid <=ENDPOINT_MAX ; epid++) { +for (epid =ENDPOINT0 ; epid <HST_ENDPOINT_MAX ; epid++) { endpoint = &target->endpoint[epid];
Same as above.
drivers/net/wireless/ath/ath9k/htc_hst.c void ath9k_htc_rx_msg(struct htc_target *htc_handle, · line 383
Quoted 11 lines
drivers/net/wireless/ath/ath9k/htc_hst.c +1
-1if (endpoint->service_id !=0 ) target->hif->start(target->hif_dev,@@ -377,7 +377,7 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle, htc_hdr = (struct htc_frame_hdr *) skb->data; epid = htc_hdr->endpoint_id; -if (epid >=ENDPOINT_MAX ) { +if (epid >=HST_ENDPOINT_MAX ) {if (pipe_id !=USB_REG_IN_PIPE )dev_kfree_skb_any (skb);else
The original check was correct ...
Sujith
PATCH 2/9 ath9k: range checking issues in htc_hst.c
Quoted 5 lines · Sujith
Quoted 1 line · Dan Carpenter
The original code had
ENDPOINT_MAXandHST_ENDPOINT_MAXswitched.Hm, no.
I'm afraid I don't understand. ENDPOINT_MAX is 22 and HST_ENDPOINT_MAX is 8. The htc_target struct is defined as having 8 endpoints.
drivers/net/wireless/ath/ath9k/htc_hst.h
137 struct htc_target {
138 void *hif_dev;
139 struct ath9k_htc_priv *drv_priv;
140 struct device *dev;
141 struct ath9k_htc_hif *hif;
142 struct htc_endpoint endpoint[HST_ENDPOINT_MAX];
^^^^^^^^^^^^^^^^^^^^^^^^^^^So in the original code:drivers/net/wireless/ath/ath9k/htc_hst.c
119 for (tepid = ENDPOINT_MAX; tepid > ENDPOINT0; tepid--) {
120 tmp_endpoint = &target->endpoint[tepid];
^^^^^^^^^^^^^^^^^^^^^^^^^
We are past the end of the array here. 22 vs 7.
Perhaps the htc_target struct should be changed to ENDPOINT_MAX?
regards,
dan carpenter
PATCH 2/9 ath9k: range checking issues in htc_hst.c
Quoted 14 lines · Dan Carpenter
I'm afraid I don't understand.
ENDPOINT_MAXis 22 andHST_ENDPOINT_MAXis 8. Thehtc_targetstruct is defined as having 8 endpoints.
drivers/net/wireless/ath/ath9k/htc_hst.h137 struct htc_target { 138 void *hif_dev; 139 struct ath9k_htc_priv *drv_priv; 140 struct device *dev; 141 struct ath9k_htc_hif *hif; 142 struct htc_endpoint endpoint[HST_ENDPOINT_MAX]; ^^^^^^^^^^^^^^^^^^^^^^^^^^^So in the original code:
drivers/net/wireless/ath/ath9k/htc_hst.c
Quoted 7 lines
119 for (tepid = ENDPOINT_MAX; tepid > ENDPOINT0; tepid--) { 120 tmp_endpoint = &target->endpoint[tepid]; ^^^^^^^^^^^^^^^^^^^^^^^^^ We are past the end of the array here. 22 vs 7.Perhaps the
htc_targetstruct should be changed toENDPOINT_MAX?
Ah right. That should be fixed.
Sujith
PATCH 2/9 ath9k: range checking issues in htc_hst.c
Quoted 1 line · Sujith
Ah right. That should be fixed.
I suggest using ARRAY_SIZE(target->endpoint) to be sure.
Signature · 2 lines
Regards, Pavel Roskin
PATCH 2/9 ath9k: range checking issues in htc_hst.c
In reply to Dan CarpenterQuoted 6 lines · Dan Carpenter
The original code had
ENDPOINT_MAXandHST_ENDPOINT_MAXswitched.Also the first loop was off by one, it started past the end of the array and went down to 1 instead of going down to 0. The test at the end of the loop to see if we exited via a break wasn't right because "
tmp_endpoint" is always non-null here.
This is a very good catch and fixes a stack corruption issue. Do you mind if I work upon this patch and send out an updated fix ?
Sujith
PATCH 2/9 ath9k: range checking issues in htc_hst.c
Quoted 8 lines · Sujith.Manoharan at atheros.com
Quoted 6 lines · Dan Carpenter
The original code had
ENDPOINT_MAXandHST_ENDPOINT_MAXswitched.Also the first loop was off by one, it started past the end of the array and went down to 1 instead of going down to 0. The test at the end of the loop to see if we exited via a break wasn't right because "
tmp_endpoint" is always non-null here.
Quoted 4 lines
This is a very good catch and fixes a stack corruption issue. Do you mind if I work upon this patch and send out an updated fix ?
Sujith
Sorry, I meant to do that yesterday but I was out of it. Yes. Please send the updated fix.
regards,
dan carpenter