lkml.org 
[lkml]   [2016]   [Feb]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.10 32/54] udf: Prevent buffer overrun with multi-byte characters
    Date
    3.10-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Andrew Gabbasov <andrew_gabbasov@mentor.com>

    commit ad402b265ecf6fa22d04043b41444cdfcdf4f52d 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: Andrew Gabbasov <andrew_gabbasov@mentor.com>
    Signed-off-by: Jan Kara <jack@suse.cz>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/udf/unicode.c | 6 +++++-
    1 file changed, 5 insertions(+), 1 deletion(-)

    --- a/fs/udf/unicode.c
    +++ b/fs/udf/unicode.c
    @@ -132,11 +132,15 @@ int udf_CS0toUTF8(struct ustr *utf_o, co
    if (c < 0x80U)
    utf_o->u_name[utf_o->u_len++] = (uint8_t)c;
    else if (c < 0x800U) {
    + if (utf_o->u_len > (UDF_NAME_LEN - 4))
    + break;
    utf_o->u_name[utf_o->u_len++] =
    (uint8_t)(0xc0 | (c >> 6));
    utf_o->u_name[utf_o->u_len++] =
    (uint8_t)(0x80 | (c & 0x3f));
    } else {
    + if (utf_o->u_len > (UDF_NAME_LEN - 5))
    + break;
    utf_o->u_name[utf_o->u_len++] =
    (uint8_t)(0xe0 | (c >> 12));
    utf_o->u_name[utf_o->u_len++] =
    @@ -281,7 +285,7 @@ static int udf_CS0toNLS(struct nls_table
    c = (c << 8) | ocu[i++];

    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? */
    if (len >= 0)
    utf_o->u_len += len;

    \
     
     \ /
      Last update: 2016-02-24 05:21    [W:5.154 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site