Skip to content

Commit c1649ec

Browse files
committed
Merge tag 'nfsd-6.2-4' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
Pull nfsd fixes from Chuck Lever: - Fix recently introduced use-after-free bugs * tag 'nfsd-6.2-4' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: NFSD: replace delayed_work with work_struct for nfsd_client_shrinker NFSD: register/unregister of nfsd-client shrinker at nfsd startup/shutdown time NFSD: fix use-after-free in nfsd4_ssc_setup_dul()
2 parents 2bbb067 + 7c24fa2 commit c1649ec

File tree

5 files changed

+20
-26
lines changed

5 files changed

+20
-26
lines changed

fs/nfsd/netns.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ struct nfsd_net {
195195

196196
atomic_t nfsd_courtesy_clients;
197197
struct shrinker nfsd_client_shrinker;
198-
struct delayed_work nfsd_shrinker_work;
198+
struct work_struct nfsd_shrinker_work;
199199
};
200200

201201
/* Simple check to find out if a given net was properly initialized */

fs/nfsd/nfs4proc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,6 +1318,7 @@ static __be32 nfsd4_ssc_setup_dul(struct nfsd_net *nn, char *ipaddr,
13181318
/* allow 20secs for mount/unmount for now - revisit */
13191319
if (signal_pending(current) ||
13201320
(schedule_timeout(20*HZ) == 0)) {
1321+
finish_wait(&nn->nfsd_ssc_waitq, &wait);
13211322
kfree(work);
13221323
return nfserr_eagain;
13231324
}

fs/nfsd/nfs4state.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4411,7 +4411,7 @@ nfsd4_state_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)
44114411
if (!count)
44124412
count = atomic_long_read(&num_delegations);
44134413
if (count)
4414-
mod_delayed_work(laundry_wq, &nn->nfsd_shrinker_work, 0);
4414+
queue_work(laundry_wq, &nn->nfsd_shrinker_work);
44154415
return (unsigned long)count;
44164416
}
44174417

@@ -4421,7 +4421,7 @@ nfsd4_state_shrinker_scan(struct shrinker *shrink, struct shrink_control *sc)
44214421
return SHRINK_STOP;
44224422
}
44234423

4424-
int
4424+
void
44254425
nfsd4_init_leases_net(struct nfsd_net *nn)
44264426
{
44274427
struct sysinfo si;
@@ -4443,16 +4443,6 @@ nfsd4_init_leases_net(struct nfsd_net *nn)
44434443
nn->nfs4_max_clients = max_t(int, max_clients, NFS4_CLIENTS_PER_GB);
44444444

44454445
atomic_set(&nn->nfsd_courtesy_clients, 0);
4446-
nn->nfsd_client_shrinker.scan_objects = nfsd4_state_shrinker_scan;
4447-
nn->nfsd_client_shrinker.count_objects = nfsd4_state_shrinker_count;
4448-
nn->nfsd_client_shrinker.seeks = DEFAULT_SEEKS;
4449-
return register_shrinker(&nn->nfsd_client_shrinker, "nfsd-client");
4450-
}
4451-
4452-
void
4453-
nfsd4_leases_net_shutdown(struct nfsd_net *nn)
4454-
{
4455-
unregister_shrinker(&nn->nfsd_client_shrinker);
44564446
}
44574447

