Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lockd: fix decoding of TEST results

We fail to advance the read pointer when reading the stat.oh field that
identifies the lock-holder in a TEST result.

This turns out not to matter if the server is knfsd, which always
returns a zero-length field. But other servers (Ganesha is an example)
may not do this. The result is bad values in fcntl F_GETLK results.

Fix this.

Signed-off-by: J. Bruce Fields <bfields@redhat.com>

+12 -32
+6 -16
fs/lockd/clnt4xdr.c
··· 128 128 static int decode_netobj(struct xdr_stream *xdr, 129 129 struct xdr_netobj *obj) 130 130 { 131 - u32 length; 132 - __be32 *p; 131 + ssize_t ret; 133 132 134 - p = xdr_inline_decode(xdr, 4); 135 - if (unlikely(p == NULL)) 136 - goto out_overflow; 137 - length = be32_to_cpup(p++); 138 - if (unlikely(length > XDR_MAX_NETOBJ)) 139 - goto out_size; 140 - obj->len = length; 141 - obj->data = (u8 *)p; 133 + ret = xdr_stream_decode_opaque_inline(xdr, (void *)&obj->data, 134 + XDR_MAX_NETOBJ); 135 + if (unlikely(ret < 0)) 136 + return -EIO; 137 + obj->len = ret; 142 138 return 0; 143 - out_size: 144 - dprintk("NFS: returned netobj was too long: %u\n", length); 145 - return -EIO; 146 - out_overflow: 147 - print_overflow_msg(__func__, xdr); 148 - return -EIO; 149 139 } 150 140 151 141 /*
+6 -16
fs/lockd/clntxdr.c
··· 125 125 static int decode_netobj(struct xdr_stream *xdr, 126 126 struct xdr_netobj *obj) 127 127 { 128 - u32 length; 129 - __be32 *p; 128 + ssize_t ret; 130 129 131 - p = xdr_inline_decode(xdr, 4); 132 - if (unlikely(p == NULL)) 133 - goto out_overflow; 134 - length = be32_to_cpup(p++); 135 - if (unlikely(length > XDR_MAX_NETOBJ)) 136 - goto out_size; 137 - obj->len = length; 138 - obj->data = (u8 *)p; 130 + ret = xdr_stream_decode_opaque_inline(xdr, (void *)&obj->data, 131 + XDR_MAX_NETOBJ); 132 + if (unlikely(ret < 0)) 133 + return -EIO; 134 + obj->len = ret; 139 135 return 0; 140 - out_size: 141 - dprintk("NFS: returned netobj was too long: %u\n", length); 142 - return -EIO; 143 - out_overflow: 144 - print_overflow_msg(__func__, xdr); 145 - return -EIO; 146 136 } 147 137 148 138 /*