diff mbox

kernel/libc uapi changes for y2038

Message ID 2664016.bYZKg6FQqR@wuerfel
State Not Applicable
Headers show

Commit Message

Arnd Bergmann May 18, 2015, 9:53 a.m. UTC
In the patch series I posted recently [1], I introduce new system calls to deal
with modified data structures, but left the question open on how these should
be best accessed from libc. The patches introduce a new __kernel_time64_t type
and based on that five new data structured: struct __kernel_timespec,
struct __kernel_itimerspec, struct __kernel_stat, struct __kernel_rusage,
and struct __kernel_timex. This works fine for the case when all libc
implementations provide their own definitions to user space, but not for
the simplest case (e.g. klibc) where the user-visible structures come directly
from the kernel uapi headers.

I still don't know what model the various libc developers prefer, so here is
an alternative approach, as a patch on top of the previous series:

Now, we rename the original structures to struct __old_kernel_*, and use a
macro to define either the __old_kernel_* or the __kernel_* structure name
to the name we actually want in user space, based on a __KERNEL_TIME_BITS
macro that can be set to either 32 or 64 for 32-bit architectures by
the libc. Depending on that macro, the compiler will either see one
of these combinations (for each of the five structures):

a) __BITS_PER_LONG == 32 && __KERNEL_TIME_BITS == 32:

   struct timespec              based on 32-bit __kernel_time_t
   struct __kernel_timespec     based on 64-bit __kernel_time64_t

b) __BITS_PER_LONG == 64 && __KERNEL_TIME_BITS == 64:

   struct timespec              based on 64-bit __kernel_time_t
   struct __kernel_timespec     based on 64-bit __kernel_time64_t

c) __BITS_PER_LONG == 32 && __KERNEL_TIME_BITS == 64:

   struct __old_kernel_timespec based on 32-bit __kernel_time_t
   struct timespec              based on 64-bit __kernel_time64_t

Would this work for everyone?  Any alternative suggestions?

	Arnd

[1] http://git.kernel.org/cgit/linux/kernel/git/arnd/playground.git/log/?h=y2038-syscalls
    https://lwn.net/Articles/643407/

Comments

Thorsten Glaser May 18, 2015, 12:16 p.m. UTC | #1
Arnd Bergmann dixit:

>In the patch series I posted recently [1], I introduce new system calls to deal
>with modified data structures, but left the question open on how these should
>be best accessed from libc. The patches introduce a new __kernel_time64_t type

Can we please have ioctls fixed for mixed 32/64-bit systems
such as MIPS (o32/n32/n64) and x86 (i386/x32/amd64) first,
before even more such chance for breakage is introduced?

I still need to use an amd64 chroot on my x32 system to do
things such as set up iptables, because those ioctls break,
because they contain data structures that contain, well,
time types. Your proposal has a nōn-zero chance to bring
these issues to i386 (and other architectures).

Thanks,
//mirabilos
Arnd Bergmann May 18, 2015, 1:32 p.m. UTC | #2
On Monday 18 May 2015 12:16:48 Thorsten Glaser wrote:
> Arnd Bergmann dixit:
> 
> >In the patch series I posted recently [1], I introduce new system calls to deal
> >with modified data structures, but left the question open on how these should
> >be best accessed from libc. The patches introduce a new __kernel_time64_t type
> 
> Can we please have ioctls fixed for mixed 32/64-bit systems
> such as MIPS (o32/n32/n64) and x86 (i386/x32/amd64) first,
> before even more such chance for breakage is introduced?

It's hard because we don't even know what ioctls are affected at this point,
and I was hoping to get this part merged as a stepping stone in the process
of finding out.

The problem is that there are so many different cases we have to worry
about just for time_t:

a) ioctls that pass a data structure from include/uapi/ with time_t and
   have a properly defined (using _IOW()/_IOR()/_IORW()) command number:
   these are easy enough to find and fix.

b) ioctls that have a data structure as before but define their ioctl
   commands differently (e.g. using a literal number). I don't think
   we can fix them before we introduce the __KERNEL_TIME_BITS macro
   from my patch, because user space needs to see a different command
   number here, and we have a lot of these.

c) ioctls that are defined ad-hoc, without any uapi header containing
   the structure, but using a proper _IOW()/_IOR()/_IORW() macro.
   These are much harder to find than a), but just as easy to fix

d) ioctls that are defined ad-hoc based on a time_t value and with
   a wrong command number.
   These will be broken no matter what we do, and our only hope is
   to find all applications using them so we can fix the user space
   sources.

e) ioctls that pass a time value as a 'long' or '__u32' instead of
   'time_t'. Fixing them requires adding new ioctl commands to let
   them work beyond 2038, independent of what we do here.

