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.