X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Freaddir.c;h=bff3ee58e2f86ecd8e599e104b46e7faa04752f5;hb=16c70f8c1b54b61c3b951b6fb220df250fe09b32;hp=fbea474bdb78884352ec0d09ea1d558177a3f732;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/fs/readdir.c b/fs/readdir.c index fbea474bd..bff3ee58e 100644 --- a/fs/readdir.c +++ b/fs/readdir.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -29,13 +30,13 @@ int vfs_readdir(struct file *file, filldir_t filler, void *buf) if (res) goto out; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); res = -ENOENT; if (!IS_DEADDIR(inode)) { res = file->f_op->readdir(file, buf, filler); file_accessed(file); } - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); out: return res; } @@ -68,20 +69,24 @@ struct readdir_callback { }; static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset, - ino_t ino, unsigned int d_type) + u64 ino, unsigned int d_type) { struct readdir_callback * buf = (struct readdir_callback *) __buf; struct old_linux_dirent __user * dirent; + unsigned long d_ino; if (buf->result) return -EINVAL; + d_ino = ino; + if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) + return -EOVERFLOW; buf->result++; dirent = buf->dirent; if (!access_ok(VERIFY_WRITE, dirent, (unsigned long)(dirent->d_name + namlen + 1) - (unsigned long)dirent)) goto efault; - if ( __put_user(ino, &dirent->d_ino) || + if ( __put_user(d_ino, &dirent->d_ino) || __put_user(offset, &dirent->d_offset) || __put_user(namlen, &dirent->d_namlen) || __copy_to_user(dirent->d_name, name, namlen) || @@ -137,22 +142,26 @@ struct getdents_callback { }; static int filldir(void * __buf, const char * name, int namlen, loff_t offset, - ino_t ino, unsigned int d_type) + u64 ino, unsigned int d_type) { struct linux_dirent __user * dirent; struct getdents_callback * buf = (struct getdents_callback *) __buf; + unsigned long d_ino; int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 2); buf->error = -EINVAL; /* only used if we fail.. */ if (reclen > buf->count) return -EINVAL; + d_ino = ino; + if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) + return -EOVERFLOW; dirent = buf->previous; if (dirent) { if (__put_user(offset, &dirent->d_off)) goto efault; } dirent = buf->current_dir; - if (__put_user(ino, &dirent->d_ino)) + if (__put_user(d_ino, &dirent->d_ino)) goto efault; if (__put_user(reclen, &dirent->d_reclen)) goto efault; @@ -221,7 +230,7 @@ struct getdents_callback64 { }; static int filldir64(void * __buf, const char * name, int namlen, loff_t offset, - ino_t ino, unsigned int d_type) + u64 ino, unsigned int d_type) { struct linux_dirent64 __user *dirent; struct getdents_callback64 * buf = (struct getdents_callback64 *) __buf; @@ -286,7 +295,9 @@ asmlinkage long sys_getdents64(unsigned int fd, struct linux_dirent64 __user * d lastdirent = buf.previous; if (lastdirent) { typeof(lastdirent->d_off) d_off = file->f_pos; - __put_user(d_off, &lastdirent->d_off); + error = -EFAULT; + if (__put_user(d_off, &lastdirent->d_off)) + goto out_putf; error = count - buf.count; }