Skip to content

Commit d042406

Browse files
Olga Kornievskaiachucklever
authored andcommitted
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 <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Fixes: 1ac3629 ("nfsd: prepare for supporting admin-revocation of state") Cc: [email protected] Signed-off-by: Olga Kornievskaia <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent fb32199 commit d042406

3 files changed

Lines changed: 12 additions & 6 deletions

File tree

fs/nfsd/nfs4state.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1759,7 +1759,7 @@ static struct nfs4_stid *find_one_sb_stid(struct nfs4_client *clp,
17591759

17601760
/**
17611761
* nfsd4_revoke_states - revoke all nfsv4 states associated with given filesystem
1762-
* @net: used to identify instance of nfsd (there is one per net namespace)
1762+
* @nn: used to identify instance of nfsd (there is one per net namespace)
17631763
* @sb: super_block used to identify target filesystem
17641764
*
17651765
* 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,
17711771
* The clients which own the states will subsequently being notified that the
17721772
* states have been "admin-revoked".
17731773
*/
1774-
void nfsd4_revoke_states(struct net *net, struct super_block *sb)
1774+
void nfsd4_revoke_states(struct nfsd_net *nn, struct super_block *sb)
17751775
{
1776-
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
17771776
unsigned int idhashval;
17781777
unsigned int sc_types;
17791778

fs/nfsd/nfsctl.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size)
259259
struct path path;
260260
char *fo_path;
261261
int error;
262+
struct nfsd_net *nn;
262263

263264
/* sanity check */
264265
if (size == 0)
@@ -285,7 +286,13 @@ static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size)
285286
* 3. Is that directory the root of an exported file system?
286287
*/
287288
error = nlmsvc_unlock_all_by_sb(path.dentry->d_sb);
288-
nfsd4_revoke_states(netns(file), path.dentry->d_sb);
289+
mutex_lock(&nfsd_mutex);
290+
nn = net_generic(netns(file), nfsd_net_id);
291+
if (nn->nfsd_serv)
292+
nfsd4_revoke_states(nn, path.dentry->d_sb);
293+
else
294+
error = -EINVAL;
295+
mutex_unlock(&nfsd_mutex);
289296

290297
path_put(&path);
291298
return error;

fs/nfsd/state.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -841,9 +841,9 @@ static inline void get_nfs4_file(struct nfs4_file *fi)
841841
struct nfsd_file *find_any_file(struct nfs4_file *f);
842842

843843
#ifdef CONFIG_NFSD_V4
844-
void nfsd4_revoke_states(struct net *net, struct super_block *sb);
844+
void nfsd4_revoke_states(struct nfsd_net *nn, struct super_block *sb);
845845
#else
846-
static inline void nfsd4_revoke_states(struct net *net, struct super_block *sb)
846+
static inline void nfsd4_revoke_states(struct nfsd_net *nn, struct super_block *sb)
847847
{
848848
}
849849
#endif

0 commit comments

Comments
 (0)