diff options
Diffstat (limited to 'fs/nfsd/nfs4proc.c')
-rw-r--r-- | fs/nfsd/nfs4proc.c | 59 |
1 files changed, 54 insertions, 5 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 8059adae013b..ad32568a1aa7 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -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 |
@@ -989,6 +989,9 @@ enum nfsd4_op_flags { | |||
989 | ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */ | 989 | ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */ |
990 | ALLOWED_ON_ABSENT_FS = 1 << 1, /* ops processed on absent fs */ | 990 | ALLOWED_ON_ABSENT_FS = 1 << 1, /* ops processed on absent fs */ |
991 | 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, | ||
992 | }; | 995 | }; |
993 | 996 | ||
994 | struct nfsd4_operation { | 997 | struct nfsd4_operation { |
@@ -1039,6 +1042,39 @@ static inline struct nfsd4_operation *OPDESC(struct nfsd4_op *op) | |||
1039 | return &nfsd4_ops[op->opnum]; | 1042 | return &nfsd4_ops[op->opnum]; |
1040 | } | 1043 | } |
1041 | 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 | |||
1042 | /* | 1078 | /* |
1043 | * COMPOUND call. | 1079 | * COMPOUND call. |
1044 | */ | 1080 | */ |
@@ -1134,6 +1170,9 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, | |||
1134 | else | 1170 | else |
1135 | BUG_ON(op->status == nfs_ok); | 1171 | BUG_ON(op->status == nfs_ok); |
1136 | 1172 | ||
1173 | if (!op->status && need_wrongsec_check(rqstp)) | ||
1174 | op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp); | ||
1175 | |||
1137 | encode_op: | 1176 | encode_op: |
1138 | /* Only from SEQUENCE */ | 1177 | /* Only from SEQUENCE */ |
1139 | if (resp->cstate.status == nfserr_replay_cache) { | 1178 | if (resp->cstate.status == nfserr_replay_cache) { |
@@ -1225,10 +1264,12 @@ static struct nfsd4_operation nfsd4_ops[] = { | |||
1225 | }, | 1264 | }, |
1226 | [OP_LOOKUP] = { | 1265 | [OP_LOOKUP] = { |
1227 | .op_func = (nfsd4op_func)nfsd4_lookup, | 1266 | .op_func = (nfsd4op_func)nfsd4_lookup, |
1267 | .op_flags = OP_HANDLES_WRONGSEC, | ||
1228 | .op_name = "OP_LOOKUP", | 1268 | .op_name = "OP_LOOKUP", |
1229 | }, | 1269 | }, |
1230 | [OP_LOOKUPP] = { | 1270 | [OP_LOOKUPP] = { |
1231 | .op_func = (nfsd4op_func)nfsd4_lookupp, | 1271 | .op_func = (nfsd4op_func)nfsd4_lookupp, |
1272 | .op_flags = OP_HANDLES_WRONGSEC, | ||
1232 | .op_name = "OP_LOOKUPP", | 1273 | .op_name = "OP_LOOKUPP", |
1233 | }, | 1274 | }, |
1234 | [OP_NVERIFY] = { | 1275 | [OP_NVERIFY] = { |
@@ -1237,6 +1278,7 @@ static struct nfsd4_operation nfsd4_ops[] = { | |||
1237 | }, | 1278 | }, |
1238 | [OP_OPEN] = { | 1279 | [OP_OPEN] = { |
1239 | .op_func = (nfsd4op_func)nfsd4_open, | 1280 | .op_func = (nfsd4op_func)nfsd4_open, |
1281 | .op_flags = OP_HANDLES_WRONGSEC, | ||
1240 | .op_name = "OP_OPEN", | 1282 | .op_name = "OP_OPEN", |
1241 | }, | 1283 | }, |
1242 | [OP_OPEN_CONFIRM] = { | 1284 | [OP_OPEN_CONFIRM] = { |
@@ -1249,17 +1291,20 @@ static struct nfsd4_operation nfsd4_ops[] = { | |||
1249 | }, | 1291 | }, |
1250 | [OP_PUTFH] = { | 1292 | [OP_PUTFH] = { |
1251 | .op_func = (nfsd4op_func)nfsd4_putfh, | 1293 | .op_func = (nfsd4op_func)nfsd4_putfh, |
1252 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, | 1294 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS |
1295 | | OP_IS_PUTFH_LIKE, | ||
1253 | .op_name = "OP_PUTFH", | 1296 | .op_name = "OP_PUTFH", |
1254 | }, | 1297 | }, |
1255 | [OP_PUTPUBFH] = { | 1298 | [OP_PUTPUBFH] = { |
1256 | .op_func = (nfsd4op_func)nfsd4_putrootfh, | 1299 | .op_func = (nfsd4op_func)nfsd4_putrootfh, |
1257 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, | 1300 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS |
1301 | | OP_IS_PUTFH_LIKE, | ||
1258 | .op_name = "OP_PUTPUBFH", | 1302 | .op_name = "OP_PUTPUBFH", |
1259 | }, | 1303 | }, |
1260 | [OP_PUTROOTFH] = { | 1304 | [OP_PUTROOTFH] = { |
1261 | .op_func = (nfsd4op_func)nfsd4_putrootfh, | 1305 | .op_func = (nfsd4op_func)nfsd4_putrootfh, |
1262 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, | 1306 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS |
1307 | | OP_IS_PUTFH_LIKE, | ||
1263 | .op_name = "OP_PUTROOTFH", | 1308 | .op_name = "OP_PUTROOTFH", |
1264 | }, | 1309 | }, |
1265 | [OP_READ] = { | 1310 | [OP_READ] = { |
@@ -1289,15 +1334,18 @@ static struct nfsd4_operation nfsd4_ops[] = { | |||
1289 | }, | 1334 | }, |
1290 | [OP_RESTOREFH] = { | 1335 | [OP_RESTOREFH] = { |
1291 | .op_func = (nfsd4op_func)nfsd4_restorefh, | 1336 | .op_func = (nfsd4op_func)nfsd4_restorefh, |
1292 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, | 1337 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS |
1338 | | OP_IS_PUTFH_LIKE, | ||
1293 | .op_name = "OP_RESTOREFH", | 1339 | .op_name = "OP_RESTOREFH", |
1294 | }, | 1340 | }, |
1295 | [OP_SAVEFH] = { | 1341 | [OP_SAVEFH] = { |
1296 | .op_func = (nfsd4op_func)nfsd4_savefh, | 1342 | .op_func = (nfsd4op_func)nfsd4_savefh, |
1343 | .op_flags = OP_HANDLES_WRONGSEC, | ||
1297 | .op_name = "OP_SAVEFH", | 1344 | .op_name = "OP_SAVEFH", |
1298 | }, | 1345 | }, |
1299 | [OP_SECINFO] = { | 1346 | [OP_SECINFO] = { |
1300 | .op_func = (nfsd4op_func)nfsd4_secinfo, | 1347 | .op_func = (nfsd4op_func)nfsd4_secinfo, |
1348 | .op_flags = OP_HANDLES_WRONGSEC, | ||
1301 | .op_name = "OP_SECINFO", | 1349 | .op_name = "OP_SECINFO", |
1302 | }, | 1350 | }, |
1303 | [OP_SETATTR] = { | 1351 | [OP_SETATTR] = { |
@@ -1361,6 +1409,7 @@ static struct nfsd4_operation nfsd4_ops[] = { | |||
1361 | }, | 1409 | }, |
1362 | [OP_SECINFO_NO_NAME] = { | 1410 | [OP_SECINFO_NO_NAME] = { |
1363 | .op_func = (nfsd4op_func)nfsd4_secinfo_no_name, | 1411 | .op_func = (nfsd4op_func)nfsd4_secinfo_no_name, |
1412 | .op_flags = OP_HANDLES_WRONGSEC, | ||
1364 | .op_name = "OP_SECINFO_NO_NAME", | 1413 | .op_name = "OP_SECINFO_NO_NAME", |
1365 | }, | 1414 | }, |
1366 | }; | 1415 | }; |