2012-01-12 06:47:35

by Dan Carpenter

[permalink] [raw]
Subject: [patch] svcrdma: endian bug in send_write_chunks()

Sparse complains because arg_ch->rs_length is declared as network
endian but we're treating it as CPU endian.

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

diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
index 249a835..30fda86 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
@@ -409,7 +409,7 @@ static int send_write_chunks(struct svcxprt_rdma *xprt,
u64 rs_offset;

arg_ch = &arg_ary->wc_array[chunk_no].wc_target;
- write_len = min(xfer_len, arg_ch->rs_length);
+ write_len = min(xfer_len, ntohl(arg_ch->rs_length));

/* Prepare the response chunk given the length actually
* written */
@@ -481,7 +481,7 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt,
chunk_no++) {
u64 rs_offset;
ch = &arg_ary->wc_array[chunk_no].wc_target;
- write_len = min(xfer_len, ch->rs_length);
+ write_len = min(xfer_len, ntohl(ch->rs_length));

/* Prepare the reply chunk given the length actually
* written */


2012-01-12 19:37:30

by Tom Tucker

[permalink] [raw]
Subject: Re: [patch] svcrdma: endian bug in send_write_chunks()

On 1/12/12 1:28 PM, Trond Myklebust wrote:
> On Thu, 2012-01-12 at 13:24 -0600, Tom Tucker wrote:
>> On 1/12/12 1:15 PM, Trond Myklebust wrote:
>>> On Thu, 2012-01-12 at 11:21 -0500, J. Bruce Fields wrote:
>>>> On Thu, Jan 12, 2012 at 09:47:22AM +0300, Dan Carpenter wrote:
>>>>> Sparse complains because arg_ch->rs_length is declared as network
>>>>> endian but we're treating it as CPU endian.
>>>> This looks like it would actually change behavior on a little endian
>>>> architecture, so how did this work before?
>>>>
>>>>> From some quick grepping, I see assignments both of the form
>>>> ...rs_length = ntohl(...)
>>>>
>>>> and
>>>>
>>>> ...rs_length = htonl(...)
>>>>
>>>> but only see one declaration for a field named rs_length.
>>>>
>>>> So my best guess would be that the code is ugly but working as is, and
>>>> needs cleanup by someone who knows how this field was intended to be
>>>> used.
>>> It looks to me as if rs_handle and rs_offset are being similarly abused.
>>> Basically, we need a serious clean up in svc_rdma_marshall.c to separate
>>> out those variables that are in XDR-encoded form and those that are not.
>>>
>> The abuse is taking place because the marshal/unmarshall is being done
>> in-place and it seemed wasteful at the time to add a chunk of memory to
>> preserve the aesthetic. A union would 'work', but you still wouldn't
>> 'know' whether the data was NBO or not by where it was -- which seems like
>> the intent of the __beXX in the first place.
> These are not variables that are used in hundreds of different places:
> why not just do the conversion from big-endian to cpu-endian when you
> actually need to use them?

That would work fine actually. At the time, I was trying to put all that
marshalling logic in that one file and reuse the already present
client-side header file that copies that stuff when it decodes it.

I'll dig around a little bit and see what might be the simplest way to
clean this up.

Tom



2012-01-12 16:21:46

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [patch] svcrdma: endian bug in send_write_chunks()

On Thu, Jan 12, 2012 at 09:47:22AM +0300, Dan Carpenter wrote:
> Sparse complains because arg_ch->rs_length is declared as network
> endian but we're treating it as CPU endian.

This looks like it would actually change behavior on a little endian
architecture, so how did this work before?

>From some quick grepping, I see assignments both of the form

...rs_length = ntohl(...)

and

...rs_length = htonl(...)

but only see one declaration for a field named rs_length.

So my best guess would be that the code is ugly but working as is, and
needs cleanup by someone who knows how this field was intended to be
used.

?

--b.

>
> Signed-off-by: Dan Carpenter <[email protected]>
>
> diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
> index 249a835..30fda86 100644
> --- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c
> +++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
> @@ -409,7 +409,7 @@ static int send_write_chunks(struct svcxprt_rdma *xprt,
> u64 rs_offset;
>
> arg_ch = &arg_ary->wc_array[chunk_no].wc_target;
> - write_len = min(xfer_len, arg_ch->rs_length);
> + write_len = min(xfer_len, ntohl(arg_ch->rs_length));
>
> /* Prepare the response chunk given the length actually
> * written */
> @@ -481,7 +481,7 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt,
> chunk_no++) {
> u64 rs_offset;
> ch = &arg_ary->wc_array[chunk_no].wc_target;
> - write_len = min(xfer_len, ch->rs_length);
> + write_len = min(xfer_len, ntohl(ch->rs_length));
>
> /* Prepare the reply chunk given the length actually
> * written */

2012-01-12 19:28:27

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [patch] svcrdma: endian bug in send_write_chunks()

On Thu, Jan 12, 2012 at 02:15:59PM -0500, Trond Myklebust wrote:
> On Thu, 2012-01-12 at 11:21 -0500, J. Bruce Fields wrote:
> > On Thu, Jan 12, 2012 at 09:47:22AM +0300, Dan Carpenter wrote:
> > > Sparse complains because arg_ch->rs_length is declared as network
> > > endian but we're treating it as CPU endian.
> >
> > This looks like it would actually change behavior on a little endian
> > architecture, so how did this work before?
> >
> > >From some quick grepping, I see assignments both of the form
> >
> > ...rs_length = ntohl(...)
> >
> > and
> >
> > ...rs_length = htonl(...)
> >
> > but only see one declaration for a field named rs_length.
> >
> > So my best guess would be that the code is ugly but working as is, and
> > needs cleanup by someone who knows how this field was intended to be
> > used.
>
> It looks to me as if rs_handle and rs_offset are being similarly abused.
> Basically, we need a serious clean up in svc_rdma_marshall.c to separate
> out those variables that are in XDR-encoded form and those that are not.

(Here everybody takes one step back and pretends to be engrossed in some
other thread.)

--b.

2012-01-12 21:31:13

by Dan Carpenter

[permalink] [raw]
Subject: Re: [patch] svcrdma: endian bug in send_write_chunks()

On Thu, Jan 12, 2012 at 11:21:41AM -0500, J. Bruce Fields wrote:
> On Thu, Jan 12, 2012 at 09:47:22AM +0300, Dan Carpenter wrote:
> > Sparse complains because arg_ch->rs_length is declared as network
> > endian but we're treating it as CPU endian.
>
> This looks like it would actually change behavior on a little endian
> architecture, so how did this work before?
>
> >From some quick grepping, I see assignments both of the form
>
> ...rs_length = ntohl(...)
>
> and
>
> ...rs_length = htonl(...)
>
> but only see one declaration for a field named rs_length.
>
> So my best guess would be that the code is ugly but working as is, and
> needs cleanup by someone who knows how this field was intended to be
> used.

Gar. Sorry for that. I knew it changed the behavior, and I tried
to see how the original code worked, but I didn't read carefully
enough. I'll try be more careful next time.

Thanks for catching that.

regards,
dan carpenter


Attachments:
(No filename) (955.00 B)
signature.asc (836.00 B)
Digital signature
Download all attachments

2012-01-12 19:24:49

by Tom Tucker

[permalink] [raw]
Subject: Re: [patch] svcrdma: endian bug in send_write_chunks()

On 1/12/12 1:15 PM, Trond Myklebust wrote:
> On Thu, 2012-01-12 at 11:21 -0500, J. Bruce Fields wrote:
>> On Thu, Jan 12, 2012 at 09:47:22AM +0300, Dan Carpenter wrote:
>>> Sparse complains because arg_ch->rs_length is declared as network
>>> endian but we're treating it as CPU endian.
>> This looks like it would actually change behavior on a little endian
>> architecture, so how did this work before?
>>
>> > From some quick grepping, I see assignments both of the form
>>
>> ...rs_length = ntohl(...)
>>
>> and
>>
>> ...rs_length = htonl(...)
>>
>> but only see one declaration for a field named rs_length.
>>
>> So my best guess would be that the code is ugly but working as is, and
>> needs cleanup by someone who knows how this field was intended to be
>> used.
> It looks to me as if rs_handle and rs_offset are being similarly abused.
> Basically, we need a serious clean up in svc_rdma_marshall.c to separate
> out those variables that are in XDR-encoded form and those that are not.
>
The abuse is taking place because the marshal/unmarshall is being done
in-place and it seemed wasteful at the time to add a chunk of memory to
preserve the aesthetic. A union would 'work', but you still wouldn't
'know' whether the data was NBO or not by where it was -- which seems like
the intent of the __beXX in the first place.

Tom


2012-01-12 19:16:03

by Myklebust, Trond

[permalink] [raw]
Subject: Re: [patch] svcrdma: endian bug in send_write_chunks()

On Thu, 2012-01-12 at 11:21 -0500, J. Bruce Fields wrote:
> On Thu, Jan 12, 2012 at 09:47:22AM +0300, Dan Carpenter wrote:
> > Sparse complains because arg_ch->rs_length is declared as network
> > endian but we're treating it as CPU endian.
>
> This looks like it would actually change behavior on a little endian
> architecture, so how did this work before?
>
> >From some quick grepping, I see assignments both of the form
>
> ...rs_length = ntohl(...)
>
> and
>
> ...rs_length = htonl(...)
>
> but only see one declaration for a field named rs_length.
>
> So my best guess would be that the code is ugly but working as is, and
> needs cleanup by someone who knows how this field was intended to be
> used.

It looks to me as if rs_handle and rs_offset are being similarly abused.
Basically, we need a serious clean up in svc_rdma_marshall.c to separate
out those variables that are in XDR-encoded form and those that are not.

--
Trond Myklebust
Linux NFS client maintainer

NetApp
[email protected]
http://www.netapp.com


2012-01-12 19:28:32

by Myklebust, Trond

[permalink] [raw]
Subject: Re: [patch] svcrdma: endian bug in send_write_chunks()

On Thu, 2012-01-12 at 13:24 -0600, Tom Tucker wrote:
> On 1/12/12 1:15 PM, Trond Myklebust wrote:
> > On Thu, 2012-01-12 at 11:21 -0500, J. Bruce Fields wrote:
> >> On Thu, Jan 12, 2012 at 09:47:22AM +0300, Dan Carpenter wrote:
> >>> Sparse complains because arg_ch->rs_length is declared as network
> >>> endian but we're treating it as CPU endian.
> >> This looks like it would actually change behavior on a little endian
> >> architecture, so how did this work before?
> >>
> >> > From some quick grepping, I see assignments both of the form
> >>
> >> ...rs_length = ntohl(...)
> >>
> >> and
> >>
> >> ...rs_length = htonl(...)
> >>
> >> but only see one declaration for a field named rs_length.
> >>
> >> So my best guess would be that the code is ugly but working as is, and
> >> needs cleanup by someone who knows how this field was intended to be
> >> used.
> > It looks to me as if rs_handle and rs_offset are being similarly abused.
> > Basically, we need a serious clean up in svc_rdma_marshall.c to separate
> > out those variables that are in XDR-encoded form and those that are not.
> >
> The abuse is taking place because the marshal/unmarshall is being done
> in-place and it seemed wasteful at the time to add a chunk of memory to
> preserve the aesthetic. A union would 'work', but you still wouldn't
> 'know' whether the data was NBO or not by where it was -- which seems like
> the intent of the __beXX in the first place.

These are not variables that are used in hundreds of different places:
why not just do the conversion from big-endian to cpu-endian when you
actually need to use them?

--
Trond Myklebust
Linux NFS client maintainer

NetApp
[email protected]
http://www.netapp.com