Skip to contentSkip to conversation

A pile in c/r sake v2

PATCH In review Cyrill Gorcunov 2 participants 9 messages Feb 3, 2012

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

cover A pile in c/r sake v2

Hi, hope this time I've addressed more or less all concerns, still please say me if something is not yet good enough.

- sys_kcmp now depends on CONFIG_CHECKPOINT_RESTORE (Ingo, I suppose arch_initcall for kcmp_cookies_init should be better than late_initcall, but I'm not sure)

- the extension of /proc/pid/stat now done against linux-next/master

Please review, thanks,

Cyrill

#1 lore raw

PATCH 1/4 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                    |  123 +++++++++++++++++++++++++++++++++++++
 fs/proc/base.c                     |    3 
 fs/proc/internal.h                 |    1 
 4 files changed, 145 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 +3 -0
Index: linux-2.6.git/fs/proc/base.c
===================================================================
@@ -3350,6 +3350,9 @@ 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),
+#ifdef CONFIG_CHECKPOINT_RESTORE
+	REG("children",  S_IRUGO, proc_tid_children_operations),
+#endif
 #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;
#2 lore raw

PATCH 2/4 syscalls, x86: Add __NR_kcmp syscall v7

In reply to Cyrill Gorcunov

While doing the checkpoint-restore in the user space 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 'comparison' syscall might be the best candidate. So here is it -- __NR_kcmp.

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

Lookups for pids are done in the caller's PID namespace only.

At moment only x86 is supported and tested.

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]>
CC Michal Marek <[email protected]>
---
 arch/x86/syscalls/syscall_32.tbl         |    1 
 arch/x86/syscalls/syscall_64.tbl         |    1 
 include/linux/kcmp.h                     |   17 +++
 include/linux/syscalls.h                 |    2 
 kernel/Makefile                          |    3 
 kernel/kcmp.c                            |  158 +++++++++++++++++++++++++++++++
 kernel/sys_ni.c                          |    3 
 tools/testing/selftests/kcmp/Makefile    |   36 +++++++
 tools/testing/selftests/kcmp/kcmp_test.c |   84 ++++++++++++++++
 tools/testing/selftests/run_tests        |    2 
 10 files changed, 306 insertions(+), 1 deletion(-)
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
+
+/* Comparison type */
+enum kcmp_type {
+	KCMP_FILE,
+	KCMP_VM,
+	KCMP_FILES,
+	KCMP_FS,
+	KCMP_SIGHAND,
+	KCMP_IO,
+	KCMP_SYSVSEM,
+
+	KCMP_TYPES,
+};
+
+#endif /* _LINUX_KCMP_H */
include/linux/syscalls.h +2 -0
Index: linux-2.6.git/include/linux/syscalls.h
===================================================================
@@ -857,4 +857,6 @@ asmlinkage long sys_process_vm_writev(pi
 				      unsigned long riovcnt,
 				      unsigned long flags);
 
+asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type,
+			 unsigned long idx1, unsigned long idx2);
 #endif
kernel/Makefile +3 -0
Index: linux-2.6.git/kernel/Makefile
===================================================================
@@ -25,6 +25,9 @@ endif
 obj-y += sched/
 obj-y += power/
 
+ifeq ($(CONFIG_CHECKPOINT_RESTORE),y)
+obj-$(CONFIG_X86) += kcmp.o
+endif
 obj-$(CONFIG_FREEZER) += freezer.o
 obj-$(CONFIG_PROFILING) += profile.o
 obj-$(CONFIG_SYSCTL_SYSCALL_CHECK) += sysctl_check.o
kernel/kcmp.c new file +158 -0

158 lines not on this page · raw message

kernel/sys_ni.c +3 -0
Index: linux-2.6.git/kernel/sys_ni.c
===================================================================
@@ -203,3 +203,6 @@ cond_syscall(sys_fanotify_mark);
 cond_syscall(sys_name_to_handle_at);
 cond_syscall(sys_open_by_handle_at);
 cond_syscall(compat_sys_open_by_handle_at);
