<div dir="ltr"><div>While testing the old code, IBM identified the issue and came up with that patch, that they are now bringing upstream.<br>The patch was already tested by IBM, but</div>I provided a patched kernel based on Ubuntu (focal) master-next on top for further testing:<div><a href="https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1882088/comments/12">https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1882088/comments/12</a></div><div>and I'm expecting some feedback from the initial reporter (IBM) on that, too.</div><div><br></div><div>Thx, Frank<br><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Jul 13, 2020 at 9:20 AM Stefan Bader <<a href="mailto:stefan.bader@canonical.com">stefan.bader@canonical.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 10.07.20 21:21, <a href="mailto:frank.heimes@canonical.com" target="_blank">frank.heimes@canonical.com</a> wrote:<br>
> From: Ursula Braun <<a href="mailto:ubraun@linux.ibm.com" target="_blank">ubraun@linux.ibm.com</a>><br>
> <br>
> BugLink: <a href="https://bugs.launchpad.net/bugs/1882088" rel="noreferrer" target="_blank">https://bugs.launchpad.net/bugs/1882088</a><br>
> <br>
> CLC proposal messages of future SMCD versions could be larger than SMCD<br>
> V1 CLC proposal messages.<br>
> To enable toleration in SMC V1 the receival of CLC proposal messages<br>
> is adapted:<br>
> * accept larger length values in CLC proposal<br>
> * check trailing eye catcher for incoming CLC proposal with V1 length only<br>
> * receive the whole CLC proposal even in cases it does not fit into the<br>
>   V1 buffer<br>
> <br>
> Fixes: e7b7a64a8493d ("smc: support variable CLC proposal messages")<br>
> Signed-off-by: Ursula Braun <<a href="mailto:ubraun@linux.ibm.com" target="_blank">ubraun@linux.ibm.com</a>><br>
> Signed-off-by: Karsten Graul <<a href="mailto:kgraul@linux.ibm.com" target="_blank">kgraul@linux.ibm.com</a>><br>
> Signed-off-by: David S. Miller <<a href="mailto:davem@davemloft.net" target="_blank">davem@davemloft.net</a>><br>
> (cherry picked from commit fb4f79264c0fc6fd5a68ffe3e31bfff97311e1f1i linux-next)<br>
> Signed-off-by: Frank Heimes <<a href="mailto:frank.heimes@canonical.com" target="_blank">frank.heimes@canonical.com</a>><br>
Acked-by: Stefan Bader <<a href="mailto:stefan.bader@canonical.com" target="_blank">stefan.bader@canonical.com</a>><br>
> ---<br>
<br>
I am a bit torn here. Though not extremely large, I find it hard to decide about<br>
risk based on the delta. And it is common code that is changed. On the positive<br>
side it is queued upstream, but that not necessarily means it is without flaws.<br>
Have been (or will there be) tests of the new code using the old version (if<br>
that is possible), old and new, and both new?<br>
<br>
-Stefan<br>
<br>
>  net/smc/smc_clc.c | 45 ++++++++++++++++++++++++w ++++++++-------------<br>
>  net/smc/smc_clc.h |  4 ++++<br>
>  2 files changed, 36 insertions(+), 13 deletions(-)<br>
> <br>
> diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c<br>
> index aee9ccfa99c2..640cce262015 100644<br>
> --- a/net/smc/smc_clc.c<br>
> +++ b/net/smc/smc_clc.c<br>
> @@ -27,6 +27,7 @@<br>
>  <br>
>  #define SMCR_CLC_ACCEPT_CONFIRM_LEN 68<br>
>  #define SMCD_CLC_ACCEPT_CONFIRM_LEN 48<br>
> +#define SMC_CLC_RECV_BUF_LEN 100<br>
>  <br>
>  /* eye catcher "SMCR" EBCDIC for CLC messages */<br>
>  static const char SMC_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xd9'};<br>
> @@ -36,7 +37,7 @@ static const char SMCD_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xc4'};<br>
>  /* check if received message has a correct header length and contains valid<br>
>   * heading and trailing eyecatchers<br>
>   */<br>
> -static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)<br>
> +static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm, bool check_trl)<br>
>  {<br>
>       struct smc_clc_msg_proposal_prefix *pclc_prfx;<br>
>       struct smc_clc_msg_accept_confirm *clc;<br>
> @@ -49,12 +50,9 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)<br>
>               return false;<br>
>       switch (clcm->type) {<br>
>       case SMC_CLC_PROPOSAL:<br>
> -             if (clcm->path != SMC_TYPE_R && clcm->path != SMC_TYPE_D &&<br>
> -                 clcm->path != SMC_TYPE_B)<br>
> -                     return false;<br>
>               pclc = (struct smc_clc_msg_proposal *)clcm;<br>
>               pclc_prfx = smc_clc_proposal_get_prefix(pclc);<br>
> -             if (ntohs(pclc->hdr.length) !=<br>
> +             if (ntohs(pclc->hdr.length) <<br>
>                       sizeof(*pclc) + ntohs(pclc->iparea_offset) +<br>
>                       sizeof(*pclc_prfx) +<br>
>                       pclc_prfx->ipv6_prefixes_cnt *<br>
> @@ -86,7 +84,8 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)<br>
>       default:<br>
>               return false;<br>
>       }<br>
> -     if (memcmp(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) &&<br>
> +     if (check_trl &&<br>
> +         memcmp(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) &&<br>
>           memcmp(trl->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER)))<br>
>               return false;<br>
>       return true;<br>
> @@ -276,7 +275,8 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,<br>
>       struct msghdr msg = {NULL, 0};<br>
>       int reason_code = 0;<br>
>       struct kvec vec = {buf, buflen};<br>
> -     int len, datlen;<br>
> +     int len, datlen, recvlen;<br>
> +     bool check_trl = true;<br>
>       int krflags;<br>
>  <br>
>       /* peek the first few bytes to determine length of data to receive<br>
> @@ -320,10 +320,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,<br>
>       }<br>
>       datlen = ntohs(clcm->length);<br>
>       if ((len < sizeof(struct smc_clc_msg_hdr)) ||<br>
> -         (datlen > buflen) ||<br>
> -         (clcm->version != SMC_CLC_V1) ||<br>
> -         (clcm->path != SMC_TYPE_R && clcm->path != SMC_TYPE_D &&<br>
> -          clcm->path != SMC_TYPE_B) ||<br>
> +         (clcm->version < SMC_CLC_V1) ||<br>
>           ((clcm->type != SMC_CLC_DECLINE) &&<br>
>            (clcm->type != expected_type))) {<br>
>               smc->sk.sk_err = EPROTO;<br>
> @@ -331,16 +328,38 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,<br>
>               goto out;<br>
>       }<br>
>  <br>
> +     if (clcm->type == SMC_CLC_PROPOSAL && clcm->path == SMC_TYPE_N)<br>
> +             reason_code = SMC_CLC_DECL_VERSMISMAT; /* just V2 offered */<br>
> +<br>
>       /* receive the complete CLC message */<br>
>       memset(&msg, 0, sizeof(struct msghdr));<br>
> -     iov_iter_kvec(&msg.msg_iter, READ, &vec, 1, datlen);<br>
> +     if (datlen > buflen) {<br>
> +             check_trl = false;<br>
> +             recvlen = buflen;<br>
> +     } else {<br>
> +             recvlen = datlen;<br>
> +     }<br>
> +     iov_iter_kvec(&msg.msg_iter, READ, &vec, 1, recvlen);<br>
>       krflags = MSG_WAITALL;<br>
>       len = sock_recvmsg(smc->clcsock, &msg, krflags);<br>
> -     if (len < datlen || !smc_clc_msg_hdr_valid(clcm)) {<br>
> +     if (len < recvlen || !smc_clc_msg_hdr_valid(clcm, check_trl)) {<br>
>               smc->sk.sk_err = EPROTO;<br>
>               reason_code = -EPROTO;<br>
>               goto out;<br>
>       }<br>
> +     datlen -= len;<br>
> +     while (datlen) {<br>
> +             u8 tmp[SMC_CLC_RECV_BUF_LEN];<br>
> +<br>
> +             vec.iov_base = &tmp;<br>
> +             vec.iov_len = SMC_CLC_RECV_BUF_LEN;<br>
> +             /* receive remaining proposal message */<br>
> +             recvlen = datlen > SMC_CLC_RECV_BUF_LEN ?<br>
> +                                             SMC_CLC_RECV_BUF_LEN : datlen;<br>
> +             iov_iter_kvec(&msg.msg_iter, READ, &vec, 1, recvlen);<br>
> +             len = sock_recvmsg(smc->clcsock, &msg, krflags);<br>
> +             datlen -= len;<br>
> +     }<br>
>       if (clcm->type == SMC_CLC_DECLINE) {<br>
>               struct smc_clc_msg_decline *dclc;<br>
>  <br>
> diff --git a/net/smc/smc_clc.h b/net/smc/smc_clc.h<br>
> index ca209272e5fa..76c2b150d040 100644<br>
> --- a/net/smc/smc_clc.h<br>
> +++ b/net/smc/smc_clc.h<br>
> @@ -25,6 +25,7 @@<br>
>  #define SMC_CLC_V1           0x1             /* SMC version                */<br>
>  #define SMC_TYPE_R           0               /* SMC-R only                 */<br>
>  #define SMC_TYPE_D           1               /* SMC-D only                 */<br>
> +#define SMC_TYPE_N           2               /* neither SMC-R nor SMC-D    */<br>
>  #define SMC_TYPE_B           3               /* SMC-R and SMC-D            */<br>
>  #define CLC_WAIT_TIME                (6 * HZ)        /* max. wait time on clcsock  */<br>
>  #define CLC_WAIT_TIME_SHORT  HZ              /* short wait time on clcsock */<br>
> @@ -44,6 +45,9 @@<br>
>  #define SMC_CLC_DECL_DIFFPREFIX      0x03070000  /* IP prefix / subnet mismatch    */<br>
>  #define SMC_CLC_DECL_GETVLANERR      0x03080000  /* err to get vlan id of ip device*/<br>
>  #define SMC_CLC_DECL_ISMVLANERR      0x03090000  /* err to reg vlan id on ism dev  */<br>
> +#define SMC_CLC_DECL_NOACTLINK       0x030a0000  /* no active smc-r link in lgr    */<br>
> +#define SMC_CLC_DECL_NOSRVLINK       0x030b0000  /* SMC-R link from srv not found  */<br>
> +#define SMC_CLC_DECL_VERSMISMAT      0x030c0000  /* SMC version mismatch           */<br>
>  #define SMC_CLC_DECL_SYNCERR 0x04000000  /* synchronization error          */<br>
>  #define SMC_CLC_DECL_PEERDECL        0x05000000  /* peer declined during handshake */<br>
>  #define SMC_CLC_DECL_INTERR  0x09990000  /* internal error                 */<br>
> <br>
<br>
<br>
</blockquote></div>