f) ioctls that use structures with pointers to other structures that
   are not defined in the uapi headers. (this might not be a problem,
   I haven't been able to figure out of these are real)

All of the above are currently broken for x32, but fixing them will
likely take a few years and leave x32 still broken because of other
uses of __kernel_long_t in ioctl.

MIPS on the other hand is no more broken than any of the other 32-bit
ABIs, because it does not use 64-bit __kernel_long_t in its n32 ABI.
 
> I still need to use an amd64 chroot on my x32 system to do
> things such as set up iptables, because those ioctls break,
> because they contain data structures that contain, well,
> time types. Your proposal has a non-zero chance to bring
> these issues to i386 (and other architectures).

We should indeed not start widely deploying user space with 64-bit time_t
on 32-bit architectures until we found and fixed a good part of the
ioctls. My plan at this point is to eliminate all uses of time_t in
the kernel and replace them with time64_t or other safe types.
This way, we will eventually find all code that passes 32-bit time types
to user space and can fix it. This will take care of the time_t
related problems on x32 as well.

	Arnd
Thorsten Glaser May 18, 2015, 5:03 p.m. UTC | #3
fup2p, this is offtopic for most lists

Arnd Bergmann dixit:

>It's hard because we don't even know what ioctls are affected at this point,
>and I was hoping to get this part merged as a stepping stone in the process
>of finding out.

Oh okay.

>e) ioctls that pass a time value as a 'long' or '__u32' instead of
>   'time_t'. Fixing them requires adding new ioctl commands to let
>   them work beyond 2038, independent of what we do here.

Yeah, that’s going to be fun.

>MIPS on the other hand is no more broken than any of the other 32-bit
>ABIs, because it does not use 64-bit __kernel_long_t in its n32 ABI.

I have heard from a MIPS porter that one of the flavours suffers
from similar problems as x32, just not to that extent. But I
don’t recall my source…

>ioctls. My plan at this point is to eliminate all uses of time_t in
>the kernel and replace them with time64_t or other safe types.
>This way, we will eventually find all code that passes 32-bit time types
>to user space and can fix it. This will take care of the time_t
>related problems on x32 as well.

Ah, interesting approach. And existing userspace, as well as new
userspace that does not declare 64-bit time_t readiness, is still
safe on currently-not-broken architectures? So, there’s enough time
to fix this before the various libcs turn that on (and it had better
be fixed by then, because it becomes ABI by then). Nice idea.

I am wondering a bit about the ioctls being hard to find. I have
not much experience with kernel programming, and even less with
Linux than with MS-DOS and BSD, but should not each driver have
a central ioctl entry point, from which it should cast the user
space data into a (possibly locally declared) structure?

bye,
//mirabilos
Arnd Bergmann May 18, 2015, 8:35 p.m. UTC | #4
On Monday 18 May 2015 17:03:08 Thorsten Glaser wrote:

> >MIPS on the other hand is no more broken than any of the other 32-bit
> >ABIs, because it does not use 64-bit __kernel_long_t in its n32 ABI.
> 
> I have heard from a MIPS porter that one of the flavours suffers
> from similar problems as x32, just not to that extent. But I
> don’t recall my source…

MIPS n32 has a lot of the same issues as x86 x32, but I'm pretty
sure that the time_t one is not among them.

> >ioctls. My plan at this point is to eliminate all uses of time_t in
> >the kernel and replace them with time64_t or other safe types.
> >This way, we will eventually find all code that passes 32-bit time types
> >to user space and can fix it. This will take care of the time_t
> >related problems on x32 as well.
> 
> Ah, interesting approach. And existing userspace, as well as new
> userspace that does not declare 64-bit time_t readiness, is still
> safe on currently-not-broken architectures? So, there’s enough time
> to fix this before the various libcs turn that on (and it had better
> be fixed by then, because it becomes ABI by then). Nice idea.

Correct. Another aspect of the approach I'm taking is that the
system-call implementation is shared between the native 64-bit
case and the new 32-bit case, while the handling for the existing
syscalls on 32-bit architectures is shared with the 32-bit compat
code on 64-bit architectures. This means if we introduce a bug
in either of them, we will find out very quickly and don't have
to wait until people start using 64-bit time_t on 32-bit user land.

> I am wondering a bit about the ioctls being hard to find. I have
> not much experience with kernel programming, and even less with
> Linux than with MS-DOS and BSD, but should not each driver have
> a central ioctl entry point, from which it should cast the user
> space data into a (possibly locally declared) structure?

Yes, that's how it works, but unfortunately we have a few thousand
drivers that declare an ioctl function, and I hope to do something
better than brute-force search all of them. The other point is that
we really need to fix all y2038-related bug in drivers, not just
the ones in ioctl. This includes things like file systems storing
time in 32-bit units on disk, or drivers trying to measure how much
time has elapsed without communicating that value elsewhere, but
failing when the time_t number goes negative.

	Arnd
John Stultz May 19, 2015, 5:54 p.m. UTC | #5
On Mon, May 18, 2015 at 2:53 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> In the patch series I posted recently [1], I introduce new system calls to deal
> with modified data structures, but left the question open on how these should
> be best accessed from libc. The patches introduce a new __kernel_time64_t type
> and based on that five new data structured: struct __kernel_timespec,
> struct __kernel_itimerspec, struct __kernel_stat, struct __kernel_rusage,
> and struct __kernel_timex. This works fine for the case when all libc
> implementations provide their own definitions to user space, but not for
> the simplest case (e.g. klibc) where the user-visible structures come directly
> from the kernel uapi headers.
>
> I still don't know what model the various libc developers prefer, so here is
> an alternative approach, as a patch on top of the previous series:
>
> Now, we rename the original structures to struct __old_kernel_*, and use a
> macro to define either the __old_kernel_* or the __kernel_* structure name
> to the name we actually want in user space, based on a __KERNEL_TIME_BITS
> macro that can be set to either 32 or 64 for 32-bit architectures by
> the libc. Depending on that macro, the compiler will either see one
> of these combinations (for each of the five structures):
>
> a) __BITS_PER_LONG == 32 && __KERNEL_TIME_BITS == 32:
>
>    struct timespec              based on 32-bit __kernel_time_t
>    struct __kernel_timespec     based on 64-bit __kernel_time64_t
>
> b) __BITS_PER_LONG == 64 && __KERNEL_TIME_BITS == 64:
>
>    struct timespec              based on 64-bit __kernel_time_t
>    struct __kernel_timespec     based on 64-bit __kernel_time64_t
>
> c) __BITS_PER_LONG == 32 && __KERNEL_TIME_BITS == 64:
>
>    struct __old_kernel_timespec based on 32-bit __kernel_time_t
>    struct timespec              based on 64-bit __kernel_time64_t
>
> Would this work for everyone?  Any alternative suggestions?
>
>         Arnd
>
> [1] http://git.kernel.org/cgit/linux/kernel/git/arnd/playground.git/log/?h=y2038-syscalls
>     https://lwn.net/Articles/643407/
>
> diff --git a/include/uapi/asm-generic/bitsperlong.h b/include/uapi/asm-generic/bitsperlong.h
> index 23e6c416b85f..ecdaf4f77f35 100644
> --- a/include/uapi/asm-generic/bitsperlong.h
> +++ b/include/uapi/asm-generic/bitsperlong.h
> @@ -12,4 +12,13 @@
>  #define __BITS_PER_LONG 32
>  #endif
>
> +/*
> + * Traditionally we define defines 'time_t' as 'long', but we need to
> + * migrate to a 64-bit type until 2038. This one is designed to be
> + * overridden by user space if it's prepared to handle 64-bit time_t.
> + */
> +#ifndef __KERNEL_TIME_BITS
> +#define __KERNEL_TIME_BITS __BITS_PER_LONG
> +#endif
> +
>  #endif /* _UAPI__ASM_GENERIC_BITS_PER_LONG */
> diff --git a/include/uapi/asm-generic/kernel_stat.h b/include/uapi/asm-generic/kernel_stat.h
> index d1db22583046..3693496c78aa 100644
> --- a/include/uapi/asm-generic/kernel_stat.h
> +++ b/include/uapi/asm-generic/kernel_stat.h
> @@ -1,6 +1,14 @@
>  #ifndef __ASM_GENERIC_KERNEL_STAT_H
>  #define __ASM_GENERIC_KERNEL_STAT_H
>
> +#include <asm/bitsperlong.h>
> +
> +#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
> +#define __old_kernel_stat2 stat
> +#else
> +#define __kernel_stat stat
> +#endif
> +
>  /*
>   * The new structure that works on both 32-bit and 64-bit and survives y2038
>   * The layout matches 'struct stat' from asm-generic/stat.h on 64-bit
> diff --git a/include/uapi/asm-generic/stat.h b/include/uapi/asm-generic/stat.h
> index 64c32ba7c1a9..f66b28b96c8d 100644
> --- a/include/uapi/asm-generic/stat.h
> +++ b/include/uapi/asm-generic/stat.h
> @@ -22,7 +22,7 @@
>
>  #define STAT_HAVE_NSEC 1
>
> -struct stat {
> +struct __old_kernel_stat2 {
>         unsigned long   st_dev;         /* Device.  */
>         unsigned long   st_ino;         /* File serial number.  */
>         unsigned int    st_mode;        /* File mode.  */
> diff --git a/include/uapi/linux/resource.h b/include/uapi/linux/resource.h
> index c4f3ba44db00..9a3876cc4436 100644
> --- a/include/uapi/linux/resource.h
> +++ b/include/uapi/linux/resource.h
> @@ -3,10 +3,16 @@
>
>  #include <linux/time.h>
>  #include <linux/types.h>
> +#include <asm/bitsperlong.h>
>
>  /*
>   * Resource control/accounting header file for linux
>   */
> +#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
> +#define __old_kernel_rusage rusage
> +#else
> +#define __kernel_rusage rusage
> +#endif

