[PATCH 05/16] fs: fix kernel_read prototype

From: Christoph Hellwig
Date: Wed Aug 30 2017 - 11:00:35 EST


Use proper ssize_t and size_t types for the return value and count
argument, move the offset last and make it an in/out argument like
all other read/write helpers.

Signed-off-by: Christoph Hellwig <hch@xxxxxx>
---
arch/mips/kernel/elf.c | 12 ++++--------
arch/x86/ia32/ia32_aout.c | 4 ++--
drivers/media/pci/cx25821/cx25821-audio-upstream.c | 8 ++------
drivers/mtd/nand/nandsim.c | 2 +-
fs/binfmt_aout.c | 3 ++-
fs/binfmt_elf.c | 22 +++++++++++++---------
fs/binfmt_elf_fdpic.c | 17 +++++++++--------
fs/binfmt_flat.c | 18 +++++-------------
fs/binfmt_misc.c | 5 ++++-
fs/coda/dir.c | 5 +++--
fs/ecryptfs/read_write.c | 2 +-
fs/exec.c | 8 ++++----
fs/read_write.c | 8 +++-----
include/linux/fs.h | 2 +-
kernel/sysctl_binary.c | 12 ++++++++----
net/9p/trans_fd.c | 4 +++-
security/keys/big_key.c | 3 ++-
17 files changed, 67 insertions(+), 68 deletions(-)

diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c
index 5c429d70e17f..290b8a12ad8c 100644
--- a/arch/mips/kernel/elf.c
+++ b/arch/mips/kernel/elf.c
@@ -87,6 +87,7 @@ int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
bool elf32;
u32 flags;
int ret;
+ loff_t pos;

elf32 = ehdr->e32.e_ident[EI_CLASS] == ELFCLASS32;
flags = elf32 ? ehdr->e32.e_flags : ehdr->e64.e_flags;
@@ -108,21 +109,16 @@ int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,

if (phdr32->p_filesz < sizeof(abiflags))
return -EINVAL;
-
- ret = kernel_read(elf, phdr32->p_offset,
- (char *)&abiflags,
- sizeof(abiflags));
+ pos = phdr32->p_offset;
} else {
if (phdr64->p_type != PT_MIPS_ABIFLAGS)
return 0;
if (phdr64->p_filesz < sizeof(abiflags))
return -EINVAL;
-
- ret = kernel_read(elf, phdr64->p_offset,
- (char *)&abiflags,
- sizeof(abiflags));
+ pos = phdr64->p_offset;
}

+ ret = kernel_read(elf, (char *)&abiflags, sizeof(abiflags), &pos);
if (ret < 0)
return ret;
if (ret != sizeof(abiflags))
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
index 8d0879f1d42c..6ae2571afd40 100644
--- a/arch/x86/ia32/ia32_aout.c
+++ b/arch/x86/ia32/ia32_aout.c
@@ -407,10 +407,10 @@ static int load_aout_library(struct file *file)
unsigned long bss, start_addr, len, error;
int retval;
struct exec ex;
-
+ loff_t pos = 0;

retval = -ENOEXEC;
- error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
+ error = kernel_read(file, (char *) &ex, sizeof(ex), &pos);
if (error != sizeof(ex))
goto out;

