From mboxrd@z Thu Jan 1 00:00:00 1970 From: Al Viro Subject: Re: [benet] possible endianness bug in be_cmd_txq_create() Date: Sun, 10 Dec 2017 18:43:08 +0000 Message-ID: <20171210184307.GT21978@ZenIV.linux.org.uk> References: <20171210164120.GS21978@ZenIV.linux.org.uk> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Cc: Sathya Perla To: netdev@vger.kernel.org Return-path: Received: from zeniv.linux.org.uk ([195.92.253.2]:50456 "EHLO ZenIV.linux.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752291AbdLJSnJ (ORCPT ); Sun, 10 Dec 2017 13:43:09 -0500 Content-Disposition: inline In-Reply-To: <20171210164120.GS21978@ZenIV.linux.org.uk> Sender: netdev-owner@vger.kernel.org List-ID: 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.