[PATCH v2 1/2] fs/kernel_read_file: Allow to read files up-to ssize_t

Pasha Tatashin pasha.tatashin at soleen.com
Tue Jun 7 08:52:18 PDT 2022


On Sun, Jun 5, 2022 at 10:45 PM Baoquan He <bhe at redhat.com> wrote:
>
> On 05/27/22 at 02:55am, Pasha Tatashin wrote:
> > Currently, the maximum file size that is supported is 2G. This may be
> > too small in some cases. For example, kexec_file_load() system call
> > loads initramfs. In some netboot cases initramfs can be rather large.
> >
> > Allow to use up-to ssize_t bytes. The callers still can limit the
> > maximum file size via buf_size.
>
> If we really met initramfs bigger than 2G, it's reasonable to increase
> the limit. While wondering why we should take sszie_t, but not size_t.

ssize_t instead of size_t so we can return errors as negative values.

Pasha

>
> >
> > Signed-off-by: Pasha Tatashin <pasha.tatashin at soleen.com>
> > ---
> >  fs/kernel_read_file.c            | 38 ++++++++++++++++----------------
> >  include/linux/kernel_read_file.h | 32 +++++++++++++--------------
> >  include/linux/limits.h           |  1 +
> >  3 files changed, 36 insertions(+), 35 deletions(-)
> >
> > diff --git a/fs/kernel_read_file.c b/fs/kernel_read_file.c
> > index 1b07550485b9..5d826274570c 100644
> > --- a/fs/kernel_read_file.c
> > +++ b/fs/kernel_read_file.c
> > @@ -29,15 +29,15 @@
> >   * change between calls to kernel_read_file().
> >   *
> >   * Returns number of bytes read (no single read will be bigger
> > - * than INT_MAX), or negative on error.
> > + * than SSIZE_MAX), or negative on error.
> >   *
> >   */
> > -int kernel_read_file(struct file *file, loff_t offset, void **buf,
> > -                  size_t buf_size, size_t *file_size,
> > -                  enum kernel_read_file_id id)
> > +ssize_t kernel_read_file(struct file *file, loff_t offset, void **buf,
> > +                      size_t buf_size, size_t *file_size,
> > +                      enum kernel_read_file_id id)
> >  {
> >       loff_t i_size, pos;
> > -     size_t copied;
> > +     ssize_t copied;
> >       void *allocated = NULL;
> >       bool whole_file;
> >       int ret;
> > @@ -58,7 +58,7 @@ int kernel_read_file(struct file *file, loff_t offset, void **buf,
> >               goto out;
> >       }
> >       /* The file is too big for sane activities. */
> > -     if (i_size > INT_MAX) {
> > +     if (i_size > SSIZE_MAX) {
> >               ret = -EFBIG;
> >               goto out;
> >       }
> > @@ -124,12 +124,12 @@ int kernel_read_file(struct file *file, loff_t offset, void **buf,
> >  }
> >  EXPORT_SYMBOL_GPL(kernel_read_file);
> >
> > -int kernel_read_file_from_path(const char *path, loff_t offset, void **buf,
> > -                            size_t buf_size, size_t *file_size,
> > -                            enum kernel_read_file_id id)
> > +ssize_t kernel_read_file_from_path(const char *path, loff_t offset, void **buf,
> > +                                size_t buf_size, size_t *file_size,
> > +                                enum kernel_read_file_id id)
> >  {
> >       struct file *file;
> > -     int ret;
> > +     ssize_t ret;
> >
> >       if (!path || !*path)
> >               return -EINVAL;
> > @@ -144,14 +144,14 @@ int kernel_read_file_from_path(const char *path, loff_t offset, void **buf,
> >  }
> >  EXPORT_SYMBOL_GPL(kernel_read_file_from_path);
> >
> > -int kernel_read_file_from_path_initns(const char *path, loff_t offset,
> > -                                   void **buf, size_t buf_size,
> > -                                   size_t *file_size,
> > -                                   enum kernel_read_file_id id)
> > +ssize_t kernel_read_file_from_path_initns(const char *path, loff_t offset,
> > +                                       void **buf, size_t buf_size,
> > +                                       size_t *file_size,
> > +                                       enum kernel_read_file_id id)
> >  {
> >       struct file *file;
> >       struct path root;
> > -     int ret;
> > +     ssize_t ret;
> >
> >       if (!path || !*path)
> >               return -EINVAL;
> > @@ -171,12 +171,12 @@ int kernel_read_file_from_path_initns(const char *path, loff_t offset,
> >  }
> >  EXPORT_SYMBOL_GPL(kernel_read_file_from_path_initns);
> >
> > -int kernel_read_file_from_fd(int fd, loff_t offset, void **buf,
> > -                          size_t buf_size, size_t *file_size,
> > -                          enum kernel_read_file_id id)
> > +ssize_t kernel_read_file_from_fd(int fd, loff_t offset, void **buf,
> > +                              size_t buf_size, size_t *file_size,
> > +                              enum kernel_read_file_id id)
> >  {
> >       struct fd f = fdget(fd);
> > -     int ret = -EBADF;
> > +     ssize_t ret = -EBADF;
> >
> >       if (!f.file || !(f.file->f_mode & FMODE_READ))
> >               goto out;
> > diff --git a/include/linux/kernel_read_file.h b/include/linux/kernel_read_file.h
> > index 575ffa1031d3..90451e2e12bd 100644
> > --- a/include/linux/kernel_read_file.h
> > +++ b/include/linux/kernel_read_file.h
> > @@ -35,21 +35,21 @@ static inline const char *kernel_read_file_id_str(enum kernel_read_file_id id)
> >       return kernel_read_file_str[id];
> >  }
> >
> > -int kernel_read_file(struct file *file, loff_t offset,
> > -                  void **buf, size_t buf_size,
> > -                  size_t *file_size,
> > -                  enum kernel_read_file_id id);
> > -int kernel_read_file_from_path(const char *path, loff_t offset,
> > -                            void **buf, size_t buf_size,
> > -                            size_t *file_size,
> > -                            enum kernel_read_file_id id);
> > -int kernel_read_file_from_path_initns(const char *path, loff_t offset,
> > -                                   void **buf, size_t buf_size,
> > -                                   size_t *file_size,
> > -                                   enum kernel_read_file_id id);
> > -int kernel_read_file_from_fd(int fd, loff_t offset,
> > -                          void **buf, size_t buf_size,
> > -                          size_t *file_size,
> > -                          enum kernel_read_file_id id);
> > +ssize_t kernel_read_file(struct file *file, loff_t offset,
> > +                      void **buf, size_t buf_size,
> > +                      size_t *file_size,
> > +                      enum kernel_read_file_id id);
> > +ssize_t kernel_read_file_from_path(const char *path, loff_t offset,
> > +                                void **buf, size_t buf_size,
> > +                                size_t *file_size,
> > +                                enum kernel_read_file_id id);
> > +ssize_t kernel_read_file_from_path_initns(const char *path, loff_t offset,
> > +                                       void **buf, size_t buf_size,
> > +                                       size_t *file_size,
> > +                                       enum kernel_read_file_id id);
> > +ssize_t kernel_read_file_from_fd(int fd, loff_t offset,
> > +                              void **buf, size_t buf_size,
> > +                              size_t *file_size,
> > +                              enum kernel_read_file_id id);
> >
> >  #endif /* _LINUX_KERNEL_READ_FILE_H */
> > diff --git a/include/linux/limits.h b/include/linux/limits.h
> > index b568b9c30bbf..f6bcc9369010 100644
> > --- a/include/linux/limits.h
> > +++ b/include/linux/limits.h
> > @@ -7,6 +7,7 @@
> >  #include <vdso/limits.h>
> >
> >  #define SIZE_MAX     (~(size_t)0)
> > +#define SSIZE_MAX    ((ssize_t)(SIZE_MAX >> 1))
> >  #define PHYS_ADDR_MAX        (~(phys_addr_t)0)
> >
> >  #define U8_MAX               ((u8)~0U)
> > --
> > 2.36.1.124.g0e6072fb45-goog
> >
>



More information about the kexec mailing list