diff --git a/drivers/media/pci/cx25821/cx25821-audio-upstream.c b/drivers/media/pci/cx25821/cx25821-audio-upstream.c
index b94eb1c0023d..ef1f6c423e6d 100644
--- a/drivers/media/pci/cx25821/cx25821-audio-upstream.c
+++ b/drivers/media/pci/cx25821/cx25821-audio-upstream.c
@@ -277,7 +277,7 @@ static int cx25821_get_audio_data(struct cx25821_dev *dev,
p = (char *)dev->_audiodata_buf_virt_addr + frame_offset;

for (i = 0; i < dev->_audio_lines_count; i++) {
- int n = kernel_read(file, file_offset, mybuf, AUDIO_LINE_SIZE);
+ int n = kernel_read(file, mybuf, AUDIO_LINE_SIZE, &file_offset);
if (n < AUDIO_LINE_SIZE) {
pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
__func__);
@@ -290,7 +290,6 @@ static int cx25821_get_audio_data(struct cx25821_dev *dev,
memcpy(p, mybuf, n);
p += n;
}
- file_offset += n;
}
dev->_audioframe_count++;
fput(file);
@@ -331,8 +330,7 @@ static int cx25821_openfile_audio(struct cx25821_dev *dev,
for (j = 0, offset = 0; j < NUM_AUDIO_FRAMES; j++) {
for (i = 0; i < dev->_audio_lines_count; i++) {
char buf[AUDIO_LINE_SIZE];
- int n = kernel_read(file, offset, buf,
- AUDIO_LINE_SIZE);
+ int n = kernel_read(file, buf, AUDIO_LINE_SIZE, &offset);

if (n < AUDIO_LINE_SIZE) {
pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
@@ -344,8 +342,6 @@ static int cx25821_openfile_audio(struct cx25821_dev *dev,

if (p)
memcpy(p + offset, buf, n);
-
- offset += n;
}
dev->_audioframe_count++;
}
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index e4211c3cc49b..a8089656879a 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -1379,7 +1379,7 @@ static ssize_t read_file(struct nandsim *ns, struct file *file, void *buf, size_
if (err)
return err;
noreclaim_flag = memalloc_noreclaim_save();
- tx = kernel_read(file, pos, buf, count);
+ tx = kernel_read(file, buf, count, &pos);
memalloc_noreclaim_restore(noreclaim_flag);
put_pages(ns);
return tx;
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 9be82c4e14a4..74e9893dbce6 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, (char *) &ex, sizeof(ex), &pos);
if (error != sizeof(ex))
goto out;

diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 6466153f2bf0..42de02ab9d9e 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, (char *)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,10 @@ static int load_elf_binary(struct linux_binprm *bprm)
would_dump(bprm, interpreter);

/* Get the exec headers */
- retval = kernel_read(interpreter, 0,
+ pos = 0;
+ retval = kernel_read(interpreter,
(void *)&loc->interp_elf_ex,
- sizeof(loc->interp_elf_ex));
+ sizeof(loc->interp_elf_ex), &pos);
if (retval != sizeof(loc->interp_elf_ex)) {
if (retval >= 0)
retval = -EIO;
@@ -1175,9 +1177,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, (char *)&elf_ex, sizeof(elf_ex), &pos);
if (retval != sizeof(elf_ex))
goto out;

@@ -1201,7 +1204,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, (char *)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 cf93a4fad012..f86222c82621 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, (char *) 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 a1e6860b6f46..afb7e9d521d2 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);
@@ -204,13 +199,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;

@@ -276,7 +269,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;
@@ -284,7 +277,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 f4718098ac31..ce7181ea60fa 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/coda/dir.c b/fs/coda/dir.c
index c0474ac6cbf2..86048b76b6d8 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, (char *)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 039e627194a9..d8af0e99bfaf 100644
--- a/fs/ecryptfs/read_write.c
+++ b/fs/ecryptfs/read_write.c
@@ -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 8adcc5eaa175..8d642e4f9857 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -922,8 +922,8 @@ 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, (char *)(*buf) + pos,
+ i_size - pos, &pos);
if (bytes < 0) {
ret = bytes;
goto out;
@@ -931,7 +931,6 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size,

if (bytes == 0)
break;
- pos += bytes;
}

if (pos != i_size) {
@@ -1524,6 +1523,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);

@@ -1534,7 +1534,7 @@ int prepare_binprm(struct linux_binprm *bprm)
bprm->cred_prepared = 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 1ea862bc7efd..1966fd6e03ce 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -415,17 +415,15 @@ ssize_t __vfs_read(struct file *file, char __user *buf, size_t count,
}
EXPORT_SYMBOL(__vfs_read);

-int kernel_read(struct file *file, loff_t offset, char *addr,
- unsigned long count)
+ssize_t kernel_read(struct file *file, char *buf, size_t count, loff_t *pos)
{
mm_segment_t old_fs;
- loff_t pos = offset;
- int result;
+ 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 *)addr, count, &pos);
+ result = vfs_read(file, (void __user *)buf, count, pos);
set_fs(old_fs);
return result;
}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index cbfe127bccf8..1b9d083adf94 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2772,13 +2772,13 @@ static inline const char *kernel_read_file_id_str(enum kernel_read_file_id id)
return kernel_read_file_str[id];
}

