Messages in this thread | | | Subject | Re: [PATCH RFC] pidns: introduce syscall getvpid | From | Konstantin Khlebnikov <> | Date | Tue, 15 Sep 2015 18:01:38 +0300 |
| |
On 15.09.2015 17:27, Eric W. Biederman wrote: > Konstantin Khlebnikov <khlebnikov@yandex-team.ru> writes: > >> pid_t getvpid(pid_t pid, pid_t source, pid_t target); >> >> This syscall converts pid from one pid-ns into pid in another pid-ns: >> it takes @pid in namespace of @source task (zero for current) and >> returns related pid in namespace of @target task (zero for current too). >> If pid is unreachable from target pid-ns then it returns zero. > > This interface as presented is inherently racy. It would be better > if source and target were file descriptors referring to the namespaces > you wish to translate between.
Yep, it's racy. As well as any operation with non-child pids. With file descriptors for source/target result will be racy anyway.
> >> Such conversion is required for interaction between processes from >> different pid-namespaces. For example when system service talks with >> client from isolated container via socket about task in container: > > Sockets are already supported. At least the metadata of sockets is. > > Maybe we need this but I am not convinced of it's utility. > > What are you trying to do that motivates this?
I'm working on hierarchical container management system which allows to create and control nested sub-containers from containers ( https://github.com/yandex/porto ). Main server works in host and have to interact with all levels of nested namespaces. This syscall makes some operations much easier: server must remember only pid in host pid namespace and convert it into right vpid on demand.
> > Eric > > >> getvpid(pid, client_pid, 0) -> pid in our pid namespace >> getvpid(pid, 0, client_pid) -> pid in client pid namespace >> >> Also service can get pid of init task and match it with container: >> >> getvpid(1, client_pid, 0) -> pid of init task for client_pid >> >> Seems like gdb and strace could use this too for converting pids of >> newly forked tasks (IIRR they get pid from %rax) into pid from >> correct namespace for further interaction. >> >> As a bonus syscall getvpid can compare pid namespaces and >> test isolation without mounted procfs: >> >> getvpid(1, 0, pid) == 0 -> pid in our sub-pid-namespace >> getvpid(1, 0, pid) == 1 -> pid in our pid-namespace >> getvpid(1, pid1, pid2) == 0 -> pid1 isolated from pid2 >> getvpid(1, pid1, pid2) == 1 -> tasks are in one pid-namespace >> getvpid(1, pid1, pid2) > 1 -> pid1 is in sub-pidns of pid2 >> >> Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> >> --- >> arch/x86/entry/syscalls/syscall_32.tbl | 1 + >> arch/x86/entry/syscalls/syscall_64.tbl | 1 + >> include/linux/syscalls.h | 1 + >> kernel/pid.c | 36 ++++++++++++++++++++++++++++++++ >> 4 files changed, 39 insertions(+) >> >> diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl >> index 7663c455b9f6..dadb55d42fc9 100644 >> --- a/arch/x86/entry/syscalls/syscall_32.tbl >> +++ b/arch/x86/entry/syscalls/syscall_32.tbl >> @@ -382,3 +382,4 @@ >> 373 i386 shutdown sys_shutdown >> 374 i386 userfaultfd sys_userfaultfd >> 375 i386 membarrier sys_membarrier >> +376 i386 getvpid sys_getvpid >> diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl >> index 278842fdf1f6..0338f2eb3b7c 100644 >> --- a/arch/x86/entry/syscalls/syscall_64.tbl >> +++ b/arch/x86/entry/syscalls/syscall_64.tbl >> @@ -331,6 +331,7 @@ >> 322 64 execveat stub_execveat >> 323 common userfaultfd sys_userfaultfd >> 324 common membarrier sys_membarrier >> +325 common getvpid sys_getvpid >> >> # >> # x32-specific system call numbers start at 512 to avoid cache impact >> diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h >> index a460e2ef2843..3405c30999e3 100644 >> --- a/include/linux/syscalls.h >> +++ b/include/linux/syscalls.h >> @@ -222,6 +222,7 @@ asmlinkage long sys_nanosleep(struct timespec __user *rqtp, struct timespec __us >> asmlinkage long sys_alarm(unsigned int seconds); >> asmlinkage long sys_getpid(void); >> asmlinkage long sys_getppid(void); >> +asmlinkage long sys_getvpid(pid_t pid, pid_t source, pid_t target); >> asmlinkage long sys_getuid(void); >> asmlinkage long sys_geteuid(void); >> asmlinkage long sys_getgid(void); >> diff --git a/kernel/pid.c b/kernel/pid.c >> index ca368793808e..caa676ff7364 100644 >> --- a/kernel/pid.c >> +++ b/kernel/pid.c >> @@ -567,6 +567,42 @@ struct pid *find_ge_pid(int nr, struct pid_namespace *ns) >> return pid; >> } >> >> +/** >> + * sys_getvpid - convert pid from one pid-namespace into pid from another >> + * >> + * @pid - pid of requested task >> + * @source - pid of task in source pid-namespace, zero for current >> + * @target - pid of task in target pid-namespace, zero for current >> + * >> + * Returns pid from target pid-ns or zero if pid is unreachable. >> + * Returns -ESRCH if some of pids are not found. >> + */ >> +SYSCALL_DEFINE3(getvpid, pid_t, pid, pid_t, source, pid_t, target) >> +{ >> +#ifdef CONFIG_PID_NS >> + struct pid_namespace *current_ns = task_active_pid_ns(current); >> + struct pid_namespace *source_ns = current_ns, *target_ns = current_ns; >> + struct pid *task_pid; >> + pid_t result = -ESRCH; >> + >> + rcu_read_lock(); >> + if (source) >> + source_ns = ns_of_pid(find_pid_ns(source, current_ns)); >> + if (target) >> + target_ns = ns_of_pid(find_pid_ns(target, current_ns)); >> + if (source_ns && target_ns) { >> + task_pid = find_pid_ns(pid, source_ns); >> + if (task_pid) >> + result = pid_nr_ns(task_pid, target_ns); >> + } >> + rcu_read_unlock(); >> + >> + return result; >> +#else >> + return pid; >> +#endif /* CONFIG_PID_NS */ >> +} >> + >> /* >> * The pid hash table is scaled according to the amount of memory in the >> * machine. From a minimum of 16 slots up to 4096 slots at one gigabyte or
-- Konstantin
| |