This all looks ok to me. Though I wonder if it would be cleaner to
have all these conditional definitions in one header, rather then
littered about in a ton of files.

I'm torn because having the definitions close to the underlying
structure helps folks reading through the code, but it still seems a
little bit messy.

thanks
-john
H. Peter Anvin May 27, 2015, 3:28 p.m. UTC | #6
On 05/18/2015 02:53 AM, Arnd Bergmann wrote:
> In the patch series I posted recently [1], I introduce new system calls to deal
> with modified data structures, but left the question open on how these should
> be best accessed from libc. The patches introduce a new __kernel_time64_t type
> and based on that five new data structured: struct __kernel_timespec,
> struct __kernel_itimerspec, struct __kernel_stat, struct __kernel_rusage,
> and struct __kernel_timex. This works fine for the case when all libc
> implementations provide their own definitions to user space, but not for
> the simplest case (e.g. klibc) where the user-visible structures come directly
> from the kernel uapi headers.
> 
> I still don't know what model the various libc developers prefer, so here is
> an alternative approach, as a patch on top of the previous series:
> 
> Now, we rename the original structures to struct __old_kernel_*, and use a
> macro to define either the __old_kernel_* or the __kernel_* structure name
> to the name we actually want in user space, based on a __KERNEL_TIME_BITS
> macro that can be set to either 32 or 64 for 32-bit architectures by
> the libc. Depending on that macro, the compiler will either see one
> of these combinations (for each of the five structures):
> 
> a) __BITS_PER_LONG == 32 && __KERNEL_TIME_BITS == 32:
> 
>    struct timespec              based on 32-bit __kernel_time_t
>    struct __kernel_timespec     based on 64-bit __kernel_time64_t
> 
> b) __BITS_PER_LONG == 64 && __KERNEL_TIME_BITS == 64:
> 
>    struct timespec              based on 64-bit __kernel_time_t
>    struct __kernel_timespec     based on 64-bit __kernel_time64_t
> 
> c) __BITS_PER_LONG == 32 && __KERNEL_TIME_BITS == 64:
> 
>    struct __old_kernel_timespec based on 32-bit __kernel_time_t
>    struct timespec              based on 64-bit __kernel_time64_t
> 
> Would this work for everyone?  Any alternative suggestions?
> 

It seems to work, except I don't really understand why there is a
difference between (b) and (c).

I also have no problem just having klibc contain its own definitions of
these structures, as long as one can prevent the kernel from defining them.

	-hpa
Arnd Bergmann May 27, 2015, 8:19 p.m. UTC | #7
On Wednesday 27 May 2015 08:28:44 H. Peter Anvin wrote:
> On 05/18/2015 02:53 AM, Arnd Bergmann wrote:
> > In the patch series I posted recently [1], I introduce new system calls to deal
> > with modified data structures, but left the question open on how these should
> > be best accessed from libc. The patches introduce a new __kernel_time64_t type
> > and based on that five new data structured: struct __kernel_timespec,
> > struct __kernel_itimerspec, struct __kernel_stat, struct __kernel_rusage,
> > and struct __kernel_timex. This works fine for the case when all libc
> > implementations provide their own definitions to user space, but not for
> > the simplest case (e.g. klibc) where the user-visible structures come directly
> > from the kernel uapi headers.
> > 
> > I still don't know what model the various libc developers prefer, so here is
> > an alternative approach, as a patch on top of the previous series:
> > 
> > Now, we rename the original structures to struct __old_kernel_*, and use a
> > macro to define either the __old_kernel_* or the __kernel_* structure name
> > to the name we actually want in user space, based on a __KERNEL_TIME_BITS
> > macro that can be set to either 32 or 64 for 32-bit architectures by
> > the libc. Depending on that macro, the compiler will either see one
> > of these combinations (for each of the five structures):
> > 
> > a) __BITS_PER_LONG == 32 && __KERNEL_TIME_BITS == 32:
> > 
> >    struct timespec              based on 32-bit __kernel_time_t
> >    struct __kernel_timespec     based on 64-bit __kernel_time64_t
> > 
> > b) __BITS_PER_LONG == 64 && __KERNEL_TIME_BITS == 64:
> > 
> >    struct timespec              based on 64-bit __kernel_time_t
> >    struct __kernel_timespec     based on 64-bit __kernel_time64_t
> > 
> > c) __BITS_PER_LONG == 32 && __KERNEL_TIME_BITS == 64:
> > 
> >    struct __old_kernel_timespec based on 32-bit __kernel_time_t
> >    struct timespec              based on 64-bit __kernel_time64_t
> > 
> > Would this work for everyone?  Any alternative suggestions?
> > 
> 
> It seems to work, except I don't really understand why there is a
> difference between (b) and (c).

