lkml.org 
[lkml]   [2012]   [Jan]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
SubjectRe: [RFC,PATCH 1/2] seccomp_filters: system call filtering using BPF
From
Date
For anyone who is interested I hacked up a program to turn what I think
is a readable seccomp syntax into BPF rules. It should make it easier
to prototype this new thing. The translator needs a LOT of love to be
worth much, but for now it can handle a couple of things and can build a
set of rules!

The rules are of the form:
label object:
value label

So using Will's BPF example code in my syntax looks like:

start syscall:
rt_sigreturn success
sigreturn success
exit_group success
exit success
read read
write write
read arg0:
0 success
write arg0:
1 success
2 success

So this says the first label is "start" and it is going to deal with the
syscall number. The first value is 'rt_sigreturn' and if syscall ==
rt_sigreturn will cause you to jump to 'success' (success and fail are
implied labels). If the syscall is 'write' we will jump to 'write.'
The write rules look at arg0. If arg0 == "1" we jump to "success". If
you run that syntax through my translator you should get Will's BPF
rules!

You'll quickly notice that the translator only understands "syscall" and
"arg0" and only x86_32, but it should be easy to add more, support the
right registers on different arches, etc, etc. If others think they
might want to hack on the translator I put it at:

http://git.infradead.org/users/eparis/bpf-translate.git

-Eric
#! /usr/bin/python -Es

import sys

if len(sys.argv) > 1:
file = open(sys.argv[1])
else:
file = sys.stdin

linecount = 0
sections = []
rules = {}
output = []
section_map = {}

def new_section(section):
if section[1] == "syscall":
output.append(("BPF_STMT(BPF_LD+BPF_W+BPF_IND, regoffset(orig_eax)),", section[0]))
elif section[1] == "arg0":
output.append(("BPF_STMT(BPF_LD+BPF_W+BPF_IND, regoffset(ebx)),", section[0]))
elif section[0] == "success":
output.append(("BPF_STMT(BPF_LD+BPF_W+BPF_LEN, 0),", section[0]))
elif section[0] == "fail":
output.append(("BPF_STMT(BPF_RET+BPF_A,0),", section[0]))

def new_rule(rule, section, last=None):
string = "BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, %s, %s, 0)," % (rule[0], rule[1])
if last:
string = string.replace(", 0)", ", fail)")
output.append((string, "0"))

if __name__ == '__main__':
while 1:
line = file.readline()
if not line:
break
linecount = linecount + 1
if ":" in line:
sections.append(line.strip().strip(":").split())
else:
key = sections[-1][0]
current_list = rules.get(key, [])
newrule = line.strip().split()
if sections[-1][1] == "syscall":
newrule = ["__NR_%s" % newrule[0], newrule[1]]
current_list.append(newrule)
rules[key] = current_list



sections.append(["success", "*"])
sections.append(["fail", "*"])

for section in sections:
new_section(section)
if rules.has_key(section[0]):
for rule in rules[section[0]]:
if rule == rules[section[0]][-1]:
new_rule(rule, section, 1)
else:
new_rule(rule, section)

for lineno,line in enumerate(output):
if (line[1] == "0"):
continue
section_map[line[1]] = lineno

for lineno,line in enumerate(output):
line = line[0]
for section in section_map.keys():
# Only replace in those last 2 commas
#if VALUE == section:
#replace VALUE with str(section_map[section] - lineno - 2)
splitline = line.split(",")
if section in splitline[-3]:
splitline[-3] = splitline[-3].replace(section, str(section_map[section] - lineno - 1))
if section in splitline[-2]:
splitline[-2] = splitline[-2].replace(section, str(section_map[section] - lineno - 1))
line = ",".join(splitline)
print line
\
 
 \ /
  Last update: 2012-01-14 00:37    [W:1.058 / U:0.280 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site