From patchwork Tue Dec 31 00:28:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13923567 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D1C4479F5 for ; Tue, 31 Dec 2024 00:29:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735604946; cv=none; b=qnFJLfPFoPnoIIuqIiQsGe33HE4ACJZErr9thIUYCBRP3MpfmXIyMn2Ba6WOZ/8+2rlZLttFRPTlPvrvmGmKVmB6WW8UC2IQiEo8JSVgkEvD1T0D6gVobdhSoWsLx9SxG1Av+PETmQkaBaEPL/I7Bv5Uehjz4bW4kS+FFdq0aBo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735604946; c=relaxed/simple; bh=GQwAtmkyCs6amxoVHXGz+jecKwg86jAnP7qW6+XwFGI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=A40ZlPZVUrD5PIjluX/cY2us2L0Lw2pWQITzyxytA/VcHcPTP69I45X4kc2Z6ptRNpR5U8abeQWa9eFa9un3PsxbsRzYZNGp3UZ1TYZd4Fr3+KDREiJ6GN1XEGgSc953U+QjNhg4JQLBuAYPsknDEQBhwWN7FkUzkYctYmgftDg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Nrw2vjnA; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Nrw2vjnA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 82E78C4CED7; Tue, 31 Dec 2024 00:29:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1735604946; bh=GQwAtmkyCs6amxoVHXGz+jecKwg86jAnP7qW6+XwFGI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Nrw2vjnAfWu3Ex8yZPzWhJuUlpiBPVMtUpTwmi+HX9qS9BKLO41fhtezI81O8zlyz 8GDdgdIadp8R5mXf/NueoEBdEH3+yC1ep+y+rLWDkrgua9OlnAt32vjf4E4RLJmZX+ xTQanJSIICzz0F1KJXafJpDYLld0ANMY+4kXH2cf/f0QiCKC2yy0T/g3nkneax5+n0 WAAaDCtNPZSVrS5kW0A3JTshs6gaWZ6Qpn5oe+Pzdh95/DhQyN3UoPTi3R7HAU/17w Yrr3+zNeXZcoHWum034cCUkH1K1IGbVzpK4ZyyqVHdxiDuMXIxhKDcwOOLtEWQR2Z0 pyyEuowVHp/pw== From: cel@kernel.org To: Neil Brown , Jeff Layton , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: , Rick Macklem , j.david.lists@gmail.com, Chuck Lever , Rick Macklem Subject: [PATCH v4 1/9] NFSD: Encode COMPOUND operation status on page boundaries Date: Mon, 30 Dec 2024 19:28:52 -0500 Message-ID: <20241231002901.12725-2-cel@kernel.org> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241231002901.12725-1-cel@kernel.org> References: <20241231002901.12725-1-cel@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Chuck Lever J. David reports an odd corruption of a READDIR reply sent to a FreeBSD client. xdr_reserve_space() has to do a special trick when the @nbytes value requests more space than there is in the current page of the XDR buffer. In that case, xdr_reserve_space() returns a pointer to the start of the next page, and then the next call to xdr_reserve_space() invokes __xdr_commit_encode() to copy enough of the data item back into the previous page to make that data item contiguous across the page boundary. But we need to be careful in the case where buffer space is reserved early for a data item whose value will be inserted into the buffer later. One such caller, nfsd4_encode_operation(), reserves 8 bytes in the encoding buffer for each COMPOUND operation. However, a READDIR result can sometimes encode file names so that there are only 4 bytes left at the end of the current XDR buffer page (though plenty of pages are left to handle the remaining encoding tasks). If a COMPOUND operation follows the READDIR result (say, a GETATTR), then nfsd4_encode_operation() will reserve 8 bytes for the op number (9) and the op status (usually NFS4_OK). In this weird case, xdr_reserve_space() returns a pointer to byte zero of the next buffer page, as it assumes the data item will be copied back into place (in the previous page) on the next call to xdr_reserve_space(). nfsd4_encode_operation() writes the op num into the buffer, then saves the next 4-byte location for the op's status code. The next xdr_reserve_space() call is part of GETATTR encoding, so the op num gets copied back into the previous page, but the saved location for the op status continues to point to the wrong spot in the current XDR buffer page because __xdr_commit_encode() moved that data item. After GETATTR encoding is complete, nfsd4_encode_operation() writes the op status over the first XDR data item in the GETATTR result. The NFS4_OK status code (0) makes it look like there are zero items in the GETATTR's attribute bitmask. The patch description of commit 2825a7f90753 ("nfsd4: allow encoding across page boundaries") [2014] remarks that NFSD "can't handle a new operation starting close to the end of a page." This bug appears to be one reason for that remark. Reported-by: J David Closes: https://lore.kernel.org/linux-nfs/3998d739-c042-46b4-8166-dbd6c5f0e804@oracle.com/T/#t Tested-by: Rick Macklem Reviewed-by: NeilBrown X-Cc: stable@vger.kernel.org Signed-off-by: Chuck Lever --- fs/nfsd/nfs4xdr.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 53fac037611c..efcb132c19d4 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -5760,15 +5760,14 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) struct nfs4_stateowner *so = resp->cstate.replay_owner; struct svc_rqst *rqstp = resp->rqstp; const struct nfsd4_operation *opdesc = op->opdesc; - int post_err_offset; + unsigned int op_status_offset; nfsd4_enc encoder; - __be32 *p; - p = xdr_reserve_space(xdr, 8); - if (!p) + if (xdr_stream_encode_u32(xdr, op->opnum) != XDR_UNIT) + goto release; + op_status_offset = xdr_stream_pos(xdr); + if (!xdr_reserve_space(xdr, XDR_UNIT)) goto release; - *p++ = cpu_to_be32(op->opnum); - post_err_offset = xdr->buf->len; if (op->opnum == OP_ILLEGAL) goto status; @@ -5809,20 +5808,21 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) * bug if we had to do this on a non-idempotent op: */ warn_on_nonidempotent_op(op); - xdr_truncate_encode(xdr, post_err_offset); + xdr_truncate_encode(xdr, op_status_offset + XDR_UNIT); } if (so) { - int len = xdr->buf->len - post_err_offset; + int len = xdr->buf->len - (op_status_offset + XDR_UNIT); so->so_replay.rp_status = op->status; so->so_replay.rp_buflen = len; - read_bytes_from_xdr_buf(xdr->buf, post_err_offset, + read_bytes_from_xdr_buf(xdr->buf, op_status_offset + XDR_UNIT, so->so_replay.rp_buf, len); } status: op->status = nfsd4_map_status(op->status, resp->cstate.minorversion); - *p = op->status; + write_bytes_to_xdr_buf(xdr->buf, op_status_offset, + &op->status, XDR_UNIT); release: if (opdesc && opdesc->op_release) opdesc->op_release(&op->u); From patchwork Tue Dec 31 00:28:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13923568 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 94B5A8BEC for ; Tue, 31 Dec 2024 00:29:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735604947; cv=none; b=fidmt/2luTYRIlU4I+CovU1x0Dv2ad3PjmMNH8NQ1jkqY2ZBnT9dwS7WgcGr2y4p/YMAr6ef5tdDUEZJr6o6DASDWkjmA3I0dmhhS70G1rrWddWwD7j/L1RVmblS8W62hG9VWTl6XSrokYq6LrpTx8ZmGBE8CmUuVy0VKqVedlE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735604947; c=relaxed/simple; bh=mTzUny1CMezcW1PIxqv5iGaLn8avZ/ysicpu9dh07AM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OE+ySnKfdCUApuhKwLS2Jy8emiJoIsjCeAc6RasUZgRGQX9pCF1/LvoyJ+B+DxVOZ/gf+ScorkmgVBv5iQMpWvx566Lwchnw+ZctBFgscDjngeX/7qxBgL78ID5twNaZynZ3zY3nwLWjSEeETLljyOSpj7d4GGP1u2W43Dt7PGQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=B5mhl/sI; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="B5mhl/sI" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A5291C4CED0; Tue, 31 Dec 2024 00:29:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1735604947; bh=mTzUny1CMezcW1PIxqv5iGaLn8avZ/ysicpu9dh07AM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=B5mhl/sI02TDANz4b00g19fNaNIy5w4cCl7MnWc2JGNycSDElJyCXVnwbAp42/DnW 8EJgxIG10DqiLuKJlU6sar4GPquzTCbUso4XDvayhjirGNDvr7qJNutEbvGCZ6+Bwu U/tjbIJ2DNzin1MGh/T132F+Wz3hbhKxHgaPjzlkIHLAuuDK1+Y6q8KlnuShYpOWAt d+xBBjnaCDVw0p9IphNOT2wDL4R8KA9LuQCPM1T2P3lgUvIXWaHAA+q2oh6rHP/s+L dJ3W7E1h52FoOOzvnIyIqTzMOpHArq4OCyxoevM6uMMoTw30rb6bvX3opcKICiFrVl TzB3J4v842esg== From: cel@kernel.org To: Neil Brown , Jeff Layton , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: , Rick Macklem , j.david.lists@gmail.com, Chuck Lever Subject: [PATCH v4 2/9] NFSD: Insulate nfsd4_encode_read() from page boundaries in the encode buffer Date: Mon, 30 Dec 2024 19:28:53 -0500 Message-ID: <20241231002901.12725-3-cel@kernel.org> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241231002901.12725-1-cel@kernel.org> References: <20241231002901.12725-1-cel@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Chuck Lever Commit 28d5bc468efe ("NFSD: Optimize nfsd4_encode_readv()") replaced the use of write_bytes_to_xdr_buf() because it's expensive and the data items to be encoded are already properly aligned. However, the current code will corrupt the encoded data if the XDR data items that are reserved early and then poked into the XDR buffer later happen to fall on a page boundary in the XDR encoding buffer. __xdr_commit_encode can shift encoded data items in the encoding buffer so that pointers returned from xdr_reserve_space() no longer address the same part of the encoding stream. This isn't an issue for splice reads because the reserved encode buffer areas must fall in the XDR buffers header for the splice to work without error. For vectored reads, however, there is a possibility of send buffer corruption in rare cases. Fixes: 28d5bc468efe ("NFSD: Optimize nfsd4_encode_readv()") Signed-off-by: Chuck Lever --- fs/nfsd/nfs4xdr.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index efcb132c19d4..094806fe1a32 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -4316,6 +4316,15 @@ static __be32 nfsd4_encode_splice_read( int status, space_left; __be32 nfserr; + /* + * Splice read doesn't work if encoding has already wandered + * into the XDR buf's page array. + */ + if (unlikely(xdr->buf->page_len)) { + WARN_ON_ONCE(1); + return nfserr_serverfault; + } + /* * Make sure there is room at the end of buf->head for * svcxdr_encode_opaque_pages() to create a tail buffer @@ -4398,25 +4407,23 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_compoundargs *argp = resp->rqstp->rq_argp; struct nfsd4_read *read = &u->read; struct xdr_stream *xdr = resp->xdr; - int starting_len = xdr->buf->len; bool splice_ok = argp->splice_ok; + unsigned int eof_offset; unsigned long maxcount; + __be32 wire_data[2]; struct file *file; - __be32 *p; if (nfserr) return nfserr; + + eof_offset = xdr_stream_pos(xdr); file = read->rd_nf->nf_file; - p = xdr_reserve_space(xdr, 8); /* eof flag and byte count */ - if (!p) { + /* Reserve space for the eof flag and byte count */ + if (unlikely(!xdr_reserve_space(xdr, XDR_UNIT * 2))) { WARN_ON_ONCE(splice_ok); return nfserr_resource; } - if (resp->xdr->buf->page_len && splice_ok) { - WARN_ON_ONCE(1); - return nfserr_serverfault; - } xdr_commit_encode(xdr); maxcount = min_t(unsigned long, read->rd_length, @@ -4427,12 +4434,13 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, else nfserr = nfsd4_encode_readv(resp, read, file, maxcount); if (nfserr) { - xdr_truncate_encode(xdr, starting_len); + xdr_truncate_encode(xdr, eof_offset); return nfserr; } - p = xdr_encode_bool(p, read->rd_eof); - *p = cpu_to_be32(read->rd_length); + wire_data[0] = read->rd_eof ? xdr_one : xdr_zero; + wire_data[1] = cpu_to_be32(read->rd_length); + write_bytes_to_xdr_buf(xdr->buf, eof_offset, &wire_data, XDR_UNIT * 2); return nfs_ok; } @@ -5303,10 +5311,6 @@ nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp, p = xdr_reserve_space(xdr, 4 + 8 + 4); if (!p) return nfserr_io; - if (resp->xdr->buf->page_len && splice_ok) { - WARN_ON_ONCE(splice_ok); - return nfserr_serverfault; - } maxcount = min_t(unsigned long, read->rd_length, (xdr->buf->buflen - xdr->buf->len)); From patchwork Tue Dec 31 00:28:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13923569 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AA0DEB660 for ; Tue, 31 Dec 2024 00:29:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735604948; cv=none; b=LLg6cq5a7y8s5BIPsTn2LGC+BklkKSPtTYUNtgXBGBvEAYaNGji6DK2XC8OKUTsRgLjjUPj/hRgpJxeQCzanC3JpyrB7O06MpPW1suRreDYJjUbI0NJIM1BFDu07PkAPfeQM/DapVOGOBxydJMA5aar7IHdMVCZO1cawGu4FkV4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735604948; c=relaxed/simple; bh=JaWDDhfb+mmrwo7+SaQV+zwajMn+Ijykp/ajU/NijbI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EcCfkVxaVUi0do++ymxLI+wCBZypFqLNKg8iskBFs5nHB1UZfVRyLOcAK429Qi5Fg8a/PPwBUjSrEi0f9KH1/5vZUKIk6skaUPaheEpZUYsXVl7oPslUXfZG07U+z+EExKC0+xNuZL7Qn4cSkEbqWZ6zeyhGggtAxorMrbxF9wo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ZWP8aD/C; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ZWP8aD/C" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B1A04C4CEDC; Tue, 31 Dec 2024 00:29:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1735604948; bh=JaWDDhfb+mmrwo7+SaQV+zwajMn+Ijykp/ajU/NijbI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZWP8aD/CGKdeP9OMK3YXigdx/QSxOmLNSEATGeCnIJaG7DX+ipIRPtg2L/M8o7vRu aBic9iVVCpJt9t490ptkQ39B6j2oLM5DdvuZd+P/yMn7uWCE8YaNQAyioNRA8HxUIX +FezGSHsIOH3vPTfPoimm7T/1nmu7c8Y9rMtXff2Tc5HiREQfMeVC2RgW8Xbeft43S KtUjvZtd9d1QfWYTxWgHDUjh4y1YkhmeeZyIomvE8TJC/ichz2LqNdioxojRTef6L8 ib6muMNo2AY93IMP6opxrbW/DxanjnEm57yfT2swtkAmc3UQLXlz+pCWoF+F51xcBY W1lSgyY3hJeKg== From: cel@kernel.org To: Neil Brown , Jeff Layton , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: , Rick Macklem , j.david.lists@gmail.com, Chuck Lever Subject: [PATCH v4 3/9] NFSD: Insulate nfsd4_encode_read_plus() from page boundaries in the encode buffer Date: Mon, 30 Dec 2024 19:28:54 -0500 Message-ID: <20241231002901.12725-4-cel@kernel.org> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241231002901.12725-1-cel@kernel.org> References: <20241231002901.12725-1-cel@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Chuck Lever Commit eeadcb757945 ("NFSD: Simplify READ_PLUS") replaced the use of write_bytes_to_xdr_buf(), copying what was in nfsd4_encode_read() at the time. However, the current code will corrupt the encoded data if the XDR data items that are reserved early and then poked into the XDR buffer later happen to fall on a page boundary in the XDR encoding buffer. __xdr_commit_encode can shift encoded data items in the encoding buffer so that pointers returned from xdr_reserve_space() no longer address the same part of the encoding stream. Fixes: eeadcb757945 ("NFSD: Simplify READ_PLUS") Signed-off-by: Chuck Lever --- fs/nfsd/nfs4xdr.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 094806fe1a32..00e2f4fc4e19 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -5336,16 +5336,17 @@ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_read *read = &u->read; struct file *file = read->rd_nf->nf_file; struct xdr_stream *xdr = resp->xdr; - int starting_len = xdr->buf->len; + unsigned int eof_offset; + __be32 wire_data[2]; u32 segments = 0; - __be32 *p; if (nfserr) return nfserr; - /* eof flag, segment count */ - p = xdr_reserve_space(xdr, 4 + 4); - if (!p) + eof_offset = xdr_stream_pos(xdr); + + /* Reserve space for the eof flag and segment count */ + if (unlikely(!xdr_reserve_space(xdr, XDR_UNIT * 2))) return nfserr_io; xdr_commit_encode(xdr); @@ -5355,15 +5356,16 @@ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr, nfserr = nfsd4_encode_read_plus_data(resp, read); if (nfserr) { - xdr_truncate_encode(xdr, starting_len); + xdr_truncate_encode(xdr, eof_offset); return nfserr; } segments++; out: - p = xdr_encode_bool(p, read->rd_eof); - *p = cpu_to_be32(segments); + wire_data[0] = read->rd_eof ? xdr_one : xdr_zero; + wire_data[1] = cpu_to_be32(segments); + write_bytes_to_xdr_buf(xdr->buf, eof_offset, &wire_data, XDR_UNIT * 2); return nfserr; } From patchwork Tue Dec 31 00:28:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13923570 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0342EBA2E for ; Tue, 31 Dec 2024 00:29:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735604950; cv=none; b=EqGua3bv5PCl0DiOsH/AoA4bazpFMYrM9bgL0V4vPk1W7dDVJWuku/Lp5Pm/oQ5E88D/Vh5evu0T7YL7xizl9Z48sZrJ3oWZcxkH9Sal1JmTZadByICYZ5eyBNNISujD4cJCuhB3Q2JyRNugD3kLjP/TtMgywRi+ofeyTK8WFZM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735604950; c=relaxed/simple; bh=bOuMa9sMAGF/sqzqytsqwn7EWGVttZ3gpupeBr5Kh4g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oqCYVb/lhZdFCHGho+ubcWz3jeE4Xb58CyRWqhf6t6L94+velVhIdDY3RrG8LFcnPCk4ccQerPFxo3N8PV/5y1QyxJEqPEOWI/O1dX5fJxB8brtz/GRkU6mevipHeRPU1gnkdTZIBKgj9o8OIOAqdnpVGj5Lx22RoeDmEUuJoPA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=F7UPVHSB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="F7UPVHSB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BC7D7C4CED7; Tue, 31 Dec 2024 00:29:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1735604949; bh=bOuMa9sMAGF/sqzqytsqwn7EWGVttZ3gpupeBr5Kh4g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=F7UPVHSB2Ms1h4D/tkkOjdiU/K5YnVZvUKFzNwM+QaFMYtwCRzu8hEQycAuylVjxU C+9g9FTSKnCyf6tb+0ZpPd8YRT8TA22Y7e/OT6Ef3kwkk4cu3HWeOTRdWWa7cBUCFy ntLBS+uUMAFmoY2/h358UvnqAMG12BWgRrjfbWxYw2sJohWXopAACzNhRK+n92aK1X AfPXMDBGOnAWBWITBO/uW9f7V992z85GOIXheQNgykDa9/p7zhPcN7d1Yli2dK23U0 e9tfSWwB6cA2ZTVZYcPvTiFLCSYEfxdHyHQTyPfjGC1Rumqh0erE/6DLal23PB0jGr Zd5nPOlzKQmKg== From: cel@kernel.org To: Neil Brown , Jeff Layton , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: , Rick Macklem , j.david.lists@gmail.com, Chuck Lever Subject: [PATCH v4 4/9] NFSD: Insulate nfsd4_encode_read_plus_data() from page boundaries in the encode buffer Date: Mon, 30 Dec 2024 19:28:55 -0500 Message-ID: <20241231002901.12725-5-cel@kernel.org> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241231002901.12725-1-cel@kernel.org> References: <20241231002901.12725-1-cel@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Chuck Lever Commit eeadcb757945 ("NFSD: Simplify READ_PLUS") replaced the use of write_bytes_to_xdr_buf(), copying what was in nfsd4_encode_read() at the time. However, the current code will corrupt the encoded data if the XDR data items that are reserved early and then poked into the XDR buffer later happen to fall on a page boundary in the XDR encoding buffer. __xdr_commit_encode can shift encoded data items in the encoding buffer so that pointers returned from xdr_reserve_space() no longer address the same part of the encoding stream. Fixes: eeadcb757945 ("NFSD: Simplify READ_PLUS") Signed-off-by: Chuck Lever --- fs/nfsd/nfs4xdr.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 00e2f4fc4e19..b770225d63dc 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -5304,14 +5304,21 @@ nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp, struct file *file = read->rd_nf->nf_file; struct xdr_stream *xdr = resp->xdr; bool splice_ok = argp->splice_ok; + unsigned int offset_offset; + __be32 nfserr, wire_count; unsigned long maxcount; - __be32 nfserr, *p; + __be64 wire_offset; - /* Content type, offset, byte count */ - p = xdr_reserve_space(xdr, 4 + 8 + 4); - if (!p) + if (xdr_stream_encode_u32(xdr, NFS4_CONTENT_DATA) != XDR_UNIT) return nfserr_io; + offset_offset = xdr_stream_pos(xdr); + + /* Reserve space for the byte offset and count */ + if (unlikely(!xdr_reserve_space(xdr, XDR_UNIT * 3))) + return nfserr_io; + xdr_commit_encode(xdr); + maxcount = min_t(unsigned long, read->rd_length, (xdr->buf->buflen - xdr->buf->len)); @@ -5322,10 +5329,12 @@ nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp, if (nfserr) return nfserr; - *p++ = cpu_to_be32(NFS4_CONTENT_DATA); - p = xdr_encode_hyper(p, read->rd_offset); - *p = cpu_to_be32(read->rd_length); - + wire_offset = cpu_to_be64(read->rd_offset); + write_bytes_to_xdr_buf(xdr->buf, offset_offset, &wire_offset, + XDR_UNIT * 2); + wire_count = cpu_to_be32(read->rd_length); + write_bytes_to_xdr_buf(xdr->buf, offset_offset + XDR_UNIT * 2, + &wire_count, XDR_UNIT); return nfs_ok; } From patchwork Tue Dec 31 00:28:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13923571 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 11012C2E0 for ; Tue, 31 Dec 2024 00:29:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735604951; cv=none; b=trwjjROVBoeVCBixkaK+LDACXbgoxClxviApSnqN7DD1bPhaEXBpmwaWx5B813akktMBKHq3V5P7KwtAJknnx3C/IDcObuPWwFy8GW3wXYysP4pIx/Bgz6w6NOyiir2HteSJw1aNQ9bTkUKYgEBkWil02nr/8ISWVKOFDElc66I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735604951; c=relaxed/simple; bh=t0dHrzz6nCVz5GdSMqgBuHRQMV2JCKRfQ1sMFljOO0I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TrHQztrv9mbLAlO98WRaw0Cy2HbamyjsYzaGhL5aoyiUU2ppTukas1XbfKjvCxXFQlZWQwdLHKOR9EUVcYboCnZU7QsCXFdKwwzaQ3KJaVTy2LBFVX+K5Mw8dGNLFqVxIVVDYD6Z1OZkv4K02hhg1tOqFRnMbP4fEDs0CrFm9hw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CAmVvO8L; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="CAmVvO8L" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C73DBC4CED0; Tue, 31 Dec 2024 00:29:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1735604950; bh=t0dHrzz6nCVz5GdSMqgBuHRQMV2JCKRfQ1sMFljOO0I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CAmVvO8LAUiVLtN796dTpld7mUqx2NgiHdZKfVeDpkx3o8SGmxJ061r2S8mF+OOFs WfzEGx+EP8umDlJ5A9uLrNdTaYwaodiW7DyiSzrNgud8qFVFEd9qRJCLPIMVSzmOVa SQo2rQTqk8Q0qst1pASOdlrM4qyhYsGri5J7oD6G+JwEDlR6pfldKxPGk2UbaujKHQ uFdHonFd+wMEapLWW5eJkFcGfof1z7B6fKQO/Gc0RxV03BUx/Gr/xsF7nWAaahH9QH Oma19ZNbM0ql+VBDKbQ8Hb0TbX5/vm6GcRSOCqObolo6B7+BNj9OW9dirhm+XLsjb7 GsUVaFlhgpzCw== From: cel@kernel.org To: Neil Brown , Jeff Layton , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: , Rick Macklem , j.david.lists@gmail.com, Chuck Lever Subject: [PATCH v4 5/9] NFSD: Insulate nfsd4_encode_fattr4() from page boundaries in the encode buffer Date: Mon, 30 Dec 2024 19:28:56 -0500 Message-ID: <20241231002901.12725-6-cel@kernel.org> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241231002901.12725-1-cel@kernel.org> References: <20241231002901.12725-1-cel@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Chuck Lever Commit ab04de60ae1c ("NFSD: Optimize nfsd4_encode_fattr()") replaced the use of write_bytes_to_xdr_buf() because it's expensive and the data items to be encoded are already properly aligned. However, there's no guarantee that the pointer returned from xdr_reserve_space() will still point to the correct reserved space in the encode buffer after one or more intervening calls to xdr_reserve_space(). It just happens to work with the current implementation of xdr_reserve_space(). This commit effectively reverts the optimization. Signed-off-by: Chuck Lever --- fs/nfsd/nfs4xdr.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index b770225d63dc..d4ee633b01e3 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -3506,8 +3506,8 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct nfsd4_fattr_args args; struct svc_fh *tempfh = NULL; int starting_len = xdr->buf->len; - __be32 *attrlen_p, status; - int attrlen_offset; + unsigned int attrlen_offset; + __be32 attrlen, status; u32 attrmask[3]; int err; struct nfsd4_compoundres *resp = rqstp->rq_resp; @@ -3627,9 +3627,8 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr, goto out; /* attr_vals */ - attrlen_offset = xdr->buf->len; - attrlen_p = xdr_reserve_space(xdr, XDR_UNIT); - if (!attrlen_p) + attrlen_offset = xdr_stream_pos(xdr); + if (unlikely(!xdr_reserve_space(xdr, XDR_UNIT))) goto out_resource; bitmap_from_arr32(attr_bitmap, attrmask, ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops)); @@ -3639,7 +3638,8 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr, if (status != nfs_ok) goto out; } - *attrlen_p = cpu_to_be32(xdr->buf->len - attrlen_offset - XDR_UNIT); + attrlen = cpu_to_be32(xdr_stream_pos(xdr) - attrlen_offset - XDR_UNIT); + write_bytes_to_xdr_buf(xdr->buf, attrlen_offset, &attrlen, XDR_UNIT); status = nfs_ok; out: From patchwork Tue Dec 31 00:28:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13923572 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C5E2FDDDC for ; Tue, 31 Dec 2024 00:29:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735604951; cv=none; b=ZAT1ryHNpvPmoWVXKKXraS6bqCRsfucAXy/AugJpJYmZxn9Fk6RYvYkorIHM7pDzEGS8NHPlKTMHphiTLd04+CceOLkgnccPOd+6VWekHT+/Fg0Xo3HR3inHQxhsuG0vseii0xU95Y/JGPFukBw4QPsGfsRCn5Tlzk8t/gMmo0M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735604951; c=relaxed/simple; bh=GTVzmyjVHGd/GZrLH23lLZR88MjBbXOX8m9pVYNp8eo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bGBg3tyN9KKxgjh7gRGuP5qw/ct/Kq0wYJ75+PbPJT72zrCCL2A0aAD+/HPC6/Qqik5Y0KHxPIqCgysdjb7JMxyqZM/V7BIczS+YXMDf/CAEObNZ17p325qhVmMeNrRo1JmcYnkTeY01d0ZjtyOm9MVkmWLvNyWrAUYK2wXqAh0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=u4+L4Fuq; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="u4+L4Fuq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D45DBC4CED7; Tue, 31 Dec 2024 00:29:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1735604951; bh=GTVzmyjVHGd/GZrLH23lLZR88MjBbXOX8m9pVYNp8eo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=u4+L4FuqDVN71I3QaIS4tr1C9MUV6VYbrmw90aPGS/+WRCvHv7hNBm3EBaUKhj5QY jWpVkyxsmwqtacw2bXEIvEa39eUHwOu1YPgvOaYG5dS9DN7hogjnUm/rdbkBTPEQ3i fpuh+S1WKAc/xAWfYvFXdegWRlt0yiUwwPI+f0vPRgCa7yI1qfswwja3/IUoecbaIO /OiFSsxGfjK2t6FrwRL3ERHeK04VcEkDBVWWPp9iWWxifIGGSxyWjoBaIb57ODtdAz lQutK6J4hUe7u1MGcrf/gh9oB882WP7S29qgiEZjBDKiaTKpQUvoCOWEDzRVekRmOf E5yRDKjBjbIow== From: cel@kernel.org To: Neil Brown , Jeff Layton , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: , Rick Macklem , j.david.lists@gmail.com, Chuck Lever Subject: [PATCH v4 6/9] NFSD: Insulate nfsd4_encode_readlink() from page boundaries in the encode buffer Date: Mon, 30 Dec 2024 19:28:57 -0500 Message-ID: <20241231002901.12725-7-cel@kernel.org> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241231002901.12725-1-cel@kernel.org> References: <20241231002901.12725-1-cel@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Chuck Lever There's no guarantee that the pointer returned from xdr_reserve_space() will still point to the correct reserved space in the encode buffer after one or more intervening calls to xdr_reserve_space(). It just happens to work with the current implementation of xdr_reserve_space(). Signed-off-by: Chuck Lever --- fs/nfsd/nfs4xdr.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index d4ee633b01e3..1afe5fe41f22 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -4449,25 +4449,21 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, union nfsd4_op_u *u) { struct nfsd4_readlink *readlink = &u->readlink; - __be32 *p, *maxcount_p, zero = xdr_zero; + __be32 *p, wire_count, zero = xdr_zero; struct xdr_stream *xdr = resp->xdr; - int length_offset = xdr->buf->len; + unsigned int length_offset; int maxcount, status; - maxcount_p = xdr_reserve_space(xdr, XDR_UNIT); - if (!maxcount_p) + /* linktext4.count */ + length_offset = xdr_stream_pos(xdr); + if (unlikely(!xdr_reserve_space(xdr, XDR_UNIT))) return nfserr_resource; - maxcount = PAGE_SIZE; + /* linktext4.data */ + maxcount = PAGE_SIZE; p = xdr_reserve_space(xdr, maxcount); if (!p) return nfserr_resource; - /* - * XXX: By default, vfs_readlink() will truncate symlinks if they - * would overflow the buffer. Is this kosher in NFSv4? If not, one - * easy fix is: if vfs_readlink() precisely fills the buffer, assume - * that truncation occurred, and return NFS4ERR_RESOURCE. - */ nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, (char *)p, &maxcount); if (nfserr == nfserr_isdir) @@ -4480,7 +4476,9 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, nfserr = nfserrno(status); goto out_err; } - *maxcount_p = cpu_to_be32(maxcount); + + wire_count = cpu_to_be32(maxcount); + write_bytes_to_xdr_buf(xdr->buf, length_offset, &wire_count, XDR_UNIT); xdr_truncate_encode(xdr, length_offset + 4 + xdr_align_size(maxcount)); write_bytes_to_xdr_buf(xdr->buf, length_offset + 4 + maxcount, &zero, xdr_pad_size(maxcount)); From patchwork Tue Dec 31 00:28:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13923573 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D71F8EEA9 for ; Tue, 31 Dec 2024 00:29:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735604952; cv=none; b=DCOSzDwaxoilePSikoNLx0bsvFutnOwkSGDDkVWXWZdCVcPfAPw2kjcOJ9WzbiRDIiTq7k4mZkIdGHBG0LZiRQ0MVJIdD53sPEMXgNSKXpd7rJEhgIzxFEZJCLYMZm7eWYwcAjpN6BqJ8cSdXvV5z3+fSq0mBB91Cgc48V5HNG4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735604952; c=relaxed/simple; bh=UMKqVod3TUfEi67sVr54bnVhU6ZxYeL1FCr2BTKr2LQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uXotDuBDfNtNLMHGomGovHk3YaWecmS2EkkEtM46pSg99G5loZkrnAvKR41V08V/vxteLXbYfnGK0FVGWEfN4HewvIjfBQSYhdlbXL87d1nlLzarxh0T4iS9CMhHpyoT3vndqyR+Tuuy8XcaV3FmnT8fluUNfemwLwHtmTgIj5I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iocgM6aj; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="iocgM6aj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E2713C4CED0; Tue, 31 Dec 2024 00:29:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1735604952; bh=UMKqVod3TUfEi67sVr54bnVhU6ZxYeL1FCr2BTKr2LQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iocgM6aj6zI92JLl1JCs0FzG51LtWZ3+lFo6NnLFi1Ej8X7R7ZTNMWHMkA1U0FGp/ MHF/KxRZKPr8zXAUDwC0BDv8Hh2+gkvr1seLhitKLiNUXz1nmzwx5Hi91D2dniYN0F IS2XzqrIjozaKYK13sWTNrl5ySxolbi7NGbVszkvJY7zSLwv283soH7Jzvfa27rMDY yqJMnBb/DEWxnLxzrQAHADaFM5Pp4dCUF3RKRUpjXTq80V0RqzOuHkntdS5WMV5lJy qkC5AL8ga5NWWCKNkkc9W3txlSvy+7dtyBgE5wWnDzKsWdEJZd8hAENO5g0VQVOuux kBnknsvhrFNcw== From: cel@kernel.org To: Neil Brown , Jeff Layton , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: , Rick Macklem , j.david.lists@gmail.com, Chuck Lever Subject: [PATCH v4 7/9] NFSD: Refactor nfsd4_do_encode_secinfo() again Date: Mon, 30 Dec 2024 19:28:58 -0500 Message-ID: <20241231002901.12725-8-cel@kernel.org> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241231002901.12725-1-cel@kernel.org> References: <20241231002901.12725-1-cel@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Chuck Lever Extract the code that encodes the secinfo4 union data type to clarify the logic. The removed warning is pretty well obscured and thus probably not terribly useful. Signed-off-by: Chuck Lever --- fs/nfsd/nfs4xdr.c | 65 +++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 1afe5fe41f22..a8b99e4796c9 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -4612,13 +4612,41 @@ nfsd4_encode_rpcsec_gss_info(struct xdr_stream *xdr, return nfs_ok; } +static __be32 +nfsd4_encode_secinfo4(struct xdr_stream *xdr, rpc_authflavor_t pf, + u32 *supported) +{ + struct rpcsec_gss_info info; + __be32 status; + + if (rpcauth_get_gssinfo(pf, &info) == 0) { + (*supported)++; + + /* flavor */ + status = nfsd4_encode_uint32_t(xdr, RPC_AUTH_GSS); + if (status != nfs_ok) + return status; + /* flavor_info */ + status = nfsd4_encode_rpcsec_gss_info(xdr, &info); + if (status != nfs_ok) + return status; + } else if (pf < RPC_AUTH_MAXFLAVOR) { + (*supported)++; + + /* flavor */ + status = nfsd4_encode_uint32_t(xdr, pf); + if (status != nfs_ok) + return status; + } + return nfs_ok; +} + static __be32 nfsd4_do_encode_secinfo(struct xdr_stream *xdr, struct svc_export *exp) { u32 i, nflavs, supported; struct exp_flavor_info *flavs; struct exp_flavor_info def_flavs[2]; - static bool report = true; __be32 *flavorsp; __be32 status; @@ -4642,42 +4670,17 @@ nfsd4_do_encode_secinfo(struct xdr_stream *xdr, struct svc_export *exp) } } - supported = 0; flavorsp = xdr_reserve_space(xdr, XDR_UNIT); if (!flavorsp) return nfserr_resource; - for (i = 0; i < nflavs; i++) { - rpc_authflavor_t pf = flavs[i].pseudoflavor; - struct rpcsec_gss_info info; - - if (rpcauth_get_gssinfo(pf, &info) == 0) { - supported++; - - /* flavor */ - status = nfsd4_encode_uint32_t(xdr, RPC_AUTH_GSS); - if (status != nfs_ok) - return status; - /* flavor_info */ - status = nfsd4_encode_rpcsec_gss_info(xdr, &info); - if (status != nfs_ok) - return status; - } else if (pf < RPC_AUTH_MAXFLAVOR) { - supported++; - - /* flavor */ - status = nfsd4_encode_uint32_t(xdr, pf); - if (status != nfs_ok) - return status; - } else { - if (report) - pr_warn("NFS: SECINFO: security flavor %u " - "is not supported\n", pf); - } + for (i = 0, supported = 0; i < nflavs; i++) { + status = nfsd4_encode_secinfo4(xdr, flavs[i].pseudoflavor, + &supported); + if (status != nfs_ok) + return status; } - if (nflavs != supported) - report = false; *flavorsp = cpu_to_be32(supported); return 0; } From patchwork Tue Dec 31 00:28:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13923574 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E0605FC0B for ; Tue, 31 Dec 2024 00:29:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735604954; cv=none; b=HcWh+ytUXGsG9ptsrd3LB0yru4ZcGSNQtExAi9tVPohRw4jujBK9u/7gPPaAA7tBPsPH7txbuoavXyZB3eTwJ7+pOg114bZ9XSjby0RhK826FQ48d5Jq6Hg+qKM4tbFmGbY1wdUIefPhy4oplSqUd95ol7VCzmXy9azVmQNqM9E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735604954; c=relaxed/simple; bh=2TNh56EU58bkLWikRL7pv/3nKn+wP3Luw8Yfa5uOFQs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ib46jxUYhU0cKIkKdRwWScAzo6irNjj9Dl0+EqKjOT/xcKueF6UtjeoD7ZO/cpxaNAaRB7EKCHZDAPAllHVU8PuLmZq3MxeLv2m9lVVMENLWuFRr0BpNWW+fbtzBigD47sWXchyW6sQ6wA4SjS+UTrsIvNvhTwo++wKnd2YUFj4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KJVq+nFD; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KJVq+nFD" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F0396C4CED4; Tue, 31 Dec 2024 00:29:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1735604953; bh=2TNh56EU58bkLWikRL7pv/3nKn+wP3Luw8Yfa5uOFQs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KJVq+nFDPfEG7W3Lbewkoud94AwOZcVwpYDMs7MvqosOG7hgp5VMk1plCxIggyP0T NQi20qQteijDPcIaGZ7K+CjF0ErQMjy+AiWFPaNhtqDCHI024NLfj6RFBYDLQiFu4L V47yT3qpPXOI/R3WNQzk5g/cJ95+i2P/7vIStFdGKBkWMWahoVJ3qnu6q3SLvdK+sn pcGIQ4FFHMP8oGkPH0yy+o5IOgULzZmNXE3WvfKwD8ffqqDbzGcomxyABAKwvXnkU0 G2Eun5wmQmuXnVhE9fXbIDU8lzEKxXcpfwB8j+90uwntaWVmNF4P0uH9IxZtBdCiKH hCVLB96F/T7cQ== From: cel@kernel.org To: Neil Brown , Jeff Layton , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: , Rick Macklem , j.david.lists@gmail.com, Chuck Lever Subject: [PATCH v4 8/9] NFSD: Insulate nfsd4_encode_secinfo() from page boundaries in the encode buffer Date: Mon, 30 Dec 2024 19:28:59 -0500 Message-ID: <20241231002901.12725-9-cel@kernel.org> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241231002901.12725-1-cel@kernel.org> References: <20241231002901.12725-1-cel@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Chuck Lever There's no guarantee that the pointer returned from xdr_reserve_space() will still point to the correct reserved space in the encode buffer after one or more intervening calls to xdr_reserve_space(). It just happens to work with the current implementation of xdr_reserve_space(). Signed-off-by: Chuck Lever --- fs/nfsd/nfs4xdr.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index a8b99e4796c9..348cd13f9012 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -4642,13 +4642,13 @@ nfsd4_encode_secinfo4(struct xdr_stream *xdr, rpc_authflavor_t pf, } static __be32 -nfsd4_do_encode_secinfo(struct xdr_stream *xdr, struct svc_export *exp) +nfsd4_encode_SECINFO4resok(struct xdr_stream *xdr, struct svc_export *exp) { u32 i, nflavs, supported; struct exp_flavor_info *flavs; struct exp_flavor_info def_flavs[2]; - __be32 *flavorsp; - __be32 status; + unsigned int count_offset; + __be32 status, wire_count; if (exp->ex_nflavors) { flavs = exp->ex_flavors; @@ -4670,8 +4670,8 @@ nfsd4_do_encode_secinfo(struct xdr_stream *xdr, struct svc_export *exp) } } - flavorsp = xdr_reserve_space(xdr, XDR_UNIT); - if (!flavorsp) + count_offset = xdr_stream_pos(xdr); + if (unlikely(!xdr_reserve_space(xdr, XDR_UNIT))) return nfserr_resource; for (i = 0, supported = 0; i < nflavs; i++) { @@ -4681,7 +4681,9 @@ nfsd4_do_encode_secinfo(struct xdr_stream *xdr, struct svc_export *exp) return status; } - *flavorsp = cpu_to_be32(supported); + wire_count = cpu_to_be32(supported); + write_bytes_to_xdr_buf(xdr->buf, count_offset, &wire_count, + XDR_UNIT); return 0; } @@ -4692,7 +4694,7 @@ nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_secinfo *secinfo = &u->secinfo; struct xdr_stream *xdr = resp->xdr; - return nfsd4_do_encode_secinfo(xdr, secinfo->si_exp); + return nfsd4_encode_SECINFO4resok(xdr, secinfo->si_exp); } static __be32 @@ -4702,7 +4704,7 @@ nfsd4_encode_secinfo_no_name(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_secinfo_no_name *secinfo = &u->secinfo_no_name; struct xdr_stream *xdr = resp->xdr; - return nfsd4_do_encode_secinfo(xdr, secinfo->sin_exp); + return nfsd4_encode_SECINFO4resok(xdr, secinfo->sin_exp); } static __be32 From patchwork Tue Dec 31 00:29:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13923575 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 13FC44C8F for ; Tue, 31 Dec 2024 00:29:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735604955; cv=none; b=dCtUUZ1N5HNjkUEJGDZRqSaN4v5h9w40tbXfGVAIo3i/aBjB3I2czUTHW4FTlITDhwsy415akHAwLmJBcpzmgEnkqa90SSVWydhvqNA9ygUfr8yhWQ1yGSdUZbzMjHfGDh7FRIzJpvshg2VHgvDOnHVyNjp+qQLZ1if3pfYjfN0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735604955; c=relaxed/simple; bh=Dvz+y0oVf9SZkGJkHtQdwbnWNBzmte4pNKg4/KKMckE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NEunozVscNJFmD9636v9Yfa2C33MMyaj/KBol8+pStXMn1m05ml7/17D53dEVYZF3nFoVTrgBbOu2QdFYELzCyTflGmPtWP4LLdjPJpGnl+7fxC/cvIjinYBldqJUiJoxyaPSfGj2s0Sj0RULnDQOWIlx6Otl7GQEexpfTx0Ego= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tWGuA5T3; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="tWGuA5T3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 07395C4CEDD; Tue, 31 Dec 2024 00:29:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1735604954; bh=Dvz+y0oVf9SZkGJkHtQdwbnWNBzmte4pNKg4/KKMckE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tWGuA5T3LFeE+M7YxL3lLFSyn+5rU6IPLiqw9Z/G5zh+H/SssJNm3ucSCElrDUADs GFoneZQbYxrcDoYd8aabbgd4hCju/jjoUyvQUgaqRCKJ4i3/o+BlJnWSWjCKZ1ALw4 rrYbsgO8kN+EB9efAZCygXjXGUkBk5VtIlUQzqlNsZYBkSqBNUNaEV8Fzaz2HxBO83 2EISicK/DH8vUo6gb+XT3LHm/Jv5VZNWkCvod5r9llqWMCU3WarEwIeKUTSF8vyqS3 ZsTqxwMXLEPdxMSw3bxOuSYzJDvjng4G/AkYwhDHwt58r5wT3MdlpgqhKhDaM5n3ta 8aFiveeZ22VFg== From: cel@kernel.org To: Neil Brown , Jeff Layton , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: , Rick Macklem , j.david.lists@gmail.com, Chuck Lever Subject: [PATCH v4 9/9] SUNRPC: Document validity guarantees of the pointer returned by reserve_space Date: Mon, 30 Dec 2024 19:29:00 -0500 Message-ID: <20241231002901.12725-10-cel@kernel.org> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241231002901.12725-1-cel@kernel.org> References: <20241231002901.12725-1-cel@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Chuck Lever A subtlety of this API is that if the @nbytes region traverses a page boundary, the next __xdr_commit_encode will shift the data item in the XDR encode buffer. This makes the returned pointer point to something else, leading to unexpected behavior. There are a few cases where the caller saves the returned pointer and then later uses it to insert a computed value into an earlier part of the stream. This can be safe only if either: - the data item is guaranteed to be in the XDR buffer's head, and thus is not ever going to be near a page boundary, or - the data item is no larger than 4 octets, since XDR alignment rules require all data items to start on 4-octet boundaries But that safety is only an artifact of the current implementation. It would be less brittle if these "safe" uses were eventually replaced. Signed-off-by: Chuck Lever Reviewed-by: NeilBrown Reviewed-by: Jeff Layton --- net/sunrpc/xdr.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 62e07c330a66..4e003cb516fe 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -1097,6 +1097,12 @@ static noinline __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, * Checks that we have enough buffer space to encode 'nbytes' more * bytes of data. If so, update the total xdr_buf length, and * adjust the length of the current kvec. + * + * The returned pointer is valid only until the next call to + * xdr_reserve_space() or xdr_commit_encode() on @xdr. The current + * implementation of this API guarantees that space reserved for a + * four-byte data item remains valid until @xdr is destroyed, but + * that might not always be true in the future. */ __be32 * xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes) {