Re: Patch "[PATCH 1/2] Revert "md: change mddev 'chunk_sectors' from int to" has been added to the 5.10-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Dec 14, 2020 at 1:49 PM Song Liu <songliubraving@xxxxxx> wrote:
>
> Here is the root cause of this issue.
>
> We miss a cast to sector_t in raid5_run(). The fix is:
>
> diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
> index 39343479ac2a9..ca0b29ac9d9a8 100644
> --- a/drivers/md/raid5.c
> +++ b/drivers/md/raid5.c
> @@ -7662,7 +7662,7 @@ static int raid5_run(struct mddev *mddev)
>         }
>
>         /* device size must be a multiple of chunk size */
> -       mddev->dev_sectors &= ~(mddev->chunk_sectors - 1);
> +       mddev->dev_sectors &= ~((sector_t)mddev->chunk_sectors - 1);
>         mddev->resync_max_sectors = mddev->dev_sectors;
>
>         if (mddev->degraded > dirty_parity_disks &&

Ok, so this made me go "Hmm, this might be a pattern to look out for".
It's zero-extending a binary 'not', which means that the 'not' only
did low bits, and the zero-extended bits weren't set.

That is probably fine in many situations, but it also does smell like
a problem case. It's one reason why the kernel uses signed types for
some fundamental constants - look at PAGE_SIZE for example. Exactly
because ~(PAGE_SIZE-1) needs to set all the high bits.

Anyway, since I have nothing better to do during the merge window
(hah!) I tried to see if I can come up with a sparse check for this
situation.

Here is my very quick hack to sparse, which I'm just throwing over the
fence to Luc and others to look at (because I still have a _lot_ of
pulls to go through), but it does actually flag the problem in 5.10:

   drivers/md/raid5.c:7665:56: warning: zero-extending a negation -
upper bits not negated

although I'm not entirely sure this won't cause way too many other
warnings for things that are very valid.

So it looks like the warning will be too noisy to be actually useful.

But because it _does_ flag that thing, and because I'm too busy to see
if it might be useful with some more work, I'll just post it here and
see if somebody wants to play with it.

            Linus
 linearize.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/linearize.c b/linearize.c
index 0250c6bb..b1a18219 100644
--- a/linearize.c
+++ b/linearize.c
@@ -2520,6 +2520,25 @@ static void check_tainted_insn(struct instruction *insn)
 	}
 }
 
+static void check_zero_extend(struct instruction *insn)
+{
+	struct instruction *def;
+	pseudo_t src = insn->src1;
+
+	if (src->type != PSEUDO_REG)
+		return;
+	def = src->def;
+	if (!def)
+		return;
+	switch (def->opcode) {
+	case OP_NEG: case OP_NOT:
+		warning(insn->pos, "zero-extending a negation - upper bits not negated");
+		break;
+	default:
+		break;
+	}
+}
+
 ///
 // issue warnings after all possible DCE
 static void late_warnings(struct entrypoint *ep)
@@ -2537,6 +2556,10 @@ static void late_warnings(struct entrypoint *ep)
 				// Check for illegal offsets.
 				check_access(insn);
 				break;
+			case OP_ZEXT:
+				// Check for missing sign extension..
+				check_zero_extend(insn);
+				break;
 			}
 		} END_FOR_EACH_PTR(insn);
 	} END_FOR_EACH_PTR(bb);

[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux