diff options
author | J. Bruce Fields <bfields@redhat.com> | 2011-10-10 15:07:40 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2011-10-11 12:15:01 -0400 |
commit | a084daf512bb66fa3c8e21c7027daea521179cd0 (patch) | |
tree | ae3432178013d3b474adac890dad3fb7262f9746 | |
parent | 04f9e664b21c4440daf4d08f31db9b18517e4b8d (diff) |
nfsd4: move name-length checks to xdr
Again, these checks are better in the xdr code.
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r-- | fs/nfsd/nfs4state.c | 24 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 45 | ||||
-rw-r--r-- | fs/nfsd/xdr4.h | 3 |
3 files changed, 33 insertions, 39 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 6bfa293e1c91..5f35f35a2da0 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -1189,17 +1189,6 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir, | |||
1189 | return clp; | 1189 | return clp; |
1190 | } | 1190 | } |
1191 | 1191 | ||
1192 | static int check_name(struct xdr_netobj name) | ||
1193 | { | ||
1194 | if (name.len == 0) | ||
1195 | return 0; | ||
1196 | if (name.len > NFS4_OPAQUE_LIMIT) { | ||
1197 | dprintk("NFSD: check_name: name too long(%d)!\n", name.len); | ||
1198 | return 0; | ||
1199 | } | ||
1200 | return 1; | ||
1201 | } | ||
1202 | |||
1203 | static void | 1192 | static void |
1204 | add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval) | 1193 | add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval) |
1205 | { | 1194 | { |
@@ -1442,7 +1431,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, | |||
1442 | __func__, rqstp, exid, exid->clname.len, exid->clname.data, | 1431 | __func__, rqstp, exid, exid->clname.len, exid->clname.data, |
1443 | addr_str, exid->flags, exid->spa_how); | 1432 | addr_str, exid->flags, exid->spa_how); |
1444 | 1433 | ||
1445 | if (!check_name(exid->clname) || (exid->flags & ~EXCHGID4_FLAG_MASK_A)) | 1434 | if (exid->flags & ~EXCHGID4_FLAG_MASK_A) |
1446 | return nfserr_inval; | 1435 | return nfserr_inval; |
1447 | 1436 | ||
1448 | /* Currently only support SP4_NONE */ | 1437 | /* Currently only support SP4_NONE */ |
@@ -1992,19 +1981,13 @@ __be32 | |||
1992 | nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | 1981 | nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
1993 | struct nfsd4_setclientid *setclid) | 1982 | struct nfsd4_setclientid *setclid) |
1994 | { | 1983 | { |
1995 | struct xdr_netobj clname = { | 1984 | struct xdr_netobj clname = setclid->se_name; |
1996 | .len = setclid->se_namelen, | ||
1997 | .data = setclid->se_name, | ||
1998 | }; | ||
1999 | nfs4_verifier clverifier = setclid->se_verf; | 1985 | nfs4_verifier clverifier = setclid->se_verf; |
2000 | unsigned int strhashval; | 1986 | unsigned int strhashval; |
2001 | struct nfs4_client *conf, *unconf, *new; | 1987 | struct nfs4_client *conf, *unconf, *new; |
2002 | __be32 status; | 1988 | __be32 status; |
2003 | char dname[HEXDIR_LEN]; | 1989 | char dname[HEXDIR_LEN]; |
2004 | 1990 | ||
2005 | if (!check_name(clname)) | ||
2006 | return nfserr_inval; | ||
2007 | |||
2008 | status = nfs4_make_rec_clidname(dname, &clname); | 1991 | status = nfs4_make_rec_clidname(dname, &clname); |
2009 | if (status) | 1992 | if (status) |
2010 | return status; | 1993 | return status; |
@@ -2523,9 +2506,6 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate, | |||
2523 | struct nfs4_openowner *oo = NULL; | 2506 | struct nfs4_openowner *oo = NULL; |
2524 | __be32 status; | 2507 | __be32 status; |
2525 | 2508 | ||
2526 | if (!check_name(open->op_owner)) | ||
2527 | return nfserr_inval; | ||
2528 | |||
2529 | if (STALE_CLIENTID(&open->op_clientid)) | 2509 | if (STALE_CLIENTID(&open->op_clientid)) |
2530 | return nfserr_stale_clientid; | 2510 | return nfserr_stale_clientid; |
2531 | 2511 | ||
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 94da8bb36c85..2cab33cc3238 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -697,6 +697,23 @@ xdr_error: | |||
697 | return nfserr_bad_xdr; | 697 | return nfserr_bad_xdr; |
698 | } | 698 | } |
699 | 699 | ||
700 | static __be32 nfsd4_decode_opaque(struct nfsd4_compoundargs *argp, struct xdr_netobj *o) | ||
701 | { | ||
702 | __be32 *p; | ||
703 | |||
704 | READ_BUF(4); | ||
705 | READ32(o->len); | ||
706 | |||
707 | if (o->len == 0 || o->len > NFS4_OPAQUE_LIMIT) | ||
708 | return nfserr_bad_xdr; | ||
709 | |||
710 | READ_BUF(o->len); | ||
711 | SAVEMEM(o->data, o->len); | ||
712 | return nfs_ok; | ||
713 | xdr_error: | ||
714 | return nfserr_bad_xdr; | ||
715 | } | ||
716 | |||
700 | static __be32 | 717 | static __be32 |
701 | nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) | 718 | nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) |
702 | { | 719 | { |
@@ -715,13 +732,12 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) | |||
715 | status = nfsd4_decode_share_deny(argp, &open->op_share_deny); | 732 | status = nfsd4_decode_share_deny(argp, &open->op_share_deny); |
716 | if (status) | 733 | if (status) |
717 | goto xdr_error; | 734 | goto xdr_error; |
718 | READ_BUF(sizeof(clientid_t) + 4); | 735 | READ_BUF(sizeof(clientid_t)); |
719 | COPYMEM(&open->op_clientid, sizeof(clientid_t)); | 736 | COPYMEM(&open->op_clientid, sizeof(clientid_t)); |
720 | READ32(open->op_owner.len); | 737 | status = nfsd4_decode_opaque(argp, &open->op_owner); |
721 | 738 | if (status) | |
722 | /* owner, open_flag */ | 739 | goto xdr_error; |
723 | READ_BUF(open->op_owner.len + 4); | 740 | READ_BUF(4); |
724 | SAVEMEM(open->op_owner.data, open->op_owner.len); | ||
725 | READ32(open->op_create); | 741 | READ32(open->op_create); |
726 | switch (open->op_create) { | 742 | switch (open->op_create) { |
727 | case NFS4_OPEN_NOCREATE: | 743 | case NFS4_OPEN_NOCREATE: |
@@ -964,12 +980,13 @@ nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclient | |||
964 | { | 980 | { |
965 | DECODE_HEAD; | 981 | DECODE_HEAD; |
966 | 982 | ||
967 | READ_BUF(12); | 983 | READ_BUF(8); |
968 | COPYMEM(setclientid->se_verf.data, 8); | 984 | COPYMEM(setclientid->se_verf.data, 8); |
969 | READ32(setclientid->se_namelen); | ||
970 | 985 | ||
971 | READ_BUF(setclientid->se_namelen + 8); | 986 | status = nfsd4_decode_opaque(argp, &setclientid->se_name); |
972 | SAVEMEM(setclientid->se_name, setclientid->se_namelen); | 987 | if (status) |
988 | return nfserr_bad_xdr; | ||
989 | READ_BUF(8); | ||
973 | READ32(setclientid->se_callback_prog); | 990 | READ32(setclientid->se_callback_prog); |
974 | READ32(setclientid->se_callback_netid_len); | 991 | READ32(setclientid->se_callback_netid_len); |
975 | 992 | ||
@@ -1112,11 +1129,9 @@ nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp, | |||
1112 | READ_BUF(NFS4_VERIFIER_SIZE); | 1129 | READ_BUF(NFS4_VERIFIER_SIZE); |
1113 | COPYMEM(exid->verifier.data, NFS4_VERIFIER_SIZE); | 1130 | COPYMEM(exid->verifier.data, NFS4_VERIFIER_SIZE); |
1114 | 1131 | ||
1115 | READ_BUF(4); | 1132 | status = nfsd4_decode_opaque(argp, &exid->clname); |
1116 | READ32(exid->clname.len); | 1133 | if (status) |
1117 | 1134 | return nfserr_bad_xdr; | |
1118 | READ_BUF(exid->clname.len); | ||
1119 | SAVEMEM(exid->clname.data, exid->clname.len); | ||
1120 | 1135 | ||
1121 | READ_BUF(4); | 1136 | READ_BUF(4); |
1122 | READ32(exid->flags); | 1137 | READ32(exid->flags); |
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index c9012149637c..4c8a7ec3f25d 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h | |||
@@ -317,8 +317,7 @@ struct nfsd4_setattr { | |||
317 | 317 | ||
318 | struct nfsd4_setclientid { | 318 | struct nfsd4_setclientid { |
319 | nfs4_verifier se_verf; /* request */ | 319 | nfs4_verifier se_verf; /* request */ |
320 | u32 se_namelen; /* request */ | 320 | struct xdr_netobj se_name; |
321 | char * se_name; /* request */ | ||
322 | u32 se_callback_prog; /* request */ | 321 | u32 se_callback_prog; /* request */ |
323 | u32 se_callback_netid_len; /* request */ | 322 | u32 se_callback_netid_len; /* request */ |
324 | char * se_callback_netid_val; /* request */ | 323 | char * se_callback_netid_val; /* request */ |