From: Sargun Dhillon <sargun@xxxxxxxxxxx> This extends the the ptrace API to allow fetching eBPF seccomp filters attached to programs. This is to enable checkpoint / restore cases. The user will have to use the traditional PTRACE_SECCOMP_GET_FILTER API call, and if they get an invalid medium type error they can switch over to the eBPF variant of the API -- PTRACE_SECCOMP_GET_FILTER_EXTENDED. Signed-off-by: Sargun Dhillon <sargun@xxxxxxxxx> --- include/linux/seccomp.h | 12 ++++++++++++ include/uapi/linux/ptrace.h | 5 +++-- kernel/ptrace.c | 3 +++ kernel/seccomp.c | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h index c723a5c4e3ff..97fdbcffacc2 100644 --- a/include/linux/seccomp.h +++ b/include/linux/seccomp.h @@ -110,4 +110,16 @@ static inline long seccomp_get_metadata(struct task_struct *task, return -EINVAL; } #endif /* CONFIG_SECCOMP_FILTER && CONFIG_CHECKPOINT_RESTORE */ +#if defined(CONFIG_SECCOMP_FILTER_EXTENDED) && defined(CONFIG_CHECKPOINT_RESTORE) +extern long seccomp_get_filter_extended(struct task_struct *task, + unsigned long n, + void __user *data); +#else +static inline long seccomp_get_filter_extended(struct task_struct *task, + unsigned long n, + void __user *data) +{ + return -EINVAL; +} +#endif /* CONFIG_SECCOMP_FILTER_EXTENDED && CONFIG_CHECKPOINT_RESTORE */ #endif /* _LINUX_SECCOMP_H */ diff --git a/include/uapi/linux/ptrace.h b/include/uapi/linux/ptrace.h index e46d82b91166..c619eb46b9d9 100644 --- a/include/uapi/linux/ptrace.h +++ b/include/uapi/linux/ptrace.h @@ -65,8 +65,9 @@ struct ptrace_peeksiginfo_args { #define PTRACE_GETSIGMASK 0x420a #define PTRACE_SETSIGMASK 0x420b -#define PTRACE_SECCOMP_GET_FILTER 0x420c -#define PTRACE_SECCOMP_GET_METADATA 0x420d +#define PTRACE_SECCOMP_GET_FILTER 0x420c +#define PTRACE_SECCOMP_GET_METADATA 0x420d +#define PTRACE_SECCOMP_GET_FILTER_EXTENDED 0x420e struct seccomp_metadata { unsigned long filter_off; /* Input: which filter */ diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 21fec73d45d4..90c62f9e1a55 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -1096,6 +1096,9 @@ int ptrace_request(struct task_struct *child, long request, ret = seccomp_get_metadata(child, addr, datavp); break; + case PTRACE_SECCOMP_GET_FILTER_EXTENDED: + ret = seccomp_get_filter_extended(child, addr, datavp); + default: break; } diff --git a/kernel/seccomp.c b/kernel/seccomp.c index b30dd25c1cb8..931a13a8cd63 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -1155,6 +1155,43 @@ long seccomp_get_metadata(struct task_struct *task, } #endif +#if defined(CONFIG_SECCOMP_FILTER_EXTENDED) && defined(CONFIG_CHECKPOINT_RESTORE) +long seccomp_get_filter_extended(struct task_struct *task, + unsigned long filter_off, + void __user *data) +{ + struct seccomp_filter *filter; + struct bpf_prog *prog; + long ret; + + if (!capable(CAP_SYS_ADMIN) || + current->seccomp.mode != SECCOMP_MODE_DISABLED) { + return -EACCES; + } + + filter = get_nth_filter(task, filter_off); + if (IS_ERR(filter)) + return PTR_ERR(filter); + + if (bpf_prog_was_classic(filter->prog)) { + ret = -EMEDIUMTYPE; + goto out; + } + prog = bpf_prog_inc_not_zero(filter->prog); + if (IS_ERR(prog)) { + ret = PTR_ERR(prog); + goto out; + } + + ret = bpf_prog_new_fd(filter->prog); + if (ret < 0) + bpf_prog_put(prog); +out: + __put_seccomp_filter(filter); + return ret; +} +#endif + #ifdef CONFIG_SYSCTL /* Human readable action names for friendly sysctl interaction */ -- 2.14.1 _______________________________________________ Containers mailing list Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linuxfoundation.org/mailman/listinfo/containers