nfs4proc.c (07f9479a40cc778bc1462ada11f95b01360ae4ff) nfs4proc.c (68d93184352f2e723f135b0a9bad93b58f9d120b)
1/*
2 * Server-side procedures for NFSv4.
3 *
4 * Copyright (c) 2002 The Regents of the University of Michigan.
5 * All rights reserved.
6 *
7 * Kendrick Smith <kmsmith@umich.edu>
8 * Andy Adamson <andros@umich.edu>

--- 389 unchanged lines hidden (view full) ---

398static __be32
399nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
400 struct nfsd4_putfh *putfh)
401{
402 fh_put(&cstate->current_fh);
403 cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
404 memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
405 putfh->pf_fhlen);
1/*
2 * Server-side procedures for NFSv4.
3 *
4 * Copyright (c) 2002 The Regents of the University of Michigan.
5 * All rights reserved.
6 *
7 * Kendrick Smith <kmsmith@umich.edu>
8 * Andy Adamson <andros@umich.edu>

--- 389 unchanged lines hidden (view full) ---

398static __be32
399nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
400 struct nfsd4_putfh *putfh)
401{
402 fh_put(&cstate->current_fh);
403 cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
404 memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
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}
408
409static __be32
410nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
411 void *arg)
412{
413 __be32 status;
414

--- 342 unchanged lines hidden (view full) ---

757 struct nfsd4_secinfo *secinfo)
758{
759 struct svc_fh resfh;
760 struct svc_export *exp;
761 struct dentry *dentry;
762 __be32 err;
763
764 fh_init(&resfh, NFS4_FHSIZE);
407}
408
409static __be32
410nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
411 void *arg)
412{
413 __be32 status;
414

--- 342 unchanged lines hidden (view full) ---

757 struct nfsd4_secinfo *secinfo)
758{
759 struct svc_fh resfh;
760 struct svc_export *exp;
761 struct dentry *dentry;
762 __be32 err;
763
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,
766 secinfo->si_name, secinfo->si_namelen,
767 &exp, &dentry);
768 if (err)
769 return err;
770 if (dentry->d_inode == NULL) {
771 exp_put(exp);
772 err = nfserr_noent;

--- 208 unchanged lines hidden (view full) ---

981}
982
983typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *,
984 void *);
985enum nfsd4_op_flags {
986 ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */
987 ALLOWED_ON_ABSENT_FS = 1 << 1, /* ops processed on absent fs */
988 ALLOWED_AS_FIRST_OP = 1 << 2, /* ops reqired first in compound */
768 err = nfsd_lookup_dentry(rqstp, &cstate->current_fh,
769 secinfo->si_name, secinfo->si_namelen,
770 &exp, &dentry);
771 if (err)
772 return err;
773 if (dentry->d_inode == NULL) {
774 exp_put(exp);
775 err = nfserr_noent;

--- 208 unchanged lines hidden (view full) ---

984}
985
986typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *,
987 void *);
988enum nfsd4_op_flags {
989 ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */
990 ALLOWED_ON_ABSENT_FS = 1 << 1, /* ops processed on absent fs */
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};
990
991struct nfsd4_operation {
992 nfsd4op_func op_func;
993 u32 op_flags;
994 char *op_name;
995};
996

--- 29 unchanged lines hidden (view full) ---

1026 return nfserr_op_not_in_session;
1027 if (op->opnum == OP_SEQUENCE)
1028 return nfs_ok;
1029 if (args->opcnt != 1)
1030 return nfserr_not_only_op;
1031 return nfs_ok;
1032}
1033
995};
996
997struct nfsd4_operation {
998 nfsd4op_func op_func;
999 u32 op_flags;
1000 char *op_name;
1001};
1002

--- 29 unchanged lines hidden (view full) ---

1032 return nfserr_op_not_in_session;
1033 if (op->opnum == OP_SEQUENCE)
1034 return nfs_ok;
1035 if (args->opcnt != 1)
1036 return nfserr_not_only_op;
1037 return nfs_ok;
1038}
1039
1040static inline struct nfsd4_operation *OPDESC(struct nfsd4_op *op)
1041{
1042 return &nfsd4_ops[op->opnum];
1043}
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
1034/*
1035 * COMPOUND call.
1036 */
1037static __be32
1038nfsd4_proc_compound(struct svc_rqst *rqstp,
1039 struct nfsd4_compoundargs *args,
1040 struct nfsd4_compoundres *resp)
1041{

--- 61 unchanged lines hidden (view full) ---

1103 slack_bytes = (char *)resp->end - (char *)resp->p;
1104 if (slack_bytes < COMPOUND_SLACK_SPACE
1105 + COMPOUND_ERR_SLACK_SPACE) {
1106 BUG_ON(slack_bytes < COMPOUND_ERR_SLACK_SPACE);
1107 op->status = nfserr_resource;
1108 goto encode_op;
1109 }
1110
1078/*
1079 * COMPOUND call.
1080 */
1081static __be32
1082nfsd4_proc_compound(struct svc_rqst *rqstp,
1083 struct nfsd4_compoundargs *args,
1084 struct nfsd4_compoundres *resp)
1085{

--- 61 unchanged lines hidden (view full) ---

1147 slack_bytes = (char *)resp->end - (char *)resp->p;
1148 if (slack_bytes < COMPOUND_SLACK_SPACE
1149 + COMPOUND_ERR_SLACK_SPACE) {
1150 BUG_ON(slack_bytes < COMPOUND_ERR_SLACK_SPACE);
1151 op->status = nfserr_resource;
1152 goto encode_op;
1153 }
1154
1111 opdesc = &nfsd4_ops[op->opnum];
1155 opdesc = OPDESC(op);
1112
1113 if (!cstate->current_fh.fh_dentry) {
1114 if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
1115 op->status = nfserr_nofilehandle;
1116 goto encode_op;
1117 }
1118 } else if (cstate->current_fh.fh_export->ex_fslocs.migrated &&
1119 !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {
1120 op->status = nfserr_moved;
1121 goto encode_op;
1122 }
1123
1124 if (opdesc->op_func)
1125 op->status = opdesc->op_func(rqstp, cstate, &op->u);
1126 else
1127 BUG_ON(op->status == nfs_ok);
1128
1156
1157 if (!cstate->current_fh.fh_dentry) {
1158 if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
1159 op->status = nfserr_nofilehandle;
1160 goto encode_op;
1161 }
1162 } else if (cstate->current_fh.fh_export->ex_fslocs.migrated &&
1163 !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {
1164 op->status = nfserr_moved;
1165 goto encode_op;
1166 }
1167
1168 if (opdesc->op_func)
1169 op->status = opdesc->op_func(rqstp, cstate, &op->u);
1170 else
1171 BUG_ON(op->status == nfs_ok);
1172
1173 if (!op->status && need_wrongsec_check(rqstp))
1174 op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp);
1175
1129encode_op:
1130 /* Only from SEQUENCE */
1131 if (resp->cstate.status == nfserr_replay_cache) {
1132 dprintk("%s NFS4.1 replay from cache\n", __func__);
1133 status = op->status;
1134 goto out;
1135 }
1136 if (op->status == nfserr_replay_me) {

--- 75 unchanged lines hidden (view full) ---

1212 .op_name = "OP_LOCKT",
1213 },
1214 [OP_LOCKU] = {
1215 .op_func = (nfsd4op_func)nfsd4_locku,
1216 .op_name = "OP_LOCKU",
1217 },
1218 [OP_LOOKUP] = {
1219 .op_func = (nfsd4op_func)nfsd4_lookup,
1176encode_op:
1177 /* Only from SEQUENCE */
1178 if (resp->cstate.status == nfserr_replay_cache) {
1179 dprintk("%s NFS4.1 replay from cache\n", __func__);
1180 status = op->status;
1181 goto out;
1182 }
1183 if (op->status == nfserr_replay_me) {

--- 75 unchanged lines hidden (view full) ---

1259 .op_name = "OP_LOCKT",
1260 },
1261 [OP_LOCKU] = {
1262 .op_func = (nfsd4op_func)nfsd4_locku,
1263 .op_name = "OP_LOCKU",
1264 },
1265 [OP_LOOKUP] = {
1266 .op_func = (nfsd4op_func)nfsd4_lookup,
1267 .op_flags = OP_HANDLES_WRONGSEC,
1220 .op_name = "OP_LOOKUP",
1221 },
1222 [OP_LOOKUPP] = {
1223 .op_func = (nfsd4op_func)nfsd4_lookupp,
1268 .op_name = "OP_LOOKUP",
1269 },
1270 [OP_LOOKUPP] = {
1271 .op_func = (nfsd4op_func)nfsd4_lookupp,
1272 .op_flags = OP_HANDLES_WRONGSEC,
1224 .op_name = "OP_LOOKUPP",
1225 },
1226 [OP_NVERIFY] = {
1227 .op_func = (nfsd4op_func)nfsd4_nverify,
1228 .op_name = "OP_NVERIFY",
1229 },
1230 [OP_OPEN] = {
1231 .op_func = (nfsd4op_func)nfsd4_open,
1273 .op_name = "OP_LOOKUPP",
1274 },
1275 [OP_NVERIFY] = {
1276 .op_func = (nfsd4op_func)nfsd4_nverify,
1277 .op_name = "OP_NVERIFY",
1278 },
1279 [OP_OPEN] = {
1280 .op_func = (nfsd4op_func)nfsd4_open,
1281 .op_flags = OP_HANDLES_WRONGSEC,
1232 .op_name = "OP_OPEN",
1233 },
1234 [OP_OPEN_CONFIRM] = {
1235 .op_func = (nfsd4op_func)nfsd4_open_confirm,
1236 .op_name = "OP_OPEN_CONFIRM",
1237 },
1238 [OP_OPEN_DOWNGRADE] = {
1239 .op_func = (nfsd4op_func)nfsd4_open_downgrade,
1240 .op_name = "OP_OPEN_DOWNGRADE",
1241 },
1242 [OP_PUTFH] = {
1243 .op_func = (nfsd4op_func)nfsd4_putfh,
1282 .op_name = "OP_OPEN",
1283 },
1284 [OP_OPEN_CONFIRM] = {
1285 .op_func = (nfsd4op_func)nfsd4_open_confirm,
1286 .op_name = "OP_OPEN_CONFIRM",
1287 },
1288 [OP_OPEN_DOWNGRADE] = {
1289 .op_func = (nfsd4op_func)nfsd4_open_downgrade,
1290 .op_name = "OP_OPEN_DOWNGRADE",
1291 },
1292 [OP_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",
1246 },
1247 [OP_PUTPUBFH] = {
1248 .op_func = (nfsd4op_func)nfsd4_putrootfh,
1296 .op_name = "OP_PUTFH",
1297 },
1298 [OP_PUTPUBFH] = {
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",
1251 },
1252 [OP_PUTROOTFH] = {
1253 .op_func = (nfsd4op_func)nfsd4_putrootfh,
1302 .op_name = "OP_PUTPUBFH",
1303 },
1304 [OP_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",
1256 },
1257 [OP_READ] = {
1258 .op_func = (nfsd4op_func)nfsd4_read,
1259 .op_name = "OP_READ",
1260 },
1261 [OP_READDIR] = {
1262 .op_func = (nfsd4op_func)nfsd4_readdir,

--- 13 unchanged lines hidden (view full) ---

1276 },
1277 [OP_RENEW] = {
1278 .op_func = (nfsd4op_func)nfsd4_renew,
1279 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
1280 .op_name = "OP_RENEW",
1281 },
1282 [OP_RESTOREFH] = {
1283 .op_func = (nfsd4op_func)nfsd4_restorefh,
1308 .op_name = "OP_PUTROOTFH",
1309 },
1310 [OP_READ] = {
1311 .op_func = (nfsd4op_func)nfsd4_read,
1312 .op_name = "OP_READ",
1313 },
1314 [OP_READDIR] = {
1315 .op_func = (nfsd4op_func)nfsd4_readdir,

--- 13 unchanged lines hidden (view full) ---

1329 },
1330 [OP_RENEW] = {
1331 .op_func = (nfsd4op_func)nfsd4_renew,
1332 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
1333 .op_name = "OP_RENEW",
1334 },
1335 [OP_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",
1286 },
1287 [OP_SAVEFH] = {
1288 .op_func = (nfsd4op_func)nfsd4_savefh,
1339 .op_name = "OP_RESTOREFH",
1340 },
1341 [OP_SAVEFH] = {
1342 .op_func = (nfsd4op_func)nfsd4_savefh,
1343 .op_flags = OP_HANDLES_WRONGSEC,
1289 .op_name = "OP_SAVEFH",
1290 },
1291 [OP_SECINFO] = {
1292 .op_func = (nfsd4op_func)nfsd4_secinfo,
1344 .op_name = "OP_SAVEFH",
1345 },
1346 [OP_SECINFO] = {
1347 .op_func = (nfsd4op_func)nfsd4_secinfo,
1348 .op_flags = OP_HANDLES_WRONGSEC,
1293 .op_name = "OP_SECINFO",
1294 },
1295 [OP_SETATTR] = {
1296 .op_func = (nfsd4op_func)nfsd4_setattr,
1297 .op_name = "OP_SETATTR",
1298 },
1299 [OP_SETCLIENTID] = {
1300 .op_func = (nfsd4op_func)nfsd4_setclientid,

--- 47 unchanged lines hidden (view full) ---

1348 },
1349 [OP_RECLAIM_COMPLETE] = {
1350 .op_func = (nfsd4op_func)nfsd4_reclaim_complete,
1351 .op_flags = ALLOWED_WITHOUT_FH,
1352 .op_name = "OP_RECLAIM_COMPLETE",
1353 },
1354 [OP_SECINFO_NO_NAME] = {
1355 .op_func = (nfsd4op_func)nfsd4_secinfo_no_name,
1349 .op_name = "OP_SECINFO",
1350 },
1351 [OP_SETATTR] = {
1352 .op_func = (nfsd4op_func)nfsd4_setattr,
1353 .op_name = "OP_SETATTR",
1354 },
1355 [OP_SETCLIENTID] = {
1356 .op_func = (nfsd4op_func)nfsd4_setclientid,

--- 47 unchanged lines hidden (view full) ---

1404 },
1405 [OP_RECLAIM_COMPLETE] = {
1406 .op_func = (nfsd4op_func)nfsd4_reclaim_complete,
1407 .op_flags = ALLOWED_WITHOUT_FH,
1408 .op_name = "OP_RECLAIM_COMPLETE",
1409 },
1410 [OP_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",
1357 },
1358};
1359
1360static const char *nfsd4_op_name(unsigned opnum)
1361{
1362 if (opnum < ARRAY_SIZE(nfsd4_ops))
1363 return nfsd4_ops[opnum].op_name;

--- 49 unchanged lines hidden ---
1413 .op_name = "OP_SECINFO_NO_NAME",
1414 },
1415};
1416
1417static const char *nfsd4_op_name(unsigned opnum)
1418{
1419 if (opnum < ARRAY_SIZE(nfsd4_ops))
1420 return nfsd4_ops[opnum].op_name;

--- 49 unchanged lines hidden ---