From patchwork Fri May 22 14:00:50 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Sakamoto X-Patchwork-Id: 6464771 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id A90BAC0020 for ; Fri, 22 May 2015 14:04:01 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BF7FD20483 for ; Fri, 22 May 2015 14:04:00 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 5CDAF20425 for ; Fri, 22 May 2015 14:03:59 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 87993265DF5; Fri, 22 May 2015 16:03:56 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id A9FF2265DF6; Fri, 22 May 2015 16:01:30 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 476A8265DB1; Fri, 22 May 2015 16:01:27 +0200 (CEST) Received: from smtp302.phy.lolipop.jp (smtp302.phy.lolipop.jp [210.157.22.85]) by alsa0.perex.cz (Postfix) with ESMTP id BA50D265D93 for ; Fri, 22 May 2015 16:01:06 +0200 (CEST) Received: from smtp302.phy.lolipop.lan (HELO smtp302.phy.lolipop.jp) (172.17.1.85) (smtp-auth username m12129643-o-takashi, mechanism plain) by smtp302.phy.lolipop.jp (qpsmtpd/0.82) with ESMTPA; Fri, 22 May 2015 23:01:00 +0900 Received: from 127.0.0.1 (127.0.0.1) by smtp302.phy.lolipop.jp (LOLIPOP-Fsecure); Fri, 22 May 2015 23:00:54 +0900 (JST) X-Virus-Status: clean(LOLIPOP-Fsecure) From: Takashi Sakamoto To: clemens@ladisch.de, tiwai@suse.de Date: Fri, 22 May 2015 23:00:50 +0900 Message-Id: <1432303254-4192-2-git-send-email-o-takashi@sakamocchi.jp> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1432303254-4192-1-git-send-email-o-takashi@sakamocchi.jp> References: <1432303254-4192-1-git-send-email-o-takashi@sakamocchi.jp> Cc: alsa-devel@alsa-project.org, linux1394-devel@lists.sourceforge.net, ffado-devel@lists.sf.net Subject: [alsa-devel] [PATCH 1/5] ALSA: firewire-lib: add buffer-over-run protection at receiving more data blocks than expected X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP In IEC 61883-6, the number of data blocks in a packet is limited up to the value of SYT_INTERVAL. Current implementation is compliant to the limitation, while it can cause buffer-over-run when the value of dbs field in received packet is illegally large. This commit adds a validator to detect such illegal packets to prevent the buffer-over-run. Actually, the buffer is aligned to the size of memory page, thus this issue hardly causes system errors due to the room to page alignment, as long as a few packets includes such jumbo payload; i.e. a packet to several received packets. Here, Behringer F-Control Audio 202 (based on OXFW 960) has a quirk to postpone transferring isochronous packet till finish handling any asynchronous packets. In this case, this model is lazy, transfers no packets according to several cycle-start packets. After finishing, this model pushes required data in next isochronous packet. As a result, the packet include more data blocks than IEC 61883-6 defines. To continue to support this model, this commit adds a new flag to extend the length of calculated payload. This flag allows the size of payload 5 times as large as IEC 61883-6 defines. As a result, packets from this model passed the validator successfully. Signed-off-by: Takashi Sakamoto --- sound/firewire/amdtp.c | 21 +++++++++++++++++++-- sound/firewire/amdtp.h | 4 ++++ sound/firewire/oxfw/oxfw-stream.c | 10 ++++++++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c index d882ca5..4eb8dc9 100644 --- a/sound/firewire/amdtp.c +++ b/sound/firewire/amdtp.c @@ -255,7 +255,12 @@ EXPORT_SYMBOL(amdtp_stream_set_parameters); */ unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s) { - return 8 + s->syt_interval * s->data_block_quadlets * 4; + unsigned int multiplier = 1; + + if (s->flags & CIP_JUMBO_PAYLOAD) + multiplier = 5; + + return 8 + s->syt_interval * s->data_block_quadlets * 4 * multiplier; } EXPORT_SYMBOL(amdtp_stream_get_max_payload); @@ -811,12 +816,16 @@ static void in_stream_callback(struct fw_iso_context *context, u32 cycle, void *private_data) { struct amdtp_stream *s = private_data; - unsigned int p, syt, packets, payload_quadlets; + unsigned int p, syt, packets; + unsigned int payload_quadlets, max_payload_quadlets; __be32 *buffer, *headers = header; /* The number of packets in buffer */ packets = header_length / IN_PACKET_HEADER_SIZE; + /* For buffer-over-run prevention. */ + max_payload_quadlets = amdtp_stream_get_max_payload(s) / 4; + for (p = 0; p < packets; p++) { if (s->packet_index < 0) break; @@ -832,6 +841,14 @@ static void in_stream_callback(struct fw_iso_context *context, u32 cycle, /* The number of quadlets in this packet */ payload_quadlets = (be32_to_cpu(headers[p]) >> ISO_DATA_LENGTH_SHIFT) / 4; + if (payload_quadlets > max_payload_quadlets) { + dev_err(&s->unit->device, + "Detect jumbo payload: %02x %02x\n", + payload_quadlets, max_payload_quadlets); + s->packet_index = -1; + break; + } + handle_in_packet(s, payload_quadlets, buffer); } diff --git a/sound/firewire/amdtp.h b/sound/firewire/amdtp.h index 8a03a91..26b9093 100644 --- a/sound/firewire/amdtp.h +++ b/sound/firewire/amdtp.h @@ -29,6 +29,9 @@ * packet is not continuous from an initial value. * @CIP_EMPTY_HAS_WRONG_DBC: Only for in-stream. The value of dbc in empty * packet is wrong but the others are correct. + * @CIP_JUMBO_PAYLOAD: Only for in-stream. The number of data blocks in an + * packet is larger than IEC 61883-6 defines. Current implementation + * allows 5 times as large as IEC 61883-6 defines. */ enum cip_flags { CIP_NONBLOCKING = 0x00, @@ -40,6 +43,7 @@ enum cip_flags { CIP_SKIP_DBC_ZERO_CHECK = 0x20, CIP_SKIP_INIT_DBC_CHECK = 0x40, CIP_EMPTY_HAS_WRONG_DBC = 0x80, + CIP_JUMBO_PAYLOAD = 0x100, }; /** diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index e6757cd..873d40f 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -232,9 +232,15 @@ int snd_oxfw_stream_init_simplex(struct snd_oxfw *oxfw, goto end; } - /* OXFW starts to transmit packets with non-zero dbc. */ + /* + * OXFW starts to transmit packets with non-zero dbc. + * OXFW postpone transferring packets till handling any asynchronous + * packets. As a result, next isochronous packet includes more data + * blocks than IEC 61883-6 defines. + */ if (stream == &oxfw->tx_stream) - oxfw->tx_stream.flags |= CIP_SKIP_INIT_DBC_CHECK; + oxfw->tx_stream.flags |= CIP_SKIP_INIT_DBC_CHECK | + CIP_JUMBO_PAYLOAD; end: return err; }