Merge branch 'for-2.6.36' of git://linux-nfs.org/~bfields/linux
* 'for-2.6.36' of git://linux-nfs.org/~bfields/linux: nfsd: fix NULL dereference in nfsd_statfs() nfsd4: fix downgrade/lock logic nfsd4: typo fix in find_any_file nfsd4: bad BUG() in preprocess_stateid_op
This commit is contained in:
commit
2547d1d20f
3 changed files with 30 additions and 24 deletions
|
@ -2450,14 +2450,13 @@ nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh,
|
||||||
static __be32
|
static __be32
|
||||||
nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open)
|
nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open)
|
||||||
{
|
{
|
||||||
u32 op_share_access, new_access;
|
u32 op_share_access = open->op_share_access & ~NFS4_SHARE_WANT_MASK;
|
||||||
|
bool new_access;
|
||||||
__be32 status;
|
__be32 status;
|
||||||
|
|
||||||
set_access(&new_access, stp->st_access_bmap);
|
new_access = !test_bit(op_share_access, &stp->st_access_bmap);
|
||||||
new_access = (~new_access) & open->op_share_access & ~NFS4_SHARE_WANT_MASK;
|
|
||||||
|
|
||||||
if (new_access) {
|
if (new_access) {
|
||||||
status = nfs4_get_vfs_file(rqstp, fp, cur_fh, new_access);
|
status = nfs4_get_vfs_file(rqstp, fp, cur_fh, op_share_access);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -2470,7 +2469,6 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *c
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
/* remember the open */
|
/* remember the open */
|
||||||
op_share_access = open->op_share_access & ~NFS4_SHARE_WANT_MASK;
|
|
||||||
__set_bit(op_share_access, &stp->st_access_bmap);
|
__set_bit(op_share_access, &stp->st_access_bmap);
|
||||||
__set_bit(open->op_share_deny, &stp->st_deny_bmap);
|
__set_bit(open->op_share_deny, &stp->st_deny_bmap);
|
||||||
|
|
||||||
|
@ -2983,7 +2981,6 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
|
||||||
*filpp = find_readable_file(stp->st_file);
|
*filpp = find_readable_file(stp->st_file);
|
||||||
else
|
else
|
||||||
*filpp = find_writeable_file(stp->st_file);
|
*filpp = find_writeable_file(stp->st_file);
|
||||||
BUG_ON(!*filpp); /* assured by check_openmode */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
status = nfs_ok;
|
status = nfs_ok;
|
||||||
|
@ -3561,7 +3558,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||||
struct nfs4_stateowner *open_sop = NULL;
|
struct nfs4_stateowner *open_sop = NULL;
|
||||||
struct nfs4_stateowner *lock_sop = NULL;
|
struct nfs4_stateowner *lock_sop = NULL;
|
||||||
struct nfs4_stateid *lock_stp;
|
struct nfs4_stateid *lock_stp;
|
||||||
struct file *filp;
|
struct nfs4_file *fp;
|
||||||
|
struct file *filp = NULL;
|
||||||
struct file_lock file_lock;
|
struct file_lock file_lock;
|
||||||
struct file_lock conflock;
|
struct file_lock conflock;
|
||||||
__be32 status = 0;
|
__be32 status = 0;
|
||||||
|
@ -3591,7 +3589,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||||
* lock stateid.
|
* lock stateid.
|
||||||
*/
|
*/
|
||||||
struct nfs4_stateid *open_stp = NULL;
|
struct nfs4_stateid *open_stp = NULL;
|
||||||
struct nfs4_file *fp;
|
|
||||||
|
|
||||||
status = nfserr_stale_clientid;
|
status = nfserr_stale_clientid;
|
||||||
if (!nfsd4_has_session(cstate) &&
|
if (!nfsd4_has_session(cstate) &&
|
||||||
|
@ -3634,6 +3631,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||||
if (status)
|
if (status)
|
||||||
goto out;
|
goto out;
|
||||||
lock_sop = lock->lk_replay_owner;
|
lock_sop = lock->lk_replay_owner;
|
||||||
|
fp = lock_stp->st_file;
|
||||||
}
|
}
|
||||||
/* lock->lk_replay_owner and lock_stp have been created or found */
|
/* lock->lk_replay_owner and lock_stp have been created or found */
|
||||||
|
|
||||||
|
@ -3648,13 +3646,19 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||||
switch (lock->lk_type) {
|
switch (lock->lk_type) {
|
||||||
case NFS4_READ_LT:
|
case NFS4_READ_LT:
|
||||||
case NFS4_READW_LT:
|
case NFS4_READW_LT:
|
||||||
filp = find_readable_file(lock_stp->st_file);
|
if (find_readable_file(lock_stp->st_file)) {
|
||||||
|
nfs4_get_vfs_file(rqstp, fp, &cstate->current_fh, NFS4_SHARE_ACCESS_READ);
|
||||||
|
filp = find_readable_file(lock_stp->st_file);
|
||||||
|
}
|
||||||
file_lock.fl_type = F_RDLCK;
|
file_lock.fl_type = F_RDLCK;
|
||||||
cmd = F_SETLK;
|
cmd = F_SETLK;
|
||||||
break;
|
break;
|
||||||
case NFS4_WRITE_LT:
|
case NFS4_WRITE_LT:
|
||||||
case NFS4_WRITEW_LT:
|
case NFS4_WRITEW_LT:
|
||||||
filp = find_writeable_file(lock_stp->st_file);
|
if (find_writeable_file(lock_stp->st_file)) {
|
||||||
|
nfs4_get_vfs_file(rqstp, fp, &cstate->current_fh, NFS4_SHARE_ACCESS_WRITE);
|
||||||
|
filp = find_writeable_file(lock_stp->st_file);
|
||||||
|
}
|
||||||
file_lock.fl_type = F_WRLCK;
|
file_lock.fl_type = F_WRLCK;
|
||||||
cmd = F_SETLK;
|
cmd = F_SETLK;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -363,23 +363,23 @@ struct nfs4_file {
|
||||||
* at all? */
|
* at all? */
|
||||||
static inline struct file *find_writeable_file(struct nfs4_file *f)
|
static inline struct file *find_writeable_file(struct nfs4_file *f)
|
||||||
{
|
{
|
||||||
if (f->fi_fds[O_RDWR])
|
if (f->fi_fds[O_WRONLY])
|
||||||
return f->fi_fds[O_RDWR];
|
return f->fi_fds[O_WRONLY];
|
||||||
return f->fi_fds[O_WRONLY];
|
return f->fi_fds[O_RDWR];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct file *find_readable_file(struct nfs4_file *f)
|
static inline struct file *find_readable_file(struct nfs4_file *f)
|
||||||
{
|
{
|
||||||
if (f->fi_fds[O_RDWR])
|
if (f->fi_fds[O_RDONLY])
|
||||||
return f->fi_fds[O_RDWR];
|
return f->fi_fds[O_RDONLY];
|
||||||
return f->fi_fds[O_RDONLY];
|
return f->fi_fds[O_RDWR];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct file *find_any_file(struct nfs4_file *f)
|
static inline struct file *find_any_file(struct nfs4_file *f)
|
||||||
{
|
{
|
||||||
if (f->fi_fds[O_RDWR])
|
if (f->fi_fds[O_RDWR])
|
||||||
return f->fi_fds[O_RDWR];
|
return f->fi_fds[O_RDWR];
|
||||||
else if (f->fi_fds[O_RDWR])
|
else if (f->fi_fds[O_WRONLY])
|
||||||
return f->fi_fds[O_WRONLY];
|
return f->fi_fds[O_WRONLY];
|
||||||
else
|
else
|
||||||
return f->fi_fds[O_RDONLY];
|
return f->fi_fds[O_RDONLY];
|
||||||
|
|
|
@ -2033,15 +2033,17 @@ out:
|
||||||
__be32
|
__be32
|
||||||
nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat, int access)
|
nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat, int access)
|
||||||
{
|
{
|
||||||
struct path path = {
|
|
||||||
.mnt = fhp->fh_export->ex_path.mnt,
|
|
||||||
.dentry = fhp->fh_dentry,
|
|
||||||
};
|
|
||||||
__be32 err;
|
__be32 err;
|
||||||
|
|
||||||
err = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP | access);
|
err = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP | access);
|
||||||
if (!err && vfs_statfs(&path, stat))
|
if (!err) {
|
||||||
err = nfserr_io;
|
struct path path = {
|
||||||
|
.mnt = fhp->fh_export->ex_path.mnt,
|
||||||
|
.dentry = fhp->fh_dentry,
|
||||||
|
};
|
||||||
|
if (vfs_statfs(&path, stat))
|
||||||
|
err = nfserr_io;
|
||||||
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue