diff options
-rw-r--r-- | arch/x86/include/asm/stat.h | 21 | ||||
-rw-r--r-- | fs/stat.c | 44 |
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 | ||
68 | struct stat { | 80 | struct 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 */ |
@@ -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 | |||
193 | static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf) | 206 | static 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 | |||
330 | static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf) | 334 | static 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)) |