diff options
author | Thorsten Leemhuis <fedora@leemhuis.info> | 2017-05-20 16:37:23 +0200 |
---|---|---|
committer | Thorsten Leemhuis <fedora@leemhuis.info> | 2017-05-20 16:37:23 +0200 |
commit | 67dc3998a447a9f9279cc691906fd9bb1dc164f7 (patch) | |
tree | e9fd93b1f3b09252132ebafc8ee3ec7f152649f3 | |
parent | 89f00eb42c3a8f2bbbd026a239e0d4a6be296f9f (diff) | |
parent | d245d93d5fb1e7391fa69ee0109fb07f6f39f935 (diff) | |
download | kernel-67dc3998a447a9f9279cc691906fd9bb1dc164f7.tar.gz kernel-67dc3998a447a9f9279cc691906fd9bb1dc164f7.tar.xz kernel-67dc3998a447a9f9279cc691906fd9bb1dc164f7.zip |
Merge remote-tracking branch 'origin/f25' into f25-user-thl-vanilla-fedora
-rw-r--r-- | 0001-SUNRPC-Refactor-svc_set_num_threads.patch | 156 | ||||
-rw-r--r-- | 0002-NFSv4-Fix-callback-server-shutdown.patch | 155 | ||||
-rw-r--r-- | kernel.spec | 7 |
3 files changed, 318 insertions, 0 deletions
diff --git a/0001-SUNRPC-Refactor-svc_set_num_threads.patch b/0001-SUNRPC-Refactor-svc_set_num_threads.patch new file mode 100644 index 000000000..d29b5fc4d --- /dev/null +++ b/0001-SUNRPC-Refactor-svc_set_num_threads.patch @@ -0,0 +1,156 @@ +From 9e0d87680d689f1758185851c3da6eafb16e71e1 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust <trond.myklebust@primarydata.com> +Date: Wed, 26 Apr 2017 11:55:26 -0400 +Subject: [PATCH] SUNRPC: Refactor svc_set_num_threads() + +Refactor to separate out the functions of starting and stopping threads +so that they can be used in other helpers. + +Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> +Tested-and-reviewed-by: Kinglong Mee <kinglongmee@gmail.com> +Signed-off-by: J. Bruce Fields <bfields@redhat.com> +--- + net/sunrpc/svc.c | 96 ++++++++++++++++++++++++++++++++++---------------------- + 1 file changed, 58 insertions(+), 38 deletions(-) + +diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c +index a08aeb5..98dc33a 100644 +--- a/net/sunrpc/svc.c ++++ b/net/sunrpc/svc.c +@@ -702,59 +702,32 @@ choose_victim(struct svc_serv *serv, struct svc_pool *pool, unsigned int *state) + return task; + } + +-/* +- * Create or destroy enough new threads to make the number +- * of threads the given number. If `pool' is non-NULL, applies +- * only to threads in that pool, otherwise round-robins between +- * all pools. Caller must ensure that mutual exclusion between this and +- * server startup or shutdown. +- * +- * Destroying threads relies on the service threads filling in +- * rqstp->rq_task, which only the nfs ones do. Assumes the serv +- * has been created using svc_create_pooled(). +- * +- * Based on code that used to be in nfsd_svc() but tweaked +- * to be pool-aware. +- */ +-int +-svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) ++/* create new threads */ ++static int ++svc_start_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) + { + struct svc_rqst *rqstp; + struct task_struct *task; + struct svc_pool *chosen_pool; +- int error = 0; + unsigned int state = serv->sv_nrthreads-1; + int node; + +- if (pool == NULL) { +- /* The -1 assumes caller has done a svc_get() */ +- nrservs -= (serv->sv_nrthreads-1); +- } else { +- spin_lock_bh(&pool->sp_lock); +- nrservs -= pool->sp_nrthreads; +- spin_unlock_bh(&pool->sp_lock); +- } +- +- /* create new threads */ +- while (nrservs > 0) { ++ do { + nrservs--; + chosen_pool = choose_pool(serv, pool, &state); + + node = svc_pool_map_get_node(chosen_pool->sp_id); + rqstp = svc_prepare_thread(serv, chosen_pool, node); +- if (IS_ERR(rqstp)) { +- error = PTR_ERR(rqstp); +- break; +- } ++ if (IS_ERR(rqstp)) ++ return PTR_ERR(rqstp); + + __module_get(serv->sv_ops->svo_module); + task = kthread_create_on_node(serv->sv_ops->svo_function, rqstp, + node, "%s", serv->sv_name); + if (IS_ERR(task)) { +- error = PTR_ERR(task); + module_put(serv->sv_ops->svo_module); + svc_exit_thread(rqstp); +- break; ++ return PTR_ERR(task); + } + + rqstp->rq_task = task; +@@ -763,15 +736,62 @@ svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) + + svc_sock_update_bufs(serv); + wake_up_process(task); +- } ++ } while (nrservs > 0); ++ ++ return 0; ++} ++ ++ ++/* destroy old threads */ ++static int ++svc_signal_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) ++{ ++ struct task_struct *task; ++ unsigned int state = serv->sv_nrthreads-1; ++ + /* destroy old threads */ +- while (nrservs < 0 && +- (task = choose_victim(serv, pool, &state)) != NULL) { ++ do { ++ task = choose_victim(serv, pool, &state); ++ if (task == NULL) ++ break; + send_sig(SIGINT, task, 1); + nrservs++; ++ } while (nrservs < 0); ++ ++ return 0; ++} ++ ++/* ++ * Create or destroy enough new threads to make the number ++ * of threads the given number. If `pool' is non-NULL, applies ++ * only to threads in that pool, otherwise round-robins between ++ * all pools. Caller must ensure that mutual exclusion between this and ++ * server startup or shutdown. ++ * ++ * Destroying threads relies on the service threads filling in ++ * rqstp->rq_task, which only the nfs ones do. Assumes the serv ++ * has been created using svc_create_pooled(). ++ * ++ * Based on code that used to be in nfsd_svc() but tweaked ++ * to be pool-aware. ++ */ ++int ++svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) ++{ ++ if (pool == NULL) { ++ /* The -1 assumes caller has done a svc_get() */ ++ nrservs -= (serv->sv_nrthreads-1); ++ } else { ++ spin_lock_bh(&pool->sp_lock); ++ nrservs -= pool->sp_nrthreads; ++ spin_unlock_bh(&pool->sp_lock); + } + +- return error; ++ if (nrservs > 0) ++ return svc_start_kthreads(serv, pool, nrservs); ++ if (nrservs < 0) ++ return svc_signal_kthreads(serv, pool, nrservs); ++ return 0; + } + EXPORT_SYMBOL_GPL(svc_set_num_threads); + +-- +2.9.4 + diff --git a/0002-NFSv4-Fix-callback-server-shutdown.patch b/0002-NFSv4-Fix-callback-server-shutdown.patch new file mode 100644 index 000000000..e5745bf01 --- /dev/null +++ b/0002-NFSv4-Fix-callback-server-shutdown.patch @@ -0,0 +1,155 @@ +From ed6473ddc704a2005b9900ca08e236ebb2d8540a Mon Sep 17 00:00:00 2001 +From: Trond Myklebust <trond.myklebust@primarydata.com> +Date: Wed, 26 Apr 2017 11:55:27 -0400 +Subject: [PATCH] NFSv4: Fix callback server shutdown + +We want to use kthread_stop() in order to ensure the threads are +shut down before we tear down the nfs_callback_info in nfs_callback_down. + +Tested-and-reviewed-by: Kinglong Mee <kinglongmee@gmail.com> +Reported-by: Kinglong Mee <kinglongmee@gmail.com> +Fixes: bb6aeba736ba9 ("NFSv4.x: Switch to using svc_set_num_threads()...") +Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> +Signed-off-by: J. Bruce Fields <bfields@redhat.com> +--- + fs/nfs/callback.c | 24 ++++++++++++++++-------- + include/linux/sunrpc/svc.h | 1 + + net/sunrpc/svc.c | 38 ++++++++++++++++++++++++++++++++++++++ + 3 files changed, 55 insertions(+), 8 deletions(-) + +diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c +index c5e27eb..73a1f92 100644 +--- a/fs/nfs/callback.c ++++ b/fs/nfs/callback.c +@@ -76,7 +76,10 @@ nfs4_callback_svc(void *vrqstp) + + set_freezable(); + +- while (!kthread_should_stop()) { ++ while (!kthread_freezable_should_stop(NULL)) { ++ ++ if (signal_pending(current)) ++ flush_signals(current); + /* + * Listen for a request on the socket + */ +@@ -85,6 +88,8 @@ nfs4_callback_svc(void *vrqstp) + continue; + svc_process(rqstp); + } ++ svc_exit_thread(rqstp); ++ module_put_and_exit(0); + return 0; + } + +@@ -103,9 +108,10 @@ nfs41_callback_svc(void *vrqstp) + + set_freezable(); + +- while (!kthread_should_stop()) { +- if (try_to_freeze()) +- continue; ++ while (!kthread_freezable_should_stop(NULL)) { ++ ++ if (signal_pending(current)) ++ flush_signals(current); + + prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE); + spin_lock_bh(&serv->sv_cb_lock); +@@ -121,11 +127,13 @@ nfs41_callback_svc(void *vrqstp) + error); + } else { + spin_unlock_bh(&serv->sv_cb_lock); +- schedule(); ++ if (!kthread_should_stop()) ++ schedule(); + finish_wait(&serv->sv_cb_waitq, &wq); + } +- flush_signals(current); + } ++ svc_exit_thread(rqstp); ++ module_put_and_exit(0); + return 0; + } + +@@ -221,14 +229,14 @@ static int nfs_callback_up_net(int minorversion, struct svc_serv *serv, + static struct svc_serv_ops nfs40_cb_sv_ops = { + .svo_function = nfs4_callback_svc, + .svo_enqueue_xprt = svc_xprt_do_enqueue, +- .svo_setup = svc_set_num_threads, ++ .svo_setup = svc_set_num_threads_sync, + .svo_module = THIS_MODULE, + }; + #if defined(CONFIG_NFS_V4_1) + static struct svc_serv_ops nfs41_cb_sv_ops = { + .svo_function = nfs41_callback_svc, + .svo_enqueue_xprt = svc_xprt_do_enqueue, +- .svo_setup = svc_set_num_threads, ++ .svo_setup = svc_set_num_threads_sync, + .svo_module = THIS_MODULE, + }; + +diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h +index 6ef19cf..9463102 100644 +--- a/include/linux/sunrpc/svc.h ++++ b/include/linux/sunrpc/svc.h +@@ -473,6 +473,7 @@ void svc_pool_map_put(void); + struct svc_serv * svc_create_pooled(struct svc_program *, unsigned int, + struct svc_serv_ops *); + int svc_set_num_threads(struct svc_serv *, struct svc_pool *, int); ++int svc_set_num_threads_sync(struct svc_serv *, struct svc_pool *, int); + int svc_pool_stats_open(struct svc_serv *serv, struct file *file); + void svc_destroy(struct svc_serv *); + void svc_shutdown_net(struct svc_serv *, struct net *); +diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c +index 98dc33a..bc0f5a0 100644 +--- a/net/sunrpc/svc.c ++++ b/net/sunrpc/svc.c +@@ -795,6 +795,44 @@ svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) + } + EXPORT_SYMBOL_GPL(svc_set_num_threads); + ++/* destroy old threads */ ++static int ++svc_stop_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) ++{ ++ struct task_struct *task; ++ unsigned int state = serv->sv_nrthreads-1; ++ ++ /* destroy old threads */ ++ do { ++ task = choose_victim(serv, pool, &state); ++ if (task == NULL) ++ break; ++ kthread_stop(task); ++ nrservs++; ++ } while (nrservs < 0); ++ return 0; ++} ++ ++int ++svc_set_num_threads_sync(struct svc_serv *serv, struct svc_pool *pool, int nrservs) ++{ ++ if (pool == NULL) { ++ /* The -1 assumes caller has done a svc_get() */ ++ nrservs -= (serv->sv_nrthreads-1); ++ } else { ++ spin_lock_bh(&pool->sp_lock); ++ nrservs -= pool->sp_nrthreads; ++ spin_unlock_bh(&pool->sp_lock); ++ } ++ ++ if (nrservs > 0) ++ return svc_start_kthreads(serv, pool, nrservs); ++ if (nrservs < 0) ++ return svc_stop_kthreads(serv, pool, nrservs); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(svc_set_num_threads_sync); ++ + /* + * Called from a server thread as it's exiting. Caller must hold the "service + * mutex" for the service. +-- +2.9.4 + diff --git a/kernel.spec b/kernel.spec index 565805b83..5d373f387 100644 --- a/kernel.spec +++ b/kernel.spec @@ -624,6 +624,10 @@ Patch864: dell-laptop-Adds-support-for-keyboard-backlight-timeout-AC-settings.pa #CVE-2017-7487 rhbz 1447734 1450417 Patch865: 0001-ipx-call-ipxitf_put-in-ioctl-error-path.patch +#CVE-2017-9059 rhbz 1451386 1451996 +Patch866: 0001-SUNRPC-Refactor-svc_set_num_threads.patch +Patch867: 0002-NFSv4-Fix-callback-server-shutdown.patch + # END OF PATCH DEFINITIONS %endif @@ -2196,6 +2200,9 @@ fi # # %changelog +* Thu May 18 2017 Justin M. Forbes <jforbes@fedoraproject.org> +- Fix CVE-2017-9059 (rhbz 1451386 1451996) + * Mon May 15 2017 Justin M. Forbes <jforbes@fedoraproject.org> - 4.10.16-200 - Linux v4.10.16 - Fix CVE-2017-7487 (rhbz 1447734 1450417) |