diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/autofs4/waitq.c | 9 | ||||
-rw-r--r-- | fs/binfmt_aout.c | 3 | ||||
-rw-r--r-- | fs/binfmt_elf.c | 23 | ||||
-rw-r--r-- | fs/binfmt_elf_fdpic.c | 17 | ||||
-rw-r--r-- | fs/binfmt_flat.c | 18 | ||||
-rw-r--r-- | fs/binfmt_misc.c | 5 | ||||
-rw-r--r-- | fs/btrfs/send.c | 18 | ||||
-rw-r--r-- | fs/coda/dir.c | 5 | ||||
-rw-r--r-- | fs/ecryptfs/read_write.c | 4 | ||||
-rw-r--r-- | fs/exec.c | 24 | ||||
-rw-r--r-- | fs/read_write.c | 43 | ||||
-rw-r--r-- | fs/splice.c | 16 |
12 files changed, 78 insertions, 107 deletions
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index 24a58bf..4ac49d0 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c @@ -56,19 +56,14 @@ static int autofs4_write(struct autofs_sb_info *sbi, struct file *file, const void *addr, int bytes) { unsigned long sigpipe, flags; - mm_segment_t fs; const char *data = (const char *)addr; ssize_t wr = 0; sigpipe = sigismember(¤t->pending.signal, SIGPIPE); - /* Save pointer to user space and point back to kernel space */ - fs = get_fs(); - set_fs(KERNEL_DS); - mutex_lock(&sbi->pipe_mutex); while (bytes) { - wr = __vfs_write(file, data, bytes, &file->f_pos); + wr = __kernel_write(file, data, bytes, &file->f_pos); if (wr <= 0) break; data += wr; @@ -76,8 +71,6 @@ static int autofs4_write(struct autofs_sb_info *sbi, } mutex_unlock(&sbi->pipe_mutex); - set_fs(fs); - /* Keep the currently executing process from receiving a * SIGPIPE unless it was already supposed to get one */ diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index 9be82c4..ce1824f 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c @@ -341,11 +341,12 @@ static int load_aout_library(struct file *file) unsigned long error; int retval; struct exec ex; + loff_t pos = 0; inode = file_inode(file); retval = -ENOEXEC; - error = kernel_read(file, 0, (char *) &ex, sizeof(ex)); + error = kernel_read(file, &ex, sizeof(ex), &pos); if (error != sizeof(ex)) goto out; diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index ec45d24..73b01e4 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -409,6 +409,7 @@ static struct elf_phdr *load_elf_phdrs(struct elfhdr *elf_ex, { struct elf_phdr *elf_phdata = NULL; int retval, size, err = -1; + loff_t pos = elf_ex->e_phoff; /* * If the size of this structure has changed, then punt, since @@ -432,8 +433,7 @@ static struct elf_phdr *load_elf_phdrs(struct elfhdr *elf_ex, goto out; /* Read in the program headers */ - retval = kernel_read(elf_file, elf_ex->e_phoff, - (char *)elf_phdata, size); + retval = kernel_read(elf_file, elf_phdata, size, &pos); if (retval != size) { err = (retval < 0) ? retval : -EIO; goto out; @@ -698,6 +698,7 @@ static int load_elf_binary(struct linux_binprm *bprm) struct elfhdr interp_elf_ex; } *loc; struct arch_elf_state arch_state = INIT_ARCH_ELF_STATE; + loff_t pos; loc = kmalloc(sizeof(*loc), GFP_KERNEL); if (!loc) { @@ -750,9 +751,9 @@ static int load_elf_binary(struct linux_binprm *bprm) if (!elf_interpreter) goto out_free_ph; - retval = kernel_read(bprm->file, elf_ppnt->p_offset, - elf_interpreter, - elf_ppnt->p_filesz); + pos = elf_ppnt->p_offset; + retval = kernel_read(bprm->file, elf_interpreter, + elf_ppnt->p_filesz, &pos); if (retval != elf_ppnt->p_filesz) { if (retval >= 0) retval = -EIO; @@ -776,9 +777,9 @@ static int load_elf_binary(struct linux_binprm *bprm) would_dump(bprm, interpreter); /* Get the exec headers */ - retval = kernel_read(interpreter, 0, - (void *)&loc->interp_elf_ex, - sizeof(loc->interp_elf_ex)); + pos = 0; + retval = kernel_read(interpreter, &loc->interp_elf_ex, + sizeof(loc->interp_elf_ex), &pos); if (retval != sizeof(loc->interp_elf_ex)) { if (retval >= 0) retval = -EIO; @@ -1175,9 +1176,10 @@ static int load_elf_library(struct file *file) unsigned long elf_bss, bss, len; int retval, error, i, j; struct elfhdr elf_ex; + loff_t pos = 0; error = -ENOEXEC; - retval = kernel_read(file, 0, (char *)&elf_ex, sizeof(elf_ex)); + retval = kernel_read(file, &elf_ex, sizeof(elf_ex), &pos); if (retval != sizeof(elf_ex)) goto out; @@ -1201,7 +1203,8 @@ static int load_elf_library(struct file *file) eppnt = elf_phdata; error = -ENOEXEC; - retval = kernel_read(file, elf_ex.e_phoff, (char *)eppnt, j); + pos = elf_ex.e_phoff; + retval = kernel_read(file, eppnt, j, &pos); if (retval != j) goto out_free_ph; diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 5aa9199..e70c039 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -145,6 +145,7 @@ static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, struct elf32_phdr *phdr; unsigned long size; int retval, loop; + loff_t pos = params->hdr.e_phoff; if (params->hdr.e_phentsize != sizeof(struct elf_phdr)) return -ENOMEM; @@ -156,8 +157,7 @@ static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, if (!params->phdrs) return -ENOMEM; - retval = kernel_read(file, params->hdr.e_phoff, - (char *) params->phdrs, size); + retval = kernel_read(file, params->phdrs, size, &pos); if (unlikely(retval != size)) return retval < 0 ? retval : -ENOEXEC; @@ -199,6 +199,7 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm) char *interpreter_name = NULL; int executable_stack; int retval, i; + loff_t pos; kdebug("____ LOAD %d ____", current->pid); @@ -246,10 +247,9 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm) if (!interpreter_name) goto error; - retval = kernel_read(bprm->file, - phdr->p_offset, - interpreter_name, - phdr->p_filesz); + pos = phdr->p_offset; + retval = kernel_read(bprm->file, interpreter_name, + phdr->p_filesz, &pos); if (unlikely(retval != phdr->p_filesz)) { if (retval >= 0) retval = -ENOEXEC; @@ -277,8 +277,9 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm) */ would_dump(bprm, interpreter); - retval = kernel_read(interpreter, 0, bprm->buf, - BINPRM_BUF_SIZE); + pos = 0; + retval = kernel_read(interpreter, bprm->buf, + BINPRM_BUF_SIZE, &pos); if (unlikely(retval != BINPRM_BUF_SIZE)) { if (retval >= 0) retval = -ENOEXEC; diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index ce6537c..475d083 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -176,19 +176,14 @@ static int create_flat_tables(struct linux_binprm *bprm, unsigned long arg_start #define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ #define RESERVED 0xC0 /* bit 6,7: reserved */ -static int decompress_exec( - struct linux_binprm *bprm, - unsigned long offset, - char *dst, - long len, - int fd) +static int decompress_exec(struct linux_binprm *bprm, loff_t fpos, char *dst, + long len, int fd) { unsigned char *buf; z_stream strm; - loff_t fpos; int ret, retval; - pr_debug("decompress_exec(offset=%lx,buf=%p,len=%lx)\n", offset, dst, len); + pr_debug("decompress_exec(offset=%llx,buf=%p,len=%lx)\n", fpos, dst, len); memset(&strm, 0, sizeof(strm)); strm.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); @@ -202,13 +197,11 @@ static int decompress_exec( } /* Read in first chunk of data and parse gzip header. */ - fpos = offset; - ret = kernel_read(bprm->file, offset, buf, LBUFSIZE); + ret = kernel_read(bprm->file, buf, LBUFSIZE, &fpos); strm.next_in = buf; strm.avail_in = ret; strm.total_in = 0; - fpos += ret; retval = -ENOEXEC; @@ -274,7 +267,7 @@ static int decompress_exec( } while ((ret = zlib_inflate(&strm, Z_NO_FLUSH)) == Z_OK) { - ret = kernel_read(bprm->file, fpos, buf, LBUFSIZE); + ret = kernel_read(bprm->file, buf, LBUFSIZE, &fpos); if (ret <= 0) break; len -= ret; @@ -282,7 +275,6 @@ static int decompress_exec( strm.next_in = buf; strm.avail_in = ret; strm.total_in = 0; - fpos += ret; } if (ret < 0) { diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index f471809..ce7181e 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -218,12 +218,15 @@ static int load_misc_binary(struct linux_binprm *bprm) bprm->file = interp_file; if (fmt->flags & MISC_FMT_CREDENTIALS) { + loff_t pos = 0; + /* * No need to call prepare_binprm(), it's already been * done. bprm->buf is stale, update from interp_file. */ memset(bprm->buf, 0, BINPRM_BUF_SIZE); - retval = kernel_read(bprm->file, 0, bprm->buf, BINPRM_BUF_SIZE); + retval = kernel_read(bprm->file, bprm->buf, BINPRM_BUF_SIZE, + &pos); } else retval = prepare_binprm(bprm); diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 8f1d3d6..32b043e 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -539,33 +539,23 @@ static struct btrfs_path *alloc_path_for_send(void) static int write_buf(struct file *filp, const void *buf, u32 len, loff_t *off) { int ret; - mm_segment_t old_fs; u32 pos = 0; - old_fs = get_fs(); - set_fs(KERNEL_DS); - while (pos < len) { - ret = vfs_write(filp, (__force const char __user *)buf + pos, - len - pos, off); + ret = kernel_write(filp, buf + pos, len - pos, off); /* TODO handle that correctly */ /*if (ret == -ERESTARTSYS) { continue; }*/ if (ret < 0) - goto out; + return ret; if (ret == 0) { - ret = -EIO; - goto out; + return -EIO; } pos += ret; } - ret = 0; - -out: - set_fs(old_fs); - return ret; + return 0; } static int tlv_put(struct send_ctx *sctx, u16 attr, const void *data, int len) diff --git a/fs/coda/dir.c b/fs/coda/dir.c index c0474ac..274ab55 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -368,9 +368,10 @@ static int coda_venus_readdir(struct file *coda_file, struct dir_context *ctx) goto out; while (1) { + loff_t pos = ctx->pos - 2; + /* read entries from the directory file */ - ret = kernel_read(host_file, ctx->pos - 2, (char *)vdir, - sizeof(*vdir)); + ret = kernel_read(host_file, vdir, sizeof(*vdir), &pos); if (ret < 0) { pr_err("%s: read dir %s failed %d\n", __func__, coda_f2s(&cii->c_fid), ret); diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c index 039e627..c596e7c 100644 --- a/fs/ecryptfs/read_write.c +++ b/fs/ecryptfs/read_write.c @@ -47,7 +47,7 @@ int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data, lower_file = ecryptfs_inode_to_private(ecryptfs_inode)->lower_file; if (!lower_file) return -EIO; - rc = kernel_write(lower_file, data, size, offset); + rc = kernel_write(lower_file, data, size, &offset); mark_inode_dirty_sync(ecryptfs_inode); return rc; } @@ -237,7 +237,7 @@ int ecryptfs_read_lower(char *data, loff_t offset, size_t size, lower_file = ecryptfs_inode_to_private(ecryptfs_inode)->lower_file; if (!lower_file) return -EIO; - return kernel_read(lower_file, offset, data, size); + return kernel_read(lower_file, data, size, &offset); } /** @@ -885,23 +885,6 @@ struct file *open_exec(const char *name) } EXPORT_SYMBOL(open_exec); -int kernel_read(struct file *file, loff_t offset, - char *addr, unsigned long count) -{ - mm_segment_t old_fs; - loff_t pos = offset; - int result; - - old_fs = get_fs(); - set_fs(get_ds()); - /* The cast to a user pointer is valid due to the set_fs() */ - result = vfs_read(file, (void __user *)addr, count, &pos); - set_fs(old_fs); - return result; -} - -EXPORT_SYMBOL(kernel_read); - int kernel_read_file(struct file *file, void **buf, loff_t *size, loff_t max_size, enum kernel_read_file_id id) { @@ -939,8 +922,7 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size, pos = 0; while (pos < i_size) { - bytes = kernel_read(file, pos, (char *)(*buf) + pos, - i_size - pos); + bytes = kernel_read(file, *buf + pos, i_size - pos, &pos); if (bytes < 0) { ret = bytes; goto out; @@ -948,7 +930,6 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size, if (bytes == 0) break; - pos += bytes; } if (pos != i_size) { @@ -1567,6 +1548,7 @@ static void bprm_fill_uid(struct linux_binprm *bprm) int prepare_binprm(struct linux_binprm *bprm) { int retval; + loff_t pos = 0; bprm_fill_uid(bprm); @@ -1577,7 +1559,7 @@ int prepare_binprm(struct linux_binprm *bprm) bprm->called_set_creds = 1; memset(bprm->buf, 0, BINPRM_BUF_SIZE); - return kernel_read(bprm->file, 0, bprm->buf, BINPRM_BUF_SIZE); + return kernel_read(bprm->file, bprm->buf, BINPRM_BUF_SIZE, &pos); } EXPORT_SYMBOL(prepare_binprm); diff --git a/fs/read_write.c b/fs/read_write.c index 61b58c7..a2b9a47 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -413,7 +413,20 @@ ssize_t __vfs_read(struct file *file, char __user *buf, size_t count, else return -EINVAL; } -EXPORT_SYMBOL(__vfs_read); + +ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos) +{ + mm_segment_t old_fs; + ssize_t result; + + old_fs = get_fs(); + set_fs(get_ds()); + /* The cast to a user pointer is valid due to the set_fs() */ + result = vfs_read(file, (void __user *)buf, count, pos); + set_fs(old_fs); + return result; +} +EXPORT_SYMBOL(kernel_read); ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { @@ -441,8 +454,6 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) return ret; } -EXPORT_SYMBOL(vfs_read); - static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos) { struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len }; @@ -471,9 +482,8 @@ ssize_t __vfs_write(struct file *file, const char __user *p, size_t count, else return -EINVAL; } -EXPORT_SYMBOL(__vfs_write); -ssize_t __kernel_write(struct file *file, const char *buf, size_t count, loff_t *pos) +ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos) { mm_segment_t old_fs; const char __user *p; @@ -496,9 +506,24 @@ ssize_t __kernel_write(struct file *file, const char *buf, size_t count, loff_t inc_syscw(current); return ret; } - EXPORT_SYMBOL(__kernel_write); +ssize_t kernel_write(struct file *file, const void *buf, size_t count, + loff_t *pos) +{ + mm_segment_t old_fs; + ssize_t res; + + old_fs = get_fs(); + set_fs(get_ds()); + /* The cast to a user pointer is valid due to the set_fs() */ + res = vfs_write(file, (__force const char __user *)buf, count, pos); + set_fs(old_fs); + + return res; +} +EXPORT_SYMBOL(kernel_write); + ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) { ssize_t ret; @@ -527,8 +552,6 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_ return ret; } -EXPORT_SYMBOL(vfs_write); - static inline loff_t file_pos_read(struct file *file) { return file->f_pos; @@ -959,9 +982,8 @@ ssize_t vfs_readv(struct file *file, const struct iovec __user *vec, return ret; } -EXPORT_SYMBOL(vfs_readv); -ssize_t vfs_writev(struct file *file, const struct iovec __user *vec, +static ssize_t vfs_writev(struct file *file, const struct iovec __user *vec, unsigned long vlen, loff_t *pos, rwf_t flags) { struct iovec iovstack[UIO_FASTIOV]; @@ -978,7 +1000,6 @@ ssize_t vfs_writev(struct file *file, const struct iovec __user *vec, } return ret; } -EXPORT_SYMBOL(vfs_writev); static ssize_t do_readv(unsigned long fd, const struct iovec __user *vec, unsigned long vlen, rwf_t flags) diff --git a/fs/splice.c b/fs/splice.c index ae41201..f3084cc 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -364,22 +364,6 @@ static ssize_t kernel_readv(struct file *file, const struct kvec *vec, return res; } -ssize_t kernel_write(struct file *file, const char *buf, size_t count, - loff_t pos) -{ - mm_segment_t old_fs; - ssize_t res; - - old_fs = get_fs(); - set_fs(get_ds()); - /* The cast to a user pointer is valid due to the set_fs() */ - res = vfs_write(file, (__force const char __user *)buf, count, &pos); - set_fs(old_fs); - - return res; -} -EXPORT_SYMBOL(kernel_write); - static ssize_t default_file_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags) |