44584448
static void init_nfs4_replay(struct nfs4_replay *rp)
@@ -6235,8 +6225,7 @@ deleg_reaper(struct nfsd_net *nn)
62356225
static void
62366226
nfsd4_state_shrinker_worker(struct work_struct *work)
62376227
{
6238-
struct delayed_work *dwork = to_delayed_work(work);
6239-
struct nfsd_net *nn = container_of(dwork, struct nfsd_net,
6228+
struct nfsd_net *nn = container_of(work, struct nfsd_net,
62406229
nfsd_shrinker_work);
62416230

62426231
courtesy_client_reaper(nn);
@@ -8066,11 +8055,20 @@ static int nfs4_state_create_net(struct net *net)
80668055
INIT_LIST_HEAD(&nn->blocked_locks_lru);
80678056

80688057
INIT_DELAYED_WORK(&nn->laundromat_work, laundromat_main);
8069-
INIT_DELAYED_WORK(&nn->nfsd_shrinker_work, nfsd4_state_shrinker_worker);
8058+
INIT_WORK(&nn->nfsd_shrinker_work, nfsd4_state_shrinker_worker);
80708059
get_net(net);
80718060

8061+
nn->nfsd_client_shrinker.scan_objects = nfsd4_state_shrinker_scan;
8062+
nn->nfsd_client_shrinker.count_objects = nfsd4_state_shrinker_count;
8063+
nn->nfsd_client_shrinker.seeks = DEFAULT_SEEKS;
8064+
8065+
if (register_shrinker(&nn->nfsd_client_shrinker, "nfsd-client"))
8066+
goto err_shrinker;
80728067
return 0;
80738068

8069+
err_shrinker:
8070+
put_net(net);
8071+
kfree(nn->sessionid_hashtbl);
80748072
err_sessionid:
80758073
kfree(nn->unconf_id_hashtbl);
80768074
err_unconf_id:
@@ -8163,6 +8161,8 @@ nfs4_state_shutdown_net(struct net *net)
81638161
struct list_head *pos, *next, reaplist;
81648162
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
81658163

8164+
unregister_shrinker(&nn->nfsd_client_shrinker);
8165+
cancel_work(&nn->nfsd_shrinker_work);
81668166
cancel_delayed_work_sync(&nn->laundromat_work);
81678167
locks_end_grace(&nn->nfsd4_manager);
81688168

fs/nfsd/nfsctl.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,9 +1457,7 @@ static __net_init int nfsd_init_net(struct net *net)
14571457
goto out_idmap_error;
14581458
nn->nfsd_versions = NULL;
14591459
nn->nfsd4_minorversions = NULL;
1460-
retval = nfsd4_init_leases_net(nn);
1461-
if (retval)
1462-
goto out_drc_error;
1460+
nfsd4_init_leases_net(nn);
14631461
retval = nfsd_reply_cache_init(nn);
14641462
if (retval)
14651463
goto out_cache_error;
@@ -1469,8 +1467,6 @@ static __net_init int nfsd_init_net(struct net *net)
14691467
return 0;
14701468

14711469
out_cache_error:
1472-
nfsd4_leases_net_shutdown(nn);
1473-
out_drc_error:
14741470
nfsd_idmap_shutdown(net);
14751471
out_idmap_error:
14761472
nfsd_export_shutdown(net);
@@ -1486,7 +1482,6 @@ static __net_exit void nfsd_exit_net(struct net *net)
14861482
nfsd_idmap_shutdown(net);
14871483
nfsd_export_shutdown(net);
14881484
nfsd_netns_free_versions(net_generic(net, nfsd_net_id));
1489-
nfsd4_leases_net_shutdown(nn);
14901485
}
14911486

14921487
static struct pernet_operations nfsd_net_ops = {

fs/nfsd/nfsd.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -504,17 +504,15 @@ extern void unregister_cld_notifier(void);
504504
extern void nfsd4_ssc_init_umount_work(struct nfsd_net *nn);
505505
#endif
506506

507-
extern int nfsd4_init_leases_net(struct nfsd_net *nn);
508-
extern void nfsd4_leases_net_shutdown(struct nfsd_net *nn);
507+
extern void nfsd4_init_leases_net(struct nfsd_net *nn);
509508

510509
#else /* CONFIG_NFSD_V4 */
511510
static inline int nfsd4_is_junction(struct dentry *dentry)
512511
{
513512
return 0;
514513
}
515514

516-
static inline int nfsd4_init_leases_net(struct nfsd_net *nn) { return 0; };
517-
static inline void nfsd4_leases_net_shutdown(struct nfsd_net *nn) {};
515+
static inline void nfsd4_init_leases_net(struct nfsd_net *nn) { };
518516

519517
#define register_cld_notifier() 0
520518
#define unregister_cld_notifier() do { } while(0)

0 commit comments

Comments
 (0)