Skip to contentSkip to conversation

struct user . u_ar0

PATCH New H. Peter Anvin 2 participants 4 messages Oct 28, 2007

Subsystems (5)
lore
Share & tools
lore

H. Peter Anvin

author reviewer
#0 lore raw

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_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

author reviewer
#1 lore raw

PATCH 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.

Cc Linux Arch Mailing List <[email protected]>
Cc Bryan Wu <[email protected]>
Cc Roman Zippel <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Richard Henderson <[email protected]>
Cc Ivan Kokshaysky <[email protected]>
Cc Russell King <[email protected]>
Cc Lennert Buytenhek <[email protected]>
Cc Håvard Skinnemoen <[email protected]>
Cc Mikael Starvik <[email protected]>
Cc Yoshinori Sato <[email protected]>
Cc Tony Luck <[email protected]>
Cc Hirokazu Takata <[email protected]>
Cc Ralf Baechle <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Martin Schwidefsky <[email protected]>
Cc Heiko Carstens <[email protected]>
Cc Paul Mundt <[email protected]>
---
 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
index 9124467..5c08004 100644
@@ -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
index 3ee9186..f85b928 100644
@@ -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
index 731aac1..c489fee 100644
@@ -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
index e176d19..9a00063 100644
@@ -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
index 7e417fc..a4eb6a4 100644
@@ -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
index 3e8b0f8..825c1e7 100644
@@ -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
index 060fb3a..7e9152f 100644
@@ -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
index abc3462..afe6a0e 100644
@@ -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
index 2538e2a..73e60fc 100644
@@ -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
index 6c64f99..14a9e18 100644
@@ -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
index 78e5a20..8b98211 100644
@@ -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
index 035258d..03b3c11 100644
@@ -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
index 8c56cca..f1f478d 100644
@@ -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
index 61f2a09..e8ca4d9 100644
@@ -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
index e59ade4..2f0223c 100644
@@ -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
index 1dc74ba..1b050e3 100644
@@ -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
index d1b8511..a1908c1 100644
@@ -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
index eb3b33e..69b6cb6 100644
@@ -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
index ccf4cea..a915d29 100644
@@ -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
index 0e85d2a..2373f73 100644
@@ -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
index 12785c6..d7d0e1d 100644
@@ -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
#2 lore raw
In reply to H. Peter Anvin
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_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):

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

author reviewer
#3 lore raw
Quoted 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