netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [benet] possible endianness bug in be_cmd_txq_create()
@ 2017-12-10 16:41 Al Viro
  2017-12-10 18:43 ` Al Viro
  2018-01-29  7:33 ` Sathya Perla
  0 siblings, 2 replies; 4+ messages in thread
From: Al Viro @ 2017-12-10 16:41 UTC (permalink / raw)
  To: netdev; +Cc: Vasundhara Volam, Sathya Perla

In be_cmd_txq_create() we have
        if (req->hdr.version > 0)
                req->if_id = cpu_to_le16(adapter->if_handle);
        req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
        req->ulp_num = BE_ULP1_NUM;
        req->type = BE_ETH_TX_RING_TYPE_STANDARD;
        req->cq_id = cpu_to_le16(cq->id);
        req->queue_size = be_encoded_q_len(txq->len);
        be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
        ver = req->hdr.version;

req points to 

struct be_cmd_req_eth_tx_create {
        struct be_cmd_req_hdr hdr;
        u8 num_pages;
        u8 ulp_num;
        u16 type;
        u16 if_id;
        u8 queue_size;
        u8 rsvd0;
        u32 rsvd1;
        u16 cq_id;
        u16 rsvd2;
        u32 rsvd3[13];
        struct phys_addr pages[8];
} __packed;

Everything appears to be consistent with little-endian data - direct
assignments to u8 fields, cpu_to_le16 for cq_id and if_id, phys_addr
array is also filled with little-endian data, so's ->hdr (several
lines prior, by be_wrb_cmd_hdr_prepare()).

The only exception is
        req->type = BE_ETH_TX_RING_TYPE_STANDARD;
where we set a 16bit field with host-endian constant (2).

benet is playing silly buggers with swap-in-place in some places, but
it's always 32bit values getting swapped, so this can't be happening
here (num_pages, ulp_num and type form a 32bit-aligned word, and
on big-endian cpu_to_le32() done to it would've ended up with num_pages = 2,
ulp_num = 0, type = 256 + PAGES_4K_SPANNED(q_mem->va, q_mem->size), which is
unlikely to do anything good).

So it really smells like this line should've been
        req->type = cpu_to_le16(BE_ETH_TX_RING_TYPE_STANDARD);

I don't have the hardware, so the above is completely untested (caught by
sparse when trying to do endianness annotations in drivers/net), but it
does look like it might be worth a look from benet maintainers.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [benet] possible endianness bug in be_cmd_txq_create()
  2017-12-10 16:41 [benet] possible endianness bug in be_cmd_txq_create() Al Viro
@ 2017-12-10 18:43 ` Al Viro
  2017-12-10 20:17   ` Al Viro
  2018-01-29  7:33 ` Sathya Perla
  1 sibling, 1 reply; 4+ messages in thread
From: Al Viro @ 2017-12-10 18:43 UTC (permalink / raw)
  To: netdev; +Cc: Sathya Perla

On Sun, Dec 10, 2017 at 04:41:20PM +0000, Al Viro wrote:

> I don't have the hardware, so the above is completely untested (caught by
> sparse when trying to do endianness annotations in drivers/net), but it
> does look like it might be worth a look from benet maintainers.

Another very fishy place is be_roce_mcc_cmd().

        req = embedded_payload(wrb);
        resp = embedded_payload(wrb);

        be_wrb_cmd_hdr_prepare(req, hdr->subsystem,
                               hdr->opcode, wrb_payload_size, wrb, NULL);

OK, we'd formed a (little-endian) header in the first 32 bytes of req and
filled wrb->{tag0,tag1,payload_length,embedded}.

        memcpy(req, wrb_payload, wrb_payload_size);
        be_dws_cpu_to_le(req, wrb_payload_size);

... only to overwrite *req with wrb_payload bulk-converted to little-endian.
OK, so it's responsibility of caller to have prepare payload so that it
would form a valid header after byteswap.

        status = be_mcc_notify_wait(adapter);
        if (cmd_status)
                *cmd_status = (status & 0xffff);
        if (ext_status)
                *ext_status = 0;

OK, we submit the resulting wrb and wait for reply.

        memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length);
        be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length);

Then we copy the response back into caller-supplied buffer, bulk-converting
it from little-endian to host-endian.  Hardware puts little-endian there,
caller wants host-endian.  But... ->response_length is a 32bit value at
offset 8 from the beginning of response.  Is it little-endian or host-endian?
In the former case we are fucked on b-e host - the value we pass to memcpy()
is going to be in hundreds of megabytes...  And everything in response seems
to be little-endian - we certainly include response_length itself into the
area covered by that bulk byteswap.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [benet] possible endianness bug in be_cmd_txq_create()
  2017-12-10 18:43 ` Al Viro
