Commit 7160d19b authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] kNFSd: Add a check in OP_LOCK for new lockowners to ensure that the open stateid is

From: NeilBrown <neilb@cse.unsw.edu.au>

owned by the lockowner clientid.
parent 80f9c3ea
...@@ -1402,7 +1402,7 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl ...@@ -1402,7 +1402,7 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
* Checks for sequence id mutating operations. * Checks for sequence id mutating operations.
*/ */
int int
nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp) nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid)
{ {
int status; int status;
struct nfs4_stateid *stp; struct nfs4_stateid *stp;
...@@ -1439,6 +1439,21 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei ...@@ -1439,6 +1439,21 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
status = nfserr_bad_stateid; status = nfserr_bad_stateid;
/* for new lock stateowners, check that the lock->v.new.open_stateid
* refers to an open stateowner, and that the lockclid
* (nfs4_lock->v.new.clientid) is the same as the
* open_stateid->st_stateowner->so_client->clientid
*/
if (lockclid) {
struct nfs4_stateowner *sop = stp->st_stateowner;
struct nfs4_client *clp = sop->so_client;
if (!sop->so_is_open_owner)
goto out;
if (!cmp_clid(&clp->cl_clientid, lockclid))
goto out;
}
if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) { if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n"); printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
stp->st_vfs_set = 0; stp->st_vfs_set = 0;
...@@ -1525,7 +1540,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs ...@@ -1525,7 +1540,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
if ((status = nfs4_preprocess_seqid_op(current_fh, oc->oc_seqid, if ((status = nfs4_preprocess_seqid_op(current_fh, oc->oc_seqid,
&oc->oc_req_stateid, &oc->oc_req_stateid,
CHECK_FH | CONFIRM | OPEN_STATE, CHECK_FH | CONFIRM | OPEN_STATE,
&oc->oc_stateowner, &stp))) &oc->oc_stateowner, &stp, NULL)))
goto out; goto out;
sop = oc->oc_stateowner; sop = oc->oc_stateowner;
...@@ -1557,7 +1572,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct n ...@@ -1557,7 +1572,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct n
if ((status = nfs4_preprocess_seqid_op(current_fh, od->od_seqid, if ((status = nfs4_preprocess_seqid_op(current_fh, od->od_seqid,
&od->od_stateid, &od->od_stateid,
CHECK_FH | OPEN_STATE, CHECK_FH | OPEN_STATE,
&od->od_stateowner, &stp))) &od->od_stateowner, &stp, NULL)))
goto out; goto out;
status = nfserr_inval; status = nfserr_inval;
...@@ -1597,7 +1612,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_clos ...@@ -1597,7 +1612,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_clos
if ((status = nfs4_preprocess_seqid_op(current_fh, close->cl_seqid, if ((status = nfs4_preprocess_seqid_op(current_fh, close->cl_seqid,
&close->cl_stateid, &close->cl_stateid,
CHECK_FH | OPEN_STATE, CHECK_FH | OPEN_STATE,
&close->cl_stateowner, &stp))) &close->cl_stateowner, &stp, NULL)))
goto out; goto out;
/* /*
* Return success, but first update the stateid. * Return success, but first update the stateid.
...@@ -1853,12 +1868,15 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock ...@@ -1853,12 +1868,15 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
printk("NFSD: nfsd4_lock: clientid is stale!\n"); printk("NFSD: nfsd4_lock: clientid is stale!\n");
goto out; goto out;
} }
/* does the clientid in the lock owner own the open stateid? */
/* validate and update open stateid and open seqid */ /* validate and update open stateid and open seqid */
status = nfs4_preprocess_seqid_op(current_fh, status = nfs4_preprocess_seqid_op(current_fh,
lock->lk_new_open_seqid, lock->lk_new_open_seqid,
&lock->lk_new_open_stateid, &lock->lk_new_open_stateid,
CHECK_FH | OPEN_STATE, CHECK_FH | OPEN_STATE,
&open_sop, &open_stp); &open_sop, &open_stp,
&lock->v.new.clientid);
if (status) if (status)
goto out; goto out;
/* create lockowner and lock stateid */ /* create lockowner and lock stateid */
...@@ -1890,7 +1908,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock ...@@ -1890,7 +1908,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
lock->lk_old_lock_seqid, lock->lk_old_lock_seqid,
&lock->lk_old_lock_stateid, &lock->lk_old_lock_stateid,
CHECK_FH | LOCK_STATE, CHECK_FH | LOCK_STATE,
&lock->lk_stateowner, &lock_stp); &lock->lk_stateowner, &lock_stp, NULL);
if (status) if (status)
goto out; goto out;
} }
...@@ -2095,7 +2113,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock ...@@ -2095,7 +2113,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
locku->lu_seqid, locku->lu_seqid,
&locku->lu_stateid, &locku->lu_stateid,
CHECK_FH | LOCK_STATE, CHECK_FH | LOCK_STATE,
&locku->lu_stateowner, &stp))) &locku->lu_stateowner, &stp, NULL)))
goto out; goto out;
filp = &stp->st_vfs_file; filp = &stp->st_vfs_file;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment