#include <linux/netdevice.h>
 #include <linux/if_vlan.h>
 #include <linux/filter.h>
+#include <linux/random.h>
 #include <asm/cacheflush.h>
 #include <asm/processor.h>
 #include <asm/facility.h>
        return -1;
 }
 
+/*
+ * Note: for security reasons, bpf code will follow a randomly
+ *      sized amount of illegal instructions.
+ */
+struct bpf_binary_header {
+       unsigned int pages;
+       u8 image[];
+};
+
+static struct bpf_binary_header *bpf_alloc_binary(unsigned int bpfsize,
+                                                 u8 **image_ptr)
+{
+       struct bpf_binary_header *header;
+       unsigned int sz, hole;
+
+       /* Most BPF filters are really small, but if some of them fill a page,
+        * allow at least 128 extra bytes for illegal instructions.
+        */
+       sz = round_up(bpfsize + sizeof(*header) + 128, PAGE_SIZE);
+       header = module_alloc(sz);
+       if (!header)
+               return NULL;
+       memset(header, 0, sz);
+       header->pages = sz / PAGE_SIZE;
+       hole = sz - bpfsize + sizeof(*header);
+       /* Insert random number of illegal instructions before BPF code
+        * and make sure the first instruction starts at an even address.
+        */
+       *image_ptr = &header->image[(prandom_u32() % hole) & -2];
+       return header;
+}
+
 void bpf_jit_compile(struct sk_filter *fp)
 {
+       struct bpf_binary_header *header = NULL;
        unsigned long size, prg_len, lit_len;
        struct bpf_jit jit, cjit;
        unsigned int *addrs;
                        size = prg_len + lit_len;
                        if (size >= BPF_SIZE_MAX)
                                goto out;
-                       jit.start = module_alloc(size);
-                       if (!jit.start)
+                       header = bpf_alloc_binary(size, &jit.start);
+                       if (!header)
                                goto out;
                        jit.prg = jit.mid = jit.start + prg_len;
                        jit.lit = jit.end = jit.start + prg_len + lit_len;
                if (jit.start)
                        print_fn_code(jit.start, jit.mid - jit.start);
        }
-       if (jit.start)
+       if (jit.start) {
+               set_memory_ro((unsigned long)header, header->pages);
                fp->bpf_func = (void *) jit.start;
+       }
 out:
        kfree(addrs);
 }
 
 void bpf_jit_free(struct sk_filter *fp)
 {
-       if (fp->bpf_func != sk_run_filter)
-               module_free(NULL, fp->bpf_func);
+       unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
+       struct bpf_binary_header *header = (void *)addr;
+
+       if (fp->bpf_func == sk_run_filter)
+               return;
+       set_memory_rw(addr, header->pages);
+       module_free(NULL, header);
 }