From: Boris Brezillon <boris.brezillon@collabora.com>
To: Kees Cook <keescook@chromium.org>
Cc: Vignesh Raghavendra <vigneshr@ti.com>,
"Gustavo A. R. Silva" <gustavo@embeddedor.com>,
Richard Weinberger <richard@nod.at>,
linux-kernel@vger.kernel.org, Marek Vasut <marek.vasut@gmail.com>,
Kyungmin Park <kyungmin.park@samsung.com>,
linux-mtd@lists.infradead.org,
Miquel Raynal <miquel.raynal@bootlin.com>,
Brian Norris <computersforpeace@gmail.com>,
David Woodhouse <dwmw2@infradead.org>
Subject: Re: [PATCH] mtd: onenand_base: Avoid fall-through warnings
Date: Wed, 22 May 2019 23:57:38 +0200 [thread overview]
Message-ID: <20190522235738.68059906@collabora.com> (raw)
In-Reply-To: <201905221403.642AF6092@keescook>
On Wed, 22 May 2019 14:30:11 -0700
Kees Cook <keescook@chromium.org> wrote:
> Sorry for being late to speaking up on this. I missed something in the
> code the first time I read the thread, that now stood out to me. Notes
> below...
>
> On Wed, May 22, 2019 at 01:04:46PM -0500, Gustavo A. R. Silva wrote:
> > diff --git a/drivers/mtd/nand/onenand/onenand_base.c b/drivers/mtd/nand/onenand/onenand_base.c
> > index f41d76248550..6cf4df9f8c01 100644
> > --- a/drivers/mtd/nand/onenand/onenand_base.c
> > +++ b/drivers/mtd/nand/onenand/onenand_base.c
> > @@ -3280,12 +3280,14 @@ static void onenand_check_features(struct mtd_info *mtd)
>
> Reverse-order review, second hunk first:
>
> > case ONENAND_DEVICE_DENSITY_2Gb:
> > /* 2Gb DDP does not have 2 plane */
> > if (!ONENAND_IS_DDP(this))
> > this->options |= ONENAND_HAS_2PLANE;
> > this->options |= ONENAND_HAS_UNLOCK_ALL;
> > + /* Fall through - ? */
> >
> > case ONENAND_DEVICE_DENSITY_1Gb:
> > /* A-Die has all block unlock */
>
> So, I think the ONENAND_DEVICE_DENSITY_2Gb should be a "break". Though,
> actually, it doesn't matter:
>
> case ONENAND_DEVICE_DENSITY_2Gb:
> /* 2Gb DDP does not have 2 plane */
> if (!ONENAND_IS_DDP(this))
> this->options |= ONENAND_HAS_2PLANE;
> this->options |= ONENAND_HAS_UNLOCK_ALL;
>
> case ONENAND_DEVICE_DENSITY_1Gb:
> /* A-Die has all block unlock */
> if (process)
> this->options |= ONENAND_HAS_UNLOCK_ALL;
> break;
>
> Falling through from ONENAND_DEVICE_DENSITY_2Gb to
> ONENAND_DEVICE_DENSITY_1Gb will actually have no side-effects:
> ONENAND_HAS_UNLOCK_ALL was unconditionally set in ..._2Gb, so there is
> no reason to fall through to ..._1Gb. (But falling through is harmless.)
>
> Now the first hunk:
>
> > if ((this->version_id & 0xf) == 0xe)
> > this->options |= ONENAND_HAS_NOP_1;
> > }
> > + /* Fall through - ? */
> >
>
> case ONENAND_DEVICE_DENSITY_4Gb:
> if (ONENAND_IS_DDP(this))
> this->options |= ONENAND_HAS_2PLANE;
> else if (numbufs == 1) {
> this->options |= ONENAND_HAS_4KB_PAGE;
> this->options |= ONENAND_HAS_CACHE_PROGRAM;
> /*
> * There are two different 4KiB pagesize chips
> * and no way to detect it by H/W config values.
> *
> * To detect the correct NOP for each chips,
> * It should check the version ID as workaround.
> *
> * Now it has as following
> * KFM4G16Q4M has NOP 4 with version ID 0x0131
> * KFM4G16Q5M has NOP 1 with versoin ID 0x013e
> */
> if ((this->version_id & 0xf) == 0xe)
> this->options |= ONENAND_HAS_NOP_1;
> }
>
> Falling through from ONENAND_DEVICE_DENSITY_4Gb to
> ONENAND_DEVICE_DENSITY_2Gb looks like it would mean that
> ONENAND_HAS_2PLANE would be unconditionally set for ...4Gb, which seems
> very strange to expect:
>
> if (ONENAND_IS_DDP(this))
> this->options |= ONENAND_HAS_2PLANE;
> ...
> if (!ONENAND_IS_DDP(this))
> this->options |= ONENAND_HAS_2PLANE;
Oops, didn't notice the ! on the second test.
>
> However! This happens later:
>
> if (ONENAND_IS_4KB_PAGE(this))
> this->options &= ~ONENAND_HAS_2PLANE;
>
> i.e. falling through to ...2Gb (which sets ONENAND_HAS_2PLANE) has no
> effect because when ONENAND_HAS_2PLANE isn't set (numbufs == 1), it gets
> _cleared_ by the above code due to ONENAND_HAS_4KB_PAGE getting set:
Are you sure !DDP implies num_bufs == 1?
>
> #define ONENAND_IS_4KB_PAGE(this) \
> (this->options & ONENAND_HAS_4KB_PAGE)
>
>
> Unfortunately, though, it's less clear about ONENAND_HAS_UNLOCK_ALL,
> which is getting set unconditionally for ...4Gb currently (due to the
> fallthrough to ...2Gb). However, this happens later:
>
> if (FLEXONENAND(this)) {
> this->options &= ~ONENAND_HAS_CONT_LOCK;
> this->options |= ONENAND_HAS_UNLOCK_ALL;
> }
> ...
> #define FLEXONENAND(this) \
> (this->device_id & DEVICE_IS_FLEXONENAND)
>
> So it's possible this fall through has no effect (are all 4Gb density
> devices also FLEXONENAND devices?)
>
All this look suspicious, and even if the fall through logic
has no side effects in practice (which I'm still not sure is the case),
I think it'd be better to explicitly set the flags that have
to be set in each case statement and add breaks.
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
WARNING: multiple messages have this Message-ID (diff)
From: Boris Brezillon <boris.brezillon@collabora.com>
To: Kees Cook <keescook@chromium.org>
Cc: "Gustavo A. R. Silva" <gustavo@embeddedor.com>,
Vignesh Raghavendra <vigneshr@ti.com>,
Richard Weinberger <richard@nod.at>,
linux-kernel@vger.kernel.org, Marek Vasut <marek.vasut@gmail.com>,
Kyungmin Park <kyungmin.park@samsung.com>,
linux-mtd@lists.infradead.org,
Miquel Raynal <miquel.raynal@bootlin.com>,
Brian Norris <computersforpeace@gmail.com>,
David Woodhouse <dwmw2@infradead.org>
Subject: Re: [PATCH] mtd: onenand_base: Avoid fall-through warnings
Date: Wed, 22 May 2019 23:57:38 +0200 [thread overview]
Message-ID: <20190522235738.68059906@collabora.com> (raw)
In-Reply-To: <201905221403.642AF6092@keescook>
On Wed, 22 May 2019 14:30:11 -0700
Kees Cook <keescook@chromium.org> wrote:
> Sorry for being late to speaking up on this. I missed something in the
> code the first time I read the thread, that now stood out to me. Notes
> below...
>
> On Wed, May 22, 2019 at 01:04:46PM -0500, Gustavo A. R. Silva wrote:
> > diff --git a/drivers/mtd/nand/onenand/onenand_base.c b/drivers/mtd/nand/onenand/onenand_base.c
> > index f41d76248550..6cf4df9f8c01 100644
> > --- a/drivers/mtd/nand/onenand/onenand_base.c
> > +++ b/drivers/mtd/nand/onenand/onenand_base.c
> > @@ -3280,12 +3280,14 @@ static void onenand_check_features(struct mtd_info *mtd)
>
> Reverse-order review, second hunk first:
>
> > case ONENAND_DEVICE_DENSITY_2Gb:
> > /* 2Gb DDP does not have 2 plane */
> > if (!ONENAND_IS_DDP(this))
> > this->options |= ONENAND_HAS_2PLANE;
> > this->options |= ONENAND_HAS_UNLOCK_ALL;
> > + /* Fall through - ? */
> >
> > case ONENAND_DEVICE_DENSITY_1Gb:
> > /* A-Die has all block unlock */
>
> So, I think the ONENAND_DEVICE_DENSITY_2Gb should be a "break". Though,
> actually, it doesn't matter:
>
> case ONENAND_DEVICE_DENSITY_2Gb:
> /* 2Gb DDP does not have 2 plane */
> if (!ONENAND_IS_DDP(this))
> this->options |= ONENAND_HAS_2PLANE;
> this->options |= ONENAND_HAS_UNLOCK_ALL;
>
> case ONENAND_DEVICE_DENSITY_1Gb:
> /* A-Die has all block unlock */
> if (process)
> this->options |= ONENAND_HAS_UNLOCK_ALL;
> break;
>
> Falling through from ONENAND_DEVICE_DENSITY_2Gb to
> ONENAND_DEVICE_DENSITY_1Gb will actually have no side-effects:
> ONENAND_HAS_UNLOCK_ALL was unconditionally set in ..._2Gb, so there is
> no reason to fall through to ..._1Gb. (But falling through is harmless.)
>
> Now the first hunk:
>
> > if ((this->version_id & 0xf) == 0xe)
> > this->options |= ONENAND_HAS_NOP_1;
> > }
> > + /* Fall through - ? */
> >
>
> case ONENAND_DEVICE_DENSITY_4Gb:
> if (ONENAND_IS_DDP(this))
> this->options |= ONENAND_HAS_2PLANE;
> else if (numbufs == 1) {
> this->options |= ONENAND_HAS_4KB_PAGE;
> this->options |= ONENAND_HAS_CACHE_PROGRAM;
> /*
> * There are two different 4KiB pagesize chips
> * and no way to detect it by H/W config values.
> *
> * To detect the correct NOP for each chips,
> * It should check the version ID as workaround.
> *
> * Now it has as following
> * KFM4G16Q4M has NOP 4 with version ID 0x0131
> * KFM4G16Q5M has NOP 1 with versoin ID 0x013e
> */
> if ((this->version_id & 0xf) == 0xe)
> this->options |= ONENAND_HAS_NOP_1;
> }
>
> Falling through from ONENAND_DEVICE_DENSITY_4Gb to
> ONENAND_DEVICE_DENSITY_2Gb looks like it would mean that
> ONENAND_HAS_2PLANE would be unconditionally set for ...4Gb, which seems
> very strange to expect:
>
> if (ONENAND_IS_DDP(this))
> this->options |= ONENAND_HAS_2PLANE;
> ...
> if (!ONENAND_IS_DDP(this))
> this->options |= ONENAND_HAS_2PLANE;
Oops, didn't notice the ! on the second test.
>
> However! This happens later:
>
> if (ONENAND_IS_4KB_PAGE(this))
> this->options &= ~ONENAND_HAS_2PLANE;
>
> i.e. falling through to ...2Gb (which sets ONENAND_HAS_2PLANE) has no
> effect because when ONENAND_HAS_2PLANE isn't set (numbufs == 1), it gets
> _cleared_ by the above code due to ONENAND_HAS_4KB_PAGE getting set:
Are you sure !DDP implies num_bufs == 1?
>
> #define ONENAND_IS_4KB_PAGE(this) \
> (this->options & ONENAND_HAS_4KB_PAGE)
>
>
> Unfortunately, though, it's less clear about ONENAND_HAS_UNLOCK_ALL,
> which is getting set unconditionally for ...4Gb currently (due to the
> fallthrough to ...2Gb). However, this happens later:
>
> if (FLEXONENAND(this)) {
> this->options &= ~ONENAND_HAS_CONT_LOCK;
> this->options |= ONENAND_HAS_UNLOCK_ALL;
> }
> ...
> #define FLEXONENAND(this) \
> (this->device_id & DEVICE_IS_FLEXONENAND)
>
> So it's possible this fall through has no effect (are all 4Gb density
> devices also FLEXONENAND devices?)
>
All this look suspicious, and even if the fall through logic
has no side effects in practice (which I'm still not sure is the case),
I think it'd be better to explicitly set the flags that have
to be set in each case statement and add breaks.
next prev parent reply other threads:[~2019-05-22 21:57 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-05-22 18:04 [PATCH] mtd: onenand_base: Avoid fall-through warnings Gustavo A. R. Silva
2019-05-22 18:04 ` Gustavo A. R. Silva
2019-05-22 21:30 ` Kees Cook
2019-05-22 21:30 ` Kees Cook
2019-05-22 21:57 ` Boris Brezillon [this message]
2019-05-22 21:57 ` Boris Brezillon
2019-05-22 22:20 ` Kees Cook
2019-05-22 22:20 ` Kees Cook
2019-05-22 22:30 ` Gustavo A. R. Silva
2019-05-22 22:30 ` Gustavo A. R. Silva
2019-05-22 21:37 ` Boris Brezillon
2019-05-22 21:37 ` Boris Brezillon
2019-05-22 21:45 ` Kees Cook
2019-05-22 21:45 ` Kees Cook
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190522235738.68059906@collabora.com \
--to=boris.brezillon@collabora.com \
--cc=computersforpeace@gmail.com \
--cc=dwmw2@infradead.org \
--cc=gustavo@embeddedor.com \
--cc=keescook@chromium.org \
--cc=kyungmin.park@samsung.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mtd@lists.infradead.org \
--cc=marek.vasut@gmail.com \
--cc=miquel.raynal@bootlin.com \
--cc=richard@nod.at \
--cc=vigneshr@ti.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.