[PATCH v5 1/6] capabilities: Introduce CAP_CHECKPOINT_RESTORE
Christian Brauner
christian.brauner at ubuntu.com
Wed Jul 15 15:06:47 UTC 2020
On Wed, Jul 15, 2020 at 04:49:49PM +0200, Adrian Reber wrote:
> This patch introduces CAP_CHECKPOINT_RESTORE, a new capability facilitating
> checkpoint/restore for non-root users.
>
> Over the last years, The CRIU (Checkpoint/Restore In Userspace) team has been
> asked numerous times if it is possible to checkpoint/restore a process as
> non-root. The answer usually was: 'almost'.
>
> The main blocker to restore a process as non-root was to control the PID of the
> restored process. This feature available via the clone3 system call, or via
> /proc/sys/kernel/ns_last_pid is unfortunately guarded by CAP_SYS_ADMIN.
>
> In the past two years, requests for non-root checkpoint/restore have increased
> due to the following use cases:
> * Checkpoint/Restore in an HPC environment in combination with a resource
> manager distributing jobs where users are always running as non-root.
> There is a desire to provide a way to checkpoint and restore long running
> jobs.
> * Container migration as non-root
> * We have been in contact with JVM developers who are integrating
> CRIU into a Java VM to decrease the startup time. These checkpoint/restore
> applications are not meant to be running with CAP_SYS_ADMIN.
>
> We have seen the following workarounds:
> * Use a setuid wrapper around CRIU:
> See https://github.com/FredHutch/slurm-examples/blob/master/checkpointer/lib/checkpointer/checkpointer-suid.c
> * Use a setuid helper that writes to ns_last_pid.
> Unfortunately, this helper delegation technique is impossible to use with
> clone3, and is thus prone to races.
> See https://github.com/twosigma/set_ns_last_pid
> * Cycle through PIDs with fork() until the desired PID is reached:
> This has been demonstrated to work with cycling rates of 100,000 PIDs/s
> See https://github.com/twosigma/set_ns_last_pid
> * Patch out the CAP_SYS_ADMIN check from the kernel
> * Run the desired application in a new user and PID namespace to provide
> a local CAP_SYS_ADMIN for controlling PIDs. This technique has limited use in
> typical container environments (e.g., Kubernetes) as /proc is
> typically protected with read-only layers (e.g., /proc/sys) for hardening
> purposes. Read-only layers prevent additional /proc mounts (due to proc's
> SB_I_USERNS_VISIBLE property), making the use of new PID namespaces limited as
> certain applications need access to /proc matching their PID namespace.
>
> The introduced capability allows to:
> * Control PIDs when the current user is CAP_CHECKPOINT_RESTORE capable
> for the corresponding PID namespace via ns_last_pid/clone3.
> * Open files in /proc/pid/map_files when the current user is
> CAP_CHECKPOINT_RESTORE capable in the root namespace, useful for recovering
> files that are unreachable via the file system such as deleted files, or memfd
> files.
>
> See corresponding selftest for an example with clone3().
>
> Signed-off-by: Adrian Reber <areber at redhat.com>
> Signed-off-by: Nicolas Viennot <Nicolas.Viennot at twosigma.com>
> ---
Thanks!
This looks good now.
Acked-by: Christian Brauner <christian.brauner at ubuntu.com>
> include/linux/capability.h | 6 ++++++
> include/uapi/linux/capability.h | 9 ++++++++-
> security/selinux/include/classmap.h | 5 +++--
> 3 files changed, 17 insertions(+), 3 deletions(-)
>
> diff --git a/include/linux/capability.h b/include/linux/capability.h
> index b4345b38a6be..1e7fe311cabe 100644
> --- a/include/linux/capability.h
> +++ b/include/linux/capability.h
> @@ -261,6 +261,12 @@ static inline bool bpf_capable(void)
> return capable(CAP_BPF) || capable(CAP_SYS_ADMIN);
> }
>
> +static inline bool checkpoint_restore_ns_capable(struct user_namespace *ns)
> +{
> + return ns_capable(ns, CAP_CHECKPOINT_RESTORE) ||
> + ns_capable(ns, CAP_SYS_ADMIN);
> +}
> +
> /* audit system wants to get cap info from files as well */
> extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
>
> diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h
> index 48ff0757ae5e..395dd0df8d08 100644
> --- a/include/uapi/linux/capability.h
> +++ b/include/uapi/linux/capability.h
> @@ -408,7 +408,14 @@ struct vfs_ns_cap_data {
> */
> #define CAP_BPF 39
>
> -#define CAP_LAST_CAP CAP_BPF
> +
> +/* Allow checkpoint/restore related operations */
> +/* Allow PID selection during clone3() */
> +/* Allow writing to ns_last_pid */
> +
> +#define CAP_CHECKPOINT_RESTORE 40
> +
> +#define CAP_LAST_CAP CAP_CHECKPOINT_RESTORE
>
> #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
>
> diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
> index e54d62d529f1..ba2e01a6955c 100644
> --- a/security/selinux/include/classmap.h
> +++ b/security/selinux/include/classmap.h
> @@ -27,9 +27,10 @@
> "audit_control", "setfcap"
>
> #define COMMON_CAP2_PERMS "mac_override", "mac_admin", "syslog", \
> - "wake_alarm", "block_suspend", "audit_read", "perfmon", "bpf"
> + "wake_alarm", "block_suspend", "audit_read", "perfmon", "bpf", \
> + "checkpoint_restore"
>
> -#if CAP_LAST_CAP > CAP_BPF
> +#if CAP_LAST_CAP > CAP_CHECKPOINT_RESTORE
> #error New capability defined, please update COMMON_CAP2_PERMS.
> #endif
>
> --
> 2.26.2
>
More information about the Linux-security-module-archive
mailing list