blob: 3eac5a02b48af5ee196080ccec4cfe6ce67061f7 [file] [log] [blame]
/*
* 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 "usctest.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 {
enum __ptrace_request 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;
char *msg;
if ((msg = parse_opts(argc, argv, NULL, NULL)))
tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
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();
}