Commit 9a282cbb authored by Dmitry Safonov's avatar Dmitry Safonov Committed by Andrei Vagin

ia32/futex: add dumping compat_robust_list

The kernel keeps two different pointers for 32-bit and 64-bit futex
lists: robust_list and compat_robust_list in task_struct.
So, dump compat_robust_list for ia32 tasks.

Note: this means that one can set *both* compat_robust_list and
robust_list pointers by using as we're here 32-bit and 64-bit syscalls.
That's one of mixed-bitness application questions.
For simplification (and omitting more syscalls), we dump here only
one of the pointers.
Signed-off-by: 's avatarDmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent d011a9fb
......@@ -11,4 +11,6 @@ static inline void core_put_tls(CoreEntry *core, tls_t tls)
core->ti_aarch64->tls = tls;
}
#define get_task_futex_robust_list_compat(pid, info) -1
#endif
......@@ -11,4 +11,6 @@ static inline void core_put_tls(CoreEntry *core, tls_t tls)
core->ti_arm->tls = tls;
}
#define get_task_futex_robust_list_compat(pid, info) -1
#endif
......@@ -8,4 +8,6 @@ extern void arch_free_thread_info(CoreEntry *core);
#define core_put_tls(core, tls)
#define get_task_futex_robust_list_compat(pid, info) -1
#endif
......@@ -7,6 +7,7 @@
#include "types.h"
#include "log.h"
#include "asm/compat.h"
#include "asm/parasite-syscall.h"
#include "asm/restorer.h"
#include <compel/asm/fpu.h>
......@@ -436,3 +437,74 @@ int restore_gpregs(struct rt_sigframe *f, UserX86RegsEntry *r)
}
return 0;
}
struct syscall_args32 {
uint32_t nr, arg0, arg1, arg2, arg3, arg4, arg5;
};
static void do_full_int80(struct syscall_args32 *args)
{
register unsigned long bp asm("bp") = args->arg5;
asm volatile ("int $0x80"
: "+a" (args->nr),
"+b" (args->arg0), "+c" (args->arg1), "+d" (args->arg2),
"+S" (args->arg3), "+D" (args->arg4), "+r" (bp)
: : "r8", "r9", "r10", "r11");
args->arg5 = bp;
}
static int get_robust_list32(pid_t pid, uintptr_t head, uintptr_t len)
{
struct syscall_args32 s = {
.nr = __NR32_get_robust_list,
.arg0 = pid,
.arg1 = (uint32_t)head,
.arg2 = (uint32_t)len,
};
do_full_int80(&s);
return (int)s.nr;
}
static int set_robust_list32(uint32_t head, uint32_t len)
{
struct syscall_args32 s = {
.nr = __NR32_set_robust_list,
.arg0 = head,
.arg1 = len,
};
do_full_int80(&s);
return (int)s.nr;
}
int get_task_futex_robust_list_compat(pid_t pid, ThreadCoreEntry *info)
{
void *mmap32;
int ret = -1;
mmap32 = alloc_compat_syscall_stack();
if (!mmap32)
return -1;
ret = get_robust_list32(pid, (uintptr_t)mmap32, (uintptr_t)mmap32 + 4);
if (ret == -ENOSYS) {
/* Check native get_task_futex_robust_list() for details. */
if (set_robust_list32(0, 0) == (uint32_t)-ENOSYS) {
info->futex_rla = 0;
info->futex_rla_len = 0;
ret = 0;
}
} else if (ret == 0) {
uint32_t *arg1 = (uint32_t*)mmap32;
info->futex_rla = *arg1;
info->futex_rla_len = *(arg1 + 1);
ret = 0;
}
free_compat_syscall_stack(mmap32);
return ret;
}
......@@ -4,6 +4,7 @@
extern int save_task_regs(void *, user_regs_struct_t *, user_fpregs_struct_t *);
extern int arch_alloc_thread_info(CoreEntry *core);
extern void arch_free_thread_info(CoreEntry *core);
extern int get_task_futex_robust_list_compat(pid_t pid, ThreadCoreEntry *info);
static inline void core_put_tls(CoreEntry *core, tls_t tls)
{
......
......@@ -673,8 +673,18 @@ int dump_thread_core(int pid, CoreEntry *core, const struct parasite_dump_thread
ThreadCoreEntry *tc = core->thread_core;
ret = collect_lsm_profile(pid, tc->creds);
if (!ret)
if (!ret) {
/*
* XXX: It's possible to set two: 32-bit and 64-bit
* futex list's heads. That makes about no sense, but
* it's possible. Until we meet such application, dump
* only one: native or compat futex's list pointer.
*/
if (!core_is_compat(core))
ret = get_task_futex_robust_list(pid, tc);
else
ret = get_task_futex_robust_list_compat(pid, tc);
}
if (!ret)
ret = dump_sched_info(pid, tc);
if (!ret) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment