A pile in c/r sake v2
Subsystems (5)
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
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.
--- 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
@@ -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
@@ -3350,6 +3350,9 @@ static const struct pid_entry tid_base_sONE ("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
@@ -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;
PATCH 2/4 syscalls, x86: Add __NR_kcmp syscall v7
In reply to Cyrill GorcunovWhile 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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -857,4 +857,6 @@ asmlinkage long sys_process_vm_writev(piunsigned 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
@@ -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
@@ -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
@@ -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
@@ -1,6 +1,6 @@ #!/bin/bash -TARGETS=breakpoints +TARGETS="breakpoints kcmp" for TARGET in $TARGETS do
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 GorcunovWe 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.
--- Documentation/filesystems/proc.txt | 5 +++++ fs/proc/array.c | 20 +++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-)
Documentation/filesystems/proc.txt +5 -0
@@ -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
@@ -508,9 +508,23 @@ static int do_task_stat(struct seq_fileseq_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);
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. Theexit_codeis needed to restore zombie tasks.Signed-off-by Cyrill Gorcunov <[email protected]>
Signature · 2 lines
Kees Cook ChromeOS Security
PATCH 4/4 c/r: prctl: Extend PR_SET_MM to set up more mm_struct entries
In reply to Cyrill GorcunovDuring 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.
--- include/linux/prctl.h | 5 ++ kernel/sys.c | 105 +++++++++++++++++++++++++++++++++++--------------- 2 files changed, 80 insertions(+), 30 deletions(-)
include/linux/prctl.h +5 -0
@@ -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
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
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 usesizeof(mm->saved_auxv)instead ofAT_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
--- include/linux/prctl.h | 5 ++ kernel/sys.c | 107 +++++++++++++++++++++++++++++++++++--------------- 2 files changed, 82 insertions(+), 30 deletions(-)
include/linux/prctl.h +5 -0
@@ -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
Kees Cook
Acked-byRe: [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 usesizeof(mm->saved_auxv)instead ofAT_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_SIZErather since plain sizeof will give you the summary size in bytes, but I think I have better idea -- lets putBUILD_BUG_ONhere, like below.
Ah, cool. Works for me. :)
-Kees
Signature · 2 lines
Kees Cook ChromeOS Security