From: Dave Hansen <dave@linux.vnet.ibm.com>
To: David Rientjes <rientjes@google.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
Johannes Weiner <hannes@cmpxchg.org>,
Michal Nazarewicz <mina86@mina86.com>,
Andrew Morton <akpm@linux-foundation.org>
Subject: Re: [PATCH 1/2] break out page allocation warning code
Date: Tue, 19 Apr 2011 18:41:13 -0700 [thread overview]
Message-ID: <1303263673.5076.612.camel@nimitz> (raw)
In-Reply-To: <alpine.DEB.2.00.1104191419470.510@chino.kir.corp.google.com>
On Tue, 2011-04-19 at 14:21 -0700, David Rientjes wrote:
> On Tue, 19 Apr 2011, KOSAKI Motohiro wrote:
> > The rule is,
> >
> > 1) writing comm
> > need task_lock
> > 2) read _another_ thread's comm
> > need task_lock
> > 3) read own comm
> > no need task_lock
>
> That was true a while ago, but you now need to protect every thread's
> ->comm with get_task_comm() or ensuring task_lock() is held to protect
> against /proc/pid/comm which can change other thread's ->comm. That was
> different before when prctl(PR_SET_NAME) would only operate on current, so
> no lock was needed when reading current->comm.
Everybody still goes through set_task_comm() to _set_ it, though. That
means that the worst case scenario that we get is output truncated
(possibly to nothing). We already have at least one existing user in
mm/ (kmemleak) that thinks this is OK. I'd tend to err in the direction
of taking a truncated or empty task name to possibly locking up the
system.
There are also plenty of instances of current->comm going in to the
kernel these days. I count 18 added since 2.6.37.
As for a long-term fix, locks probably aren't the answer. Would
something like this completely untested patch work? It would have the
added bonus that it keeps tsk->comm users working for the moment. We
could eventually add an rcu_read_lock()-annotated access function.
---
linux-2.6.git-dave/fs/exec.c | 22 +++++++++++++++-------
linux-2.6.git-dave/include/linux/init_task.h | 3 ++-
linux-2.6.git-dave/include/linux/sched.h | 3 ++-
3 files changed, 19 insertions(+), 9 deletions(-)
diff -puN mm/page_alloc.c~tsk_comm mm/page_alloc.c
diff -puN include/linux/sched.h~tsk_comm include/linux/sched.h
--- linux-2.6.git/include/linux/sched.h~tsk_comm 2011-04-19 18:23:58.435013635 -0700
+++ linux-2.6.git-dave/include/linux/sched.h 2011-04-19 18:24:44.651034028 -0700
@@ -1334,10 +1334,11 @@ struct task_struct {
* credentials (COW) */
struct cred *replacement_session_keyring; /* for KEYCTL_SESSION_TO_PARENT */
- char comm[TASK_COMM_LEN]; /* executable name excluding path
+ char comm_buf[TASK_COMM_LEN]; /* executable name excluding path
- access with [gs]et_task_comm (which lock
it with task_lock())
- initialized normally by setup_new_exec */
+ char __rcu *comm;
/* file system info */
int link_count, total_link_count;
#ifdef CONFIG_SYSVIPC
diff -puN include/linux/init_task.h~tsk_comm include/linux/init_task.h
--- linux-2.6.git/include/linux/init_task.h~tsk_comm 2011-04-19 18:24:48.703035798 -0700
+++ linux-2.6.git-dave/include/linux/init_task.h 2011-04-19 18:25:22.147050279 -0700
@@ -161,7 +161,8 @@ extern struct cred init_cred;
.group_leader = &tsk, \
RCU_INIT_POINTER(.real_cred, &init_cred), \
RCU_INIT_POINTER(.cred, &init_cred), \
- .comm = "swapper", \
+ .comm_buf = "swapper", \
+ .comm = &tsk.comm_buf, \
.thread = INIT_THREAD, \
.fs = &init_fs, \
.files = &init_files, \
diff -puN fs/exec.c~tsk_comm fs/exec.c
--- linux-2.6.git/fs/exec.c~tsk_comm 2011-04-19 18:25:32.283054625 -0700
+++ linux-2.6.git-dave/fs/exec.c 2011-04-19 18:37:47.991485880 -0700
@@ -1007,17 +1007,25 @@ char *get_task_comm(char *buf, struct ta
void set_task_comm(struct task_struct *tsk, char *buf)
{
+ char tmp_comm[TASK_COMM_LEN];
+
task_lock(tsk);
+ memcpy(tmp_comm, tsk->comm_buf, TASK_COMM_LEN);
+ tsk->comm = tmp;
/*
- * Threads may access current->comm without holding
- * the task lock, so write the string carefully.
- * Readers without a lock may see incomplete new
- * names but are safe from non-terminating string reads.
+ * Make sure no one is still looking at tsk->comm_buf
*/
- memset(tsk->comm, 0, TASK_COMM_LEN);
- wmb();
- strlcpy(tsk->comm, buf, sizeof(tsk->comm));
+ synchronize_rcu();
+
+ strlcpy(tsk->comm_buf, buf, sizeof(tsk->comm));
+ tsk->comm = tsk->com_buff;
+ /*
+ * Make sure no one is still looking at the
+ * stack-allocated buffer
+ */
+ synchronize_rcu();
+
task_unlock(tsk);
perf_event_comm(tsk);
}
-- Dave
WARNING: multiple messages have this Message-ID (diff)
From: Dave Hansen <dave@linux.vnet.ibm.com>
To: David Rientjes <rientjes@google.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
Johannes Weiner <hannes@cmpxchg.org>,
Michal Nazarewicz <mina86@mina86.com>,
Andrew Morton <akpm@linux-foundation.org>
Subject: Re: [PATCH 1/2] break out page allocation warning code
Date: Tue, 19 Apr 2011 18:41:13 -0700 [thread overview]
Message-ID: <1303263673.5076.612.camel@nimitz> (raw)
In-Reply-To: <alpine.DEB.2.00.1104191419470.510@chino.kir.corp.google.com>
On Tue, 2011-04-19 at 14:21 -0700, David Rientjes wrote:
> On Tue, 19 Apr 2011, KOSAKI Motohiro wrote:
> > The rule is,
> >
> > 1) writing comm
> > need task_lock
> > 2) read _another_ thread's comm
> > need task_lock
> > 3) read own comm
> > no need task_lock
>
> That was true a while ago, but you now need to protect every thread's
> ->comm with get_task_comm() or ensuring task_lock() is held to protect
> against /proc/pid/comm which can change other thread's ->comm. That was
> different before when prctl(PR_SET_NAME) would only operate on current, so
> no lock was needed when reading current->comm.
Everybody still goes through set_task_comm() to _set_ it, though. That
means that the worst case scenario that we get is output truncated
(possibly to nothing). We already have at least one existing user in
mm/ (kmemleak) that thinks this is OK. I'd tend to err in the direction
of taking a truncated or empty task name to possibly locking up the
system.
There are also plenty of instances of current->comm going in to the
kernel these days. I count 18 added since 2.6.37.
As for a long-term fix, locks probably aren't the answer. Would
something like this completely untested patch work? It would have the
added bonus that it keeps tsk->comm users working for the moment. We
could eventually add an rcu_read_lock()-annotated access function.
---
linux-2.6.git-dave/fs/exec.c | 22 +++++++++++++++-------
linux-2.6.git-dave/include/linux/init_task.h | 3 ++-
linux-2.6.git-dave/include/linux/sched.h | 3 ++-
3 files changed, 19 insertions(+), 9 deletions(-)
diff -puN mm/page_alloc.c~tsk_comm mm/page_alloc.c
diff -puN include/linux/sched.h~tsk_comm include/linux/sched.h
--- linux-2.6.git/include/linux/sched.h~tsk_comm 2011-04-19 18:23:58.435013635 -0700
+++ linux-2.6.git-dave/include/linux/sched.h 2011-04-19 18:24:44.651034028 -0700
@@ -1334,10 +1334,11 @@ struct task_struct {
* credentials (COW) */
struct cred *replacement_session_keyring; /* for KEYCTL_SESSION_TO_PARENT */
- char comm[TASK_COMM_LEN]; /* executable name excluding path
+ char comm_buf[TASK_COMM_LEN]; /* executable name excluding path
- access with [gs]et_task_comm (which lock
it with task_lock())
- initialized normally by setup_new_exec */
+ char __rcu *comm;
/* file system info */
int link_count, total_link_count;
#ifdef CONFIG_SYSVIPC
diff -puN include/linux/init_task.h~tsk_comm include/linux/init_task.h
--- linux-2.6.git/include/linux/init_task.h~tsk_comm 2011-04-19 18:24:48.703035798 -0700
+++ linux-2.6.git-dave/include/linux/init_task.h 2011-04-19 18:25:22.147050279 -0700
@@ -161,7 +161,8 @@ extern struct cred init_cred;
.group_leader = &tsk, \
RCU_INIT_POINTER(.real_cred, &init_cred), \
RCU_INIT_POINTER(.cred, &init_cred), \
- .comm = "swapper", \
+ .comm_buf = "swapper", \
+ .comm = &tsk.comm_buf, \
.thread = INIT_THREAD, \
.fs = &init_fs, \
.files = &init_files, \
diff -puN fs/exec.c~tsk_comm fs/exec.c
--- linux-2.6.git/fs/exec.c~tsk_comm 2011-04-19 18:25:32.283054625 -0700
+++ linux-2.6.git-dave/fs/exec.c 2011-04-19 18:37:47.991485880 -0700
@@ -1007,17 +1007,25 @@ char *get_task_comm(char *buf, struct ta
void set_task_comm(struct task_struct *tsk, char *buf)
{
+ char tmp_comm[TASK_COMM_LEN];
+
task_lock(tsk);
+ memcpy(tmp_comm, tsk->comm_buf, TASK_COMM_LEN);
+ tsk->comm = tmp;
/*
- * Threads may access current->comm without holding
- * the task lock, so write the string carefully.
- * Readers without a lock may see incomplete new
- * names but are safe from non-terminating string reads.
+ * Make sure no one is still looking at tsk->comm_buf
*/
- memset(tsk->comm, 0, TASK_COMM_LEN);
- wmb();
- strlcpy(tsk->comm, buf, sizeof(tsk->comm));
+ synchronize_rcu();
+
+ strlcpy(tsk->comm_buf, buf, sizeof(tsk->comm));
+ tsk->comm = tsk->com_buff;
+ /*
+ * Make sure no one is still looking at the
+ * stack-allocated buffer
+ */
+ synchronize_rcu();
+
task_unlock(tsk);
perf_event_comm(tsk);
}
-- Dave
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2011-04-20 1:41 UTC|newest]
Thread overview: 79+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-04-15 17:04 [PATCH 1/2] break out page allocation warning code Dave Hansen
2011-04-15 17:04 ` Dave Hansen
2011-04-15 17:04 ` [PATCH 2/2] print vmalloc() state after allocation failures Dave Hansen
2011-04-15 17:04 ` Dave Hansen
2011-04-15 17:20 ` Michal Nazarewicz
2011-04-15 17:20 ` Michal Nazarewicz
2011-04-15 17:44 ` Dave Hansen
2011-04-15 17:44 ` Dave Hansen
2011-04-17 0:03 ` David Rientjes
2011-04-17 0:03 ` David Rientjes
2011-04-18 15:21 ` Dave Hansen
2011-04-18 15:21 ` Dave Hansen
2011-04-17 0:02 ` [PATCH 1/2] break out page allocation warning code David Rientjes
2011-04-17 0:02 ` David Rientjes
2011-04-18 15:10 ` Dave Hansen
2011-04-18 15:10 ` Dave Hansen
2011-04-18 20:25 ` David Rientjes
2011-04-18 20:25 ` David Rientjes
2011-04-18 20:57 ` Dave Hansen
2011-04-18 20:57 ` Dave Hansen
2011-04-19 21:23 ` David Rientjes
2011-04-19 21:23 ` David Rientjes
2011-04-18 21:03 ` Dave Hansen
2011-04-18 21:03 ` Dave Hansen
2011-04-18 21:22 ` Dave Hansen
2011-04-18 21:22 ` Dave Hansen
2011-04-19 0:44 ` KOSAKI Motohiro
2011-04-19 0:44 ` KOSAKI Motohiro
2011-04-19 21:21 ` David Rientjes
2011-04-19 21:21 ` David Rientjes
2011-04-20 0:39 ` KOSAKI Motohiro
2011-04-20 0:39 ` KOSAKI Motohiro
2011-04-20 20:24 ` David Rientjes
2011-04-20 20:24 ` David Rientjes
2011-04-20 20:34 ` john stultz
2011-04-20 20:34 ` john stultz
2011-04-21 1:29 ` KOSAKI Motohiro
2011-04-21 1:29 ` KOSAKI Motohiro
2011-04-25 4:21 ` KOSAKI Motohiro
2011-04-25 4:21 ` KOSAKI Motohiro
2011-04-26 19:27 ` john stultz
2011-04-26 19:27 ` john stultz
2011-04-27 23:51 ` David Rientjes
2011-04-27 23:51 ` David Rientjes
2011-04-28 0:32 ` john stultz
2011-04-28 0:32 ` john stultz
2011-04-28 1:29 ` john stultz
2011-04-28 1:29 ` john stultz
2011-04-28 22:48 ` David Rientjes
2011-04-28 22:48 ` David Rientjes
2011-04-28 23:48 ` john stultz
2011-04-28 23:48 ` john stultz
2011-04-29 0:04 ` john stultz
2011-04-29 0:04 ` john stultz
2011-04-26 21:25 ` john stultz
2011-04-26 21:25 ` john stultz
2011-04-28 3:05 ` KOSAKI Motohiro
2011-04-28 3:05 ` KOSAKI Motohiro
2011-04-20 1:41 ` Dave Hansen [this message]
2011-04-20 1:41 ` Dave Hansen
2011-04-20 1:50 ` KOSAKI Motohiro
2011-04-20 1:50 ` KOSAKI Motohiro
2011-04-20 2:19 ` KOSAKI Motohiro
2011-04-20 2:19 ` KOSAKI Motohiro
2011-04-20 2:46 ` Dave Hansen
2011-04-20 2:46 ` Dave Hansen
-- strict thread matches above, loose matches on Subject: below --
2011-04-19 16:21 Dave Hansen
2011-04-19 16:21 ` Dave Hansen
2011-04-08 20:22 Dave Hansen
2011-04-08 20:22 ` Dave Hansen
2011-04-08 20:37 ` David Rientjes
2011-04-08 20:37 ` David Rientjes
2011-04-08 20:43 ` Dave Hansen
2011-04-08 20:43 ` Dave Hansen
2011-04-08 20:54 ` Michał Nazarewicz
2011-04-08 21:02 ` Dave Hansen
2011-04-08 21:02 ` Dave Hansen
2011-04-11 10:20 ` Michal Nazarewicz
2011-04-11 10:20 ` Michal Nazarewicz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1303263673.5076.612.camel@nimitz \
--to=dave@linux.vnet.ibm.com \
--cc=akpm@linux-foundation.org \
--cc=hannes@cmpxchg.org \
--cc=kosaki.motohiro@jp.fujitsu.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mina86@mina86.com \
--cc=rientjes@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.