Skip to contentSkip to conversation

A few patches in a sake of c/r functionality

PATCH In review Cyrill Gorcunov 8 participants 60 messages Jan 23, 2012 – Jan 25, 2012

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover A few patches in a sake of c/r functionality

Hi,

here are a few patches in a sake of c/r. Nothing really serious except a new kcmp syscall I think. Please review, comments are really appreciated!

Cyrill

#1 lore raw

PATCH 1/4 fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v8

When we do checkpoint of a task we need to know the list of children the task, has but there is no easy and fast way to generate reverse parent->children chain from arbitrary <pid> (while a parent pid is provided in "PPid" field of /proc/<pid>/status).

So instead of walking over all pids in the system (creating one big process tree in memory, just to figure out which children a task has) -- we add explicit /proc/<pid>/task/<tid>/children entry, because the kernel already has this kind of information but it is not yet exported.

This is a first level children, not the whole process tree.

v2:
- Kame suggested to use a separated /proc/<pid>/children entry instead of poking /proc/<pid>/status
- Andew suggested to use rcu facility instead of locking tasklist_lock
- Tejun pointed that non-seekable seq file might not be enough for tasks with large number of children

v3:
- To be on a safe side use %lu format for pid_t printing

v4:
- New line get printed when sequence ends not at seq->stop, a nit pointed by Tejun
- Documentation update
- tasklist_lock is back, Oleg pointed that ->children list is actually not rcu-safe

v5:
- Oleg suggested to make /proc/<pid>/task/<tid>/children instead of global /proc/<pid>/children, which eliminates hardness related to threads and children migration, and allows patch to be a way simplier.

v6:
- Drop ptrace_may_access tests, pids are can be found anyway so nothing to protect here.
- Update comments and docs, pointed by Oleg.

v7:
- Use get_pid over proc-pid directly, to simplify code, pointed by Oleg.

v8:
- Obtain a starting pid from the proc's inode directly.

Cc Andrew Morton <[email protected]>
Cc Pavel Emelyanov <[email protected]>
Cc Serge Hallyn <[email protected]>
Cc KAMEZAWA Hiroyuki <[email protected]>
---
 Documentation/filesystems/proc.txt |   18 +++++
 fs/proc/array.c                    |  123 +++++++++++++++++++++++++++++++++++++
 fs/proc/base.c                     |    1 
 fs/proc/internal.h                 |    1 
 4 files changed, 143 insertions(+)
Documentation/filesystems/proc.txt +18 -0
Index: linux-2.6.git/Documentation/filesystems/proc.txt
===================================================================
@@ -40,6 +40,7 @@ Table of Contents
   3.4	/proc/<pid>/coredump_filter - Core dump filtering settings
   3.5	/proc/<pid>/mountinfo - Information about mounts
   3.6	/proc/<pid>/comm  & /proc/<pid>/task/<tid>/comm
+  3.7   /proc/<pid>/task/<tid>/children - Information about task children
 
   4	Configuring procfs
   4.1	Mount options
@@ -1549,6 +1550,23 @@ then the kernel's TASK_COMM_LEN (current
 comm value.
 
 
+3.7	/proc/<pid>/task/<tid>/children - Information about task children
+-------------------------------------------------------------------------
+This file provides a fast way to retrieve first level children pids
+of a task pointed by <pid>/<tid> pair. The format is a space separated
+stream of pids.
+
+Note the "first level" here -- if a child has own children they will
+not be listed here, one needs to read /proc/<children-pid>/task/<tid>/children
+to obtain the descendants.
+
+Since this interface is intended to be fast and cheap it doesn't
+guarantee to provide precise results and some children might be
+skipped, especially if they've exited right after we printed their
+pids, so one need to either stop or freeze processes being inspected
+if precise results are needed.
+
+
 ------------------------------------------------------------------------------
 Configuring procfs
 ------------------------------------------------------------------------------
fs/proc/array.c +123 -0

126 lines not on this page · raw message

fs/proc/base.c +1 -0
Index: linux-2.6.git/fs/proc/base.c
===================================================================
@@ -3384,6 +3384,7 @@ static const struct pid_entry tid_base_s
 	ONE("stat",      S_IRUGO, proc_tid_stat),
 	ONE("statm",     S_IRUGO, proc_pid_statm),
 	REG("maps",      S_IRUGO, proc_maps_operations),
+	REG("children",  S_IRUGO, proc_tid_children_operations),
 #ifdef CONFIG_NUMA
 	REG("numa_maps", S_IRUGO, proc_numa_maps_operations),
 #endif
fs/proc/internal.h +1 -0
Index: linux-2.6.git/fs/proc/internal.h
===================================================================
@@ -53,6 +53,7 @@ extern int proc_pid_statm(struct seq_fil
 				struct pid *pid, struct task_struct *task);
 extern loff_t mem_lseek(struct file *file, loff_t offset, int orig);
 
+extern const struct file_operations proc_tid_children_operations;
 extern const struct file_operations proc_maps_operations;
 extern const struct file_operations proc_numa_maps_operations;
 extern const struct file_operations proc_smaps_operations;
Reviewed-by on v1 1/4
#2 lore raw

Re: [patch 1/4] fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v8

Quoted 11 lines · Cyrill Gorcunov

When we do checkpoint of a task we need to know the list of children the task, has but there is no easy and fast way to generate reverse parent->children chain from arbitrary <pid> (while a parent pid is provided in "PPid" field of /proc/<pid>/status).

[...]
Cc Andrew Morton <[email protected]>
Cc Pavel Emelyanov <[email protected]>
Cc Serge Hallyn <[email protected]>
Cc KAMEZAWA Hiroyuki <[email protected]>

fs/proc/array.c int proc_pid_statm(struct seq_file *m, s · line 614

Quoted 8 lines
fs/proc/array.c +8 -0
+static int children_seq_show(struct seq_file *seq, void *v)
+{
+       struct inode *inode = seq->private;
+       pid_t pid;
+
+       pid = pid_nr_ns(v, inode->i_sb->s_fs_info);
+       return seq_printf(seq, " %d", pid);
+}

Does this mean the file contents always starts with a space? I think I'd prefer a trailing space than a leading one. Better yet, neither. :)

-Kees

Signature · 2 lines
Kees Cook
ChromeOS Security
#3 lore raw

Re: [patch 1/4] fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v8

Quoted 15 lines · Kees Cook
Quoted 11 lines · Cyrill Gorcunov

When we do checkpoint of a task we need to know the list of children the task, has but there is no easy and fast way to generate reverse parent->children chain from arbitrary <pid> (while a parent pid is provided in "PPid" field of /proc/<pid>/status).

[...]
Cc Andrew Morton <[email protected]>
Cc Pavel Emelyanov <[email protected]>
Cc Serge Hallyn <[email protected]>
Cc KAMEZAWA Hiroyuki <[email protected]>
Quoted 13 lines

fs/proc/array.c int proc_pid_statm(struct seq_file *m, s · line 614

Quoted 8 lines
fs/proc/array.c +8 -0
+static int children_seq_show(struct seq_file *seq, void *v)
+{
+       struct inode *inode = seq->private;
+       pid_t pid;
+
+       pid = pid_nr_ns(v, inode->i_sb->s_fs_info);
+       return seq_printf(seq, " %d", pid);
+}

Does this mean the file contents always starts with a space? I think I'd prefer a trailing space than a leading one. Better yet, neither. :)

Yeah, it there children, they will be in say " 1 2 3 4\n" format. To drop this space completely i'll have to add more code, which I actually trying to escape. Can we live with it? ;)

Cyrill

#4 lore raw

Re: [patch 1/4] fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v8

Quoted 30 lines · Cyrill Gorcunov
Quoted 15 lines · Kees Cook
Quoted 11 lines · Cyrill Gorcunov

When we do checkpoint of a task we need to know the list of children the task, has but there is no easy and fast way to generate reverse parent->children chain from arbitrary <pid> (while a parent pid is provided in "PPid" field of /proc/<pid>/status).

[...]
Cc Andrew Morton <[email protected]>
Cc Pavel Emelyanov <[email protected]>
Cc Serge Hallyn <[email protected]>
Cc KAMEZAWA Hiroyuki <[email protected]>
Quoted 13 lines

fs/proc/array.c int proc_pid_statm(struct seq_file *m, s · line 614

Quoted 8 lines
fs/proc/array.c +8 -0
+static int children_seq_show(struct seq_file *seq, void *v)
+{
+       struct inode *inode = seq->private;
+       pid_t pid;
+
+       pid = pid_nr_ns(v, inode->i_sb->s_fs_info);
+       return seq_printf(seq, " %d", pid);
+}

Does this mean the file contents always starts with a space? I think I'd prefer a trailing space than a leading one. Better yet, neither. :)

Quoted 3 lines

Yeah, it there children, they will be in say " 1 2 3 4\n" format. To drop this space completely i'll have to add more code, which I actually trying to escape. Can we live with it? ;)

How about just:

return seq_printf(seq, "%d ", pid);

instead?

-Kees

Signature · 2 lines
Kees Cook
ChromeOS Security
#5 lore raw

Re: [patch 1/4] fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v8

Quoted 11 lines · Kees Cook
Quoted 4 lines

Yeah, it there children, they will be in say " 1 2 3 4\n" format. To drop this space completely i'll have to add more code, which I actually trying to escape. Can we live with it? ;)

How about just:

return seq_printf(seq, "%d ", pid);

instead?

ok, will update.

Cyrill

#6 lore raw

Re: [patch 1/4] fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v8

In reply to Cyrill Gorcunov
Quoted 60 lines · On Mon, 23 Jan 2012 18:20:37 +0400 Cyrill Gorcunov <[email protected]> wrote:

When we do checkpoint of a task we need to know the list of children the task, has but there is no easy and fast way to generate reverse parent->children chain from arbitrary <pid> (while a parent pid is provided in "PPid" field of /proc/<pid>/status).

So instead of walking over all pids in the system (creating one big process tree in memory, just to figure out which children a task has) -- we add explicit /proc/<pid>/task/<tid>/children entry, because the kernel already has this kind of information but it is not yet exported.

This is a first level children, not the whole process tree.

v2:
- Kame suggested to use a separated /proc/<pid>/children entry instead of poking /proc/<pid>/status
- Andew suggested to use rcu facility instead of locking tasklist_lock
- Tejun pointed that non-seekable seq file might not be enough for tasks with large number of children

v3:
- To be on a safe side use %lu format for pid_t printing

v4:
- New line get printed when sequence ends not at seq->stop, a nit pointed by Tejun
- Documentation update
- tasklist_lock is back, Oleg pointed that ->children list is actually not rcu-safe

v5:
- Oleg suggested to make /proc/<pid>/task/<tid>/children instead of global /proc/<pid>/children, which eliminates hardness related to threads and children migration, and allows patch to be a way simplier.

v6:
- Drop ptrace_may_access tests, pids are can be found anyway so nothing to protect here.
- Update comments and docs, pointed by Oleg.

v7:
- Use get_pid over proc-pid directly, to simplify code, pointed by Oleg.

v8:
- Obtain a starting pid from the proc's inode directly.

Cc Andrew Morton <[email protected]>
Cc Pavel Emelyanov <[email protected]>
Cc Serge Hallyn <[email protected]>
Cc KAMEZAWA Hiroyuki <[email protected]>

From viewpoint I played with seq_file, yesterday.

fs/proc/array.c +3 -0
+static void *children_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	return get_children_pid(seq->private, NULL, *pos);

fs/proc/array.c int proc_pid_statm(struct seq_file *m, s · line 628

Quoted 10 lines
fs/proc/array.c +10 -0
+}
+
+static void *children_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct pid *pid = NULL;
+
+	pid = get_children_pid(seq->private, v, *pos + 1);
+	if (!pid)
+		seq_printf(seq, "\n");
+	put_pid(v);

Because seq_printf() may fail. This seems dangeorus.

If seq_printf() fails and returns NULL, "\n" will not be printed out and user land parser will go wrong.

I think all seq_printf() should be handled in ->show(). (And you can use seq_putc() for "\n".)

Thanks,
-Kame

#7 lore raw

Re: [patch 1/4] fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v8

On Tue, Jan 24, 2012 at 11:07:30AM +0900, KAMEZAWA Hiroyuki wrote:
...

Quoted 19 lines

From viewpoint I played with seq_file, yesterday.

fs/proc/array.c int proc_pid_statm(struct seq_file *m, s · line 628

Quoted 13 lines
fs/proc/array.c +13 -0
+static void *children_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	return get_children_pid(seq->private, NULL, *pos);
+}
+
+static void *children_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct pid *pid = NULL;
+
+	pid = get_children_pid(seq->private, v, *pos + 1);
+	if (!pid)
+		seq_printf(seq, "\n");
+	put_pid(v);

Because seq_printf() may fail. This seems dangeorus.

Quoted 3 lines

If seq_printf() fails and returns NULL, "\n" will not be printed out and user land parser will go wrong.

Hmm. But userspace app will get eof, so frankly I don't see a problem here. Or maybe I miss something?

Quoted 3 lines

I think all seq_printf() should be handled in ->show(). (And you can use seq_putc() for "\n".)

Sure, i'll change it to seq_putc.

Cyrill

#8 lore raw

Re: [patch 1/4] fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v8

Quoted 21 lines · On Tue, 24 Jan 2012 10:53:38 +0400 Cyrill Gorcunov <[email protected]> wrote:

On Tue, Jan 24, 2012 at 11:07:30AM +0900, KAMEZAWA Hiroyuki wrote:
...

Quoted 19 lines

From viewpoint I played with seq_file, yesterday.

fs/proc/array.c int proc_pid_statm(struct seq_file *m, s · line 628

Quoted 13 lines
fs/proc/array.c +13 -0
+static void *children_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	return get_children_pid(seq->private, NULL, *pos);
+}
+
+static void *children_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct pid *pid = NULL;
+
+	pid = get_children_pid(seq->private, v, *pos + 1);
+	if (!pid)
+		seq_printf(seq, "\n");
+	put_pid(v);

Because seq_printf() may fail. This seems dangeorus.

Quoted 7 lines
Quoted 3 lines

If seq_printf() fails and returns NULL, "\n" will not be printed out and user land parser will go wrong.

Hmm. But userspace app will get eof, so frankly I don't see a problem here. Or maybe I miss something?

Userspace need to take care of whether there may be"\n" or not even if read() returns EOF.
As an interface, it's BUG to say "\n" will be there if you're lucky!" (*) I know script language can handle this but we shouldn't assume that.

How about just remove "\n" at EOF ? I think it's unnecessary.

Thanks,
-Kame

#9 lore raw

Re: [patch 1/4] fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v8

Quoted 5 lines · KAMEZAWA Hiroyuki
Quoted 4 lines

Hmm. But userspace app will get eof, so frankly I don't see a problem here. Or maybe I miss something?

Quoted 7 lines

Userspace need to take care of whether there may be"\n" or not even if read() returns EOF.
As an interface, it's BUG to say "\n" will be there if you're lucky!" (*) I know script language can handle this but we shouldn't assume that.

How about just remove "\n" at EOF ? I think it's unnecessary.

Sure thing, it's not a problem to remove it completely.

Cyrill

#10 lore raw

Re: [patch 1/4] fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v8

Quoted 11 lines · Cyrill Gorcunov
Quoted 10 lines · KAMEZAWA Hiroyuki
Quoted 4 lines

Hmm. But userspace app will get eof, so frankly I don't see a problem here. Or maybe I miss something?

Userspace need to take care of whether there may be"\n" or not even if read() returns EOF.
As an interface, it's BUG to say "\n" will be there if you're lucky!" (*) I know script language can handle this but we shouldn't assume that.

Quoted 4 lines
Quoted 2 lines

How about just remove "\n" at EOF ? I think it's unnecessary.

Sure thing, it's not a problem to remove it completely.

Foolish question. Is there any reason why this is a file instead of being the obvious directory full of symlinks?

Eric

#11 lore raw

Re: [patch 1/4] fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v8

Quoted 13 lines · Eric W. Biederman
Quoted 11 lines · Cyrill Gorcunov
Quoted 10 lines · KAMEZAWA Hiroyuki
Quoted 4 lines

Hmm. But userspace app will get eof, so frankly I don't see a problem here. Or maybe I miss something?

Userspace need to take care of whether there may be"\n" or not even if read() returns EOF.
As an interface, it's BUG to say "\n" will be there if you're lucky!" (*) I know script language can handle this but we shouldn't assume that.

Quoted 8 lines
Quoted 4 lines
Quoted 2 lines

How about just remove "\n" at EOF ? I think it's unnecessary.

Sure thing, it's not a problem to remove it completely.

Foolish question. Is there any reason why this is a file instead of being the obvious directory full of symlinks?

How would these symlinks look like? "../../pid"? There were a conversation about such things (https://lkml.org/lkml/2011/12/2/142) but I suppose we were agree on children with pids as consensus.

Cyrill

#12 lore raw

Re: [patch 1/4] fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v8

Quoted 19 lines · Cyrill Gorcunov
Quoted 18 lines · Eric W. Biederman
Quoted 15 lines · Cyrill Gorcunov
Quoted 5 lines · KAMEZAWA Hiroyuki
Quoted 4 lines

Hmm. But userspace app will get eof, so frankly I don't see a problem here. Or maybe I miss something?

Quoted 7 lines

Userspace need to take care of whether there may be"\n" or not even if read() returns EOF.
As an interface, it's BUG to say "\n" will be there if you're lucky!" (*) I know script language can handle this but we shouldn't assume that.

How about just remove "\n" at EOF ? I think it's unnecessary.

Sure thing, it's not a problem to remove it completely.

Quoted 7 lines
Quoted 3 lines

Foolish question. Is there any reason why this is a file instead of being the obvious directory full of symlinks?

How would these symlinks look like? "../../pid"? There were a conversation about such things (https://lkml.org/lkml/2011/12/2/142) but I suppose we were agree on children with pids as consensus.

I couldn't find any agreement in this link. Suppose wrong url?

#13 lore raw

Re: [patch 1/4] fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v8

Quoted 24 lines · KOSAKI Motohiro
Quoted 23 lines · Cyrill Gorcunov
Quoted 21 lines · Eric W. Biederman
Quoted 11 lines · Cyrill Gorcunov
Quoted 10 lines · KAMEZAWA Hiroyuki
Quoted 4 lines

Hmm. But userspace app will get eof, so frankly I don't see a problem here. Or maybe I miss something?

Userspace need to take care of whether there may be"\n" or not even if read() returns EOF.
As an interface, it's BUG to say "\n" will be there if you're lucky!" (*) I know script language can handle this but we shouldn't assume that.

Quoted 4 lines
Quoted 2 lines

How about just remove "\n" at EOF ? I think it's unnecessary.

Sure thing, it's not a problem to remove it completely.

Foolish question. Is there any reason why this is a file instead of being the obvious directory full of symlinks?

Quoted 5 lines
Quoted 3 lines

How would these symlinks look like? "../../pid"? There were a conversation about such things (https://lkml.org/lkml/2011/12/2/142) but I suppose we were agree on children with pids as consensus.

I couldn't find any agreement in this link. Suppose wrong url?

Now that you have reminded me of this thread. I can say that the link would need to look like ../../pid. Our children will always be thread group leaders, so we can safely point to the /proc/<pid> directories. So readlink would return ../../<pid> or however many dots are needed. Follow link could just warp us to that directory as it does for the other magic proc symlinks.

My feeling is that a children subdirectory would be a lot more useful than a simple file that lists the children.

Eric

#14 lore raw

Re: [patch 1/4] fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v8

Quoted 15 lines · Eric W. Biederman
Quoted 6 lines · KOSAKI Motohiro
Quoted 4 lines

How would these symlinks look like? "../../pid"? There were a conversation about such things (https://lkml.org/lkml/2011/12/2/142) but I suppose we were agree on children with pids as consensus.

I couldn't find any agreement in this link. Suppose wrong url?

Now that you have reminded me of this thread. I can say that the link would need to look like ../../pid. Our children will always be thread group leaders, so we can safely point to the /proc/<pid> directories. So readlink would return ../../<pid> or however many dots are needed. Follow link could just warp us to that directory as it does for the other magic proc symlinks.

Quoted 3 lines

My feeling is that a children subdirectory would be a lot more useful than a simple file that lists the children.

I'll check what I can do, thanks.

Cyrill

#15 lore raw

Re: [patch 1/4] fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v8

Quoted 8 lines · Cyrill Gorcunov
Quoted 8 lines

Now that you have reminded me of this thread. I can say that the link would need to look like ../../pid. Our children will always be thread group leaders, so we can safely point to the /proc/<pid> directories. So readlink would return ../../<pid> or however many dots are needed. Follow link could just warp us to that directory as it does for the other magic proc symlinks.

Quoted 6 lines
Quoted 3 lines

My feeling is that a children subdirectory would be a lot more useful than a simple file that lists the children.

I'll check what I can do, thanks.

Sigh. This will require complete code rewrite. And since I've just made it to live under CONFIG_CHECKPOINT_RESTORE I would prefer if we stick with children file. So if there are no strong objections agains 'children' as a file, could we leave it as is, ie in stream-of-pids form?

Cyrill

Reviewed-by Oleg Nesterov Reviewed-by Kees Cook
#16 lore raw

Re: [patch 1/4] fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v8

In reply to KAMEZAWA Hiroyuki
Quoted 32 lines · KAMEZAWA Hiroyuki
Quoted 21 lines · On Tue, 24 Jan 2012 10:53:38 +0400 Cyrill Gorcunov <[email protected]> wrote:

On Tue, Jan 24, 2012 at 11:07:30AM +0900, KAMEZAWA Hiroyuki wrote:
...

Quoted 19 lines

From viewpoint I played with seq_file, yesterday.

Review

Quoted 13 lines
(quoted diff) +13 -0
+static void *children_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	return get_children_pid(seq->private, NULL, *pos);
+}
+
+static void *children_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct pid *pid = NULL;
+
+	pid = get_children_pid(seq->private, v, *pos + 1);
+	if (!pid)
+		seq_printf(seq, "\n");
+	put_pid(v);

Because seq_printf() may fail. This seems dangeorus.

Quoted 7 lines
Quoted 3 lines

If seq_printf() fails and returns NULL, "\n" will not be printed out and user land parser will go wrong.

Hmm. But userspace app will get eof, so frankly I don't see a problem here. Or maybe I miss something?

Quoted 7 lines

Userspace need to take care of whether there may be"\n" or not even if read() returns EOF.
As an interface, it's BUG to say "\n" will be there if you're lucky!" (*) I know script language can handle this but we shouldn't assume that.

How about just remove "\n" at EOF ? I think it's unnecessary.

This one should fit both "%d " and no "\n" requirements.

Cyrill
---
From: Cyrill Gorcunov <[email protected]>
Subject: fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v9

When we do checkpoint of a task we need to know the list of children the task, has but there is no easy and fast way to generate reverse parent->children chain from arbitrary <pid> (while a parent pid is provided in "PPid" field of /proc/<pid>/status).

So instead of walking over all pids in the system (creating one big process tree in memory, just to figure out which children a task has) -- we add explicit /proc/<pid>/task/<tid>/children entry, because the kernel already has this kind of information but it is not yet exported.

This is a first level children, not the whole process tree.

Cc Andrew Morton <[email protected]>
Cc Pavel Emelyanov <[email protected]>
Cc Serge Hallyn <[email protected]>
Cc KAMEZAWA Hiroyuki <[email protected]>
---
 Documentation/filesystems/proc.txt |   18 +++++
 fs/proc/array.c                    |  121 +++++++++++++++++++++++++++++++++++++
 fs/proc/base.c                     |    1 
 fs/proc/internal.h                 |    1 
 4 files changed, 141 insertions(+)
Documentation/filesystems/proc.txt +18 -0
Index: linux-2.6.git/Documentation/filesystems/proc.txt
===================================================================
@@ -40,6 +40,7 @@ Table of Contents
   3.4	/proc/<pid>/coredump_filter - Core dump filtering settings
   3.5	/proc/<pid>/mountinfo - Information about mounts
   3.6	/proc/<pid>/comm  & /proc/<pid>/task/<tid>/comm
+  3.7   /proc/<pid>/task/<tid>/children - Information about task children
 
   4	Configuring procfs
   4.1	Mount options
@@ -1549,6 +1550,23 @@ then the kernel's TASK_COMM_LEN (current
 comm value.
 
 
+3.7	/proc/<pid>/task/<tid>/children - Information about task children
+-------------------------------------------------------------------------
+This file provides a fast way to retrieve first level children pids
+of a task pointed by <pid>/<tid> pair. The format is a space separated
+stream of pids.
+
+Note the "first level" here -- if a child has own children they will
+not be listed here, one needs to read /proc/<children-pid>/task/<tid>/children
+to obtain the descendants.
+
+Since this interface is intended to be fast and cheap it doesn't
+guarantee to provide precise results and some children might be
+skipped, especially if they've exited right after we printed their
+pids, so one need to either stop or freeze processes being inspected
+if precise results are needed.
+
+
 ------------------------------------------------------------------------------
 Configuring procfs
 ------------------------------------------------------------------------------
fs/proc/array.c +121 -0

124 lines not on this page · raw message

fs/proc/base.c +1 -0
Index: linux-2.6.git/fs/proc/base.c
===================================================================
@@ -3384,6 +3384,7 @@ static const struct pid_entry tid_base_s
 	ONE("stat",      S_IRUGO, proc_tid_stat),
 	ONE("statm",     S_IRUGO, proc_pid_statm),
 	REG("maps",      S_IRUGO, proc_maps_operations),
+	REG("children",  S_IRUGO, proc_tid_children_operations),
 #ifdef CONFIG_NUMA
 	REG("numa_maps", S_IRUGO, proc_numa_maps_operations),
 #endif
fs/proc/internal.h +1 -0
Index: linux-2.6.git/fs/proc/internal.h
===================================================================
@@ -53,6 +53,7 @@ extern int proc_pid_statm(struct seq_fil
 				struct pid *pid, struct task_struct *task);
 extern loff_t mem_lseek(struct file *file, loff_t offset, int orig);
 
+extern const struct file_operations proc_tid_children_operations;
 extern const struct file_operations proc_maps_operations;
 extern const struct file_operations proc_numa_maps_operations;
 extern const struct file_operations proc_smaps_operations;
maintainer
#17 lore raw

Re: [patch 1/4] fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v8

In reply to Cyrill Gorcunov
Quoted 11 lines · On Mon, 23 Jan 2012 18:20:37 +0400 Cyrill Gorcunov <[email protected]> wrote:

When we do checkpoint of a task we need to know the list of children the task, has but there is no easy and fast way to generate reverse parent->children chain from arbitrary <pid> (while a parent pid is provided in "PPid" field of /proc/<pid>/status).

So instead of walking over all pids in the system (creating one big process tree in memory, just to figure out which children a task has) -- we add explicit /proc/<pid>/task/<tid>/children entry, because the kernel already has this kind of information but it is not yet exported.

This is a first level children, not the whole process tree.

Is there a reason for not putting this new code inside CONFIG_CHECKPOINT_RESTART? If so, please changelog that.

We could add

/* #ifdef CONFIG_CHECKPOINT_RESTART (reasoning goes here) */

so that if we should decide to pull all this code out again, a grep will flag this code for consideration.

#18 lore raw

Re: [patch 1/4] fs, proc: Introduce /proc/<pid>/task/<tid>/children entry v8

Quoted 13 lines · Andrew Morton
Quoted 10 lines · On Mon, 23 Jan 2012 18:20:37 +0400 Cyrill Gorcunov <[email protected]> wrote:

When we do checkpoint of a task we need to know the list of children the task, has but there is no easy and fast way to generate reverse parent->children chain from arbitrary <pid> (while a parent pid is provided in "PPid" field of /proc/<pid>/status).

So instead of walking over all pids in the system (creating one big process tree in memory, just to figure out which children a task has) -- we add explicit /proc/<pid>/task/<tid>/children entry, because the kernel already has this kind of information but it is not yet exported.

Quoted 5 lines
Quoted 1 line

This is a first level children, not the whole process tree.

Is there a reason for not putting this new code inside CONFIG_CHECKPOINT_RESTART? If so, please changelog that.

I don't know if someone might need it as well, so I've asked in one of previous iterations if this file is to be under CONFIG_CHECKPOINT_RESTART. So, sure, I'll wrap it this way.

Quoted 7 lines

We could add

/* #ifdef CONFIG_CHECKPOINT_RESTART (reasoning goes here) */

so that if we should decide to pull all this code out again, a grep will flag this code for consideration.

Cyrill

#19 lore raw

RFC PATCH 2/4 syscalls, x86: Add __NR_kcmp syscall v4

In reply to Cyrill Gorcunov

While doing the checkpoint-restore in the userspace one need to determine whether various kernel objects (like mm_struct-s of file_struct-s) are shared between tasks and restore this state.

The 2nd step can be solved by using appropriate CLONE_ flags and the unshare syscall, while there's currently no ways for solving the 1st one.

One of the ways for checking whether two tasks share e.g. mm_struct is to provide some mm_struct ID of a task to its proc file, but showing such info considered to be not that good for security reasons.

Thus after some debates we end up in conclusion that using that named 'comparision' syscall might be the best candidate. So here is it -- __NR_kcmp.

It takes up to 5 agruments - the pids of the two tasks (which characteristics should be compared), the comparision type and (in case of comparision of files) two file descriptors.

At moment only x86 is supported.

CC "Eric W. Biederman" <[email protected]>
CC Pavel Emelyanov <[email protected]>
CC Andrey Vagin <[email protected]>
CC KOSAKI Motohiro <[email protected]>
CC Ingo Molnar <[email protected]>
CC H. Peter Anvin <[email protected]>
CC Thomas Gleixner <[email protected]>
CC Glauber Costa <[email protected]>
CC Andi Kleen <[email protected]>
CC Tejun Heo <[email protected]>
CC Matt Helsley <[email protected]>
CC Pekka Enberg <[email protected]>
CC Eric Dumazet <[email protected]>
CC Vasiliy Kulikov <[email protected]>
CC Andrew Morton <[email protected]>
CC Alexey Dobriyan <[email protected]>
---
 arch/x86/include/asm/kcmp.h      |   17 ++++
 arch/x86/include/asm/syscalls.h  |    4 
 arch/x86/kernel/Makefile         |    1 
 arch/x86/kernel/kcmp.c           |  163 +++++++++++++++++++++++++++++++++++++++
 arch/x86/syscalls/syscall_32.tbl |    1 
 arch/x86/syscalls/syscall_64.tbl |    1 
 6 files changed, 187 insertions(+)
arch/x86/include/asm/kcmp.h new file +17 -0
Index: linux-2.6.git/arch/x86/include/asm/kcmp.h
===================================================================
@@ -0,0 +1,17 @@
+#ifndef _LINUX_KCMP_H
+#define _LINUX_KCMP_H
+
+/* Comparision type */
+enum {
+	KCMP_FILE,
+	KCMP_VM,
+	KCMP_FILES,
+	KCMP_FS,
+	KCMP_SIGHAND,
+	KCMP_IO,
+	KCMP_SYSVSEM,
+
+	KCMP_TYPES,
+};
+
+#endif /* _LINUX_KCMP_H */
arch/x86/include/asm/syscalls.h +4 -0
Index: linux-2.6.git/arch/x86/include/asm/syscalls.h
===================================================================
@@ -42,6 +42,10 @@ long sys_sigaltstack(const stack_t __use
 asmlinkage int sys_set_thread_area(struct user_desc __user *);
 asmlinkage int sys_get_thread_area(struct user_desc __user *);
 
+/* kenrel/kcmp.c */
+asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type,
+			 unsigned long idx1, unsigned long idx2);
+
 /* X86_32 only */
 #ifdef CONFIG_X86_32
 
arch/x86/kernel/Makefile +1 -0
Index: linux-2.6.git/arch/x86/kernel/Makefile
===================================================================
@@ -34,6 +34,7 @@ obj-y			+= alternative.o i8253.o pci-nom
 obj-y			+= tsc.o io_delay.o rtc.o
 obj-y			+= pci-iommu_table.o
 obj-y			+= resource.o
+obj-y			+= kcmp.o
 
 obj-y				+= trampoline.o trampoline_$(BITS).o
 obj-y				+= process.o
arch/x86/kernel/kcmp.c new file +163 -0

163 lines not on this page · raw message

arch/x86/syscalls/syscall_32.tbl +1 -0
Index: linux-2.6.git/arch/x86/syscalls/syscall_32.tbl
===================================================================
@@ -355,3 +355,4 @@
 346	i386	setns			sys_setns
 347	i386	process_vm_readv	sys_process_vm_readv		compat_sys_process_vm_readv
 348	i386	process_vm_writev	sys_process_vm_writev		compat_sys_process_vm_writev
+349	i386	kcmp			sys_kcmp
arch/x86/syscalls/syscall_64.tbl +1 -0
Index: linux-2.6.git/arch/x86/syscalls/syscall_64.tbl
===================================================================
@@ -318,3 +318,4 @@
 309	64	getcpu			sys_getcpu
 310	64	process_vm_readv	sys_process_vm_readv
 311	64	process_vm_writev	sys_process_vm_writev
+312	64	kcmp			sys_kcmp
#20 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

arch/x86/kernel/kcmp.c line 21

Quoted 8 lines · Cyrill Gorcunov
arch/x86/kernel/kcmp.c new file +8 -0
+
+static unsigned long cookies[KCMP_TYPES][2] __read_mostly;
+
+static long kptr_obfuscate(long v, int type)
+{
+	return (v + cookies[type][0]) ^ cookies[type][1];
+}
+

Arf... when I said to use xor I meant instead of the add, not instead of the multiply, so:

	return (v ^ cookies[type][0]) * cookies[type][1];

Otherwise you have absolutely no source of diffusion at all (symmetric cryptography is about combinations of diffusion -- spreading the content -- and confusion -- scrambling individual bits of content.)

+ for (i = 0; i < KCMP_TYPES; i++) {
+ for (j = 0; j < 2; j++) {
+ get_random_bytes(&cookies[i][j],
+ sizeof(cookies[i][j]));
+ cookies[i][j] |= (~(~0UL >> 1) | 1);
+ }
+ }

Only cookies[1] -- being used as a multiplicative constant -- needs the OR.

-hpa

Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.
#21 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 27 lines · H. Peter Anvin

arch/x86/kernel/kcmp.c line 21

Quoted 8 lines · Cyrill Gorcunov
arch/x86/kernel/kcmp.c new file +8 -0
+
+static unsigned long cookies[KCMP_TYPES][2] __read_mostly;
+
+static long kptr_obfuscate(long v, int type)
+{
+	return (v + cookies[type][0]) ^ cookies[type][1];
+}
+

Arf... when I said to use xor I meant instead of the add, not instead of the multiply, so:

	return (v ^ cookies[type][0]) * cookies[type][1];

Otherwise you have absolutely no source of diffusion at all (symmetric cryptography is about combinations of diffusion -- spreading the content -- and confusion -- scrambling individual bits of content.)

arch/x86/kernel/kcmp.c new file +7 -0
+	for (i = 0; i < KCMP_TYPES; i++) {
+		for (j = 0; j < 2; j++) {
+			get_random_bytes(&cookies[i][j],
+					 sizeof(cookies[i][j]));
+			cookies[i][j] |= (~(~0UL >>  1) | 1);
+		}
+	}
Quoted 1 line

Only cookies[1] -- being used as a multiplicative constant -- needs the OR.

OK. Thanks. I'll update.

Cyrill

#22 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

In reply to Cyrill Gorcunov
Quoted 60 lines · On Mon, 23 Jan 2012 18:20:38 +0400 Cyrill Gorcunov <[email protected]> wrote:

While doing the checkpoint-restore in the userspace one need to determine whether various kernel objects (like mm_struct-s of file_struct-s) are shared between tasks and restore this state.

The 2nd step can be solved by using appropriate CLONE_ flags and the unshare syscall, while there's currently no ways for solving the 1st one.

One of the ways for checking whether two tasks share e.g. mm_struct is to provide some mm_struct ID of a task to its proc file, but showing such info considered to be not that good for security reasons.

Thus after some debates we end up in conclusion that using that named 'comparision' syscall might be the best candidate. So here is it -- __NR_kcmp.

It takes up to 5 agruments - the pids of the two tasks (which characteristics should be compared), the comparision type and (in case of comparision of files) two file descriptors.

At moment only x86 is supported.

CC "Eric W. Biederman" <[email protected]>
CC Pavel Emelyanov <[email protected]>
CC Andrey Vagin <[email protected]>
CC KOSAKI Motohiro <[email protected]>
CC Ingo Molnar <[email protected]>
CC H. Peter Anvin <[email protected]>
CC Thomas Gleixner <[email protected]>
CC Glauber Costa <[email protected]>
CC Andi Kleen <[email protected]>
CC Tejun Heo <[email protected]>
CC Matt Helsley <[email protected]>
CC Pekka Enberg <[email protected]>
CC Eric Dumazet <[email protected]>
CC Vasiliy Kulikov <[email protected]>
CC Andrew Morton <[email protected]>
CC Alexey Dobriyan <[email protected]>
---
 arch/x86/include/asm/kcmp.h      |   17 ++++
 arch/x86/include/asm/syscalls.h  |    4 
 arch/x86/kernel/Makefile         |    1 
 arch/x86/kernel/kcmp.c           |  163 +++++++++++++++++++++++++++++++++++++++
 arch/x86/syscalls/syscall_32.tbl |    1 
 arch/x86/syscalls/syscall_64.tbl |    1 
 6 files changed, 187 insertions(+)

Index: linux-2.6.git/arch/x86/include/asm/kcmp.h
===================================================================

arch/x86/include/asm/kcmp.h new file +7 -0
@@ -0,0 +1,17 @@
+#ifndef _LINUX_KCMP_H
+#define _LINUX_KCMP_H
+
+/* Comparision type */
+enum {
+	KCMP_FILE,
+	KCMP_VM,

arch/x86/include/asm/kcmp.h line 17

Quoted 10 lines
arch/x86/include/asm/kcmp.h new file +10 -0
+	KCMP_FILES,
+	KCMP_FS,
+	KCMP_SIGHAND,
+	KCMP_IO,
+	KCMP_SYSVSEM,
+
+	KCMP_TYPES,
+};
+
+#endif /* _LINUX_KCMP_H */

Why under /arch ?

Quoted 43 lines

Index: linux-2.6.git/arch/x86/include/asm/syscalls.h
===================================================================

arch/x86/include/asm/syscalls.h +4 -0
@@ -42,6 +42,10 @@ long sys_sigaltstack(const stack_t __use
 asmlinkage int sys_set_thread_area(struct user_desc __user *);
 asmlinkage int sys_get_thread_area(struct user_desc __user *);
 
+/* kenrel/kcmp.c */
+asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type,
+			 unsigned long idx1, unsigned long idx2);
+
 /* X86_32 only */
 #ifdef CONFIG_X86_32
 

Index: linux-2.6.git/arch/x86/kernel/Makefile
===================================================================

arch/x86/kernel/Makefile +1 -0
@@ -34,6 +34,7 @@ obj-y			+= alternative.o i8253.o pci-nom
 obj-y			+= tsc.o io_delay.o rtc.o
 obj-y			+= pci-iommu_table.o
 obj-y			+= resource.o
+obj-y			+= kcmp.o
 
 obj-y				+= trampoline.o trampoline_$(BITS).o
 obj-y				+= process.o

Index: linux-2.6.git/arch/x86/kernel/kcmp.c
===================================================================

arch/x86/kernel/kcmp.c new file +11 -0
@@ -0,0 +1,163 @@
+#include <linux/kernel.h>
+#include <linux/syscalls.h>
+#include <linux/fdtable.h>
+#include <linux/string.h>
+#include <linux/random.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/cache.h>
+#include <linux/bug.h>
+#include <linux/err.h>
+

arch/x86/kernel/kcmp.c line 21

Quoted 10 lines
arch/x86/kernel/kcmp.c new file +10 -0
+#include <asm/unistd.h>
+#include <asm/kcmp.h>
+
+static unsigned long cookies[KCMP_TYPES][2] __read_mostly;
+
+static long kptr_obfuscate(long v, int type)
+{
+	return (v + cookies[type][0]) ^ cookies[type][1];
+}
+

I'm sorry could you add comments to swho what this does ?

Quoted 116 lines
arch/x86/kernel/kcmp.c new file +116 -0
+/*
+ * 0 - equal
+ * 1 - less than
+ * 2 - greater than
+ * 3 - not equal but ordering unavailable
+ */
+static int kcmp_ptr(long v1, long v2, int type)
+{
+	long ret;
+
+	ret = kptr_obfuscate(v1, type) - kptr_obfuscate(v2, type);
+
+	return (ret < 0) | ((ret > 0) << 1);
+}
+
+#define KCMP_TASK_PTR(task1, task2, member, type)	\
+	kcmp_ptr((long)(task1)->member,			\
+		 (long)(task2)->member,			\
+		 type)
+
+#define KCMP_PTR(ptr1, ptr2, type)			\
+	kcmp_ptr((long)ptr1, (long)ptr2, type)
+
+/* A caller must be sure the task is presented in memory */
+static struct file *
+get_file_raw_ptr(struct task_struct *task, unsigned int idx)
+{
+	struct fdtable *fdt;
+	struct file *file;
+
+	spin_lock(&task->files->file_lock);
+	fdt = files_fdtable(task->files);
+	if (idx < fdt->max_fds)
+		file = fdt->fd[idx];
+	else
+		file = NULL;
+	spin_unlock(&task->files->file_lock);
+
+	return file;
+}
+
+SYSCALL_DEFINE5(kcmp, pid_t, pid1, pid_t, pid2, int, type,
+		unsigned long, idx1, unsigned long, idx2)
+{
+	struct task_struct *task1;
+	struct task_struct *task2;
+	int ret = 0;
+
+	rcu_read_lock();
+
+	task1 = find_task_by_vpid(pid1);
+	if (!task1) {
+		rcu_read_unlock();
+		return -ESRCH;
+	}
+
+	task2 = find_task_by_vpid(pid2);
+	if (!task2) {
+		put_task_struct(task1);
+		rcu_read_unlock();
+		return -ESRCH;
+	}
+
+	get_task_struct(task1);
+	get_task_struct(task2);
+
+	rcu_read_unlock();
+
+	if (!ptrace_may_access(task1, PTRACE_MODE_READ) ||
+	    !ptrace_may_access(task2, PTRACE_MODE_READ)) {
+		ret = -EACCES;
+		goto err;
+	}
+
+	/*
+	 * Note for all cases but the KCMP_FILE we
+	 * don't take any locks in a sake of speed.
+	 */
+
+	switch (type) {
+	case KCMP_FILE: {
+		struct file *filp1, *filp2;
+
+		filp1 = get_file_raw_ptr(task1, idx1);
+		filp2 = get_file_raw_ptr(task2, idx2);
+
+		if (filp1 && filp2)
+			ret = KCMP_PTR(filp1, filp2, KCMP_FILE);
+		else
+			ret = -ENOENT;
+		break;
+	}
+	case KCMP_VM:
+		ret = KCMP_TASK_PTR(task1, task2, mm, KCMP_VM);
+		break;
+	case KCMP_FILES:
+		ret = KCMP_TASK_PTR(task1, task2, files, KCMP_FILES);
+		break;
+	case KCMP_FS:
+		ret = KCMP_TASK_PTR(task1, task2, fs, KCMP_FS);
+		break;
+	case KCMP_SIGHAND:
+		ret = KCMP_TASK_PTR(task1, task2, sighand, KCMP_SIGHAND);
+		break;
+	case KCMP_IO:
+		ret = KCMP_TASK_PTR(task1, task2, io_context, KCMP_IO);
+		break;
+	case KCMP_SYSVSEM:
+#ifdef CONFIG_SYSVIPC
+		ret = KCMP_TASK_PTR(task1, task2, sysvsem.undo_list, KCMP_SYSVSEM);
+#else
+		ret = -ENOENT;
+		goto err;
+#endif
+		break;
+	default:

arch/x86/kernel/kcmp.c line 147

Quoted 10 lines
arch/x86/kernel/kcmp.c new file +10 -0
+		ret = -EINVAL;
+		goto err;
+	}
+
+err:
+	put_task_struct(task1);
+	put_task_struct(task2);
+
+	return ret;
+}

It seems this function itself doesn't depend on arch.

Thanks,
-Kame

#23 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

On Tue, Jan 24, 2012 at 11:16:55AM +0900, KAMEZAWA Hiroyuki wrote:
...

Quoted 17 lines
Quoted 17 lines

Index: linux-2.6.git/arch/x86/include/asm/kcmp.h
===================================================================

arch/x86/include/asm/kcmp.h new file +11 -0
@@ -0,0 +1,17 @@
+#ifndef _LINUX_KCMP_H
+#define _LINUX_KCMP_H
+
+/* Comparision type */
+enum {
+	KCMP_FILE,
+	KCMP_VM,
+	KCMP_FILES,
+	KCMP_FS,
+	KCMP_SIGHAND,
+	KCMP_IO,
Quoted 9 lines

arch/x86/include/asm/kcmp.h line 17

Quoted 6 lines
arch/x86/include/asm/kcmp.h new file +6 -0
+	KCMP_SYSVSEM,
+
+	KCMP_TYPES,
+};
+
+#endif /* _LINUX_KCMP_H */

Why under /arch ?

Hi Kame,

because I've tested it under x86 only. Once someone confirm it's needed on some else arch and does work as expected -- it wont be a problem to make it system wide. Until then -- I think better to stick with at least tested case.
...

Quoted 8 lines

arch/x86/include/asm/kcmp.h

Quoted 6 lines
arch/x86/include/asm/kcmp.h new file +6 -0
+
+static long kptr_obfuscate(long v, int type)
+{
+	return (v + cookies[type][0]) ^ cookies[type][1];
+}
+

I'm sorry could you add comments to swho what this does ?

The idea is disorder the in-memory order but remain order suitable for sorting. Anywa, as Peter pointed this helper must be redone. I'll post updated version.

Quoted 3 lines

It seems this function itself doesn't depend on arch.

Yes, it doesn't. But as I said if someone confirm it's needed on non-x86 and get tested, that will not be a problem to make it system-side.

Cyrill

#24 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 4 lines · Cyrill Gorcunov
Quoted 3 lines

Why under /arch ?

Quoted 8 lines

Hi Kame,

because I've tested it under x86 only. Once someone confirm it's needed on some else arch and does work as expected -- it wont be a problem to make it system wide. Until then -- I think better to stick with at least tested case.
...

That's not a reason to put it in arch/ ... that's possibly a reason to not map the system call on other architectures yet.

-hpa

#25 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 14 lines · H. Peter Anvin
Quoted 4 lines · Cyrill Gorcunov
Quoted 3 lines

Why under /arch ?

Quoted 8 lines

Hi Kame,

because I've tested it under x86 only. Once someone confirm it's needed on some else arch and does work as expected -- it wont be a problem to make it system wide. Until then -- I think better to stick with at least tested case.
...

Quoted 3 lines

That's not a reason to put it in arch/ ... that's possibly a reason to not map the system call on other architectures yet.

Where it should live then? In kernel/ or mm/ ?

Cyrill

#26 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 15 lines · On Tue, 24 Jan 2012 11:17:16 +0400 Cyrill Gorcunov <[email protected]> wrote:
Quoted 14 lines · H. Peter Anvin
Quoted 12 lines · Cyrill Gorcunov
Quoted 3 lines

Why under /arch ?

Hi Kame,

because I've tested it under x86 only. Once someone confirm it's needed on some else arch and does work as expected -- it wont be a problem to make it system wide. Until then -- I think better to stick with at least tested case.
...

Quoted 6 lines
Quoted 3 lines

That's not a reason to put it in arch/ ... that's possibly a reason to not map the system call on other architectures yet.

Where it should live then? In kernel/ or mm/ ?

kernel/checkpoint_restart ?

gathering related changes to a directory may help developpers joins later.... To me, this makes seeing git log easy ;)

Thanks,
-Kame

#27 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

On Tue, Jan 24, 2012 at 04:20:31PM +0900, KAMEZAWA Hiroyuki wrote:
...

Quoted 5 lines
Quoted 5 lines
Quoted 4 lines

That's not a reason to put it in arch/ ... that's possibly a reason to not map the system call on other architectures yet.

Quoted 8 lines
Quoted 2 lines

Where it should live then? In kernel/ or mm/ ?

kernel/checkpoint_restart ?

gathering related changes to a directory may help developpers joins later.... To me, this makes seeing git log easy ;)

Such separate directory implies everything related to c/r should live there, it also implies (I think) that code which is under CHECKPOINT_RESTORE should be moved there as well, so I'm not sure, Kame ;) I guess mm/ will be a good place since these are operations with memory pointers.

Cyrill

#28 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 12 lines · On Tue, 24 Jan 2012 11:38:42 +0400 Cyrill Gorcunov <[email protected]> wrote:

On Tue, Jan 24, 2012 at 04:20:31PM +0900, KAMEZAWA Hiroyuki wrote:
...

Quoted 10 lines
Quoted 7 lines
Quoted 4 lines

That's not a reason to put it in arch/ ... that's possibly a reason to not map the system call on other architectures yet.

Where it should live then? In kernel/ or mm/ ?

kernel/checkpoint_restart ?

Quoted 9 lines
Quoted 3 lines

gathering related changes to a directory may help developpers joins later.... To me, this makes seeing git log easy ;)

Such separate directory implies everything related to c/r should live there, it also implies (I think) that code which is under CHECKPOINT_RESTORE should be moved there as well, so I'm not sure, Kame ;) I guess mm/ will be a good place since these are operations with memory pointers.

please do as you like.
-Kame

#29 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 19 lines · KAMEZAWA Hiroyuki
Quoted 16 lines · On Tue, 24 Jan 2012 11:38:42 +0400 Cyrill Gorcunov <[email protected]> wrote:

On Tue, Jan 24, 2012 at 04:20:31PM +0900, KAMEZAWA Hiroyuki wrote:
...

Quoted 13 lines
Quoted 7 lines
Quoted 4 lines

That's not a reason to put it in arch/ ... that's possibly a reason to not map the system call on other architectures yet.

Where it should live then? In kernel/ or mm/ ?

kernel/checkpoint_restart ?

gathering related changes to a directory may help developpers joins later.... To me, this makes seeing git log easy ;)

Quoted 7 lines
Quoted 5 lines

Such separate directory implies everything related to c/r should live there, it also implies (I think) that code which is under CHECKPOINT_RESTORE should be moved there as well, so I'm not sure, Kame ;) I guess mm/ will be a good place since these are operations with memory pointers.

please do as you like.

So it should be something like below I think...

Cyrill
---
From: Cyrill Gorcunov <[email protected]>
Subject: [RFC] syscalls, x86: Add __NR_kcmp syscall v5

While doing the checkpoint-restore in the userspace one need to determine whether various kernel objects (like mm_struct-s of file_struct-s) are shared between tasks and restore this state.

The 2nd step can be solved by using appropriate CLONE_ flags and the unshare syscall, while there's currently no ways for solving the 1st one.

One of the ways for checking whether two tasks share e.g. mm_struct is to provide some mm_struct ID of a task to its proc file, but showing such info considered to be not that good for security reasons.

Thus after some debates we end up in conclusion that using that named 'comparision' syscall might be the best candidate. So here is it -- __NR_kcmp.

It takes up to 5 agruments - the pids of the two tasks (which characteristics should be compared), the comparision type and (in case of comparision of files) two file descriptors.

At moment only x86 is supported.

CC "Eric W. Biederman" <[email protected]>
CC Pavel Emelyanov <[email protected]>
CC Andrey Vagin <[email protected]>
CC KOSAKI Motohiro <[email protected]>
CC Ingo Molnar <[email protected]>
CC H. Peter Anvin <[email protected]>
CC Thomas Gleixner <[email protected]>
CC Glauber Costa <[email protected]>
CC Andi Kleen <[email protected]>
CC Tejun Heo <[email protected]>
CC Matt Helsley <[email protected]>
CC Pekka Enberg <[email protected]>
CC Eric Dumazet <[email protected]>
CC Vasiliy Kulikov <[email protected]>
CC Andrew Morton <[email protected]>
CC Alexey Dobriyan <[email protected]>
---
 arch/x86/include/asm/syscalls.h  |    4 
 arch/x86/syscalls/syscall_32.tbl |    1 
 arch/x86/syscalls/syscall_64.tbl |    1 
 include/linux/kcmp.h             |   17 ++++
 mm/Makefile                      |    1 
 mm/kcmp.c                        |  163 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 187 insertions(+)
arch/x86/include/asm/syscalls.h +4 -0
Index: linux-2.6.git/arch/x86/include/asm/syscalls.h
===================================================================
@@ -42,6 +42,10 @@ long sys_sigaltstack(const stack_t __use
 asmlinkage int sys_set_thread_area(struct user_desc __user *);
 asmlinkage int sys_get_thread_area(struct user_desc __user *);
 
+/* mm/kcmp.c */
+asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type,
+			 unsigned long idx1, unsigned long idx2);
+
 /* X86_32 only */
 #ifdef CONFIG_X86_32
 
arch/x86/syscalls/syscall_32.tbl +1 -0
Index: linux-2.6.git/arch/x86/syscalls/syscall_32.tbl
===================================================================
@@ -355,3 +355,4 @@
 346	i386	setns			sys_setns
 347	i386	process_vm_readv	sys_process_vm_readv		compat_sys_process_vm_readv
 348	i386	process_vm_writev	sys_process_vm_writev		compat_sys_process_vm_writev
+349	i386	kcmp			sys_kcmp
arch/x86/syscalls/syscall_64.tbl +1 -0
Index: linux-2.6.git/arch/x86/syscalls/syscall_64.tbl
===================================================================
@@ -318,3 +318,4 @@
 309	64	getcpu			sys_getcpu
 310	64	process_vm_readv	sys_process_vm_readv
 311	64	process_vm_writev	sys_process_vm_writev
+312	64	kcmp			sys_kcmp
include/linux/kcmp.h new file +17 -0
Index: linux-2.6.git/include/linux/kcmp.h
===================================================================
@@ -0,0 +1,17 @@
+#ifndef _LINUX_KCMP_H
+#define _LINUX_KCMP_H
+
+/* Comparision type */
+enum {
+	KCMP_FILE,
+	KCMP_VM,
+	KCMP_FILES,
+	KCMP_FS,
+	KCMP_SIGHAND,
+	KCMP_IO,
+	KCMP_SYSVSEM,
+
+	KCMP_TYPES,
+};
+
+#endif /* _LINUX_KCMP_H */
mm/Makefile +1 -0
Index: linux-2.6.git/mm/Makefile
===================================================================
@@ -51,3 +51,4 @@ obj-$(CONFIG_HWPOISON_INJECT) += hwpoiso
 obj-$(CONFIG_DEBUG_KMEMLEAK) += kmemleak.o
 obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) += kmemleak-test.o
 obj-$(CONFIG_CLEANCACHE) += cleancache.o
+obj-$(CONFIG_X86) += kcmp.o
mm/kcmp.c new file +163 -0

163 lines not on this page · raw message

#30 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 3 lines
Quoted 1 line

please do as you like.

So it should be something like below I think...

Looks ok this version to me. So, if you fix other developers pointed issue, I'll ack this.

thanks.

#31 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 7 lines · KOSAKI Motohiro
Quoted 3 lines
Quoted 1 line

please do as you like.

So it should be something like below I think...

Looks ok this version to me. So, if you fix other developers pointed issue, I'll ack this.

Thanks!

Eric, so mm/ would be fine or I still should move it to kernel/ instead? I've addressed other issues I hope.

Cyrill

#32 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 5 lines · Cyrill Gorcunov
Quoted 4 lines · KOSAKI Motohiro
Quoted 3 lines
Quoted 1 line

please do as you like.

So it should be something like below I think...

Quoted 8 lines
Quoted 3 lines

Looks ok this version to me. So, if you fix other developers pointed issue, I'll ack this.

Thanks!

Eric, so mm/ would be fine or I still should move it to kernel/ instead? I've addressed other issues I hope.

The world won't fall apart if the code lands in mm. I have a strong preference for kernel/. I just don't see anything at all memory management like about that code. Even the fact that you are comparing pointers is an implementation detail.

Eric

#33 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 13 lines · Eric W. Biederman
Quoted 11 lines · Cyrill Gorcunov
Quoted 7 lines · KOSAKI Motohiro
Quoted 3 lines
Quoted 1 line

please do as you like.

So it should be something like below I think...

Looks ok this version to me. So, if you fix other developers pointed issue, I'll ack this.

Thanks!

Quoted 7 lines
Quoted 2 lines

Eric, so mm/ would be fine or I still should move it to kernel/ instead? I've addressed other issues I hope.

The world won't fall apart if the code lands in mm. I have a strong preference for kernel/. I just don't see anything at all memory management like about that code. Even the fact that you are comparing pointers is an implementation detail.

This one should fit all requirements I guess.

Cyrill
---
From: Cyrill Gorcunov <[email protected]>
Subject: [RFC] syscalls, x86: Add __NR_kcmp syscall v6

While doing the checkpoint-restore in the userspace one need to determine whether various kernel objects (like mm_struct-s of file_struct-s) are shared between tasks and restore this state.

The 2nd step can be solved by using appropriate CLONE_ flags and the unshare syscall, while there's currently no ways for solving the 1st one.

One of the ways for checking whether two tasks share e.g. mm_struct is to provide some mm_struct ID of a task to its proc file, but showing such info considered to be not that good for security reasons.

Thus after some debates we end up in conclusion that using that named 'comparision' syscall might be the best candidate. So here is it -- __NR_kcmp.

It takes up to 5 agruments - the pids of the two tasks (which characteristics should be compared), the comparision type and (in case of comparision of files) two file descriptors.

At moment only x86 is supported.

CC "Eric W. Biederman" <[email protected]>
CC Pavel Emelyanov <[email protected]>
CC Andrey Vagin <[email protected]>
CC KOSAKI Motohiro <[email protected]>
CC Ingo Molnar <[email protected]>
CC H. Peter Anvin <[email protected]>
CC Thomas Gleixner <[email protected]>
CC Glauber Costa <[email protected]>
CC Andi Kleen <[email protected]>
CC Tejun Heo <[email protected]>
CC Matt Helsley <[email protected]>
CC Pekka Enberg <[email protected]>
CC Eric Dumazet <[email protected]>
CC Vasiliy Kulikov <[email protected]>
CC Andrew Morton <[email protected]>
CC Alexey Dobriyan <[email protected]>
---
 arch/x86/include/asm/syscalls.h  |    4 
 arch/x86/syscalls/syscall_32.tbl |    1 
 arch/x86/syscalls/syscall_64.tbl |    1 
 include/linux/kcmp.h             |   17 ++++
 kernel/Makefile                  |    1 
 kernel/kcmp.c                    |  163 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 187 insertions(+)
arch/x86/include/asm/syscalls.h +4 -0
Index: linux-2.6.git/arch/x86/include/asm/syscalls.h
===================================================================
@@ -42,6 +42,10 @@ long sys_sigaltstack(const stack_t __use
 asmlinkage int sys_set_thread_area(struct user_desc __user *);
 asmlinkage int sys_get_thread_area(struct user_desc __user *);
 
+/* kernel/kcmp.c */
+asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type,
+			 unsigned long idx1, unsigned long idx2);
+
 /* X86_32 only */
 #ifdef CONFIG_X86_32
 
arch/x86/syscalls/syscall_32.tbl +1 -0
Index: linux-2.6.git/arch/x86/syscalls/syscall_32.tbl
===================================================================
@@ -355,3 +355,4 @@
 346	i386	setns			sys_setns
 347	i386	process_vm_readv	sys_process_vm_readv		compat_sys_process_vm_readv
 348	i386	process_vm_writev	sys_process_vm_writev		compat_sys_process_vm_writev
+349	i386	kcmp			sys_kcmp
arch/x86/syscalls/syscall_64.tbl +1 -0
Index: linux-2.6.git/arch/x86/syscalls/syscall_64.tbl
===================================================================
@@ -318,3 +318,4 @@
 309	64	getcpu			sys_getcpu
 310	64	process_vm_readv	sys_process_vm_readv
 311	64	process_vm_writev	sys_process_vm_writev
+312	64	kcmp			sys_kcmp
include/linux/kcmp.h new file +17 -0
Index: linux-2.6.git/include/linux/kcmp.h
===================================================================
@@ -0,0 +1,17 @@
+#ifndef _LINUX_KCMP_H
+#define _LINUX_KCMP_H
+
+/* Comparision type */
+enum {
+	KCMP_FILE,
+	KCMP_VM,
+	KCMP_FILES,
+	KCMP_FS,
+	KCMP_SIGHAND,
+	KCMP_IO,
+	KCMP_SYSVSEM,
+
+	KCMP_TYPES,
+};
+
+#endif /* _LINUX_KCMP_H */
kernel/Makefile +1 -0
Index: linux-2.6.git/kernel/Makefile
===================================================================
@@ -25,6 +25,7 @@ endif
 obj-y += sched/
 obj-y += power/
 
+obj-$(CONFIG_X86) += kcmp.o
 obj-$(CONFIG_FREEZER) += freezer.o
 obj-$(CONFIG_PROFILING) += profile.o
 obj-$(CONFIG_SYSCTL_SYSCALL_CHECK) += sysctl_check.o
kernel/kcmp.c new file +163 -0

163 lines not on this page · raw message

#34 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 17 lines · Cyrill Gorcunov
Quoted 16 lines · Eric W. Biederman
Quoted 13 lines · Cyrill Gorcunov
Quoted 7 lines · KOSAKI Motohiro
Quoted 3 lines
Quoted 1 line

please do as you like.

So it should be something like below I think...

Looks ok this version to me. So, if you fix other developers pointed issue, I'll ack this.

Thanks!

Eric, so mm/ would be fine or I still should move it to kernel/ instead? I've addressed other issues I hope.

Quoted 6 lines
Quoted 4 lines

The world won't fall apart if the code lands in mm. I have a strong preference for kernel/. I just don't see anything at all memory management like about that code. Even the fact that you are comparing pointers is an implementation detail.

This one should fit all requirements I guess.

Bahahaha!

Looking I see one more nit.

You need an entry in include/linux/syscalls.h

Eric

Quoted 287 lines

---
From: Cyrill Gorcunov <[email protected]>
Subject: [RFC] syscalls, x86: Add __NR_kcmp syscall v6

While doing the checkpoint-restore in the userspace one need to determine whether various kernel objects (like mm_struct-s of file_struct-s) are shared between tasks and restore this state.

The 2nd step can be solved by using appropriate CLONE_ flags and the unshare syscall, while there's currently no ways for solving the 1st one.

One of the ways for checking whether two tasks share e.g. mm_struct is to provide some mm_struct ID of a task to its proc file, but showing such info considered to be not that good for security reasons.

Thus after some debates we end up in conclusion that using that named 'comparision' syscall might be the best candidate. So here is it -- __NR_kcmp.

It takes up to 5 agruments - the pids of the two tasks (which characteristics should be compared), the comparision type and (in case of comparision of files) two file descriptors.

At moment only x86 is supported.

CC "Eric W. Biederman" <[email protected]>
CC Pavel Emelyanov <[email protected]>
CC Andrey Vagin <[email protected]>
CC KOSAKI Motohiro <[email protected]>
CC Ingo Molnar <[email protected]>
CC H. Peter Anvin <[email protected]>
CC Thomas Gleixner <[email protected]>
CC Glauber Costa <[email protected]>
CC Andi Kleen <[email protected]>
CC Tejun Heo <[email protected]>
CC Matt Helsley <[email protected]>
CC Pekka Enberg <[email protected]>
CC Eric Dumazet <[email protected]>
CC Vasiliy Kulikov <[email protected]>
CC Andrew Morton <[email protected]>
CC Alexey Dobriyan <[email protected]>
---
 arch/x86/include/asm/syscalls.h  |    4 
 arch/x86/syscalls/syscall_32.tbl |    1 
 arch/x86/syscalls/syscall_64.tbl |    1 
 include/linux/kcmp.h             |   17 ++++
 kernel/Makefile                  |    1 
 kernel/kcmp.c                    |  163 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 187 insertions(+)

Index: linux-2.6.git/arch/x86/include/asm/syscalls.h
===================================================================

arch/x86/include/asm/syscalls.h +4 -0
@@ -42,6 +42,10 @@ long sys_sigaltstack(const stack_t __use
 asmlinkage int sys_set_thread_area(struct user_desc __user *);
 asmlinkage int sys_get_thread_area(struct user_desc __user *);
 
+/* kernel/kcmp.c */
+asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type,
+			 unsigned long idx1, unsigned long idx2);
+
 /* X86_32 only */
 #ifdef CONFIG_X86_32
 

Index: linux-2.6.git/arch/x86/syscalls/syscall_32.tbl
===================================================================

arch/x86/syscalls/syscall_32.tbl +1 -0
@@ -355,3 +355,4 @@
 346	i386	setns			sys_setns
 347	i386	process_vm_readv	sys_process_vm_readv		compat_sys_process_vm_readv
 348	i386	process_vm_writev	sys_process_vm_writev		compat_sys_process_vm_writev
+349	i386	kcmp			sys_kcmp

Index: linux-2.6.git/arch/x86/syscalls/syscall_64.tbl
===================================================================

arch/x86/syscalls/syscall_64.tbl +1 -0
@@ -318,3 +318,4 @@
 309	64	getcpu			sys_getcpu
 310	64	process_vm_readv	sys_process_vm_readv
 311	64	process_vm_writev	sys_process_vm_writev
+312	64	kcmp			sys_kcmp

Index: linux-2.6.git/include/linux/kcmp.h
===================================================================

include/linux/kcmp.h new file +17 -0
@@ -0,0 +1,17 @@
+#ifndef _LINUX_KCMP_H
+#define _LINUX_KCMP_H
+
+/* Comparision type */
+enum {
+	KCMP_FILE,
+	KCMP_VM,
+	KCMP_FILES,
+	KCMP_FS,
+	KCMP_SIGHAND,
+	KCMP_IO,
+	KCMP_SYSVSEM,
+
+	KCMP_TYPES,
+};
+
+#endif /* _LINUX_KCMP_H */

Index: linux-2.6.git/kernel/Makefile
===================================================================

kernel/Makefile +1 -0
@@ -25,6 +25,7 @@ endif
 obj-y += sched/
 obj-y += power/
 
+obj-$(CONFIG_X86) += kcmp.o
 obj-$(CONFIG_FREEZER) += freezer.o
 obj-$(CONFIG_PROFILING) += profile.o
 obj-$(CONFIG_SYSCTL_SYSCALL_CHECK) += sysctl_check.o

Index: linux-2.6.git/kernel/kcmp.c
===================================================================

kernel/kcmp.c new file +163 -0
@@ -0,0 +1,163 @@
+#include <linux/kernel.h>
+#include <linux/syscalls.h>
+#include <linux/fdtable.h>
+#include <linux/string.h>
+#include <linux/random.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/cache.h>
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/kcmp.h>
+
+#include <asm/unistd.h>
+
+static unsigned long cookies[KCMP_TYPES][2] __read_mostly;
+
+static long kptr_obfuscate(long v, int type)
+{
+	return (v ^ cookies[type][0]) * cookies[type][1];
+}
+
+/*
+ * 0 - equal
+ * 1 - less than
+ * 2 - greater than
+ * 3 - not equal but ordering unavailable
+ */
+static int kcmp_ptr(long v1, long v2, int type)
+{
+	long ret;
+
+	ret = kptr_obfuscate(v1, type) - kptr_obfuscate(v2, type);
+
+	return (ret < 0) | ((ret > 0) << 1);
+}
+
+#define KCMP_TASK_PTR(task1, task2, member, type)	\
+	kcmp_ptr((long)(task1)->member,			\
+		 (long)(task2)->member,			\
+		 type)
+
+#define KCMP_PTR(ptr1, ptr2, type)			\
+	kcmp_ptr((long)ptr1, (long)ptr2, type)
+
+/* A caller must be sure the task is presented in memory */
+static struct file *
+get_file_raw_ptr(struct task_struct *task, unsigned int idx)
+{
+	struct fdtable *fdt;
+	struct file *file;
+
+	spin_lock(&task->files->file_lock);
+	fdt = files_fdtable(task->files);
+	if (idx < fdt->max_fds)
+		file = fdt->fd[idx];
+	else
+		file = NULL;
+	spin_unlock(&task->files->file_lock);
+
+	return file;
+}
+
+SYSCALL_DEFINE5(kcmp, pid_t, pid1, pid_t, pid2, int, type,
+		unsigned long, idx1, unsigned long, idx2)
+{
+	struct task_struct *task1;
+	struct task_struct *task2;
+	int ret = 0;
+
+	rcu_read_lock();
+
+	task1 = find_task_by_vpid(pid1);
+	if (!task1) {
+		rcu_read_unlock();
+		return -ESRCH;
+	}
+
+	task2 = find_task_by_vpid(pid2);
+	if (!task2) {
+		put_task_struct(task1);
+		rcu_read_unlock();
+		return -ESRCH;
+	}
+
+	get_task_struct(task1);
+	get_task_struct(task2);
+
+	rcu_read_unlock();
+
+	if (!ptrace_may_access(task1, PTRACE_MODE_READ) ||
+	    !ptrace_may_access(task2, PTRACE_MODE_READ)) {
+		ret = -EACCES;
+		goto err;
+	}
+
+	/*
+	 * Note for all cases but the KCMP_FILE we
+	 * don't take any locks in a sake of speed.
+	 */
+
+	switch (type) {
+	case KCMP_FILE: {
+		struct file *filp1, *filp2;
+
+		filp1 = get_file_raw_ptr(task1, idx1);
+		filp2 = get_file_raw_ptr(task2, idx2);
+
+		if (filp1 && filp2)
+			ret = KCMP_PTR(filp1, filp2, KCMP_FILE);
+		else
+			ret = -ENOENT;
+		break;
+	}
+	case KCMP_VM:
+		ret = KCMP_TASK_PTR(task1, task2, mm, KCMP_VM);
+		break;
+	case KCMP_FILES:
+		ret = KCMP_TASK_PTR(task1, task2, files, KCMP_FILES);
+		break;
+	case KCMP_FS:
+		ret = KCMP_TASK_PTR(task1, task2, fs, KCMP_FS);
+		break;
+	case KCMP_SIGHAND:
+		ret = KCMP_TASK_PTR(task1, task2, sighand, KCMP_SIGHAND);
+		break;
+	case KCMP_IO:
+		ret = KCMP_TASK_PTR(task1, task2, io_context, KCMP_IO);
+		break;
+	case KCMP_SYSVSEM:
+#ifdef CONFIG_SYSVIPC
+		ret = KCMP_TASK_PTR(task1, task2, sysvsem.undo_list, KCMP_SYSVSEM);
+#else
+		ret = -ENOENT;
+		goto err;
+#endif
+		break;
+	default:
+		ret = -EINVAL;
+		goto err;
+	}
+
+err:
+	put_task_struct(task1);
+	put_task_struct(task2);
+
+	return ret;
+}
+
+static __init int kcmp_cookie_init(void)
+{
+	int i, j;
+
+	for (i = 0; i < KCMP_TYPES; i++) {
+		for (j = 0; j < 2; j++) {
+			get_random_bytes(&cookies[i][j],
+					 sizeof(cookies[i][j]));
+		}
+		cookies[i][1] |= (~(~0UL >>  1) | 1);
+	}
+
+	return 0;
+}
+late_initcall(kcmp_cookie_init);
#35 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

On Tue, Jan 24, 2012 at 01:20:12PM -0800, Eric W. Biederman wrote:
...

Quoted 8 lines
Quoted 2 lines

This one should fit all requirements I guess.

Bahahaha!

Looking I see one more nit.

You need an entry in include/linux/syscalls.h

Sigh.. ;) Not just this. I'll post updated version to address Andrew's comments too once I finish it (not today probably).

