mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-01-11 17:10:13 +00:00
nfsd: check that server is running in unlock_filesystem
If we are trying to unlock the filesystem via an administrative
interface and nfsd isn't running, it crashes the server. This
happens currently because nfsd4_revoke_states() access state
structures (eg., conf_id_hashtbl) that has been freed as a part
of the server shutdown.
[ 59.465072] Call trace:
[ 59.465308] nfsd4_revoke_states+0x1b4/0x898 [nfsd] (P)
[ 59.465830] write_unlock_fs+0x258/0x440 [nfsd]
[ 59.466278] nfsctl_transaction_write+0xb0/0x120 [nfsd]
[ 59.466780] vfs_write+0x1f0/0x938
[ 59.467088] ksys_write+0xfc/0x1f8
[ 59.467395] __arm64_sys_write+0x74/0xb8
[ 59.467746] invoke_syscall.constprop.0+0xdc/0x1e8
[ 59.468177] do_el0_svc+0x154/0x1d8
[ 59.468489] el0_svc+0x40/0xe0
[ 59.468767] el0t_64_sync_handler+0xa0/0xe8
[ 59.469138] el0t_64_sync+0x1ac/0x1b0
Ensure this can't happen by taking the nfsd_mutex and checking that
the server is still up, and then holding the mutex across the call to
nfsd4_revoke_states().
Reviewed-by: NeilBrown <neil@brown.name>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Fixes: 1ac3629bf0125 ("nfsd: prepare for supporting admin-revocation of state")
Cc: stable@vger.kernel.org
Signed-off-by: Olga Kornievskaia <okorniev@redhat.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
parent
fb321998de
commit
d0424066fc
@ -1759,7 +1759,7 @@ static struct nfs4_stid *find_one_sb_stid(struct nfs4_client *clp,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* nfsd4_revoke_states - revoke all nfsv4 states associated with given filesystem
|
* nfsd4_revoke_states - revoke all nfsv4 states associated with given filesystem
|
||||||
* @net: used to identify instance of nfsd (there is one per net namespace)
|
* @nn: used to identify instance of nfsd (there is one per net namespace)
|
||||||
* @sb: super_block used to identify target filesystem
|
* @sb: super_block used to identify target filesystem
|
||||||
*
|
*
|
||||||
* All nfs4 states (open, lock, delegation, layout) held by the server instance
|
* All nfs4 states (open, lock, delegation, layout) held by the server instance
|
||||||
@ -1771,9 +1771,8 @@ static struct nfs4_stid *find_one_sb_stid(struct nfs4_client *clp,
|
|||||||
* The clients which own the states will subsequently being notified that the
|
* The clients which own the states will subsequently being notified that the
|
||||||
* states have been "admin-revoked".
|
* states have been "admin-revoked".
|
||||||
*/
|
*/
|
||||||
void nfsd4_revoke_states(struct net *net, struct super_block *sb)
|
void nfsd4_revoke_states(struct nfsd_net *nn, struct super_block *sb)
|
||||||
{
|
{
|
||||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
|
||||||
unsigned int idhashval;
|
unsigned int idhashval;
|
||||||
unsigned int sc_types;
|
unsigned int sc_types;
|
||||||
|
|
||||||
|
|||||||
@ -259,6 +259,7 @@ static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size)
|
|||||||
struct path path;
|
struct path path;
|
||||||
char *fo_path;
|
char *fo_path;
|
||||||
int error;
|
int error;
|
||||||
|
struct nfsd_net *nn;
|
||||||
|
|
||||||
/* sanity check */
|
/* sanity check */
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
@ -285,7 +286,13 @@ static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size)
|
|||||||
* 3. Is that directory the root of an exported file system?
|
* 3. Is that directory the root of an exported file system?
|
||||||
*/
|
*/
|
||||||
error = nlmsvc_unlock_all_by_sb(path.dentry->d_sb);
|
error = nlmsvc_unlock_all_by_sb(path.dentry->d_sb);
|
||||||
nfsd4_revoke_states(netns(file), path.dentry->d_sb);
|
mutex_lock(&nfsd_mutex);
|
||||||
|
nn = net_generic(netns(file), nfsd_net_id);
|
||||||
|
if (nn->nfsd_serv)
|
||||||
|
nfsd4_revoke_states(nn, path.dentry->d_sb);
|
||||||
|
else
|
||||||
|
error = -EINVAL;
|
||||||
|
mutex_unlock(&nfsd_mutex);
|
||||||
|
|
||||||
path_put(&path);
|
path_put(&path);
|
||||||
return error;
|
return error;
|
||||||
|
|||||||
@ -841,9 +841,9 @@ static inline void get_nfs4_file(struct nfs4_file *fi)
|
|||||||
struct nfsd_file *find_any_file(struct nfs4_file *f);
|
struct nfsd_file *find_any_file(struct nfs4_file *f);
|
||||||
|
|
||||||
#ifdef CONFIG_NFSD_V4
|
#ifdef CONFIG_NFSD_V4
|
||||||
void nfsd4_revoke_states(struct net *net, struct super_block *sb);
|
void nfsd4_revoke_states(struct nfsd_net *nn, struct super_block *sb);
|
||||||
#else
|
#else
|
||||||
static inline void nfsd4_revoke_states(struct net *net, struct super_block *sb)
|
static inline void nfsd4_revoke_states(struct nfsd_net *nn, struct super_block *sb)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user