|
@@ -403,7 +403,7 @@ nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
|
|
cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
|
|
memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
|
|
memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
|
|
putfh->pf_fhlen);
|
|
putfh->pf_fhlen);
|
|
- return fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
|
|
|
|
|
|
+ return fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_BYPASS_GSS);
|
|
}
|
|
}
|
|
|
|
|
|
static __be32
|
|
static __be32
|
|
@@ -989,6 +989,9 @@ enum nfsd4_op_flags {
|
|
ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */
|
|
ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */
|
|
ALLOWED_ON_ABSENT_FS = 1 << 1, /* ops processed on absent fs */
|
|
ALLOWED_ON_ABSENT_FS = 1 << 1, /* ops processed on absent fs */
|
|
ALLOWED_AS_FIRST_OP = 1 << 2, /* ops reqired first in compound */
|
|
ALLOWED_AS_FIRST_OP = 1 << 2, /* ops reqired first in compound */
|
|
|
|
+ /* For rfc 5661 section 2.6.3.1.1: */
|
|
|
|
+ OP_HANDLES_WRONGSEC = 1 << 3,
|
|
|
|
+ OP_IS_PUTFH_LIKE = 1 << 4,
|
|
};
|
|
};
|
|
|
|
|
|
struct nfsd4_operation {
|
|
struct nfsd4_operation {
|
|
@@ -1039,6 +1042,39 @@ static inline struct nfsd4_operation *OPDESC(struct nfsd4_op *op)
|
|
return &nfsd4_ops[op->opnum];
|
|
return &nfsd4_ops[op->opnum];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static bool need_wrongsec_check(struct svc_rqst *rqstp)
|
|
|
|
+{
|
|
|
|
+ struct nfsd4_compoundres *resp = rqstp->rq_resp;
|
|
|
|
+ struct nfsd4_compoundargs *argp = rqstp->rq_argp;
|
|
|
|
+ struct nfsd4_op *this = &argp->ops[resp->opcnt - 1];
|
|
|
|
+ struct nfsd4_op *next = &argp->ops[resp->opcnt];
|
|
|
|
+ struct nfsd4_operation *thisd;
|
|
|
|
+ struct nfsd4_operation *nextd;
|
|
|
|
+
|
|
|
|
+ thisd = OPDESC(this);
|
|
|
|
+ /*
|
|
|
|
+ * Most ops check wronsec on our own; only the putfh-like ops
|
|
|
|
+ * have special rules.
|
|
|
|
+ */
|
|
|
|
+ if (!(thisd->op_flags & OP_IS_PUTFH_LIKE))
|
|
|
|
+ return false;
|
|
|
|
+ /*
|
|
|
|
+ * rfc 5661 2.6.3.1.1.6: don't bother erroring out a
|
|
|
|
+ * put-filehandle operation if we're not going to use the
|
|
|
|
+ * result:
|
|
|
|
+ */
|
|
|
|
+ if (argp->opcnt == resp->opcnt)
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ nextd = OPDESC(next);
|
|
|
|
+ /*
|
|
|
|
+ * Rest of 2.6.3.1.1: certain operations will return WRONGSEC
|
|
|
|
+ * errors themselves as necessary; others should check for them
|
|
|
|
+ * now:
|
|
|
|
+ */
|
|
|
|
+ return !(nextd->op_flags & OP_HANDLES_WRONGSEC);
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* COMPOUND call.
|
|
* COMPOUND call.
|
|
*/
|
|
*/
|
|
@@ -1134,6 +1170,9 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
|
|
else
|
|
else
|
|
BUG_ON(op->status == nfs_ok);
|
|
BUG_ON(op->status == nfs_ok);
|
|
|
|
|
|
|
|
+ if (!op->status && need_wrongsec_check(rqstp))
|
|
|
|
+ op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp);
|
|
|
|
+
|
|
encode_op:
|
|
encode_op:
|
|
/* Only from SEQUENCE */
|
|
/* Only from SEQUENCE */
|
|
if (resp->cstate.status == nfserr_replay_cache) {
|
|
if (resp->cstate.status == nfserr_replay_cache) {
|
|
@@ -1225,10 +1264,12 @@ static struct nfsd4_operation nfsd4_ops[] = {
|
|
},
|
|
},
|
|
[OP_LOOKUP] = {
|
|
[OP_LOOKUP] = {
|
|
.op_func = (nfsd4op_func)nfsd4_lookup,
|
|
.op_func = (nfsd4op_func)nfsd4_lookup,
|
|
|
|
+ .op_flags = OP_HANDLES_WRONGSEC,
|
|
.op_name = "OP_LOOKUP",
|
|
.op_name = "OP_LOOKUP",
|
|
},
|
|
},
|
|
[OP_LOOKUPP] = {
|
|
[OP_LOOKUPP] = {
|
|
.op_func = (nfsd4op_func)nfsd4_lookupp,
|
|
.op_func = (nfsd4op_func)nfsd4_lookupp,
|
|
|
|
+ .op_flags = OP_HANDLES_WRONGSEC,
|
|
.op_name = "OP_LOOKUPP",
|
|
.op_name = "OP_LOOKUPP",
|
|
},
|
|
},
|
|
[OP_NVERIFY] = {
|
|
[OP_NVERIFY] = {
|
|
@@ -1237,6 +1278,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
|
|
},
|
|
},
|
|
[OP_OPEN] = {
|
|
[OP_OPEN] = {
|
|
.op_func = (nfsd4op_func)nfsd4_open,
|
|
.op_func = (nfsd4op_func)nfsd4_open,
|
|
|
|
+ .op_flags = OP_HANDLES_WRONGSEC,
|
|
.op_name = "OP_OPEN",
|
|
.op_name = "OP_OPEN",
|
|
},
|
|
},
|
|
[OP_OPEN_CONFIRM] = {
|
|
[OP_OPEN_CONFIRM] = {
|
|
@@ -1249,17 +1291,20 @@ static struct nfsd4_operation nfsd4_ops[] = {
|
|
},
|
|
},
|
|
[OP_PUTFH] = {
|
|
[OP_PUTFH] = {
|
|
.op_func = (nfsd4op_func)nfsd4_putfh,
|
|
.op_func = (nfsd4op_func)nfsd4_putfh,
|
|
- .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
|
|
|
|
|
|
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
|
|
|
|
+ | OP_IS_PUTFH_LIKE,
|
|
.op_name = "OP_PUTFH",
|
|
.op_name = "OP_PUTFH",
|
|
},
|
|
},
|
|
[OP_PUTPUBFH] = {
|
|
[OP_PUTPUBFH] = {
|
|
.op_func = (nfsd4op_func)nfsd4_putrootfh,
|
|
.op_func = (nfsd4op_func)nfsd4_putrootfh,
|
|
- .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
|
|
|
|
|
|
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
|
|
|
|
+ | OP_IS_PUTFH_LIKE,
|
|
.op_name = "OP_PUTPUBFH",
|
|
.op_name = "OP_PUTPUBFH",
|
|
},
|
|
},
|
|
[OP_PUTROOTFH] = {
|
|
[OP_PUTROOTFH] = {
|
|
.op_func = (nfsd4op_func)nfsd4_putrootfh,
|
|
.op_func = (nfsd4op_func)nfsd4_putrootfh,
|
|
- .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
|
|
|
|
|
|
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
|
|
|
|
+ | OP_IS_PUTFH_LIKE,
|
|
.op_name = "OP_PUTROOTFH",
|
|
.op_name = "OP_PUTROOTFH",
|
|
},
|
|
},
|
|
[OP_READ] = {
|
|
[OP_READ] = {
|
|
@@ -1289,15 +1334,18 @@ static struct nfsd4_operation nfsd4_ops[] = {
|
|
},
|
|
},
|
|
[OP_RESTOREFH] = {
|
|
[OP_RESTOREFH] = {
|
|
.op_func = (nfsd4op_func)nfsd4_restorefh,
|
|
.op_func = (nfsd4op_func)nfsd4_restorefh,
|
|
- .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
|
|
|
|
|
|
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
|
|
|
|
+ | OP_IS_PUTFH_LIKE,
|
|
.op_name = "OP_RESTOREFH",
|
|
.op_name = "OP_RESTOREFH",
|
|
},
|
|
},
|
|
[OP_SAVEFH] = {
|
|
[OP_SAVEFH] = {
|
|
.op_func = (nfsd4op_func)nfsd4_savefh,
|
|
.op_func = (nfsd4op_func)nfsd4_savefh,
|
|
|
|
+ .op_flags = OP_HANDLES_WRONGSEC,
|
|
.op_name = "OP_SAVEFH",
|
|
.op_name = "OP_SAVEFH",
|
|
},
|
|
},
|
|
[OP_SECINFO] = {
|
|
[OP_SECINFO] = {
|
|
.op_func = (nfsd4op_func)nfsd4_secinfo,
|
|
.op_func = (nfsd4op_func)nfsd4_secinfo,
|
|
|
|
+ .op_flags = OP_HANDLES_WRONGSEC,
|
|
.op_name = "OP_SECINFO",
|
|
.op_name = "OP_SECINFO",
|
|
},
|
|
},
|
|
[OP_SETATTR] = {
|
|
[OP_SETATTR] = {
|
|
@@ -1361,6 +1409,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
|
|
},
|
|
},
|
|
[OP_SECINFO_NO_NAME] = {
|
|
[OP_SECINFO_NO_NAME] = {
|
|
.op_func = (nfsd4op_func)nfsd4_secinfo_no_name,
|
|
.op_func = (nfsd4op_func)nfsd4_secinfo_no_name,
|
|
|
|
+ .op_flags = OP_HANDLES_WRONGSEC,
|
|
.op_name = "OP_SECINFO_NO_NAME",
|
|
.op_name = "OP_SECINFO_NO_NAME",
|
|
},
|
|
},
|
|
};
|
|
};
|