Commit 2eb4051e authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Fix readdir error return value

From: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>

There are a couple of places in the readdir code where it forgets to set
the returned error code to -EFAULT, leaving it at the default -EINVAL.

Fix that up, and rename getdents_callback64.count to "result", which makes
more sense.
parent 61a6c177
...@@ -59,7 +59,7 @@ struct old_linux_dirent { ...@@ -59,7 +59,7 @@ struct old_linux_dirent {
struct readdir_callback { struct readdir_callback {
struct old_linux_dirent __user * dirent; struct old_linux_dirent __user * dirent;
int count; int result;
}; };
static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset, static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset,
...@@ -68,21 +68,24 @@ static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset ...@@ -68,21 +68,24 @@ static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset
struct readdir_callback * buf = (struct readdir_callback *) __buf; struct readdir_callback * buf = (struct readdir_callback *) __buf;
struct old_linux_dirent __user * dirent; struct old_linux_dirent __user * dirent;
if (buf->count) if (buf->result)
return -EINVAL; return -EINVAL;
buf->count++; buf->result++;
dirent = buf->dirent; dirent = buf->dirent;
if (!access_ok(VERIFY_WRITE, (unsigned long)dirent, if (!access_ok(VERIFY_WRITE, (unsigned long)dirent,
(unsigned long)(dirent->d_name + namlen + 1) - (unsigned long)(dirent->d_name + namlen + 1) -
(unsigned long)dirent)) (unsigned long)dirent))
return -EFAULT; goto efault;
if ( __put_user(ino, &dirent->d_ino) || if ( __put_user(ino, &dirent->d_ino) ||
__put_user(offset, &dirent->d_offset) || __put_user(offset, &dirent->d_offset) ||
__put_user(namlen, &dirent->d_namlen) || __put_user(namlen, &dirent->d_namlen) ||
__copy_to_user(dirent->d_name, name, namlen) || __copy_to_user(dirent->d_name, name, namlen) ||
__put_user(0, dirent->d_name + namlen)) __put_user(0, dirent->d_name + namlen))
return -EFAULT; goto efault;
return 0; return 0;
efault:
buf->result = -EFAULT;
return -EFAULT;
} }
asmlinkage long old_readdir(unsigned int fd, struct old_linux_dirent __user * dirent, unsigned int count) asmlinkage long old_readdir(unsigned int fd, struct old_linux_dirent __user * dirent, unsigned int count)
...@@ -96,12 +99,12 @@ asmlinkage long old_readdir(unsigned int fd, struct old_linux_dirent __user * di ...@@ -96,12 +99,12 @@ asmlinkage long old_readdir(unsigned int fd, struct old_linux_dirent __user * di
if (!file) if (!file)
goto out; goto out;
buf.count = 0; buf.result = 0;
buf.dirent = dirent; buf.dirent = dirent;
error = vfs_readdir(file, fillonedir, &buf); error = vfs_readdir(file, fillonedir, &buf);
if (error >= 0) if (error >= 0)
error = buf.count; error = buf.result;
fput(file); fput(file);
out: out:
...@@ -144,7 +147,6 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset, ...@@ -144,7 +147,6 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
goto efault; goto efault;
} }
dirent = buf->current_dir; dirent = buf->current_dir;
buf->previous = dirent;
if (__put_user(ino, &dirent->d_ino)) if (__put_user(ino, &dirent->d_ino))
goto efault; goto efault;
if (__put_user(reclen, &dirent->d_reclen)) if (__put_user(reclen, &dirent->d_reclen))
...@@ -153,11 +155,13 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset, ...@@ -153,11 +155,13 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
goto efault; goto efault;
if (__put_user(0, dirent->d_name + namlen)) if (__put_user(0, dirent->d_name + namlen))
goto efault; goto efault;
buf->previous = dirent;
((char *) dirent) += reclen; ((char *) dirent) += reclen;
buf->current_dir = dirent; buf->current_dir = dirent;
buf->count -= reclen; buf->count -= reclen;
return 0; return 0;
efault: efault:
buf->error = -EFAULT;
return -EFAULT; return -EFAULT;
} }
...@@ -225,7 +229,6 @@ static int filldir64(void * __buf, const char * name, int namlen, loff_t offset, ...@@ -225,7 +229,6 @@ static int filldir64(void * __buf, const char * name, int namlen, loff_t offset,
goto efault; goto efault;
} }
dirent = buf->current_dir; dirent = buf->current_dir;
buf->previous = dirent;
if (__put_user(ino, &dirent->d_ino)) if (__put_user(ino, &dirent->d_ino))
goto efault; goto efault;
if (__put_user(0, &dirent->d_off)) if (__put_user(0, &dirent->d_off))
...@@ -238,11 +241,13 @@ static int filldir64(void * __buf, const char * name, int namlen, loff_t offset, ...@@ -238,11 +241,13 @@ static int filldir64(void * __buf, const char * name, int namlen, loff_t offset,
goto efault; goto efault;
if (__put_user(0, dirent->d_name + namlen)) if (__put_user(0, dirent->d_name + namlen))
goto efault; goto efault;
buf->previous = dirent;
((char *) dirent) += reclen; ((char *) dirent) += reclen;
buf->current_dir = dirent; buf->current_dir = dirent;
buf->count -= reclen; buf->count -= reclen;
return 0; return 0;
efault: efault:
buf->error = -EFAULT;
return -EFAULT; return -EFAULT;
} }
......
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