From: "zhangjian (CG)" <zhangjian496@huawei.com>
To: Scott Mayhew <smayhew@redhat.com>
Cc: <sorenson@redhat.com>, <s.ikarashi@fujitsu.com>,
<jlayton@kernel.org>, <steved@redhat.com>,
<linux-nfs@vger.kernel.org>
Subject: Re: [PATCH v2] nfsdcld: fix cld pipe read size
Date: Wed, 26 Feb 2025 12:30:48 +0800 [thread overview]
Message-ID: <9308fbc6-bfca-4e8e-ad09-f9f5d87d782e@huawei.com> (raw)
In-Reply-To: <Z721I_6o2BDfHHqG@aion>
Thank for review, I will make my v3 patch
On Tue, 25 Feb 2025, Scott Mayhew wrote:
> You still have some line wrapping issues. Your commit message should
> generally have line breaks at 80 characters or less. Fix that and the
> other issue below and you can add
>
> Reviewed-by: Scott Mayhew <smayhew@redhat.com>
>
> On Mon, 24 Feb 2025, zhangjian (CG) wrote:
>
>> When nfsd inits failed for detecting cld version in nfsd4_client_tracking_init, kernel may assume nfsdcld support version 1 message format and try to upcall with v1 message size to nfsdcld. There exists one error case in the following process, causeing nfsd hunging for nfsdcld replay:
>>
>> kernel write to pipe->msgs (v1 msg length)
>> |--------- first msg --------|-------- second message -------|
>>
>> nfsdcld read from pipe->msgs (v2 msg length)
>> |------------ first msg --------------|---second message-----|
>> | valid message | ignore | wrong message |
>>
>> When two nfsd kernel thread add two upcall messages to cld pipe with v1 version cld_msg (size == 1034) concurrently,but nfsdcld reads with v2 version size(size == 1067), 33 bytes of the second message will be read and merged with first message. The 33 bytes in second message will be ignored. Nfsdcld will then read 1001 bytes in second message, which cause FATAL in cld_messaged_size checking. Nfsd kernel thread will hang for it forever until nfs server restarts.
>>
>> Signed-off-by: zhangjian <zhangjian496@huawei.com>
>> ---
>> utils/nfsdcld/nfsdcld.c | 63 ++++++++++++++++++++++++++++-------------
>> 1 file changed, 43 insertions(+), 20 deletions(-)
>>
>> diff --git a/utils/nfsdcld/nfsdcld.c b/utils/nfsdcld/nfsdcld.c
>> index dbc7a57..76308d1 100644
>> --- a/utils/nfsdcld/nfsdcld.c
>> +++ b/utils/nfsdcld/nfsdcld.c
>> @@ -716,35 +716,58 @@ reply:
>> }
>> }
>>
>> +static int cld_pipe_read_msg(struct cld_client *clnt) {
>> + ssize_t len, left_len;
>> + ssize_t hdr_len = sizeof(struct cld_msg_hdr);
>> + struct cld_msg_hdr *hdr = (struct cld_msg_hdr *)&clnt->cl_u;;
>> +
>> + len = atomicio(read, clnt->cl_fd, hdr, hdr_len);
>> +
>> + if (len <= 0) {
>> + xlog(L_ERROR, "%s: pipe read failed: %m", __func__);
>> + goto fail_read;
>> + }
>> +
>> + switch (hdr->cm_vers) {
>> + case 1:
>> + left_len = sizeof(struct cld_msg) - hdr_len;
>> + break;
>> + case 2:
>> + left_len = sizeof(struct cld_msg_v2) - hdr_len;
>> + break;
>> + default:
>> + xlog(L_ERROR, "%s: unsupported upcall version: %hu",
>> + __func__, hdr->cm_vers);
>
> and this line needs to be indented way less ^^^
>
>> + goto fail_read;
>> + }
>> +
>> + len = atomicio(read, clnt->cl_fd, hdr, left_len);
>> +
>> + if (len <= 0) {
>> + xlog(L_ERROR, "%s: pipe read failed: %m", __func__);
>> + goto fail_read;
>> + }
>> +
>> + return 0;
>> +
>> +fail_read:
>> + cld_pipe_open(clnt);
>> + return -1;
>> +}
>> +
>> static void
>> cldcb(int UNUSED(fd), short which, void *data)
>> {
>> - ssize_t len;
>> struct cld_client *clnt = data;
>> -#if UPCALL_VERSION >= 2
>> - struct cld_msg_v2 *cmsg = &clnt->cl_u.cl_msg_v2;
>> -#else
>> - struct cld_msg *cmsg = &clnt->cl_u.cl_msg;
>> -#endif
>> + struct cld_msg_hdr *hdr = (struct cld_msg_hdr *)&clnt->cl_u;
>>
>> if (which != EV_READ)
>> goto out;
>>
>> - len = atomicio(read, clnt->cl_fd, cmsg, sizeof(*cmsg));
>> - if (len <= 0) {
>> - xlog(L_ERROR, "%s: pipe read failed: %m", __func__);
>> - cld_pipe_open(clnt);
>> + if (cld_pipe_read_msg(clnt) < 0)
>> goto out;
>> - }
>> -
>> - if (cmsg->cm_vers > UPCALL_VERSION) {
>> - xlog(L_ERROR, "%s: unsupported upcall version: %hu",
>> - __func__, cmsg->cm_vers);
>> - cld_pipe_open(clnt);
>> - goto out;
>> - }
>>
>> - switch(cmsg->cm_cmd) {
>> + switch (hdr->cm_cmd) {
>> case Cld_Create:
>> cld_create(clnt);
>> break;
>> @@ -765,7 +788,7 @@ cldcb(int UNUSED(fd), short which, void *data)
>> break;
>> default:
>> xlog(L_WARNING, "%s: command %u is not yet implemented",
>> - __func__, cmsg->cm_cmd);
>> + __func__, hdr->cm_cmd);
>> cld_not_implemented(clnt);
>> }
>> out:
>> --
>> 2.33.0
>>
>>
>
>
prev parent reply other threads:[~2025-02-26 4:30 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <07ba7ede-5127-4978-9195-26c3d04679c4@huawei.com>
[not found] ` <cfa8c2a3-4e2d-45c8-a605-c66d92412d41@huawei.com>
[not found] ` <277a7a65-0aea-496c-beb5-e4b6f6afc10e@huawei.com>
2025-02-25 8:22 ` [PATCH v2] nfsdcld: fix cld pipe read size zhangjian (CG)
2025-02-25 12:21 ` Scott Mayhew
2025-02-26 4:09 ` zhangjian (CG)
2025-02-26 4:28 ` zhangjian (CG)
[not found] ` <Z721I_6o2BDfHHqG@aion>
2025-02-26 4:30 ` zhangjian (CG) [this message]
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=9308fbc6-bfca-4e8e-ad09-f9f5d87d782e@huawei.com \
--to=zhangjian496@huawei.com \
--cc=jlayton@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=s.ikarashi@fujitsu.com \
--cc=smayhew@redhat.com \
--cc=sorenson@redhat.com \
--cc=steved@redhat.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox