nfsd-6.11 fixes:
- Fix a number of crashers - Update email address for an NFSD reviewer -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEKLLlsBKG3yQ88j7+M2qzM29mf5cFAmbPLJQACgkQM2qzM29m f5edLBAAveHRyP1XKgLIFtIX40GxK029NEHT2vq9ageaLFsFGylAaAgXSB5rUXER 3FfhOrNuAr/ZAV2bqm/qnA3yDuh/OuD9MIxEA+C2cNJ4bjEKXaqq5iePTK+AeNGH cnvE3UlI9rQkflpuZxbliJZm+u+mxaKnMO2riFbZeKrQh5C6Mn6z4fXp88CZj65U 7oDeONqyjMEtkjJPutzJZr0gJbPjeGgZlrsVgMMg/nki3y+Fal6Rt0hDO2u9evV9 3zTyJ7S7yUnsZ0b2JTx061EfJLd7KFmefWG4UKRKYk1XtiDbHt/cUSi4/QBA0EWw 6VK5aJWUF2OwUpkAYohU0o4/qApoce1raR0cpwrRwzLINDdwPTkfz9L8dpjRPJ68 ubUhWP7D/xASD5RhSrbH6lG8XY3ISXkRk2knwKXFtJtq2uIz2Gxc6F1gzzPE/whR N6JxdiMrUaKoO4qiwOtrXwiYACR9+qsVSW/QxNG1xdQhNXyLb5L6uUSe384MPybw nVIkrOdwO4uors6DzkFoHI/Au2QrTi9pzn53PK01RkhrJKUIS3lMPBnPbf5RAIQN EowYaJNSm52Px+omXzZzHoOgI0h0P3UWiuXoui1Zcy/xCT6uEbj5QtKxM6iKSXyd 4KU3DnC+9nr6+3ld47MFn38f7gmPNrvB56XMCDQKmr9x9OmtB5k= =fRqF -----END PGP SIGNATURE----- Merge tag 'nfsd-6.11-2' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux Pull nfsd fixes from Chuck Lever: - Fix a number of crashers - Update email address for an NFSD reviewer * tag 'nfsd-6.11-2' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: fs/nfsd: fix update of inode attrs in CB_GETATTR nfsd: fix potential UAF in nfsd4_cb_getattr_release nfsd: hold reference to delegation when updating it for cb_getattr MAINTAINERS: Update Olga Kornievskaia's email address nfsd: prevent panic for nfsv4.0 closed files in nfs4_show_open nfsd: ensure that nfsd4_fattr_args.context is zeroed out
This commit is contained in:
commit
a18093afa3
@ -12167,7 +12167,7 @@ KERNEL NFSD, SUNRPC, AND LOCKD SERVERS
|
|||||||
M: Chuck Lever <chuck.lever@oracle.com>
|
M: Chuck Lever <chuck.lever@oracle.com>
|
||||||
M: Jeff Layton <jlayton@kernel.org>
|
M: Jeff Layton <jlayton@kernel.org>
|
||||||
R: Neil Brown <neilb@suse.de>
|
R: Neil Brown <neilb@suse.de>
|
||||||
R: Olga Kornievskaia <kolga@netapp.com>
|
R: Olga Kornievskaia <okorniev@redhat.com>
|
||||||
R: Dai Ngo <Dai.Ngo@oracle.com>
|
R: Dai Ngo <Dai.Ngo@oracle.com>
|
||||||
R: Tom Talpey <tom@talpey.com>
|
R: Tom Talpey <tom@talpey.com>
|
||||||
L: linux-nfs@vger.kernel.org
|
L: linux-nfs@vger.kernel.org
|
||||||
|
14
fs/attr.c
14
fs/attr.c
@ -487,9 +487,17 @@ int notify_change(struct mnt_idmap *idmap, struct dentry *dentry,
|
|||||||
error = security_inode_setattr(idmap, dentry, attr);
|
error = security_inode_setattr(idmap, dentry, attr);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
error = try_break_deleg(inode, delegated_inode);
|
|
||||||
if (error)
|
/*
|
||||||
return error;
|
* If ATTR_DELEG is set, then these attributes are being set on
|
||||||
|
* behalf of the holder of a write delegation. We want to avoid
|
||||||
|
* breaking the delegation in this case.
|
||||||
|
*/
|
||||||
|
if (!(ia_valid & ATTR_DELEG)) {
|
||||||
|
error = try_break_deleg(inode, delegated_inode);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
if (inode->i_op->setattr)
|
if (inode->i_op->setattr)
|
||||||
error = inode->i_op->setattr(idmap, dentry, attr);
|
error = inode->i_op->setattr(idmap, dentry, attr);
|
||||||
|
@ -2789,15 +2789,18 @@ static int nfs4_show_open(struct seq_file *s, struct nfs4_stid *st)
|
|||||||
deny & NFS4_SHARE_ACCESS_READ ? "r" : "-",
|
deny & NFS4_SHARE_ACCESS_READ ? "r" : "-",
|
||||||
deny & NFS4_SHARE_ACCESS_WRITE ? "w" : "-");
|
deny & NFS4_SHARE_ACCESS_WRITE ? "w" : "-");
|
||||||
|
|
||||||
spin_lock(&nf->fi_lock);
|
if (nf) {
|
||||||
file = find_any_file_locked(nf);
|
spin_lock(&nf->fi_lock);
|
||||||
if (file) {
|
file = find_any_file_locked(nf);
|
||||||
nfs4_show_superblock(s, file);
|
if (file) {
|
||||||
seq_puts(s, ", ");
|
nfs4_show_superblock(s, file);
|
||||||
nfs4_show_fname(s, file);
|
seq_puts(s, ", ");
|
||||||
seq_puts(s, ", ");
|
nfs4_show_fname(s, file);
|
||||||
}
|
seq_puts(s, ", ");
|
||||||
spin_unlock(&nf->fi_lock);
|
}
|
||||||
|
spin_unlock(&nf->fi_lock);
|
||||||
|
} else
|
||||||
|
seq_puts(s, "closed, ");
|
||||||
nfs4_show_owner(s, oo);
|
nfs4_show_owner(s, oo);
|
||||||
if (st->sc_status & SC_STATUS_ADMIN_REVOKED)
|
if (st->sc_status & SC_STATUS_ADMIN_REVOKED)
|
||||||
seq_puts(s, ", admin-revoked");
|
seq_puts(s, ", admin-revoked");
|
||||||
@ -3075,9 +3078,9 @@ nfsd4_cb_getattr_release(struct nfsd4_callback *cb)
|
|||||||
struct nfs4_delegation *dp =
|
struct nfs4_delegation *dp =
|
||||||
container_of(ncf, struct nfs4_delegation, dl_cb_fattr);
|
container_of(ncf, struct nfs4_delegation, dl_cb_fattr);
|
||||||
|
|
||||||
nfs4_put_stid(&dp->dl_stid);
|
|
||||||
clear_bit(CB_GETATTR_BUSY, &ncf->ncf_cb_flags);
|
clear_bit(CB_GETATTR_BUSY, &ncf->ncf_cb_flags);
|
||||||
wake_up_bit(&ncf->ncf_cb_flags, CB_GETATTR_BUSY);
|
wake_up_bit(&ncf->ncf_cb_flags, CB_GETATTR_BUSY);
|
||||||
|
nfs4_put_stid(&dp->dl_stid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct nfsd4_callback_ops nfsd4_cb_recall_any_ops = {
|
static const struct nfsd4_callback_ops nfsd4_cb_recall_any_ops = {
|
||||||
@ -8812,7 +8815,7 @@ nfsd4_get_writestateid(struct nfsd4_compound_state *cstate,
|
|||||||
/**
|
/**
|
||||||
* nfsd4_deleg_getattr_conflict - Recall if GETATTR causes conflict
|
* nfsd4_deleg_getattr_conflict - Recall if GETATTR causes conflict
|
||||||
* @rqstp: RPC transaction context
|
* @rqstp: RPC transaction context
|
||||||
* @inode: file to be checked for a conflict
|
* @dentry: dentry of inode to be checked for a conflict
|
||||||
* @modified: return true if file was modified
|
* @modified: return true if file was modified
|
||||||
* @size: new size of file if modified is true
|
* @size: new size of file if modified is true
|
||||||
*
|
*
|
||||||
@ -8827,16 +8830,16 @@ nfsd4_get_writestateid(struct nfsd4_compound_state *cstate,
|
|||||||
* code is returned.
|
* code is returned.
|
||||||
*/
|
*/
|
||||||
__be32
|
__be32
|
||||||
nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
|
nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct dentry *dentry,
|
||||||
bool *modified, u64 *size)
|
bool *modified, u64 *size)
|
||||||
{
|
{
|
||||||
__be32 status;
|
__be32 status;
|
||||||
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
|
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
|
||||||
struct file_lock_context *ctx;
|
struct file_lock_context *ctx;
|
||||||
struct file_lease *fl;
|
struct file_lease *fl;
|
||||||
struct nfs4_delegation *dp;
|
|
||||||
struct iattr attrs;
|
struct iattr attrs;
|
||||||
struct nfs4_cb_fattr *ncf;
|
struct nfs4_cb_fattr *ncf;
|
||||||
|
struct inode *inode = d_inode(dentry);
|
||||||
|
|
||||||
*modified = false;
|
*modified = false;
|
||||||
ctx = locks_inode_context(inode);
|
ctx = locks_inode_context(inode);
|
||||||
@ -8859,7 +8862,8 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
|
|||||||
goto break_lease;
|
goto break_lease;
|
||||||
}
|
}
|
||||||
if (type == F_WRLCK) {
|
if (type == F_WRLCK) {
|
||||||
dp = fl->c.flc_owner;
|
struct nfs4_delegation *dp = fl->c.flc_owner;
|
||||||
|
|
||||||
if (dp->dl_recall.cb_clp == *(rqstp->rq_lease_breaker)) {
|
if (dp->dl_recall.cb_clp == *(rqstp->rq_lease_breaker)) {
|
||||||
spin_unlock(&ctx->flc_lock);
|
spin_unlock(&ctx->flc_lock);
|
||||||
return 0;
|
return 0;
|
||||||
@ -8867,6 +8871,7 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
|
|||||||
break_lease:
|
break_lease:
|
||||||
nfsd_stats_wdeleg_getattr_inc(nn);
|
nfsd_stats_wdeleg_getattr_inc(nn);
|
||||||
dp = fl->c.flc_owner;
|
dp = fl->c.flc_owner;
|
||||||
|
refcount_inc(&dp->dl_stid.sc_count);
|
||||||
ncf = &dp->dl_cb_fattr;
|
ncf = &dp->dl_cb_fattr;
|
||||||
nfs4_cb_getattr(&dp->dl_cb_fattr);
|
nfs4_cb_getattr(&dp->dl_cb_fattr);
|
||||||
spin_unlock(&ctx->flc_lock);
|
spin_unlock(&ctx->flc_lock);
|
||||||
@ -8876,27 +8881,37 @@ break_lease:
|
|||||||
/* Recall delegation only if client didn't respond */
|
/* Recall delegation only if client didn't respond */
|
||||||
status = nfserrno(nfsd_open_break_lease(inode, NFSD_MAY_READ));
|
status = nfserrno(nfsd_open_break_lease(inode, NFSD_MAY_READ));
|
||||||
if (status != nfserr_jukebox ||
|
if (status != nfserr_jukebox ||
|
||||||
!nfsd_wait_for_delegreturn(rqstp, inode))
|
!nfsd_wait_for_delegreturn(rqstp, inode)) {
|
||||||
|
nfs4_put_stid(&dp->dl_stid);
|
||||||
return status;
|
return status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!ncf->ncf_file_modified &&
|
if (!ncf->ncf_file_modified &&
|
||||||
(ncf->ncf_initial_cinfo != ncf->ncf_cb_change ||
|
(ncf->ncf_initial_cinfo != ncf->ncf_cb_change ||
|
||||||
ncf->ncf_cur_fsize != ncf->ncf_cb_fsize))
|
ncf->ncf_cur_fsize != ncf->ncf_cb_fsize))
|
||||||
ncf->ncf_file_modified = true;
|
ncf->ncf_file_modified = true;
|
||||||
if (ncf->ncf_file_modified) {
|
if (ncf->ncf_file_modified) {
|
||||||
|
int err;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Per section 10.4.3 of RFC 8881, the server would
|
* Per section 10.4.3 of RFC 8881, the server would
|
||||||
* not update the file's metadata with the client's
|
* not update the file's metadata with the client's
|
||||||
* modified size
|
* modified size
|
||||||
*/
|
*/
|
||||||
attrs.ia_mtime = attrs.ia_ctime = current_time(inode);
|
attrs.ia_mtime = attrs.ia_ctime = current_time(inode);
|
||||||
attrs.ia_valid = ATTR_MTIME | ATTR_CTIME;
|
attrs.ia_valid = ATTR_MTIME | ATTR_CTIME | ATTR_DELEG;
|
||||||
setattr_copy(&nop_mnt_idmap, inode, &attrs);
|
inode_lock(inode);
|
||||||
mark_inode_dirty(inode);
|
err = notify_change(&nop_mnt_idmap, dentry, &attrs, NULL);
|
||||||
|
inode_unlock(inode);
|
||||||
|
if (err) {
|
||||||
|
nfs4_put_stid(&dp->dl_stid);
|
||||||
|
return nfserrno(err);
|
||||||
|
}
|
||||||
ncf->ncf_cur_fsize = ncf->ncf_cb_fsize;
|
ncf->ncf_cur_fsize = ncf->ncf_cb_fsize;
|
||||||
*size = ncf->ncf_cur_fsize;
|
*size = ncf->ncf_cur_fsize;
|
||||||
*modified = true;
|
*modified = true;
|
||||||
}
|
}
|
||||||
|
nfs4_put_stid(&dp->dl_stid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -3545,6 +3545,9 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
|
|||||||
args.dentry = dentry;
|
args.dentry = dentry;
|
||||||
args.ignore_crossmnt = (ignore_crossmnt != 0);
|
args.ignore_crossmnt = (ignore_crossmnt != 0);
|
||||||
args.acl = NULL;
|
args.acl = NULL;
|
||||||
|
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
|
||||||
|
args.context = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make a local copy of the attribute bitmap that can be modified.
|
* Make a local copy of the attribute bitmap that can be modified.
|
||||||
@ -3562,7 +3565,7 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
|
|||||||
}
|
}
|
||||||
args.size = 0;
|
args.size = 0;
|
||||||
if (attrmask[0] & (FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE)) {
|
if (attrmask[0] & (FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE)) {
|
||||||
status = nfsd4_deleg_getattr_conflict(rqstp, d_inode(dentry),
|
status = nfsd4_deleg_getattr_conflict(rqstp, dentry,
|
||||||
&file_modified, &size);
|
&file_modified, &size);
|
||||||
if (status)
|
if (status)
|
||||||
goto out;
|
goto out;
|
||||||
@ -3617,7 +3620,6 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
|
|||||||
args.contextsupport = false;
|
args.contextsupport = false;
|
||||||
|
|
||||||
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
|
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
|
||||||
args.context = NULL;
|
|
||||||
if ((attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) ||
|
if ((attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) ||
|
||||||
attrmask[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
|
attrmask[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
|
||||||
if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
|
if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
|
||||||
|
@ -781,5 +781,5 @@ static inline bool try_to_expire_client(struct nfs4_client *clp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern __be32 nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp,
|
extern __be32 nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp,
|
||||||
struct inode *inode, bool *file_modified, u64 *size);
|
struct dentry *dentry, bool *file_modified, u64 *size);
|
||||||
#endif /* NFSD4_STATE_H */
|
#endif /* NFSD4_STATE_H */
|
||||||
|
@ -210,6 +210,7 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
|
|||||||
#define ATTR_OPEN (1 << 15) /* Truncating from open(O_TRUNC) */
|
#define ATTR_OPEN (1 << 15) /* Truncating from open(O_TRUNC) */
|
||||||
#define ATTR_TIMES_SET (1 << 16)
|
#define ATTR_TIMES_SET (1 << 16)
|
||||||
#define ATTR_TOUCH (1 << 17)
|
#define ATTR_TOUCH (1 << 17)
|
||||||
|
#define ATTR_DELEG (1 << 18) /* Delegated attrs. Don't break write delegations */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Whiteout is represented by a char device. The following constants define the
|
* Whiteout is represented by a char device. The following constants define the
|
||||||
|
Loading…
Reference in New Issue
Block a user