From nobody Sat Jul 25 18:08:07 2026 Received: from cstnet.cn (smtp25.cstnet.cn [159.226.251.25]) (using TLSv1.2 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 82EDE30AAA9; Wed, 15 Jul 2026 08:40:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=159.226.251.25 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784104850; cv=none; b=UQ1D1nOvjyN3kvZZcNKkOPyd1L0m1WWBT9VXVAKDcgsOTCVch7HJ/qu+tOQ+v3t5HO1B/3DgegFmc07tSQamDntYECiiTJqUctIi/dIbOpyrMdDoz2ic4zhX1KY6D3MDq5fcp8+8a03QyHk6ctGUs/cdbLzBZjo7KKiIK0leZgg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784104850; c=relaxed/simple; bh=BKJzznLYfhTchyxf63FxU2j+0aAzXY0+Ug9LbB5nVdM=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=TNFl0Uo80oVz3obMZEdn3FF2HXzZPl2ntkvgxNjDywjukRAZTSLnrTNJjbsyk2TTA7c0Zog2bX7K5SjIvx8MpmpURP1BJXaTtb6YivpgxNHDSg6Dx5rrDLK0edFmzUmpzjo+k4DtTWhYyOPQpMblG59Za/Y4M5LSToFDsySTrMU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iscas.ac.cn; spf=pass smtp.mailfrom=iscas.ac.cn; arc=none smtp.client-ip=159.226.251.25 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iscas.ac.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iscas.ac.cn Received: from localhost.localdomain (unknown [111.196.245.140]) by APP-05 (Coremail) with SMTP id zQCowAAXnP+MR1dqoGJHGA--.25443S2; Wed, 15 Jul 2026 16:40:44 +0800 (CST) From: Pengpeng Hou To: Mauro Carvalho Chehab Cc: Pengpeng Hou , linux-media@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] media: ttusb-dec: validate command response lengths Date: Wed, 15 Jul 2026 16:40:44 +0800 Message-ID: <20260715084044.35466-1-pengpeng@iscas.ac.cn> X-Mailer: git-send-email 2.50.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: zQCowAAXnP+MR1dqoGJHGA--.25443S2 X-Coremail-Antispam: 1UD129KBjvJXoW3Wr45Cw4kXF1fXrW5trWfGrg_yoWfXr47pF 4UKayFyr1UAa18JryfCr40vF9xZ3s2yFyxK34rW3sIqF4kWa4UGFyjga4Yvr18CrZrGF15 Xrn8Ka45Kr43W3DanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUyC14x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK02 1l84ACjcxK6xIIjxv20xvE14v26F1j6w1UM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26r4U JVWxJr1l84ACjcxK6I8E87Iv67AKxVWxJr0_GcWl84ACjcxK6I8E87Iv6xkF7I0E14v26r xl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj 6xIIjxv20xvE14v26r1q6rW5McIj6I8E87Iv67AKxVW8JVWxJwAm72CE4IkC6x0Yz7v_Jr 0_Gr1lF7xvr2IYc2Ij64vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7MxAIw28IcxkI7VAK I48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7 xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUAVWUtwCIc40Y0x0EwIxGrwCI42IY6xII jxv20xvE14v26r4j6ryUMIIF0xvE2Ix0cI8IcVCY1x0267AKxVWxJVW8Jr1lIxAIcVCF04 k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4A2jsIEc7Cj xVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x0JUsiSdUUUUU= X-CM-SenderInfo: pshqw1xhqjqxpvfd2hldfou0/ Content-Type: text/plain; charset="utf-8" The command helper allocates a 60-byte payload after a four-byte header. A successful USB bulk read can still be shorter than that header or advertise a payload length not contained in the actual transfer. The helper copied that length before callers could inspect it. Pass the destination capacity through the internal frontend callback and reject response lengths outside the actual received bytes, the fixed payload buffer, or a supplied destination. Reject oversized request parameters as well. Signed-off-by: Pengpeng Hou --- drivers/media/usb/ttusb-dec/ttusb_dec.c | 61 +++++++++++++++--------- drivers/media/usb/ttusb-dec/ttusbdecfe.c | 9 ++-- drivers/media/usb/ttusb-dec/ttusbdecfe.h | 3 +- 3 files changed, 46 insertions(+), 27 deletions(-) diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/tt= usb-dec/ttusb_dec.c index 825a3875989d..70675f742b3b 100644 --- a/drivers/media/usb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c @@ -314,12 +314,15 @@ static u16 crc16(u16 crc, const u8 *buf, size_t len) =20 static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, int param_length, const u8 params[], - int *result_length, u8 cmd_result[]) + int *result_length, u8 cmd_result[], + unsigned int cmd_result_size) { int result, actual_len; u8 *b; =20 dprintk("%s\n", __func__); + if (param_length < 0 || param_length > COMMAND_PACKET_SIZE) + return -EINVAL; =20 b =3D kzalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL); if (!b) @@ -360,18 +363,28 @@ static int ttusb_dec_send_command(struct ttusb_dec *d= ec, const u8 command, printk("%s: result bulk message failed: error %d\n", __func__, result); goto err_mutex_unlock; - } else { - if (debug) { - printk(KERN_DEBUG "%s: result: %*ph\n", - __func__, actual_len, b); - } + } + + dprintk("%s: result: %*ph\n", __func__, actual_len, b); =20 - if (result_length) - *result_length =3D b[3]; - if (cmd_result && b[3] > 0) - memcpy(cmd_result, &b[4], b[3]); + if (actual_len < 4) { + pr_warn("%s: short result packet\n", __func__); + result =3D -EPROTO; + goto err_mutex_unlock; } =20 + if (b[3] > COMMAND_PACKET_SIZE || b[3] > actual_len - 4 || + (cmd_result && b[3] > cmd_result_size)) { + pr_warn("%s: invalid result length %u\n", __func__, b[3]); + result =3D -EPROTO; + goto err_mutex_unlock; + } + + if (result_length) + *result_length =3D b[3]; + if (cmd_result && b[3] > 0) + memcpy(cmd_result, &b[4], b[3]); + err_mutex_unlock: mutex_unlock(&dec->usb_mutex); err_free: @@ -389,7 +402,8 @@ static int ttusb_dec_get_stb_state (struct ttusb_dec *d= ec, unsigned int *mode, =20 dprintk("%s\n", __func__); =20 - result =3D ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c); + result =3D ttusb_dec_send_command(dec, 0x08, 0, NULL, + &c_length, c, sizeof(c)); if (result) return result; =20 @@ -448,7 +462,7 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec) memcpy(&b[2], &audio, 2); memcpy(&b[4], &video, 2); =20 - ttusb_dec_send_command(dec, 0x50, sizeof(b), b, NULL, NULL); + ttusb_dec_send_command(dec, 0x50, sizeof(b), b, NULL, NULL, 0); =20 dvb_filter_pes2ts_init(&dec->a_pes2ts, dec->pid[DMX_PES_AUDIO], ttusb_dec_audio_pes2ts_cb, dec); @@ -902,7 +916,7 @@ static int ttusb_dec_set_interface(struct ttusb_dec *de= c, break; case TTUSB_DEC_INTERFACE_IN: result =3D ttusb_dec_send_command(dec, 0x80, sizeof(b), - b, NULL, NULL); + b, NULL, NULL, 0); if (result) return result; result =3D usb_set_interface(dec->udev, 0, 8); @@ -1021,7 +1035,7 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_f= eed *dvbdmxfeed) =20 } =20 - result =3D ttusb_dec_send_command(dec, 0x80, sizeof(b0), b0, NULL, NULL); + result =3D ttusb_dec_send_command(dec, 0x80, sizeof(b0), b0, NULL, NULL, = 0); if (result) return result; =20 @@ -1056,7 +1070,7 @@ static int ttusb_dec_start_sec_feed(struct dvb_demux_= feed *dvbdmxfeed) memcpy(&b0[5], &dvbdmxfeed->filter->filter.filter_value[0], 1); =20 result =3D ttusb_dec_send_command(dec, 0x60, sizeof(b0), b0, - &c_length, c); + &c_length, c, sizeof(c)); =20 if (!result) { if (c_length =3D=3D 2) { @@ -1114,7 +1128,7 @@ static int ttusb_dec_stop_ts_feed(struct dvb_demux_fe= ed *dvbdmxfeed) struct ttusb_dec *dec =3D dvbdmxfeed->demux->priv; u8 b0[] =3D { 0x00 }; =20 - ttusb_dec_send_command(dec, 0x81, sizeof(b0), b0, NULL, NULL); + ttusb_dec_send_command(dec, 0x81, sizeof(b0), b0, NULL, NULL, 0); =20 dec->pva_stream_count--; =20 @@ -1135,7 +1149,7 @@ static int ttusb_dec_stop_sec_feed(struct dvb_demux_f= eed *dvbdmxfeed) list_del(&finfo->filter_info_list); spin_unlock_irqrestore(&dec->filter_info_list_lock, flags); kfree(finfo); - ttusb_dec_send_command(dec, 0x62, sizeof(b0), b0, NULL, NULL); + ttusb_dec_send_command(dec, 0x62, sizeof(b0), b0, NULL, NULL, 0); =20 dec->filter_stream_count--; =20 @@ -1238,7 +1252,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec) if (usb_submit_urb(dec->irq_urb, GFP_KERNEL)) printk("%s: usb_submit_urb failed\n",__func__); /* enable irq pipe */ - ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL); + ttusb_dec_send_command(dec, 0xb0, sizeof(b), b, NULL, NULL, 0); =20 return 0; } @@ -1354,7 +1368,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) firmware_csum_ns =3D htons(firmware_csum); memcpy(&b0[6], &firmware_csum_ns, 2); =20 - result =3D ttusb_dec_send_command(dec, 0x41, sizeof(b0), b0, NULL, NULL); + result =3D ttusb_dec_send_command(dec, 0x41, sizeof(b0), b0, NULL, NULL, = 0); =20 if (result) { release_firmware(fw_entry); @@ -1395,7 +1409,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) } } =20 - result =3D ttusb_dec_send_command(dec, 0x43, sizeof(b1), b1, NULL, NULL); + result =3D ttusb_dec_send_command(dec, 0x43, sizeof(b1), b1, NULL, NULL, = 0); =20 release_firmware(fw_entry); kfree(b); @@ -1621,10 +1635,13 @@ static void ttusb_dec_exit_filters(struct ttusb_dec= *dec) =20 static int fe_send_command(struct dvb_frontend* fe, const u8 command, int param_length, const u8 params[], - int *result_length, u8 cmd_result[]) + int *result_length, u8 cmd_result[], + unsigned int cmd_result_size) { struct ttusb_dec* dec =3D fe->dvb->priv; - return ttusb_dec_send_command(dec, command, param_length, params, result_= length, cmd_result); + + return ttusb_dec_send_command(dec, command, param_length, params, + result_length, cmd_result, cmd_result_size); } =20 static const struct ttusbdecfe_config fe_config =3D { diff --git a/drivers/media/usb/ttusb-dec/ttusbdecfe.c b/drivers/media/usb/t= tusb-dec/ttusbdecfe.c index 215221370c19..b013d6dfcbee 100644 --- a/drivers/media/usb/ttusb-dec/ttusbdecfe.c +++ b/drivers/media/usb/ttusb-dec/ttusbdecfe.c @@ -44,7 +44,8 @@ static int ttusbdecfe_dvbt_read_status(struct dvb_fronten= d *fe, =20 *status=3D0; =20 - ret=3Dstate->config->send_command(fe, 0x73, sizeof(b), b, &len, result); + ret =3D state->config->send_command(fe, 0x73, sizeof(b), b, &len, result, + sizeof(result)); if(ret) return ret; =20 @@ -85,7 +86,7 @@ static int ttusbdecfe_dvbt_set_frontend(struct dvb_fronte= nd *fe) =20 __be32 freq =3D htonl(p->frequency / 1000); memcpy(&b[4], &freq, sizeof (u32)); - state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL); + state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL, 0); =20 return 0; } @@ -130,7 +131,7 @@ static int ttusbdecfe_dvbs_set_frontend(struct dvb_fron= tend *fe) lnb_voltage =3D htonl(state->voltage); memcpy(&b[28], &lnb_voltage, sizeof(u32)); =20 - state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL); + state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL, 0); =20 return 0; } @@ -149,7 +150,7 @@ static int ttusbdecfe_dvbs_diseqc_send_master_cmd(struc= t dvb_frontend* fe, struc =20 state->config->send_command(fe, 0x72, sizeof(b) - (6 - cmd->msg_len), b, - NULL, NULL); + NULL, NULL, 0); =20 return 0; } diff --git a/drivers/media/usb/ttusb-dec/ttusbdecfe.h b/drivers/media/usb/t= tusb-dec/ttusbdecfe.h index 73828bb2258c..339711f83ff0 100644 --- a/drivers/media/usb/ttusb-dec/ttusbdecfe.h +++ b/drivers/media/usb/ttusb-dec/ttusbdecfe.h @@ -14,7 +14,8 @@ struct ttusbdecfe_config { int (*send_command)(struct dvb_frontend* fe, const u8 command, int param_length, const u8 params[], - int *result_length, u8 cmd_result[]); + int *result_length, u8 cmd_result[], + unsigned int cmd_result_size); }; =20 extern struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe= _config* config); --=20 2.43.0