Commit 30c1c584 authored by Olaf Kirch's avatar Olaf Kirch Committed by Linus Torvalds

[PATCH] statfs compat functions can return EOVERFLOW on NFS

A while ago, we fixed a problem in statfs on 64bit system that caused it
to return EOVERFLOW when the number of files reported by the underlying
file system was -1 (which happens for NFS for instance). The problematic
code was this:

        if (sizeof ubuf->f_blocks == 4) {
                if ((kbuf->f_blocks | kbuf->f_bfree |
                     kbuf->f_bavail | kbuf->f_files | kbuf->f_ffree) &
                    0xffffffff00000000ULL)
                        return -EOVERFLOW;
		...
	}

The problem was fixed by explicitly allowing f_files and f_ffree to be -1.

The same problem exists in fs/compat.c, and the attached patch fixes it
in a similar manner.
Signed-Off-By: default avatarOlaf Kirch <okir@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent fc0c58f5
...@@ -117,10 +117,17 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs * ...@@ -117,10 +117,17 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *
{ {
if (sizeof ubuf->f_blocks == 4) { if (sizeof ubuf->f_blocks == 4) {
if ((kbuf->f_blocks | kbuf->f_bfree | if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail) &
kbuf->f_bavail | kbuf->f_files | kbuf->f_ffree) &
0xffffffff00000000ULL) 0xffffffff00000000ULL)
return -EOVERFLOW; 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)) || if (verify_area(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
__put_user(kbuf->f_type, &ubuf->f_type) || __put_user(kbuf->f_type, &ubuf->f_type) ||
...@@ -184,10 +191,17 @@ asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user ...@@ -184,10 +191,17 @@ asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user
static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf) static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf)
{ {
if (sizeof ubuf->f_blocks == 4) { if (sizeof ubuf->f_blocks == 4) {
if ((kbuf->f_blocks | kbuf->f_bfree | if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail) &
kbuf->f_bavail | kbuf->f_files | kbuf->f_ffree) &
0xffffffff00000000ULL) 0xffffffff00000000ULL)
return -EOVERFLOW; 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)) || if (verify_area(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
__put_user(kbuf->f_type, &ubuf->f_type) || __put_user(kbuf->f_type, &ubuf->f_type) ||
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment