Patch "race of lockd inetaddr notifiers vs nlmsvc_rqst change" has been added to the 4.14-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
race of lockd inetaddr notifiers vs nlmsvc_rqst change
to the 4.14-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
race-of-lockd-inetaddr-notifiers-vs-nlmsvc_rqst-change.patch
and it can be found in the queue-4.14 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From foo@baz Thu Feb 1 13:45:42 CET 2018
From: Vasily Averin <[email protected]>
Date: Fri, 10 Nov 2017 10:19:26 +0300
Subject: race of lockd inetaddr notifiers vs nlmsvc_rqst change
From: Vasily Averin <[email protected]>
[ Upstream commit 6b18dd1c03e07262ea0866084856b2a3c5ba8d09 ]
lockd_inet[6]addr_event use nlmsvc_rqst without taken nlmsvc_mutex, nlmsvc_rqst can be changed during execution of notifiers and crash the host.
Patch enables access to nlmsvc_rqst only when it was correctly initialized and delays its cleanup until notifiers are no longer in use.
Note that nlmsvc_rqst can be temporally set to ERR_PTR, so the "if (nlmsvc_rqst)" check in notifiers is insufficient on its own.
--- fs/lockd/svc.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
fs/lockd/svc.c +14 -2
@@ -57,6 +57,9 @@ static struct task_struct *nlmsvc_task;static struct svc_rqst *nlmsvc_rqst;unsigned long nlmsvc_timeout; +atomic_t nlm_ntf_refcnt =ATOMIC_INIT (0 ); +DECLARE_WAIT_QUEUE_HEAD (nlm_ntf_wq); +unsigned int lockd_net_id;/*
@@ -292,7 +295,8 @@ static int lockd_inetaddr_event(struct nstruct in_ifaddr *ifa = (struct in_ifaddr *)ptr;struct sockaddr_in sin; -if (event !=NETDEV_DOWN ) +if ((event !=NETDEV_DOWN ) || + !atomic_inc_not_zero (&nlm_ntf_refcnt)) goto out;if (nlmsvc_rqst) {
@@ -303,6 +307,8 @@ static int lockd_inetaddr_event(struct nsvc_age_temp_xprts_now (nlmsvc_rqst->rq_server, (struct sockaddr *)&sin); } +atomic_dec (&nlm_ntf_refcnt); +wake_up (&nlm_ntf_wq); out:return NOTIFY_DONE ;
@@ -319,7 +325,8 @@ static int lockd_inet6addr_event(structstruct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;struct sockaddr_in6 sin6; -if (event !=NETDEV_DOWN ) +if ((event !=NETDEV_DOWN ) || + !atomic_inc_not_zero (&nlm_ntf_refcnt)) goto out;if (nlmsvc_rqst) {
@@ -331,6 +338,8 @@ static int lockd_inet6addr_event(structsvc_age_temp_xprts_now (nlmsvc_rqst->rq_server, (struct sockaddr *)&sin6); } +atomic_dec (&nlm_ntf_refcnt); +wake_up (&nlm_ntf_wq); out:return NOTIFY_DONE ;
@@ -347,10 +356,12 @@ static void lockd_unregister_notifiers(v#if IS_ENABLED (CONFIG_IPV6 )unregister_inet6addr_notifier (&lockd_inet6addr_notifier);#endif +wait_event (nlm_ntf_wq,atomic_read (&nlm_ntf_refcnt) ==0 ); }static void lockd_svc_exit_thread (void ) { +atomic_dec (&nlm_ntf_refcnt);lockd_unregister_notifiers ();svc_exit_thread (nlmsvc_rqst); }
@@ -375,6 +386,7 @@ static int lockd_start_svc(struct svc_se goto out_rqst; } +atomic_inc (&nlm_ntf_refcnt);svc_sock_update_bufs (serv); serv->sv_maxconn = nlm_max_connections;
Patches currently in stable-queue which might be from [email protected] are
queue-4.14/lockd-fix-list_add-double-add-caused-by-legacy-signal-interface.patch queue-4.14/grace-replace-bug_on-by-warn_once-in-exit_net-hook.patch queue-4.14/perf-core-fix-memory-leak-triggered-by-perf-namespace.patch queue-4.14/race-of-lockd-inetaddr-notifiers-vs-nlmsvc_rqst-change.patch