RE: [PATCH] capabilities: Introduce CAP_RESTORE

Nicolas Viennot
2020-05-27T18:06:00Z

> > Also in this thread Kamil mentioned that they also need calling prctl
> > with PR_SET_MM during restore in their production setup.
>
> We're using that as well but it really feels like this:
>
> prctl_map = (struct prctl_mm_map){
> .start_code = start_code,
> .end_code = end_code,
> .start_stack = start_stack,
> .start_data = start_data,
> .end_data = end_data,
> .start_brk = start_brk,
> .brk = brk_val,
> .arg_start = arg_start,
> .arg_end = arg_end,
> .env_start = env_start,
> .env_end = env_end,
> .auxv = NULL,
> .auxv_size = 0,
> .exe_fd = -1,
> };
>
> should belong under ns_capable(CAP_SYS_ADMIN). Why is that necessary to relax?

When the prctl(PR_SET_MM_MAP...), the only privileged operation is to change the symlink of /proc/self/exe via set_mm_exe_file().
See https://github.com/torvalds/linux/blob/444fc5cde64330661bf59944c43844e7d4c2ccd8/kernel/sys.c#L2001-L2004
It needs CAP_SYS_ADMIN of the current namespace.

I would argue that setting the current process exe file check should just be reduced to a "can you ptrace a children" check.
Here's why: any process can masquerade into another executable with ptrace.
One can fork a child, ptrace it, have the child execve("target_exe"), then replace its memory content with an arbitrary program.
With CRIU's libcompel parasite mechanism (https://criu.org/Compel) this is fairly easy to implement.
In fact, we could modify CRIU to do just that (but with a fair amount of efforts due to the way CRIU is written),
and not rely on being able to SET_MM_EXE_FILE via prctl(). In turn, that would give an easy way to masquerade any process
into another one, provided that one can ptrace a child.

When not using PR_SET_MM_MAP, but using SET_MM_EXE_FILE, the CAP_RESOURCES at the root namespace level is required:
https://github.com/torvalds/linux/blob/444fc5cde64330661bf59944c43844e7d4c2ccd8/kernel/sys.c#L2109
This seems inconsistent. Also for some reason changing auxv is not privileged if using prctl via the MM_MAP mechanism, but is privileged otherwise.