|
@@ -991,8 +991,8 @@ out_err:
|
|
|
return ERR_PTR(err);
|
|
|
}
|
|
|
|
|
|
-struct bpf_prog *bpf_prepare_filter(struct bpf_prog *fp,
|
|
|
- bpf_aux_classic_check_t trans)
|
|
|
+static struct bpf_prog *bpf_prepare_filter(struct bpf_prog *fp,
|
|
|
+ bpf_aux_classic_check_t trans)
|
|
|
{
|
|
|
int err;
|
|
|
|
|
@@ -1074,6 +1074,53 @@ int bpf_prog_create(struct bpf_prog **pfp, struct sock_fprog_kern *fprog)
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(bpf_prog_create);
|
|
|
|
|
|
+/**
|
|
|
+ * bpf_prog_create_from_user - create an unattached filter from user buffer
|
|
|
+ * @pfp: the unattached filter that is created
|
|
|
+ * @fprog: the filter program
|
|
|
+ * @trans: post-classic verifier transformation handler
|
|
|
+ *
|
|
|
+ * 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)
|
|
|
+{
|
|
|
+ unsigned int fsize = bpf_classic_proglen(fprog);
|
|
|
+ struct bpf_prog *fp;
|
|
|
+
|
|
|
+ /* Make sure new filter is there and in the right amounts. */
|
|
|
+ if (fprog->filter == NULL)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ fp = bpf_prog_alloc(bpf_prog_size(fprog->len), 0);
|
|
|
+ if (!fp)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ if (copy_from_user(fp->insns, fprog->filter, fsize)) {
|
|
|
+ __bpf_prog_free(fp);
|
|
|
+ return -EFAULT;
|
|
|
+ }
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ /* bpf_prepare_filter() already takes care of freeing
|
|
|
+ * memory in case something goes wrong.
|
|
|
+ */
|
|
|
+ fp = bpf_prepare_filter(fp, trans);
|
|
|
+ if (IS_ERR(fp))
|
|
|
+ return PTR_ERR(fp);
|
|
|
+
|
|
|
+ *pfp = fp;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
void bpf_prog_destroy(struct bpf_prog *fp)
|
|
|
{
|
|
|
__bpf_prog_release(fp);
|