Cyrill

maintainer
#36 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

In reply to Cyrill Gorcunov
Quoted 1 line · On Wed, 25 Jan 2012 00:50:39 +0400 Cyrill Gorcunov <[email protected]> wrote:

This one should fit all requirements I guess.

[wakes up]

Quoted 11 lines

While doing the checkpoint-restore in the userspace one need to determine whether various kernel objects (like mm_struct-s of file_struct-s) are shared between tasks and restore this state.

The 2nd step can be solved by using appropriate CLONE_ flags and the unshare syscall, while there's currently no ways for solving the 1st one.

One of the ways for checking whether two tasks share e.g. mm_struct is to provide some mm_struct ID of a task to its proc file, but showing such info considered to be not that good for security reasons.

Quoted 7 lines

Thus after some debates we end up in conclusion that using that named 'comparision' syscall might be the best candidate. So here is it -- __NR_kcmp.

It takes up to 5 agruments - the pids of the two tasks (which characteristics should be compared), the comparision type and (in case of comparision of files) two file descriptors.

PIDs are not unique. One wonders what happens in this syscall if the same pid appears in two namespaces.

<reads the code>

Seems that it performs lookups only in the caller's PID namespace. Maybe this is appropriate but it should be described and justified in the changelog and in code comments, please. And in the forthcoming manpage ;)

