Commit e90129a6 authored by Brenden Blanco's avatar Brenden Blanco

Enforce limit of 1000 open [uk]probes

The number of open probes has bitten users already, so lets enforce a
limit with a meaningful(ish) message.
Signed-off-by: default avatarBrenden Blanco <bblanco@plumgrid.com>
parent d1a0e7f2
...@@ -36,6 +36,7 @@ KALLSYMS = "/proc/kallsyms" ...@@ -36,6 +36,7 @@ KALLSYMS = "/proc/kallsyms"
ksym_addrs = [] ksym_addrs = []
ksym_names = [] ksym_names = []
ksym_loaded = 0 ksym_loaded = 0
_kprobe_limit = 1000
@atexit.register @atexit.register
def cleanup_kprobes(): def cleanup_kprobes():
...@@ -54,6 +55,12 @@ def cleanup_kprobes(): ...@@ -54,6 +55,12 @@ def cleanup_kprobes():
if tracefile: if tracefile:
tracefile.close() tracefile.close()
def _check_probe_quota(num_new_probes):
if len(open_kprobes) + len(open_uprobes) + num_new_probes > _kprobe_limit:
raise Exception("Number of open probes would exceed quota")
class BPF(object): class BPF(object):
SOCKET_FILTER = 1 SOCKET_FILTER = 1
KPROBE = 2 KPROBE = 2
...@@ -282,8 +289,10 @@ class BPF(object): ...@@ -282,8 +289,10 @@ class BPF(object):
lines = p.communicate()[0].decode().split() lines = p.communicate()[0].decode().split()
with open("%s/../kprobes/blacklist" % TRACEFS) as f: with open("%s/../kprobes/blacklist" % TRACEFS) as f:
blacklist = [line.split()[1] for line in f.readlines()] blacklist = [line.split()[1] for line in f.readlines()]
return [line.rstrip() for line in lines if fns = [line.rstrip() for line in lines if
(line != "\n" and line not in blacklist)] (line != "\n" and line not in blacklist)]
_check_probe_quota(len(fns))
return fns
def attach_kprobe(self, event="", fn_name="", event_re="", def attach_kprobe(self, event="", fn_name="", event_re="",
pid=-1, cpu=0, group_fd=-1): pid=-1, cpu=0, group_fd=-1):
...@@ -298,6 +307,7 @@ class BPF(object): ...@@ -298,6 +307,7 @@ class BPF(object):
pass pass
return return
_check_probe_quota(1)
fn = self.load_func(fn_name, BPF.KPROBE) fn = self.load_func(fn_name, BPF.KPROBE)
ev_name = "p_" + event.replace("+", "_").replace(".", "_") ev_name = "p_" + event.replace("+", "_").replace(".", "_")
desc = "p:kprobes/%s %s" % (ev_name, event) desc = "p:kprobes/%s %s" % (ev_name, event)
...@@ -340,6 +350,7 @@ class BPF(object): ...@@ -340,6 +350,7 @@ class BPF(object):
pass pass
return return
_check_probe_quota(1)
fn = self.load_func(fn_name, BPF.KPROBE) fn = self.load_func(fn_name, BPF.KPROBE)
ev_name = "r_" + event.replace("+", "_").replace(".", "_") ev_name = "r_" + event.replace("+", "_").replace(".", "_")
desc = "r:kprobes/%s %s" % (ev_name, event) desc = "r:kprobes/%s %s" % (ev_name, event)
...@@ -463,6 +474,7 @@ class BPF(object): ...@@ -463,6 +474,7 @@ class BPF(object):
(path, addr) = BPF._check_path_symbol(name, sym, addr) (path, addr) = BPF._check_path_symbol(name, sym, addr)
_check_probe_quota(1)
fn = self.load_func(fn_name, BPF.KPROBE) fn = self.load_func(fn_name, BPF.KPROBE)
ev_name = "p_%s_0x%x" % (self._probe_repl.sub("_", path), addr) ev_name = "p_%s_0x%x" % (self._probe_repl.sub("_", path), addr)
desc = "p:uprobes/%s %s:0x%x" % (ev_name, path, addr) desc = "p:uprobes/%s %s:0x%x" % (ev_name, path, addr)
...@@ -506,6 +518,7 @@ class BPF(object): ...@@ -506,6 +518,7 @@ class BPF(object):
(path, addr) = BPF._check_path_symbol(name, sym, addr) (path, addr) = BPF._check_path_symbol(name, sym, addr)
_check_probe_quota(1)
fn = self.load_func(fn_name, BPF.KPROBE) fn = self.load_func(fn_name, BPF.KPROBE)
ev_name = "r_%s_0x%x" % (self._probe_repl.sub("_", path), addr) ev_name = "r_%s_0x%x" % (self._probe_repl.sub("_", path), addr)
desc = "r:uprobes/%s %s:0x%x" % (ev_name, path, addr) desc = "r:uprobes/%s %s:0x%x" % (ev_name, path, addr)
......
...@@ -25,5 +25,15 @@ class TestKprobeCnt(TestCase): ...@@ -25,5 +25,15 @@ class TestKprobeCnt(TestCase):
open_cnt = self.b.num_open_kprobes() open_cnt = self.b.num_open_kprobes()
self.assertEqual(actual_cnt, open_cnt) self.assertEqual(actual_cnt, open_cnt)
class TestProbeQuota(TestCase):
def setUp(self):
self.b = BPF(text="""int count(void *ctx) { return 0; }""")
def test_probe_quota(self):
with self.assertRaises(Exception):
self.b.attach_kprobe(event_re=".*", fn_name="count")
if __name__ == "__main__": if __name__ == "__main__":
main() main()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment