Skip to content

Commit 8eefed8

Browse files
committed
Merge tag 'nfsd-6.18-2' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
Pull nfsd fixes from Chuck Lever: "Regression fixes: - Revert the patch that removed the cap on MAX_OPS_PER_COMPOUND - Address a kernel build issue Stable fixes: - Fix crash when a client queries new attributes on forechannel - Fix rare NFSD crash when tracing is enabled" * tag 'nfsd-6.18-2' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: Revert "NFSD: Remove the cap on number of operations per NFSv4 COMPOUND" nfsd: Avoid strlen conflict in nfsd4_encode_components_esc() NFSD: Fix crash in nfsd4_read_release() NFSD: Define actions for the new time_deleg FATTR4 attributes
2 parents fd57572 + 3e7f011 commit 8eefed8

File tree

5 files changed

+35
-12
lines changed

5 files changed

+35
-12
lines changed

fs/nfsd/nfs4proc.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -988,10 +988,11 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
988988
static void
989989
nfsd4_read_release(union nfsd4_op_u *u)
990990
{
991-
if (u->read.rd_nf)
991+
if (u->read.rd_nf) {
992+
trace_nfsd_read_done(u->read.rd_rqstp, u->read.rd_fhp,
993+
u->read.rd_offset, u->read.rd_length);
992994
nfsd_file_put(u->read.rd_nf);
993-
trace_nfsd_read_done(u->read.rd_rqstp, u->read.rd_fhp,
994-
u->read.rd_offset, u->read.rd_length);
995+
}
995996
}
996997

997998
static __be32
@@ -2892,10 +2893,20 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
28922893

28932894
rqstp->rq_lease_breaker = (void **)&cstate->clp;
28942895

2895-
trace_nfsd_compound(rqstp, args->tag, args->taglen, args->opcnt);
2896+
trace_nfsd_compound(rqstp, args->tag, args->taglen, args->client_opcnt);
28962897
while (!status && resp->opcnt < args->opcnt) {
28972898
op = &args->ops[resp->opcnt++];
28982899

2900+
if (unlikely(resp->opcnt == NFSD_MAX_OPS_PER_COMPOUND)) {
2901+
/* If there are still more operations to process,
2902+
* stop here and report NFS4ERR_RESOURCE. */
2903+
if (cstate->minorversion == 0 &&
2904+
args->client_opcnt > resp->opcnt) {
2905+
op->status = nfserr_resource;
2906+
goto encode_op;
2907+
}
2908+
}
2909+
28992910
/*
29002911
* The XDR decode routines may have pre-set op->status;
29012912
* for example, if there is a miscellaneous XDR error
@@ -2972,7 +2983,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
29722983
status = op->status;
29732984
}
29742985

2975-
trace_nfsd_compound_status(args->opcnt, resp->opcnt,
2986+
trace_nfsd_compound_status(args->client_opcnt, resp->opcnt,
29762987
status, nfsd4_op_name(op->opnum));
29772988

29782989
nfsd4_cstate_clear_replay(cstate);

fs/nfsd/nfs4state.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3902,6 +3902,7 @@ static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs *ca, struct nfs
39023902
ca->headerpadsz = 0;
39033903
ca->maxreq_sz = min_t(u32, ca->maxreq_sz, maxrpc);
39043904
ca->maxresp_sz = min_t(u32, ca->maxresp_sz, maxrpc);
3905+
ca->maxops = min_t(u32, ca->maxops, NFSD_MAX_OPS_PER_COMPOUND);
39053906
ca->maxresp_cached = min_t(u32, ca->maxresp_cached,
39063907
NFSD_SLOT_CACHE_SIZE + NFSD_MIN_HDR_SEQ_SZ);
39073908
ca->maxreqs = min_t(u32, ca->maxreqs, NFSD_MAX_SLOTS_PER_SESSION);

fs/nfsd/nfs4xdr.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2488,8 +2488,10 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
24882488

24892489
if (xdr_stream_decode_u32(argp->xdr, &argp->minorversion) < 0)
24902490
return false;
2491-
if (xdr_stream_decode_u32(argp->xdr, &argp->opcnt) < 0)
2491+
if (xdr_stream_decode_u32(argp->xdr, &argp->client_opcnt) < 0)
24922492
return false;
2493+
argp->opcnt = min_t(u32, argp->client_opcnt,
2494+
NFSD_MAX_OPS_PER_COMPOUND);
24932495

24942496
if (argp->opcnt > ARRAY_SIZE(argp->iops)) {
24952497
argp->ops = vcalloc(argp->opcnt, sizeof(*argp->ops));
@@ -2628,10 +2630,8 @@ static __be32 nfsd4_encode_components_esc(struct xdr_stream *xdr, char sep,
26282630
__be32 *p;
26292631
__be32 pathlen;
26302632
int pathlen_offset;
2631-
int strlen, count=0;
26322633
char *str, *end, *next;
2633-
2634-
dprintk("nfsd4_encode_components(%s)\n", components);
2634+
int count = 0;
26352635

26362636
pathlen_offset = xdr->buf->len;
26372637
p = xdr_reserve_space(xdr, 4);
@@ -2658,9 +2658,8 @@ static __be32 nfsd4_encode_components_esc(struct xdr_stream *xdr, char sep,
26582658
for (; *end && (*end != sep); end++)
26592659
/* find sep or end of string */;
26602660

2661-
strlen = end - str;
2662-
if (strlen) {
2663-
if (xdr_stream_encode_opaque(xdr, str, strlen) < 0)
2661+
if (end > str) {
2662+
if (xdr_stream_encode_opaque(xdr, str, end - str) < 0)
26642663
return nfserr_resource;
26652664
count++;
26662665
} else
@@ -2939,6 +2938,12 @@ struct nfsd4_fattr_args {
29392938
typedef __be32(*nfsd4_enc_attr)(struct xdr_stream *xdr,
29402939
const struct nfsd4_fattr_args *args);
29412940

2941+
static __be32 nfsd4_encode_fattr4__inval(struct xdr_stream *xdr,
2942+
const struct nfsd4_fattr_args *args)
2943+
{
2944+
return nfserr_inval;
2945+
}
2946+
29422947
static __be32 nfsd4_encode_fattr4__noop(struct xdr_stream *xdr,
29432948
const struct nfsd4_fattr_args *args)
29442949
{
@@ -3560,6 +3565,8 @@ static const nfsd4_enc_attr nfsd4_enc_fattr4_encode_ops[] = {
35603565

35613566
[FATTR4_MODE_UMASK] = nfsd4_encode_fattr4__noop,
35623567
[FATTR4_XATTR_SUPPORT] = nfsd4_encode_fattr4_xattr_support,
3568+
[FATTR4_TIME_DELEG_ACCESS] = nfsd4_encode_fattr4__inval,
3569+
[FATTR4_TIME_DELEG_MODIFY] = nfsd4_encode_fattr4__inval,
35633570
[FATTR4_OPEN_ARGUMENTS] = nfsd4_encode_fattr4_open_arguments,
35643571
};
35653572

fs/nfsd/nfsd.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ struct readdir_cd {
5757
__be32 err; /* 0, nfserr, or nfserr_eof */
5858
};
5959

60+
/* Maximum number of operations per session compound */
61+
#define NFSD_MAX_OPS_PER_COMPOUND 200
62+
6063
struct nfsd_genl_rqstp {
6164
struct sockaddr rq_daddr;
6265
struct sockaddr rq_saddr;

fs/nfsd/xdr4.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,7 @@ struct nfsd4_compoundargs {
903903
char * tag;
904904
u32 taglen;
905905
u32 minorversion;
906+
u32 client_opcnt;
906907
u32 opcnt;
907908
bool splice_ok;
908909
struct nfsd4_op *ops;

0 commit comments

Comments
 (0)