Merge branch 'i2c-embedded/for-current' of git://git.pengutronix.de/git/wsa/linux
[pandora-kernel.git] / fs / stat.c
index c733dc5..b6ff118 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -57,12 +57,13 @@ EXPORT_SYMBOL(vfs_getattr);
 
 int vfs_fstat(unsigned int fd, struct kstat *stat)
 {
-       struct file *f = fget(fd);
+       int fput_needed;
+       struct file *f = fget_light(fd, &fput_needed);
        int error = -EBADF;
 
        if (f) {
                error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat);
-               fput(f);
+               fput_light(f, fput_needed);
        }
        return error;
 }
@@ -137,8 +138,8 @@ static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * sta
        tmp.st_nlink = stat->nlink;
        if (tmp.st_nlink != stat->nlink)
                return -EOVERFLOW;
-       SET_UID(tmp.st_uid, stat->uid);
-       SET_GID(tmp.st_gid, stat->gid);
+       SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
+       SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
        tmp.st_rdev = old_encode_dev(stat->rdev);
 #if BITS_PER_LONG == 32
        if (stat->size > MAX_NON_LFS)
@@ -190,24 +191,32 @@ SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, stat
 
 #endif /* __ARCH_WANT_OLD_STAT */
 
+#if BITS_PER_LONG == 32
+#  define choose_32_64(a,b) a
+#else
+#  define choose_32_64(a,b) b
+#endif
+
+#define valid_dev(x)  choose_32_64(old_valid_dev,new_valid_dev)(x)
+#define encode_dev(x) choose_32_64(old_encode_dev,new_encode_dev)(x)
+
+#ifndef INIT_STRUCT_STAT_PADDING
+#  define INIT_STRUCT_STAT_PADDING(st) memset(&st, 0, sizeof(st))
+#endif
+
 static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
 {
        struct stat tmp;
 
-#if BITS_PER_LONG == 32
-       if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
+       if (!valid_dev(stat->dev) || !valid_dev(stat->rdev))
                return -EOVERFLOW;
-#else
-       if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
+#if BITS_PER_LONG == 32
+       if (stat->size > MAX_NON_LFS)
                return -EOVERFLOW;
 #endif
 
-       memset(&tmp, 0, sizeof(tmp));
-#if BITS_PER_LONG == 32
-       tmp.st_dev = old_encode_dev(stat->dev);
-#else
-       tmp.st_dev = new_encode_dev(stat->dev);
-#endif
+       INIT_STRUCT_STAT_PADDING(tmp);
+       tmp.st_dev = encode_dev(stat->dev);
        tmp.st_ino = stat->ino;
        if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
                return -EOVERFLOW;
@@ -215,17 +224,9 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
        tmp.st_nlink = stat->nlink;
        if (tmp.st_nlink != stat->nlink)
                return -EOVERFLOW;
-       SET_UID(tmp.st_uid, stat->uid);
-       SET_GID(tmp.st_gid, stat->gid);
-#if BITS_PER_LONG == 32
-       tmp.st_rdev = old_encode_dev(stat->rdev);
-#else
-       tmp.st_rdev = new_encode_dev(stat->rdev);
-#endif
-#if BITS_PER_LONG == 32
-       if (stat->size > MAX_NON_LFS)
-               return -EOVERFLOW;
-#endif 
+       SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
+       SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
+       tmp.st_rdev = encode_dev(stat->rdev);
        tmp.st_size = stat->size;
        tmp.st_atime = stat->atime.tv_sec;
        tmp.st_mtime = stat->mtime.tv_sec;
@@ -327,11 +328,15 @@ SYSCALL_DEFINE3(readlink, const char __user *, path, char __user *, buf,
 /* ---------- LFS-64 ----------- */
 #ifdef __ARCH_WANT_STAT64
 
+#ifndef INIT_STRUCT_STAT64_PADDING
+#  define INIT_STRUCT_STAT64_PADDING(st) memset(&st, 0, sizeof(st))
+#endif
+
 static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf)
 {
        struct stat64 tmp;
 
-       memset(&tmp, 0, sizeof(struct stat64));
+       INIT_STRUCT_STAT64_PADDING(tmp);
 #ifdef CONFIG_MIPS
        /* mips has weird padding, so we don't get 64 bits there */
        if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
@@ -350,8 +355,8 @@ static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf)
 #endif
        tmp.st_mode = stat->mode;
        tmp.st_nlink = stat->nlink;
-       tmp.st_uid = stat->uid;
-       tmp.st_gid = stat->gid;
+       tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid);
+       tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid);
        tmp.st_atime = stat->atime.tv_sec;
        tmp.st_atime_nsec = stat->atime.tv_nsec;
        tmp.st_mtime = stat->mtime.tv_sec;