@@ -216,6 +216,12 @@ nfsd3_proc_write(struct svc_rqst *rqstp)
(unsigned long long) argp->offset,
argp->stable? " stable" : "");
+ resp->status = nfserr_fbig;
+ if (argp->offset >= OFFSET_MAX)
+ goto out;
+ if (argp->offset + argp->len >= OFFSET_MAX)
+ goto out;
+
fh_copy(&resp->fh, &argp->fh);
resp->committed = argp->stable;
nvecs = svc_fill_write_vector(rqstp, &argp->payload);
@@ -224,6 +230,7 @@ nfsd3_proc_write(struct svc_rqst *rqstp)
rqstp->rq_vec, nvecs, &cnt,
resp->committed, resp->verf);
resp->count = cnt;
+out:
return rpc_success;
}
@@ -1022,7 +1022,9 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
int nvecs;
if (write->wr_offset >= OFFSET_MAX)
- return nfserr_inval;
+ return nfserr_fbig;
+ if (write->wr_offset + write->wr_buflen >= OFFSET_MAX)
+ return nfserr_fbig;
cnt = write->wr_buflen;
trace_nfsd_write_start(rqstp, &cstate->current_fh,
Ensure that a client cannot specify a WRITE range that falls in a byte range outside what the kernel's internal types (such as loff_t, which is signed) can represent. The kiocb iterators, invoked in nfsd_vfs_write(), should properly limit write operations to within the underlying file system's s_maxbytes. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> --- fs/nfsd/nfs3proc.c | 7 +++++++ fs/nfsd/nfs4proc.c | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-)