summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThorsten Leemhuis <fedora@leemhuis.info>2017-05-20 16:37:23 +0200
committerThorsten Leemhuis <fedora@leemhuis.info>2017-05-20 16:37:23 +0200
commit67dc3998a447a9f9279cc691906fd9bb1dc164f7 (patch)
treee9fd93b1f3b09252132ebafc8ee3ec7f152649f3
parent89f00eb42c3a8f2bbbd026a239e0d4a6be296f9f (diff)
parentd245d93d5fb1e7391fa69ee0109fb07f6f39f935 (diff)
downloadkernel-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.patch156
-rw-r--r--0002-NFSv4-Fix-callback-server-shutdown.patch155
-rw-r--r--kernel.spec7
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)