Improve prctl decoding

* configure.ac (AC_CHECK_HEADERS): Add linux/securebits.h.
* prctl.c (sys_prctl): Implement full decoding of all PR_* constants
as defined in linux v3.19.
(sys_arch_prctl): Fix decoding of unknown commands.
* xlat/cap.in: New file.
* xlat/pr_mce_kill.in: New file.
* xlat/pr_mce_kill_policy.in: New file.
* xlat/pr_set_mm.in: New file.
* xlat/pr_tsc.in: New file.
* xlat/pr_unalign_flags.in: New file.
* xlat/secbits.in: New file.
* xlat/prctl_options.in: Remove non-linux constants, add fallback
definitions.
* xlat/seccomp_mode.in: Add fallback definitions.
This commit is contained in:
Дмитрий Левин 2015-02-14 01:51:03 +00:00
parent cff9f8aa94
commit 1e88073053
11 changed files with 403 additions and 201 deletions

View File

@ -253,6 +253,7 @@ AC_CHECK_HEADERS(m4_normalize([
linux/mmtimer.h
linux/perf_event.h
linux/seccomp.h
linux/securebits.h
linux/utsname.h
mqueue.h
netinet/sctp.h

425
prctl.c
View File

@ -3,140 +3,288 @@
#include <sys/prctl.h>
#include "xlat/prctl_options.h"
#include "xlat/pr_unalign_flags.h"
#include "xlat/pr_mce_kill.h"
#include "xlat/pr_mce_kill_policy.h"
#include "xlat/pr_set_mm.h"
#include "xlat/pr_tsc.h"
static const char *
unalignctl_string(unsigned int ctl)
{
static char buf[sizeof(int)*2 + 2];
switch (ctl) {
#ifdef PR_UNALIGN_NOPRINT
case PR_UNALIGN_NOPRINT:
return "NOPRINT";
#ifndef TASK_COMM_LEN
# define TASK_COMM_LEN 16
#endif
#ifdef PR_UNALIGN_SIGBUS
case PR_UNALIGN_SIGBUS:
return "SIGBUS";
#endif
default:
break;
}
sprintf(buf, "%x", ctl);
return buf;
}
#ifdef HAVE_LINUX_SECCOMP_H
# include <linux/seccomp.h>
#endif
#include "xlat/seccomp_mode.h"
#ifdef HAVE_LINUX_SECUREBITS_H
# include <linux/securebits.h>
#endif
#include "xlat/secbits.h"
/* these constants are the same as in <linux/capability.h> */
enum {
#include "caps0.h"
#include "caps1.h"
};
#include "xlat/cap.h"
static int
prctl_enter(struct tcb *tcp)
{
unsigned int i;
printxval(prctl_options, tcp->u_arg[0], "PR_???");
switch (tcp->u_arg[0]) {
/* PR_GET_* are decoded on exit. */
case PR_GET_CHILD_SUBREAPER:
case PR_GET_DUMPABLE:
case PR_GET_ENDIAN:
case PR_GET_FPEMU:
case PR_GET_FPEXC:
case PR_GET_KEEPCAPS:
case PR_GET_NAME:
case PR_GET_PDEATHSIG:
case PR_GET_SECCOMP:
case PR_GET_SECUREBITS:
case PR_GET_TID_ADDRESS:
case PR_GET_TIMERSLACK:
case PR_GET_TIMING:
case PR_GET_TSC:
case PR_GET_UNALIGN:
/* PR_TASK_PERF_EVENTS_* have nothing to decode on enter. */
case PR_TASK_PERF_EVENTS_DISABLE:
case PR_TASK_PERF_EVENTS_ENABLE:
break;
case PR_SET_CHILD_SUBREAPER:
case PR_SET_DUMPABLE:
case PR_SET_ENDIAN:
case PR_SET_FPEMU:
case PR_SET_FPEXC:
case PR_SET_KEEPCAPS:
case PR_SET_TIMING:
tprintf(", %lu", tcp->u_arg[1]);
break;
case PR_CAPBSET_DROP:
case PR_CAPBSET_READ:
tprints(", ");
printxval(cap, tcp->u_arg[1], "CAP_???");
break;
case PR_MCE_KILL:
tprints(", ");
printxval(pr_mce_kill, tcp->u_arg[1], "PR_MCE_KILL_???");
tprints(", ");
if (PR_MCE_KILL_SET == tcp->u_arg[1])
printxval(pr_mce_kill_policy, tcp->u_arg[2],
"PR_MCE_KILL_???");
else
tprintf("%#lx", tcp->u_arg[2]);
for (i = 3; i < tcp->s_ent->nargs; i++)
tprintf(", %#lx", tcp->u_arg[i]);
break;
case PR_SET_NAME:
tprints(", ");
printstr(tcp, tcp->u_arg[1], TASK_COMM_LEN);
break;
case PR_SET_MM:
tprints(", ");
printxval(pr_set_mm, tcp->u_arg[1], "PR_SET_MM_???");
for (i = 2; i < tcp->s_ent->nargs; i++)
tprintf(", %#lx", tcp->u_arg[i]);
break;
case PR_SET_PDEATHSIG:
tprints(", ");
if ((unsigned long) tcp->u_arg[1] > 128)
tprintf("%lu", tcp->u_arg[1]);
else
tprints(signame(tcp->u_arg[1]));
break;
case PR_SET_PTRACER:
tprints(", ");
if (tcp->u_arg[1] == -1)
tprints("PR_SET_PTRACER_ANY");
else
tprintf("%lu", tcp->u_arg[1]);
break;
case PR_SET_SECCOMP:
tprints(", ");
printxval(seccomp_mode, tcp->u_arg[1],
"SECCOMP_MODE_???");
if (SECCOMP_MODE_STRICT == tcp->u_arg[1])
break;
if (SECCOMP_MODE_FILTER == tcp->u_arg[1]) {
tprints(", ");
print_seccomp_filter(tcp, tcp->u_arg[2]);
break;
}
for (i = 2; i < tcp->s_ent->nargs; i++)
tprintf(", %#lx", tcp->u_arg[i]);
break;
case PR_SET_SECUREBITS:
tprints(", ");
printflags(secbits, tcp->u_arg[1], "SECBIT_???");
break;
case PR_SET_TIMERSLACK:
tprintf(", %ld", tcp->u_arg[1]);
break;
case PR_SET_TSC:
tprints(", ");
printxval(pr_tsc, tcp->u_arg[1], "PR_TSC_???");
break;
case PR_SET_UNALIGN:
tprints(", ");
printflags(pr_unalign_flags, tcp->u_arg[1], "PR_UNALIGN_???");
break;
case PR_SET_NO_NEW_PRIVS:
case PR_SET_THP_DISABLE:
tprintf(", %lu", tcp->u_arg[1]);
for (i = 2; i < tcp->s_ent->nargs; i++)
tprintf(", %#lx", tcp->u_arg[i]);
break;
case PR_GET_NO_NEW_PRIVS:
case PR_GET_THP_DISABLE:
case PR_MCE_KILL_GET:
/* Return code of "GET" commands will be decoded on exit */
case PR_MPX_DISABLE_MANAGEMENT:
case PR_MPX_ENABLE_MANAGEMENT:
default:
for (i = 1; i < tcp->s_ent->nargs; i++)
tprintf(", %#lx", tcp->u_arg[i]);
break;
}
return 0;
}
static int
prctl_exit(struct tcb *tcp)
{
unsigned long addr;
unsigned int i;
switch (tcp->u_arg[0]) {
case PR_CAPBSET_READ:
case PR_GET_DUMPABLE:
case PR_GET_KEEPCAPS:
case PR_GET_NO_NEW_PRIVS:
case PR_GET_SECCOMP:
case PR_GET_THP_DISABLE:
case PR_GET_TIMERSLACK:
case PR_GET_TIMING:
return syserror(tcp) ? 0 : RVAL_UDECIMAL;
case PR_GET_CHILD_SUBREAPER:
case PR_GET_ENDIAN:
case PR_GET_FPEMU:
case PR_GET_FPEXC:
tprints(", ");
/* cannot use printnum_int() because of syserror() */
if (!tcp->u_arg[1])
tprints("NULL");
else if (syserror(tcp) || umove(tcp, tcp->u_arg[1], &i) < 0)
tprintf("%#lx", tcp->u_arg[1]);
else
tprintf("[%u]", i);
break;
case PR_GET_NAME:
tprints(", ");
if (!tcp->u_arg[1])
tprints("NULL");
else if (syserror(tcp))
tprintf("%#lx", tcp->u_arg[1]);
else
printstr(tcp, tcp->u_arg[1], -1);
break;
case PR_GET_PDEATHSIG:
tprints(", ");
if (!tcp->u_arg[1])
tprints("NULL");
else if (syserror(tcp) || umove(tcp, tcp->u_arg[1], &i) < 0)
tprintf("%#lx", tcp->u_arg[1]);
else {
tprints("[");
tprints(signame(i));
tprints("]");
}
break;
case PR_GET_SECUREBITS:
if (syserror(tcp) || tcp->u_rval == 0)
return 0;
tcp->auxstr = sprintflags("", secbits, tcp->u_rval);
return RVAL_STR;
case PR_GET_TID_ADDRESS:
tprints(", ");
/* cannot use printnum_long() because of syserror() */
if (!tcp->u_arg[1])
tprints("NULL");
else if (syserror(tcp) || umove(tcp, tcp->u_arg[1], &addr) < 0)
tprintf("%#lx", tcp->u_arg[1]);
else
tprintf("[%#lx]", addr);
break;
case PR_GET_TSC:
tprints(", ");
if (!tcp->u_arg[1])
tprints("NULL");
else if (syserror(tcp) || umove(tcp, tcp->u_arg[1], &i) < 0)
tprintf("%#lx", tcp->u_arg[1]);
else {
tprints("[");
printxval(pr_tsc, i, "PR_TSC_???");
tprints("]");
}
break;
case PR_GET_UNALIGN:
tprints(", ");
if (!tcp->u_arg[1])
tprints("NULL");
else if (syserror(tcp) || umove(tcp, tcp->u_arg[1], &i) < 0)
tprintf("%#lx", tcp->u_arg[1]);
else {
tprints("[");
printflags(pr_unalign_flags, i, "PR_UNALIGN_???");
tprints("]");
}
break;
case PR_MCE_KILL_GET:
if (syserror(tcp))
return 0;
tcp->auxstr = xlookup(pr_mce_kill_policy, tcp->u_rval);
return tcp->auxstr ? RVAL_STR : RVAL_UDECIMAL;
default:
break;
}
return 0;
}
int
sys_prctl(struct tcb *tcp)
{
unsigned int i;
if (entering(tcp)) {
printxval(prctl_options, tcp->u_arg[0], "PR_???");
switch (tcp->u_arg[0]) {
#ifdef PR_GETNSHARE
case PR_GETNSHARE:
break;
#endif
#ifdef PR_SET_PDEATHSIG
case PR_SET_PDEATHSIG:
tprintf(", %lu", tcp->u_arg[1]);
break;
#endif
#ifdef PR_GET_PDEATHSIG
case PR_GET_PDEATHSIG:
break;
#endif
#ifdef PR_SET_DUMPABLE
case PR_SET_DUMPABLE:
tprintf(", %lu", tcp->u_arg[1]);
break;
#endif
#ifdef PR_GET_DUMPABLE
case PR_GET_DUMPABLE:
break;
#endif
#ifdef PR_SET_UNALIGN
case PR_SET_UNALIGN:
tprintf(", %s", unalignctl_string(tcp->u_arg[1]));
break;
#endif
#ifdef PR_GET_UNALIGN
case PR_GET_UNALIGN:
tprintf(", %#lx", tcp->u_arg[1]);
break;
#endif
#ifdef PR_SET_KEEPCAPS
case PR_SET_KEEPCAPS:
tprintf(", %lu", tcp->u_arg[1]);
break;
#endif
#ifdef PR_GET_KEEPCAPS
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]);
break;
}
} else {
switch (tcp->u_arg[0]) {
#ifdef PR_GET_PDEATHSIG
case PR_GET_PDEATHSIG:
if (umove(tcp, tcp->u_arg[1], &i) < 0)
tprintf(", %#lx", tcp->u_arg[1]);
else
tprintf(", {%u}", i);
break;
#endif
#ifdef PR_GET_DUMPABLE
case PR_GET_DUMPABLE:
return RVAL_UDECIMAL;
#endif
#ifdef PR_GET_UNALIGN
case PR_GET_UNALIGN:
if (syserror(tcp) || umove(tcp, tcp->u_arg[1], &i) < 0)
break;
tcp->auxstr = unalignctl_string(i);
return RVAL_STR;
#endif
#ifdef PR_GET_KEEPCAPS
case PR_GET_KEEPCAPS:
return RVAL_UDECIMAL;
#endif
default:
break;
}
}
return 0;
return entering(tcp) ? prctl_enter(tcp) : prctl_exit(tcp);
}
#if defined X86_64 || defined X32
@ -146,24 +294,25 @@ sys_prctl(struct tcb *tcp)
int
sys_arch_prctl(struct tcb *tcp)
{
if (entering(tcp)) {
if (entering(tcp))
printxval(archvals, tcp->u_arg[0], "ARCH_???");
if (tcp->u_arg[0] == ARCH_SET_GS
|| tcp->u_arg[0] == ARCH_SET_FS
) {
tprintf(", %#lx", tcp->u_arg[1]);
}
} else {
if (tcp->u_arg[0] == ARCH_GET_GS
|| tcp->u_arg[0] == ARCH_GET_FS
) {
long int v;
if (!syserror(tcp) && umove(tcp, tcp->u_arg[1], &v) != -1)
tprintf(", [%#lx]", v);
else
tprintf(", %#lx", tcp->u_arg[1]);
switch (tcp->u_arg[0]) {
case ARCH_GET_GS:
case ARCH_GET_FS:
if (exiting(tcp)) {
if (syserror(tcp))
break;
tprints(", ");
printnum_long(tcp, tcp->u_arg[1], "%#lx");
}
return 0;
default:
if (exiting(tcp))
return 0;
}
tprintf(", %#lx", tcp->u_arg[1]);
return 0;
}
#endif /* X86_64 || X32 */

39
xlat/cap.in Normal file
View File

@ -0,0 +1,39 @@
#unconditional
CAP_CHOWN
CAP_DAC_OVERRIDE
CAP_DAC_READ_SEARCH
CAP_FOWNER
CAP_FSETID
CAP_KILL
CAP_SETGID
CAP_SETUID
CAP_SETPCAP
CAP_LINUX_IMMUTABLE
CAP_NET_BIND_SERVICE
CAP_NET_BROADCAST
CAP_NET_ADMIN
CAP_NET_RAW
CAP_IPC_LOCK
CAP_IPC_OWNER
CAP_SYS_MODULE
CAP_SYS_RAWIO
CAP_SYS_CHROOT
CAP_SYS_PTRACE
CAP_SYS_PACCT
CAP_SYS_ADMIN
CAP_SYS_BOOT
CAP_SYS_NICE
CAP_SYS_RESOURCE
CAP_SYS_TIME
CAP_SYS_TTY_CONFIG
CAP_MKNOD
CAP_LEASE
CAP_AUDIT_WRITE
CAP_AUDIT_CONTROL
CAP_SETFCAP
CAP_MAC_OVERRIDE
CAP_MAC_ADMIN
CAP_SYSLOG
CAP_WAKE_ALARM
CAP_BLOCK_SUSPEND
CAP_AUDIT_READ

2
xlat/pr_mce_kill.in Normal file
View File

@ -0,0 +1,2 @@
PR_MCE_KILL_CLEAR 0
PR_MCE_KILL_SET 1

View File

@ -0,0 +1,3 @@
PR_MCE_KILL_LATE 0
PR_MCE_KILL_EARLY 1
PR_MCE_KILL_DEFAULT 2

15
xlat/pr_set_mm.in Normal file
View File

@ -0,0 +1,15 @@
PR_SET_MM_START_CODE 1
PR_SET_MM_END_CODE 2
PR_SET_MM_START_DATA 3
PR_SET_MM_END_DATA 4
PR_SET_MM_START_STACK 5
PR_SET_MM_START_BRK 6
PR_SET_MM_BRK 7
PR_SET_MM_ARG_START 8
PR_SET_MM_ARG_END 9
PR_SET_MM_ENV_START 10
PR_SET_MM_ENV_END 11
PR_SET_MM_AUXV 12
PR_SET_MM_EXE_FILE 13
PR_SET_MM_MAP 14
PR_SET_MM_MAP_SIZE 15

2
xlat/pr_tsc.in Normal file
View File

@ -0,0 +1,2 @@
PR_TSC_ENABLE 1
PR_TSC_SIGSEGV 2

2
xlat/pr_unalign_flags.in Normal file
View File

@ -0,0 +1,2 @@
PR_UNALIGN_NOPRINT 1
PR_UNALIGN_SIGBUS 2

View File

@ -1,60 +1,43 @@
PR_MAXPROCS
PR_ISBLOCKED
PR_SETSTACKSIZE
PR_GETSTACKSIZE
PR_MAXPPROCS
PR_UNBLKONEXEC
PR_ATOMICSIM
PR_SETEXITSIG
PR_RESIDENT
PR_ATTACHADDR
PR_DETACHADDR
PR_TERMCHILD
PR_GETSHMASK
PR_GETNSHARE
PR_COREPID
PR_ATTACHADDRPERM
PR_PTHREADEXIT
PR_SET_PDEATHSIG
PR_GET_PDEATHSIG
PR_GET_DUMPABLE
PR_SET_DUMPABLE
PR_GET_UNALIGN
PR_SET_UNALIGN
PR_GET_KEEPCAPS
PR_SET_KEEPCAPS
PR_GET_FPEMU
PR_SET_FPEMU
PR_GET_FPEXC
PR_SET_FPEXC
PR_GET_TIMING
PR_SET_TIMING
PR_SET_NAME
PR_GET_NAME
PR_GET_ENDIAN
PR_SET_ENDIAN
PR_GET_SECCOMP
PR_SET_SECCOMP
PR_CAPBSET_READ
PR_CAPBSET_DROP
PR_GET_TSC
PR_SET_TSC
PR_GET_SECUREBITS
PR_SET_SECUREBITS
PR_SET_TIMERSLACK
PR_GET_TIMERSLACK
PR_TASK_PERF_EVENTS_DISABLE
PR_TASK_PERF_EVENTS_ENABLE
PR_MCE_KILL
PR_MCE_KILL_GET
PR_SET_MM
PR_SET_PTRACER
PR_SET_CHILD_SUBREAPER
PR_GET_CHILD_SUBREAPER
PR_SET_NO_NEW_PRIVS
PR_GET_NO_NEW_PRIVS
PR_GET_TID_ADDRESS
PR_SET_THP_DISABLE
PR_GET_THP_DISABLE
PR_MPX_ENABLE_MANAGEMENT
PR_MPX_DISABLE_MANAGEMENT
PR_SET_PDEATHSIG 1
PR_GET_PDEATHSIG 2
PR_GET_DUMPABLE 3
PR_SET_DUMPABLE 4
PR_GET_UNALIGN 5
PR_SET_UNALIGN 6
PR_GET_KEEPCAPS 7
PR_SET_KEEPCAPS 8
PR_GET_FPEMU 9
PR_SET_FPEMU 10
PR_GET_FPEXC 11
PR_SET_FPEXC 12
PR_GET_TIMING 13
PR_SET_TIMING 14
PR_SET_NAME 15
PR_GET_NAME 16
PR_GET_ENDIAN 19
PR_SET_ENDIAN 20
PR_GET_SECCOMP 21
PR_SET_SECCOMP 22
PR_CAPBSET_READ 23
PR_CAPBSET_DROP 24
PR_GET_TSC 25
PR_SET_TSC 26
PR_GET_SECUREBITS 27
PR_SET_SECUREBITS 28
PR_SET_TIMERSLACK 29
PR_GET_TIMERSLACK 30
PR_TASK_PERF_EVENTS_DISABLE 31
PR_TASK_PERF_EVENTS_ENABLE 32
PR_MCE_KILL 33
PR_MCE_KILL_GET 34
PR_SET_MM 35
PR_SET_PTRACER 0x59616d61
PR_SET_CHILD_SUBREAPER 36
PR_GET_CHILD_SUBREAPER 37
PR_SET_NO_NEW_PRIVS 38
PR_GET_NO_NEW_PRIVS 39
PR_GET_TID_ADDRESS 40
PR_SET_THP_DISABLE 41
PR_GET_THP_DISABLE 42
PR_MPX_ENABLE_MANAGEMENT 43
PR_MPX_DISABLE_MANAGEMENT 44

6
xlat/secbits.in Normal file
View File

@ -0,0 +1,6 @@
SECBIT_NOROOT (1 << 0)
SECBIT_NOROOT_LOCKED (1 << 1)
SECBIT_NO_SETUID_FIXUP (1 << 2)
SECBIT_NO_SETUID_FIXUP_LOCKED (1 << 3)
SECBIT_KEEP_CAPS (1 << 4)
SECBIT_KEEP_CAPS_LOCKED (1 << 5)

View File

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