lkml.org 
[lkml]   [2020]   [Sep]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 4.9 60/90] ubifs: Fix out-of-bounds memory access caused by abnormal value of node_len
    Date
    From: Liu Song <liu.song11@zte.com.cn>

    [ Upstream commit acc5af3efa303d5f36cc8c0f61716161f6ca1384 ]

    In “ubifs_check_node”, when the value of "node_len" is abnormal,
    the code will goto label of "out_len" for execution. Then, in the
    following "ubifs_dump_node", if inode type is "UBIFS_DATA_NODE",
    in "print_hex_dump", an out-of-bounds access may occur due to the
    wrong "ch->len".

    Therefore, when the value of "node_len" is abnormal, data length
    should to be adjusted to a reasonable safe range. At this time,
    structured data is not credible, so dump the corrupted data directly
    for analysis.

    Signed-off-by: Liu Song <liu.song11@zte.com.cn>
    Signed-off-by: Richard Weinberger <richard@nod.at>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/ubifs/io.c | 16 ++++++++++++++--
    1 file changed, 14 insertions(+), 2 deletions(-)

    diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
    index 97be412153328..9213a9e046ae0 100644
    --- a/fs/ubifs/io.c
    +++ b/fs/ubifs/io.c
    @@ -237,7 +237,7 @@ int ubifs_is_mapped(const struct ubifs_info *c, int lnum)
    int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
    int offs, int quiet, int must_chk_crc)
    {
    - int err = -EINVAL, type, node_len;
    + int err = -EINVAL, type, node_len, dump_node = 1;
    uint32_t crc, node_crc, magic;
    const struct ubifs_ch *ch = buf;

    @@ -290,10 +290,22 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
    out_len:
    if (!quiet)
    ubifs_err(c, "bad node length %d", node_len);
    + if (type == UBIFS_DATA_NODE && node_len > UBIFS_DATA_NODE_SZ)
    + dump_node = 0;
    out:
    if (!quiet) {
    ubifs_err(c, "bad node at LEB %d:%d", lnum, offs);
    - ubifs_dump_node(c, buf);
    + if (dump_node) {
    + ubifs_dump_node(c, buf);
    + } else {
    + int safe_len = min3(node_len, c->leb_size - offs,
    + (int)UBIFS_MAX_DATA_NODE_SZ);
    + pr_err("\tprevent out-of-bounds memory access\n");
    + pr_err("\ttruncated data node length %d\n", safe_len);
    + pr_err("\tcorrupted data node:\n");
    + print_hex_dump(KERN_ERR, "\t", DUMP_PREFIX_OFFSET, 32, 1,
    + buf, safe_len, 0);
    + }
    dump_stack();
    }
    return err;
    --
    2.25.1
    \
     
     \ /
      Last update: 2020-09-18 04:26    [W:4.033 / U:0.132 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site