Quoted 1 line

At moment only x86 is supported.

Presumably you have a test app. Please let's include that app in tools/testing/selftests/ for arch maintainers and others to use and maintain.

Quoted 11 lines

...

kernel/kcmp.c new file +5 -0
@@ -0,0 +1,163 @@
+#include <linux/kernel.h>
+#include <linux/syscalls.h>
+#include <linux/fdtable.h>
+#include <linux/string.h>
+#include <linux/random.h>

kernel/kcmp.c line 15

Quoted 10 lines
kernel/kcmp.c new file +10 -0
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/cache.h>
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/kcmp.h>
+
+#include <asm/unistd.h>
+
+static unsigned long cookies[KCMP_TYPES][2] __read_mostly;

This reader of this code doesn't understand why all this cookie stuff is in here. Please include code comments which explain the reason for the existence of this code.

kernel/kcmp.c line 26

Quoted 10 lines
kernel/kcmp.c new file +10 -0
+static long kptr_obfuscate(long v, int type)
+{
+	return (v ^ cookies[type][0]) * cookies[type][1];
+}
+
+/*
+ * 0 - equal
+ * 1 - less than
+ * 2 - greater than
+ * 3 - not equal but ordering unavailable

what the heck does case 3 mean? Why is it here?

Quoted 7 lines
kernel/kcmp.c new file +7 -0
+ */
+static int kcmp_ptr(long v1, long v2, int type)
+{
+	long ret;
+
+	ret = kptr_obfuscate(v1, type) - kptr_obfuscate(v2, type);
+

kernel/kcmp.c line 43

Quoted 10 lines
kernel/kcmp.c new file +10 -0
+	return (ret < 0) | ((ret > 0) << 1);
+}
+
+#define KCMP_TASK_PTR(task1, task2, member, type)	\
+	kcmp_ptr((long)(task1)->member,			\
+		 (long)(task2)->member,			\
+		 type)
+
+#define KCMP_PTR(ptr1, ptr2, type)			\
+	kcmp_ptr((long)ptr1, (long)ptr2, type)

