aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/stat.h21
-rw-r--r--fs/stat.c44
2 files changed, 45 insertions, 20 deletions
diff --git a/arch/x86/include/asm/stat.h b/arch/x86/include/asm/stat.h
index e0b1d9bbcbc6..7b3ddc348585 100644
--- a/arch/x86/include/asm/stat.h
+++ b/arch/x86/include/asm/stat.h
@@ -25,6 +25,12 @@ struct stat {
25 unsigned long __unused5; 25 unsigned long __unused5;
26}; 26};
27 27
28/* We don't need to memset the whole thing just to initialize the padding */
29#define INIT_STRUCT_STAT_PADDING(st) do { \
30 st.__unused4 = 0; \
31 st.__unused5 = 0; \
32} while (0)
33
28#define STAT64_HAS_BROKEN_ST_INO 1 34#define STAT64_HAS_BROKEN_ST_INO 1
29 35
30/* This matches struct stat64 in glibc2.1, hence the absolutely 36/* This matches struct stat64 in glibc2.1, hence the absolutely
@@ -63,6 +69,12 @@ struct stat64 {
63 unsigned long long st_ino; 69 unsigned long long st_ino;
64}; 70};
65 71
72/* We don't need to memset the whole thing just to initialize the padding */
73#define INIT_STRUCT_STAT64_PADDING(st) do { \
74 memset(&st.__pad0, 0, sizeof(st.__pad0)); \
75 memset(&st.__pad3, 0, sizeof(st.__pad3)); \
76} while (0)
77
66#else /* __i386__ */ 78#else /* __i386__ */
67 79
68struct stat { 80struct stat {
@@ -87,6 +99,15 @@ struct stat {
87 unsigned long st_ctime_nsec; 99 unsigned long st_ctime_nsec;
88 long __unused[3]; 100 long __unused[3];
89}; 101};
102
103/* We don't need to memset the whole thing just to initialize the padding */
104#define INIT_STRUCT_STAT_PADDING(st) do { \
105 st.__pad0 = 0; \
106 st.__unused[0] = 0; \
107 st.__unused[1] = 0; \
108 st.__unused[2] = 0; \
109} while (0)
110
90#endif 111#endif
91 112
92/* for 32bit emulation and 32 bit kernels */ 113/* for 32bit emulation and 32 bit kernels */
diff --git a/fs/stat.c b/fs/stat.c
index c733dc5753ae..b30ac60291e2 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -190,24 +190,32 @@ SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, stat
190 190
191#endif /* __ARCH_WANT_OLD_STAT */ 191#endif /* __ARCH_WANT_OLD_STAT */
192 192
193#if BITS_PER_LONG == 32
194# define choose_32_64(a,b) a
195#else
196# define choose_32_64(a,b) b
197#endif
198
199#define valid_dev(x) choose_32_64(old_valid_dev,new_valid_dev)(x)
200#define encode_dev(x) choose_32_64(old_encode_dev,new_encode_dev)(x)
201
202#ifndef INIT_STRUCT_STAT_PADDING
203# define INIT_STRUCT_STAT_PADDING(st) memset(&st, 0, sizeof(st))
204#endif
205
193static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf) 206static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
194{ 207{
195 struct stat tmp; 208 struct stat tmp;
196 209
197#if BITS_PER_LONG == 32 210 if (!valid_dev(stat->dev) || !valid_dev(stat->rdev))
198 if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
199 return -EOVERFLOW; 211 return -EOVERFLOW;
200#else 212#if BITS_PER_LONG == 32
201 if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev)) 213 if (stat->size > MAX_NON_LFS)
202 return -EOVERFLOW; 214 return -EOVERFLOW;
203#endif 215#endif
204 216
205 memset(&tmp, 0, sizeof(tmp)); 217 INIT_STRUCT_STAT_PADDING(tmp);
206#if BITS_PER_LONG == 32 218 tmp.st_dev = encode_dev(stat->dev);
207 tmp.st_dev = old_encode_dev(stat->dev);
208#else
209 tmp.st_dev = new_encode_dev(stat->dev);
210#endif
211 tmp.st_ino = stat->ino; 219 tmp.st_ino = stat->ino;
212 if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino) 220 if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
213 return -EOVERFLOW; 221 return -EOVERFLOW;
@@ -217,15 +225,7 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
217 return -EOVERFLOW; 225 return -EOVERFLOW;
218 SET_UID(tmp.st_uid, stat->uid); 226 SET_UID(tmp.st_uid, stat->uid);
219 SET_GID(tmp.st_gid, stat->gid); 227 SET_GID(tmp.st_gid, stat->gid);
220#if BITS_PER_LONG == 32 228 tmp.st_rdev = encode_dev(stat->rdev);
221 tmp.st_rdev = old_encode_dev(stat->rdev);
222#else
223 tmp.st_rdev = new_encode_dev(stat->rdev);
224#endif
225#if BITS_PER_LONG == 32
226 if (stat->size > MAX_NON_LFS)
227 return -EOVERFLOW;
228#endif
229 tmp.st_size = stat->size; 229 tmp.st_size = stat->size;
230 tmp.st_atime = stat->atime.tv_sec; 230 tmp.st_atime = stat->atime.tv_sec;
231 tmp.st_mtime = stat->mtime.tv_sec; 231 tmp.st_mtime = stat->mtime.tv_sec;
@@ -327,11 +327,15 @@ SYSCALL_DEFINE3(readlink, const char __user *, path, char __user *, buf,
327/* ---------- LFS-64 ----------- */ 327/* ---------- LFS-64 ----------- */
328#ifdef __ARCH_WANT_STAT64 328#ifdef __ARCH_WANT_STAT64
329 329
330#ifndef INIT_STRUCT_STAT64_PADDING
331# define INIT_STRUCT_STAT64_PADDING(st) memset(&st, 0, sizeof(st))
332#endif
333
330static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf) 334static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf)
331{ 335{
332 struct stat64 tmp; 336 struct stat64 tmp;
333 337
334 memset(&tmp, 0, sizeof(struct stat64)); 338 INIT_STRUCT_STAT64_PADDING(tmp);
335#ifdef CONFIG_MIPS 339#ifdef CONFIG_MIPS
336 /* mips has weird padding, so we don't get 64 bits there */ 340 /* mips has weird padding, so we don't get 64 bits there */
337 if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev)) 341 if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))