All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] Allow to kexec with initramfs larger than 2G
@ 2022-05-27  2:55 ` Pasha Tatashin
  0 siblings, 0 replies; 21+ 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] 21+ messages in thread

* [PATCH v2 0/2] Allow to kexec with initramfs larger than 2G
@ 2022-05-27  2:55 ` Pasha Tatashin
  0 siblings, 0 replies; 21+ messages in thread
From: Pasha Tatashin @ 2022-05-27  2:55 UTC (permalink / raw)
  To: kexec

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] 21+ messages in thread

* [PATCH v2 1/2] fs/kernel_read_file: Allow to read files up-to ssize_t
  2022-05-27  2:55 ` Pasha Tatashin
@ 2022-05-27  2:55   ` Pasha Tatashin
  -1 siblings, 0 replies; 21+ 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] 21+ messages in thread

* [PATCH v2 1/2] fs/kernel_read_file: Allow to read files up-to ssize_t
@ 2022-05-27  2:55   ` Pasha Tatashin
  0 siblings, 0 replies; 21+ messages in thread
From: Pasha Tatashin @ 2022-05-27  2:55 UTC (permalink / raw)
  To: kexec

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] 21+ messages in thread

* [PATCH v2 2/2] kexec_file: Increase maximum file size to 4G
  2022-05-27  2:55 ` Pasha Tatashin
@ 2022-05-27  2:55   ` Pasha Tatashin
  -1 siblings, 0 replies; 21+ 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] 21+ messages in thread

* [PATCH v2 2/2] kexec_file: Increase maximum file size to 4G
@ 2022-05-27  2:55   ` Pasha Tatashin
  0 siblings, 0 replies; 21+ messages in thread
From: Pasha Tatashin @ 2022-05-27  2:55 UTC (permalink / raw)
  To: kexec

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] 21+ 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   ` Pasha Tatashin
@ 2022-06-06  2:45     ` Baoquan He
  -1 siblings, 0 replies; 21+ 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] 21+ 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
  0 siblings, 0 replies; 21+ 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
> 


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 2/2] kexec_file: Increase maximum file size to 4G
  2022-05-27  2:55   ` Pasha Tatashin
@ 2022-06-06  2:56     ` Baoquan He
  -1 siblings, 0 replies; 21+ 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] 21+ messages in thread

* Re: [PATCH v2 2/2] kexec_file: Increase maximum file size to 4G
@ 2022-06-06  2:56     ` Baoquan He
  0 siblings, 0 replies; 21+ 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
> 


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 21+ 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
  -1 siblings, 0 replies; 21+ 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] 21+ 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
  0 siblings, 0 replies; 21+ 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
> >
>

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 21+ 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
  -1 siblings, 0 replies; 21+ 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] 21+ messages in thread

* Re: [PATCH v2 2/2] kexec_file: Increase maximum file size to 4G
@ 2022-06-07 16:02       ` Pasha Tatashin
  0 siblings, 0 replies; 21+ 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
> >
>

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 21+ 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
  -1 siblings, 0 replies; 21+ 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


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 2/2] kexec_file: Increase maximum file size to 4G
@ 2022-06-08  0:28         ` Baoquan He
  0 siblings, 0 replies; 21+ 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] 21+ 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
  -1 siblings, 0 replies; 21+ 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.


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 1/2] fs/kernel_read_file: Allow to read files up-to ssize_t
@ 2022-06-08  0:57         ` Baoquan He
  0 siblings, 0 replies; 21+ 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] 21+ 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   ` Pasha Tatashin
@ 2022-06-08  0:58     ` Baoquan He
  -1 siblings, 0 replies; 21+ 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