I tried to keep a) and b) similar, and change nothing other than the
introduction of the extra __kernel_time64_t and __kernel_timespec
here, for the case of __KERNEL_TIME_BITS == __BITS_PER_LONG, in order
to minimize the risk of introducing regressions for existing libc
builds against new kernel headers.

Case c) is the only one that actually changes the existing definitions,
which makes it different from both a) and b).

> I also have no problem just having klibc contain its own definitions of
> these structures, as long as one can prevent the kernel from defining them.

Ok, good to know. If that works for all libc implementations, we
could take a simpler approach and just define __old_kernel_timespec
plus __kernel_timespec but not timespec (and respectively for the
other structures) when __KERNEL_TIME_BITS == 64 is set, and leave
the real user space definitions up to libc (which can then
add the #defines or not if they want to).

	Arnd
diff mbox

Patch

diff --git a/include/uapi/asm-generic/bitsperlong.h b/include/uapi/asm-generic/bitsperlong.h
index 23e6c416b85f..ecdaf4f77f35 100644
--- a/include/uapi/asm-generic/bitsperlong.h
+++ b/include/uapi/asm-generic/bitsperlong.h
@@ -12,4 +12,13 @@ 
 #define __BITS_PER_LONG 32
 #endif
 
+/*
+ * Traditionally we define defines 'time_t' as 'long', but we need to
+ * migrate to a 64-bit type until 2038. This one is designed to be
+ * overridden by user space if it's prepared to handle 64-bit time_t.
+ */
+#ifndef __KERNEL_TIME_BITS
+#define __KERNEL_TIME_BITS __BITS_PER_LONG
+#endif
+
 #endif /* _UAPI__ASM_GENERIC_BITS_PER_LONG */
diff --git a/include/uapi/asm-generic/kernel_stat.h b/include/uapi/asm-generic/kernel_stat.h
index d1db22583046..3693496c78aa 100644
--- a/include/uapi/asm-generic/kernel_stat.h
+++ b/include/uapi/asm-generic/kernel_stat.h
@@ -1,6 +1,14 @@ 
 #ifndef __ASM_GENERIC_KERNEL_STAT_H
 #define __ASM_GENERIC_KERNEL_STAT_H
 
+#include <asm/bitsperlong.h>
+
+#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
+#define __old_kernel_stat2 stat
+#else
+#define __kernel_stat stat
+#endif
+
 /*
  * The new structure that works on both 32-bit and 64-bit and survives y2038
  * The layout matches 'struct stat' from asm-generic/stat.h on 64-bit
diff --git a/include/uapi/asm-generic/stat.h b/include/uapi/asm-generic/stat.h
index 64c32ba7c1a9..f66b28b96c8d 100644
--- a/include/uapi/asm-generic/stat.h
+++ b/include/uapi/asm-generic/stat.h
@@ -22,7 +22,7 @@ 
 
 #define STAT_HAVE_NSEC 1
 
-struct stat {
+struct __old_kernel_stat2 {
 	unsigned long	st_dev;		/* Device.  */
 	unsigned long	st_ino;		/* File serial number.  */
 	unsigned int	st_mode;	/* File mode.  */
diff --git a/include/uapi/linux/resource.h b/include/uapi/linux/resource.h
index c4f3ba44db00..9a3876cc4436 100644
--- a/include/uapi/linux/resource.h
+++ b/include/uapi/linux/resource.h
@@ -3,10 +3,16 @@ 
 
 #include <linux/time.h>
 #include <linux/types.h>
+#include <asm/bitsperlong.h>
 
 /*
  * Resource control/accounting header file for linux
  */
+#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
+#define __old_kernel_rusage rusage
+#else
+#define __kernel_rusage rusage
+#endif
 
 /*
  * Definition of struct rusage taken from BSD 4.3 Reno
@@ -20,7 +26,7 @@ 
 #define RUSAGE_BOTH	(-2)		/* sys_wait4() uses this */
 #define	RUSAGE_THREAD	1		/* only the calling thread */
 
-struct	rusage {
+struct	__old_kernel_rusage {
 	struct timeval ru_utime;	/* user time used */
 	struct timeval ru_stime;	/* system time used */
 	__kernel_long_t	ru_maxrss;	/* maximum resident set size */
diff --git a/include/uapi/linux/time.h b/include/uapi/linux/time.h
index 72d894df3013..b3988606128f 100644
--- a/include/uapi/linux/time.h
+++ b/include/uapi/linux/time.h
@@ -6,11 +6,24 @@ 
 
 #ifndef _STRUCT_TIMESPEC
 #define _STRUCT_TIMESPEC
-struct timespec {
+
+#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
+#define __old_kernel_timespec timespec
+#else
+#define __kernel_timespec timespec
+#endif
+#endif
+
+#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
+#define __old_kernel_itimerspec itimerspec
+#else
+#define __kernel_itimerspec itimerspec
+#endif
+
+struct __old_kernel_timespec {
 	__kernel_time_t	tv_sec;			/* seconds */
 	long		tv_nsec;		/* nanoseconds */
 };
-#endif
 
 struct timeval {
 	__kernel_time_t		tv_sec;		/* seconds */
@@ -31,7 +44,7 @@  struct timezone {
 #define	ITIMER_VIRTUAL		1
 #define	ITIMER_PROF		2
 
-struct itimerspec {
+struct __old_kernel_itimerspec {
 	struct timespec it_interval;	/* timer period */
 	struct timespec it_value;	/* timer expiration */
 };
diff --git a/include/uapi/linux/timex.h b/include/uapi/linux/timex.h
index 9b131f107ada..3cfa50caa77d 100644
--- a/include/uapi/linux/timex.h
+++ b/include/uapi/linux/timex.h
@@ -54,14 +54,22 @@ 
 #define _UAPI_LINUX_TIMEX_H
 
 #include <linux/time.h>
+#include <asm/bitsperlong.h>
+
+#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
+#define __old_kernel_timex timex
+#else
+#define __kernel_timex timex
+#endif
 
 #define NTP_API		4	/* NTP API version */
 
+
 /*
  * syscall interface - used (mainly by NTP daemon)
  * to discipline kernel clock oscillator
  */
-struct timex {
+struct __old_kernel_timex {
 	unsigned int modes;	/* mode selector */
 	__kernel_long_t offset;	/* time offset (usec) */
 	__kernel_long_t freq;	/* frequency offset (scaled ppm) */
diff --git a/arch/arm/include/uapi/asm/stat.h b/arch/arm/include/uapi/asm/stat.h
index 537a12553dd8..18ff0e2383ad 100644
--- a/arch/arm/include/uapi/asm/stat.h
+++ b/arch/arm/include/uapi/asm/stat.h
@@ -19,7 +19,7 @@  struct __old_kernel_stat {
 
 #define STAT_HAVE_NSEC 
 
-struct stat {
+struct __old_kernel_stat2 {
 #if defined(__ARMEB__)
 	unsigned short st_dev;
 	unsigned short __pad1;
diff --git a/arch/avr32/include/uapi/asm/stat.h b/arch/avr32/include/uapi/asm/stat.h
index 2b528ca17985..5df389890f8a 100644
--- a/arch/avr32/include/uapi/asm/stat.h
+++ b/arch/avr32/include/uapi/asm/stat.h
@@ -24,7 +24,7 @@  struct __old_kernel_stat {
         unsigned long  st_ctime;
 };
 
-struct stat {
+struct __old_kernel_stat2 {
         unsigned long st_dev;
         unsigned long st_ino;
         unsigned short st_mode;
diff --git a/arch/blackfin/include/uapi/asm/stat.h b/arch/blackfin/include/uapi/asm/stat.h
index 99ee343aec23..cd417baf51fc 100644
--- a/arch/blackfin/include/uapi/asm/stat.h
+++ b/arch/blackfin/include/uapi/asm/stat.h
@@ -9,7 +9,7 @@ 
 
 #include <asm-generic/kernel_stat.h>
 
-struct stat {
+struct __old_kernel_stat2 {
 	unsigned short st_dev;
 	unsigned short __pad1;
 	unsigned long st_ino;
diff --git a/arch/cris/include/uapi/asm/stat.h b/arch/cris/include/uapi/asm/stat.h
index 4837884cd2d3..38d1dba3ea6a 100644
--- a/arch/cris/include/uapi/asm/stat.h
+++ b/arch/cris/include/uapi/asm/stat.h
@@ -22,7 +22,7 @@  struct __old_kernel_stat {
 
 #define STAT_HAVE_NSEC 1
 
-struct stat {
+struct __old_kernel_stat2 {
 	unsigned long  st_dev;
 	unsigned long  st_ino;
 	unsigned short st_mode;
diff --git a/arch/frv/include/uapi/asm/stat.h b/arch/frv/include/uapi/asm/stat.h
index 5448b198fbb6..5ff15ccef6c3 100644
--- a/arch/frv/include/uapi/asm/stat.h
+++ b/arch/frv/include/uapi/asm/stat.h
@@ -18,7 +18,7 @@  struct __old_kernel_stat {
 };
 
 /* This matches struct stat in uClibc/glibc.  */
-struct stat {
+struct __old_kernel_stat2 {
 	unsigned char __pad1[6];
 	unsigned short st_dev;
 
diff --git a/arch/m32r/include/uapi/asm/stat.h b/arch/m32r/include/uapi/asm/stat.h
index d0ffa70f73c0..03531561b8cd 100644
--- a/arch/m32r/include/uapi/asm/stat.h
+++ b/arch/m32r/include/uapi/asm/stat.h
@@ -20,7 +20,7 @@  struct __old_kernel_stat {
 
 #define STAT_HAVE_NSEC	1
 
-struct stat {
+struct __old_kernel_stat2 {
 	unsigned short st_dev;
 	unsigned short __pad1;
 	unsigned long  st_ino;
diff --git a/arch/m68k/include/uapi/asm/stat.h b/arch/m68k/include/uapi/asm/stat.h
index 6f455db47b4e..f7936ed51c09 100644
--- a/arch/m68k/include/uapi/asm/stat.h
+++ b/arch/m68k/include/uapi/asm/stat.h
@@ -17,7 +17,7 @@  struct __old_kernel_stat {
 	unsigned long  st_ctime;
 };
 
-struct stat {
+struct __old_kernel_stat2 {
 	unsigned short st_dev;
 	unsigned short __pad1;
 	unsigned long  st_ino;
diff --git a/arch/mips/include/uapi/asm/stat.h b/arch/mips/include/uapi/asm/stat.h
index 53e58fbd83fa..c0b82a1ccf17 100644
--- a/arch/mips/include/uapi/asm/stat.h
+++ b/arch/mips/include/uapi/asm/stat.h
@@ -16,7 +16,7 @@ 
 
 #if (_MIPS_SIM == _MIPS_SIM_ABI32) || (_MIPS_SIM == _MIPS_SIM_NABI32)
 
-struct stat {
+struct __old_kernel_stat2 {
 	unsigned	st_dev;
 	long		st_pad1[3];		/* Reserved for network id */
 	ino_t		st_ino;
@@ -90,7 +90,7 @@  struct stat64 {
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
 /* The memory layout is the same as of struct stat64 of the 32-bit kernel.  */
-struct stat {
+struct __old_kernel_stat2 {
 	unsigned int		st_dev;
 	unsigned int		st_pad0[3]; /* Reserved for st_dev expansion */
 
diff --git a/arch/mn10300/include/uapi/asm/stat.h b/arch/mn10300/include/uapi/asm/stat.h
index af3b4d6b7b7a..ab507885dd05 100644
--- a/arch/mn10300/include/uapi/asm/stat.h
+++ b/arch/mn10300/include/uapi/asm/stat.h
@@ -17,7 +17,7 @@  struct __old_kernel_stat {
 	unsigned long  st_ctime;
 };
 
-struct stat {
+struct __old_kernel_stat2 {
 	unsigned long  st_dev;
 	unsigned long  st_ino;
 	unsigned short st_mode;
diff --git a/arch/parisc/include/uapi/asm/stat.h b/arch/parisc/include/uapi/asm/stat.h
index f06ce7ba0115..d632b5453628 100644
--- a/arch/parisc/include/uapi/asm/stat.h
+++ b/arch/parisc/include/uapi/asm/stat.h
@@ -4,7 +4,7 @@ 
 #include <linux/types.h>
 #include <asm-generic/kernel_stat.h>
 
-struct stat {
+struct __old_kernel_stat2 {
 	unsigned int	st_dev;		/* dev_t is 32 bits on parisc */
 	unsigned int	st_ino;		/* 32 bits */
 	unsigned short	st_mode;	/* 16 bits */
diff --git a/arch/powerpc/include/uapi/asm/stat.h b/arch/powerpc/include/uapi/asm/stat.h
index 248d8072267f..4b62b30ed12c 100644
--- a/arch/powerpc/include/uapi/asm/stat.h
+++ b/arch/powerpc/include/uapi/asm/stat.h
@@ -7,6 +7,13 @@ 
  * 2 of the License, or (at your option) any later version.
  */
 #include <linux/types.h>
+#include <asm/bitsperlong.h>
+
+#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
+#define __old_kernel_stat2 stat
+#else
+#define __kernel_stat stat
+#endif
 
 #define STAT_HAVE_NSEC 1
 
@@ -26,7 +33,7 @@  struct __old_kernel_stat {
 };
 #endif /* !__powerpc64__ */
 
-struct stat {
+struct __old_kernel_stat2 {
 	unsigned long	st_dev;
 	ino_t		st_ino;
 #ifdef __powerpc64__
@@ -78,7 +85,7 @@  struct stat64 {
 	unsigned int	__unused5;
 };
 
-/* this matches the powerpc64 'struct stat' for compat tasks */
+/* this matches the powerpc64 'struct __old_kernel_stat2' for compat tasks */
 struct __kernel_stat {
 	unsigned long long	st_dev;
 	unsigned long long	st_ino;
@@ -101,6 +107,5 @@  struct __kernel_stat {
 	unsigned long long	__unused5;
 	unsigned long long	__unused6;
 };
 
 #endif /* _ASM_POWERPC_STAT_H */
diff --git a/arch/s390/include/uapi/asm/stat.h b/arch/s390/include/uapi/asm/stat.h
index d4c2711249dd..5f40f51ecdab 100644
--- a/arch/s390/include/uapi/asm/stat.h
+++ b/arch/s390/include/uapi/asm/stat.h
@@ -7,6 +7,14 @@ 
 #ifndef _S390_STAT_H
 #define _S390_STAT_H
 
+#include <asm/bitsperlong.h>
+
+#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
+#define __old_kernel_stat2 stat
+#else
+#define __kernel_stat stat
+#endif
+
 #ifndef __s390x__
 struct __old_kernel_stat {
         unsigned short st_dev;
@@ -22,7 +30,7 @@  struct __old_kernel_stat {
         unsigned long  st_ctime;
 };
 
-struct stat {
+struct __old_kernel_stat2 {
         unsigned short st_dev;
         unsigned short __pad1;
         unsigned long  st_ino;
@@ -75,7 +83,7 @@  struct stat64 {
 
 #else /* __s390x__ */
 
-struct stat {
+struct __old_kernel_stat {
         unsigned long  st_dev;
         unsigned long  st_ino;
         unsigned long  st_nlink;
diff --git a/arch/sh/include/uapi/asm/stat.h b/arch/sh/include/uapi/asm/stat.h
index a13ffbcccd50..0d3358037558 100644
--- a/arch/sh/include/uapi/asm/stat.h
+++ b/arch/sh/include/uapi/asm/stat.h
@@ -18,7 +18,7 @@  struct __old_kernel_stat {
 };
 
 #if defined(__SH5__) || defined(CONFIG_CPU_SH5)
-struct stat {
+struct __old_kernel_stat2 {
 	unsigned short st_dev;
 	unsigned short __pad1;
 	unsigned long st_ino;
@@ -77,7 +77,7 @@  struct stat64 {
 	unsigned long	__unused2;
 };
 #else
-struct stat {
+struct __old_kernel_stat2 {
 	unsigned long  st_dev;
 	unsigned long  st_ino;
 	unsigned short st_mode;
diff --git a/arch/sparc/include/uapi/asm/stat.h b/arch/sparc/include/uapi/asm/stat.h
index 6d19c7bdc641..8ace4436a31f 100644
--- a/arch/sparc/include/uapi/asm/stat.h
+++ b/arch/sparc/include/uapi/asm/stat.h
@@ -2,6 +2,13 @@ 
 #define __SPARC_STAT_H
 
 #include <linux/types.h>
+#include <asm/bitsperlong.h>
+
+#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
+#define __old_kernel_stat2 stat
+#else
+#define __kernel_stat stat
+#endif
 
 #if defined(__sparc__) && defined(__arch64__)
 /* 64 bit sparc */
@@ -48,7 +55,8 @@  struct stat64 {
 
 #else
 /* 32 bit sparc */
-struct stat {
+
+struct __old_kernel_stat2 {
 	unsigned short	st_dev;
 	ino_t		st_ino;
 	mode_t		st_mode;
diff --git a/arch/x86/include/uapi/asm/stat.h b/arch/x86/include/uapi/asm/stat.h
index 5d5754fc3d36..5fa5beeafd86 100644
--- a/arch/x86/include/uapi/asm/stat.h
+++ b/arch/x86/include/uapi/asm/stat.h
@@ -2,11 +2,18 @@ 
 #define _ASM_X86_STAT_H
 
 #include <asm/posix_types.h>
+#include <asm/bitsperlong.h>
 
 #define STAT_HAVE_NSEC 1
 
+#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
+#define __old_kernel_stat2 stat
+#else
+#define __kernel_stat stat
+#endif
+
 #ifdef __i386__
-struct stat {
+struct __old_kernel_stat2 {
 	unsigned long  st_dev;
 	unsigned long  st_ino;
 	unsigned short st_mode;
@@ -73,7 +80,7 @@  struct stat64 {
 
 #else /* __i386__ */
 
-struct stat {
+struct __old_kernel_stat2 {
 	__kernel_ulong_t	st_dev;
 	__kernel_ulong_t	st_ino;
 	__kernel_ulong_t	st_nlink;
diff --git a/arch/xtensa/include/uapi/asm/stat.h b/arch/xtensa/include/uapi/asm/stat.h
index 8d9c1d9d82d0..94e40d22eb88 100644
--- a/arch/xtensa/include/uapi/asm/stat.h
+++ b/arch/xtensa/include/uapi/asm/stat.h
@@ -15,7 +15,7 @@ 
 
 #define STAT_HAVE_NSEC 1
 
-struct stat {
+struct __old_kernel_stat2 {
 	unsigned long	st_dev;
 	unsigned long	st_ino;
 	unsigned int	st_mode;