<div class="__aliyun_email_body_block"><div  style="line-height:1.7;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;color:#000000;"><div  style="clear:both;">Thanks a lot.</div><div  style="clear:both;"><br ></div><div  style="clear:both;">I will send you another version soon.</div><div  style="clear:both;"><br ></div><div  style="clear:both;">BTW: I do believe these functions should be split into a function family. It's really hard to call them correctly and hard to debug as well.</div><div  style="clear:both;"><br ></div><div  style="clear:both;">Aiden Leong</div><div  style="clear:both;"><br /></div><blockquote  style="margin-right:0;margin-top:0;margin-bottom:0;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;color:#000000;"><div  style="clear:both;">------------------------------------------------------------------</div><div  style="clear:both;">From:Kees Cook <keescook@chromium.org></div><div  style="clear:both;">Send Time:2020年6月25日(星期四) 13:35</div><div  style="clear:both;">To:Aiden Leong <aiden.leong@aibsd.com></div><div  style="clear:both;">Cc:Gustavo A. R. Silva <gustavo@embeddedor.com>; Thomas Gleixner <tglx@linutronix.de>; Ferdinand Blomqvist <ferdinand.blomqvist@gmail.com>; YueHaibing <yuehaibing@huawei.com>; dm-devel <dm-devel@redhat.com>; linux-kernel <linux-kernel@vger.kernel.org>; Alasdair Kergon <agk@redhat.com>; Mike Snitzer <snitzer@redhat.com>; Anton Vorontsov <anton@enomsg.org>; Colin Cross <ccross@android.com>; Tony Luck <tony.luck@intel.com></div><div  style="clear:both;">Subject:Re: [RFC] Reed-Solomon Code: Update no_eras to the actual number of errors</div><div  style="clear:both;"><br /></div>On Wed, Jun 24, 2020 at 09:10:53PM -0700, Aiden Leong wrote:<br >> Corr and eras_pos are updated to actual correction pattern and erasure<br >> positions, but no_eras is not.<br >> <br >> When this library is used to recover lost bytes, we normally memset the<br >> lost trunk of bytes to zero as a placeholder. Unfortunately, if the lost<br >> byte is zero, b[i] is zero too. Without correct no_eras, users won't be<br >> able to determine the valid length of corr and eras_pos.<br >> <br >> Signed-off-by: Aiden Leong <aiden.leong@aibsd.com><br >> ---<br >>  drivers/md/dm-verity-fec.c      |  2 +-<br >>  fs/pstore/ram_core.c            |  2 +-<br >>  include/linux/rslib.h           |  4 ++--<br >>  lib/reed_solomon/decode_rs.c    | 20 ++++++++++++++------<br >>  lib/reed_solomon/reed_solomon.c |  4 ++--<br >>  lib/reed_solomon/test_rslib.c   | 18 ++++++++++++------<br >>  6 files changed, 32 insertions(+), 18 deletions(-)<br >> <br >> diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c<br >> index fb41b4f23c48..ae8366a50244 100644<br >> --- a/drivers/md/dm-verity-fec.c<br >> +++ b/drivers/md/dm-verity-fec.c<br >> @@ -50,7 +50,7 @@ static int fec_decode_rs8(struct dm_verity *v, struct dm_verity_fec_io *fio,<br >>   for (i = 0; i < v->fec->roots; i++)<br >>    par[i] = fec[i];<br >>  <br >> - return decode_rs8(fio->rs, data, par, v->fec->rsn, NULL, neras,<br >> + return decode_rs8(fio->rs, data, par, v->fec->rsn, NULL, &neras,<br >>       fio->erasures, 0, NULL);<br >>  }<br >>  <br >> diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c<br >> index aa8e0b65ff1a..fcc661a60640 100644<br >> --- a/fs/pstore/ram_core.c<br >> +++ b/fs/pstore/ram_core.c<br >> @@ -115,7 +115,7 @@ static int persistent_ram_decode_rs8(struct persistent_ram_zone *prz,<br >>  <br >>   for (i = 0; i < prz->ecc_info.ecc_size; i++)<br >>    prz->ecc_info.par[i] = ecc[i];<br >> - return decode_rs8(prz->rs_decoder, data, prz->ecc_info.par, len,<br >> + return decode_rs8(prz->rs_decoder, data, prz->ecc_info.par, &len,<br >>      NULL, 0, NULL, 0, NULL);<br ><br >This looks like the wrong arg changed -- did you compile test this?<br ><br >>  }<br >>  <br >> diff --git a/include/linux/rslib.h b/include/linux/rslib.h<br >> index 238bb85243d3..80662abc9af7 100644<br >> --- a/include/linux/rslib.h<br >> +++ b/include/linux/rslib.h<br >> @@ -64,7 +64,7 @@ int encode_rs8(struct rs_control *rs, uint8_t *data, int len, uint16_t *par,<br >>  #endif<br >>  #ifdef CONFIG_REED_SOLOMON_DEC8<br >>  int decode_rs8(struct rs_control *rs, uint8_t *data, uint16_t *par, int len,<br >> -  uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk,<br >> +  uint16_t *s, int *no_eras, int *eras_pos, uint16_t invmsk,<br >>          uint16_t *corr);<br >>  #endif<br >>  <br >> @@ -75,7 +75,7 @@ int encode_rs16(struct rs_control *rs, uint16_t *data, int len, uint16_t *par,<br >>  #endif<br >>  #ifdef CONFIG_REED_SOLOMON_DEC16<br >>  int decode_rs16(struct rs_control *rs, uint16_t *data, uint16_t *par, int len,<br >> -  uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk,<br >> +  uint16_t *s, int *no_eras, int *eras_pos, uint16_t invmsk,<br >>    uint16_t *corr);<br >>  #endif<br >>  <br >> diff --git a/lib/reed_solomon/decode_rs.c b/lib/reed_solomon/decode_rs.c<br >> index 805de84ae83d..122bc08eb75f 100644<br >> --- a/lib/reed_solomon/decode_rs.c<br >> +++ b/lib/reed_solomon/decode_rs.c<br >> @@ -24,6 +24,7 @@<br >>   int count = 0;<br >>   int num_corrected;<br >>   uint16_t msk = (uint16_t) rs->nn;<br >> + int no_eras_orig = no_eras ? *no_eras : 0;<br ><br >To avoid code churn, I would name this int no_eras, and change the arg<br >to something like no_eras_ptr:<br ><br > int no_eras = no_eras_ptr ? *no_eras_ptr : 0;<br ><br >>  <br >>   /*<br >>    * The decoder buffers are in the rs control struct. They are<br >> @@ -106,11 +107,11 @@<br >>   memset(&lambda[1], 0, nroots * sizeof(lambda[0]));<br >>   lambda[0] = 1;<br >>  <br >> - if (no_eras > 0) {<br >> + if (no_eras_orig > 0) {<br >>    /* Init lambda to be the erasure locator polynomial */<br >>    lambda[1] = alpha_to[rs_modnn(rs,<br >>       prim * (nn - 1 - (eras_pos[0] + pad)))];<br >> -  for (i = 1; i < no_eras; i++) {<br >> +  for (i = 1; i < no_eras_orig; i++) {<br >>     u = rs_modnn(rs, prim * (nn - 1 - (eras_pos[i] + pad)));<br >>     for (j = i + 1; j > 0; j--) {<br >>      tmp = index_of[lambda[j - 1]];<br >> @@ -129,8 +130,8 @@<br >>    * Begin Berlekamp-Massey algorithm to determine error+erasure<br >>    * locator polynomial<br >>    */<br >> - r = no_eras;<br >> - el = no_eras;<br >> + r = no_eras_orig;<br >> + el = no_eras_orig;<br >>   while (++r <= nroots) { /* r is the step number */<br >>    /* Compute discrepancy at the r-th step in poly-form */<br >>    discr_r = 0;<br >> @@ -158,8 +159,8 @@<br >>      } else<br >>       t[i + 1] = lambda[i + 1];<br >>     }<br >> -   if (2 * el <= r + no_eras - 1) {<br >> -    el = r + no_eras - el;<br >> +   if (2 * el <= r + no_eras_orig - 1) {<br >> +    el = r + no_eras_orig - el;<br >>      /*<br >>       * 2 lines below: B(x) <-- inv(discr_r) *<br >>       * lambda(x)<br >> @@ -312,14 +313,21 @@<br >>      eras_pos[j++] = loc[i] - pad;<br >>     }<br >>    }<br >> +  if (no_eras > 0)<br >> +   *no_eras = j;<br ><br >Is this meant to be "if (j > 0)" or "if (no_eras != NULL)" ? It's<br >uncommon to use > 0 for a pointer value.<br ><br >>   } else if (data && par) {<br >>    /* Apply error to data and parity */<br >> +  j = 0;<br >>    for (i = 0; i < count; i++) {<br >>     if (loc[i] < (nn - nroots))<br >>      data[loc[i] - pad] ^= b[i];<br >>     else<br >>      par[loc[i] - pad - len] ^= b[i];<br >> +   if (b[i])<br >> +    j++;<br >>    }<br >> +  if (no_eras > 0)<br >> +   *no_eras = j;<br ><br >I assume it's a pointer test, so both would be:<br ><br >  if (no_eras_ptr != NULL)<br >   *no_eras_ptr = j;<br ><br >>   }<br >>  <br >>   return  num_corrected;<br >> diff --git a/lib/reed_solomon/reed_solomon.c b/lib/reed_solomon/reed_solomon.c<br >> index bbc01bad3053..b2c811674c98 100644<br >> --- a/lib/reed_solomon/reed_solomon.c<br >> +++ b/lib/reed_solomon/reed_solomon.c<br >> @@ -359,7 +359,7 @@ EXPORT_SYMBOL_GPL(encode_rs8);<br >>   *  errors. The count includes errors in the parity.<br >>   */<br >>  int decode_rs8(struct rs_control *rsc, uint8_t *data, uint16_t *par, int len,<br >> -        uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk,<br >> +        uint16_t *s, int *no_eras, int *eras_pos, uint16_t invmsk,<br >>          uint16_t *corr)<br >>  {<br >>  #include "decode_rs.c"<br >> @@ -410,7 +410,7 @@ EXPORT_SYMBOL_GPL(encode_rs16);<br >>   *  errors. The count includes errors in the parity.<br >>   */<br >>  int decode_rs16(struct rs_control *rsc, uint16_t *data, uint16_t *par, int len,<br >> -  uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk,<br >> +  uint16_t *s, int *no_eras, int *eras_pos, uint16_t invmsk,<br >>    uint16_t *corr)<br >>  {<br >>  #include "decode_rs.c"<br >> diff --git a/lib/reed_solomon/test_rslib.c b/lib/reed_solomon/test_rslib.c<br >> index 4eb29f365ece..b30a4aea8796 100644<br >> --- a/lib/reed_solomon/test_rslib.c<br >> +++ b/lib/reed_solomon/test_rslib.c<br >> @@ -258,7 +258,7 @@ static void compute_syndrome(struct rs_control *rsc, uint16_t *data,<br >>  <br >>  /* Test up to error correction capacity */<br >>  static void test_uc(struct rs_control *rs, int len, int errs,<br >> -  int eras, int trials, struct estat *stat,<br >> +  int *eras, int trials, struct estat *stat,<br >>    struct wspace *ws, int method)<br >>  {<br >>   int dlen = len - rs->codec->nroots;<br >> @@ -327,8 +327,11 @@ static int ex_rs_helper(struct rs_control *rs, struct wspace *ws,<br >>    pr_info("  %s\n", desc[method]);<br >>  <br >>   for (errs = 0; errs <= nroots / 2; errs++)<br >> -  for (eras = 0; eras <= nroots - 2 * errs; eras++)<br >> -   test_uc(rs, len, errs, eras, trials, &stat, ws, method);<br >> +  for (eras = 0; eras <= nroots - 2 * errs; eras++) {<br >> +   int no_eras = ers;<br >> +<br >> +   test_uc(rs, len, errs, &no_eras, trials, &stat, ws, method);<br >> +  }<br >>  <br >>   if (v >= V_CSUMMARY) {<br >>    pr_info("    Decodes wrong:        %d / %d\n",<br >> @@ -364,7 +367,7 @@ static int exercise_rs(struct rs_control *rs, struct wspace *ws,<br >>  <br >>  /* Tests for correct behaviour beyond error correction capacity */<br >>  static void test_bc(struct rs_control *rs, int len, int errs,<br >> -  int eras, int trials, struct bcstat *stat,<br >> +  int *eras, int trials, struct bcstat *stat,<br >>    struct wspace *ws)<br >>  {<br >>   int nroots = rs->codec->nroots;<br >> @@ -420,8 +423,11 @@ static int exercise_rs_bc(struct rs_control *rs, struct wspace *ws,<br >>     eras = 0;<br >>  <br >>    cutoff = nroots <= len - errs ? nroots : len - errs;<br >> -  for (; eras <= cutoff; eras++)<br >> -   test_bc(rs, len, errs, eras, trials, &stat, ws);<br >> +  for (; eras <= cutoff; eras++) {<br >> +   int no_eras = eras;<br >> +<br >> +   test_bc(rs, len, errs, &no_eras, trials, &stat, ws);<br >> +  }<br >>   }<br >>  <br >>   if (v >= V_CSUMMARY) {<br >> -- <br >> 2.25.1<br >> <br ><br >Otherwise, yeah, cool. Looks good.<br ><br >-- <br >Kees Cook</blockquote></div></div>