aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4proc.c')
-rw-r--r--fs/nfsd/nfs4proc.c59
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
409static __be32 409static __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
994struct nfsd4_operation { 997struct 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
1045static 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
1137encode_op: 1176encode_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};