struct user . u_ar0
Subsystems (5)
H. Peter Anvin
reviewerI recently noticed that all architectures appear to have an entry n struct user called u_ar0:
struct user_pt_regs * u_ar0; /* Used by gdb to help find the values
for */
/* the registers. */
In all cases, u_ar0 is a pointer type, although the type of pointer varies with the architecture.
However, under no conditions does this field ever contain a pointer value! It is set by the a.out code and its derivatives as an offset, not a pointer value (there are a total of four references in the kernel, in arch/{m68k,blackfin}/kernel/process.c, arch/x86/ia32/ia32_aout.c and fs/binfmt_aout.c -- they are all functionally identical and write-only):
dump.u_ar0 = (void *)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump)));
Any reason to *NOT* change this field to "unsigned long"? <asm/user.h>, where struct user is defined, is not exported to userspace in any architecture as far as I can tell, although <linux/user.h>, which just contains #include <asm/user.h>, *is* exported (clearly a bug.)
-hpa
H. Peter Anvin
reviewerPATCH 1/1 Sanitize the type of struct user.u_ar0
struct user.u_ar0 is defined to contain a pointer offset on all architectures in which it is defined (all architectures which define an a.out format except SPARC.) However, it has a pointer type in the headers, which is pointless -- <asm/user.h> is not exported to userspace, and it just makes the code messy.
Redefine the field as "unsigned long" (which is the same size as a pointer on all Linux architectures) and change the setting code to user offsetof() instead of hand-coded arithmetic.
--- arch/blackfin/kernel/process.c | 2 +- arch/m68k/kernel/process.c | 2 +- arch/x86/ia32/ia32_aout.c | 2 +- fs/binfmt_aout.c | 2 +- include/asm-alpha/user.h | 2 +- include/asm-arm/user.h | 2 +- include/asm-avr32/user.h | 2 +- include/asm-blackfin/user.h | 2 +- include/asm-cris/user.h | 2 +- include/asm-h8300/user.h | 3 +-- include/asm-ia64/user.h | 2 +- include/asm-m32r/user.h | 2 +- include/asm-m68k/user.h | 3 +-- include/asm-mips/user.h | 2 +- include/asm-powerpc/user.h | 2 +- include/asm-s390/user.h | 3 +-- include/asm-sh/user.h | 2 +- include/asm-sh64/user.h | 2 +- include/asm-v850/user.h | 2 +- include/asm-x86/user_32.h | 2 +- include/asm-x86/user_64.h | 2 +- 21 files changed, 21 insertions(+), 24 deletions(-)
arch/blackfin/kernel/process.c +1 -1
@@ -257,7 +257,7 @@ void dump_thread(struct pt_regs *regs, struct user *dump) ((unsigned long )(TASK_SIZE - dump->start_stack)) >>PAGE_SHIFT ; - dump->u_ar0 = (struct user_regs_struct *)((int )&dump->regs - (int )dump); + dump->u_ar0 = offsetof(struct user , regs); dump->regs.r0 = regs->r0; dump->regs.r1 = regs->r1;
arch/m68k/kernel/process.c +1 -1
@@ -335,7 +335,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump)if (dump->start_stack <TASK_SIZE ) dump->u_ssize = ((unsigned long ) (TASK_SIZE - dump->start_stack)) >>PAGE_SHIFT ; - dump->u_ar0 = (struct user_regs_struct *)((int )&dump->regs - (int )dump); + dump->u_ar0 = offsetof(struct user , regs); sw = ((struct switch_stack *)regs) -1 ; dump->regs.d1 = regs->d1; dump->regs.d2 = regs->d2;
arch/x86/ia32/ia32_aout.c +1 -1
@@ -162,7 +162,7 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, u has_dumped =1 ; current->flags |=PF_DUMPCORE ;strncpy (dump.u_comm, current->comm,sizeof (current->comm)); - dump.u_ar0 = (u32)(((unsigned long )(&dump.regs)) - ((unsigned long )(&dump))); + dump.u_ar0 = offsetof(struct user32 , regs); dump.signal = signr;dump_thread32 (regs, &dump);
fs/binfmt_aout.c +1 -1
@@ -115,7 +115,7 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, u current->flags |=PF_DUMPCORE ;strncpy (dump.u_comm, current->comm,sizeof (dump.u_comm));#ifndef __sparc__ - dump.u_ar0 = (void *)(((unsigned long )(&dump.regs)) - ((unsigned long )(&dump))); + dump.u_ar0 = offsetof(struct user , regs);#endif dump.signal = signr;dump_thread (regs, &dump);
include/asm-alpha/user.h +1 -1
@@ -39,7 +39,7 @@ struct user {unsigned long start_data;/* data starting address */ unsigned long start_stack;/* stack starting address */ long int signal;/* signal causing core dump */ -struct regs * u_ar0;/* help gdb find registers */ +unsigned long u_ar0;/* help gdb find registers */ unsigned long magic;/* identifies a core file */ char u_comm[32 ];/* user command name */ };
include/asm-arm/user.h +1 -1
@@ -67,7 +67,7 @@ struct user{esp register. */ long int signal;/* Signal that caused the core dump. */ int reserved;/* No longer used */ -struct pt_regs * u_ar0;/* Used by gdb to help find the values for */ +unsigned long u_ar0;/* Used by gdb to help find the values for */ /* the registers. */ unsigned long magic;/* To uniquely identify a core file */ char u_comm[32 ];/* User command that was responsible */
include/asm-avr32/user.h +1 -1
@@ -51,7 +51,7 @@ struct user {unsigned long start_data;/* data starting address */ unsigned long start_stack;/* stack starting address */ long int signal;/* signal causing core dump */ -struct regs * u_ar0;/* help gdb find registers */ +unsigned long u_ar0;/* help gdb find registers */ unsigned long magic;/* identifies a core file */ char u_comm[32 ];/* user command name */ };
include/asm-blackfin/user.h +1 -1
@@ -75,7 +75,7 @@ struct user {esp register. */ long int signal;/* Signal that caused the core dump. */ int reserved;/* No longer used */ -struct user_regs_struct *u_ar0; +unsigned long u_ar0;/* Used by gdb to help find the values for */ /* the registers. */ unsigned long magic;/* To uniquely identify a core file */
include/asm-cris/user.h +1 -1
@@ -38,7 +38,7 @@ struct user {unsigned long start_data;/* data starting address */ unsigned long start_stack;/* stack starting address */ long int signal;/* signal causing core dump */ -struct regs * u_ar0;/* help gdb find registers */ +unsigned long u_ar0;/* help gdb find registers */ unsigned long magic;/* identifies a core file */ char u_comm[32 ];/* user command name */ };
include/asm-h8300/user.h +1 -2
@@ -62,8 +62,7 @@ struct user{esp register. */ long int signal;/* Signal that caused the core dump. */ int reserved;/* No longer used */ -struct user_regs_struct *u_ar0; -/* Used by gdb to help find the values for */ +unsigned long u_ar0;/* Used by gdb to help find the values for */ /* the registers. */ unsigned long magic;/* To uniquely identify a core file */ char u_comm[32 ];/* User command that was responsible */
include/asm-ia64/user.h +1 -1
@@ -44,7 +44,7 @@ struct user {unsigned long start_data;/* data starting address */ unsigned long start_stack;/* stack starting address */ long int signal;/* signal causing core dump */ -struct regs * u_ar0;/* help gdb find registers */ +unsigned long u_ar0;/* help gdb find registers */ unsigned long magic;/* identifies a core file */ char u_comm[32 ];/* user command name */ };
include/asm-m32r/user.h +1 -1
@@ -38,7 +38,7 @@ struct user {unsigned long start_data;/* data starting address */ unsigned long start_stack;/* stack starting address */ long int signal;/* signal causing core dump */ -struct regs * u_ar0;/* help gdb find registers */ +unsigned long u_ar0;/* help gdb find registers */ unsigned long magic;/* identifies a core file */ char u_comm[32 ];/* user command name */ };
include/asm-m68k/user.h +1 -2
@@ -72,8 +72,7 @@ struct user{esp register. */ long int signal;/* Signal that caused the core dump. */ int reserved;/* No longer used */ -struct user_regs_struct *u_ar0; -/* Used by gdb to help find the values for */ +unsigned long u_ar0;/* Used by gdb to help find the values for */ /* the registers. */ struct user_m68kfp_struct * u_fpstate;/* Math Co-processor pointer. */ unsigned long magic;/* To uniquely identify a core file */
include/asm-mips/user.h +1 -1
@@ -46,7 +46,7 @@ struct user {unsigned long start_data;/* data starting address */ unsigned long start_stack;/* stack starting address */ long int signal;/* signal causing core dump */ -struct regs * u_ar0;/* help gdb find registers */ +unsigned long u_ar0;/* help gdb find registers */ unsigned long magic;/* identifies a core file */ char u_comm[32 ];/* user command name */ };
include/asm-powerpc/user.h +1 -1
@@ -40,7 +40,7 @@ struct user {unsigned long start_data;/* data starting address */ unsigned long start_stack;/* stack starting address */ long int signal;/* signal causing core dump */ -struct regs * u_ar0;/* help gdb find registers */ +unsigned long u_ar0;/* help gdb find registers */ unsigned long magic;/* identifies a core file */ char u_comm[32 ];/* user command name */ };
include/asm-s390/user.h +1 -2
@@ -63,8 +63,7 @@ struct user {the top of the stack is always found in the esp register. */ long int signal;/* Signal that caused the core dump. */ -struct user_regs_struct *u_ar0; -/* Used by gdb to help find the values for */ +unsigned long u_ar0;/* Used by gdb to help find the values for */ /* the registers. */ unsigned long magic;/* To uniquely identify a core file */ char u_comm[32 ];/* User command that was responsible */
include/asm-sh/user.h +1 -1
@@ -45,7 +45,7 @@ struct user {unsigned long start_data;/* data starting address */ unsigned long start_stack;/* stack starting address */ long int signal;/* signal causing core dump */ -struct regs * u_ar0;/* help gdb find registers */ +unsigned long u_ar0;/* help gdb find registers */ struct user_fpu_struct * u_fpstate;/* Math Co-processor pointer */ unsigned long magic;/* identifies a core file */ char u_comm[32 ];/* user command name */
include/asm-sh64/user.h +1 -1
@@ -55,7 +55,7 @@ struct user {unsigned long start_data;/* data starting address */ unsigned long start_stack;/* stack starting address */ long int signal;/* signal causing core dump */ -struct regs * u_ar0;/* help gdb find registers */ +unsigned long u_ar0;/* help gdb find registers */ struct user_fpu_struct * u_fpstate;/* Math Co-processor pointer */ unsigned long magic;/* identifies a core file */ char u_comm[32 ];/* user command name */
include/asm-v850/user.h +1 -1
@@ -40,7 +40,7 @@ struct user {unsigned long start_data;/* data starting address */ unsigned long start_stack;/* stack starting address */ long int signal;/* signal causing core dump */ -struct regs * u_ar0;/* help gdb find registers */ +unsigned long u_ar0;/* help gdb find registers */ unsigned long magic;/* identifies a core file */ char u_comm[32 ];/* user command name */ };
include/asm-x86/user_32.h +1 -1
@@ -106,7 +106,7 @@ struct user{esp register. */ long int signal;/* Signal that caused the core dump. */ int reserved;/* No longer used */ -struct user_pt_regs * u_ar0;/* Used by gdb to help find the values for */ +unsigned long u_ar0;/* Used by gdb to help find the values for */ /* the registers. */ struct user_i387_struct * u_fpstate;/* Math Co-processor pointer. */ unsigned long magic;/* To uniquely identify a core file */
include/asm-x86/user_64.h +1 -1
@@ -97,7 +97,7 @@ struct user{long int signal;/* Signal that caused the core dump. */ int reserved;/* No longer used */ int pad1; -struct user_pt_regs * u_ar0;/* Used by gdb to help find the values for */ +unsigned long u_ar0;/* Used by gdb to help find the values for */ /* the registers. */ struct user_i387_struct * u_fpstate;/* Math Co-processor pointer. */ unsigned long magic;/* To uniquely identify a core file */
Signature · 1 line
1.5.3.4
Quoted 16 lines · H. Peter Anvin
I recently noticed that all architectures appear to have an entry n struct user called
u_ar0:struct
user_pt_regs*u_ar0; /* Used by gdb to help find the values
for *//* the registers. */In all cases,
u_ar0is a pointer type, although the type of pointer varies with the architecture.However, under no conditions does this field ever contain a pointer value! It is set by the a.out code and its derivatives as an offset, not a pointer value (there are a total of four references in the kernel, in
arch/{m68k,blackfin}/kernel/process.c,arch/x86/ia32/ia32_aout.candfs/binfmt_aout.c-- they are all functionally identical and write-only):
Quoted 7 lines
dump.u_ar0 = (void *)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump)));
Any reason to *NOT* change this field to "unsigned long"? <
asm/user.h>, where struct user is defined, is not exported to userspace in any architecture as far as I can tell, although <linux/user.h>, which just contains #include <asm/user.h>, *is* exported (clearly a bug.)
Blackfin doesnt support a.out, so it may be easier to just change it to "reserved2" (assuming this structure is part of our ABI), or delete it (assuming the structure is internal to the kernel only). -mike
H. Peter Anvin
reviewerQuoted 5 lines · Mike Frysinger
Blackfin doesnt support a.out, so it may be easier to just change it to "reserved2" (assuming this structure is part of our ABI), or delete it (assuming the structure is internal to the kernel only). -mike
Blackfin explicitly sets in in arch/blackfin/kernel/process.c, so you might want to consider what it is used for. As far as a.out is concerned, it appears to be part of the core dump format.
-hpa