Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,13 @@ $ seccomp-tools emu spec/data/libseccomp.bpf write 0x3

![emu](https://github.com/david942j/seccomp-tools/blob/master/examples/emu-amigo.png?raw=true)

## Architecture Supported

[x] x86_64
[x] x32
[x] x86
[x] arm64 (Thanks to @saagarjha!)

## Development

I recommend to use [rbenv](https://github.com/rbenv/rbenv) for your Ruby environment.
Expand Down
7 changes: 7 additions & 0 deletions README.tpl.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ SHELL_OUTPUT_OF(seccomp-tools emu spec/data/libseccomp.bpf write 0x3)

![emu](https://github.com/david942j/seccomp-tools/blob/master/examples/emu-amigo.png?raw=true)

## Architecture Supported

[x] x86_64
[x] x32
[x] x86
[x] arm64 (Thanks to @saagarjha!)

## Development

I recommend to use [rbenv](https://github.com/rbenv/rbenv) for your Ruby environment.
Expand Down
12 changes: 11 additions & 1 deletion lib/seccomp-tools/const.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,20 @@ def load_const(cons)

const_set(cons, instance_eval(IO.read(filename)))
end

def load_args
hash = instance_eval(IO.read(File.join(__dir__, 'consts', 'sys_arg.rb')))
Hash.new do |_h, k|
next hash[k] if hash[k]
next hash[k.to_s[4..-1].to_sym] if k.to_s.start_with?('x32_')

nil
end
end
end

# The argument names of all syscalls.
SYS_ARG = instance_eval(IO.read(File.join(__dir__, 'consts', 'sys_arg.rb'))).freeze
SYS_ARG = Syscall.load_args.freeze

# Constants from https://github.com/torvalds/linux/blob/master/include/uapi/linux/audit.h.
module Audit
Expand Down
3 changes: 2 additions & 1 deletion lib/seccomp-tools/consts/sys_nr/amd64.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# frozen_string_literal: true

X32_MODE_BIT = 0x40000000
{
read: 0,
write: 1,
Expand Down Expand Up @@ -334,4 +335,4 @@
pkey_alloc: 330,
pkey_free: 331,
statx: 332
}
}.tap { |h| h.keys.each { |k| h["x32_#{k}".to_sym] = h[k] | X32_MODE_BIT } } # rubocop:disable Style/HashEachMethods
7 changes: 6 additions & 1 deletion lib/seccomp-tools/instruction/jmp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,17 @@ def src_str

hex = "0x#{k.to_s(16)}"
case a.val
when 0 then Util.colorize(Const::Syscall.const_get(arch.upcase.to_sym).invert[k] || hex, t: :syscall)
# interpret as syscalls only if it's an equality test
when 0 then Util.colorize(jop == :== ? sysname_by_k || hex : hex, t: :syscall)
when 4 then Util.colorize(Const::Audit::ARCH.invert[k] || hex, t: :arch)
else hex
end
end

def sysname_by_k
Const::Syscall.const_get(arch.upcase.to_sym).invert[k]
end

def src
SRC.invert[code & 8] == :x ? :x : k
end
Expand Down
Binary file added spec/data/x32.bpf
Binary file not shown.
35 changes: 35 additions & 0 deletions spec/disasm/disasm_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,26 @@
EOS
end

it 'x32 syscall and args' do
bpf = IO.binread(File.join(__dir__, '..', 'data', 'x32.bpf'))
expect(described_class.disasm(bpf)).to eq <<-EOS
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x09 0xc000003e if (A != ARCH_X86_64) goto 0011
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x07 0x40000000 if (A < 0x40000000) goto 0011
0004: 0x15 0x06 0x00 0x40000000 if (A == x32_read) goto 0011
0005: 0x15 0x05 0x00 0x40000001 if (A == x32_write) goto 0011
0006: 0x15 0x04 0x00 0x400000ac if (A == x32_iopl) goto 0011
0007: 0x15 0x00 0x03 0x40000009 if (A != x32_mmap) goto 0011
0008: 0x20 0x00 0x00 0x00000010 A = addr # x32_mmap(addr, len, prot, flags, fd, pgoff)
0009: 0x15 0x01 0x00 0x00000000 if (A == 0x0) goto 0011
0010: 0x06 0x00 0x00 0x00050005 return ERRNO(5)
0011: 0x06 0x00 0x00 0x7fff0000 return ALLOW
EOS
end

it 'syscall args' do
bpf = IO.binread(File.join(__dir__, '..', 'data', 'gctf-2019-quals-caas.bpf'))
expect(described_class.disasm(bpf)).to eq <<-EOS
Expand Down Expand Up @@ -258,6 +278,21 @@
EOS
end

it 'args of unknown syscall' do
bpf = "\x20\x00\x00\x00\x00\x00\x00\x00" \
"\x15\x00\x00\x01\xE7\x03\x00\x00" \
"\x20\x00\x00\x00\x10\x00\x00\x00" \
"\x06\x00\x00\x00\x00\x00\x00\x00"
expect(described_class.disasm(bpf)).to eq <<-EOS
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000000 A = sys_number
0001: 0x15 0x00 0x01 0x000003e7 if (A != 0x3e7) goto 0003
0002: 0x20 0x00 0x00 0x00000010 A = args[0]
0003: 0x06 0x00 0x00 0x00000000 return KILL
EOS
end

it 'all instructions' do
bpf = IO.binread(File.join(__dir__, '..', 'data', 'all_inst.bpf'))
expect(described_class.disasm(bpf)).to eq <<-EOS
Expand Down
2 changes: 1 addition & 1 deletion tasks/sys_arg.rake
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ task :sys_arg do

parse_failed = {}
proto = content.scan(/^asmlinkage long sys_(\w+)\(([^)]+)\);/m).each_with_object({}) do |(name, args), hash|
next if name == 'sigsuspend' # there're two implementations, don't know which one should be used
next if name == 'sigsuspend' # XXX: there are two implementations, don't know which one should be used
next error(name, args, 'dup') if hash.key?(name)

parse_args(args).tap do |res|
Expand Down