-extern int kernel_read(struct file *, loff_t, char *, unsigned long);
extern int kernel_read_file(struct file *, void **, loff_t *, loff_t,
enum kernel_read_file_id);
extern int kernel_read_file_from_path(char *, void **, loff_t *, loff_t,
enum kernel_read_file_id);
extern int kernel_read_file_from_fd(int, void **, loff_t *, loff_t,
enum kernel_read_file_id);
+extern ssize_t kernel_read(struct file *, char *, size_t, loff_t *);
extern ssize_t kernel_write(struct file *, const char *, size_t, loff_t);
extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
extern struct file * open_exec(const char *);
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
index 02e1859f2ca8..243fa1c28b4a 100644
--- a/kernel/sysctl_binary.c
+++ b/kernel/sysctl_binary.c
@@ -986,8 +986,9 @@ static ssize_t bin_intvec(struct file *file,
size_t length = oldlen / sizeof(*vec);
char *str, *end;
int i;
+ loff_t pos = 0;

- result = kernel_read(file, 0, buffer, BUFSZ - 1);
+ result = kernel_read(file, buffer, BUFSZ - 1, &pos);
if (result < 0)
goto out_kfree;

@@ -1057,8 +1058,9 @@ static ssize_t bin_ulongvec(struct file *file,
size_t length = oldlen / sizeof(*vec);
char *str, *end;
int i;
+ loff_t pos = 0;

- result = kernel_read(file, 0, buffer, BUFSZ - 1);
+ result = kernel_read(file, buffer, BUFSZ - 1, &pos);
if (result < 0)
goto out_kfree;

@@ -1120,8 +1122,9 @@ static ssize_t bin_uuid(struct file *file,
if (oldval && oldlen) {
char buf[UUID_STRING_LEN + 1];
uuid_t uuid;
+ loff_t pos = 0;

- result = kernel_read(file, 0, buf, sizeof(buf) - 1);
+ result = kernel_read(file, buf, sizeof(buf) - 1, &pos);
if (result < 0)
goto out;

@@ -1154,8 +1157,9 @@ static ssize_t bin_dn_node_address(struct file *file,
char buf[15], *nodep;
unsigned long area, node;
__le16 dnaddr;
+ loff_t pos = 0;

- result = kernel_read(file, 0, buf, sizeof(buf) - 1);
+ result = kernel_read(file, buf, sizeof(buf) - 1, &pos);
if (result < 0)
goto out;

diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index ddfa86648f95..f12815777beb 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -272,6 +272,7 @@ static int p9_fd_read(struct p9_client *client, void *v, int len)
{
int ret;
struct p9_trans_fd *ts = NULL;
+ loff_t pos;

if (client && client->status != Disconnected)
ts = client->trans;
@@ -282,7 +283,8 @@ static int p9_fd_read(struct p9_client *client, void *v, int len)
if (!(ts->rd->f_flags & O_NONBLOCK))
p9_debug(P9_DEBUG_ERROR, "blocking read ...\n");

- ret = kernel_read(ts->rd, ts->rd->f_pos, v, len);
+ pos = ts->rd->f_pos;
+ ret = kernel_read(ts->rd, v, len, &pos);
if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
client->status = Disconnected;
return ret;
diff --git a/security/keys/big_key.c b/security/keys/big_key.c
index 835c1ab30d01..9f4c86cade8e 100644
--- a/security/keys/big_key.c
+++ b/security/keys/big_key.c
@@ -295,6 +295,7 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
u8 *data;
u8 *enckey = (u8 *)key->payload.data[big_key_data];
size_t enclen = ALIGN(datalen, crypto_skcipher_blocksize(big_key_skcipher));
+ loff_t pos = 0;

data = kmalloc(enclen, GFP_KERNEL);
if (!data)
@@ -307,7 +308,7 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
}

/* read file to kernel and decrypt */
- ret = kernel_read(file, 0, data, enclen);
+ ret = kernel_read(file, data, enclen, &pos);
if (ret >= 0 && ret != enclen) {
ret = -EIO;
goto err_fput;
--
2.11.0