diff options
author | Christoph Hellwig <hch@lst.de> | 2008-10-16 01:02:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-16 14:21:33 -0400 |
commit | f7a5000f7a8924e9c5fad1801616601d6dc65a17 (patch) | |
tree | 82bd7f554378b26fe23707a3755359787b252574 | |
parent | f7ad160b49c49dc9cd383b9184c6fa4a9b4f7ebb (diff) |
compat: move cp_compat_stat to common code
struct stat / compat_stat is the same on all architectures, so
cp_compat_stat should be, too.
Turns out it is, except that various architectures have slightly and some
high2lowuid/high2lowgid or the direct assignment instead of the
SET_UID/SET_GID that expands to the correct one anyway.
This patch replaces the arch-specific cp_compat_stat implementations with
a common one based on the x86-64 one.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: David S. Miller <davem@davemloft.net> [ sparc bits ]
Acked-by: Kyle McMartin <kyle@mcmartin.ca> [ parisc bits ]
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | arch/ia64/ia32/sys_ia32.c | 35 | ||||
-rw-r--r-- | arch/mips/kernel/linux32.c | 35 | ||||
-rw-r--r-- | arch/parisc/kernel/sys_parisc32.c | 47 | ||||
-rw-r--r-- | arch/powerpc/kernel/sys_ppc32.c | 36 | ||||
-rw-r--r-- | arch/s390/kernel/compat_linux.c | 35 | ||||
-rw-r--r-- | arch/sparc64/kernel/sys_sparc32.c | 35 | ||||
-rw-r--r-- | arch/x86/ia32/sys_ia32.c | 35 | ||||
-rw-r--r-- | fs/compat.c | 39 | ||||
-rw-r--r-- | include/linux/compat.h | 1 |
9 files changed, 39 insertions, 259 deletions
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index bf196cbb3796..2362a8eefb30 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c | |||
@@ -118,41 +118,6 @@ sys32_execve (char __user *name, compat_uptr_t __user *argv, compat_uptr_t __use | |||
118 | return error; | 118 | return error; |
119 | } | 119 | } |
120 | 120 | ||
121 | int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf) | ||
122 | { | ||
123 | compat_ino_t ino; | ||
124 | int err; | ||
125 | |||
126 | if ((u64) stat->size > MAX_NON_LFS || | ||
127 | !old_valid_dev(stat->dev) || | ||
128 | !old_valid_dev(stat->rdev)) | ||
129 | return -EOVERFLOW; | ||
130 | |||
131 | ino = stat->ino; | ||
132 | if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino) | ||
133 | return -EOVERFLOW; | ||
134 | |||
135 | if (clear_user(ubuf, sizeof(*ubuf))) | ||
136 | return -EFAULT; | ||
137 | |||
138 | err = __put_user(old_encode_dev(stat->dev), &ubuf->st_dev); | ||
139 | err |= __put_user(ino, &ubuf->st_ino); | ||
140 | err |= __put_user(stat->mode, &ubuf->st_mode); | ||
141 | err |= __put_user(stat->nlink, &ubuf->st_nlink); | ||
142 | err |= __put_user(high2lowuid(stat->uid), &ubuf->st_uid); | ||
143 | err |= __put_user(high2lowgid(stat->gid), &ubuf->st_gid); | ||
144 | err |= __put_user(old_encode_dev(stat->rdev), &ubuf->st_rdev); | ||
145 | err |= __put_user(stat->size, &ubuf->st_size); | ||
146 | err |= __put_user(stat->atime.tv_sec, &ubuf->st_atime); | ||
147 | err |= __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec); | ||
148 | err |= __put_user(stat->mtime.tv_sec, &ubuf->st_mtime); | ||
149 | err |= __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec); | ||
150 | err |= __put_user(stat->ctime.tv_sec, &ubuf->st_ctime); | ||
151 | err |= __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec); | ||
152 | err |= __put_user(stat->blksize, &ubuf->st_blksize); | ||
153 | err |= __put_user(stat->blocks, &ubuf->st_blocks); | ||
154 | return err; | ||
155 | } | ||
156 | 121 | ||
157 | #if PAGE_SHIFT > IA32_PAGE_SHIFT | 122 | #if PAGE_SHIFT > IA32_PAGE_SHIFT |
158 | 123 | ||
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 2fefb14414b7..89223a9bff2c 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c | |||
@@ -63,41 +63,6 @@ | |||
63 | #define merge_64(r1, r2) ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL)) | 63 | #define merge_64(r1, r2) ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL)) |
64 | #endif | 64 | #endif |
65 | 65 | ||
66 | /* | ||
67 | * Revalidate the inode. This is required for proper NFS attribute caching. | ||
68 | */ | ||
69 | |||
70 | int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf) | ||
71 | { | ||
72 | struct compat_stat tmp; | ||
73 | |||
74 | if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev)) | ||
75 | return -EOVERFLOW; | ||
76 | |||
77 | memset(&tmp, 0, sizeof(tmp)); | ||
78 | tmp.st_dev = new_encode_dev(stat->dev); | ||
79 | tmp.st_ino = stat->ino; | ||
80 | if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino) | ||
81 | return -EOVERFLOW; | ||
82 | tmp.st_mode = stat->mode; | ||
83 | tmp.st_nlink = stat->nlink; | ||
84 | SET_UID(tmp.st_uid, stat->uid); | ||
85 | SET_GID(tmp.st_gid, stat->gid); | ||
86 | tmp.st_rdev = new_encode_dev(stat->rdev); | ||
87 | tmp.st_size = stat->size; | ||
88 | tmp.st_atime = stat->atime.tv_sec; | ||
89 | tmp.st_mtime = stat->mtime.tv_sec; | ||
90 | tmp.st_ctime = stat->ctime.tv_sec; | ||
91 | #ifdef STAT_HAVE_NSEC | ||
92 | tmp.st_atime_nsec = stat->atime.tv_nsec; | ||
93 | tmp.st_mtime_nsec = stat->mtime.tv_nsec; | ||
94 | tmp.st_ctime_nsec = stat->ctime.tv_nsec; | ||
95 | #endif | ||
96 | tmp.st_blocks = stat->blocks; | ||
97 | tmp.st_blksize = stat->blksize; | ||
98 | return copy_to_user(statbuf, &tmp, sizeof(tmp)) ? -EFAULT : 0; | ||
99 | } | ||
100 | |||
101 | asmlinkage unsigned long | 66 | asmlinkage unsigned long |
102 | sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot, | 67 | sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot, |
103 | unsigned long flags, unsigned long fd, unsigned long pgoff) | 68 | unsigned long flags, unsigned long fd, unsigned long pgoff) |
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c index 71efd6a28e2a..2c3af17e049c 100644 --- a/arch/parisc/kernel/sys_parisc32.c +++ b/arch/parisc/kernel/sys_parisc32.c | |||
@@ -237,53 +237,6 @@ int sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user | |||
237 | return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); | 237 | return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); |
238 | } | 238 | } |
239 | 239 | ||
240 | int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf) | ||
241 | { | ||
242 | compat_ino_t ino; | ||
243 | int err; | ||
244 | |||
245 | if (stat->size > MAX_NON_LFS || !new_valid_dev(stat->dev) || | ||
246 | !new_valid_dev(stat->rdev)) | ||
247 | return -EOVERFLOW; | ||
248 | |||
249 | ino = stat->ino; | ||
250 | if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino) | ||
251 | return -EOVERFLOW; | ||
252 | |||
253 | err = put_user(new_encode_dev(stat->dev), &statbuf->st_dev); | ||
254 | err |= put_user(ino, &statbuf->st_ino); | ||
255 | err |= put_user(stat->mode, &statbuf->st_mode); | ||
256 | err |= put_user(stat->nlink, &statbuf->st_nlink); | ||
257 | err |= put_user(0, &statbuf->st_reserved1); | ||
258 | err |= put_user(0, &statbuf->st_reserved2); | ||
259 | err |= put_user(new_encode_dev(stat->rdev), &statbuf->st_rdev); | ||
260 | err |= put_user(stat->size, &statbuf->st_size); | ||
261 | err |= put_user(stat->atime.tv_sec, &statbuf->st_atime); | ||
262 | err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec); | ||
263 | err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime); | ||
264 | err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec); | ||
265 | err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime); | ||
266 | err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec); | ||
267 | err |= put_user(stat->blksize, &statbuf->st_blksize); | ||
268 | err |= put_user(stat->blocks, &statbuf->st_blocks); | ||
269 | err |= put_user(0, &statbuf->__unused1); | ||
270 | err |= put_user(0, &statbuf->__unused2); | ||
271 | err |= put_user(0, &statbuf->__unused3); | ||
272 | err |= put_user(0, &statbuf->__unused4); | ||
273 | err |= put_user(0, &statbuf->__unused5); | ||
274 | err |= put_user(0, &statbuf->st_fstype); /* not avail */ | ||
275 | err |= put_user(0, &statbuf->st_realdev); /* not avail */ | ||
276 | err |= put_user(0, &statbuf->st_basemode); /* not avail */ | ||
277 | err |= put_user(0, &statbuf->st_spareshort); | ||
278 | err |= put_user(stat->uid, &statbuf->st_uid); | ||
279 | err |= put_user(stat->gid, &statbuf->st_gid); | ||
280 | err |= put_user(0, &statbuf->st_spare4[0]); | ||
281 | err |= put_user(0, &statbuf->st_spare4[1]); | ||
282 | err |= put_user(0, &statbuf->st_spare4[2]); | ||
283 | |||
284 | return err; | ||
285 | } | ||
286 | |||
287 | /*** copied from mips64 ***/ | 240 | /*** copied from mips64 ***/ |
288 | /* | 241 | /* |
289 | * Ooo, nasty. We need here to frob 32-bit unsigned longs to | 242 | * Ooo, nasty. We need here to frob 32-bit unsigned longs to |
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index ff7de7b0797e..d00599bb24a1 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c | |||
@@ -61,42 +61,6 @@ asmlinkage long ppc32_select(u32 n, compat_ulong_t __user *inp, | |||
61 | return compat_sys_select((int)n, inp, outp, exp, compat_ptr(tvp_x)); | 61 | return compat_sys_select((int)n, inp, outp, exp, compat_ptr(tvp_x)); |
62 | } | 62 | } |
63 | 63 | ||
64 | int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf) | ||
65 | { | ||
66 | compat_ino_t ino; | ||
67 | long err; | ||
68 | |||
69 | if (stat->size > MAX_NON_LFS || !new_valid_dev(stat->dev) || | ||
70 | !new_valid_dev(stat->rdev)) | ||
71 | return -EOVERFLOW; | ||
72 | |||
73 | ino = stat->ino; | ||
74 | if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino) | ||
75 | return -EOVERFLOW; | ||
76 | |||
77 | err = access_ok(VERIFY_WRITE, statbuf, sizeof(*statbuf)) ? 0 : -EFAULT; | ||
78 | err |= __put_user(new_encode_dev(stat->dev), &statbuf->st_dev); | ||
79 | err |= __put_user(ino, &statbuf->st_ino); | ||
80 | err |= __put_user(stat->mode, &statbuf->st_mode); | ||
81 | err |= __put_user(stat->nlink, &statbuf->st_nlink); | ||
82 | err |= __put_user(stat->uid, &statbuf->st_uid); | ||
83 | err |= __put_user(stat->gid, &statbuf->st_gid); | ||
84 | err |= __put_user(new_encode_dev(stat->rdev), &statbuf->st_rdev); | ||
85 | err |= __put_user(stat->size, &statbuf->st_size); | ||
86 | err |= __put_user(stat->atime.tv_sec, &statbuf->st_atime); | ||
87 | err |= __put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec); | ||
88 | err |= __put_user(stat->mtime.tv_sec, &statbuf->st_mtime); | ||
89 | err |= __put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec); | ||
90 | err |= __put_user(stat->ctime.tv_sec, &statbuf->st_ctime); | ||
91 | err |= __put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec); | ||
92 | err |= __put_user(stat->blksize, &statbuf->st_blksize); | ||
93 | err |= __put_user(stat->blocks, &statbuf->st_blocks); | ||
94 | err |= __put_user(0, &statbuf->__unused4[0]); | ||
95 | err |= __put_user(0, &statbuf->__unused4[1]); | ||
96 | |||
97 | return err; | ||
98 | } | ||
99 | |||
100 | /* Note: it is necessary to treat option as an unsigned int, | 64 | /* Note: it is necessary to treat option as an unsigned int, |
101 | * with the corresponding cast to a signed int to insure that the | 65 | * with the corresponding cast to a signed int to insure that the |
102 | * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) | 66 | * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) |
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 98e246dc0233..9b471d785ec1 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c | |||
@@ -362,41 +362,6 @@ asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned | |||
362 | return sys_ftruncate(fd, (high << 32) | low); | 362 | return sys_ftruncate(fd, (high << 32) | low); |
363 | } | 363 | } |
364 | 364 | ||
365 | int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf) | ||
366 | { | ||
367 | compat_ino_t ino; | ||
368 | int err; | ||
369 | |||
370 | if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev)) | ||
371 | return -EOVERFLOW; | ||
372 | |||
373 | ino = stat->ino; | ||
374 | if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino) | ||
375 | return -EOVERFLOW; | ||
376 | |||
377 | err = put_user(old_encode_dev(stat->dev), &statbuf->st_dev); | ||
378 | err |= put_user(stat->ino, &statbuf->st_ino); | ||
379 | err |= put_user(stat->mode, &statbuf->st_mode); | ||
380 | err |= put_user(stat->nlink, &statbuf->st_nlink); | ||
381 | err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid); | ||
382 | err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid); | ||
383 | err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev); | ||
384 | err |= put_user(stat->size, &statbuf->st_size); | ||
385 | err |= put_user(stat->atime.tv_sec, &statbuf->st_atime); | ||
386 | err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec); | ||
387 | err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime); | ||
388 | err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec); | ||
389 | err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime); | ||
390 | err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec); | ||
391 | err |= put_user(stat->blksize, &statbuf->st_blksize); | ||
392 | err |= put_user(stat->blocks, &statbuf->st_blocks); | ||
393 | /* fixme | ||
394 | err |= put_user(0, &statbuf->__unused4[0]); | ||
395 | err |= put_user(0, &statbuf->__unused4[1]); | ||
396 | */ | ||
397 | return err; | ||
398 | } | ||
399 | |||
400 | asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid, | 365 | asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid, |
401 | struct compat_timespec __user *interval) | 366 | struct compat_timespec __user *interval) |
402 | { | 367 | { |
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index 3320c9d0075f..73a33dc3bcca 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c | |||
@@ -148,41 +148,6 @@ asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned | |||
148 | return sys_ftruncate(fd, (high << 32) | low); | 148 | return sys_ftruncate(fd, (high << 32) | low); |
149 | } | 149 | } |
150 | 150 | ||
151 | int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf) | ||
152 | { | ||
153 | compat_ino_t ino; | ||
154 | int err; | ||
155 | |||
156 | if (stat->size > MAX_NON_LFS || !old_valid_dev(stat->dev) || | ||
157 | !old_valid_dev(stat->rdev)) | ||
158 | return -EOVERFLOW; | ||
159 | |||
160 | ino = stat->ino; | ||
161 | if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino) | ||
162 | return -EOVERFLOW; | ||
163 | |||
164 | err = put_user(old_encode_dev(stat->dev), &statbuf->st_dev); | ||
165 | err |= put_user(stat->ino, &statbuf->st_ino); | ||
166 | err |= put_user(stat->mode, &statbuf->st_mode); | ||
167 | err |= put_user(stat->nlink, &statbuf->st_nlink); | ||
168 | err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid); | ||
169 | err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid); | ||
170 | err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev); | ||
171 | err |= put_user(stat->size, &statbuf->st_size); | ||
172 | err |= put_user(stat->atime.tv_sec, &statbuf->st_atime); | ||
173 | err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec); | ||
174 | err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime); | ||
175 | err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec); | ||
176 | err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime); | ||
177 | err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec); | ||
178 | err |= put_user(stat->blksize, &statbuf->st_blksize); | ||
179 | err |= put_user(stat->blocks, &statbuf->st_blocks); | ||
180 | err |= put_user(0, &statbuf->__unused4[0]); | ||
181 | err |= put_user(0, &statbuf->__unused4[1]); | ||
182 | |||
183 | return err; | ||
184 | } | ||
185 | |||
186 | static int cp_compat_stat64(struct kstat *stat, | 151 | static int cp_compat_stat64(struct kstat *stat, |
187 | struct compat_stat64 __user *statbuf) | 152 | struct compat_stat64 __user *statbuf) |
188 | { | 153 | { |
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c index beda4232ce69..4d3ad8d78a4d 100644 --- a/arch/x86/ia32/sys_ia32.c +++ b/arch/x86/ia32/sys_ia32.c | |||
@@ -49,41 +49,6 @@ | |||
49 | 49 | ||
50 | #define AA(__x) ((unsigned long)(__x)) | 50 | #define AA(__x) ((unsigned long)(__x)) |
51 | 51 | ||
52 | int cp_compat_stat(struct kstat *kbuf, struct compat_stat __user *ubuf) | ||
53 | { | ||
54 | compat_ino_t ino; | ||
55 | |||
56 | typeof(ubuf->st_uid) uid = 0; | ||
57 | typeof(ubuf->st_gid) gid = 0; | ||
58 | SET_UID(uid, kbuf->uid); | ||
59 | SET_GID(gid, kbuf->gid); | ||
60 | if (!old_valid_dev(kbuf->dev) || !old_valid_dev(kbuf->rdev)) | ||
61 | return -EOVERFLOW; | ||
62 | if (kbuf->size >= 0x7fffffff) | ||
63 | return -EOVERFLOW; | ||
64 | ino = kbuf->ino; | ||
65 | if (sizeof(ino) < sizeof(kbuf->ino) && ino != kbuf->ino) | ||
66 | return -EOVERFLOW; | ||
67 | if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct compat_stat)) || | ||
68 | __put_user(old_encode_dev(kbuf->dev), &ubuf->st_dev) || | ||
69 | __put_user(ino, &ubuf->st_ino) || | ||
70 | __put_user(kbuf->mode, &ubuf->st_mode) || | ||
71 | __put_user(kbuf->nlink, &ubuf->st_nlink) || | ||
72 | __put_user(uid, &ubuf->st_uid) || | ||
73 | __put_user(gid, &ubuf->st_gid) || | ||
74 | __put_user(old_encode_dev(kbuf->rdev), &ubuf->st_rdev) || | ||
75 | __put_user(kbuf->size, &ubuf->st_size) || | ||
76 | __put_user(kbuf->atime.tv_sec, &ubuf->st_atime) || | ||
77 | __put_user(kbuf->atime.tv_nsec, &ubuf->st_atime_nsec) || | ||
78 | __put_user(kbuf->mtime.tv_sec, &ubuf->st_mtime) || | ||
79 | __put_user(kbuf->mtime.tv_nsec, &ubuf->st_mtime_nsec) || | ||
80 | __put_user(kbuf->ctime.tv_sec, &ubuf->st_ctime) || | ||
81 | __put_user(kbuf->ctime.tv_nsec, &ubuf->st_ctime_nsec) || | ||
82 | __put_user(kbuf->blksize, &ubuf->st_blksize) || | ||
83 | __put_user(kbuf->blocks, &ubuf->st_blocks)) | ||
84 | return -EFAULT; | ||
85 | return 0; | ||
86 | } | ||
87 | 52 | ||
88 | asmlinkage long sys32_truncate64(char __user *filename, | 53 | asmlinkage long sys32_truncate64(char __user *filename, |
89 | unsigned long offset_low, | 54 | unsigned long offset_low, |
diff --git a/fs/compat.c b/fs/compat.c index aae13d31612f..5f9ec449c799 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -137,6 +137,45 @@ asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval _ | |||
137 | return compat_sys_futimesat(AT_FDCWD, filename, t); | 137 | return compat_sys_futimesat(AT_FDCWD, filename, t); |
138 | } | 138 | } |
139 | 139 | ||
140 | static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf) | ||
141 | { | ||
142 | compat_ino_t ino = stat->ino; | ||
143 | typeof(ubuf->st_uid) uid = 0; | ||
144 | typeof(ubuf->st_gid) gid = 0; | ||
145 | int err; | ||
146 | |||
147 | SET_UID(uid, stat->uid); | ||
148 | SET_GID(gid, stat->gid); | ||
149 | |||
150 | if ((u64) stat->size > MAX_NON_LFS || | ||
151 | !old_valid_dev(stat->dev) || | ||
152 | !old_valid_dev(stat->rdev)) | ||
153 | return -EOVERFLOW; | ||
154 | if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino) | ||
155 | return -EOVERFLOW; | ||
156 | |||
157 | if (clear_user(ubuf, sizeof(*ubuf))) | ||
158 | return -EFAULT; | ||
159 | |||
160 | err = __put_user(old_encode_dev(stat->dev), &ubuf->st_dev); | ||
161 | err |= __put_user(ino, &ubuf->st_ino); | ||
162 | err |= __put_user(stat->mode, &ubuf->st_mode); | ||
163 | err |= __put_user(stat->nlink, &ubuf->st_nlink); | ||
164 | err |= __put_user(uid, &ubuf->st_uid); | ||
165 | err |= __put_user(gid, &ubuf->st_gid); | ||
166 | err |= __put_user(old_encode_dev(stat->rdev), &ubuf->st_rdev); | ||
167 | err |= __put_user(stat->size, &ubuf->st_size); | ||
168 | err |= __put_user(stat->atime.tv_sec, &ubuf->st_atime); | ||
169 | err |= __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec); | ||
170 | err |= __put_user(stat->mtime.tv_sec, &ubuf->st_mtime); | ||
171 | err |= __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec); | ||
172 | err |= __put_user(stat->ctime.tv_sec, &ubuf->st_ctime); | ||
173 | err |= __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec); | ||
174 | err |= __put_user(stat->blksize, &ubuf->st_blksize); | ||
175 | err |= __put_user(stat->blocks, &ubuf->st_blocks); | ||
176 | return err; | ||
177 | } | ||
178 | |||
140 | asmlinkage long compat_sys_newstat(char __user * filename, | 179 | asmlinkage long compat_sys_newstat(char __user * filename, |
141 | struct compat_stat __user *statbuf) | 180 | struct compat_stat __user *statbuf) |
142 | { | 181 | { |
diff --git a/include/linux/compat.h b/include/linux/compat.h index cf8d11cad5ae..999dddd8d939 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h | |||
@@ -78,7 +78,6 @@ typedef struct { | |||
78 | compat_sigset_word sig[_COMPAT_NSIG_WORDS]; | 78 | compat_sigset_word sig[_COMPAT_NSIG_WORDS]; |
79 | } compat_sigset_t; | 79 | } compat_sigset_t; |
80 | 80 | ||
81 | extern int cp_compat_stat(struct kstat *, struct compat_stat __user *); | ||
82 | extern int get_compat_timespec(struct timespec *, const struct compat_timespec __user *); | 81 | extern int get_compat_timespec(struct timespec *, const struct compat_timespec __user *); |
83 | extern int put_compat_timespec(const struct timespec *, struct compat_timespec __user *); | 82 | extern int put_compat_timespec(const struct timespec *, struct compat_timespec __user *); |
84 | 83 | ||