ugh. This:

static long kptr_obfuscate(void *p, enum you_forgot_to_name_the_enum type)

{
	return ((long)p ^ cookies[type][0]) * cookies[type][1];
}

static int kcmp_task_pointers(void *task1, void *task2, size_t field_offset,
enum you_forgot_to_name_the_enum type)

{
	void **field1 = t1 + field_offset;	/* points to a pointer in the task_struct */
	void **field2 = t1 + field_offset;
	long diff;

	diff = kptr_obfuscate(*field1, type) - kptr_obfuscate(*field2, type);
	return (diff < 0) | ((diff > 0) << 1);
}
	...
	ret = kcmp_task_pointers(task1, task2, offsetof(task_struct, mm),
				KCMP_VM);
	...

see? No nasty macros, it's type-correct and it uses only a single explicit typecast.

kernel/kcmp.c line 45

Quoted 1 line
kernel/kcmp.c new file +1 -0
+/* A caller must be sure the task is presented in memory */

"The caller must have pinned the task"

Quoted 36 lines
kernel/kcmp.c new file +36 -0
+static struct file *
+get_file_raw_ptr(struct task_struct *task, unsigned int idx)
+{
+	struct fdtable *fdt;
+	struct file *file;
+
+	spin_lock(&task->files->file_lock);
+	fdt = files_fdtable(task->files);
+	if (idx < fdt->max_fds)
+		file = fdt->fd[idx];
+	else
+		file = NULL;
+	spin_unlock(&task->files->file_lock);
+
+	return file;
+}
+
+SYSCALL_DEFINE5(kcmp, pid_t, pid1, pid_t, pid2, int, type,
+		unsigned long, idx1, unsigned long, idx2)
+{
+	struct task_struct *task1;
+	struct task_struct *task2;
+	int ret = 0;
+
+	rcu_read_lock();
+
+	task1 = find_task_by_vpid(pid1);
+	if (!task1) {
+		rcu_read_unlock();
+		return -ESRCH;
+	}
+
+	task2 = find_task_by_vpid(pid2);
+	if (!task2) {
+		put_task_struct(task1);
+		rcu_read_unlock();

kernel/kcmp.c line 91

Quoted 10 lines
kernel/kcmp.c new file +10 -0
+		return -ESRCH;
+	}
+
+	get_task_struct(task1);
+	get_task_struct(task2);
+
+	rcu_read_unlock();
+
+	if (!ptrace_may_access(task1, PTRACE_MODE_READ) ||
+	    !ptrace_may_access(task2, PTRACE_MODE_READ)) {

Add a comment explaining this decision.

Quoted 32 lines
kernel/kcmp.c new file +32 -0
+		ret = -EACCES;
+		goto err;
+	}
+
+	/*
+	 * Note for all cases but the KCMP_FILE we
+	 * don't take any locks in a sake of speed.
+	 */
+
+	switch (type) {
+	case KCMP_FILE: {
+		struct file *filp1, *filp2;
+
+		filp1 = get_file_raw_ptr(task1, idx1);
+		filp2 = get_file_raw_ptr(task2, idx2);
+
+		if (filp1 && filp2)
+			ret = KCMP_PTR(filp1, filp2, KCMP_FILE);
+		else
+			ret = -ENOENT;
+		break;
+	}
+	case KCMP_VM:
+		ret = KCMP_TASK_PTR(task1, task2, mm, KCMP_VM);
+		break;
+	case KCMP_FILES:
+		ret = KCMP_TASK_PTR(task1, task2, files, KCMP_FILES);
+		break;
+	case KCMP_FS:
+		ret = KCMP_TASK_PTR(task1, task2, fs, KCMP_FS);
+		break;
+	case KCMP_SIGHAND:

kernel/kcmp.c line 133

Quoted 10 lines
kernel/kcmp.c new file +10 -0
+		ret = KCMP_TASK_PTR(task1, task2, sighand, KCMP_SIGHAND);
+		break;
+	case KCMP_IO:
+		ret = KCMP_TASK_PTR(task1, task2, io_context, KCMP_IO);
+		break;
+	case KCMP_SYSVSEM:
+#ifdef CONFIG_SYSVIPC
+		ret = KCMP_TASK_PTR(task1, task2, sysvsem.undo_list, KCMP_SYSVSEM);
+#else
+		ret = -ENOENT;

ENOENT seems inappropriate here.

Quoted 15 lines
kernel/kcmp.c new file +15 -0
+		goto err;
+#endif
+		break;
+	default:
+		ret = -EINVAL;
+		goto err;
+	}
+
+err:
+	put_task_struct(task1);
+	put_task_struct(task2);
+
+	return ret;
+}
+

