the filter string; the error message should still be useful though
 even without more accurate position info.
 
+5.2.1 Filter limitations
+------------------------
+
+If a filter is placed on a string pointer ``(char *)`` that does not point
+to a string on the ring buffer, but instead points to kernel or user space
+memory, then, for safety reasons, at most 1024 bytes of the content is
+copied onto a temporary buffer to do the compare. If the copy of the memory
+faults (the pointer points to memory that should not be accessed), then the
+string compare will be treated as not matching.
+
 5.3 Clearing filters
 --------------------
 
 
  * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
  */
 
+#include <linux/uaccess.h>
 #include <linux/module.h>
 #include <linux/ctype.h>
 #include <linux/mutex.h>
 DEFINE_EQUALITY_PRED(16);
 DEFINE_EQUALITY_PRED(8);
 
+/* user space strings temp buffer */
+#define USTRING_BUF_SIZE       1024
+
+struct ustring_buffer {
+       char            buffer[USTRING_BUF_SIZE];
+};
+
+static __percpu struct ustring_buffer *ustring_per_cpu;
+
+static __always_inline char *test_string(char *str)
+{
+       struct ustring_buffer *ubuf;
+       char __user *ustr;
+       char *kstr;
+
+       if (!ustring_per_cpu)
+               return NULL;
+
+       ubuf = this_cpu_ptr(ustring_per_cpu);
+       kstr = ubuf->buffer;
+
+       /*
+        * We use TASK_SIZE to denote user or kernel space, but this will
+        * not work for all architectures. If it picks the wrong one, it may
+        * just fail the filter (but will not bug).
+        *
+        * TODO: Have a way to properly denote which one this is for.
+        */
+       if (likely((unsigned long)str >= TASK_SIZE)) {
+               /* For safety, do not trust the string pointer */
+               if (!strncpy_from_kernel_nofault(kstr, str, USTRING_BUF_SIZE))
+                       return NULL;
+       } else {
+               /* user space address? */
+               ustr = (char __user *)str;
+               if (!strncpy_from_user_nofault(kstr, ustr, USTRING_BUF_SIZE))
+                       return NULL;
+       }
+       return kstr;
+}
+
 /* Filter predicate for fixed sized arrays of characters */
 static int filter_pred_string(struct filter_pred *pred, void *event)
 {
 static int filter_pred_pchar(struct filter_pred *pred, void *event)
 {
        char **addr = (char **)(event + pred->offset);
+       char *str;
        int cmp, match;
-       int len = strlen(*addr) + 1;    /* including tailing '\0' */
+       int len;
 
-       cmp = pred->regex.match(*addr, &pred->regex, len);
+       str = test_string(*addr);
+       if (!str)
+               return 0;
+
+       len = strlen(str) + 1;  /* including tailing '\0' */
+       cmp = pred->regex.match(str, &pred->regex, len);
 
        match = cmp ^ pred->not;
 
                        pred->fn = filter_pred_strloc;
                } else if (field->filter_type == FILTER_RDYN_STRING)
                        pred->fn = filter_pred_strrelloc;
-               else
+               else {
+
+                       if (!ustring_per_cpu) {
+                               /* Once allocated, keep it around for good */
+                               ustring_per_cpu = alloc_percpu(struct ustring_buffer);
+                               if (!ustring_per_cpu)
+                                       goto err_mem;
+                       }
+
                        pred->fn = filter_pred_pchar;
+               }
                /* go past the last quote */
                i++;
 
 err_free:
        kfree(pred);
        return -EINVAL;
+err_mem:
+       kfree(pred);
+       return -ENOMEM;
 }
 
 enum {