summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/autofs4/waitq.c9
-rw-r--r--fs/binfmt_aout.c3
-rw-r--r--fs/binfmt_elf.c23
-rw-r--r--fs/binfmt_elf_fdpic.c17
-rw-r--r--fs/binfmt_flat.c18
-rw-r--r--fs/binfmt_misc.c5
-rw-r--r--fs/btrfs/send.c18
-rw-r--r--fs/coda/dir.c5
-rw-r--r--fs/ecryptfs/read_write.c4
-rw-r--r--fs/exec.c24
-rw-r--r--fs/read_write.c43
-rw-r--r--fs/splice.c16
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(&current->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);
}
/**
diff --git a/fs/exec.c b/fs/exec.c
index daa19d8..69a5432 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -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)
OpenPOWER on IntegriCloud