Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Christoph Hellwig and committed by
Linus Torvalds
f7a5000f f7ad160b

+39 -259
-35
arch/ia64/ia32/sys_ia32.c
··· 118 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 122 #if PAGE_SHIFT > IA32_PAGE_SHIFT 158 123
-35
arch/mips/kernel/linux32.c
··· 63 63 #define merge_64(r1, r2) ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL)) 64 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 66 asmlinkage unsigned long 102 67 sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot, 103 68 unsigned long flags, unsigned long fd, unsigned long pgoff)
-47
arch/parisc/kernel/sys_parisc32.c
··· 237 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 240 /*** copied from mips64 ***/ 288 241 /* 289 242 * Ooo, nasty. We need here to frob 32-bit unsigned longs to
-36
arch/powerpc/kernel/sys_ppc32.c
··· 61 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 64 /* Note: it is necessary to treat option as an unsigned int, 101 65 * with the corresponding cast to a signed int to insure that the 102 66 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
-35
arch/s390/kernel/compat_linux.c
··· 362 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 365 asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid, 401 366 struct compat_timespec __user *interval) 402 367 {
-35
arch/sparc64/kernel/sys_sparc32.c
··· 148 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 151 static int cp_compat_stat64(struct kstat *stat, 187 152 struct compat_stat64 __user *statbuf) 188 153 {
-35
arch/x86/ia32/sys_ia32.c
··· 49 49 50 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 53 asmlinkage long sys32_truncate64(char __user *filename, 89 54 unsigned long offset_low,
+39
fs/compat.c
··· 137 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 179 asmlinkage long compat_sys_newstat(char __user * filename, 141 180 struct compat_stat __user *statbuf) 142 181 {
-1
include/linux/compat.h
··· 78 78 compat_sigset_word sig[_COMPAT_NSIG_WORDS]; 79 79 } compat_sigset_t; 80 80 81 - extern int cp_compat_stat(struct kstat *, struct compat_stat __user *); 82 81 extern int get_compat_timespec(struct timespec *, const struct compat_timespec __user *); 83 82 extern int put_compat_timespec(const struct timespec *, struct compat_timespec __user *); 84 83