[libbdplus-devel] [Git][videolan/libbdplus][master] Add some basic validity checks for cached conversion table
Petri Hintukainen (@hpi)
gitlab at videolan.org
Wed Oct 6 15:31:11 UTC 2021
Petri Hintukainen pushed to branch master at VideoLAN / libbdplus
Commits:
228d22fd by anonymous at 2021-10-06T18:30:03+03:00
Add some basic validity checks for cached conversion table
- - - - -
2 changed files:
- src/examples/convtab_dump.c
- src/libbdplus/bdsvm/segment.c
Changes:
=====================================
src/examples/convtab_dump.c
=====================================
@@ -60,6 +60,7 @@ int main(int argc, char **argv)
uint32_t numTables, table;
uint32_t ptr = 0;
uint32_t offset = 0;
+ int errors = 0;
if (argc < 2) {
fprintf(stderr, "%s /path/to/conv_tab.bin\n", argv[0]);
@@ -89,6 +90,7 @@ int main(int argc, char **argv)
for (segment = 0; segment < numSegments; segment++) {
uint32_t numEntries, entry;
+ uint64_t prev_off1 = 0;
offset = FETCH4(&tab[ptr + (segment * 4) ]);
@@ -143,6 +145,31 @@ int main(int argc, char **argv)
printf(" %08X %08X: %02X %02X %02X %02X %02X\n",
(uint32_t)(off1 >> 32), (uint32_t)(off1 & 0xffffffff),
patch1[0], patch1[1], patch1[2], patch1[3], patch1[4]);
+
+ if ((flags >> 6) == 3) {
+ printf(" *** invalid flags ***\n");
+ errors++;
+ }
+ if ((flags >> 6) == 1) {
+ if (patch0_buffer_offset < 8 || patch1_buffer_offset < 8) {
+ printf(" *** Invalid in-packet offset (inside ts header) ***\n");
+ errors++;
+ }
+ if (patch0_buffer_offset > 187 || patch1_buffer_offset > 187) {
+ printf(" *** Invalid in-packet offset (overwrite) ***\n");
+ errors++;
+ }
+ if (off0 >= off1) {
+ printf(" *** invalid offset (off0 >= off1) ***\n");
+ errors++;
+ }
+ if (off0 < prev_off1) {
+ printf(" *** invalid offset sequence (not monotonic) ***\n");
+ errors++;
+ }
+ prev_off1 = off1;
+ }
+
} // for entry
} // for segment
@@ -151,5 +178,5 @@ int main(int argc, char **argv)
} // for table
- return 0;
+ return errors;
}
=====================================
src/libbdplus/bdsvm/segment.c
=====================================
@@ -143,6 +143,70 @@ struct bdplus_st_s {
uint64_t next_patch_offset; /* optimize patching */
};
+/*
+ *
+ */
+
+static int64_t _entry_offset0(const entry_t *e)
+{
+ return (((uint64_t)e->index +
+ (uint64_t)e->patch0_address_adjust) *
+ (uint64_t)0xC0 +
+ (uint64_t)e->patch0_buffer_offset);
+}
+
+static int64_t _entry_offset1(const entry_t *e)
+{
+ return (( (uint64_t)e->index +
+ (uint64_t)e->patch0_address_adjust +
+ (uint64_t)e->patch1_address_adjust) *
+ (uint64_t)0xC0 +
+ (uint64_t)e->patch1_buffer_offset);
+}
+
+static int _is_invalid_entry(const entry_t *e, const entry_t *prev)
+{
+ unsigned invalid = 0;
+
+ /*
+ Do some basic sanity checks for conversion table entry.
+ Note: Following checks are incomplete. The idea is to catch tables with
+ random or encrypted data. This works quite well because of there are
+ thousands of entries in the table.
+
+ Checks could be improved a lot if we parse also .clpi file and the stream.
+ */
+
+ if ((e->flags >> 6) == 3) {
+ BD_DEBUG(DBG_BDPLUS, "[segment] invalid flags in entry.\n");
+ return 1;
+ }
+
+ /* Check only unconditionally applied entries. */
+ /* Inactive entries are most likely filled with random data to secure the key. */
+ if ((e->flags >> 6) == 1) {
+ if (e->patch0_buffer_offset < 8 || e->patch0_buffer_offset > 187 ||
+ e->patch1_buffer_offset < 8 || e->patch1_buffer_offset > 187) {
+
+ /* - too easy to reconstruct, would compromize segment key */
+ /* - ATC is used to control buffering and disk spinning at _lower_ layers */
+ /* - not user-visible, useless for watermarking. */
+ BD_DEBUG(DBG_BDPLUS, "[segment] invalid patch buffer offsets in entry.\n");
+ invalid = 1;
+ }
+ if (_entry_offset0(e) >= _entry_offset1(e) ||
+ ( prev && (prev->flags >> 6) == 1 &&
+ _entry_offset0(e) < _entry_offset1(prev))) {
+
+ /* tables are always sorted */
+ BD_DEBUG(DBG_BDPLUS, "[segment] invalid offset in entry.\n");
+ invalid = 1;
+ }
+ }
+
+ return invalid;
+}
+
/*
*
*/
@@ -167,6 +231,25 @@ uint32_t segment_numEntries(conv_table_t *ct)
return entries;
}
+static int32_t segment_validateTable(conv_table_t *ct)
+{
+ uint32_t table, currseg, currentry;
+ int errors = 0;
+
+ for (table = 0; table < ct->numTables; table++) {
+ subtable_t *subtable = &ct->Tables[ table ];
+ for (currseg = 0; currseg < subtable->numSegments; currseg++) {
+ segment_t *segment = &subtable->Segments[ currseg ];
+ for (currentry = 0; currentry < segment->numEntries; currentry++) {
+ entry_t *entry = &segment->Entries[ currentry ];
+ errors += _is_invalid_entry(entry, currentry == 0 ? NULL : (entry - 1));
+ }
+ }
+ }
+ return errors;
+}
+
+
int32_t segment_setTable(conv_table_t **conv_tab, uint8_t *Table, uint32_t len)
{
uint32_t table, currseg, currentry;
@@ -774,9 +857,17 @@ int32_t segment_load(conv_table_t **conv_tab, FILE *fd)
if (len) {
// Decode the table into C structures.
segment_setTable(conv_tab, buffer, fileLen);
- X_FREE(buffer);
+ }
+
+ X_FREE(buffer);
- if(conv_tab) return 1;
+ if (*conv_tab) {
+ int errors = segment_validateTable(*conv_tab);
+ if (errors == 0) {
+ return 1;
+ }
+ BD_DEBUG(DBG_BDPLUS|DBG_CRIT, "[bdplus] dropping broken cached conversion table (%d invalid entries).\n", errors);
+ segment_freeTable(conv_tab);
}
return 0;
}
View it on GitLab: https://code.videolan.org/videolan/libbdplus/-/commit/228d22fd114b0f6b24841a175fd44a9c95f8e8ba
--
View it on GitLab: https://code.videolan.org/videolan/libbdplus/-/commit/228d22fd114b0f6b24841a175fd44a9c95f8e8ba
You're receiving this email because of your account on code.videolan.org.
More information about the libbdplus-devel
mailing list