/* * net/sched/em_text.c Textsearch ematch * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * Authors: Thomas Graf */ #include #include #include #include #include #include #include #include #include struct text_match { u16 from_offset; u16 to_offset; u8 from_layer; u8 to_layer; struct ts_config *config; }; #define EM_TEXT_PRIV(m) ((struct text_match *) (m)->data) static int em_text_match(struct sk_buff *skb, struct tcf_ematch *m, struct tcf_pkt_info *info) { struct text_match *tm = EM_TEXT_PRIV(m); int from, to; from = tcf_get_base_ptr(skb, tm->from_layer) - skb->data; from += tm->from_offset; to = tcf_get_base_ptr(skb, tm->to_layer) - skb->data; to += tm->to_offset; return skb_find_text(skb, from, to, tm->config) != UINT_MAX; } static int em_text_change(struct net *net, void *data, int len, struct tcf_ematch *m) { struct text_match *tm; struct tcf_em_text *conf = data; struct ts_config *ts_conf; int flags = 0; if (len < sizeof(*conf) || len < (sizeof(*conf) + conf->pattern_len)) return -EINVAL; if (conf->from_layer > conf->to_layer) return -EINVAL; if (conf->from_layer == conf->to_layer && conf->from_offset > conf->to_offset) return -EINVAL; retry: ts_conf = textsearch_prepare(conf->algo, (u8 *) conf + sizeof(*conf), conf->pattern_len, GFP_KERNEL, flags); if (flags & TS_AUTOLOAD) rtnl_lock(); if (IS_ERR(ts_conf)) { if (PTR_ERR(ts_conf) == -ENOENT && !(flags & TS_AUTOLOAD)) { rtnl_unlock(); flags |= TS_AUTOLOAD; goto retry; } else return PTR_ERR(ts_conf); } else if (flags & TS_AUTOLOAD) { textsearch_destroy(ts_conf); return -EAGAIN; } tm = kmalloc(sizeof(*tm), GFP_KERNEL); if (tm == NULL) { textsearch_destroy(ts_conf); return -ENOBUFS; } tm->from_offset = conf->from_offset; tm->to_offset = conf->to_offset; tm->from_layer = conf->from_layer; tm->to_layer = conf->to_layer; tm->config = ts_conf; m->datalen = sizeof(*tm); m->data = (unsigned long) tm; return 0; } static void em_text_destroy(struct tcf_ematch *m) { if (EM_TEXT_PRIV(m) && EM_TEXT_PRIV(m)->config) textsearch_destroy(EM_TEXT_PRIV(m)->config); } static int em_text_dump(struct sk_buff *skb, struct tcf_ematch *m) { struct text_match *tm = EM_TEXT_PRIV(m); struct tcf_em_text conf; strncpy(conf.algo, tm->config->ops->name, sizeof(conf.algo) - 1); conf.from_offset = tm->from_offset; conf.to_offset = tm->to_offset; conf.from_layer = tm->from_layer; conf.to_layer = tm->to_layer; conf.pattern_len = textsearch_get_pattern_len(tm->config); conf.pad = 0; if (nla_put_nohdr(skb, sizeof(conf), &conf) < 0) goto nla_put_failure; if (nla_append(skb, conf.pattern_len, textsearch_get_pattern(tm->config)) < 0) goto nla_put_failure; return 0; nla_put_failure: return -1; } static struct tcf_ematch_ops em_text_ops = { .kind = TCF_EM_TEXT, .change = em_text_change, .match = em_text_match, .destroy = em_text_destroy, .dump = em_text_dump, .owner = THIS_MODULE, .link = LIST_HEAD_INIT(em_text_ops.link) }; static int __init init_em_text(void) { return tcf_em_register(&em_text_ops); } static void __exit exit_em_text(void) { tcf_em_unregister(&em_text_ops); } MODULE_LICENSE("GPL"); module_init(init_em_text); module_exit(exit_em_text); MODULE_ALIAS_TCF_EMATCH(TCF_EM_TEXT); /tools/testing/selftests/powerpc/pmu/ebb/trace.h?id=a76a82a3e38c8d3fb6499e3dfaeb0949241ab588'>trace.h
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2017-01-26 16:39:55 +0100
committerIngo Molnar <mingo@kernel.org>2017-01-30 11:41:25 +0100
commita76a82a3e38c8d3fb6499e3dfaeb0949241ab588 (patch)
treeb5bc906278fe1ac66d75de984d26bf59b43b3ed8 /tools/testing/selftests/powerpc/pmu/ebb/trace.h
parent566cf877a1fcb6d6dc0126b076aad062054c2637 (diff)
perf/core: Fix use-after-free bug
Dmitry reported a KASAN use-after-free on event->group_leader. It turns out there's a hole in perf_remove_from_context() due to event_function_call() not calling its function when the task associated with the event is already dead. In this case the event will have been detached from the task, but the grouping will have been retained, such that group operations might still work properly while there are live child events etc. This does however mean that we can miss a perf_group_detach() call when the group decomposes, this in turn can then lead to use-after-free. Fix it by explicitly doing the group detach if its still required. Reported-by: Dmitry Vyukov <dvyukov@google.com> Tested-by: Dmitry Vyukov <dvyukov@google.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Arnaldo Carvalho de Melo <acme@kernel.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: stable@vger.kernel.org # v4.5+ Cc: syzkaller <syzkaller@googlegroups.com> Fixes: 63b6da39bb38 ("perf: Fix perf_event_exit_task() race") Link: http://lkml.kernel.org/r/20170126153955.GD6515@twins.programming.kicks-ass.net Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/testing/selftests/powerpc/pmu/ebb/trace.h')