Implement seccomp decoding

* configure.ac (AC_CHECK_HEADERS): Add linux/filter.h
and linux/seccomp.h.
* defs.h (print_seccomp_filter): New prototype.
* linux/dummy.h (sys_seccomp): Remove.
* linux/syscall.h (sys_seccomp): New prototype.
* prctl.c: Include <linux/seccomp.h>.
(sys_prctl): Decode PR_SET_SECCOMP.
* seccomp.c: New file.
* Makefile.am (strace_SOURCES): Add it.
* xlat/bpf_class.in: New file.
* xlat/bpf_miscop.in: Likewise.
* xlat/bpf_mode.in: Likewise.
* xlat/bpf_op_alu.in: Likewise.
* xlat/bpf_op_jmp.in: Likewise.
* xlat/bpf_rval.in: Likewise.
* xlat/bpf_size.in: Likewise.
* xlat/bpf_src.in: Likewise.
* xlat/seccomp_filter_flags.in: Likewise.
* xlat/seccomp_mode.in: Likewise.
* xlat/seccomp_ops.in: Likewise.
* xlat/seccomp_ret_action.in: Likewise.
This commit is contained in:
Дмитрий Левин 2015-02-04 23:50:50 +00:00
parent 0946052255
commit 2af6903f45
19 changed files with 357 additions and 1 deletions

View File

@ -86,6 +86,7 @@ strace_SOURCES = \
resource.c \
sched.c \
scsi.c \
seccomp.c \
signal.c \
sock.c \
socketutils.c \

View File

