203 lines
5.1 KiB
C
203 lines
5.1 KiB
C
/*
|
|
* check out-of-bound/unaligned addresses given to
|
|
* - {PEEK,POKE}{DATA,TEXT,USER}
|
|
* - {GET,SET}{,FG}REGS
|
|
* - {GET,SET}SIGINFO
|
|
*
|
|
* Copyright (c) 2008 Analog Devices Inc.
|
|
*
|
|
* Licensed under the GPL-2 or later
|
|
*/
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
#include <errno.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
#include <config.h>
|
|
#include "ptrace.h"
|
|
|
|
#include "test.h"
|
|
#include "spawn_ptrace_child.h"
|
|
#include "config.h"
|
|
|
|
/* this should be sizeof(struct user), but that info is only found
|
|
* in the kernel asm/user.h which is not exported to userspace.
|
|
*/
|
|
#if defined(__i386__)
|
|
#define SIZEOF_USER 284
|
|
#elif defined(__x86_64__)
|
|
#define SIZEOF_USER 928
|
|
#else
|
|
#define SIZEOF_USER 0x1000 /* just pick a big number */
|
|
#endif
|
|
|
|
char *TCID = "ptrace06";
|
|
|
|
struct test_case_t {
|
|
int request;
|
|
long addr;
|
|
long data;
|
|
} test_cases[] = {
|
|
{
|
|
PTRACE_PEEKDATA,.addr = 0}, {
|
|
PTRACE_PEEKDATA,.addr = 1}, {
|
|
PTRACE_PEEKDATA,.addr = 2}, {
|
|
PTRACE_PEEKDATA,.addr = 3}, {
|
|
PTRACE_PEEKDATA,.addr = -1}, {
|
|
PTRACE_PEEKDATA,.addr = -2}, {
|
|
PTRACE_PEEKDATA,.addr = -3}, {
|
|
PTRACE_PEEKDATA,.addr = -4}, {
|
|
PTRACE_PEEKTEXT,.addr = 0}, {
|
|
PTRACE_PEEKTEXT,.addr = 1}, {
|
|
PTRACE_PEEKTEXT,.addr = 2}, {
|
|
PTRACE_PEEKTEXT,.addr = 3}, {
|
|
PTRACE_PEEKTEXT,.addr = -1}, {
|
|
PTRACE_PEEKTEXT,.addr = -2}, {
|
|
PTRACE_PEEKTEXT,.addr = -3}, {
|
|
PTRACE_PEEKTEXT,.addr = -4}, {
|
|
PTRACE_PEEKUSER,.addr = SIZEOF_USER + 1}, {
|
|
PTRACE_PEEKUSER,.addr = SIZEOF_USER + 2}, {
|
|
PTRACE_PEEKUSER,.addr = SIZEOF_USER + 3}, {
|
|
PTRACE_PEEKUSER,.addr = SIZEOF_USER + 4}, {
|
|
PTRACE_PEEKUSER,.addr = -1}, {
|
|
PTRACE_PEEKUSER,.addr = -2}, {
|
|
PTRACE_PEEKUSER,.addr = -3}, {
|
|
PTRACE_PEEKUSER,.addr = -4}, {
|
|
PTRACE_POKEDATA,.addr = 0}, {
|
|
PTRACE_POKEDATA,.addr = 1}, {
|
|
PTRACE_POKEDATA,.addr = 2}, {
|
|
PTRACE_POKEDATA,.addr = 3}, {
|
|
PTRACE_POKEDATA,.addr = -1}, {
|
|
PTRACE_POKEDATA,.addr = -2}, {
|
|
PTRACE_POKEDATA,.addr = -3}, {
|
|
PTRACE_POKEDATA,.addr = -4}, {
|
|
PTRACE_POKETEXT,.addr = 0}, {
|
|
PTRACE_POKETEXT,.addr = 1}, {
|
|
PTRACE_POKETEXT,.addr = 2}, {
|
|
PTRACE_POKETEXT,.addr = 3}, {
|
|
PTRACE_POKETEXT,.addr = -1}, {
|
|
PTRACE_POKETEXT,.addr = -2}, {
|
|
PTRACE_POKETEXT,.addr = -3}, {
|
|
PTRACE_POKETEXT,.addr = -4}, {
|
|
PTRACE_POKEUSER,.addr = SIZEOF_USER + 1}, {
|
|
PTRACE_POKEUSER,.addr = SIZEOF_USER + 2}, {
|
|
PTRACE_POKEUSER,.addr = SIZEOF_USER + 3}, {
|
|
PTRACE_POKEUSER,.addr = SIZEOF_USER + 4}, {
|
|
PTRACE_POKEUSER,.addr = -1}, {
|
|
PTRACE_POKEUSER,.addr = -2}, {
|
|
PTRACE_POKEUSER,.addr = -3}, {
|
|
PTRACE_POKEUSER,.addr = -4},
|
|
#ifdef PTRACE_GETREGS
|
|
{
|
|
PTRACE_GETREGS,.data = 0}, {
|
|
PTRACE_GETREGS,.data = 1}, {
|
|
PTRACE_GETREGS,.data = 2}, {
|
|
PTRACE_GETREGS,.data = 3}, {
|
|
PTRACE_GETREGS,.data = -1}, {
|
|
PTRACE_GETREGS,.data = -2}, {
|
|
PTRACE_GETREGS,.data = -3}, {
|
|
PTRACE_GETREGS,.data = -4},
|
|
#endif
|
|
#ifdef PTRACE_GETFGREGS
|
|
{
|
|
PTRACE_GETFGREGS,.data = 0}, {
|
|
PTRACE_GETFGREGS,.data = 1}, {
|
|
PTRACE_GETFGREGS,.data = 2}, {
|
|
PTRACE_GETFGREGS,.data = 3}, {
|
|
PTRACE_GETFGREGS,.data = -1}, {
|
|
PTRACE_GETFGREGS,.data = -2}, {
|
|
PTRACE_GETFGREGS,.data = -3}, {
|
|
PTRACE_GETFGREGS,.data = -4},
|
|
#endif
|
|
#ifdef PTRACE_SETREGS
|
|
{
|
|
PTRACE_SETREGS,.data = 0}, {
|
|
PTRACE_SETREGS,.data = 1}, {
|
|
PTRACE_SETREGS,.data = 2}, {
|
|
PTRACE_SETREGS,.data = 3}, {
|
|
PTRACE_SETREGS,.data = -1}, {
|
|
PTRACE_SETREGS,.data = -2}, {
|
|
PTRACE_SETREGS,.data = -3}, {
|
|
PTRACE_SETREGS,.data = -4},
|
|
#endif
|
|
#ifdef PTRACE_SETFGREGS
|
|
{
|
|
PTRACE_SETFGREGS,.data = 0}, {
|
|
PTRACE_SETFGREGS,.data = 1}, {
|
|
PTRACE_SETFGREGS,.data = 2}, {
|
|
PTRACE_SETFGREGS,.data = 3}, {
|
|
PTRACE_SETFGREGS,.data = -1}, {
|
|
PTRACE_SETFGREGS,.data = -2}, {
|
|
PTRACE_SETFGREGS,.data = -3}, {
|
|
PTRACE_SETFGREGS,.data = -4},
|
|
#endif
|
|
#if HAVE_DECL_PTRACE_GETSIGINFO
|
|
{
|
|
PTRACE_GETSIGINFO,.data = 0}, {
|
|
PTRACE_GETSIGINFO,.data = 1}, {
|
|
PTRACE_GETSIGINFO,.data = 2}, {
|
|
PTRACE_GETSIGINFO,.data = 3}, {
|
|
PTRACE_GETSIGINFO,.data = -1}, {
|
|
PTRACE_GETSIGINFO,.data = -2}, {
|
|
PTRACE_GETSIGINFO,.data = -3}, {
|
|
PTRACE_GETSIGINFO,.data = -4},
|
|
#endif
|
|
#if HAVE_DECL_PTRACE_SETSIGINFO
|
|
{
|
|
PTRACE_SETSIGINFO,.data = 0}, {
|
|
PTRACE_SETSIGINFO,.data = 1}, {
|
|
PTRACE_SETSIGINFO,.data = 2}, {
|
|
PTRACE_SETSIGINFO,.data = 3}, {
|
|
PTRACE_SETSIGINFO,.data = -1}, {
|
|
PTRACE_SETSIGINFO,.data = -2}, {
|
|
PTRACE_SETSIGINFO,.data = -3}, {
|
|
PTRACE_SETSIGINFO,.data = -4},
|
|
#endif
|
|
};
|
|
|
|
int TST_TOTAL = ARRAY_SIZE(test_cases);
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
size_t i;
|
|
long ret;
|
|
int saved_errno;
|
|
|
|
tst_parse_opts(argc, argv, NULL, NULL);
|
|
|
|
make_a_baby(argc, argv);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(test_cases); ++i) {
|
|
struct test_case_t *tc = &test_cases[i];
|
|
|
|
errno = 0;
|
|
ret =
|
|
ptrace(tc->request, pid, (void *)tc->addr,
|
|
(void *)tc->data);
|
|
saved_errno = errno;
|
|
if (ret != -1)
|
|
tst_resm(TFAIL,
|
|
"ptrace(%s, ..., %li, %li) returned %li instead of -1",
|
|
strptrace(tc->request), tc->addr, tc->data,
|
|
ret);
|
|
else if (saved_errno != EIO && saved_errno != EFAULT)
|
|
tst_resm(TFAIL,
|
|
"ptrace(%s, ..., %li, %li) expected errno EIO or EFAULT; actual: %i (%s)",
|
|
strptrace(tc->request), tc->addr, tc->data,
|
|
saved_errno, strerror(saved_errno));
|
|
else
|
|
tst_resm(TPASS,
|
|
"ptrace(%s, ..., %li, %li) failed as expected",
|
|
strptrace(tc->request), tc->addr, tc->data);
|
|
}
|
|
|
|
/* hopefully this worked */
|
|
ptrace(PTRACE_KILL, pid, NULL, NULL);
|
|
|
|
tst_exit();
|
|
}
|