kernel/kcmp.c line 158

Quoted 10 lines
kernel/kcmp.c new file +10 -0
+static __init int kcmp_cookie_init(void)
+{
+	int i, j;
+
+	for (i = 0; i < KCMP_TYPES; i++) {
+		for (j = 0; j < 2; j++) {
+			get_random_bytes(&cookies[i][j],
+					 sizeof(cookies[i][j]));
+		}
+		cookies[i][1] |= (~(~0UL >>  1) | 1);

hm, what's the point in writing a random number to cookies[i][1] and then immediately overwriting that with a constant?

Quoted 5 lines
kernel/kcmp.c new file +5 -0
+	}
+
+	return 0;
+}
+late_initcall(kcmp_cookie_init);
maintainer
#37 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 5 lines · On Tue, 24 Jan 2012 13:22:22 -0800 Andrew Morton <[email protected]>…

static int kcmp_task_pointers(void *task1, void *task2, size_t field_offset,
enum you_forgot_to_name_the_enum type)

{
	void **field1 = t1 + field_offset;	/* points to a pointer in the task_struct */
	void **field2 = t1 + field_offset;

On reflection, this was being too cute. It would be better to make the function type-safer and just put up with the local typecasts:

static int kcmp_task_pointers(struct task_struct *task1,
struct task_struct *task2, size_t field_offset, enum you_forgot_to_name_the_enum type)

{
	void **field1 = (void *)t1 + field_offset;
	void **field2 = (void *)t2 + field_offset;
#38 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 12 lines · Andrew Morton
Quoted 5 lines · On Tue, 24 Jan 2012 13:22:22 -0800 Andrew Morton <[email protected]>…

static int kcmp_task_pointers(void *task1, void *task2, size_t field_offset,
enum you_forgot_to_name_the_enum type)

{
	void **field1 = t1 + field_offset;	/* points to a pointer in the task_struct */
	void **field2 = t1 + field_offset;

On reflection, this was being too cute. It would be better to make the function type-safer and just put up with the local typecasts:

Quoted 7 lines

static int kcmp_task_pointers(struct task_struct *task1,
struct task_struct *task2, size_t field_offset, enum you_forgot_to_name_the_enum type)

{
	void **field1 = (void *)t1 + field_offset;
	void **field2 = (void *)t2 + field_offset;

Arithmetic on void pointers?

-hpa

maintainer
#39 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 21 lines · On Tue, 24 Jan 2012 13:46:31 -0800 "H. Peter Anvin" <[email protected]> wrote:
Quoted 12 lines · Andrew Morton
Quoted 5 lines · On Tue, 24 Jan 2012 13:22:22 -0800 Andrew Morton <[email protected]>…

static int kcmp_task_pointers(void *task1, void *task2, size_t field_offset,
enum you_forgot_to_name_the_enum type)

{
	void **field1 = t1 + field_offset;	/* points to a pointer in the task_struct */
	void **field2 = t1 + field_offset;

On reflection, this was being too cute. It would be better to make the function type-safer and just put up with the local typecasts:

Quoted 7 lines

static int kcmp_task_pointers(struct task_struct *task1,
struct task_struct *task2, size_t field_offset, enum you_forgot_to_name_the_enum type)

{
	void **field1 = (void *)t1 + field_offset;
	void **field2 = (void *)t2 + field_offset;
Quoted 2 lines

Arithmetic on void pointers?

All the world is gcc!

#40 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 4 lines · Andrew Morton
Quoted 2 lines

Arithmetic on void pointers?

All the world is gcc!

Even so, warnings are annoying...

-hpa

maintainer
#41 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 8 lines · On Tue, 24 Jan 2012 14:52:32 -0800 "H. Peter Anvin" <[email protected]> wrote:
Quoted 4 lines · Andrew Morton
Quoted 2 lines

Arithmetic on void pointers?

All the world is gcc!

Even so, warnings are annoying...

We already do arithmetic on void* in many places. Run "make W=3" and admire..

#42 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

In reply to Andrew Morton
Quoted 11 lines · Andrew Morton

PIDs are not unique. One wonders what happens in this syscall if the same pid appears in two namespaces.

<reads the code>

Seems that it performs lookups only in the caller's PID namespace. Maybe this is appropriate but it should be described and justified in the changelog and in code comments, please. And in the forthcoming manpage ;)

Yes, caller's namespace was used intentionally, will add comments (manpage makes me shiver).

Quoted 5 lines
Quoted 1 line

At moment only x86 is supported.

Presumably you have a test app. Please let's include that app in tools/testing/selftests/ for arch maintainers and others to use and maintain.

ok

Quoted 6 lines
Quoted 1 line

+static unsigned long cookies[KCMP_TYPES][2] __read_mostly;

This reader of this code doesn't understand why all this cookie stuff is in here. Please include code comments which explain the reason for the existence of this code.

ok

Quoted 4 lines
Quoted 4 lines
kernel/kcmp.c new file +4 -0
+static long kptr_obfuscate(long v, int type)
+{
+	return (v ^ cookies[type][0]) * cookies[type][1];
+}
Quoted 9 lines

kernel/kcmp.c line 26

Quoted 6 lines
kernel/kcmp.c new file +6 -0
+
+/*
+ * 0 - equal
+ * 1 - less than
+ * 2 - greater than
+ * 3 - not equal but ordering unavailable

what the heck does case 3 mean? Why is it here?

I'll add a comment. It's reserved for case where we might need to disable gt/lt comparision result. Probably in future.

Quoted 22 lines

kernel/kcmp.c line 43

Quoted 3 lines
kernel/kcmp.c new file +3 -0
+
+#define KCMP_PTR(ptr1, ptr2, type)			\
+	kcmp_ptr((long)ptr1, (long)ptr2, type)

ugh. This:

static long kptr_obfuscate(void *p, enum you_forgot_to_name_the_enum type)

{
	return ((long)p ^ cookies[type][0]) * cookies[type][1];
}

static int kcmp_task_pointers(void *task1, void *task2, size_t field_offset,
enum you_forgot_to_name_the_enum type)

{
	void **field1 = t1 + field_offset;	/* points to a pointer in the task_struct */
	void **field2 = t1 + field_offset;
	long diff;

