diff --git a/fs/read_write.c b/fs/read_write.c index 4da846a2bf17..4da3e553090b 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -441,7 +441,7 @@ SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high, whence); retval = (int)offset; - if (offset >= 0) { + if (offset >= 0 || (unsigned_offsets(fd_file(f)) && offset < -MAX_ERRNO)) { retval = -EFAULT; if (!copy_to_user(result, &offset, sizeof(offset))) retval = 0; @@ -753,13 +753,13 @@ SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, ssize_t ksys_pread64(unsigned int fd, char __user *buf, size_t count, loff_t pos) { - if (pos < 0) - return -EINVAL; - CLASS(fd, f)(fd); if (fd_empty(f)) return -EBADF; + if (pos < 0 && !unsigned_offsets(fd_file(f))) + return -EINVAL; + if (fd_file(f)->f_mode & FMODE_PREAD) return vfs_read(fd_file(f), buf, count, &pos); @@ -783,13 +783,13 @@ COMPAT_SYSCALL_DEFINE5(pread64, unsigned int, fd, char __user *, buf, ssize_t ksys_pwrite64(unsigned int fd, const char __user *buf, size_t count, loff_t pos) { - if (pos < 0) - return -EINVAL; - CLASS(fd, f)(fd); if (fd_empty(f)) return -EBADF; + if (pos < 0 && !unsigned_offsets(fd_file(f))) + return -EINVAL; + if (fd_file(f)->f_mode & FMODE_PWRITE) return vfs_write(fd_file(f), buf, count, &pos); @@ -1123,14 +1123,14 @@ static ssize_t do_preadv(unsigned long fd, const struct iovec __user *vec, { ssize_t ret = -EBADF; - if (pos < 0) - return -EINVAL; - CLASS(fd, f)(fd); if (!fd_empty(f)) { - ret = -ESPIPE; - if (fd_file(f)->f_mode & FMODE_PREAD) - ret = vfs_readv(fd_file(f), vec, vlen, &pos, flags); + ret = -EINVAL; + if (pos >= 0 || unsigned_offsets(fd_file(f))) { + ret = -ESPIPE; + if (fd_file(f)->f_mode & FMODE_PREAD) + ret = vfs_readv(fd_file(f), vec, vlen, &pos, flags); + } } if (ret > 0) @@ -1144,14 +1144,14 @@ static ssize_t do_pwritev(unsigned long fd, const struct iovec __user *vec, { ssize_t ret = -EBADF; - if (pos < 0) - return -EINVAL; - CLASS(fd, f)(fd); if (!fd_empty(f)) { - ret = -ESPIPE; - if (fd_file(f)->f_mode & FMODE_PWRITE) - ret = vfs_writev(fd_file(f), vec, vlen, &pos, flags); + ret = -EINVAL; + if (pos >= 0 || unsigned_offsets(fd_file(f))) { + ret = -ESPIPE; + if (fd_file(f)->f_mode & FMODE_PWRITE) + ret = vfs_writev(fd_file(f), vec, vlen, &pos, flags); + } } if (ret > 0)