summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/core/filter.c16
-rw-r--r--net/packet/af_packet.c2
2 files changed, 12 insertions, 6 deletions
diff --git a/net/core/filter.c b/net/core/filter.c
index 53a5036fb32d..da3e5357f138 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -1084,16 +1084,18 @@ EXPORT_SYMBOL_GPL(bpf_prog_create);
* @pfp: the unattached filter that is created
* @fprog: the filter program
* @trans: post-classic verifier transformation handler
+ * @save_orig: save classic BPF program
*
* This function effectively does the same as bpf_prog_create(), only
* that it builds up its insns buffer from user space provided buffer.
* 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,
- bpf_aux_classic_check_t trans)
+ bpf_aux_classic_check_t trans, bool save_orig)
{
unsigned int fsize = bpf_classic_proglen(fprog);
struct bpf_prog *fp;
+ int err;
/* Make sure new filter is there and in the right amounts. */
if (fprog->filter == NULL)
@@ -1109,12 +1111,16 @@ int bpf_prog_create_from_user(struct bpf_prog **pfp, struct sock_fprog *fprog,
}
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;
+ 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
* memory in case something goes wrong.
*/
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index aa4b15c35884..81c900fbc4a4 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1567,7 +1567,7 @@ static int fanout_set_data_cbpf(struct packet_sock *po, char __user *data,
if (copy_from_user(&fprog, data, len))
return -EFAULT;
- ret = bpf_prog_create_from_user(&new, &fprog, NULL);
+ ret = bpf_prog_create_from_user(&new, &fprog, NULL, false);
if (ret)
return ret;