@ 2017-12-10 20:17   ` Al Viro
  0 siblings, 0 replies; 4+ messages in thread
From: Al Viro @ 2017-12-10 20:17 UTC (permalink / raw)
  To: netdev; +Cc: Sathya Perla

On Sun, Dec 10, 2017 at 06:43:08PM +0000, Al Viro wrote:
> On Sun, Dec 10, 2017 at 04:41:20PM +0000, Al Viro wrote:
> 
> > I don't have the hardware, so the above is completely untested (caught by
> > sparse when trying to do endianness annotations in drivers/net), but it
> > does look like it might be worth a look from benet maintainers.
> 
> Another very fishy place is be_roce_mcc_cmd().

be_get_fw_log_level()/be_set_fw_log_level() look slightly fishy as well:
the latter has
                        if (cfgs->module[i].trace_lvl[j].mode == MODE_UART)
                                cfgs->module[i].trace_lvl[j].dbg_lvl =
                                                        cpu_to_le32(level);
while the former
                        if (cfgs->module[0].trace_lvl[j].mode == MODE_UART)
                                level = cfgs->module[0].trace_lvl[j].dbg_lvl;
and returns level without further conversions.  The caller of be_cmd_set_...()
pass a host-endian value as level (48 or 64); the caller of be_cmd_get_...()
expect a host-endian return value - it compares the result with 48.

There's almost certainly a missing conversion somewhere; at a guess -
le32_to_cpu() on the be_cmd_get_...() side.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [benet] possible endianness bug in be_cmd_txq_create()
  2017-12-10 16:41 [benet] possible endianness bug in be_cmd_txq_create() Al Viro
  2017-12-10 18:43 ` Al Viro
@ 2018-01-29  7:33 ` Sathya Perla
  1 sibling, 0 replies; 4+ messages in thread
From: Sathya Perla @ 2018-01-29  7:33 UTC (permalink / raw)
  To: Al Viro
  Cc: Netdev, Vasundhara Volam, Sathya Perla,
	Suresh Kumar Reddy Reddygari

On Sun, Dec 10, 2017 at 10:11 PM, Al Viro <viro@zeniv.linux.org.uk> wrote:
>
> In be_cmd_txq_create() we have
>         if (req->hdr.version > 0)
>                 req->if_id = cpu_to_le16(adapter->if_handle);
>         req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
>         req->ulp_num = BE_ULP1_NUM;
>         req->type = BE_ETH_TX_RING_TYPE_STANDARD;
>         req->cq_id = cpu_to_le16(cq->id);
>         req->queue_size = be_encoded_q_len(txq->len);
>         be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
>         ver = req->hdr.version;
>
...
>
> Everything appears to be consistent with little-endian data - direct
> assignments to u8 fields, cpu_to_le16 for cq_id and if_id, phys_addr
> array is also filled with little-endian data, so's ->hdr (several
> lines prior, by be_wrb_cmd_hdr_prepare()).
>
> The only exception is
>         req->type = BE_ETH_TX_RING_TYPE_STANDARD;
> where we set a 16bit field with host-endian constant (2).
>
..
>
> So it really smells like this line should've been
>         req->type = cpu_to_le16(BE_ETH_TX_RING_TYPE_STANDARD);
>
Sorry for replying late...I missed this mail. I guess the old
@emulex.com email ids don't work anymore -- it's @broadcom.com now!
Yes, this does look like a bug; we'll send a patch to fix this.

Thanks!

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-01-29  7:33 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-12-10 16:41 [benet] possible endianness bug in be_cmd_txq_create() Al Viro
2017-12-10 18:43 ` Al Viro
2017-12-10 20:17   ` Al Viro
2018-01-29  7:33 ` Sathya Perla

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).