struct bpf_prog_aux {
        atomic_t refcnt;
        u32 used_map_cnt;
+       u32 max_ctx_offset;
        const struct bpf_verifier_ops *ops;
        struct bpf_map **used_maps;
        struct bpf_prog *prog;
 
                              int is_signed, int filter_type);
 extern int trace_add_event_call(struct trace_event_call *call);
 extern int trace_remove_event_call(struct trace_event_call *call);
+extern int trace_event_get_offsets(struct trace_event_call *call);
 
 #define is_signed_type(type)   (((type)(-1)) < (type)1)
 
 
                            enum bpf_access_type t)
 {
        if (env->prog->aux->ops->is_valid_access &&
-           env->prog->aux->ops->is_valid_access(off, size, t))
+           env->prog->aux->ops->is_valid_access(off, size, t)) {
+               /* remember the offset of last byte accessed in ctx */
+               if (env->prog->aux->max_ctx_offset < off + size)
+                       env->prog->aux->max_ctx_offset = off + size;
                return 0;
+       }
 
        verbose("invalid bpf_context access off=%d size=%d\n", off, size);
        return -EACCES;
 
                return -EINVAL;
        }
 
+       if (is_tracepoint) {
+               int off = trace_event_get_offsets(event->tp_event);
+
+               if (prog->aux->max_ctx_offset > off) {
+                       bpf_prog_put(prog);
+                       return -EACCES;
+               }
+       }
        event->tp_event->prog = prog;
 
        return 0;
 
        }
 }
 
+/*
+ * run-time version of trace_event_get_offsets_<call>() that returns the last
+ * accessible offset of trace fields excluding __dynamic_array bytes
+ */
+int trace_event_get_offsets(struct trace_event_call *call)
+{
+       struct ftrace_event_field *tail;
+       struct list_head *head;
+
+       head = trace_get_fields(call);
+       /*
+        * head->next points to the last field with the largest offset,
+        * since it was added last by trace_define_field()
+        */
+       tail = list_first_entry(head, struct ftrace_event_field, link);
+       return tail->offset + tail->size;
+}
+
 int trace_event_raw_init(struct trace_event_call *call)
 {
        int id;