kernel/sys.c: fix compat uname machine
[safe/jmp/linux-2.6] / kernel / trace / trace_events_filter.c
index e27bb6a..88c0b6d 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/ctype.h>
 #include <linux/mutex.h>
 #include <linux/perf_event.h>
+#include <linux/slab.h>
 
 #include "trace.h"
 #include "trace_output.h"
@@ -211,8 +212,9 @@ static int filter_pred_pchar(struct filter_pred *pred, void *event,
 {
        char **addr = (char **)(event + pred->offset);
        int cmp, match;
+       int len = strlen(*addr) + 1;    /* including tailing '\0' */
 
-       cmp = pred->regex.match(*addr, &pred->regex, pred->regex.field_len);
+       cmp = pred->regex.match(*addr, &pred->regex, len);
 
        match = cmp ^ pred->not;
 
@@ -251,7 +253,18 @@ static int filter_pred_none(struct filter_pred *pred, void *event,
        return 0;
 }
 
-/* Basic regex callbacks */
+/*
+ * regex_match_foo - Basic regex callbacks
+ *
+ * @str: the string to be searched
+ * @r:   the regex structure containing the pattern string
+ * @len: the length of the string to be searched (including '\0')
+ *
+ * Note:
+ * - @str might not be NULL-terminated if it's of type DYN_STRING
+ *   or STATIC_STRING
+ */
+
 static int regex_match_full(char *str, struct regex *r, int len)
 {
        if (strncmp(str, r->pattern, len) == 0)
@@ -261,23 +274,24 @@ static int regex_match_full(char *str, struct regex *r, int len)
 
 static int regex_match_front(char *str, struct regex *r, int len)
 {
-       if (strncmp(str, r->pattern, len) == 0)
+       if (strncmp(str, r->pattern, r->len) == 0)
                return 1;
        return 0;
 }
 
 static int regex_match_middle(char *str, struct regex *r, int len)
 {
-       if (strstr(str, r->pattern))
+       if (strnstr(str, r->pattern, len))
                return 1;
        return 0;
 }
 
 static int regex_match_end(char *str, struct regex *r, int len)
 {
-       char *ptr = strstr(str, r->pattern);
+       int strlen = len - 1;
 
-       if (ptr && (ptr[r->len] == 0))
+       if (strlen >= r->len &&
+           memcmp(str + strlen - r->len, r->pattern, r->len) == 0)
                return 1;
        return 0;
 }
@@ -781,10 +795,8 @@ static int filter_add_pred(struct filter_parse_state *ps,
                        pred->regex.field_len = field->size;
                } else if (field->filter_type == FILTER_DYN_STRING)
                        fn = filter_pred_strloc;
-               else {
+               else
                        fn = filter_pred_pchar;
-                       pred->regex.field_len = strlen(pred->regex.pattern);
-               }
        } else {
                if (field->is_signed)
                        ret = strict_strtoll(pred->regex.pattern, 0, &val);
@@ -1231,11 +1243,11 @@ static int replace_system_preds(struct event_subsystem *system,
                                char *filter_string)
 {
        struct ftrace_event_call *call;
-       struct event_filter *filter;
-       int err;
        bool fail = true;
+       int err;
 
        list_for_each_entry(call, &ftrace_events, list) {
+               struct event_filter *filter = call->filter;
 
                if (!call->define_fields)
                        continue;
@@ -1262,7 +1274,7 @@ static int replace_system_preds(struct event_subsystem *system,
 
        if (fail) {
                parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0);
-               return err;
+               return -EINVAL;
        }
        return 0;
 }
@@ -1281,8 +1293,7 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
        if (!strcmp(strstrip(filter_string), "0")) {
                filter_disable_preds(call);
                remove_filter_string(call->filter);
-               mutex_unlock(&event_mutex);
-               return 0;
+               goto out_unlock;
        }
 
        err = -ENOMEM;
@@ -1330,8 +1341,7 @@ int apply_subsystem_event_filter(struct event_subsystem *system,
        if (!strcmp(strstrip(filter_string), "0")) {
                filter_free_subsystem_preds(system);
                remove_filter_string(system->filter);
-               mutex_unlock(&event_mutex);
-               return 0;
+               goto out_unlock;
        }
 
        err = -ENOMEM;
@@ -1362,7 +1372,7 @@ out_unlock:
        return err;
 }
 
-#ifdef CONFIG_EVENT_PROFILE
+#ifdef CONFIG_PERF_EVENTS
 
 void ftrace_profile_free_filter(struct perf_event *event)
 {
@@ -1386,15 +1396,20 @@ int ftrace_profile_set_filter(struct perf_event *event, int event_id,
                if (call->id == event_id)
                        break;
        }
+
+       err = -EINVAL;
        if (!call)
-               return -EINVAL;
+               goto out_unlock;
 
+       err = -EEXIST;
        if (event->filter)
-               return -EEXIST;
+               goto out_unlock;
 
        filter = __alloc_preds();
-       if (IS_ERR(filter))
-               return PTR_ERR(filter);
+       if (IS_ERR(filter)) {
+               err = PTR_ERR(filter);
+               goto out_unlock;
+       }
 
        err = -ENOMEM;
        ps = kzalloc(sizeof(*ps), GFP_KERNEL);
@@ -1419,10 +1434,11 @@ free_preds:
        if (err)
                __free_preds(filter);
 
+out_unlock:
        mutex_unlock(&event_mutex);
 
        return err;
 }
 
-#endif /* CONFIG_EVENT_PROFILE */
+#endif /* CONFIG_PERF_EVENTS */