Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1231040 > unrolled thread
| Started by | David Rientjes <rientjes@google.com> |
|---|---|
| First post | 2015-09-23 01:40 +0200 |
| Last post | 2015-09-24 21:50 +0200 |
| Articles | 11 — 5 participants |
Back to article view | Back to linux.kernel
[patch] mm, oom: remove task_lock protecting comm printing David Rientjes <rientjes@google.com> - 2015-09-23 01:40 +0200
Re: [patch] mm, oom: remove task_lock protecting comm printing Michal Hocko <mhocko@kernel.org> - 2015-09-23 09:50 +0200
Re: [patch] mm, oom: remove task_lock protecting comm printing Vladimir Davydov <vdavydov@parallels.com> - 2015-09-23 10:10 +0200
Re: [patch] mm, oom: remove task_lock protecting comm printing Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com> - 2015-09-23 11:20 +0200
Re: [patch] mm, oom: remove task_lock protecting comm printing Vladimir Davydov <vdavydov@parallels.com> - 2015-09-23 11:40 +0200
Re: [patch] mm, oom: remove task_lock protecting comm printing Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com> - 2015-09-23 11:50 +0200
Re: [patch] mm, oom: remove task_lock protecting comm printing Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com> - 2015-09-23 12:00 +0200
Re: [patch] mm, oom: remove task_lock protecting comm printing Vladimir Davydov <vdavydov@parallels.com> - 2015-09-23 12:10 +0200
Re: [patch] mm, oom: remove task_lock protecting comm printing Michal Hocko <mhocko@kernel.org> - 2015-09-23 12:50 +0200
Re: [patch] mm, oom: remove task_lock protecting comm printing Michal Hocko <mhocko@kernel.org> - 2015-09-23 11:50 +0200
Re: [patch] mm, oom: remove task_lock protecting comm printing Johannes Weiner <hannes@cmpxchg.org> - 2015-09-24 21:50 +0200
| From | David Rientjes <rientjes@google.com> |
|---|---|
| Date | 2015-09-23 01:40 +0200 |
| Subject | [patch] mm, oom: remove task_lock protecting comm printing |
| Message-ID | <qbFkf-3rQ-9@gated-at.bofh.it> |
The oom killer takes task_lock() in a couple of places solely to protect
printing the task's comm.
A process's comm, including current's comm, may change due to
/proc/pid/comm or PR_SET_NAME.
The comm will always be NULL-terminated, so the worst race scenario would
only be during update. We can tolerate a comm being printed that is in
the middle of an update to avoid taking the lock.
Other locations in the kernel have already dropped task_lock() when
printing comm, so this is consistent.
Suggested-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: David Rientjes <rientjes@google.com>
---
include/linux/cpuset.h | 4 ++--
kernel/cpuset.c | 14 +++++++-------
mm/oom_kill.c | 8 +-------
3 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -93,7 +93,7 @@ extern int current_cpuset_is_being_rebound(void);
extern void rebuild_sched_domains(void);
-extern void cpuset_print_task_mems_allowed(struct task_struct *p);
+extern void cpuset_print_current_mems_allowed(void);
/*
* read_mems_allowed_begin is required when making decisions involving
@@ -219,7 +219,7 @@ static inline void rebuild_sched_domains(void)
partition_sched_domains(1, NULL, NULL);
}
-static inline void cpuset_print_task_mems_allowed(struct task_struct *p)
+static inline void cpuset_print_current_mems_allowed(void)
{
}
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -2599,22 +2599,22 @@ int cpuset_mems_allowed_intersects(const struct task_struct *tsk1,
}
/**
- * cpuset_print_task_mems_allowed - prints task's cpuset and mems_allowed
- * @tsk: pointer to task_struct of some task.
+ * cpuset_print_current_mems_allowed - prints current's cpuset and mems_allowed
*
- * Description: Prints @task's name, cpuset name, and cached copy of its
+ * Description: Prints current's name, cpuset name, and cached copy of its
* mems_allowed to the kernel log.
*/
-void cpuset_print_task_mems_allowed(struct task_struct *tsk)
+void cpuset_print_current_mems_allowed(void)
{
struct cgroup *cgrp;
rcu_read_lock();
- cgrp = task_cs(tsk)->css.cgroup;
- pr_info("%s cpuset=", tsk->comm);
+ cgrp = task_cs(current)->css.cgroup;
+ pr_info("%s cpuset=", current->comm);
pr_cont_cgroup_name(cgrp);
- pr_cont(" mems_allowed=%*pbl\n", nodemask_pr_args(&tsk->mems_allowed));
+ pr_cont(" mems_allowed=%*pbl\n",
+ nodemask_pr_args(¤t->mems_allowed));
rcu_read_unlock();
}
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -386,13 +386,11 @@ static void dump_tasks(struct mem_cgroup *memcg, const nodemask_t *nodemask)
static void dump_header(struct oom_control *oc, struct task_struct *p,
struct mem_cgroup *memcg)
{
- task_lock(current);
pr_warning("%s invoked oom-killer: gfp_mask=0x%x, order=%d, "
"oom_score_adj=%hd\n",
current->comm, oc->gfp_mask, oc->order,
current->signal->oom_score_adj);
- cpuset_print_task_mems_allowed(current);
- task_unlock(current);
+ cpuset_print_current_mems_allowed();
dump_stack();
if (memcg)
mem_cgroup_print_oom_info(memcg, p);
@@ -518,10 +516,8 @@ void oom_kill_process(struct oom_control *oc, struct task_struct *p,
if (__ratelimit(&oom_rs))
dump_header(oc, p, memcg);
- task_lock(p);
pr_err("%s: Kill process %d (%s) score %u or sacrifice child\n",
message, task_pid_nr(p), p->comm, points);
- task_unlock(p);
/*
* If any of p's children has a different mm and is eligible for kill,
@@ -586,10 +582,8 @@ void oom_kill_process(struct oom_control *oc, struct task_struct *p,
if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
continue;
- task_lock(p); /* Protect ->comm from prctl() */
pr_err("Kill process %d (%s) sharing same memory\n",
task_pid_nr(p), p->comm);
- task_unlock(p);
do_send_sig_info(SIGKILL, SEND_SIG_FORCED, p, true);
}
rcu_read_unlock();
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2015-09-23 09:50 +0200 |
| Message-ID | <qbMYq-686-7@gated-at.bofh.it> |
| In reply to | #1231040 |
On Tue 22-09-15 16:30:13, David Rientjes wrote:
> The oom killer takes task_lock() in a couple of places solely to protect
> printing the task's comm.
>
> A process's comm, including current's comm, may change due to
> /proc/pid/comm or PR_SET_NAME.
>
> The comm will always be NULL-terminated, so the worst race scenario would
> only be during update. We can tolerate a comm being printed that is in
> the middle of an update to avoid taking the lock.
>
> Other locations in the kernel have already dropped task_lock() when
> printing comm, so this is consistent.
cpuset_print_task_mems_allowed seems unrelated and it would probably
deserve a separate pach.
> Suggested-by: Oleg Nesterov <oleg@redhat.com>
> Signed-off-by: David Rientjes <rientjes@google.com>
For the task_lock part
Acked-by: Michal Hocko <mhocko@suse.com>
> ---
> include/linux/cpuset.h | 4 ++--
> kernel/cpuset.c | 14 +++++++-------
> mm/oom_kill.c | 8 +-------
> 3 files changed, 10 insertions(+), 16 deletions(-)
>
> diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
> --- a/include/linux/cpuset.h
> +++ b/include/linux/cpuset.h
> @@ -93,7 +93,7 @@ extern int current_cpuset_is_being_rebound(void);
>
> extern void rebuild_sched_domains(void);
>
> -extern void cpuset_print_task_mems_allowed(struct task_struct *p);
> +extern void cpuset_print_current_mems_allowed(void);
>
> /*
> * read_mems_allowed_begin is required when making decisions involving
> @@ -219,7 +219,7 @@ static inline void rebuild_sched_domains(void)
> partition_sched_domains(1, NULL, NULL);
> }
>
> -static inline void cpuset_print_task_mems_allowed(struct task_struct *p)
> +static inline void cpuset_print_current_mems_allowed(void)
> {
> }
>
> diff --git a/kernel/cpuset.c b/kernel/cpuset.c
> --- a/kernel/cpuset.c
> +++ b/kernel/cpuset.c
> @@ -2599,22 +2599,22 @@ int cpuset_mems_allowed_intersects(const struct task_struct *tsk1,
> }
>
> /**
> - * cpuset_print_task_mems_allowed - prints task's cpuset and mems_allowed
> - * @tsk: pointer to task_struct of some task.
> + * cpuset_print_current_mems_allowed - prints current's cpuset and mems_allowed
> *
> - * Description: Prints @task's name, cpuset name, and cached copy of its
> + * Description: Prints current's name, cpuset name, and cached copy of its
> * mems_allowed to the kernel log.
> */
> -void cpuset_print_task_mems_allowed(struct task_struct *tsk)
> +void cpuset_print_current_mems_allowed(void)
> {
> struct cgroup *cgrp;
>
> rcu_read_lock();
>
> - cgrp = task_cs(tsk)->css.cgroup;
> - pr_info("%s cpuset=", tsk->comm);
> + cgrp = task_cs(current)->css.cgroup;
> + pr_info("%s cpuset=", current->comm);
> pr_cont_cgroup_name(cgrp);
> - pr_cont(" mems_allowed=%*pbl\n", nodemask_pr_args(&tsk->mems_allowed));
> + pr_cont(" mems_allowed=%*pbl\n",
> + nodemask_pr_args(¤t->mems_allowed));
>
> rcu_read_unlock();
> }
> diff --git a/mm/oom_kill.c b/mm/oom_kill.c
> --- a/mm/oom_kill.c
> +++ b/mm/oom_kill.c
> @@ -386,13 +386,11 @@ static void dump_tasks(struct mem_cgroup *memcg, const nodemask_t *nodemask)
> static void dump_header(struct oom_control *oc, struct task_struct *p,
> struct mem_cgroup *memcg)
> {
> - task_lock(current);
> pr_warning("%s invoked oom-killer: gfp_mask=0x%x, order=%d, "
> "oom_score_adj=%hd\n",
> current->comm, oc->gfp_mask, oc->order,
> current->signal->oom_score_adj);
> - cpuset_print_task_mems_allowed(current);
> - task_unlock(current);
> + cpuset_print_current_mems_allowed();
> dump_stack();
> if (memcg)
> mem_cgroup_print_oom_info(memcg, p);
> @@ -518,10 +516,8 @@ void oom_kill_process(struct oom_control *oc, struct task_struct *p,
> if (__ratelimit(&oom_rs))
> dump_header(oc, p, memcg);
>
> - task_lock(p);
> pr_err("%s: Kill process %d (%s) score %u or sacrifice child\n",
> message, task_pid_nr(p), p->comm, points);
> - task_unlock(p);
>
> /*
> * If any of p's children has a different mm and is eligible for kill,
> @@ -586,10 +582,8 @@ void oom_kill_process(struct oom_control *oc, struct task_struct *p,
> if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
> continue;
>
> - task_lock(p); /* Protect ->comm from prctl() */
> pr_err("Kill process %d (%s) sharing same memory\n",
> task_pid_nr(p), p->comm);
> - task_unlock(p);
> do_send_sig_info(SIGKILL, SEND_SIG_FORCED, p, true);
> }
> rcu_read_unlock();
--
Michal Hocko
SUSE Labs
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Vladimir Davydov <vdavydov@parallels.com> |
|---|---|
| Date | 2015-09-23 10:10 +0200 |
| Message-ID | <qbNhL-6K3-3@gated-at.bofh.it> |
| In reply to | #1231040 |
Hi,
On Tue, Sep 22, 2015 at 04:30:13PM -0700, David Rientjes wrote:
> The oom killer takes task_lock() in a couple of places solely to protect
> printing the task's comm.
>
> A process's comm, including current's comm, may change due to
> /proc/pid/comm or PR_SET_NAME.
>
> The comm will always be NULL-terminated, so the worst race scenario would
> only be during update. We can tolerate a comm being printed that is in
> the middle of an update to avoid taking the lock.
>
> Other locations in the kernel have already dropped task_lock() when
> printing comm, so this is consistent.
Without the protection, can't reading task->comm race with PR_SET_NAME
as described below?
Let T->comm[16] = "name\0rubbish1234"
CPU1 CPU2
---- ----
set_task_comm(T, "longname\0")
T->comm[0] = 'l'
T->comm[1] = 'o'
T->comm[2] = 'n'
T->comm[3] = 'g'
T->comm[4] = 'n'
printk("%s\n", T->comm)
T->comm = "longnrubbish1234"
OOPS: the string is not
nil-terminated!
T->comm[5] = 'a'
T->comm[6] = 'm'
T->comm[7] = 'e'
T->comm[8] = '\0'
Thanks,
Vladimir
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com> |
|---|---|
| Date | 2015-09-23 11:20 +0200 |
| Message-ID | <qbOnw-8gf-13@gated-at.bofh.it> |
| In reply to | #1231218 |
On (09/23/15 11:06), Vladimir Davydov wrote:
> Hi,
>
> On Tue, Sep 22, 2015 at 04:30:13PM -0700, David Rientjes wrote:
> > The oom killer takes task_lock() in a couple of places solely to protect
> > printing the task's comm.
> >
> > A process's comm, including current's comm, may change due to
> > /proc/pid/comm or PR_SET_NAME.
> >
> > The comm will always be NULL-terminated, so the worst race scenario would
> > only be during update. We can tolerate a comm being printed that is in
> > the middle of an update to avoid taking the lock.
> >
> > Other locations in the kernel have already dropped task_lock() when
> > printing comm, so this is consistent.
>
> Without the protection, can't reading task->comm race with PR_SET_NAME
> as described below?
the previous name was already null terminated, so it should be
[name\0old_name\0]
-ss
>
> Let T->comm[16] = "name\0rubbish1234"
>
> CPU1 CPU2
> ---- ----
> set_task_comm(T, "longname\0")
> T->comm[0] = 'l'
> T->comm[1] = 'o'
> T->comm[2] = 'n'
> T->comm[3] = 'g'
> T->comm[4] = 'n'
> printk("%s\n", T->comm)
> T->comm = "longnrubbish1234"
> OOPS: the string is not
> nil-terminated!
> T->comm[5] = 'a'
> T->comm[6] = 'm'
> T->comm[7] = 'e'
> T->comm[8] = '\0'
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Vladimir Davydov <vdavydov@parallels.com> |
|---|---|
| Date | 2015-09-23 11:40 +0200 |
| Message-ID | <qbOGS-bd-39@gated-at.bofh.it> |
| In reply to | #1231277 |
On Wed, Sep 23, 2015 at 06:13:54PM +0900, Sergey Senozhatsky wrote:
> On (09/23/15 11:06), Vladimir Davydov wrote:
> > Hi,
> >
> > On Tue, Sep 22, 2015 at 04:30:13PM -0700, David Rientjes wrote:
> > > The oom killer takes task_lock() in a couple of places solely to protect
> > > printing the task's comm.
> > >
> > > A process's comm, including current's comm, may change due to
> > > /proc/pid/comm or PR_SET_NAME.
> > >
> > > The comm will always be NULL-terminated, so the worst race scenario would
> > > only be during update. We can tolerate a comm being printed that is in
> > > the middle of an update to avoid taking the lock.
> > >
> > > Other locations in the kernel have already dropped task_lock() when
> > > printing comm, so this is consistent.
> >
> > Without the protection, can't reading task->comm race with PR_SET_NAME
> > as described below?
>
> the previous name was already null terminated,
Yeah, but if the old name is shorter than the new one, set_task_comm()
overwrites the terminating null of the old name before writing the new
terminating null, so there is a short time window during which tsk->comm
might be not null-terminated, no?
Thanks,
Vladimir
> so it should be
>
> [name\0old_name\0]
>
> -ss
>
> >
> > Let T->comm[16] = "name\0rubbish1234"
> >
> > CPU1 CPU2
> > ---- ----
> > set_task_comm(T, "longname\0")
> > T->comm[0] = 'l'
> > T->comm[1] = 'o'
> > T->comm[2] = 'n'
> > T->comm[3] = 'g'
> > T->comm[4] = 'n'
> > printk("%s\n", T->comm)
> > T->comm = "longnrubbish1234"
> > OOPS: the string is not
> > nil-terminated!
> > T->comm[5] = 'a'
> > T->comm[6] = 'm'
> > T->comm[7] = 'e'
> > T->comm[8] = '\0'
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com> |
|---|---|
| Date | 2015-09-23 11:50 +0200 |
| Message-ID | <qbOQy-mP-13@gated-at.bofh.it> |
| In reply to | #1231289 |
On (09/23/15 11:43), Michal Hocko wrote: [..] > > > the previous name was already null terminated, > > > > Yeah, but if the old name is shorter than the new one, set_task_comm() > > overwrites the terminating null of the old name before writing the new > > terminating null, so there is a short time window during which tsk->comm > > might be not null-terminated, no? > > Not really: > case PR_SET_NAME: > comm[sizeof(me->comm) - 1] = 0; > if (strncpy_from_user(comm, (char __user *)arg2, > sizeof(me->comm) - 1) < 0) > return -EFAULT; > > So it first writes the terminating 0 and only then starts copying. right. hm, shouldn't set_task_comm()->__set_task_comm() do the same? -ss -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com> |
|---|---|
| Date | 2015-09-23 12:00 +0200 |
| Message-ID | <qbP0e-yp-11@gated-at.bofh.it> |
| In reply to | #1231292 |
On (09/23/15 18:50), Sergey Senozhatsky wrote:
> On (09/23/15 11:43), Michal Hocko wrote:
> [..]
> > > > the previous name was already null terminated,
> > >
> > > Yeah, but if the old name is shorter than the new one, set_task_comm()
> > > overwrites the terminating null of the old name before writing the new
> > > terminating null, so there is a short time window during which tsk->comm
> > > might be not null-terminated, no?
> >
> > Not really:
> > case PR_SET_NAME:
> > comm[sizeof(me->comm) - 1] = 0;
> > if (strncpy_from_user(comm, (char __user *)arg2,
> > sizeof(me->comm) - 1) < 0)
> > return -EFAULT;
> >
> > So it first writes the terminating 0 and only then starts copying.
>
> right.
... no right. that should have been
me->comm[sizeof(me->comm) - 1] = 0;
to be save. no?
> hm, shouldn't set_task_comm()->__set_task_comm() do the same?
or something like this instead
---
fs/exec.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/exec.c b/fs/exec.c
index b06623a..d7d2de0 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1072,6 +1072,7 @@ EXPORT_SYMBOL_GPL(get_task_comm);
void __set_task_comm(struct task_struct *tsk, const char *buf, bool exec)
{
+ tsk->comm[sizeof(tsk->comm) - 1] = 0;
task_lock(tsk);
trace_task_rename(tsk, buf);
strlcpy(tsk->comm, buf, sizeof(tsk->comm));
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Vladimir Davydov <vdavydov@parallels.com> |
|---|---|
| Date | 2015-09-23 12:10 +0200 |
| Message-ID | <qbP9T-Z0-17@gated-at.bofh.it> |
| In reply to | #1231292 |
On Wed, Sep 23, 2015 at 06:50:22PM +0900, Sergey Senozhatsky wrote: > On (09/23/15 11:43), Michal Hocko wrote: > [..] > > > > the previous name was already null terminated, > > > > > > Yeah, but if the old name is shorter than the new one, set_task_comm() > > > overwrites the terminating null of the old name before writing the new > > > terminating null, so there is a short time window during which tsk->comm > > > might be not null-terminated, no? > > > > Not really: > > case PR_SET_NAME: > > comm[sizeof(me->comm) - 1] = 0; > > if (strncpy_from_user(comm, (char __user *)arg2, > > sizeof(me->comm) - 1) < 0) > > return -EFAULT; > > > > So it first writes the terminating 0 and only then starts copying. It writes 0 to a temporary buffer, not to tsk->comm, so I don't think it's related. However, reading tsk->comm w/o locking must be safe anyway, because tsk->comm[TASK_COMM_LEN-1] is always 0 (inherited from init_task) and it never gets overwritten, because __set_task_comm() uses strlcpy(). > > right. > > hm, shouldn't set_task_comm()->__set_task_comm() do the same? I don't think so - see above. Thanks, Vladimir -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2015-09-23 12:50 +0200 |
| Message-ID | <qbPMC-1HW-9@gated-at.bofh.it> |
| In reply to | #1231304 |
On Wed 23-09-15 13:07:40, Vladimir Davydov wrote: > On Wed, Sep 23, 2015 at 06:50:22PM +0900, Sergey Senozhatsky wrote: > > On (09/23/15 11:43), Michal Hocko wrote: > > [..] > > > > > the previous name was already null terminated, > > > > > > > > Yeah, but if the old name is shorter than the new one, set_task_comm() > > > > overwrites the terminating null of the old name before writing the new > > > > terminating null, so there is a short time window during which tsk->comm > > > > might be not null-terminated, no? > > > > > > Not really: > > > case PR_SET_NAME: > > > comm[sizeof(me->comm) - 1] = 0; > > > if (strncpy_from_user(comm, (char __user *)arg2, > > > sizeof(me->comm) - 1) < 0) > > > return -EFAULT; > > > > > > So it first writes the terminating 0 and only then starts copying. > > It writes 0 to a temporary buffer, not to tsk->comm, so I don't think > it's related. However, reading tsk->comm w/o locking must be safe > anyway, because tsk->comm[TASK_COMM_LEN-1] is always 0 (inherited from > init_task) and it never gets overwritten, because __set_task_comm() uses > strlcpy(). Right you are! I am blind obviously... Thought we are copying directly to the task->comm. -- Michal Hocko SUSE Labs -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2015-09-23 11:50 +0200 |
| Message-ID | <qbOQy-mP-15@gated-at.bofh.it> |
| In reply to | #1231289 |
On Wed 23-09-15 12:30:22, Vladimir Davydov wrote:
> On Wed, Sep 23, 2015 at 06:13:54PM +0900, Sergey Senozhatsky wrote:
> > On (09/23/15 11:06), Vladimir Davydov wrote:
> > > Hi,
> > >
> > > On Tue, Sep 22, 2015 at 04:30:13PM -0700, David Rientjes wrote:
> > > > The oom killer takes task_lock() in a couple of places solely to protect
> > > > printing the task's comm.
> > > >
> > > > A process's comm, including current's comm, may change due to
> > > > /proc/pid/comm or PR_SET_NAME.
> > > >
> > > > The comm will always be NULL-terminated, so the worst race scenario would
> > > > only be during update. We can tolerate a comm being printed that is in
> > > > the middle of an update to avoid taking the lock.
> > > >
> > > > Other locations in the kernel have already dropped task_lock() when
> > > > printing comm, so this is consistent.
> > >
> > > Without the protection, can't reading task->comm race with PR_SET_NAME
> > > as described below?
> >
> > the previous name was already null terminated,
>
> Yeah, but if the old name is shorter than the new one, set_task_comm()
> overwrites the terminating null of the old name before writing the new
> terminating null, so there is a short time window during which tsk->comm
> might be not null-terminated, no?
Not really:
case PR_SET_NAME:
comm[sizeof(me->comm) - 1] = 0;
if (strncpy_from_user(comm, (char __user *)arg2,
sizeof(me->comm) - 1) < 0)
return -EFAULT;
So it first writes the terminating 0 and only then starts copying.
--
Michal Hocko
SUSE Labs
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Johannes Weiner <hannes@cmpxchg.org> |
|---|---|
| Date | 2015-09-24 21:50 +0200 |
| Message-ID | <qckGK-4iF-27@gated-at.bofh.it> |
| In reply to | #1231040 |
On Tue, Sep 22, 2015 at 04:30:13PM -0700, David Rientjes wrote: > The oom killer takes task_lock() in a couple of places solely to protect > printing the task's comm. > > A process's comm, including current's comm, may change due to > /proc/pid/comm or PR_SET_NAME. > > The comm will always be NULL-terminated, so the worst race scenario would > only be during update. We can tolerate a comm being printed that is in > the middle of an update to avoid taking the lock. > > Other locations in the kernel have already dropped task_lock() when > printing comm, so this is consistent. > > Suggested-by: Oleg Nesterov <oleg@redhat.com> > Signed-off-by: David Rientjes <rientjes@google.com> Acked-by: Johannes Weiner <hannes@cmpxchg.org> -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web