From: Jiri Slaby <jirislaby@gmail.com>
To: John Stultz <john.stultz@linaro.org>
Cc: LKML <linux-kernel@vger.kernel.org>, "Ted Ts'o" <tytso@mit.edu>,
KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>,
David Rientjes <rientjes@google.com>,
Dave Hansen <dave@linux.vnet.ibm.com>,
Andrew Morton <akpm@linux-foundation.org>,
linux-mm@kvack.org
Subject: Re: [PATCH 1/3] comm: Introduce comm_lock seqlock to protect task->comm access
Date: Tue, 17 May 2011 00:01:25 +0200 [thread overview]
Message-ID: <4DD19EB5.7060900@gmail.com> (raw)
In-Reply-To: <1305580757-13175-2-git-send-email-john.stultz@linaro.org>
On 05/16/2011 11:19 PM, John Stultz wrote:
> The implicit rules for current->comm access being safe without locking
> are no longer true. Accessing current->comm without holding the task
> lock may result in null or incomplete strings (however, access won't
> run off the end of the string).
>
> In order to properly fix this, I've introduced a comm_lock spinlock
> which will protect comm access and modified get_task_comm() and
> set_task_comm() to use it.
>
> Since there are a number of cases where comm access is open-coded
> safely grabbing the task_lock(), we preserve the task locking in
> set_task_comm, so those users are also safe.
>
> With this patch, users that access current->comm without a lock
> are still prone to null/incomplete comm strings, but it should
> be no worse then it is now.
>
> The next step is to go through and convert all comm accesses to
> use get_task_comm(). This is substantial, but can be done bit by
> bit, reducing the race windows with each patch.
>
> CC: Ted Ts'o <tytso@mit.edu>
> CC: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
> CC: David Rientjes <rientjes@google.com>
> CC: Dave Hansen <dave@linux.vnet.ibm.com>
> CC: Andrew Morton <akpm@linux-foundation.org>
> CC: linux-mm@kvack.org
> Acked-by: David Rientjes <rientjes@google.com>
> Signed-off-by: John Stultz <john.stultz@linaro.org>
> ---
> fs/exec.c | 19 ++++++++++++++++---
> include/linux/init_task.h | 1 +
> include/linux/sched.h | 5 ++---
> 3 files changed, 19 insertions(+), 6 deletions(-)
>
> diff --git a/fs/exec.c b/fs/exec.c
> index 5e62d26..34fa611 100644
> --- a/fs/exec.c
> +++ b/fs/exec.c
> @@ -998,17 +998,28 @@ static void flush_old_files(struct files_struct * files)
>
> char *get_task_comm(char *buf, struct task_struct *tsk)
> {
> - /* buf must be at least sizeof(tsk->comm) in size */
> - task_lock(tsk);
> + unsigned long flags;
> +
> + spin_lock_irqsave(&tsk->comm_lock, flags);
> strncpy(buf, tsk->comm, sizeof(tsk->comm));
> - task_unlock(tsk);
> + spin_unlock_irqrestore(&tsk->comm_lock, flags);
> return buf;
> }
>
> void set_task_comm(struct task_struct *tsk, char *buf)
> {
> + unsigned long flags;
> +
> + /*
> + * XXX - Even though comm is protected by comm_lock,
> + * we take the task_lock here to serialize against
> + * current users that directly access comm.
> + * Once those users are removed, we can drop the
> + * task locking & memsetting.
> + */
> task_lock(tsk);
>
> + spin_lock_irqsave(&tsk->comm_lock, flags);
> /*
> * Threads may access current->comm without holding
> * the task lock, so write the string carefully.
> @@ -1018,6 +1029,8 @@ void set_task_comm(struct task_struct *tsk, char *buf)
> memset(tsk->comm, 0, TASK_COMM_LEN);
> wmb();
> strlcpy(tsk->comm, buf, sizeof(tsk->comm));
> + spin_unlock_irqrestore(&tsk->comm_lock, flags);
> +
> task_unlock(tsk);
> perf_event_comm(tsk);
> }
> diff --git a/include/linux/init_task.h b/include/linux/init_task.h
> index caa151f..b69d94b 100644
> --- a/include/linux/init_task.h
> +++ b/include/linux/init_task.h
> @@ -161,6 +161,7 @@ extern struct cred init_cred;
> .group_leader = &tsk, \
> RCU_INIT_POINTER(.real_cred, &init_cred), \
> RCU_INIT_POINTER(.cred, &init_cred), \
> + .comm_lock = __SPIN_LOCK_UNLOCKED(tsk.comm_lock), \
Hmm, you should also init the spinlock somewhere in copy_process.
Otherwise when a process is forked in the middle of [gs]et_task_comm
called on it on another cpu, you have two locked locks and only the
parent's will be unlocked, right?
> .comm = "swapper", \
> .thread = INIT_THREAD, \
> .fs = &init_fs, \
> diff --git a/include/linux/sched.h b/include/linux/sched.h
> index 18d63ce..f8a7cdf 100644
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -1333,10 +1333,9 @@ struct task_struct {
> const struct cred __rcu *cred; /* effective (overridable) subjective task
> * credentials (COW) */
> struct cred *replacement_session_keyring; /* for KEYCTL_SESSION_TO_PARENT */
> -
> + spinlock_t comm_lock; /* protect's comm */
> char comm[TASK_COMM_LEN]; /* executable name excluding path
> - - access with [gs]et_task_comm (which lock
> - it with task_lock())
> + - access with [gs]et_task_comm
> - initialized normally by setup_new_exec */
> /* file system info */
> int link_count, total_link_count;
thanks,
--
js
WARNING: multiple messages have this Message-ID (diff)
From: Jiri Slaby <jirislaby@gmail.com>
To: John Stultz <john.stultz@linaro.org>
Cc: LKML <linux-kernel@vger.kernel.org>, Ted Ts'o <tytso@mit.edu>,
KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>,
David Rientjes <rientjes@google.com>,
Dave Hansen <dave@linux.vnet.ibm.com>,
Andrew Morton <akpm@linux-foundation.org>,
linux-mm@kvack.org
Subject: Re: [PATCH 1/3] comm: Introduce comm_lock seqlock to protect task->comm access
Date: Tue, 17 May 2011 00:01:25 +0200 [thread overview]
Message-ID: <4DD19EB5.7060900@gmail.com> (raw)
In-Reply-To: <1305580757-13175-2-git-send-email-john.stultz@linaro.org>
On 05/16/2011 11:19 PM, John Stultz wrote:
> The implicit rules for current->comm access being safe without locking
> are no longer true. Accessing current->comm without holding the task
> lock may result in null or incomplete strings (however, access won't
> run off the end of the string).
>
> In order to properly fix this, I've introduced a comm_lock spinlock
> which will protect comm access and modified get_task_comm() and
> set_task_comm() to use it.
>
> Since there are a number of cases where comm access is open-coded
> safely grabbing the task_lock(), we preserve the task locking in
> set_task_comm, so those users are also safe.
>
> With this patch, users that access current->comm without a lock
> are still prone to null/incomplete comm strings, but it should
> be no worse then it is now.
>
> The next step is to go through and convert all comm accesses to
> use get_task_comm(). This is substantial, but can be done bit by
> bit, reducing the race windows with each patch.
>
> CC: Ted Ts'o <tytso@mit.edu>
> CC: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
> CC: David Rientjes <rientjes@google.com>
> CC: Dave Hansen <dave@linux.vnet.ibm.com>
> CC: Andrew Morton <akpm@linux-foundation.org>
> CC: linux-mm@kvack.org
> Acked-by: David Rientjes <rientjes@google.com>
> Signed-off-by: John Stultz <john.stultz@linaro.org>
> ---
> fs/exec.c | 19 ++++++++++++++++---
> include/linux/init_task.h | 1 +
> include/linux/sched.h | 5 ++---
> 3 files changed, 19 insertions(+), 6 deletions(-)
>
> diff --git a/fs/exec.c b/fs/exec.c
> index 5e62d26..34fa611 100644
> --- a/fs/exec.c
> +++ b/fs/exec.c
> @@ -998,17 +998,28 @@ static void flush_old_files(struct files_struct * files)
>
> char *get_task_comm(char *buf, struct task_struct *tsk)
> {
> - /* buf must be at least sizeof(tsk->comm) in size */
> - task_lock(tsk);
> + unsigned long flags;
> +
> + spin_lock_irqsave(&tsk->comm_lock, flags);
> strncpy(buf, tsk->comm, sizeof(tsk->comm));
> - task_unlock(tsk);
> + spin_unlock_irqrestore(&tsk->comm_lock, flags);
> return buf;
> }
>
> void set_task_comm(struct task_struct *tsk, char *buf)
> {
> + unsigned long flags;
> +
> + /*
> + * XXX - Even though comm is protected by comm_lock,
> + * we take the task_lock here to serialize against
> + * current users that directly access comm.
> + * Once those users are removed, we can drop the
> + * task locking & memsetting.
> + */
> task_lock(tsk);
>
> + spin_lock_irqsave(&tsk->comm_lock, flags);
> /*
> * Threads may access current->comm without holding
> * the task lock, so write the string carefully.
> @@ -1018,6 +1029,8 @@ void set_task_comm(struct task_struct *tsk, char *buf)
> memset(tsk->comm, 0, TASK_COMM_LEN);
> wmb();
> strlcpy(tsk->comm, buf, sizeof(tsk->comm));
> + spin_unlock_irqrestore(&tsk->comm_lock, flags);
> +
> task_unlock(tsk);
> perf_event_comm(tsk);
> }
> diff --git a/include/linux/init_task.h b/include/linux/init_task.h
> index caa151f..b69d94b 100644
> --- a/include/linux/init_task.h
> +++ b/include/linux/init_task.h
> @@ -161,6 +161,7 @@ extern struct cred init_cred;
> .group_leader = &tsk, \
> RCU_INIT_POINTER(.real_cred, &init_cred), \
> RCU_INIT_POINTER(.cred, &init_cred), \
> + .comm_lock = __SPIN_LOCK_UNLOCKED(tsk.comm_lock), \
Hmm, you should also init the spinlock somewhere in copy_process.
Otherwise when a process is forked in the middle of [gs]et_task_comm
called on it on another cpu, you have two locked locks and only the
parent's will be unlocked, right?
> .comm = "swapper", \
> .thread = INIT_THREAD, \
> .fs = &init_fs, \
> diff --git a/include/linux/sched.h b/include/linux/sched.h
> index 18d63ce..f8a7cdf 100644
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -1333,10 +1333,9 @@ struct task_struct {
> const struct cred __rcu *cred; /* effective (overridable) subjective task
> * credentials (COW) */
> struct cred *replacement_session_keyring; /* for KEYCTL_SESSION_TO_PARENT */
> -
> + spinlock_t comm_lock; /* protect's comm */
> char comm[TASK_COMM_LEN]; /* executable name excluding path
> - - access with [gs]et_task_comm (which lock
> - it with task_lock())
> + - access with [gs]et_task_comm
> - initialized normally by setup_new_exec */
> /* file system info */
> int link_count, total_link_count;
thanks,
--
js
--
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-05-16 22:01 UTC|newest]
Thread overview: 58+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-05-16 21:19 [PATCH 0/3] v4 Improve task->comm locking situation John Stultz
2011-05-16 21:19 ` John Stultz
2011-05-16 21:19 ` [PATCH 1/3] comm: Introduce comm_lock seqlock to protect task->comm access John Stultz
2011-05-16 21:19 ` John Stultz
2011-05-16 22:01 ` Jiri Slaby [this message]
2011-05-16 22:01 ` Jiri Slaby
2011-05-17 1:47 ` John Stultz
2011-05-17 1:47 ` John Stultz
2011-05-18 0:28 ` KOSAKI Motohiro
2011-05-18 0:28 ` KOSAKI Motohiro
2011-05-16 21:19 ` [PATCH 2/3] printk: Add %ptc to safely print a task's comm John Stultz
2011-05-16 21:19 ` John Stultz
2011-05-16 21:54 ` Jiri Slaby
2011-05-16 21:54 ` Jiri Slaby
2011-05-16 23:10 ` John Stultz
2011-05-16 23:10 ` John Stultz
2011-05-16 23:56 ` Joe Perches
2011-05-16 23:56 ` Joe Perches
2011-05-17 0:11 ` John Stultz
2011-05-17 0:11 ` John Stultz
2011-05-17 7:21 ` Jiri Slaby
2011-05-17 7:21 ` Jiri Slaby
2011-05-18 0:32 ` KOSAKI Motohiro
2011-05-18 0:32 ` KOSAKI Motohiro
2011-05-16 21:19 ` [PATCH 3/3] checkpatch.pl: Add check for task comm references John Stultz
2011-05-16 21:19 ` John Stultz
2011-05-16 21:29 ` Michal Nazarewicz
2011-05-16 21:29 ` Michal Nazarewicz
2011-05-16 21:34 ` David Rientjes
2011-05-16 21:34 ` David Rientjes
2011-05-16 23:04 ` Joe Perches
2011-05-16 23:04 ` Joe Perches
2011-05-16 23:11 ` Michal Nazarewicz
2011-05-16 23:11 ` Michal Nazarewicz
2011-05-16 23:22 ` Joe Perches
2011-05-16 23:22 ` Joe Perches
2011-05-18 3:16 ` [PATCH 0/3] v4 Improve task->comm locking situation Tetsuo Handa
2011-05-18 4:10 ` KOSAKI Motohiro
2011-05-18 4:15 ` John Stultz
2011-05-18 5:27 ` Tetsuo Handa
-- strict thread matches above, loose matches on Subject: below --
2011-05-12 23:02 [PATCH 0/3] v3 " John Stultz
2011-05-12 23:02 ` [PATCH 1/3] comm: Introduce comm_lock seqlock to protect task->comm access John Stultz
2011-05-12 23:02 ` John Stultz
2011-05-13 11:13 ` KOSAKI Motohiro
2011-05-13 11:13 ` KOSAKI Motohiro
2011-05-13 18:27 ` John Stultz
2011-05-13 18:27 ` John Stultz
2011-05-14 11:12 ` KOSAKI Motohiro
2011-05-14 11:12 ` KOSAKI Motohiro
2011-05-16 20:34 ` John Stultz
2011-05-16 20:34 ` John Stultz
2011-05-11 0:23 [RFC][PATCH 0/3] v2 Improve task->comm locking situation John Stultz
2011-05-11 0:23 ` [PATCH 1/3] comm: Introduce comm_lock seqlock to protect task->comm access John Stultz
2011-05-11 0:23 ` John Stultz
2011-05-11 17:39 ` Andi Kleen
2011-05-11 17:39 ` Andi Kleen
2011-05-12 22:00 ` David Rientjes
2011-05-12 22:00 ` David Rientjes
2011-04-28 4:03 [RFC][PATCH 0/3] Improve task->comm locking situation John Stultz
2011-04-28 4:03 ` [PATCH 1/3] comm: Introduce comm_lock seqlock to protect task->comm access John Stultz
2011-04-28 4:03 ` John Stultz
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=4DD19EB5.7060900@gmail.com \
--to=jirislaby@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=dave@linux.vnet.ibm.com \
--cc=john.stultz@linaro.org \
--cc=kosaki.motohiro@jp.fujitsu.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=rientjes@google.com \
--cc=tytso@mit.edu \
/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.