123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- From bd4fcbdbd9835716213debce07f08c81311ce9a6 Mon Sep 17 00:00:00 2001
- From: Lidong Chen <lidong.chen@oracle.com>
- Date: Wed, 22 Jan 2025 07:17:02 +0000
- Subject: [PATCH] fs/zfs: Use safe math macros to prevent overflows
- Replace direct arithmetic operations with macros from include/grub/safemath.h
- to prevent potential overflow issues when calculating the memory sizes.
- Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
- Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
- Upstream: 88e491a0f744c6b19b6d4caa300a576ba56db7c9
- Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
- ---
- grub-core/fs/zfs/zfs.c | 50 +++++++++++++++++++++++++++++++++++++-----
- 1 file changed, 44 insertions(+), 6 deletions(-)
- diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
- index a497b1869..2f303d655 100644
- --- a/grub-core/fs/zfs/zfs.c
- +++ b/grub-core/fs/zfs/zfs.c
- @@ -2387,6 +2387,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
- zap_dnode->endian) << DNODE_SHIFT);
- grub_err_t err;
- grub_zfs_endian_t endian;
- + grub_size_t sz;
-
- if (zap_verify (zap, zap_dnode->endian))
- return 0;
- @@ -2448,8 +2449,14 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
- if (le->le_type != ZAP_CHUNK_ENTRY)
- continue;
-
- - buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian)
- - * name_elem_length + 1);
- + if (grub_mul (grub_zfs_to_cpu16 (le->le_name_length, endian), name_elem_length, &sz) ||
- + grub_add (sz, 1, &sz))
- + {
- + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("buffer size overflow"));
- + grub_free (l);
- + return grub_errno;
- + }
- + buf = grub_malloc (sz);
- if (zap_leaf_array_get (l, endian, blksft,
- grub_zfs_to_cpu16 (le->le_name_chunk,
- endian),
- @@ -2872,6 +2879,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
- && ((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa)
- {
- char *sym_value;
- + grub_size_t sz;
- grub_size_t sym_sz;
- int free_symval = 0;
- char *oldpath = path, *oldpathbuf = path_buf;
- @@ -2923,7 +2931,18 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
- break;
- free_symval = 1;
- }
- - path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1);
- +
- + if (grub_add (sym_sz, grub_strlen (oldpath), &sz) ||
- + grub_add (sz, 1, &sz))
- + {
- + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("path buffer size overflow"));
- + grub_free (oldpathbuf);
- + if (free_symval)
- + grub_free (sym_value);
- + err = grub_errno;
- + break;
- + }
- + path = path_buf = grub_malloc (sz);
- if (!path_buf)
- {
- grub_free (oldpathbuf);
- @@ -2960,6 +2979,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
- {
- void *sahdrp;
- int hdrsize;
- + grub_size_t sz;
-
- if (dnode_path->dn.dn.dn_bonuslen != 0)
- {
- @@ -2993,7 +3013,15 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
- + SA_SIZE_OFFSET),
- dnode_path->dn.endian);
- char *oldpath = path, *oldpathbuf = path_buf;
- - path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1);
- + if (grub_add (sym_sz, grub_strlen (oldpath), &sz) ||
- + grub_add (sz, 1, &sz))
- + {
- + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("path buffer size overflow"));
- + grub_free (oldpathbuf);
- + err = grub_errno;
- + break;
- + }
- + path = path_buf = grub_malloc (sz);
- if (!path_buf)
- {
- grub_free (oldpathbuf);
- @@ -3568,6 +3596,7 @@ grub_zfs_nvlist_lookup_nvlist_array (const char *nvlist, const char *name,
- unsigned i;
- grub_size_t nelm;
- int elemsize = 0;
- + int sz;
-
- found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST_ARRAY, &nvpair,
- &size, &nelm);
- @@ -3602,7 +3631,12 @@ grub_zfs_nvlist_lookup_nvlist_array (const char *nvlist, const char *name,
- return 0;
- }
-
- - ret = grub_zalloc (elemsize + sizeof (grub_uint32_t));
- + if (grub_add (elemsize, sizeof (grub_uint32_t), &sz))
- + {
- + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("elemsize overflow"));
- + return 0;
- + }
- + ret = grub_zalloc (sz);
- if (!ret)
- return 0;
- grub_memcpy (ret, nvlist, sizeof (grub_uint32_t));
- @@ -4193,6 +4227,7 @@ iterate_zap_snap (const char *name, grub_uint64_t val,
- struct grub_dirhook_info info;
- char *name2;
- int ret;
- + grub_size_t sz;
-
- dnode_end_t mdn;
-
- @@ -4213,7 +4248,10 @@ iterate_zap_snap (const char *name, grub_uint64_t val,
- return 0;
- }
-
- - name2 = grub_malloc (grub_strlen (name) + 2);
- + if (grub_add (grub_strlen (name), 2, &sz))
- + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("name length overflow"));
- +
- + name2 = grub_malloc (sz);
- name2[0] = '@';
- grub_memcpy (name2 + 1, name, grub_strlen (name) + 1);
- ret = ctx->hook (name2, &info, ctx->hook_data);
- --
- 2.50.1
|