	diff = kptr_obfuscate(*field1, type) - kptr_obfuscate(*field2, type);
	return (diff < 0) | ((diff > 0) << 1);
}
Quoted 8 lines
	...
	ret = kcmp_task_pointers(task1, task2, offsetof(task_struct, mm),
				KCMP_VM);
	...

see? No nasty macros, it's type-correct and it uses only a single explicit typecast.

ok, i'll change it of course, but I personally like macros version more.

Quoted 8 lines
Quoted 1 line

+/* A caller must be sure the task is presented in memory */

"The caller must have pinned the task"

kernel/kcmp.c line 91

Quoted 2 lines
kernel/kcmp.c new file +2 -0
+	if (!ptrace_may_access(task1, PTRACE_MODE_READ) ||
+	    !ptrace_may_access(task2, PTRACE_MODE_READ)) {

Add a comment explaining this decision.

OK.

Quoted 3 lines

ENOENT seems inappropriate here.

Which one should be better?

Quoted 5 lines
Quoted 5 lines
kernel/kcmp.c new file +5 -0
+static __init int kcmp_cookie_init(void)
+{
+	int i, j;
+
+	for (i = 0; i < KCMP_TYPES; i++) {
Quoted 8 lines

kernel/kcmp.c line 158

Quoted 5 lines
kernel/kcmp.c new file +5 -0
+		for (j = 0; j < 2; j++) {
+			get_random_bytes(&cookies[i][j],
+					 sizeof(cookies[i][j]));
+		}
+		cookies[i][1] |= (~(~0UL >>  1) | 1);

hm, what's the point in writing a random number to cookies[i][1] and then immediately overwriting that with a constant?

It's '|=' , not '='.

Cyrill

maintainer
#43 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 5 lines · On Wed, 25 Jan 2012 01:46:30 +0400 Cyrill Gorcunov <[email protected]> wrote:
Quoted 3 lines

ENOENT seems inappropriate here.

Which one should be better?

EINVAL, I guess.

#44 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

In reply to Andrew Morton
Quoted 6 lines · Andrew Morton

<reads the code>

Seems that it performs lookups only in the caller's PID namespace. Maybe this is appropriate but it should be described and justified in the changelog and in code comments, please. And in the forthcoming manpage ;)

Well pids should always and only be looked up in the callers pid namespace. Any other behavior is broken. It is probably worth a mention in a manpage but you should not need to justify using abstractions as they were designed to be used.

Quoted 35 lines
Quoted 6 lines
kernel/kcmp.c new file +6 -0
+static int kcmp_ptr(long v1, long v2, int type)
+{
+	long ret;
+
+	ret = kptr_obfuscate(v1, type) - kptr_obfuscate(v2, type);
+

kernel/kcmp.c line 43

Quoted 10 lines
kernel/kcmp.c new file +10 -0
+	return (ret < 0) | ((ret > 0) << 1);
+}
+
+#define KCMP_TASK_PTR(task1, task2, member, type)	\
+	kcmp_ptr((long)(task1)->member,			\
+		 (long)(task2)->member,			\
+		 type)
+
+#define KCMP_PTR(ptr1, ptr2, type)			\
+	kcmp_ptr((long)ptr1, (long)ptr2, type)

ugh. This:

static long kptr_obfuscate(void *p, enum you_forgot_to_name_the_enum type)

{
	return ((long)p ^ cookies[type][0]) * cookies[type][1];
}

static int kcmp_task_pointers(void *task1, void *task2, size_t field_offset,
enum you_forgot_to_name_the_enum type)

{
	void **field1 = t1 + field_offset;	/* points to a pointer in the task_struct */
	void **field2 = t1 + field_offset;
	long diff;

	diff = kptr_obfuscate(*field1, type) - kptr_obfuscate(*field2, type);
	return (diff < 0) | ((diff > 0) << 1);
}
Quoted 7 lines
	...
	ret = kcmp_task_pointers(task1, task2, offsetof(task_struct, mm),
				KCMP_VM);
	...

see? No nasty macros, it's type-correct and it uses only a single explicit typecast.

Seriously? Simply open coding the comparison would be better.

        ret = kcmp_ptr(task1->files, task2->files, type);

All pointers are not encoded the same as void * pointers. Admittedly the only case I can think of are function pointers on Itanium, but what is a little wrong today can easily become a lot wrong tomorrow.

Making the kcmp_ptr arguments void * seems the way to go though.

Now there is one interesting case we are not handling properly. If any of our pointers can be NULL which I think happens in the file case we should return -EBADF instead of reporting two NULL pointers point to the same object.

Eric

maintainer
#45 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 3 lines · On Tue, 24 Jan 2012 14:54:18 -0800 [email protected] (Eric W. Biederman)…

Simply open coding the comparison would be better.

        ret = kcmp_ptr(task1->files, task2->files, type);

yup, that's nice.

maintainer
#46 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

In reply to Cyrill Gorcunov
Quoted 1 line · On Wed, 25 Jan 2012 00:50:39 +0400 Cyrill Gorcunov <[email protected]> wrote:

While doing the checkpoint-restore in the userspace

btw, some questions regarding the overall project: do you guys actually have working userspace code which can at least partially perform a c/r? What state is all this in?

I'd be a bit concerned if we're putting code into mainline which has not been demonstrated to achieve any form of successful checkpoint/restore.

#47 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

Quoted 9 lines · Andrew Morton
Quoted 1 line · On Wed, 25 Jan 2012 00:50:39 +0400 Cyrill Gorcunov <[email protected]> wrote:

While doing the checkpoint-restore in the userspace

btw, some questions regarding the overall project: do you guys actually have working userspace code which can at least partially perform a c/r? What state is all this in?

Yes, we have a number of test-cases which do c/r. See details on
http://criu.org/ . We don't announce it yet since everything is under heavy development.

Quoted 2 lines

I'd be a bit concerned if we're putting code into mainline which has not been demonstrated to achieve any form of successful checkpoint/restore.

Cyrill

#48 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

In reply to KAMEZAWA Hiroyuki
Quoted 22 lines · KAMEZAWA Hiroyuki
Quoted 19 lines · On Tue, 24 Jan 2012 11:17:16 +0400 Cyrill Gorcunov <[email protected]> wrote:
Quoted 17 lines · H. Peter Anvin
Quoted 4 lines · Cyrill Gorcunov
Quoted 3 lines

Why under /arch ?

Quoted 8 lines

Hi Kame,

because I've tested it under x86 only. Once someone confirm it's needed on some else arch and does work as expected -- it wont be a problem to make it system wide. Until then -- I think better to stick with at least tested case.
...

That's not a reason to put it in arch/ ... that's possibly a reason to not map the system call on other architectures yet.

Quoted 7 lines
Quoted 2 lines

Where it should live then? In kernel/ or mm/ ?

kernel/checkpoint_restart ?

gathering related changes to a directory may help developpers joins later.... To me, this makes seeing git log easy ;)

kernel/

The dominant use may be checkpoint restart but the code is not at all checkpoint restart specific.

Eric

#49 lore raw

Re: [patch 2/4] [RFC] syscalls, x86: Add __NR_kcmp syscall v4

On Tue, Jan 24, 2012 at 12:49:27AM -0800, Eric W. Biederman wrote:
...

Quoted 6 lines

kernel/

The dominant use may be checkpoint restart but the code is not at all checkpoint restart specific.

Crap, just sent out mm/ version :)

Cyrill

#50 lore raw

PATCH 3/4 c/r: procfs: add arg_start/end, env_start/end and exit_code members to /proc/$pid/stat

In reply to Cyrill Gorcunov

We would like to have an ability to restore command line arguments and envirion pointers so the task being restored would print appropriate values in /proc/pid/cmdline and /proc/pid/envirion. The exit_code is needed to restore zombie tasks.

Cc Pavel Emelyanov <[email protected]>
Cc Serge Hallyn <[email protected]>
Cc Kees Cook <[email protected]>
Cc KAMEZAWA Hiroyuki <[email protected]>
Cc Alexey Dobriyan <[email protected]>
Cc Tejun Heo <[email protected]>
Cc Andrew Vagin <[email protected]>
Cc Vasiliy Kulikov <[email protected]>
Cc Alexey Dobriyan <[email protected]>
Cc "Eric W. Biederman" <[email protected]>
---
 fs/proc/array.c |   10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
fs/proc/array.c +8 -2
Index: linux-2.6.git/fs/proc/array.c
===================================================================
@@ -464,7 +464,8 @@ static int do_task_stat(struct seq_file
 
 	seq_printf(m, "%d (%s) %c %d %d %d %d %d %u %lu \
 %lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
-%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld %lu %lu %lu\n",
+%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld %lu %lu %lu \
+%lu %lu %lu %lu %d\n",
 		pid_nr_ns(pid, ns),
 		tcomm,
 		state,
@@ -514,7 +515,12 @@ static int do_task_stat(struct seq_file
 		cputime_to_clock_t(cgtime),
 		(mm && permitted) ? mm->start_data : 0,
 		(mm && permitted) ? mm->end_data : 0,
-		(mm && permitted) ? mm->start_brk : 0);
+		(mm && permitted) ? mm->start_brk : 0,
+		(mm && permitted) ? mm->arg_start : 0,
+		(mm && permitted) ? mm->arg_end : 0,
+		(mm && permitted) ? mm->env_start : 0,
+		(mm && permitted) ? mm->env_end : 0,
+		task->exit_code);
 	if (mm)
 		mmput(mm);
 	return 0;
#51 lore raw

Re: [patch 3/4] c/r: procfs: add arg_start/end, env_start/end and exit_code members to /proc/$pid/stat

Quoted 39 lines · Cyrill Gorcunov

We would like to have an ability to restore command line arguments and envirion pointers so the task being restored would print appropriate values in /proc/pid/cmdline and /proc/pid/envirion. The exit_code is needed to restore zombie tasks.

Cc Pavel Emelyanov <[email protected]>
Cc Serge Hallyn <[email protected]>
Cc Kees Cook <[email protected]>
Cc KAMEZAWA Hiroyuki <[email protected]>
Cc Alexey Dobriyan <[email protected]>
Cc Tejun Heo <[email protected]>
Cc Andrew Vagin <[email protected]>
Cc Vasiliy Kulikov <[email protected]>
Cc Alexey Dobriyan <[email protected]>
Cc "Eric W. Biederman" <[email protected]>

---
 fs/proc/array.c |   10 ++++++++--

 1 file changed, 8 insertions(+), 2 deletions(-)

Index: linux-2.6.git/fs/proc/array.c
===================================================================

fs/proc/array.c +2 -1
@@ -464,7 +464,8 @@ static int do_task_stat(struct seq_file
 
        seq_printf(m, "%d (%s) %c %d %d %d %d %d %u %lu \
  %lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
-%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld %lu %lu %lu\n",
+%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld %lu %lu %lu \
+%lu %lu %lu %lu %d\n",
                pid_nr_ns(pid, ns),
                tcomm,
                state,
@@ -514,7 +515,12 @@ static int do_task_stat(struct seq_file
                cputime_to_clock_t(cgtime),
                (mm && permitted) ? mm->start_data : 0,
                (mm && permitted) ? mm->end_data : 0,

fs/proc/array.c static int do_task_stat(struct seq_file · line 526

Quoted 10 lines
fs/proc/array.c +6 -1
-               (mm && permitted) ? mm->start_brk : 0);
+               (mm && permitted) ? mm->start_brk : 0,
+               (mm && permitted) ? mm->arg_start : 0,
+               (mm && permitted) ? mm->arg_end : 0,
+               (mm && permitted) ? mm->env_start : 0,
+               (mm && permitted) ? mm->env_end : 0,
+               task->exit_code);
        if (mm)
                mmput(mm);
        return 0;

You're not exposing auxv here? In your testing, what situations ended up using auxv after initial startup? Or is your intention to be able to freeze a process potentially before libc has examined auxv?

-Kees

Signature · 2 lines
Kees Cook
ChromeOS Security
#52 lore raw

Re: [patch 3/4] c/r: procfs: add arg_start/end, env_start/end and exit_code members to /proc/$pid/stat

Quoted 46 lines · Kees Cook
Quoted 45 lines · Cyrill Gorcunov

We would like to have an ability to restore command line arguments and envirion pointers so the task being restored would print appropriate values in /proc/pid/cmdline and /proc/pid/envirion. The exit_code is needed to restore zombie tasks.

Cc Pavel Emelyanov <[email protected]>
Cc Serge Hallyn <[email protected]>
Cc Kees Cook <[email protected]>
Cc KAMEZAWA Hiroyuki <[email protected]>
Cc Alexey Dobriyan <[email protected]>
Cc Tejun Heo <[email protected]>
Cc Andrew Vagin <[email protected]>
Cc Vasiliy Kulikov <[email protected]>
Cc Alexey Dobriyan <[email protected]>
Cc "Eric W. Biederman" <[email protected]>

---
 fs/proc/array.c |   10 ++++++++--

 1 file changed, 8 insertions(+), 2 deletions(-)

Index: linux-2.6.git/fs/proc/array.c
===================================================================

fs/proc/array.c +7 -2
@@ -464,7 +464,8 @@ static int do_task_stat(struct seq_file
 
        seq_printf(m, "%d (%s) %c %d %d %d %d %d %u %lu \
  %lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
-%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld %lu %lu %lu\n",
+%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld %lu %lu %lu \
+%lu %lu %lu %lu %d\n",
                pid_nr_ns(pid, ns),
                tcomm,
                state,
@@ -514,7 +515,12 @@ static int do_task_stat(struct seq_file
                cputime_to_clock_t(cgtime),
                (mm && permitted) ? mm->start_data : 0,
                (mm && permitted) ? mm->end_data : 0,
-               (mm && permitted) ? mm->start_brk : 0);
+               (mm && permitted) ? mm->start_brk : 0,
+               (mm && permitted) ? mm->arg_start : 0,
+               (mm && permitted) ? mm->arg_end : 0,
+               (mm && permitted) ? mm->env_start : 0,
+               (mm && permitted) ? mm->env_end : 0,
Quoted 9 lines

fs/proc/array.c static int do_task_stat(struct seq_file · line 526

Quoted 4 lines
fs/proc/array.c +1 -0
+               task->exit_code);
        if (mm)
                mmput(mm);
        return 0;

You're not exposing auxv here? In your testing, what situations ended up using auxv after initial startup? Or is your intention to be able to freeze a process potentially before libc has examined auxv?

auxv already available via /proc/pid/auxv so I thought it would be redundant to put it into different place. Or you meant something else?

In testing I simply read auxv values from /proc/pid/auxv and restore them back via prctl at restore time. (prctl patch is in this series but it's slightly buggy so I post correct version later).

And intention is simply dump this vector at checkpoint time and restore when needed.

Cyrill

maintainer
#53 lore raw

Re: [patch 3/4] c/r: procfs: add arg_start/end, env_start/end and exit_code members to /proc/$pid/stat

In reply to Cyrill Gorcunov
Quoted 6 lines · On Mon, 23 Jan 2012 18:20:39 +0400 Cyrill Gorcunov <[email protected]> wrote:

We would like to have an ability to restore command line arguments and envirion pointers so the task being restored would print appropriate values in /proc/pid/cmdline and /proc/pid/envirion. The exit_code is needed to restore zombie tasks.

Please update Documentation/filesystems/proc.txt.

Quoted 17 lines
fs/proc/array.c +2 -1
@@ -464,7 +464,8 @@ static int do_task_stat(struct seq_file
 
 	seq_printf(m, "%d (%s) %c %d %d %d %d %d %u %lu \
 %lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
-%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld %lu %lu %lu\n",
+%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld %lu %lu %lu \
+%lu %lu %lu %lu %d\n",
 		pid_nr_ns(pid, ns),
 		tcomm,
 		state,
@@ -514,7 +515,12 @@ static int do_task_stat(struct seq_file
 		cputime_to_clock_t(cgtime),
 		(mm && permitted) ? mm->start_data : 0,
 		(mm && permitted) ? mm->end_data : 0,

fs/proc/array.c static int do_task_stat(struct seq_file · line 526

Quoted 10 lines
fs/proc/array.c +6 -1
-		(mm && permitted) ? mm->start_brk : 0);
+		(mm && permitted) ? mm->start_brk : 0,
+		(mm && permitted) ? mm->arg_start : 0,
+		(mm && permitted) ? mm->arg_end : 0,
+		(mm && permitted) ? mm->env_start : 0,
+		(mm && permitted) ? mm->env_end : 0,
+		task->exit_code);
 	if (mm)
 		mmput(mm);
 	return 0;

/proc/pid/stat is getting out of control. People are now sending patches because reading from this thing already takes too long.

The problem is that if you only want one field, you have to incur the cost of preparing all the fields. The magnitude of this problem increases exponentially over time!

I'm unsure what to do about it really. Perhaps add a new /proc/pid/mmstat for MM-specific things. We could put the above six fields in there, as long as we move quickly.

#54 lore raw

Re: [patch 3/4] c/r: procfs: add arg_start/end, env_start/end and exit_code members to /proc/$pid/stat

Quoted 11 lines · Andrew Morton
Quoted 6 lines · On Mon, 23 Jan 2012 18:20:39 +0400 Cyrill Gorcunov <[email protected]> wrote:

We would like to have an ability to restore command line arguments and envirion pointers so the task being restored would print appropriate values in /proc/pid/cmdline and /proc/pid/envirion. The exit_code is needed to restore zombie tasks.

Please update Documentation/filesystems/proc.txt.

ok

Quoted 13 lines

fs/proc/array.c static int do_task_stat(struct seq_file · line 526

Quoted 9 lines
fs/proc/array.c +6 -0
+		(mm && permitted) ? mm->start_brk : 0,
+		(mm && permitted) ? mm->arg_start : 0,
+		(mm && permitted) ? mm->arg_end : 0,
+		(mm && permitted) ? mm->env_start : 0,
+		(mm && permitted) ? mm->env_end : 0,
+		task->exit_code);
 	if (mm)
 		mmput(mm);
 	return 0;

/proc/pid/stat is getting out of control. People are now sending patches because reading from this thing already takes too long.

Quoted 8 lines

The problem is that if you only want one field, you have to incur the cost of preparing all the fields. The magnitude of this problem increases exponentially over time!

I'm unsure what to do about it really. Perhaps add a new /proc/pid/mmstat for MM-specific things. We could put the above six fields in there, as long as we move quickly.

I can add prctl PR_GET_MM with subcodes, since PR_SET_MM is already here and wrapped with CHECKPOINT_RESTORE. Would this be better?

Cyrill

maintainer
#55 lore raw

Re: [patch 3/4] c/r: procfs: add arg_start/end, env_start/end and exit_code members to /proc/$pid/stat

Quoted 4 lines · On Wed, 25 Jan 2012 10:54:50 +0400 Cyrill Gorcunov <[email protected]> wrote:
Quoted 4 lines
Quoted 4 lines
fs/proc/array.c +4 -0
+		(mm && permitted) ? mm->start_brk : 0,
+		(mm && permitted) ? mm->arg_start : 0,
+		(mm && permitted) ? mm->arg_end : 0,
+		(mm && permitted) ? mm->env_start : 0,
Quoted 8 lines
Quoted 8 lines

fs/proc/array.c static int do_task_stat(struct seq_file · line 526

Quoted 5 lines
fs/proc/array.c +2 -0
+		(mm && permitted) ? mm->env_end : 0,
+		task->exit_code);
 	if (mm)
 		mmput(mm);
 	return 0;

/proc/pid/stat is getting out of control. People are now sending patches because reading from this thing already takes too long.

err, actually, that was /proc/stat/

Quoted 11 lines
Quoted 8 lines

The problem is that if you only want one field, you have to incur the cost of preparing all the fields. The magnitude of this problem increases exponentially over time!

I'm unsure what to do about it really. Perhaps add a new /proc/pid/mmstat for MM-specific things. We could put the above six fields in there, as long as we move quickly.

I can add prctl PR_GET_MM with subcodes, since PR_SET_MM is already here and wrapped with CHECKPOINT_RESTORE. Would this be better?

mm, not really - /proc is the logical/expected place for it.

I'm thinking that perhaps we should start again with all of this and export all this information in brand new, well-designed procfs files. We'd still maintain /proc/stat and /proc/pid/stat but people should migrate off them. Eventually (10 years?) everyone will be setting their CONFIG_PROC_[PID_]STAT to 'n' and perhaps we can retire the things.

Meanwhile, I suppose you may as well continue to make /proc/pid/stat even crazier :( It isn't as bad as /proc/stat!

btw, do we really need to do "(mm && permitted)" so many times? ie, can we split that seq_printf up and do

	if (mm && permitted) {
		seq_printf(m + offset, "%lu", mm->start_data);
		...
	} else {
		seq_printf(m + offset, "0 0 0 0 0 0 0 0 0");
	}

? Although this probably won't help much.

#56 lore raw

Re: [patch 3/4] c/r: procfs: add arg_start/end, env_start/end and exit_code members to /proc/$pid/stat

Quoted 7 lines · Andrew Morton
Quoted 2 lines · On Wed, 25 Jan 2012 10:54:50 +0400 Cyrill Gorcunov <[email protected]> wrote:
Quoted 2 lines

/proc/pid/stat is getting out of control. People are now sending patches because reading from this thing already takes too long.

err, actually, that was /proc/stat/

Ah! (I saw those thread, but then I get confused and thought maybe there were for /proc/pid/stat as well but I simply missed it ;)

Quoted 6 lines
Quoted 3 lines

I can add prctl PR_GET_MM with subcodes, since PR_SET_MM is already here and wrapped with CHECKPOINT_RESTORE. Would this be better?

mm, not really - /proc is the logical/expected place for it.

Quoted 9 lines

I'm thinking that perhaps we should start again with all of this and export all this information in brand new, well-designed procfs files. We'd still maintain /proc/stat and /proc/pid/stat but people should migrate off them. Eventually (10 years?) everyone will be setting their CONFIG_PROC_[PID_]STAT to 'n' and perhaps we can retire the things.

Meanwhile, I suppose you may as well continue to make /proc/pid/stat even crazier :( It isn't as bad as /proc/stat!

At moment indeed it's not that bloated... yet.

Quoted 12 lines

btw, do we really need to do "(mm && permitted)" so many times? ie, can we split that seq_printf up and do

	if (mm && permitted) {
		seq_printf(m + offset, "%lu", mm->start_data);
		...
	} else {
		seq_printf(m + offset, "0 0 0 0 0 0 0 0 0");
	}

? Although this probably won't help much.

Yeah we can. I'll update.

Cyrill

#57 lore raw

PATCH 4/4 c/r: prctl: Extend PR_SET_MM to set up more mm_struct entries

In reply to Cyrill Gorcunov

After restore we would like the 'ps' command show the command line and evironment exactly the same it was at checkpoint time.

So this additional PR_SET_MM_ allow us to do so. Note that these members of mm_struct is rather used for output in procfs, except auxv vector which is used by ld.so mostly.

Cc Michael Kerrisk <[email protected]>
Cc Kees Cook <[email protected]>
Cc Tejun Heo <[email protected]>
Cc Andrew Vagin <[email protected]>
Cc Serge Hallyn <[email protected]>
Cc Pavel Emelyanov <[email protected]>
Cc Vasiliy Kulikov <[email protected]>
Cc KAMEZAWA Hiroyuki <[email protected]>
Cc Michael Kerrisk <[email protected]>
Cc Andrew Morton <[email protected]>
---
 include/linux/prctl.h |    5 +++
 kernel/sys.c          |   73 +++++++++++++++++++++++++++++++-------------------
 2 files changed, 51 insertions(+), 27 deletions(-)
include/linux/prctl.h +5 -0
Index: linux-2.6.git/include/linux/prctl.h
===================================================================
@@ -113,5 +113,10 @@
 # define PR_SET_MM_START_STACK		5
 # define PR_SET_MM_START_BRK		6
 # define PR_SET_MM_BRK			7
+# define PR_SET_MM_ARG_START		8
+# define PR_SET_MM_ARG_END		9
+# define PR_SET_MM_ENV_START		10
+# define PR_SET_MM_ENV_END		11
+# define PR_SET_MM_AUXV			12
 
 #endif /* _LINUX_PRCTL_H */
kernel/sys.c +46 -27

117 lines not on this page · raw message

#58 lore raw

Re: [patch 4/4] c/r: prctl: Extend PR_SET_MM to set up more mm_struct entries

Quoted 18 lines · Cyrill Gorcunov

After restore we would like the 'ps' command show the command line and evironment exactly the same it was at checkpoint time.

So this additional PR_SET_MM_ allow us to do so. Note that these members of mm_struct is rather used for output in procfs, except auxv vector which is used by ld.so mostly.

Cc Michael Kerrisk <[email protected]>
Cc Kees Cook <[email protected]>
Cc Tejun Heo <[email protected]>
Cc Andrew Vagin <[email protected]>
Cc Serge Hallyn <[email protected]>
Cc Pavel Emelyanov <[email protected]>
Cc Vasiliy Kulikov <[email protected]>
Cc KAMEZAWA Hiroyuki <[email protected]>
Cc Michael Kerrisk <[email protected]>
Cc Andrew Morton <[email protected]>
Quoted 1 line

---

This one is with typo fixed.

Cyrill
---
From: Cyrill Gorcunov <[email protected]>
Subject: c/r: prctl: Extend PR_SET_MM to set up more mm_struct entries

After restore we would like the 'ps' command show the command line and evironment exactly the same it was at checkpoint time.

So this additional PR_SET_MM_ allow us to do so. Note that these members of mm_struct is rather used for output in procfs, except auxv vector which is used by ld.so mostly.

Cc Michael Kerrisk <[email protected]>
Cc Kees Cook <[email protected]>
Cc Tejun Heo <[email protected]>
Cc Andrew Vagin <[email protected]>
Cc Serge Hallyn <[email protected]>
Cc Pavel Emelyanov <[email protected]>
Cc Vasiliy Kulikov <[email protected]>
Cc KAMEZAWA Hiroyuki <[email protected]>
Cc Michael Kerrisk <[email protected]>
Cc Andrew Morton <[email protected]>
---
 include/linux/prctl.h |    5 +++
 kernel/sys.c          |   73 +++++++++++++++++++++++++++++++-------------------
 2 files changed, 51 insertions(+), 27 deletions(-)
include/linux/prctl.h +5 -0
Index: linux-2.6.git/include/linux/prctl.h
===================================================================
@@ -113,5 +113,10 @@
 # define PR_SET_MM_START_STACK		5
 # define PR_SET_MM_START_BRK		6
 # define PR_SET_MM_BRK			7
+# define PR_SET_MM_ARG_START		8
+# define PR_SET_MM_ARG_END		9
+# define PR_SET_MM_ENV_START		10
+# define PR_SET_MM_ENV_END		11
+# define PR_SET_MM_AUXV			12
 
 #endif /* _LINUX_PRCTL_H */
kernel/sys.c +46 -27

117 lines not on this page · raw message

#59 lore raw

Re: [patch 4/4] c/r: prctl: Extend PR_SET_MM to set up more mm_struct entries

Quoted 11 lines · Cyrill Gorcunov
Quoted 7 lines · Cyrill Gorcunov

After restore we would like the 'ps' command show the command line and evironment exactly the same it was at checkpoint time.

So this additional PR_SET_MM_ allow us to do so. Note that these members of mm_struct is rather used for output in procfs, except auxv vector which is used by ld.so mostly.

This one is with typo fixed.
---

After some more testing I found there is a proble, so I'll send updated version later. Please dont review ;)

Cyrill