Commit 4b54cad0 authored by Andrew Gabbasov's avatar Andrew Gabbasov Committed by Luis Henriques

udf: Prevent buffer overrun with multi-byte characters

commit ad402b26 upstream.

udf_CS0toUTF8 function stops the conversion when the output buffer
length reaches UDF_NAME_LEN-2, which is correct maximum name length,
but, when checking, it leaves the space for a single byte only,
while multi-bytes output characters can take more space, causing
buffer overflow.

Similar error exists in udf_CS0toNLS function, that restricts
the output length to UDF_NAME_LEN, while actual maximum allowed
length is UDF_NAME_LEN-2.

In these cases the output can override not only the current buffer
length field, causing corruption of the name buffer itself, but also
following allocation structures, causing kernel crash.

Adjust the output length checks in both functions to prevent buffer
overruns in case of multi-bytes UTF8 or NLS characters.
Signed-off-by: default avatarAndrew Gabbasov <andrew_gabbasov@mentor.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent 6654e621
...@@ -133,11 +133,15 @@ int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i) ...@@ -133,11 +133,15 @@ int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i)
if (c < 0x80U) if (c < 0x80U)
utf_o->u_name[utf_o->u_len++] = (uint8_t)c; utf_o->u_name[utf_o->u_len++] = (uint8_t)c;
else if (c < 0x800U) { else if (c < 0x800U) {
if (utf_o->u_len > (UDF_NAME_LEN - 4))
break;
utf_o->u_name[utf_o->u_len++] = utf_o->u_name[utf_o->u_len++] =
(uint8_t)(0xc0 | (c >> 6)); (uint8_t)(0xc0 | (c >> 6));
utf_o->u_name[utf_o->u_len++] = utf_o->u_name[utf_o->u_len++] =
(uint8_t)(0x80 | (c & 0x3f)); (uint8_t)(0x80 | (c & 0x3f));
} else { } else {
if (utf_o->u_len > (UDF_NAME_LEN - 5))
break;
utf_o->u_name[utf_o->u_len++] = utf_o->u_name[utf_o->u_len++] =
(uint8_t)(0xe0 | (c >> 12)); (uint8_t)(0xe0 | (c >> 12));
utf_o->u_name[utf_o->u_len++] = utf_o->u_name[utf_o->u_len++] =
...@@ -282,7 +286,7 @@ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, ...@@ -282,7 +286,7 @@ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o,
c = (c << 8) | ocu[i++]; c = (c << 8) | ocu[i++];
len = nls->uni2char(c, &utf_o->u_name[utf_o->u_len], len = nls->uni2char(c, &utf_o->u_name[utf_o->u_len],
UDF_NAME_LEN - utf_o->u_len); UDF_NAME_LEN - 2 - utf_o->u_len);
/* Valid character? */ /* Valid character? */
if (len >= 0) if (len >= 0)
utf_o->u_len += len; utf_o->u_len += len;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment