From 90b8014c3046834e05a1879a6e38de3ae05b18c2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 10 Jan 2019 17:10:46 +0100 Subject: [PATCH] 3.18-stable patches added patches: fork-record-start_time-late.patch sunrpc-fix-cache_head-leak-due-to-queued-request.patch sunrpc-use-svc_net-in-svcauth_gss_-functions.patch --- queue-3.18/fork-record-start_time-late.patch | 78 +++++++++++++++++++ queue-3.18/series | 3 + ...ache_head-leak-due-to-queued-request.patch | 68 ++++++++++++++++ ...se-svc_net-in-svcauth_gss_-functions.patch | 56 +++++++++++++ 4 files changed, 205 insertions(+) create mode 100644 queue-3.18/fork-record-start_time-late.patch create mode 100644 queue-3.18/sunrpc-fix-cache_head-leak-due-to-queued-request.patch create mode 100644 queue-3.18/sunrpc-use-svc_net-in-svcauth_gss_-functions.patch diff --git a/queue-3.18/fork-record-start_time-late.patch b/queue-3.18/fork-record-start_time-late.patch new file mode 100644 index 00000000000..1ea70bc2ef5 --- /dev/null +++ b/queue-3.18/fork-record-start_time-late.patch @@ -0,0 +1,78 @@ +From 7b55851367136b1efd84d98fea81ba57a98304cf Mon Sep 17 00:00:00 2001 +From: David Herrmann +Date: Tue, 8 Jan 2019 13:58:52 +0100 +Subject: fork: record start_time late + +From: David Herrmann + +commit 7b55851367136b1efd84d98fea81ba57a98304cf upstream. + +This changes the fork(2) syscall to record the process start_time after +initializing the basic task structure but still before making the new +process visible to user-space. + +Technically, we could record the start_time anytime during fork(2). But +this might lead to scenarios where a start_time is recorded long before +a process becomes visible to user-space. For instance, with +userfaultfd(2) and TLS, user-space can delay the execution of fork(2) +for an indefinite amount of time (and will, if this causes network +access, or similar). + +By recording the start_time late, it much closer reflects the point in +time where the process becomes live and can be observed by other +processes. + +Lastly, this makes it much harder for user-space to predict and control +the start_time they get assigned. Previously, user-space could fork a +process and stall it in copy_thread_tls() before its pid is allocated, +but after its start_time is recorded. This can be misused to later-on +cycle through PIDs and resume the stalled fork(2) yielding a process +that has the same pid and start_time as a process that existed before. +This can be used to circumvent security systems that identify processes +by their pid+start_time combination. + +Even though user-space was always aware that start_time recording is +flaky (but several projects are known to still rely on start_time-based +identification), changing the start_time to be recorded late will help +mitigate existing attacks and make it much harder for user-space to +control the start_time a process gets assigned. + +Reported-by: Jann Horn +Signed-off-by: Tom Gundersen +Signed-off-by: David Herrmann +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/fork.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -1321,8 +1321,6 @@ static struct task_struct *copy_process( + + posix_cpu_timers_init(p); + +- p->start_time = ktime_get_ns(); +- p->real_start_time = ktime_get_boot_ns(); + p->io_context = NULL; + p->audit_context = NULL; + if (clone_flags & CLONE_THREAD) +@@ -1487,6 +1485,17 @@ static struct task_struct *copy_process( + spin_lock(¤t->sighand->siglock); + + /* ++ * From this point on we must avoid any synchronous user-space ++ * communication until we take the tasklist-lock. In particular, we do ++ * not want user-space to be able to predict the process start-time by ++ * stalling fork(2) after we recorded the start_time but before it is ++ * visible to the system. ++ */ ++ ++ p->start_time = ktime_get_ns(); ++ p->real_start_time = ktime_get_boot_ns(); ++ ++ /* + * Copy seccomp details explicitly here, in case they were changed + * before holding sighand lock. + */ diff --git a/queue-3.18/series b/queue-3.18/series index 5c4ed873078..7f377fa51d6 100644 --- a/queue-3.18/series +++ b/queue-3.18/series @@ -29,3 +29,6 @@ mips-ensure-pmd_present-returns-false-after-pmd_mknotpresent.patch mips-align-kernel-load-address-to-64kb.patch cifs-fix-error-mapping-for-smb2_lock-command-which-caused-ofd-lock-problem.patch scsi-zfcp-fix-posting-too-many-status-read-buffers-leading-to-adapter-shutdown.patch +fork-record-start_time-late.patch +sunrpc-fix-cache_head-leak-due-to-queued-request.patch +sunrpc-use-svc_net-in-svcauth_gss_-functions.patch diff --git a/queue-3.18/sunrpc-fix-cache_head-leak-due-to-queued-request.patch b/queue-3.18/sunrpc-fix-cache_head-leak-due-to-queued-request.patch new file mode 100644 index 00000000000..27be9ac9c16 --- /dev/null +++ b/queue-3.18/sunrpc-fix-cache_head-leak-due-to-queued-request.patch @@ -0,0 +1,68 @@ +From 4ecd55ea074217473f94cfee21bb72864d39f8d7 Mon Sep 17 00:00:00 2001 +From: Vasily Averin +Date: Wed, 28 Nov 2018 11:45:57 +0300 +Subject: sunrpc: fix cache_head leak due to queued request + +From: Vasily Averin + +commit 4ecd55ea074217473f94cfee21bb72864d39f8d7 upstream. + +After commit d202cce8963d, an expired cache_head can be removed from the +cache_detail's hash. + +However, the expired cache_head may be waiting for a reply from a +previously submitted request. Such a cache_head has an increased +refcounter and therefore it won't be freed after cache_put(freeme). + +Because the cache_head was removed from the hash it cannot be found +during cache_clean() and can be leaked forever, together with stalled +cache_request and other taken resources. + +In our case we noticed it because an entry in the export cache was +holding a reference on a filesystem. + +Fixes d202cce8963d ("sunrpc: never return expired entries in sunrpc_cache_lookup") +Cc: Pavel Tikhomirov +Cc: stable@kernel.org # 2.6.35 +Signed-off-by: Vasily Averin +Reviewed-by: NeilBrown +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + net/sunrpc/cache.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/net/sunrpc/cache.c ++++ b/net/sunrpc/cache.c +@@ -50,6 +50,10 @@ static void cache_init(struct cache_head + h->last_refresh = now; + } + ++static void cache_fresh_locked(struct cache_head *head, time_t expiry); ++static void cache_fresh_unlocked(struct cache_head *head, ++ struct cache_detail *detail); ++ + struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, + struct cache_head *key, int hash) + { +@@ -94,6 +98,7 @@ struct cache_head *sunrpc_cache_lookup(s + *hp = tmp->next; + tmp->next = NULL; + detail->entries --; ++ cache_fresh_locked(tmp, 0); + freeme = tmp; + break; + } +@@ -109,8 +114,10 @@ struct cache_head *sunrpc_cache_lookup(s + cache_get(new); + write_unlock(&detail->hash_lock); + +- if (freeme) ++ if (freeme) { ++ cache_fresh_unlocked(freeme, detail); + cache_put(freeme, detail); ++ } + return new; + } + EXPORT_SYMBOL_GPL(sunrpc_cache_lookup); diff --git a/queue-3.18/sunrpc-use-svc_net-in-svcauth_gss_-functions.patch b/queue-3.18/sunrpc-use-svc_net-in-svcauth_gss_-functions.patch new file mode 100644 index 00000000000..4fa9ecf9c5f --- /dev/null +++ b/queue-3.18/sunrpc-use-svc_net-in-svcauth_gss_-functions.patch @@ -0,0 +1,56 @@ +From b8be5674fa9a6f3677865ea93f7803c4212f3e10 Mon Sep 17 00:00:00 2001 +From: Vasily Averin +Date: Mon, 24 Dec 2018 14:44:42 +0300 +Subject: sunrpc: use SVC_NET() in svcauth_gss_* functions + +From: Vasily Averin + +commit b8be5674fa9a6f3677865ea93f7803c4212f3e10 upstream. + +Signed-off-by: Vasily Averin +Cc: stable@vger.kernel.org +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + net/sunrpc/auth_gss/svcauth_gss.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/net/sunrpc/auth_gss/svcauth_gss.c ++++ b/net/sunrpc/auth_gss/svcauth_gss.c +@@ -1102,7 +1102,7 @@ static int svcauth_gss_legacy_init(struc + struct kvec *resv = &rqstp->rq_res.head[0]; + struct rsi *rsip, rsikey; + int ret; +- struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); ++ struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id); + + memset(&rsikey, 0, sizeof(rsikey)); + ret = gss_read_verf(gc, argv, authp, +@@ -1213,7 +1213,7 @@ static int svcauth_gss_proxy_init(struct + uint64_t handle; + int status; + int ret; +- struct net *net = rqstp->rq_xprt->xpt_net; ++ struct net *net = SVC_NET(rqstp); + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); + + memset(&ud, 0, sizeof(ud)); +@@ -1403,7 +1403,7 @@ svcauth_gss_accept(struct svc_rqst *rqst + __be32 *rpcstart; + __be32 *reject_stat = resv->iov_base + resv->iov_len; + int ret; +- struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); ++ struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id); + + dprintk("RPC: svcauth_gss: argv->iov_len = %zd\n", + argv->iov_len); +@@ -1691,7 +1691,7 @@ svcauth_gss_release(struct svc_rqst *rqs + struct rpc_gss_wire_cred *gc = &gsd->clcred; + struct xdr_buf *resbuf = &rqstp->rq_res; + int stat = -EINVAL; +- struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); ++ struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id); + + if (gc->gc_proc != RPC_GSS_PROC_DATA) + goto out; -- 2.47.3