> 


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 1/2] fs/kernel_read_file: Allow to read files up-to ssize_t
@ 2022-06-08  0:58     ` Baoquan He
  0 siblings, 0 replies; 21+ 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] 21+ messages in thread

* Re: [PATCH v2 1/2] fs/kernel_read_file: Allow to read files up-to ssize_t
@ 2022-05-28  3:06 kernel test robot
  0 siblings, 0 replies; 21+ messages in thread
From: kernel test robot @ 2022-05-28  3:06 UTC (permalink / raw)
  To: kbuild

[-- Attachment #1: Type: text/plain, Size: 10339 bytes --]

CC: kbuild-all(a)lists.01.org
BCC: lkp(a)intel.com
In-Reply-To: <20220527025535.3953665-2-pasha.tatashin@soleen.com>
References: <20220527025535.3953665-2-pasha.tatashin@soleen.com>
TO: Pasha Tatashin <pasha.tatashin@soleen.com>
TO: pasha.tatashin(a)soleen.com
TO: sashal(a)kernel.org
TO: ebiederm(a)xmission.com
TO: rburanyi(a)google.com
TO: gthelen(a)google.com
TO: viro(a)zeniv.linux.org.uk
TO: kexec(a)lists.infradead.org
TO: linux-fsdevel(a)vger.kernel.org
TO: linux-kernel(a)vger.kernel.org

Hi Pasha,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.18 next-20220527]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/intel-lab-lkp/linux/commits/Pasha-Tatashin/Allow-to-kexec-with-initramfs-larger-than-2G/20220527-105815
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 7f50d4dfe816dd916a7cbf39039674825c2b388b
:::::: branch date: 24 hours ago
:::::: commit date: 24 hours ago
config: x86_64-randconfig-m001 (https://download.01.org/0day-ci/archive/20220528/202205281006.650Vdx6y-lkp(a)intel.com/config)
compiler: gcc-11 (Debian 11.3.0-1) 11.3.0

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>

smatch warnings:
fs/kernel_read_file.c:61 kernel_read_file() warn: impossible condition '(i_size > (((~0) >> 1))) => (s64min-s64max > s64max)'

vim +61 fs/kernel_read_file.c

5287b07f6d7cc3 Kees Cook      2020-10-02    7  
113eeb517780ad Kees Cook      2020-10-02    8  /**
113eeb517780ad Kees Cook      2020-10-02    9   * kernel_read_file() - read file contents into a kernel buffer
113eeb517780ad Kees Cook      2020-10-02   10   *
113eeb517780ad Kees Cook      2020-10-02   11   * @file	file to read from
0fa8e084648779 Kees Cook      2020-10-02   12   * @offset	where to start reading from (see below).
113eeb517780ad Kees Cook      2020-10-02   13   * @buf		pointer to a "void *" buffer for reading into (if
113eeb517780ad Kees Cook      2020-10-02   14   *		*@buf is NULL, a buffer will be allocated, and
113eeb517780ad Kees Cook      2020-10-02   15   *		@buf_size will be ignored)
113eeb517780ad Kees Cook      2020-10-02   16   * @buf_size	size of buf, if already allocated. If @buf not
113eeb517780ad Kees Cook      2020-10-02   17   *		allocated, this is the largest size to allocate.
885352881f11f1 Kees Cook      2020-10-02   18   * @file_size	if non-NULL, the full size of @file will be
885352881f11f1 Kees Cook      2020-10-02   19   *		written here.
113eeb517780ad Kees Cook      2020-10-02   20   * @id		the kernel_read_file_id identifying the type of
113eeb517780ad Kees Cook      2020-10-02   21   *		file contents being read (for LSMs to examine)
113eeb517780ad Kees Cook      2020-10-02   22   *
0fa8e084648779 Kees Cook      2020-10-02   23   * @offset must be 0 unless both @buf and @file_size are non-NULL
0fa8e084648779 Kees Cook      2020-10-02   24   * (i.e. the caller must be expecting to read partial file contents
0fa8e084648779 Kees Cook      2020-10-02   25   * via an already-allocated @buf, in at most @buf_size chunks, and
0fa8e084648779 Kees Cook      2020-10-02   26   * will be able to determine when the entire file was read by
0fa8e084648779 Kees Cook      2020-10-02   27   * checking @file_size). This isn't a recommended way to read a
0fa8e084648779 Kees Cook      2020-10-02   28   * file, though, since it is possible that the contents might
0fa8e084648779 Kees Cook      2020-10-02   29   * change between calls to kernel_read_file().
0fa8e084648779 Kees Cook      2020-10-02   30   *
113eeb517780ad Kees Cook      2020-10-02   31   * Returns number of bytes read (no single read will be bigger
71c48c48184de1 Pasha Tatashin 2022-05-27   32   * than SSIZE_MAX), or negative on error.
113eeb517780ad Kees Cook      2020-10-02   33   *
113eeb517780ad Kees Cook      2020-10-02   34   */
71c48c48184de1 Pasha Tatashin 2022-05-27   35  ssize_t kernel_read_file(struct file *file, loff_t offset, void **buf,
885352881f11f1 Kees Cook      2020-10-02   36  			 size_t buf_size, size_t *file_size,
885352881f11f1 Kees Cook      2020-10-02   37  			 enum kernel_read_file_id id)
5287b07f6d7cc3 Kees Cook      2020-10-02   38  {
5287b07f6d7cc3 Kees Cook      2020-10-02   39  	loff_t i_size, pos;
71c48c48184de1 Pasha Tatashin 2022-05-27   40  	ssize_t copied;
5287b07f6d7cc3 Kees Cook      2020-10-02   41  	void *allocated = NULL;
0fa8e084648779 Kees Cook      2020-10-02   42  	bool whole_file;
5287b07f6d7cc3 Kees Cook      2020-10-02   43  	int ret;
5287b07f6d7cc3 Kees Cook      2020-10-02   44  
0fa8e084648779 Kees Cook      2020-10-02   45  	if (offset != 0 && (!*buf || !file_size))
0fa8e084648779 Kees Cook      2020-10-02   46  		return -EINVAL;
0fa8e084648779 Kees Cook      2020-10-02   47  
113eeb517780ad Kees Cook      2020-10-02   48  	if (!S_ISREG(file_inode(file)->i_mode))
5287b07f6d7cc3 Kees Cook      2020-10-02   49  		return -EINVAL;
5287b07f6d7cc3 Kees Cook      2020-10-02   50  
5287b07f6d7cc3 Kees Cook      2020-10-02   51  	ret = deny_write_access(file);
5287b07f6d7cc3 Kees Cook      2020-10-02   52  	if (ret)
5287b07f6d7cc3 Kees Cook      2020-10-02   53  		return ret;
5287b07f6d7cc3 Kees Cook      2020-10-02   54  
5287b07f6d7cc3 Kees Cook      2020-10-02   55  	i_size = i_size_read(file_inode(file));
5287b07f6d7cc3 Kees Cook      2020-10-02   56  	if (i_size <= 0) {
5287b07f6d7cc3 Kees Cook      2020-10-02   57  		ret = -EINVAL;
5287b07f6d7cc3 Kees Cook      2020-10-02   58  		goto out;
5287b07f6d7cc3 Kees Cook      2020-10-02   59  	}
0fa8e084648779 Kees Cook      2020-10-02   60  	/* The file is too big for sane activities. */
71c48c48184de1 Pasha Tatashin 2022-05-27  @61  	if (i_size > SSIZE_MAX) {
5287b07f6d7cc3 Kees Cook      2020-10-02   62  		ret = -EFBIG;
5287b07f6d7cc3 Kees Cook      2020-10-02   63  		goto out;
5287b07f6d7cc3 Kees Cook      2020-10-02   64  	}
0fa8e084648779 Kees Cook      2020-10-02   65  	/* The entire file cannot be read in one buffer. */
0fa8e084648779 Kees Cook      2020-10-02   66  	if (!file_size && offset == 0 && i_size > buf_size) {
0fa8e084648779 Kees Cook      2020-10-02   67  		ret = -EFBIG;
0fa8e084648779 Kees Cook      2020-10-02   68  		goto out;
0fa8e084648779 Kees Cook      2020-10-02   69  	}
0fa8e084648779 Kees Cook      2020-10-02   70  
0fa8e084648779 Kees Cook      2020-10-02   71  	whole_file = (offset == 0 && i_size <= buf_size);
0fa8e084648779 Kees Cook      2020-10-02   72  	ret = security_kernel_read_file(file, id, whole_file);
0fa8e084648779 Kees Cook      2020-10-02   73  	if (ret)
0fa8e084648779 Kees Cook      2020-10-02   74  		goto out;
0fa8e084648779 Kees Cook      2020-10-02   75  
885352881f11f1 Kees Cook      2020-10-02   76  	if (file_size)
885352881f11f1 Kees Cook      2020-10-02   77  		*file_size = i_size;
5287b07f6d7cc3 Kees Cook      2020-10-02   78  
5287b07f6d7cc3 Kees Cook      2020-10-02   79  	if (!*buf)
5287b07f6d7cc3 Kees Cook      2020-10-02   80  		*buf = allocated = vmalloc(i_size);
5287b07f6d7cc3 Kees Cook      2020-10-02   81  	if (!*buf) {
5287b07f6d7cc3 Kees Cook      2020-10-02   82  		ret = -ENOMEM;
5287b07f6d7cc3 Kees Cook      2020-10-02   83  		goto out;
5287b07f6d7cc3 Kees Cook      2020-10-02   84  	}
5287b07f6d7cc3 Kees Cook      2020-10-02   85  
0fa8e084648779 Kees Cook      2020-10-02   86  	pos = offset;
0fa8e084648779 Kees Cook      2020-10-02   87  	copied = 0;
0fa8e084648779 Kees Cook      2020-10-02   88  	while (copied < buf_size) {
0fa8e084648779 Kees Cook      2020-10-02   89  		ssize_t bytes;
0fa8e084648779 Kees Cook      2020-10-02   90  		size_t wanted = min_t(size_t, buf_size - copied,
0fa8e084648779 Kees Cook      2020-10-02   91  					      i_size - pos);
0fa8e084648779 Kees Cook      2020-10-02   92  
0fa8e084648779 Kees Cook      2020-10-02   93  		bytes = kernel_read(file, *buf + copied, wanted, &pos);
5287b07f6d7cc3 Kees Cook      2020-10-02   94  		if (bytes < 0) {
5287b07f6d7cc3 Kees Cook      2020-10-02   95  			ret = bytes;
5287b07f6d7cc3 Kees Cook      2020-10-02   96  			goto out_free;
5287b07f6d7cc3 Kees Cook      2020-10-02   97  		}
5287b07f6d7cc3 Kees Cook      2020-10-02   98  
5287b07f6d7cc3 Kees Cook      2020-10-02   99  		if (bytes == 0)
5287b07f6d7cc3 Kees Cook      2020-10-02  100  			break;
0fa8e084648779 Kees Cook      2020-10-02  101  		copied += bytes;
5287b07f6d7cc3 Kees Cook      2020-10-02  102  	}
5287b07f6d7cc3 Kees Cook      2020-10-02  103  
0fa8e084648779 Kees Cook      2020-10-02  104  	if (whole_file) {
5287b07f6d7cc3 Kees Cook      2020-10-02  105  		if (pos != i_size) {
5287b07f6d7cc3 Kees Cook      2020-10-02  106  			ret = -EIO;
5287b07f6d7cc3 Kees Cook      2020-10-02  107  			goto out_free;
5287b07f6d7cc3 Kees Cook      2020-10-02  108  		}
5287b07f6d7cc3 Kees Cook      2020-10-02  109  
5287b07f6d7cc3 Kees Cook      2020-10-02  110  		ret = security_kernel_post_read_file(file, *buf, i_size, id);
0fa8e084648779 Kees Cook      2020-10-02  111  	}
5287b07f6d7cc3 Kees Cook      2020-10-02  112  
5287b07f6d7cc3 Kees Cook      2020-10-02  113  out_free:
5287b07f6d7cc3 Kees Cook      2020-10-02  114  	if (ret < 0) {
5287b07f6d7cc3 Kees Cook      2020-10-02  115  		if (allocated) {
5287b07f6d7cc3 Kees Cook      2020-10-02  116  			vfree(*buf);
5287b07f6d7cc3 Kees Cook      2020-10-02  117  			*buf = NULL;
5287b07f6d7cc3 Kees Cook      2020-10-02  118  		}
5287b07f6d7cc3 Kees Cook      2020-10-02  119  	}
5287b07f6d7cc3 Kees Cook      2020-10-02  120  
5287b07f6d7cc3 Kees Cook      2020-10-02  121  out:
5287b07f6d7cc3 Kees Cook      2020-10-02  122  	allow_write_access(file);
0fa8e084648779 Kees Cook      2020-10-02  123  	return ret == 0 ? copied : ret;
5287b07f6d7cc3 Kees Cook      2020-10-02  124  }
5287b07f6d7cc3 Kees Cook      2020-10-02  125  EXPORT_SYMBOL_GPL(kernel_read_file);
5287b07f6d7cc3 Kees Cook      2020-10-02  126  

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2022-06-08  4:48 UTC | newest]

Thread overview: 21+ 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 ` 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:45   ` Baoquan He
2022-06-06  2:45     ` Baoquan He
2022-06-07 15:52     ` Pasha Tatashin
2022-06-07 15:52       ` Pasha Tatashin
2022-06-08  0:57       ` Baoquan He
2022-06-08  0:57         ` Baoquan He
2022-06-08  0:58   ` 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-05-27  2:55   ` Pasha Tatashin
2022-06-06  2:56   ` Baoquan He
2022-06-06  2:56     ` Baoquan He
2022-06-07 16:02     ` Pasha Tatashin
2022-06-07 16:02       ` Pasha Tatashin
2022-06-08  0:28       ` Baoquan He
2022-06-08  0:28         ` Baoquan He
2022-05-28  3:06 [PATCH v2 1/2] fs/kernel_read_file: Allow to read files up-to ssize_t kernel test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.