Commit bab18991 authored by Daniel Borkmann's avatar Daniel Borkmann Committed by David S. Miller

bpf, seccomp: prepare for upcoming criu support

The current ongoing effort to dump existing cBPF seccomp filters back
to user space requires to hold the pre-transformed instructions like
we do in case of socket filters from sk_attach_filter() side, so they
can be reloaded in original form at a later point in time by utilities
such as criu.

To prepare for this, simply extend the bpf_prog_create_from_user()
API to hold a flag that tells whether we should store the original
or not. Also, fanout filters could make use of that in future for
things like diag. While fanout filters already use bpf_prog_destroy(),
move seccomp over to them as well to handle original programs when
present.
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Cc: Tycho Andersen <tycho.andersen@canonical.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Tested-by: default avatarTycho Andersen <tycho.andersen@canonical.com>
Acked-by: default avatarAlexei Starovoitov <ast@plumgrid.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0a15afd2
...@@ -411,7 +411,7 @@ typedef int (*bpf_aux_classic_check_t)(struct sock_filter *filter, ...@@ -411,7 +411,7 @@ typedef int (*bpf_aux_classic_check_t)(struct sock_filter *filter,
int bpf_prog_create(struct bpf_prog **pfp, struct sock_fprog_kern *fprog); int bpf_prog_create(struct bpf_prog **pfp, struct sock_fprog_kern *fprog);
int bpf_prog_create_from_user(struct bpf_prog **pfp, struct sock_fprog *fprog, int bpf_prog_create_from_user(struct bpf_prog **pfp, struct sock_fprog *fprog,
bpf_aux_classic_check_t trans); bpf_aux_classic_check_t trans, bool save_orig);
void bpf_prog_destroy(struct bpf_prog *fp); void bpf_prog_destroy(struct bpf_prog *fp);
int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk); int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
......
...@@ -370,7 +370,7 @@ static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog) ...@@ -370,7 +370,7 @@ static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
ret = bpf_prog_create_from_user(&sfilter->prog, fprog, ret = bpf_prog_create_from_user(&sfilter->prog, fprog,
seccomp_check_filter); seccomp_check_filter, false);
if (ret < 0) { if (ret < 0) {
kfree(sfilter); kfree(sfilter);
return ERR_PTR(ret); return ERR_PTR(ret);
...@@ -469,7 +469,7 @@ void get_seccomp_filter(struct task_struct *tsk) ...@@ -469,7 +469,7 @@ void get_seccomp_filter(struct task_struct *tsk)
static inline void seccomp_filter_free(struct seccomp_filter *filter) static inline void seccomp_filter_free(struct seccomp_filter *filter)
{ {
if (filter) { if (filter) {
bpf_prog_free(filter->prog); bpf_prog_destroy(filter->prog);
kfree(filter); kfree(filter);
} }
} }
......
...@@ -1084,16 +1084,18 @@ EXPORT_SYMBOL_GPL(bpf_prog_create); ...@@ -1084,16 +1084,18 @@ EXPORT_SYMBOL_GPL(bpf_prog_create);
* @pfp: the unattached filter that is created * @pfp: the unattached filter that is created
* @fprog: the filter program * @fprog: the filter program
* @trans: post-classic verifier transformation handler * @trans: post-classic verifier transformation handler
* @save_orig: save classic BPF program
* *
* This function effectively does the same as bpf_prog_create(), only * This function effectively does the same as bpf_prog_create(), only
* that it builds up its insns buffer from user space provided buffer. * that it builds up its insns buffer from user space provided buffer.
* It also allows for passing a bpf_aux_classic_check_t handler. * It also allows for passing a bpf_aux_classic_check_t handler.
*/ */
int bpf_prog_create_from_user(struct bpf_prog **pfp, struct sock_fprog *fprog, int bpf_prog_create_from_user(struct bpf_prog **pfp, struct sock_fprog *fprog,
bpf_aux_classic_check_t trans) bpf_aux_classic_check_t trans, bool save_orig)
{ {
unsigned int fsize = bpf_classic_proglen(fprog); unsigned int fsize = bpf_classic_proglen(fprog);
struct bpf_prog *fp; struct bpf_prog *fp;
int err;
/* Make sure new filter is there and in the right amounts. */ /* Make sure new filter is there and in the right amounts. */
if (fprog->filter == NULL) if (fprog->filter == NULL)
...@@ -1109,12 +1111,16 @@ int bpf_prog_create_from_user(struct bpf_prog **pfp, struct sock_fprog *fprog, ...@@ -1109,12 +1111,16 @@ int bpf_prog_create_from_user(struct bpf_prog **pfp, struct sock_fprog *fprog,
} }
fp->len = fprog->len; fp->len = fprog->len;
/* Since unattached filters are not copied back to user
* space through sk_get_filter(), we do not need to hold
* a copy here, and can spare us the work.
*/
fp->orig_prog = NULL; fp->orig_prog = NULL;
if (save_orig) {
err = bpf_prog_store_orig_filter(fp, fprog);
if (err) {
__bpf_prog_free(fp);
return -ENOMEM;
}
}
/* bpf_prepare_filter() already takes care of freeing /* bpf_prepare_filter() already takes care of freeing
* memory in case something goes wrong. * memory in case something goes wrong.
*/ */
......
...@@ -1567,7 +1567,7 @@ static int fanout_set_data_cbpf(struct packet_sock *po, char __user *data, ...@@ -1567,7 +1567,7 @@ static int fanout_set_data_cbpf(struct packet_sock *po, char __user *data,
if (copy_from_user(&fprog, data, len)) if (copy_from_user(&fprog, data, len))
return -EFAULT; return -EFAULT;
ret = bpf_prog_create_from_user(&new, &fprog, NULL); ret = bpf_prog_create_from_user(&new, &fprog, NULL, false);
if (ret) if (ret)
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment