diff options
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/export.c | 6 | ||||
-rw-r--r-- | fs/nfsd/nfs3proc.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs3xdr.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs4proc.c | 73 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 42 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 11 | ||||
-rw-r--r-- | fs/nfsd/nfsfh.c | 2 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 33 | ||||
-rw-r--r-- | fs/nfsd/vfs.h | 6 |
9 files changed, 129 insertions, 48 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index ad000aeb21a2..b9566e46219f 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -1354,12 +1354,6 @@ exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp) | |||
1354 | if (IS_ERR(exp)) | 1354 | if (IS_ERR(exp)) |
1355 | return nfserrno(PTR_ERR(exp)); | 1355 | return nfserrno(PTR_ERR(exp)); |
1356 | rv = fh_compose(fhp, exp, exp->ex_path.dentry, NULL); | 1356 | rv = fh_compose(fhp, exp, exp->ex_path.dentry, NULL); |
1357 | if (rv) | ||
1358 | goto out; | ||
1359 | rv = check_nfsd_access(exp, rqstp); | ||
1360 | if (rv) | ||
1361 | fh_put(fhp); | ||
1362 | out: | ||
1363 | exp_put(exp); | 1357 | exp_put(exp); |
1364 | return rv; | 1358 | return rv; |
1365 | } | 1359 | } |
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index 2247fc91d5e9..9095f3c21df9 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c | |||
@@ -245,7 +245,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp, | |||
245 | } | 245 | } |
246 | 246 | ||
247 | /* Now create the file and set attributes */ | 247 | /* Now create the file and set attributes */ |
248 | nfserr = nfsd_create_v3(rqstp, dirfhp, argp->name, argp->len, | 248 | nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len, |
249 | attr, newfhp, | 249 | attr, newfhp, |
250 | argp->createmode, argp->verf, NULL, NULL); | 250 | argp->createmode, argp->verf, NULL, NULL); |
251 | 251 | ||
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index ad48faca20fc..08c6e36ab2eb 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c | |||
@@ -842,7 +842,7 @@ out: | |||
842 | return rv; | 842 | return rv; |
843 | } | 843 | } |
844 | 844 | ||
845 | __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen) | 845 | static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen) |
846 | { | 846 | { |
847 | struct svc_fh fh; | 847 | struct svc_fh fh; |
848 | int err; | 848 | int err; |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 5fcb1396a7e3..3a6dbd70b34b 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -196,9 +196,9 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o | |||
196 | 196 | ||
197 | /* | 197 | /* |
198 | * Note: create modes (UNCHECKED,GUARDED...) are the same | 198 | * Note: create modes (UNCHECKED,GUARDED...) are the same |
199 | * in NFSv4 as in v3. | 199 | * in NFSv4 as in v3 except EXCLUSIVE4_1. |
200 | */ | 200 | */ |
201 | status = nfsd_create_v3(rqstp, current_fh, open->op_fname.data, | 201 | status = do_nfsd_create(rqstp, current_fh, open->op_fname.data, |
202 | open->op_fname.len, &open->op_iattr, | 202 | open->op_fname.len, &open->op_iattr, |
203 | &resfh, open->op_createmode, | 203 | &resfh, open->op_createmode, |
204 | (u32 *)open->op_verf.data, | 204 | (u32 *)open->op_verf.data, |
@@ -403,7 +403,7 @@ nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
403 | cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen; | 403 | cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen; |
404 | memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval, | 404 | memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval, |
405 | putfh->pf_fhlen); | 405 | putfh->pf_fhlen); |
406 | return fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP); | 406 | return fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_BYPASS_GSS); |
407 | } | 407 | } |
408 | 408 | ||
409 | static __be32 | 409 | static __be32 |
@@ -762,6 +762,9 @@ nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
762 | __be32 err; | 762 | __be32 err; |
763 | 763 | ||
764 | fh_init(&resfh, NFS4_FHSIZE); | 764 | fh_init(&resfh, NFS4_FHSIZE); |
765 | err = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, NFSD_MAY_EXEC); | ||
766 | if (err) | ||
767 | return err; | ||
765 | err = nfsd_lookup_dentry(rqstp, &cstate->current_fh, | 768 | err = nfsd_lookup_dentry(rqstp, &cstate->current_fh, |
766 | secinfo->si_name, secinfo->si_namelen, | 769 | secinfo->si_name, secinfo->si_namelen, |
767 | &exp, &dentry); | 770 | &exp, &dentry); |
@@ -986,6 +989,9 @@ enum nfsd4_op_flags { | |||
986 | ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */ | 989 | ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */ |
987 | ALLOWED_ON_ABSENT_FS = 1 << 1, /* ops processed on absent fs */ | 990 | ALLOWED_ON_ABSENT_FS = 1 << 1, /* ops processed on absent fs */ |
988 | ALLOWED_AS_FIRST_OP = 1 << 2, /* ops reqired first in compound */ | 991 | ALLOWED_AS_FIRST_OP = 1 << 2, /* ops reqired first in compound */ |
992 | /* For rfc 5661 section 2.6.3.1.1: */ | ||
993 | OP_HANDLES_WRONGSEC = 1 << 3, | ||
994 | OP_IS_PUTFH_LIKE = 1 << 4, | ||
989 | }; | 995 | }; |
990 | 996 | ||
991 | struct nfsd4_operation { | 997 | struct nfsd4_operation { |
@@ -1031,6 +1037,44 @@ static __be32 nfs41_check_op_ordering(struct nfsd4_compoundargs *args) | |||
1031 | return nfs_ok; | 1037 | return nfs_ok; |
1032 | } | 1038 | } |
1033 | 1039 | ||
1040 | static inline struct nfsd4_operation *OPDESC(struct nfsd4_op *op) | ||
1041 | { | ||
1042 | return &nfsd4_ops[op->opnum]; | ||
1043 | } | ||
1044 | |||
1045 | static bool need_wrongsec_check(struct svc_rqst *rqstp) | ||
1046 | { | ||
1047 | struct nfsd4_compoundres *resp = rqstp->rq_resp; | ||
1048 | struct nfsd4_compoundargs *argp = rqstp->rq_argp; | ||
1049 | struct nfsd4_op *this = &argp->ops[resp->opcnt - 1]; | ||
1050 | struct nfsd4_op *next = &argp->ops[resp->opcnt]; | ||
1051 | struct nfsd4_operation *thisd; | ||
1052 | struct nfsd4_operation *nextd; | ||
1053 | |||
1054 | thisd = OPDESC(this); | ||
1055 | /* | ||
1056 | * Most ops check wronsec on our own; only the putfh-like ops | ||
1057 | * have special rules. | ||
1058 | */ | ||
1059 | if (!(thisd->op_flags & OP_IS_PUTFH_LIKE)) | ||
1060 | return false; | ||
1061 | /* | ||
1062 | * rfc 5661 2.6.3.1.1.6: don't bother erroring out a | ||
1063 | * put-filehandle operation if we're not going to use the | ||
1064 | * result: | ||
1065 | */ | ||
1066 | if (argp->opcnt == resp->opcnt) | ||
1067 | return false; | ||
1068 | |||
1069 | nextd = OPDESC(next); | ||
1070 | /* | ||
1071 | * Rest of 2.6.3.1.1: certain operations will return WRONGSEC | ||
1072 | * errors themselves as necessary; others should check for them | ||
1073 | * now: | ||
1074 | */ | ||
1075 | return !(nextd->op_flags & OP_HANDLES_WRONGSEC); | ||
1076 | } | ||
1077 | |||
1034 | /* | 1078 | /* |
1035 | * COMPOUND call. | 1079 | * COMPOUND call. |
1036 | */ | 1080 | */ |
@@ -1108,7 +1152,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, | |||
1108 | goto encode_op; | 1152 | goto encode_op; |
1109 | } | 1153 | } |
1110 | 1154 | ||
1111 | opdesc = &nfsd4_ops[op->opnum]; | 1155 | opdesc = OPDESC(op); |
1112 | 1156 | ||
1113 | if (!cstate->current_fh.fh_dentry) { | 1157 | if (!cstate->current_fh.fh_dentry) { |
1114 | if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) { | 1158 | if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) { |
@@ -1126,6 +1170,9 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, | |||
1126 | else | 1170 | else |
1127 | BUG_ON(op->status == nfs_ok); | 1171 | BUG_ON(op->status == nfs_ok); |
1128 | 1172 | ||
1173 | if (!op->status && need_wrongsec_check(rqstp)) | ||
1174 | op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp); | ||
1175 | |||
1129 | encode_op: | 1176 | encode_op: |
1130 | /* Only from SEQUENCE */ | 1177 | /* Only from SEQUENCE */ |
1131 | if (resp->cstate.status == nfserr_replay_cache) { | 1178 | if (resp->cstate.status == nfserr_replay_cache) { |
@@ -1217,10 +1264,12 @@ static struct nfsd4_operation nfsd4_ops[] = { | |||
1217 | }, | 1264 | }, |
1218 | [OP_LOOKUP] = { | 1265 | [OP_LOOKUP] = { |
1219 | .op_func = (nfsd4op_func)nfsd4_lookup, | 1266 | .op_func = (nfsd4op_func)nfsd4_lookup, |
1267 | .op_flags = OP_HANDLES_WRONGSEC, | ||
1220 | .op_name = "OP_LOOKUP", | 1268 | .op_name = "OP_LOOKUP", |
1221 | }, | 1269 | }, |
1222 | [OP_LOOKUPP] = { | 1270 | [OP_LOOKUPP] = { |
1223 | .op_func = (nfsd4op_func)nfsd4_lookupp, | 1271 | .op_func = (nfsd4op_func)nfsd4_lookupp, |
1272 | .op_flags = OP_HANDLES_WRONGSEC, | ||
1224 | .op_name = "OP_LOOKUPP", | 1273 | .op_name = "OP_LOOKUPP", |
1225 | }, | 1274 | }, |
1226 | [OP_NVERIFY] = { | 1275 | [OP_NVERIFY] = { |
@@ -1229,6 +1278,7 @@ static struct nfsd4_operation nfsd4_ops[] = { | |||
1229 | }, | 1278 | }, |
1230 | [OP_OPEN] = { | 1279 | [OP_OPEN] = { |
1231 | .op_func = (nfsd4op_func)nfsd4_open, | 1280 | .op_func = (nfsd4op_func)nfsd4_open, |
1281 | .op_flags = OP_HANDLES_WRONGSEC, | ||
1232 | .op_name = "OP_OPEN", | 1282 | .op_name = "OP_OPEN", |
1233 | }, | 1283 | }, |
1234 | [OP_OPEN_CONFIRM] = { | 1284 | [OP_OPEN_CONFIRM] = { |
@@ -1241,17 +1291,20 @@ static struct nfsd4_operation nfsd4_ops[] = { | |||
1241 | }, | 1291 | }, |
1242 | [OP_PUTFH] = { | 1292 | [OP_PUTFH] = { |
1243 | .op_func = (nfsd4op_func)nfsd4_putfh, | 1293 | .op_func = (nfsd4op_func)nfsd4_putfh, |
1244 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, | 1294 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS |
1295 | | OP_IS_PUTFH_LIKE, | ||
1245 | .op_name = "OP_PUTFH", | 1296 | .op_name = "OP_PUTFH", |
1246 | }, | 1297 | }, |
1247 | [OP_PUTPUBFH] = { | 1298 | [OP_PUTPUBFH] = { |
1248 | .op_func = (nfsd4op_func)nfsd4_putrootfh, | 1299 | .op_func = (nfsd4op_func)nfsd4_putrootfh, |
1249 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, | 1300 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS |
1301 | | OP_IS_PUTFH_LIKE, | ||
1250 | .op_name = "OP_PUTPUBFH", | 1302 | .op_name = "OP_PUTPUBFH", |
1251 | }, | 1303 | }, |
1252 | [OP_PUTROOTFH] = { | 1304 | [OP_PUTROOTFH] = { |
1253 | .op_func = (nfsd4op_func)nfsd4_putrootfh, | 1305 | .op_func = (nfsd4op_func)nfsd4_putrootfh, |
1254 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, | 1306 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS |
1307 | | OP_IS_PUTFH_LIKE, | ||
1255 | .op_name = "OP_PUTROOTFH", | 1308 | .op_name = "OP_PUTROOTFH", |
1256 | }, | 1309 | }, |
1257 | [OP_READ] = { | 1310 | [OP_READ] = { |
@@ -1281,15 +1334,18 @@ static struct nfsd4_operation nfsd4_ops[] = { | |||
1281 | }, | 1334 | }, |
1282 | [OP_RESTOREFH] = { | 1335 | [OP_RESTOREFH] = { |
1283 | .op_func = (nfsd4op_func)nfsd4_restorefh, | 1336 | .op_func = (nfsd4op_func)nfsd4_restorefh, |
1284 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, | 1337 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS |
1338 | | OP_IS_PUTFH_LIKE, | ||
1285 | .op_name = "OP_RESTOREFH", | 1339 | .op_name = "OP_RESTOREFH", |
1286 | }, | 1340 | }, |
1287 | [OP_SAVEFH] = { | 1341 | [OP_SAVEFH] = { |
1288 | .op_func = (nfsd4op_func)nfsd4_savefh, | 1342 | .op_func = (nfsd4op_func)nfsd4_savefh, |
1343 | .op_flags = OP_HANDLES_WRONGSEC, | ||
1289 | .op_name = "OP_SAVEFH", | 1344 | .op_name = "OP_SAVEFH", |
1290 | }, | 1345 | }, |
1291 | [OP_SECINFO] = { | 1346 | [OP_SECINFO] = { |
1292 | .op_func = (nfsd4op_func)nfsd4_secinfo, | 1347 | .op_func = (nfsd4op_func)nfsd4_secinfo, |
1348 | .op_flags = OP_HANDLES_WRONGSEC, | ||
1293 | .op_name = "OP_SECINFO", | 1349 | .op_name = "OP_SECINFO", |
1294 | }, | 1350 | }, |
1295 | [OP_SETATTR] = { | 1351 | [OP_SETATTR] = { |
@@ -1353,6 +1409,7 @@ static struct nfsd4_operation nfsd4_ops[] = { | |||
1353 | }, | 1409 | }, |
1354 | [OP_SECINFO_NO_NAME] = { | 1410 | [OP_SECINFO_NO_NAME] = { |
1355 | .op_func = (nfsd4op_func)nfsd4_secinfo_no_name, | 1411 | .op_func = (nfsd4op_func)nfsd4_secinfo_no_name, |
1412 | .op_flags = OP_HANDLES_WRONGSEC, | ||
1356 | .op_name = "OP_SECINFO_NO_NAME", | 1413 | .op_name = "OP_SECINFO_NO_NAME", |
1357 | }, | 1414 | }, |
1358 | }; | 1415 | }; |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 4cf04e11c66c..e98f3c2e9492 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -1519,6 +1519,9 @@ nfsd4_create_session(struct svc_rqst *rqstp, | |||
1519 | bool confirm_me = false; | 1519 | bool confirm_me = false; |
1520 | int status = 0; | 1520 | int status = 0; |
1521 | 1521 | ||
1522 | if (cr_ses->flags & ~SESSION4_FLAG_MASK_A) | ||
1523 | return nfserr_inval; | ||
1524 | |||
1522 | nfs4_lock_state(); | 1525 | nfs4_lock_state(); |
1523 | unconf = find_unconfirmed_client(&cr_ses->clientid); | 1526 | unconf = find_unconfirmed_client(&cr_ses->clientid); |
1524 | conf = find_confirmed_client(&cr_ses->clientid); | 1527 | conf = find_confirmed_client(&cr_ses->clientid); |
@@ -1637,8 +1640,9 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp, | |||
1637 | return nfserr_badsession; | 1640 | return nfserr_badsession; |
1638 | 1641 | ||
1639 | status = nfsd4_map_bcts_dir(&bcts->dir); | 1642 | status = nfsd4_map_bcts_dir(&bcts->dir); |
1640 | nfsd4_new_conn(rqstp, cstate->session, bcts->dir); | 1643 | if (!status) |
1641 | return nfs_ok; | 1644 | nfsd4_new_conn(rqstp, cstate->session, bcts->dir); |
1645 | return status; | ||
1642 | } | 1646 | } |
1643 | 1647 | ||
1644 | static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid) | 1648 | static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid) |
@@ -1725,6 +1729,13 @@ static void nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_sessi | |||
1725 | return; | 1729 | return; |
1726 | } | 1730 | } |
1727 | 1731 | ||
1732 | static bool nfsd4_session_too_many_ops(struct svc_rqst *rqstp, struct nfsd4_session *session) | ||
1733 | { | ||
1734 | struct nfsd4_compoundargs *args = rqstp->rq_argp; | ||
1735 | |||
1736 | return args->opcnt > session->se_fchannel.maxops; | ||
1737 | } | ||
1738 | |||
1728 | __be32 | 1739 | __be32 |
1729 | nfsd4_sequence(struct svc_rqst *rqstp, | 1740 | nfsd4_sequence(struct svc_rqst *rqstp, |
1730 | struct nfsd4_compound_state *cstate, | 1741 | struct nfsd4_compound_state *cstate, |
@@ -1753,6 +1764,10 @@ nfsd4_sequence(struct svc_rqst *rqstp, | |||
1753 | if (!session) | 1764 | if (!session) |
1754 | goto out; | 1765 | goto out; |
1755 | 1766 | ||
1767 | status = nfserr_too_many_ops; | ||
1768 | if (nfsd4_session_too_many_ops(rqstp, session)) | ||
1769 | goto out; | ||
1770 | |||
1756 | status = nfserr_badslot; | 1771 | status = nfserr_badslot; |
1757 | if (seq->slotid >= session->se_fchannel.maxreqs) | 1772 | if (seq->slotid >= session->se_fchannel.maxreqs) |
1758 | goto out; | 1773 | goto out; |
@@ -1808,6 +1823,8 @@ out: | |||
1808 | __be32 | 1823 | __be32 |
1809 | nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_reclaim_complete *rc) | 1824 | nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_reclaim_complete *rc) |
1810 | { | 1825 | { |
1826 | int status = 0; | ||
1827 | |||
1811 | if (rc->rca_one_fs) { | 1828 | if (rc->rca_one_fs) { |
1812 | if (!cstate->current_fh.fh_dentry) | 1829 | if (!cstate->current_fh.fh_dentry) |
1813 | return nfserr_nofilehandle; | 1830 | return nfserr_nofilehandle; |
@@ -1817,9 +1834,14 @@ nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta | |||
1817 | */ | 1834 | */ |
1818 | return nfs_ok; | 1835 | return nfs_ok; |
1819 | } | 1836 | } |
1837 | |||
1820 | nfs4_lock_state(); | 1838 | nfs4_lock_state(); |
1821 | if (is_client_expired(cstate->session->se_client)) { | 1839 | status = nfserr_complete_already; |
1822 | nfs4_unlock_state(); | 1840 | if (cstate->session->se_client->cl_firststate) |
1841 | goto out; | ||
1842 | |||
1843 | status = nfserr_stale_clientid; | ||
1844 | if (is_client_expired(cstate->session->se_client)) | ||
1823 | /* | 1845 | /* |
1824 | * The following error isn't really legal. | 1846 | * The following error isn't really legal. |
1825 | * But we only get here if the client just explicitly | 1847 | * But we only get here if the client just explicitly |
@@ -1827,11 +1849,13 @@ nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta | |||
1827 | * error it gets back on an operation for the dead | 1849 | * error it gets back on an operation for the dead |
1828 | * client. | 1850 | * client. |
1829 | */ | 1851 | */ |
1830 | return nfserr_stale_clientid; | 1852 | goto out; |
1831 | } | 1853 | |
1854 | status = nfs_ok; | ||
1832 | nfsd4_create_clid_dir(cstate->session->se_client); | 1855 | nfsd4_create_clid_dir(cstate->session->se_client); |
1856 | out: | ||
1833 | nfs4_unlock_state(); | 1857 | nfs4_unlock_state(); |
1834 | return nfs_ok; | 1858 | return status; |
1835 | } | 1859 | } |
1836 | 1860 | ||
1837 | __be32 | 1861 | __be32 |
@@ -2462,7 +2486,7 @@ find_delegation_file(struct nfs4_file *fp, stateid_t *stid) | |||
2462 | return NULL; | 2486 | return NULL; |
2463 | } | 2487 | } |
2464 | 2488 | ||
2465 | int share_access_to_flags(u32 share_access) | 2489 | static int share_access_to_flags(u32 share_access) |
2466 | { | 2490 | { |
2467 | share_access &= ~NFS4_SHARE_WANT_MASK; | 2491 | share_access &= ~NFS4_SHARE_WANT_MASK; |
2468 | 2492 | ||
@@ -2882,7 +2906,7 @@ out: | |||
2882 | return status; | 2906 | return status; |
2883 | } | 2907 | } |
2884 | 2908 | ||
2885 | struct lock_manager nfsd4_manager = { | 2909 | static struct lock_manager nfsd4_manager = { |
2886 | }; | 2910 | }; |
2887 | 2911 | ||
2888 | static void | 2912 | static void |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index c6766af00d98..990181103214 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -424,15 +424,12 @@ nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access | |||
424 | static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts) | 424 | static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts) |
425 | { | 425 | { |
426 | DECODE_HEAD; | 426 | DECODE_HEAD; |
427 | u32 dummy; | ||
428 | 427 | ||
429 | READ_BUF(NFS4_MAX_SESSIONID_LEN + 8); | 428 | READ_BUF(NFS4_MAX_SESSIONID_LEN + 8); |
430 | COPYMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN); | 429 | COPYMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN); |
431 | READ32(bcts->dir); | 430 | READ32(bcts->dir); |
432 | /* XXX: Perhaps Tom Tucker could help us figure out how we | 431 | /* XXX: skipping ctsa_use_conn_in_rdma_mode. Perhaps Tom Tucker |
433 | * should be using ctsa_use_conn_in_rdma_mode: */ | 432 | * could help us figure out we should be using it. */ |
434 | READ32(dummy); | ||
435 | |||
436 | DECODE_TAIL; | 433 | DECODE_TAIL; |
437 | } | 434 | } |
438 | 435 | ||
@@ -588,8 +585,6 @@ nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt) | |||
588 | READ_BUF(lockt->lt_owner.len); | 585 | READ_BUF(lockt->lt_owner.len); |
589 | READMEM(lockt->lt_owner.data, lockt->lt_owner.len); | 586 | READMEM(lockt->lt_owner.data, lockt->lt_owner.len); |
590 | 587 | ||
591 | if (argp->minorversion && !zero_clientid(&lockt->lt_clientid)) | ||
592 | return nfserr_inval; | ||
593 | DECODE_TAIL; | 588 | DECODE_TAIL; |
594 | } | 589 | } |
595 | 590 | ||
@@ -3120,7 +3115,7 @@ nfsd4_encode_destroy_session(struct nfsd4_compoundres *resp, int nfserr, | |||
3120 | return nfserr; | 3115 | return nfserr; |
3121 | } | 3116 | } |
3122 | 3117 | ||
3123 | __be32 | 3118 | static __be32 |
3124 | nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr, | 3119 | nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr, |
3125 | struct nfsd4_sequence *seq) | 3120 | struct nfsd4_sequence *seq) |
3126 | { | 3121 | { |
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 55c8e63af0be..90c6aa6d5e0f 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
@@ -344,7 +344,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
344 | * which clients virtually always use auth_sys for, | 344 | * which clients virtually always use auth_sys for, |
345 | * even while using RPCSEC_GSS for NFS. | 345 | * even while using RPCSEC_GSS for NFS. |
346 | */ | 346 | */ |
347 | if (access & NFSD_MAY_LOCK) | 347 | if (access & NFSD_MAY_LOCK || access & NFSD_MAY_BYPASS_GSS) |
348 | goto skip_pseudoflavor_check; | 348 | goto skip_pseudoflavor_check; |
349 | /* | 349 | /* |
350 | * Clients may expect to be able to use auth_sys during mount, | 350 | * Clients may expect to be able to use auth_sys during mount, |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 129f3c9f62d5..d5718273bb32 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -181,16 +181,10 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
181 | struct svc_export *exp; | 181 | struct svc_export *exp; |
182 | struct dentry *dparent; | 182 | struct dentry *dparent; |
183 | struct dentry *dentry; | 183 | struct dentry *dentry; |
184 | __be32 err; | ||
185 | int host_err; | 184 | int host_err; |
186 | 185 | ||
187 | dprintk("nfsd: nfsd_lookup(fh %s, %.*s)\n", SVCFH_fmt(fhp), len,name); | 186 | dprintk("nfsd: nfsd_lookup(fh %s, %.*s)\n", SVCFH_fmt(fhp), len,name); |
188 | 187 | ||
189 | /* Obtain dentry and export. */ | ||
190 | err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC); | ||
191 | if (err) | ||
192 | return err; | ||
193 | |||
194 | dparent = fhp->fh_dentry; | 188 | dparent = fhp->fh_dentry; |
195 | exp = fhp->fh_export; | 189 | exp = fhp->fh_export; |
196 | exp_get(exp); | 190 | exp_get(exp); |
@@ -254,6 +248,9 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, | |||
254 | struct dentry *dentry; | 248 | struct dentry *dentry; |
255 | __be32 err; | 249 | __be32 err; |
256 | 250 | ||
251 | err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC); | ||
252 | if (err) | ||
253 | return err; | ||
257 | err = nfsd_lookup_dentry(rqstp, fhp, name, len, &exp, &dentry); | 254 | err = nfsd_lookup_dentry(rqstp, fhp, name, len, &exp, &dentry); |
258 | if (err) | 255 | if (err) |
259 | return err; | 256 | return err; |
@@ -877,13 +874,11 @@ static __be32 | |||
877 | nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | 874 | nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, |
878 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) | 875 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) |
879 | { | 876 | { |
880 | struct inode *inode; | ||
881 | mm_segment_t oldfs; | 877 | mm_segment_t oldfs; |
882 | __be32 err; | 878 | __be32 err; |
883 | int host_err; | 879 | int host_err; |
884 | 880 | ||
885 | err = nfserr_perm; | 881 | err = nfserr_perm; |
886 | inode = file->f_path.dentry->d_inode; | ||
887 | 882 | ||
888 | if (file->f_op->splice_read && rqstp->rq_splice_ok) { | 883 | if (file->f_op->splice_read && rqstp->rq_splice_ok) { |
889 | struct splice_desc sd = { | 884 | struct splice_desc sd = { |
@@ -1340,11 +1335,18 @@ out_nfserr: | |||
1340 | } | 1335 | } |
1341 | 1336 | ||
1342 | #ifdef CONFIG_NFSD_V3 | 1337 | #ifdef CONFIG_NFSD_V3 |
1338 | |||
1339 | static inline int nfsd_create_is_exclusive(int createmode) | ||
1340 | { | ||
1341 | return createmode == NFS3_CREATE_EXCLUSIVE | ||
1342 | || createmode == NFS4_CREATE_EXCLUSIVE4_1; | ||
1343 | } | ||
1344 | |||
1343 | /* | 1345 | /* |
1344 | * NFSv3 version of nfsd_create | 1346 | * NFSv3 and NFSv4 version of nfsd_create |
1345 | */ | 1347 | */ |
1346 | __be32 | 1348 | __be32 |
1347 | nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | 1349 | do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, |
1348 | char *fname, int flen, struct iattr *iap, | 1350 | char *fname, int flen, struct iattr *iap, |
1349 | struct svc_fh *resfhp, int createmode, u32 *verifier, | 1351 | struct svc_fh *resfhp, int createmode, u32 *verifier, |
1350 | int *truncp, int *created) | 1352 | int *truncp, int *created) |
@@ -1396,7 +1398,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1396 | if (err) | 1398 | if (err) |
1397 | goto out; | 1399 | goto out; |
1398 | 1400 | ||
1399 | if (createmode == NFS3_CREATE_EXCLUSIVE) { | 1401 | if (nfsd_create_is_exclusive(createmode)) { |
1400 | /* solaris7 gets confused (bugid 4218508) if these have | 1402 | /* solaris7 gets confused (bugid 4218508) if these have |
1401 | * the high bit set, so just clear the high bits. If this is | 1403 | * the high bit set, so just clear the high bits. If this is |
1402 | * ever changed to use different attrs for storing the | 1404 | * ever changed to use different attrs for storing the |
@@ -1437,6 +1439,11 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1437 | && dchild->d_inode->i_atime.tv_sec == v_atime | 1439 | && dchild->d_inode->i_atime.tv_sec == v_atime |
1438 | && dchild->d_inode->i_size == 0 ) | 1440 | && dchild->d_inode->i_size == 0 ) |
1439 | break; | 1441 | break; |
1442 | case NFS4_CREATE_EXCLUSIVE4_1: | ||
1443 | if ( dchild->d_inode->i_mtime.tv_sec == v_mtime | ||
1444 | && dchild->d_inode->i_atime.tv_sec == v_atime | ||
1445 | && dchild->d_inode->i_size == 0 ) | ||
1446 | goto set_attr; | ||
1440 | /* fallthru */ | 1447 | /* fallthru */ |
1441 | case NFS3_CREATE_GUARDED: | 1448 | case NFS3_CREATE_GUARDED: |
1442 | err = nfserr_exist; | 1449 | err = nfserr_exist; |
@@ -1455,7 +1462,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1455 | 1462 | ||
1456 | nfsd_check_ignore_resizing(iap); | 1463 | nfsd_check_ignore_resizing(iap); |
1457 | 1464 | ||
1458 | if (createmode == NFS3_CREATE_EXCLUSIVE) { | 1465 | if (nfsd_create_is_exclusive(createmode)) { |
1459 | /* Cram the verifier into atime/mtime */ | 1466 | /* Cram the verifier into atime/mtime */ |
1460 | iap->ia_valid = ATTR_MTIME|ATTR_ATIME | 1467 | iap->ia_valid = ATTR_MTIME|ATTR_ATIME |
1461 | | ATTR_MTIME_SET|ATTR_ATIME_SET; | 1468 | | ATTR_MTIME_SET|ATTR_ATIME_SET; |
@@ -2034,7 +2041,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp, | |||
2034 | struct inode *inode = dentry->d_inode; | 2041 | struct inode *inode = dentry->d_inode; |
2035 | int err; | 2042 | int err; |
2036 | 2043 | ||
2037 | if (acc == NFSD_MAY_NOP) | 2044 | if ((acc & NFSD_MAY_MASK) == NFSD_MAY_NOP) |
2038 | return 0; | 2045 | return 0; |
2039 | #if 0 | 2046 | #if 0 |
2040 | dprintk("nfsd: permission 0x%x%s%s%s%s%s%s%s mode 0%o%s%s%s\n", | 2047 | dprintk("nfsd: permission 0x%x%s%s%s%s%s%s%s mode 0%o%s%s%s\n", |
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h index 9a370a5e36b7..e0bbac04d1dd 100644 --- a/fs/nfsd/vfs.h +++ b/fs/nfsd/vfs.h | |||
@@ -17,10 +17,14 @@ | |||
17 | #define NFSD_MAY_SATTR 8 | 17 | #define NFSD_MAY_SATTR 8 |
18 | #define NFSD_MAY_TRUNC 16 | 18 | #define NFSD_MAY_TRUNC 16 |
19 | #define NFSD_MAY_LOCK 32 | 19 | #define NFSD_MAY_LOCK 32 |
20 | #define NFSD_MAY_MASK 63 | ||
21 | |||
22 | /* extra hints to permission and open routines: */ | ||
20 | #define NFSD_MAY_OWNER_OVERRIDE 64 | 23 | #define NFSD_MAY_OWNER_OVERRIDE 64 |
21 | #define NFSD_MAY_LOCAL_ACCESS 128 /* IRIX doing local access check on device special file*/ | 24 | #define NFSD_MAY_LOCAL_ACCESS 128 /* IRIX doing local access check on device special file*/ |
22 | #define NFSD_MAY_BYPASS_GSS_ON_ROOT 256 | 25 | #define NFSD_MAY_BYPASS_GSS_ON_ROOT 256 |
23 | #define NFSD_MAY_NOT_BREAK_LEASE 512 | 26 | #define NFSD_MAY_NOT_BREAK_LEASE 512 |
27 | #define NFSD_MAY_BYPASS_GSS 1024 | ||
24 | 28 | ||
25 | #define NFSD_MAY_CREATE (NFSD_MAY_EXEC|NFSD_MAY_WRITE) | 29 | #define NFSD_MAY_CREATE (NFSD_MAY_EXEC|NFSD_MAY_WRITE) |
26 | #define NFSD_MAY_REMOVE (NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC) | 30 | #define NFSD_MAY_REMOVE (NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC) |
@@ -54,7 +58,7 @@ __be32 nfsd_create(struct svc_rqst *, struct svc_fh *, | |||
54 | int type, dev_t rdev, struct svc_fh *res); | 58 | int type, dev_t rdev, struct svc_fh *res); |
55 | #ifdef CONFIG_NFSD_V3 | 59 | #ifdef CONFIG_NFSD_V3 |
56 | __be32 nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *); | 60 | __be32 nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *); |
57 | __be32 nfsd_create_v3(struct svc_rqst *, struct svc_fh *, | 61 | __be32 do_nfsd_create(struct svc_rqst *, struct svc_fh *, |
58 | char *name, int len, struct iattr *attrs, | 62 | char *name, int len, struct iattr *attrs, |
59 | struct svc_fh *res, int createmode, | 63 | struct svc_fh *res, int createmode, |
60 | u32 *verifier, int *truncp, int *created); | 64 | u32 *verifier, int *truncp, int *created); |