@ -223,11 +223,13 @@ AC_CHECK_HEADERS(m4_normalize([
inttypes.h
ioctls.h
linux/falloc.h
linux/filter.h
linux/hiddev.h
linux/input.h
linux/mmtimer.h
linux/perf_event.h
linux/ptrace.h
linux/seccomp.h
linux/utsname.h
mqueue.h
netinet/sctp.h

1
defs.h
View File

@ -734,6 +734,7 @@ extern void tprint_iov_upto(struct tcb *, unsigned long, unsigned long, int deco
extern void tprint_open_modes(int);
extern const char *sprint_open_modes(int);
extern void print_loff_t(struct tcb *, long);
extern void print_seccomp_filter(struct tcb *tcp, unsigned long);
extern const struct_ioctlent *ioctl_lookup(const unsigned int);
extern const struct_ioctlent *ioctl_next_match(const struct_ioctlent *);

View File

@ -44,7 +44,6 @@
#define sys_open_by_handle_at printargs
#define sys_sched_getattr printargs
#define sys_sched_setattr printargs
#define sys_seccomp printargs
#define sys_sysfs printargs
#define sys_vm86 printargs
#define sys_vm86old printargs

View File

@ -222,6 +222,7 @@ int sys_sched_rr_get_interval();
int sys_sched_setaffinity();
int sys_sched_setparam();
int sys_sched_setscheduler();
int sys_seccomp();
int sys_select();
int sys_semctl();
int sys_semget();

28
prctl.c
View File

@ -25,6 +25,12 @@ unalignctl_string(unsigned int ctl)
return buf;
}
#ifdef HAVE_LINUX_SECCOMP_H
# include <linux/seccomp.h>
#endif
#include "xlat/seccomp_mode.h"
int
sys_prctl(struct tcb *tcp)
{
@ -74,6 +80,28 @@ sys_prctl(struct tcb *tcp)
case PR_GET_KEEPCAPS:
break;
#endif
#ifdef PR_SET_SECCOMP
case PR_SET_SECCOMP:
tprints(", ");
printxval(seccomp_mode, tcp->u_arg[1],
"SECCOMP_MODE_???");
# ifdef SECCOMP_MODE_STRICT
if (SECCOMP_MODE_STRICT == tcp->u_arg[1])
break;
# endif
# ifdef SECCOMP_MODE_FILTER
if (SECCOMP_MODE_FILTER == tcp->u_arg[1]) {
tprints(", ");
print_seccomp_filter(tcp, tcp->u_arg[2]);
break;
}
# endif
for (i = 2; i < tcp->s_ent->nargs; i++)
tprintf(", %#lx", tcp->u_arg[i]);
break;
#endif /* PR_SET_SECCOMP */
default:
for (i = 1; i < tcp->s_ent->nargs; i++)
tprintf(", %#lx", tcp->u_arg[i]);

264
seccomp.c Normal file
View File

@ -0,0 +1,264 @@
/*
* Copyright (c) 2015 Dmitry V. Levin <ldv@altlinux.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "defs.h"
#ifdef HAVE_LINUX_SECCOMP_H
# include <linux/seccomp.h>
#endif
#ifndef SECCOMP_SET_MODE_STRICT
# define SECCOMP_SET_MODE_STRICT 1
#endif
#ifndef SECCOMP_SET_MODE_FILTER
# define SECCOMP_SET_MODE_FILTER 1
#endif
#include "xlat/seccomp_ops.h"
#ifndef SECCOMP_FILTER_FLAG_TSYNC
# define SECCOMP_FILTER_FLAG_TSYNC 1
#endif
#include "xlat/seccomp_filter_flags.h"
#ifdef HAVE_LINUX_FILTER_H
# include <linux/filter.h>
# include "xlat/bpf_class.h"
# include "xlat/bpf_miscop.h"
# include "xlat/bpf_mode.h"
# include "xlat/bpf_op_alu.h"
# include "xlat/bpf_op_jmp.h"
# include "xlat/bpf_rval.h"
# include "xlat/bpf_size.h"
# include "xlat/bpf_src.h"
# ifndef SECCOMP_RET_ACTION
# define SECCOMP_RET_ACTION 0x7fff0000U
# endif
# include "xlat/seccomp_ret_action.h"
#endif
struct bpf_filter {
uint16_t code;
uint8_t jt;
uint8_t jf;
uint32_t k;
};
#ifdef HAVE_LINUX_FILTER_H
static void
decode_bpf_code(uint16_t code)
{
uint16_t i = code & ~BPF_CLASS(code);
printxval(bpf_class, BPF_CLASS(code), "BPF_???");
switch (BPF_CLASS(code)) {
case BPF_LD:
case BPF_LDX:
tprints(" | ");
printxval(bpf_size, BPF_SIZE(code), "BPF_???");
tprints(" | ");
printxval(bpf_mode, BPF_MODE(code), "BPF_???");
break;
case BPF_ST:
case BPF_STX:
if (i)
tprintf(" | %#x /* %s */", i, "BPF_???");
break;
case BPF_ALU:
tprints(" | ");
printxval(bpf_src, BPF_SRC(code), "BPF_???");
tprints(" | ");
printxval(bpf_op_alu, BPF_OP(code), "BPF_???");
break;
case BPF_JMP:
tprints(" | ");
printxval(bpf_src, BPF_SRC(code), "BPF_???");
tprints(" | ");
printxval(bpf_op_jmp, BPF_OP(code), "BPF_???");
break;
case BPF_RET:
tprints(" | ");
printxval(bpf_rval, BPF_RVAL(code), "BPF_???");
i &= ~BPF_RVAL(code);
if (i)
tprintf(" | %#x /* %s */", i, "BPF_???");
break;
case BPF_MISC:
tprints(" | ");
printxval(bpf_miscop, BPF_MISCOP(code), "BPF_???");
i &= ~BPF_MISCOP(code);
if (i)
tprintf(" | %#x /* %s */", i, "BPF_???");
break;
}
}
static void
decode_bpf_stmt(const struct bpf_filter *filter)
{
#ifdef HAVE_LINUX_FILTER_H
tprints("BPF_STMT(");
decode_bpf_code(filter->code);
tprints(", ");
if (BPF_CLASS(filter->code) == BPF_RET) {
unsigned int action = SECCOMP_RET_ACTION & filter->k;
unsigned int data = filter->k & ~action;
printxval(seccomp_ret_action, action, "SECCOMP_RET_???");
if (data)
tprintf(" | %#x)", data);
else
tprints(")");
} else {
tprintf("%#x)", filter->k);
}
#else
tprintf("BPF_STMT(%#x, %#x)", filter->code, filter->k);
#endif /* HAVE_LINUX_FILTER_H */
}
static void
decode_bpf_jump(const struct bpf_filter *filter)
{
#ifdef HAVE_LINUX_FILTER_H
tprints("BPF_JUMP(");
decode_bpf_code(filter->code);
tprintf(", %#x, %#x, %#x)",
filter->k, filter->jt, filter->jf);
#else
tprintf("BPF_JUMP(%#x, %#x, %#x, %#x)",
filter->code, filter->k, filter->jt, filter->jf);
#endif /* HAVE_LINUX_FILTER_H */
}
static void
decode_filter(const struct bpf_filter *filter)
{
if (filter->jt || filter->jf)
decode_bpf_jump(filter);
else
decode_bpf_stmt(filter);
}
#endif /* HAVE_LINUX_FILTER_H */
#ifndef BPF_MAXINSNS
# define BPF_MAXINSNS 4096
#endif
static void
decode_fprog(struct tcb *tcp, unsigned short len, unsigned long addr)
{
if (!len || abbrev(tcp)) {
tprintf("{len = %u, filter = %#lx}", len, addr);
} else {
unsigned int i = 0;
tprints("[");
while (i < len && i < BPF_MAXINSNS) {
struct bpf_filter filter;
if (umove(tcp, addr, &filter) < 0)
break;
if (i)
tprints(", ");
decode_filter(&filter);
addr += sizeof(filter);
++i;
}
if (i < len)
tprints("...");
tprints("]");
}
}
void
print_seccomp_filter(struct tcb *tcp, unsigned long addr)
{
if (addr) {
#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
if (current_wordsize == 4) {
struct {
unsigned short len;
uint32_t filter;
} fprog;
if (umove(tcp, addr, &fprog) < 0)
tprintf("%#lx", addr);
else
decode_fprog(tcp, fprog.len, fprog.filter);
} else {
#endif
struct {
unsigned short len;
unsigned long filter;
} fprog;
if (umove(tcp, addr, &fprog) < 0)
tprintf("%#lx", addr);
else
decode_fprog(tcp, fprog.len, fprog.filter);
#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
}
#endif
} else {
tprints("NULL");
}
}
static void
decode_seccomp_set_mode_strict(unsigned int flags, unsigned long addr)
{
tprintf("%u, ", flags);
if (addr)
tprintf("%#lx", addr);
else
tprints("NULL");
}
int
sys_seccomp(struct tcb *tcp)
{
if (entering(tcp)) {
unsigned int op = tcp->u_arg[0];
printxval(seccomp_ops, op, "SECCOMP_SET_MODE_???");
tprints(", ");
if (op == SECCOMP_SET_MODE_FILTER) {
printflags(seccomp_filter_flags, tcp->u_arg[1],
"SECCOMP_FILTER_FLAG_???");
tprints(", ");
print_seccomp_filter(tcp, tcp->u_arg[2]);
} else {
decode_seccomp_set_mode_strict(tcp->u_arg[1],
tcp->u_arg[2]);
}
}
return 0;
}

8
xlat/bpf_class.in Normal file
View File

@ -0,0 +1,8 @@
BPF_LD
BPF_LDX
BPF_ST
BPF_STX
BPF_ALU
BPF_JMP
BPF_RET
BPF_MISC

2
xlat/bpf_miscop.in Normal file
View File

@ -0,0 +1,2 @@
BPF_TAX
BPF_TXA

7
xlat/bpf_mode.in Normal file
View File

@ -0,0 +1,7 @@
BPF_IMM
BPF_ABS
BPF_IND
BPF_MEM
BPF_LEN
BPF_MSH
BPF_XADD

13
xlat/bpf_op_alu.in Normal file
View File

@ -0,0 +1,13 @@
BPF_ADD
BPF_SUB
BPF_MUL
BPF_DIV
BPF_OR
BPF_AND
BPF_LSH
BPF_RSH
BPF_NEG
BPF_MOD
BPF_XOR
BPF_MOV
BPF_ARSH

10
xlat/bpf_op_jmp.in Normal file
View File

@ -0,0 +1,10 @@
BPF_JA
BPF_JEQ
BPF_JGT
BPF_JGE
BPF_JSET
BPF_JNE
BPF_JSGT
BPF_JSGE
BPF_CALL
BPF_EXIT

3
xlat/bpf_rval.in Normal file
View File

@ -0,0 +1,3 @@
BPF_K
BPF_X
BPF_A

4
xlat/bpf_size.in Normal file
View File

@ -0,0 +1,4 @@
BPF_W
BPF_H
BPF_B
BPF_DW

2
xlat/bpf_src.in Normal file
View File

@ -0,0 +1,2 @@
BPF_K
BPF_X

View File

@ -0,0 +1 @@
SECCOMP_FILTER_FLAG_TSYNC

3
xlat/seccomp_mode.in Normal file
View File

@ -0,0 +1,3 @@
SECCOMP_MODE_DISABLED
SECCOMP_MODE_STRICT
SECCOMP_MODE_FILTER

2
xlat/seccomp_ops.in Normal file
View File

@ -0,0 +1,2 @@
SECCOMP_SET_MODE_STRICT
SECCOMP_SET_MODE_FILTER

View File

@ -0,0 +1,5 @@
SECCOMP_RET_KILL
SECCOMP_RET_TRAP
SECCOMP_RET_ERRNO
SECCOMP_RET_TRACE
SECCOMP_RET_ALLOW