upgrade to linux 2.6.10-1.12_FC2
[linux-2.6.git] / fs / compat.c
index 8fdb224..4120c9e 100644 (file)
@@ -117,10 +117,17 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *
 {
        
        if (sizeof ubuf->f_blocks == 4) {
-               if ((kbuf->f_blocks | kbuf->f_bfree |
-                    kbuf->f_bavail | kbuf->f_files | kbuf->f_ffree) &
+               if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail) &
                    0xffffffff00000000ULL)
                        return -EOVERFLOW;
+               /* f_files and f_ffree may be -1; it's okay
+                * to stuff that into 32 bits */
+               if (kbuf->f_files != 0xffffffffffffffffULL
+                && (kbuf->f_files & 0xffffffff00000000ULL))
+                       return -EOVERFLOW;
+               if (kbuf->f_ffree != 0xffffffffffffffffULL
+                && (kbuf->f_ffree & 0xffffffff00000000ULL))
+                       return -EOVERFLOW;
        }
        if (verify_area(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
            __put_user(kbuf->f_type, &ubuf->f_type) ||
@@ -184,10 +191,17 @@ out:
 static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf)
 {
        if (sizeof ubuf->f_blocks == 4) {
-               if ((kbuf->f_blocks | kbuf->f_bfree |
-                    kbuf->f_bavail | kbuf->f_files | kbuf->f_ffree) &
+               if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail) &
                    0xffffffff00000000ULL)
                        return -EOVERFLOW;
+               /* f_files and f_ffree may be -1; it's okay
+                * to stuff that into 32 bits */
+               if (kbuf->f_files != 0xffffffffffffffffULL
+                && (kbuf->f_files & 0xffffffff00000000ULL))
+                       return -EOVERFLOW;
+               if (kbuf->f_ffree != 0xffffffffffffffffULL
+                && (kbuf->f_ffree & 0xffffffff00000000ULL))
+                       return -EOVERFLOW;
        }
        if (verify_area(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
            __put_user(kbuf->f_type, &ubuf->f_type) ||
@@ -205,7 +219,7 @@ static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstat
        return 0;
 }
 
-asmlinkage long compat_statfs64(const char __user *path, compat_size_t sz, struct compat_statfs64 __user *buf)
+asmlinkage long compat_sys_statfs64(const char __user *path, compat_size_t sz, struct compat_statfs64 __user *buf)
 {
        struct nameidata nd;
        int error;
@@ -224,7 +238,7 @@ asmlinkage long compat_statfs64(const char __user *path, compat_size_t sz, struc
        return error;
 }
 
-asmlinkage long compat_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf)
+asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf)
 {
        struct file * file;
        struct kstatfs tmp;
@@ -527,11 +541,11 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
                set_fs(KERNEL_DS);
                ret = sys_fcntl(fd, cmd, (unsigned long)&f);
                set_fs(old_fs);
-               if ((cmd == F_GETLK) && (ret == 0)) {
-                       if ((compat_off_t) f.l_start != f.l_start ||
-                           (compat_off_t) f.l_len != f.l_len)
+               if (cmd == F_GETLK && ret == 0) {
+                       if ((f.l_start >= COMPAT_OFF_T_MAX) ||
+                           ((f.l_start + f.l_len) > COMPAT_OFF_T_MAX))
                                ret = -EOVERFLOW;
-                       else
+                       if (ret == 0)
                                ret = put_compat_flock(&f, compat_ptr(arg));
                }
                break;
@@ -548,11 +562,11 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
                                ((cmd == F_SETLK64) ? F_SETLK : F_SETLKW),
                                (unsigned long)&f);
                set_fs(old_fs);
-               if ((cmd == F_GETLK64) && (ret == 0)) {
-                       if ((compat_loff_t) f.l_start != f.l_start ||
-                           (compat_loff_t) f.l_len != f.l_len)
+               if (cmd == F_GETLK64 && ret == 0) {
+                       if ((f.l_start >= COMPAT_LOFF_T_MAX) ||
+                           ((f.l_start + f.l_len) > COMPAT_LOFF_T_MAX))
                                ret = -EOVERFLOW;
-                       else
+                       if (ret == 0)
                                ret = put_compat_flock64(&f, compat_ptr(arg));
                }
                break;
@@ -846,7 +860,7 @@ efault:
        return -EFAULT;
 }
 
-asmlinkage long compat_old_readdir(unsigned int fd,
+asmlinkage long compat_sys_old_readdir(unsigned int fd,
        struct compat_old_linux_dirent __user *dirent, unsigned int count)
 {
        int error;
@@ -1373,25 +1387,25 @@ int compat_do_execve(char * filename,
        int retval;
        int i;
 
-       file = open_exec(filename);
-
-       retval = PTR_ERR(file);
-       if (IS_ERR(file))
-               return retval;
-
-       sched_exec();
-
        retval = -ENOMEM;
        bprm = kmalloc(sizeof(*bprm), GFP_KERNEL);
        if (!bprm)
                goto out_ret;
        memset(bprm, 0, sizeof(*bprm));
 
+       file = open_exec(filename);
+       retval = PTR_ERR(file);
+       if (IS_ERR(file))
+               goto out_kfree;
+
+       sched_exec();
+
        bprm->p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
        bprm->file = file;
        bprm->filename = filename;
        bprm->interp = filename;
        bprm->mm = mm_alloc();
+       retval = -ENOMEM;
        if (!bprm->mm)
                goto out_file;
 
@@ -1458,6 +1472,8 @@ out_file:
                allow_write_access(bprm->file);
                fput(bprm->file);
        }
+
+out_kfree:
        kfree(bprm);
 
 out_ret: