2010-05-08 16:22:27

by Dan Carpenter

[permalink] [raw]
Subject: [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.

Signed-off-by: Dan Carpenter <[email protected]>

diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
index 7bf6ce1..0c062d0 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
@@ -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


2010-05-10 04:36:57

by Sujith

[permalink] [raw]
Subject: [patch 2/9] ath9k: range checking issues in htc_hst.c

Dan Carpenter wrote:
> The original code had ENDPOINT_MAX and HST_ENDPOINT_MAX switched.

Hm, no.

> 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]>
>
> diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
> index 7bf6ce1..0c062d0 100644
> --- a/drivers/net/wireless/ath/ath9k/htc_hst.c
> +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
> @@ -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.

> 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_MAX should be used here, but '<=' should be replaced by '<'.

> 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];

Same as above.

> 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

The original check was correct ...

Sujith

2010-05-11 05:49:44

by Sujith

[permalink] [raw]
Subject: [patch 2/9] ath9k: range checking issues in htc_hst.c

Dan Carpenter wrote:
> 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.

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

2010-05-10 10:50:25

by Sujith

[permalink] [raw]
Subject: Re: [patch 2/9] ath9k: range checking issues in htc_hst.c

Dan Carpenter wrote:
> 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?

Ah right. That should be fixed.

Sujith

2010-05-10 12:17:32

by Pavel Roskin

[permalink] [raw]
Subject: Re: [ath9k-devel] [patch 2/9] ath9k: range checking issues in htc_hst.c

On Mon, 2010-05-10 at 16:20 +0530, Sujith wrote:

> Ah right. That should be fixed.

I suggest using ARRAY_SIZE(target->endpoint) to be sure.

--
Regards,
Pavel Roskin

2010-05-10 10:24:25

by Dan Carpenter

[permalink] [raw]
Subject: Re: [patch 2/9] ath9k: range checking issues in htc_hst.c


On Mon, May 10, 2010 at 10:07:12AM +0530, Sujith wrote:
> Dan Carpenter wrote:
> > The original code had ENDPOINT_MAX and HST_ENDPOINT_MAX switched.
>
> 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

2010-05-11 09:30:29

by Dan Carpenter

[permalink] [raw]
Subject: Re: [patch 2/9] ath9k: range checking issues in htc_hst.c

On Tue, May 11, 2010 at 11:20:02AM +0530, [email protected] wrote:
> Dan Carpenter wrote:
> > 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.
>
> 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