+
+/* compare kernel pointers */
+cond_syscall(sys_kcmp);
tools/testing/selftests/kcmp/Makefile new file +36 -0
Index: linux-2.6.git/tools/testing/selftests/kcmp/Makefile
===================================================================
@@ -0,0 +1,36 @@
+ifeq ($(strip $(V)),)
+	E = @echo
+	Q = @
+else
+	E = @\#
+	Q =
+endif
+export E Q
+
+uname_M := $(shell uname -m 2>/dev/null || echo not)
+ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/)
+ifeq ($(ARCH),i386)
+        ARCH := X86
+	CFLAGS := -DCONFIG_X86_32 -D__i386__
+endif
+ifeq ($(ARCH),x86_64)
+	ARCH := X86
+	CFLAGS := -DCONFIG_X86_64 -D__x86_64__
+endif
+
+CFLAGS += -I../../../../arch/x86/include/generated/
+CFLAGS += -I../../../../include/
+CFLAGS += -I../../../../usr/include/
+
+all:
+ifeq ($(ARCH),X86)
+	$(E) "  CC run_test"
+	$(Q) gcc $(CFLAGS) kcmp_test.c -o run_test
+else
+	$(E) "Not an x86 target, can't build kcmp selftest"
+endif
+
+clean:
+	$(E) "  CLEAN"
+	$(Q) rm -fr ./run_test
+	$(Q) rm -fr ./test-file
tools/testing/selftests/kcmp/kcmp_test.c new file +84 -0

84 lines not on this page · raw message

tools/testing/selftests/run_tests +1 -1
Index: linux-2.6.git/tools/testing/selftests/run_tests
===================================================================
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-TARGETS=breakpoints
+TARGETS="breakpoints kcmp"
 
 for TARGET in $TARGETS
 do
#3 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 program environment pointers but first we need to obtain them somehow. Thus we put these values into /proc/$pid/stat. The exit_code is needed to restore zombie tasks.

Cc Kees Cook <[email protected]>
Cc Pavel Emelyanov <[email protected]>
Cc Serge Hallyn <[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]>
---
 Documentation/filesystems/proc.txt |    5 +++++
 fs/proc/array.c                    |   20 +++++++++++++++++---
 2 files changed, 22 insertions(+), 3 deletions(-)
