Allow separate printing of struct user_desc.entry_number
Kernel reads only entry_number field in the beginning of the get_thread_area syscall handler. Let's replicate this behaviour. * defs.h (enum user_desc_print_filter): New enumeration. (print_user_desc): Add an argument for signalling which part of the structure should be printed. * clone.c (print_tls_arg): Update print_user_desc call. * ldt.c (print_user_desc): Add filter argument. Print entry_number on entering and the rest on exiting. Store entering value of the entry_number field in order to print the updated value in the impossible case of changed entry_number value. (SYS_FUNC(modify_ldt), SYS_FUNC(set_thread_area)): Update print_user_desc call. (SYS_FUNC(get_thread_area)): Call print_user_desc with USER_DESC_ENTERING format argument on entering and with USER_DESC_EXITING on exiting.
This commit is contained in:
parent
1e23e9aab8
commit
0c7e458044
2
clone.c
2
clone.c
@ -84,7 +84,7 @@ print_tls_arg(struct tcb *const tcp, const kernel_ulong_t addr)
|
||||
if (current_personality == 1)
|
||||
# endif
|
||||
{
|
||||
print_user_desc(tcp, tcp->u_arg[ARG_TLS]);
|
||||
print_user_desc(tcp, tcp->u_arg[ARG_TLS], USER_DESC_BOTH);
|
||||
}
|
||||
# if SUPPORTED_PERSONALITIES > 1
|
||||
else
|
||||
|
16
defs.h
16
defs.h
@ -768,7 +768,21 @@ extern void print_itimerval32(struct tcb *, kernel_ulong_t addr);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRUCT_USER_DESC
|
||||
extern void print_user_desc(struct tcb *, kernel_ulong_t addr);
|
||||
/**
|
||||
* Filter what to print from the point of view of the get_thread_area syscall.
|
||||
* Kernel copies only entry_number field at first and then tries to write the
|
||||
* whole structure.
|
||||
*/
|
||||
enum user_desc_print_filter {
|
||||
/* Print the "entering" part of struct user_desc - entry_number. */
|
||||
USER_DESC_ENTERING = 1,
|
||||
/* Print the "exiting" part of the structure. */
|
||||
USER_DESC_EXITING = 2,
|
||||
USER_DESC_BOTH = USER_DESC_ENTERING | USER_DESC_EXITING,
|
||||
};
|
||||
|
||||
extern void print_user_desc(struct tcb *, kernel_ulong_t addr,
|
||||
enum user_desc_print_filter filter);
|
||||
#endif
|
||||
|
||||
/* Strace log generation machinery.
|
||||
|
104
ldt.c
104
ldt.c
@ -42,30 +42,94 @@
|
||||
# include "xstring.h"
|
||||
|
||||
void
|
||||
print_user_desc(struct tcb *const tcp, const kernel_ulong_t addr)
|
||||
print_user_desc(struct tcb *const tcp, const kernel_ulong_t addr,
|
||||
enum user_desc_print_filter filter)
|
||||
{
|
||||
struct user_desc desc;
|
||||
unsigned *entry_number = get_tcb_priv_data(tcp);
|
||||
|
||||
if (umove_or_printaddr(tcp, addr, &desc))
|
||||
return;
|
||||
switch (filter) {
|
||||
case USER_DESC_ENTERING:
|
||||
if (umove_or_printaddr(tcp, addr, &desc.entry_number))
|
||||
return;
|
||||
|
||||
PRINT_FIELD_ID("{", desc, entry_number);
|
||||
PRINT_FIELD_0X(", ", desc, base_addr);
|
||||
PRINT_FIELD_0X(", ", desc, limit);
|
||||
PRINT_FIELD_U_CAST(", ", desc, seg_32bit, unsigned int);
|
||||
PRINT_FIELD_U_CAST(", ", desc, contents, unsigned int);
|
||||
PRINT_FIELD_U_CAST(", ", desc, read_exec_only, unsigned int);
|
||||
PRINT_FIELD_U_CAST(", ", desc, limit_in_pages, unsigned int);
|
||||
PRINT_FIELD_U_CAST(", ", desc, seg_not_present, unsigned int);
|
||||
PRINT_FIELD_U_CAST(", ", desc, useable, unsigned int);
|
||||
break;
|
||||
|
||||
case USER_DESC_EXITING:
|
||||
if (!addr || !verbose(tcp))
|
||||
return;
|
||||
if (syserror(tcp) || umove(tcp, addr, &desc)) {
|
||||
if (entry_number)
|
||||
tprints(", ...}");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case USER_DESC_BOTH:
|
||||
if (umove_or_printaddr(tcp, addr, &desc))
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (filter & USER_DESC_ENTERING) {
|
||||
PRINT_FIELD_ID("{", desc, entry_number);
|
||||
|
||||
/*
|
||||
* If we don't print the whole structure now, let's save it for
|
||||
* later.
|
||||
*/
|
||||
if (filter == USER_DESC_ENTERING) {
|
||||
entry_number = xmalloc(sizeof(*entry_number));
|
||||
|
||||
*entry_number = desc.entry_number;
|
||||
set_tcb_priv_data(tcp, entry_number, free);
|
||||
}
|
||||
}
|
||||
|
||||
if (filter & USER_DESC_EXITING) {
|
||||
/*
|
||||
* It should be the same in case of get_thread_area, but we can
|
||||
* never be sure...
|
||||
*/
|
||||
if (filter == USER_DESC_EXITING) {
|
||||
if (entry_number) {
|
||||
if (*entry_number != desc.entry_number) {
|
||||
if ((int) desc.entry_number == -1)
|
||||
tprints(" => -1");
|
||||
else
|
||||
tprintf(" => %u",
|
||||
desc.entry_number);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* This is really strange. If we are here, it
|
||||
* means that we failed on entering but somehow
|
||||
* succeeded on exiting.
|
||||
*/
|
||||
PRINT_FIELD_ID(" => {", desc, entry_number);
|
||||
}
|
||||
}
|
||||
|
||||
PRINT_FIELD_0X(", ", desc, base_addr);
|
||||
PRINT_FIELD_0X(", ", desc, limit);
|
||||
PRINT_FIELD_U_CAST(", ", desc, seg_32bit, unsigned int);
|
||||
PRINT_FIELD_U_CAST(", ", desc, contents, unsigned int);
|
||||
PRINT_FIELD_U_CAST(", ", desc, read_exec_only, unsigned int);
|
||||
PRINT_FIELD_U_CAST(", ", desc, limit_in_pages, unsigned int);
|
||||
PRINT_FIELD_U_CAST(", ", desc, seg_not_present, unsigned int);
|
||||
PRINT_FIELD_U_CAST(", ", desc, useable, unsigned int);
|
||||
|
||||
# ifdef HAVE_STRUCT_USER_DESC_LM
|
||||
/* lm is totally ignored for 32-bit processes */
|
||||
if (current_klongsize == 8)
|
||||
PRINT_FIELD_U_CAST(", ", desc, lm, unsigned int);
|
||||
/* lm is totally ignored for 32-bit processes */
|
||||
if (current_klongsize == 8)
|
||||
PRINT_FIELD_U_CAST(", ", desc, lm, unsigned int);
|
||||
# endif /* HAVE_STRUCT_USER_DESC_LM */
|
||||
|
||||
tprints("}");
|
||||
tprints("}");
|
||||
}
|
||||
}
|
||||
|
||||
SYS_FUNC(modify_ldt)
|
||||
@ -75,7 +139,7 @@ SYS_FUNC(modify_ldt)
|
||||
if (tcp->u_arg[2] != sizeof(struct user_desc))
|
||||
printaddr(tcp->u_arg[1]);
|
||||
else
|
||||
print_user_desc(tcp, tcp->u_arg[1]);
|
||||
print_user_desc(tcp, tcp->u_arg[1], USER_DESC_BOTH);
|
||||
tprintf(", %" PRI_klu, tcp->u_arg[2]);
|
||||
|
||||
return 0;
|
||||
@ -97,7 +161,7 @@ SYS_FUNC(modify_ldt)
|
||||
SYS_FUNC(set_thread_area)
|
||||
{
|
||||
if (entering(tcp)) {
|
||||
print_user_desc(tcp, tcp->u_arg[0]);
|
||||
print_user_desc(tcp, tcp->u_arg[0], USER_DESC_BOTH);
|
||||
} else {
|
||||
struct user_desc desc;
|
||||
|
||||
@ -117,8 +181,8 @@ SYS_FUNC(set_thread_area)
|
||||
|
||||
SYS_FUNC(get_thread_area)
|
||||
{
|
||||
if (exiting(tcp))
|
||||
print_user_desc(tcp, tcp->u_arg[0]);
|
||||
print_user_desc(tcp, tcp->u_arg[0],
|
||||
entering(tcp) ? USER_DESC_ENTERING : USER_DESC_EXITING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user