NFSD: Encode COMPOUND operation status on page boundaries
Subsystems (3)
[email protected]
maintainerRFC PATCH 1/1 NFSD: Encode COMPOUND operation status on page boundaries
From: Chuck Lever <[email protected]>
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 that 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 behavior appears to be one reason for that remark.
Break up the reservation of the COMPOUND op num and op status data items into two distinct 4-octet reservations. Thanks to XDR data item alignment restrictions, a 4-octet buffer reservation can never straddle a page boundary.
--- fs/nfsd/nfs4xdr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/nfsd/nfs4xdr.c +3 -2
@@ -5764,10 +5764,11 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)nfsd4_enc encoder;__be32 *p; - p =xdr_reserve_space (xdr,8 ); +if (xdr_stream_encode_u32 (xdr, op->opnum) !=XDR_UNIT ) + goto release; + p =xdr_reserve_space (xdr,XDR_UNIT );if (!p) goto release; - *p++ =cpu_to_be32 (op->opnum); post_err_offset = xdr->buf->len;if (op->opnum ==OP_ILLEGAL )
Signature · 1 line
2.47.0
Quoted 39 lines · On Sun, Dec 22, 2024 at 4:10 PM <[email protected]> wrote:
From: Chuck Lever <[email protected]>
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 toxdr_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 that 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 (usuallyNFS4_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 toxdr_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 nextxdr_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.
Quoted 4 lines
After GETATTR encoding is complete,
nfsd4_encode_operation()writes the op status over the first XDR data item in the GETATTR result. TheNFS4_OKstatus code (0) makes it look like there are zero items in the GETATTR's attribute bitmask.
I can confirm that this patch fixes the test case I have, which is based on J. David's reproducer.
I also think the analysis sounds right. I had gotten to the point where I thought it was some oddball case related to xdr_reserve_space() and saw that the pointer used by GETATTR's nfsd4_encode_bitmap4() was 4 bytes into a page, for the broken case.
(As an aside, it appears that "%p" is broken for 32bit arches. I needed to use "%x" with a (unsigned int) cast to printk() pointers. I doubt anyone much cares about 32bits any more, but I might look to see if I can fix it.)
Good work Chuck!
Quoted 10 lines
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 behavior appears to be one reason for that remark.Break up the reservation of the COMPOUND op num and op status data items into two distinct 4-octet reservations. Thanks to XDR data item alignment restrictions, a 4-octet buffer reservation can never straddle a page boundary.
I don't know enough about the code to comment w.r.t. whether or not this is a correct fix, although it seems to work for the test case.
I will note that it is a pretty subtle trap and it would be nice if something could be done to avoid this coding mistake from happening again. All I can think of is defining a new function that must be used instead of xdr_reserve_space() if there will be other encoding calls done before the pointer is used. Something like xdr_reserve_u32_long_term(). (Chuck is much better at naming stuff than I am.)
--> If your fix is correct, in general, this function would just call xdr_reserve_space(xdr, XDR_UNIT),
but it could also set a flag in the xdr structure so that it can
only be done once until
the flag is cleared (by a function call when the code is done
with the pointer), or something like that?
Anyhow, others probably can suggest better changes that would avoid this trap?
Good work, rick
Quoted 29 lines
Reported-by J David <[email protected]>Signed-off-by Chuck Lever <[email protected]>--- fs/nfsd/nfs4xdr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)fs/nfsd/nfs4xdr.c +3
-3@@ -5764,10 +5764,11 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)nfsd4_enc encoder;__be32 *p; - p =xdr_reserve_space (xdr,8 ); +if (xdr_stream_encode_u32 (xdr, op->opnum) !=XDR_UNIT ) + goto release; + p =xdr_reserve_space (xdr,XDR_UNIT );if (!p) goto release; - *p++ =cpu_to_be32 (op->opnum); post_err_offset = xdr->buf->len;if (op->opnum ==OP_ILLEGAL ) --2.47.0
Quoted 71 lines · Rick Macklem
Quoted 39 lines · On Sun, Dec 22, 2024 at 4:10 PM <[email protected]> wrote:
From: Chuck Lever <[email protected]>
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 toxdr_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 that 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 (usuallyNFS4_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 toxdr_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 nextxdr_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.Quoted 4 lines
After GETATTR encoding is complete,
nfsd4_encode_operation()writes the op status over the first XDR data item in the GETATTR result. TheNFS4_OKstatus code (0) makes it look like there are zero items in the GETATTR's attribute bitmask.I can confirm that this patch fixes the test case I have, which is based on J. David's reproducer.
I also think the analysis sounds right. I had gotten to the point where I thought it was some oddball case related to
xdr_reserve_space()and saw that the pointer used by GETATTR'snfsd4_encode_bitmap4()was 4 bytes into a page, for the broken case.
(As an aside, it appears that "%p" is broken for 32bit arches. I needed to use "%x" with a (unsigned int) cast toprintk()pointers. I doubt anyone much cares about 32bits any more, but I might look to see if I can fix it.)Good work Chuck!
Quoted 10 lines
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 behavior appears to be one reason for that remark.Break up the reservation of the COMPOUND op num and op status data items into two distinct 4-octet reservations. Thanks to XDR data item alignment restrictions, a 4-octet buffer reservation can never straddle a page boundary.
I don't know enough about the code to comment w.r.t. whether or not this is a correct fix, although it seems to work for the test case.
Quoted 12 lines
I will note that it is a pretty subtle trap and it would be nice if something could be done to avoid this coding mistake from happening again. All I can think of is defining a new function that must be used instead of
xdr_reserve_space()if there will be other encoding calls done before the pointer is used. Something likexdr_reserve_u32_long_term(). (Chuck is much better at naming stuff than I am.)
--> If your fix is correct, in general, this function would just callxdr_reserve_space(xdr, XDR_UNIT),
but it could also set a flag in the xdr structure so that it can
only be done once until
the flag is cleared (by a function call when the code is done
with the pointer), or something like that?
I take back this latter bit w.r.t. a flag. If the function only allocates 4bytes,
it will never straddle pages and cause problems.
My suggestion would just clarify that "long term" pointers can only be used for a 4 byte (XDR_UNIT) allocation.
rick
Quoted 34 lines
Anyhow, others probably can suggest better changes that would avoid this trap?
Good work, rick
Quoted 29 lines
Reported-by J David <[email protected]>Signed-off-by Chuck Lever <[email protected]>--- fs/nfsd/nfs4xdr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)fs/nfsd/nfs4xdr.c +3
-3@@ -5764,10 +5764,11 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)nfsd4_enc encoder;__be32 *p; - p =xdr_reserve_space (xdr,8 ); +if (xdr_stream_encode_u32 (xdr, op->opnum) !=XDR_UNIT ) + goto release; + p =xdr_reserve_space (xdr,XDR_UNIT );if (!p) goto release; - *p++ =cpu_to_be32 (op->opnum); post_err_offset = xdr->buf->len;if (op->opnum ==OP_ILLEGAL ) --2.47.0
Quoted 40 lines · Rick Macklem
Quoted 39 lines · On Sun, Dec 22, 2024 at 4:10 PM <[email protected]> wrote:
From: Chuck Lever <[email protected]>
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 toxdr_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 that 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 (usuallyNFS4_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 toxdr_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 nextxdr_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.
Quoted 6 lines
Quoted 4 lines
After GETATTR encoding is complete,
nfsd4_encode_operation()writes the op status over the first XDR data item in the GETATTR result. TheNFS4_OKstatus code (0) makes it look like there are zero items in the GETATTR's attribute bitmask.I can confirm that this patch fixes the test case I have, which is based on J. David's reproducer.
May I add:
?
Quoted 4 lines
I also think the analysis sounds right. I had gotten to the point where I thought it was some oddball case related to
xdr_reserve_space()and saw that the pointer used by GETATTR'snfsd4_encode_bitmap4()was 4 bytes into a page, for the broken case.
May I also add:
?
Quoted 3 lines
(As an aside, it appears that "%p" is broken for 32bit arches. I needed to use "%x" with a (unsigned int) cast to
printk()pointers. I doubt anyone much cares about 32bits any more, but I might look to see if I can fix it.)
On Linux, the %p formatter emits a hash instead of the actual pointer address, for security reasons. There are ways to disable this -- see the "no_hash_pointers" kernel command line argument for the big hammer.
(Documentation/admin-guide/kernel-parameters.txt)
Quoted 1 line
Good work Chuck!
Thanks!
Quoted 11 lines
Quoted 9 lines
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 behavior appears to be one reason for that remark.Break up the reservation of the COMPOUND op num and op status data items into two distinct 4-octet reservations. Thanks to XDR data item alignment restrictions, a 4-octet buffer reservation can never straddle a page boundary.
I don't know enough about the code to comment w.r.t. whether or not this is a correct fix, although it seems to work for the test case.
The most correct fix, IMO, would be to use write_bytes_to_xdr_buf() to insert the op status once the operation has been encoded. That API does not depend on an ephemeral C pointer into a buffer.
The most performant fix is the one proposed here, and this one is also likely to apply cleanly to older Linux kernels.
Quoted 4 lines
I will note that it is a pretty subtle trap and it would be nice if something could be done to avoid this coding mistake from happening again. All I can think of is defining a new function that must be used instead of
xdr_reserve_space()if there will be other encoding calls done before the
Quoted 8 lines
pointer is used. Something like
xdr_reserve_u32_long_term(). (Chuck is much better at naming stuff than I am.)
--> If your fix is correct, in general, this function would just callxdr_reserve_space(xdr, XDR_UNIT),
but it could also set a flag in the xdr structure so that it can
only be done once until
the flag is cleared (by a function call when the code is done
with the pointer), or something like that?
Well there's no limit on the number of times you can call xdr_reserve_space(XDR_UNIT) and save the result.
It just so happens that, with the current implementation of xdr_reserve_space(), reserving up to 4 octets returns a pointer that remains valid as long as the buffer exists. For larger sizes, that doesn't happen to work -- the returned pointer is guaranteed to be valid only until the next call to xdr_reserve_space() or xdr_commit_encode().
The only reason to use the "save the pointer" trick is because it is more performant than write_bytes_to_xdr_buf() (go look at what that API does to see why).
So the whole "save a pointer into the XDR buf, use it later" trick is brittle and depends on an undocumented behavior of that API. At this point, the least we can do is add a warning to reserve_space's kdoc comment. The best we could do is come up with an API that performs reasonably well and makes this common trope less brittle.
I'm auditing the code base for other places that might make unsafe assumptions about the pointer returned from xdr_reserve_space(). nfsd4_encode_read() and read_plus() both do. Probably the SunRPC GSS-API encoders do as well.
Quoted 33 lines
Anyhow, others probably can suggest better changes that would avoid this trap?
Good work, rick
Quoted 29 lines
Reported-by J David <[email protected]>Signed-off-by Chuck Lever <[email protected]>--- fs/nfsd/nfs4xdr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)fs/nfsd/nfs4xdr.c +3
-3@@ -5764,10 +5764,11 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)nfsd4_enc encoder;__be32 *p; - p =xdr_reserve_space (xdr,8 ); +if (xdr_stream_encode_u32 (xdr, op->opnum) !=XDR_UNIT ) + goto release; + p =xdr_reserve_space (xdr,XDR_UNIT );if (!p) goto release; - *p++ =cpu_to_be32 (op->opnum); post_err_offset = xdr->buf->len;if (op->opnum ==OP_ILLEGAL ) --2.47.0
Signature · 1 line
Chuck Lever
Quoted 46 lines · Chuck Lever
Quoted 44 lines · Rick Macklem
Quoted 43 lines · On Sun, Dec 22, 2024 at 4:10 PM <[email protected]> wrote:
From: Chuck Lever <[email protected]>
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 toxdr_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 that 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 (usuallyNFS4_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 toxdr_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 nextxdr_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. TheNFS4_OKstatus code (0) makes it look like there are zero items in the GETATTR's attribute bitmask.
Quoted 8 lines
Quoted 2 lines
I can confirm that this patch fixes the test case I have, which is based on J. David's reproducer.
May I add:
Tested-by Rick Macklem <[email protected]>?
Sure, if you'd like. I have now tested both versions of the patch. I suppose I'm more well known as [email protected] but they both work.
Quoted 7 lines
Quoted 6 lines
I also think the analysis sounds right. I had gotten to the point where I thought it was some oddball case related to
xdr_reserve_space()and saw that the pointer used by GETATTR'snfsd4_encode_bitmap4()was 4 bytes into a page, for the broken case.
Quoted 5 lines
May I also add:
Reviewed-by Rick Macklem <[email protected]>?
Both patches look fine to me, although I do not understand the code in __write_bytes_to_xdr_buf(), so I'm not sure I'm the guy to review this stuff. I do understand that a xdr_reserve_space(xdr, 4) is safe, since it is impossible for it to straddle a page.
I'll leave it up to you.
Quoted 11 lines
Quoted 5 lines
(As an aside, it appears that "%p" is broken for 32bit arches. I needed to use "%x" with a (unsigned int) cast to
printk()pointers. I doubt anyone much cares about 32bits any more, but I might look to see if I can fix it.)On Linux, the %p formatter emits a hash instead of the actual pointer address, for security reasons. There are ways to disable this -- see the "
no_hash_pointers" kernel command line argument for the big hammer.(
Documentation/admin-guide/kernel-parameters.txt)
Thanks for the info. The "pointers" did throw me off for a bit;-)
Thanks, rick
Quoted 102 lines
Quoted 3 lines
Good work Chuck!
Thanks!
Quoted 11 lines
Quoted 9 lines
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 behavior appears to be one reason for that remark.Break up the reservation of the COMPOUND op num and op status data items into two distinct 4-octet reservations. Thanks to XDR data item alignment restrictions, a 4-octet buffer reservation can never straddle a page boundary.
I don't know enough about the code to comment w.r.t. whether or not this is a correct fix, although it seems to work for the test case.
The most correct fix, IMO, would be to use
write_bytes_to_xdr_buf()to insert the op status once the operation has been encoded. That API does not depend on an ephemeral C pointer into a buffer.The most performant fix is the one proposed here, and this one is also likely to apply cleanly to older Linux kernels.
Quoted 4 lines
I will note that it is a pretty subtle trap and it would be nice if something could be done to avoid this coding mistake from happening again. All I can think of is defining a new function that must be used instead of
xdr_reserve_space()if there will be other encoding calls done before theQuoted 8 lines
pointer is used. Something like
xdr_reserve_u32_long_term(). (Chuck is much better at naming stuff than I am.)
--> If your fix is correct, in general, this function would just callxdr_reserve_space(xdr, XDR_UNIT),
but it could also set a flag in the xdr structure so that it can
only be done once until
the flag is cleared (by a function call when the code is done
with the pointer), or something like that?Well there's no limit on the number of times you can call
xdr_reserve_space(XDR_UNIT)and save the result.It just so happens that, with the current implementation of
xdr_reserve_space(), reserving up to 4 octets returns a pointer that remains valid as long as the buffer exists. For larger sizes, that doesn't happen to work -- the returned pointer is guaranteed to be valid only until the next call toxdr_reserve_space()orxdr_commit_encode().The only reason to use the "save the pointer" trick is because it is more performant than
write_bytes_to_xdr_buf()(go look at what that API does to see why).So the whole "save a pointer into the XDR buf, use it later" trick is brittle and depends on an undocumented behavior of that API. At this point, the least we can do is add a warning to reserve_space's kdoc comment. The best we could do is come up with an API that performs reasonably well and makes this common trope less brittle.
I'm auditing the code base for other places that might make unsafe assumptions about the pointer returned from
xdr_reserve_space().nfsd4_encode_read()andread_plus()both do. Probably the SunRPC GSS-API encoders do as well.Quoted 29 lines
Anyhow, others probably can suggest better changes that would avoid this trap?
Good work, rick
Quoted 25 lines
Reported-by J David <[email protected]>Signed-off-by Chuck Lever <[email protected]>--- fs/nfsd/nfs4xdr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)fs/nfsd/nfs4xdr.c +3
-2@@ -5764,10 +5764,11 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)nfsd4_enc encoder;__be32 *p; - p =xdr_reserve_space (xdr,8 ); +if (xdr_stream_encode_u32 (xdr, op->opnum) !=XDR_UNIT ) + goto release; + p =xdr_reserve_space (xdr,XDR_UNIT );if (!p) goto release; - *p++ =cpu_to_be32 (op->opnum); post_err_offset = xdr->buf->len;Quoted 4 lines
Quoted 4 lines
fs/nfsd/nfs4xdr.c +0
-1if (op->opnum ==OP_ILLEGAL ) --2.47.0
--
Chuck Lever