* [PATCH v2 0/2] Allow to kexec with initramfs larger than 2G @ 2022-05-27 2:55 Pasha Tatashin 2022-05-27 2:55 ` [PATCH v2 1/2] fs/kernel_read_file: Allow to read files up-to ssize_t Pasha Tatashin 2022-05-27 2:55 ` [PATCH v2 2/2] kexec_file: Increase maximum file size to 4G Pasha Tatashin 0 siblings, 2 replies; 10+ messages in thread From: Pasha Tatashin @ 2022-05-27 2:55 UTC (permalink / raw) To: pasha.tatashin, sashal, ebiederm, rburanyi, gthelen, viro, kexec, linux-fsdevel, linux-kernel Currently, the largest initramfs that is supported by kexec_file_load() syscall is 2G. This is because kernel_read_file() returns int, and is limited to INT_MAX or 2G. On the other hand, there are kexec based boot loaders (i.e. u-root), that may need to boot netboot images that might be larger than 2G. The first patch changes the return type from int to ssize_t in kernel_read_file* functions. The second patch increases the maximum initramfs file size to 4G. Tested: verified that can kexec_file_load() works with 4G initramfs on x86_64. Pasha Tatashin (2): fs/kernel_read_file: Allow to read files up-to ssize_t kexec_file: Increase maximum file size to 4G fs/kernel_read_file.c | 38 ++++++++++++++++---------------- include/linux/kernel_read_file.h | 32 +++++++++++++-------------- include/linux/limits.h | 1 + kernel/kexec_file.c | 10 ++++++--- 4 files changed, 43 insertions(+), 38 deletions(-) -- 2.36.1.124.g0e6072fb45-goog ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 1/2] fs/kernel_read_file: Allow to read files up-to ssize_t 2022-05-27 2:55 [PATCH v2 0/2] Allow to kexec with initramfs larger than 2G Pasha Tatashin @ 2022-05-27 2:55 ` Pasha Tatashin 2022-06-06 2:45 ` Baoquan He 2022-06-08 0:58 ` Baoquan He 2022-05-27 2:55 ` [PATCH v2 2/2] kexec_file: Increase maximum file size to 4G Pasha Tatashin 1 sibling, 2 replies; 10+ messages in thread From: Pasha Tatashin @ 2022-05-27 2:55 UTC (permalink / raw) To: pasha.tatashin, sashal, ebiederm, rburanyi, gthelen, viro, kexec, linux-fsdevel, linux-kernel 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. Signed-off-by: Pasha Tatashin <pasha.tatashin@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 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] fs/kernel_read_file: Allow to read files up-to ssize_t 2022-05-27 2:55 ` [PATCH v2 1/2] fs/kernel_read_file: Allow to read files up-to ssize_t Pasha Tatashin @ 2022-06-06 2:45 ` Baoquan He 2022-06-07 15:52 ` Pasha Tatashin 2022-06-08 0:58 ` Baoquan He 1 sibling, 1 reply; 10+ messages in thread From: Baoquan He @ 2022-06-06 2:45 UTC (permalink / raw) To: Pasha Tatashin Cc: sashal, ebiederm, rburanyi, gthelen, viro, kexec, linux-fsdevel, linux-kernel 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. > > Signed-off-by: Pasha Tatashin <pasha.tatashin@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 > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] fs/kernel_read_file: Allow to read files up-to ssize_t 2022-06-06 2:45 ` Baoquan He @ 2022-06-07 15:52 ` Pasha Tatashin 2022-06-08 0:57 ` Baoquan He 0 siblings, 1 reply; 10+ messages in thread From: Pasha Tatashin @ 2022-06-07 15:52 UTC (permalink / raw) To: Baoquan He Cc: Sasha Levin, Eric W. Biederman, rburanyi, Greg Thelen, viro, kexec mailing list, linux-fsdevel, LKML On Sun, Jun 5, 2022 at 10:45 PM Baoquan He <bhe@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@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 > > > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] fs/kernel_read_file: Allow to read files up-to ssize_t 2022-06-07 15:52 ` Pasha Tatashin @ 2022-06-08 0:57 ` Baoquan He 0 siblings, 0 replies; 10+ messages in thread From: Baoquan He @ 2022-06-08 0:57 UTC (permalink / raw) To: Pasha Tatashin Cc: Sasha Levin, Eric W. Biederman, rburanyi, Greg Thelen, viro, kexec mailing list, linux-fsdevel, LKML On 06/07/22 at 11:52am, Pasha Tatashin wrote: > On Sun, Jun 5, 2022 at 10:45 PM Baoquan He <bhe@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. Makes sense. Thanks. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] fs/kernel_read_file: Allow to read files up-to ssize_t 2022-05-27 2:55 ` [PATCH v2 1/2] fs/kernel_read_file: Allow to read files up-to ssize_t Pasha Tatashin 2022-06-06 2:45 ` Baoquan He @ 2022-06-08 0:58 ` Baoquan He 1 sibling, 0 replies; 10+ messages in thread From: Baoquan He @ 2022-06-08 0:58 UTC (permalink / raw) To: Pasha Tatashin Cc: sashal, ebiederm, rburanyi, akpm, gthelen, viro, kexec, linux-fsdevel, linux-kernel 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. LGTM, Acked-by: Baoquan He <bhe@redhat.com> > > Signed-off-by: Pasha Tatashin <pasha.tatashin@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 > ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 2/2] kexec_file: Increase maximum file size to 4G 2022-05-27 2:55 [PATCH v2 0/2] Allow to kexec with initramfs larger than 2G Pasha Tatashin 2022-05-27 2:55 ` [PATCH v2 1/2] fs/kernel_read_file: Allow to read files up-to ssize_t Pasha Tatashin @ 2022-05-27 2:55 ` Pasha Tatashin 2022-06-06 2:56 ` Baoquan He 1 sibling, 1 reply; 10+ messages in thread From: Pasha Tatashin @ 2022-05-27 2:55 UTC (permalink / raw) To: pasha.tatashin, sashal, ebiederm, rburanyi, gthelen, viro, kexec, linux-fsdevel, linux-kernel In some case initrd can be large. For example, it could be a netboot image loaded by u-root, that is kexec'ing into it. The maximum size of initrd is arbitrary set to 2G. Also, the limit is not very obvious because it is hidden behind a generic INT_MAX macro. Theoretically, we could make it LONG_MAX, but it is safer to keep it sane, and just increase it to 4G. Increase the size to 4G, and make it obvious by having a new macro that specifies the maximum file size supported by kexec_file_load() syscall: KEXEC_FILE_SIZE_MAX. Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com> --- kernel/kexec_file.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index 8347fc158d2b..f00cf70d82b9 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -31,6 +31,9 @@ static int kexec_calculate_store_digests(struct kimage *image); +/* Maximum size in bytes for kernel/initrd files. */ +#define KEXEC_FILE_SIZE_MAX min_t(s64, 4LL << 30, SSIZE_MAX) + /* * Currently this is the only default function that is exported as some * architectures need it to do additional handlings. @@ -223,11 +226,12 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, const char __user *cmdline_ptr, unsigned long cmdline_len, unsigned flags) { - int ret; + ssize_t ret; void *ldata; ret = kernel_read_file_from_fd(kernel_fd, 0, &image->kernel_buf, - INT_MAX, NULL, READING_KEXEC_IMAGE); + KEXEC_FILE_SIZE_MAX, NULL, + READING_KEXEC_IMAGE); if (ret < 0) return ret; image->kernel_buf_len = ret; @@ -247,7 +251,7 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, /* It is possible that there no initramfs is being loaded */ if (!(flags & KEXEC_FILE_NO_INITRAMFS)) { ret = kernel_read_file_from_fd(initrd_fd, 0, &image->initrd_buf, - INT_MAX, NULL, + KEXEC_FILE_SIZE_MAX, NULL, READING_KEXEC_INITRAMFS); if (ret < 0) goto out; -- 2.36.1.124.g0e6072fb45-goog ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v2 2/2] kexec_file: Increase maximum file size to 4G 2022-05-27 2:55 ` [PATCH v2 2/2] kexec_file: Increase maximum file size to 4G Pasha Tatashin @ 2022-06-06 2:56 ` Baoquan He 2022-06-07 16:02 ` Pasha Tatashin 0 siblings, 1 reply; 10+ messages in thread From: Baoquan He @ 2022-06-06 2:56 UTC (permalink / raw) To: Pasha Tatashin Cc: sashal, ebiederm, rburanyi, gthelen, viro, kexec, linux-fsdevel, linux-kernel On 05/27/22 at 02:55am, Pasha Tatashin wrote: > In some case initrd can be large. For example, it could be a netboot > image loaded by u-root, that is kexec'ing into it. > > The maximum size of initrd is arbitrary set to 2G. Also, the limit is > not very obvious because it is hidden behind a generic INT_MAX macro. > > Theoretically, we could make it LONG_MAX, but it is safer to keep it > sane, and just increase it to 4G. Do we need to care about 32bit system where initramfs could be larger than 2G? On 32bit system, SSIZE_MAX is still 2G, right? Another concern is if 2G is enough. If we can foresee it might need be enlarged again in a near future, LONG_MAX certainly is not a good value, but a little bigger multiple of 2G can be better? > > Increase the size to 4G, and make it obvious by having a new macro > that specifies the maximum file size supported by kexec_file_load() > syscall: KEXEC_FILE_SIZE_MAX. > > Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com> > --- > kernel/kexec_file.c | 10 +++++++--- > 1 file changed, 7 insertions(+), 3 deletions(-) > > diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c > index 8347fc158d2b..f00cf70d82b9 100644 > --- a/kernel/kexec_file.c > +++ b/kernel/kexec_file.c > @@ -31,6 +31,9 @@ > > static int kexec_calculate_store_digests(struct kimage *image); > > +/* Maximum size in bytes for kernel/initrd files. */ > +#define KEXEC_FILE_SIZE_MAX min_t(s64, 4LL << 30, SSIZE_MAX) > + > /* > * Currently this is the only default function that is exported as some > * architectures need it to do additional handlings. > @@ -223,11 +226,12 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, > const char __user *cmdline_ptr, > unsigned long cmdline_len, unsigned flags) > { > - int ret; > + ssize_t ret; > void *ldata; > > ret = kernel_read_file_from_fd(kernel_fd, 0, &image->kernel_buf, > - INT_MAX, NULL, READING_KEXEC_IMAGE); > + KEXEC_FILE_SIZE_MAX, NULL, > + READING_KEXEC_IMAGE); > if (ret < 0) > return ret; > image->kernel_buf_len = ret; > @@ -247,7 +251,7 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, > /* It is possible that there no initramfs is being loaded */ > if (!(flags & KEXEC_FILE_NO_INITRAMFS)) { > ret = kernel_read_file_from_fd(initrd_fd, 0, &image->initrd_buf, > - INT_MAX, NULL, > + KEXEC_FILE_SIZE_MAX, NULL, > READING_KEXEC_INITRAMFS); > if (ret < 0) > goto out; > -- > 2.36.1.124.g0e6072fb45-goog > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 2/2] kexec_file: Increase maximum file size to 4G 2022-06-06 2:56 ` Baoquan He @ 2022-06-07 16:02 ` Pasha Tatashin 2022-06-08 0:28 ` Baoquan He 0 siblings, 1 reply; 10+ messages in thread From: Pasha Tatashin @ 2022-06-07 16:02 UTC (permalink / raw) To: Baoquan He Cc: Sasha Levin, Eric W. Biederman, rburanyi, Greg Thelen, viro, kexec mailing list, linux-fsdevel, LKML On Sun, Jun 5, 2022 at 10:56 PM Baoquan He <bhe@redhat.com> wrote: > > On 05/27/22 at 02:55am, Pasha Tatashin wrote: > > In some case initrd can be large. For example, it could be a netboot > > image loaded by u-root, that is kexec'ing into it. > > > > The maximum size of initrd is arbitrary set to 2G. Also, the limit is > > not very obvious because it is hidden behind a generic INT_MAX macro. > > > > Theoretically, we could make it LONG_MAX, but it is safer to keep it > > sane, and just increase it to 4G. > > Do we need to care about 32bit system where initramfs could be larger > than 2G? On 32bit system, SSIZE_MAX is still 2G, right? Yes, on 32-bit SSIZE_MAX is still 2G, so we are safe to keep 32-bit systems run exactly as today. #define KEXEC_FILE_SIZE_MAX min_t(s64, 4LL << 30, SSIZE_MAX) Is meant to protect against running over the 2G limit on 32-bit systems. > > Another concern is if 2G is enough. If we can foresee it might need be > enlarged again in a near future, LONG_MAX certainly is not a good > value, but a little bigger multiple of 2G can be better? This little series enables increasing the max value above 2G, but still keeps it within a sane size i.e. 4G, If 4G seems too small, I can change it to 8G or 16G instead of 4G. Thanks, Pasha > > > > > Increase the size to 4G, and make it obvious by having a new macro > > that specifies the maximum file size supported by kexec_file_load() > > syscall: KEXEC_FILE_SIZE_MAX. > > > > Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com> > > --- > > kernel/kexec_file.c | 10 +++++++--- > > 1 file changed, 7 insertions(+), 3 deletions(-) > > > > diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c > > index 8347fc158d2b..f00cf70d82b9 100644 > > --- a/kernel/kexec_file.c > > +++ b/kernel/kexec_file.c > > @@ -31,6 +31,9 @@ > > > > static int kexec_calculate_store_digests(struct kimage *image); > > > > +/* Maximum size in bytes for kernel/initrd files. */ > > +#define KEXEC_FILE_SIZE_MAX min_t(s64, 4LL << 30, SSIZE_MAX) > > + > > /* > > * Currently this is the only default function that is exported as some > > * architectures need it to do additional handlings. > > @@ -223,11 +226,12 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, > > const char __user *cmdline_ptr, > > unsigned long cmdline_len, unsigned flags) > > { > > - int ret; > > + ssize_t ret; > > void *ldata; > > > > ret = kernel_read_file_from_fd(kernel_fd, 0, &image->kernel_buf, > > - INT_MAX, NULL, READING_KEXEC_IMAGE); > > + KEXEC_FILE_SIZE_MAX, NULL, > > + READING_KEXEC_IMAGE); > > if (ret < 0) > > return ret; > > image->kernel_buf_len = ret; > > @@ -247,7 +251,7 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, > > /* It is possible that there no initramfs is being loaded */ > > if (!(flags & KEXEC_FILE_NO_INITRAMFS)) { > > ret = kernel_read_file_from_fd(initrd_fd, 0, &image->initrd_buf, > > - INT_MAX, NULL, > > + KEXEC_FILE_SIZE_MAX, NULL, > > READING_KEXEC_INITRAMFS); > > if (ret < 0) > > goto out; > > -- > > 2.36.1.124.g0e6072fb45-goog > > > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 2/2] kexec_file: Increase maximum file size to 4G 2022-06-07 16:02 ` Pasha Tatashin @ 2022-06-08 0:28 ` Baoquan He 0 siblings, 0 replies; 10+ messages in thread From: Baoquan He @ 2022-06-08 0:28 UTC (permalink / raw) To: Pasha Tatashin Cc: Sasha Levin, Eric W. Biederman, rburanyi, Greg Thelen, viro, kexec mailing list, linux-fsdevel, LKML On 06/07/22 at 12:02pm, Pasha Tatashin wrote: > On Sun, Jun 5, 2022 at 10:56 PM Baoquan He <bhe@redhat.com> wrote: > > > > On 05/27/22 at 02:55am, Pasha Tatashin wrote: > > > In some case initrd can be large. For example, it could be a netboot > > > image loaded by u-root, that is kexec'ing into it. > > > > > > The maximum size of initrd is arbitrary set to 2G. Also, the limit is > > > not very obvious because it is hidden behind a generic INT_MAX macro. > > > > > > Theoretically, we could make it LONG_MAX, but it is safer to keep it > > > sane, and just increase it to 4G. > > > > Do we need to care about 32bit system where initramfs could be larger > > than 2G? On 32bit system, SSIZE_MAX is still 2G, right? > > Yes, on 32-bit SSIZE_MAX is still 2G, so we are safe to keep 32-bit > systems run exactly as today. > > #define KEXEC_FILE_SIZE_MAX min_t(s64, 4LL << 30, SSIZE_MAX) > Is meant to protect against running over the 2G limit on 32-bit systems. OK. In fact I was wrong. I386 doesn't have kexec_file loading support. > > > > > Another concern is if 2G is enough. If we can foresee it might need be ~~ 4G, typo > > enlarged again in a near future, LONG_MAX certainly is not a good > > value, but a little bigger multiple of 2G can be better? > > This little series enables increasing the max value above 2G, but > still keeps it within a sane size i.e. 4G, If 4G seems too small, I > can change it to 8G or 16G instead of 4G. Just raising to try to discuss if 4G is enough. I have no knowledge about how much is enough, and we don't need to guess, if you think 4G is enough according to information you get, that's OK. We can wait a while to see if other people have words about the vlaue. If no, then 4G is a good one. Thanks Baoquan ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2022-06-08 4:48 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-05-27 2:55 [PATCH v2 0/2] Allow to kexec with initramfs larger than 2G Pasha Tatashin 2022-05-27 2:55 ` [PATCH v2 1/2] fs/kernel_read_file: Allow to read files up-to ssize_t Pasha Tatashin 2022-06-06 2:45 ` Baoquan He 2022-06-07 15:52 ` Pasha Tatashin 2022-06-08 0:57 ` Baoquan He 2022-06-08 0:58 ` Baoquan He 2022-05-27 2:55 ` [PATCH v2 2/2] kexec_file: Increase maximum file size to 4G Pasha Tatashin 2022-06-06 2:56 ` Baoquan He 2022-06-07 16:02 ` Pasha Tatashin 2022-06-08 0:28 ` Baoquan He
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox