Skip to content

Commit 9ac93d1

Browse files
arkqperexg
authored andcommitted
Fix TLV dB parser in case of used container
In case when dB information does not appear as the only TLV type in the stream (it might be wrapped in a container, but the container can not have any other type), the TLV parser fails to get the dB TLV pointer. This commit fixes it by distinguishing between TLV parse error and dB information not being found in a container (-ENOENT), so the parser can iterate over all elements in the container. Also, it fixes out-of-bounds read in case of malicious TLV record. Closes: #409 Signed-off-by: Arkadiusz Bokowy <arkadiusz.bokowy@gmail.com> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
1 parent fc58f8f commit 9ac93d1

File tree

1 file changed

+14
-5
lines changed

1 file changed

+14
-5
lines changed

src/control/tlv.c

+14-5
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,21 @@
4040
#define int_index(size) (((size) + sizeof(int) - 1) / sizeof(int))
4141
/* max size of a TLV entry for dB information (including compound one) */
4242
#define MAX_TLV_RANGE_SIZE 256
43+
/* min length of a TLV stream to contain type and size */
44+
#define MIN_TLV_STREAM_LEN ((SNDRV_CTL_TLVO_LEN + 1) * sizeof(int))
4345
#endif
4446

4547
/**
4648
* \brief Parse TLV stream and retrieve dB information
4749
* \param tlv the TLV source
4850
* \param tlv_size the byte size of TLV source
4951
* \param db_tlvp the pointer stored the dB TLV information
50-
* \return the byte size of dB TLV information if found in the given
51-
* TLV source, or a negative error code.
52+
* \return The byte size of dB TLV information if found in the given TLV
53+
* source, -ENOENT if not found, or a negative error code in case of an error.
5254
*
5355
* This function parses the given TLV source and stores the TLV start
5456
* point if the TLV information regarding dB conversion is found.
55-
* The stored TLV pointer can be passed to the convesion functions
57+
* The stored TLV pointer can be passed to the conversion functions
5658
* #snd_tlv_convert_to_dB(), #snd_tlv_convert_from_dB() and
5759
* #snd_tlv_get_dB_range().
5860
*/
@@ -64,6 +66,13 @@ int snd_tlv_parse_dB_info(unsigned int *tlv,
6466
unsigned int size;
6567
int err;
6668

69+
/* Validate that it is possible to read the type and size
70+
* without reading past the end of the buffer. */
71+
if (tlv_size < MIN_TLV_STREAM_LEN) {
72+
SNDERR("TLV stream too short");
73+
return -EINVAL;
74+
}
75+
6776
*db_tlvp = NULL;
6877
type = tlv[SNDRV_CTL_TLVO_TYPE];
6978
size = tlv[SNDRV_CTL_TLVO_LEN];
@@ -79,7 +88,7 @@ int snd_tlv_parse_dB_info(unsigned int *tlv,
7988
while (size > 0) {
8089
unsigned int len;
8190
err = snd_tlv_parse_dB_info(tlv, size, db_tlvp);
82-
if (err < 0)
91+
if (err < 0 && err != -ENOENT)
8392
return err; /* error */
8493
if (err > 0)
8594
return err; /* found */
@@ -114,7 +123,7 @@ int snd_tlv_parse_dB_info(unsigned int *tlv,
114123
default:
115124
break;
116125
}
117-
return -EINVAL; /* not found */
126+
return -ENOENT;
118127
}
119128

120129
/**

0 commit comments

Comments
 (0)