Documentation/filesystems/proc.txt +5 -0
Index: linux-2.6.git/Documentation/filesystems/proc.txt
===================================================================
@@ -311,6 +311,11 @@ Table 1-4: Contents of the stat files (a
   start_data    address above which program data+bss is placed
   end_data      address below which program data+bss is placed
   start_brk     address above which program heap can be expanded with brk()
+  arg_start     address above which program command line is placed
+  arg_end       address below which program command line is placed
+  env_start     address above which program environment is placed
+  env_end       address below which program environment is placed
+  exit_code     the thread's exit_code in the form reported by the waitpid system call
 ..............................................................................
 
 The /proc/PID/maps file containing the currently mapped memory regions and
fs/proc/array.c +17 -3
Index: linux-2.6.git/fs/proc/array.c
===================================================================
@@ -508,9 +508,23 @@ static int do_task_stat(struct seq_file
 	seq_put_decimal_ull(m, ' ', delayacct_blkio_ticks(task));
 	seq_put_decimal_ull(m, ' ', cputime_to_clock_t(gtime));
 	seq_put_decimal_ll(m, ' ', cputime_to_clock_t(cgtime));
-	seq_put_decimal_ull(m, ' ', (mm && permitted) ? mm->start_data : 0);
-	seq_put_decimal_ull(m, ' ', (mm && permitted) ? mm->end_data : 0);
-	seq_put_decimal_ull(m, ' ', (mm && permitted) ? mm->start_brk : 0);
+
+	if (mm && permitted) {
+		seq_put_decimal_ull(m, ' ', mm->start_data);
+		seq_put_decimal_ull(m, ' ', mm->end_data);
+		seq_put_decimal_ull(m, ' ', mm->start_brk);
+		seq_put_decimal_ull(m, ' ', mm->arg_start);
+		seq_put_decimal_ull(m, ' ', mm->arg_end);
+		seq_put_decimal_ull(m, ' ', mm->env_start);
+		seq_put_decimal_ull(m, ' ', mm->env_end);
+	} else
+		seq_printf(m, " 0 0 0 0 0 0 0");
+
+	if (permitted)
+		seq_put_decimal_ll(m, ' ', task->exit_code);
+	else
+		seq_put_decimal_ll(m, ' ', 0);
+
 	seq_putc(m, '\n');
 	if (mm)
 		mmput(mm);
Acked-by on v1 3/4
#4 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 · Cyrill Gorcunov

We would like to have an ability to restore command line arguments and program environment pointers but first we need to obtain them somehow. Thus we put these values into /proc/$pid/stat. The exit_code is needed to restore zombie tasks.

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

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

In reply to Cyrill Gorcunov

During checkpoint we dump whole process memory to a file and the dump includes process stack memory. But among stack data itself, the stack carries additional parameters such as command line arguments, environment data and auxiliary vector.

So when we do restore procedure and once we've restored stack data itself we need to setup mm_struct::arg_start/end, env_start/end, so restored process would be able to find command line arguments and environment data it had at checkpoint time. The same applies to auxiliary vector.

For this reason additional PR_SET_MM_(ARG_START | ARG_END | ENV_START | ENV_END | AUXV) codes are introduced.

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          |  105 +++++++++++++++++++++++++++++++++++---------------
 2 files changed, 80 insertions(+), 30 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 +75 -30

156 lines not on this page · raw message

#6 lore raw

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

Quoted 5 lines · Cyrill Gorcunov

+       case PR_SET_MM_AUXV: {
+               unsigned long user_auxv[AT_VECTOR_SIZE]; +
+               if (arg4 > sizeof(mm->saved_auxv))
+                       goto out;

While these are both AT_VECTOR_SIZE, I think it might be better to use sizeof(mm->saved_auxv) instead of AT_VECTOR_SIZE, just so that they can never get out sync and there's a single reference for the size.

-Kees

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

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

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

+       case PR_SET_MM_AUXV: {
+               unsigned long user_auxv[AT_VECTOR_SIZE]; +
+               if (arg4 > sizeof(mm->saved_auxv))
+                       goto out;

While these are both AT_VECTOR_SIZE, I think it might be better to use sizeof(mm->saved_auxv) instead of AT_VECTOR_SIZE, just so that they can never get out sync and there's a single reference for the size.

I suppose you meant ARRAY_SIZE rather since plain sizeof will give you the summary size in bytes, but I think I have better idea -- lets put BUILD_BUG_ON here, like below.

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

During checkpoint we dump whole process memory to a file and the dump includes process stack memory. But among stack data itself, the stack carries additional parameters such as command line arguments, environment data and auxiliary vector.

So when we do restore procedure and once we've restored stack data itself we need to setup mm_struct::arg_start/end, env_start/end, so restored process would be able to find command line arguments and environment data it had at checkpoint time. The same applies to auxiliary vector.

For this reason additional PR_SET_MM_(ARG_START | ARG_END | ENV_START | ENV_END | AUXV) codes are introduced.

v2: Add BUILD_BUG_ON guard

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          |  107 +++++++++++++++++++++++++++++++++++---------------
 2 files changed, 82 insertions(+), 30 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 +77 -30

158 lines not on this page · raw message

Acked-by
#8 lore raw

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

Quoted 8 lines · Cyrill Gorcunov
Quoted 7 lines · Kees Cook
Quoted 5 lines · Cyrill Gorcunov

+       case PR_SET_MM_AUXV: {
+               unsigned long user_auxv[AT_VECTOR_SIZE]; +
+               if (arg4 > sizeof(mm->saved_auxv))
+                       goto out;

Quoted 8 lines
Quoted 4 lines

While these are both AT_VECTOR_SIZE, I think it might be better to use sizeof(mm->saved_auxv) instead of AT_VECTOR_SIZE, just so that they can never get out sync and there's a single reference for the size.

I suppose you meant ARRAY_SIZE rather since plain sizeof will give you the summary size in bytes, but I think I have better idea -- lets put BUILD_BUG_ON here, like below.

Ah, cool. Works for me. :)

-Kees

Signature · 2 lines
Kees Cook
ChromeOS Security