linux-mtd.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* potential memory corruption in check_leaf()
@ 2014-11-06 10:09 Dan Carpenter
  2014-11-25 15:00 ` Artem Bityutskiy
  0 siblings, 1 reply; 2+ messages in thread
From: Dan Carpenter @ 2014-11-06 10:09 UTC (permalink / raw)
  To: Artem Bityutskiy; +Cc: linux-mtd

Hello Artem Bityutskiy,

The patch 1e51764a3c2a: "UBIFS: add new flash file system" from Jul
14, 2008, leads to the following static checker warning:

	fs/ubifs/debug.c:2039 check_leaf()
	warn: is 'node' large enough for 'struct ubifs_data_node'?

fs/ubifs/debug.c
  1978  static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr,
  1979                        void *priv)
  1980  {
  1981          ino_t inum;
  1982          void *node;
  1983          struct ubifs_ch *ch;
  1984          int err, type = key_type(c, &zbr->key);
  1985          struct fsck_inode *fscki;
  1986  
  1987          if (zbr->len < UBIFS_CH_SZ) {
                    ^^^^^^^^^^^^^^^^^^^^^^^
We check that ->len is at least 24 bytes.

  1988                  ubifs_err("bad leaf length %d (LEB %d:%d)",
  1989                            zbr->len, zbr->lnum, zbr->offs);
  1990                  return -EINVAL;
  1991          }
  1992  
  1993          node = kmalloc(zbr->len, GFP_NOFS);
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Allocate node.

  1994          if (!node)
  1995                  return -ENOMEM;
  1996  
  1997          err = ubifs_tnc_read_node(c, zbr, node);
  1998          if (err) {
  1999                  ubifs_err("cannot read leaf node at LEB %d:%d, error %d",
  2000                            zbr->lnum, zbr->offs, err);
  2001                  goto out_free;
  2002          }
  2003  
  2004          /* If this is an inode node, add it to RB-tree of inodes */
  2005          if (type == UBIFS_INO_KEY) {
  2006                  fscki = add_inode(c, priv, node);
  2007                  if (IS_ERR(fscki)) {
  2008                          err = PTR_ERR(fscki);
  2009                          ubifs_err("error %d while adding inode node", err);
  2010                          goto out_dump;
  2011                  }
  2012                  goto out;
  2013          }
  2014  
  2015          if (type != UBIFS_DENT_KEY && type != UBIFS_XENT_KEY &&
  2016              type != UBIFS_DATA_KEY) {
  2017                  ubifs_err("unexpected node type %d at LEB %d:%d",
  2018                            type, zbr->lnum, zbr->offs);
  2019                  err = -EINVAL;
  2020                  goto out_free;
  2021          }
  2022  
  2023          ch = node;
                ^^^^^^^^^^
24 bytes is large enough for "ch".

  2024          if (le64_to_cpu(ch->sqnum) > c->max_sqnum) {
  2025                  ubifs_err("too high sequence number, max. is %llu",
  2026                            c->max_sqnum);
  2027                  err = -EINVAL;
  2028                  goto out_dump;
  2029          }
  2030  
  2031          if (type == UBIFS_DATA_KEY) {
  2032                  long long blk_offs;
  2033                  struct ubifs_data_node *dn = node;
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
But it's not large enough for "dn".

  2034  
  2035                  /*
  2036                   * Search the inode node this data node belongs to and insert
  2037                   * it to the RB-tree of inodes.
  2038                   */
  2039                  inum = key_inum_flash(c, &dn->key);
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The check waits until we use "dn" before complaining, in case there is
another size check after the assignment.

Also on the other side of the if statement:
fs/ubifs/debug.c:2071 check_leaf() warn: is 'node' large enough for 'struct ubifs_dent_node'?

regards,
dan carpenter

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: potential memory corruption in check_leaf()
  2014-11-06 10:09 potential memory corruption in check_leaf() Dan Carpenter
@ 2014-11-25 15:00 ` Artem Bityutskiy
  0 siblings, 0 replies; 2+ messages in thread
From: Artem Bityutskiy @ 2014-11-25 15:00 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: linux-mtd

On Thu, 2014-11-06 at 13:09 +0300, Dan Carpenter wrote:
>   1988                  ubifs_err("bad leaf length %d (LEB %d:%d)",
>   1989                            zbr->len, zbr->lnum, zbr->offs);
>   1990                  return -EINVAL;
>   1991          }

Yes, this code is a small sanity check. zbr->len is supposed to be the
length of whatever node type is referred by this znode branch.


>   1993          node = kmalloc(zbr->len, GFP_NOFS);
>                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> Allocate node.

Supposedly we allocate enough to store the node we refer to.

>   2031          if (type == UBIFS_DATA_KEY) {
>   2032                  long long blk_offs;
>   2033                  struct ubifs_data_node *dn = node;
>                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> But it's not large enough for "dn".

Well, this should not happen, but let's add an assert here to check that
we have enough space for 'dn'.

Something like this.


>From 6785baa1697c15a51408e7317709cbf078604695 Mon Sep 17 00:00:00 2001
From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Date: Tue, 25 Nov 2014 16:41:26 +0200
Subject: [PATCH] UBIFS: add a couple of extra asserts

... to catch possible memory corruptions.

Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
---
 fs/ubifs/debug.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 7ed13e1..4cfb3e8 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -2032,6 +2032,8 @@ static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr,
 		long long blk_offs;
 		struct ubifs_data_node *dn = node;
 
+		ubifs_assert(zbr->len >= UBIFS_DATA_NODE_SZ);
+
 		/*
 		 * Search the inode node this data node belongs to and insert
 		 * it to the RB-tree of inodes.
@@ -2060,6 +2062,8 @@ static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr,
 		struct ubifs_dent_node *dent = node;
 		struct fsck_inode *fscki1;
 
+		ubifs_assert(zbr->len >= UBIFS_DENT_NODE_SZ);
+
 		err = ubifs_validate_entry(c, dent);
 		if (err)
 			goto out_dump;
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2014-11-25 15:01 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-06 10:09 potential memory corruption in check_leaf() Dan Carpenter
2014-11-25 15:00 ` Artem Bityutskiy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).