Skip to content

Commit

Permalink
linux-user: fix QEMU_STRACE=1 segfault
Browse files Browse the repository at this point in the history
While debugging some issues with QEMU_STRACE I stumbled over segmentation
faults that were pretty reproducible. Turns out we tried to treat a
normal return value as errno, resulting in an access over array boundaries
for the resolution.

Fix this by allowing failure to resolve invalid errnos into strings.

Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
  • Loading branch information
agraf authored and Riku Voipio committed Feb 2, 2012
1 parent 583359a commit 962b289
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 4 deletions.
18 changes: 14 additions & 4 deletions linux-user/strace.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,13 @@ print_ipc(const struct syscallname *name,
static void
print_syscall_ret_addr(const struct syscallname *name, abi_long ret)
{
if( ret == -1 ) {
gemu_log(" = -1 errno=%d (%s)\n", errno, target_strerror(errno));
char *errstr = NULL;

if (ret == -1) {
errstr = target_strerror(errno);
}
if ((ret == -1) && errstr) {
gemu_log(" = -1 errno=%d (%s)\n", errno, errstr);
} else {
gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
}
Expand Down Expand Up @@ -1515,14 +1520,19 @@ void
print_syscall_ret(int num, abi_long ret)
{
int i;
char *errstr = NULL;

for(i=0;i<nsyscalls;i++)
if( scnames[i].nr == num ) {
if( scnames[i].result != NULL ) {
scnames[i].result(&scnames[i],ret);
} else {
if( ret < 0 ) {
gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n", -ret, target_strerror(-ret));
if (ret < 0) {
errstr = target_strerror(-ret);
}
if (errstr) {
gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n",
-ret, errstr);
} else {
gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
}
Expand Down
3 changes: 3 additions & 0 deletions linux-user/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,9 @@ static inline int is_error(abi_long ret)

char *target_strerror(int err)
{
if ((err >= ERRNO_TABLE_SIZE) || (err < 0)) {
return NULL;
}
return strerror(target_to_host_errno(err));
}

Expand Down

0 comments on commit 962b289

Please sign in to comment.