Commit 86e07ce7 authored by David Gibson's avatar David Gibson Committed by Linus Torvalds

[PATCH] Fix error handling with put_compat_statfs()

In fs/compat.c, whenever put_compat_statfs() returns an error, the
containing syscall returns -EFAULT.  This is presumably by analogy with the
non-compat case, where any non-zero code from copy_to_user() should be
translated into an EFAULT.  However, put_compat_statfs() is also return
-EOVERFLOW.  The same applies for put_compat_statfs64().

This bug can be observed with a statfs() on a hugetlbfs directory.
hugetlbfs, when mounted without limits reports available, free and total
blocks as -1 (itself a bug, another patch coming).  statfs() will
mysteriously return EFAULT although it's parameters are perfectly valid
addresses.

This patch causes the compat versions of statfs() and statfs64() to
correctly propogate the return values from put_compat_statfs() and
put_compat_statfs64().
Signed-off-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f3d48f03
...@@ -168,8 +168,8 @@ asmlinkage long compat_sys_statfs(const char __user *path, struct compat_statfs ...@@ -168,8 +168,8 @@ asmlinkage long compat_sys_statfs(const char __user *path, struct compat_statfs
if (!error) { if (!error) {
struct kstatfs tmp; struct kstatfs tmp;
error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp);
if (!error && put_compat_statfs(buf, &tmp)) if (!error)
error = -EFAULT; error = put_compat_statfs(buf, &tmp);
path_release(&nd); path_release(&nd);
} }
return error; return error;
...@@ -186,8 +186,8 @@ asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user ...@@ -186,8 +186,8 @@ asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user
if (!file) if (!file)
goto out; goto out;
error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp);
if (!error && put_compat_statfs(buf, &tmp)) if (!error)
error = -EFAULT; error = put_compat_statfs(buf, &tmp);
fput(file); fput(file);
out: out:
return error; return error;
...@@ -236,8 +236,8 @@ asmlinkage long compat_sys_statfs64(const char __user *path, compat_size_t sz, s ...@@ -236,8 +236,8 @@ asmlinkage long compat_sys_statfs64(const char __user *path, compat_size_t sz, s
if (!error) { if (!error) {
struct kstatfs tmp; struct kstatfs tmp;
error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp);
if (!error && put_compat_statfs64(buf, &tmp)) if (!error)
error = -EFAULT; error = put_compat_statfs64(buf, &tmp);
path_release(&nd); path_release(&nd);
} }
return error; return error;
...@@ -257,8 +257,8 @@ asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct c ...@@ -257,8 +257,8 @@ asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct c
if (!file) if (!file)
goto out; goto out;
error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp);
if (!error && put_compat_statfs64(buf, &tmp)) if (!error)
error = -EFAULT; error = put_compat_statfs64(buf, &tmp);
fput(file); fput(file);
out: out:
return error; return error;
......
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