fs: 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>
This commit is contained in:
Lidong Chen authored and Daniel Kiper committed 2025-02-13 15:45:57 +01:00
1 parent fbaddcca54
commit 6608163b08
8 files changed
+104 -19

No files matched your search

+8 -1
View File
@@ -21,6 +21,7 @@
#include <grub/fs.h> #include <grub/fs.h>
#include <grub/disk.h> #include <grub/disk.h>
#include <grub/dl.h> #include <grub/dl.h>
#include <grub/safemath.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@@ -68,6 +69,7 @@ handle_symlink (struct grub_archelp_data *data,
char *rest; char *rest;
char *linktarget; char *linktarget;
grub_size_t linktarget_len; grub_size_t linktarget_len;
grub_size_t sz;
*restart = 0; *restart = 0;
@@ -98,7 +100,12 @@ handle_symlink (struct grub_archelp_data *data,
if (linktarget[0] == '\0') if (linktarget[0] == '\0')
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
linktarget_len = grub_strlen (linktarget); linktarget_len = grub_strlen (linktarget);
target = grub_malloc (linktarget_len + grub_strlen (*name) + 2);
if (grub_add (linktarget_len, grub_strlen (*name), &sz) ||
grub_add (sz, 2, &sz))
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("link target length overflow"));
target = grub_malloc (sz);
if (!target) if (!target)
return grub_errno; return grub_errno;
+28 -6
View File
@@ -1801,6 +1801,7 @@ find_path (struct grub_btrfs_data *data,
char *path_alloc = NULL; char *path_alloc = NULL;
char *origpath = NULL; char *origpath = NULL;
unsigned symlinks_max = 32; unsigned symlinks_max = 32;
grub_size_t sz;
err = get_root (data, key, tree, type); err = get_root (data, key, tree, type);
if (err) if (err)
@@ -1891,9 +1892,15 @@ find_path (struct grub_btrfs_data *data,
struct grub_btrfs_dir_item *cdirel; struct grub_btrfs_dir_item *cdirel;
if (elemsize > allocated) if (elemsize > allocated)
{ {
allocated = 2 * elemsize; if (grub_mul (2, elemsize, &allocated) ||
grub_add (allocated, 1, &sz))
{
grub_free (path_alloc);
grub_free (origpath);
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("directory item size overflow"));
}
grub_free (direl); grub_free (direl);
direl = grub_malloc (allocated + 1); direl = grub_malloc (sz);
if (!direl) if (!direl)
{ {
grub_free (path_alloc); grub_free (path_alloc);
@@ -1955,8 +1962,16 @@ find_path (struct grub_btrfs_data *data,
grub_free (origpath); grub_free (origpath);
return err; return err;
} }
tmp = grub_malloc (grub_le_to_cpu64 (inode.size)
+ grub_strlen (path) + 1); if (grub_add (grub_le_to_cpu64 (inode.size), grub_strlen (path), &sz) ||
grub_add (sz, 1, &sz))
{
grub_free (direl);
grub_free (path_alloc);
grub_free (origpath);
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("buffer size overflow"));
}
tmp = grub_malloc (sz);
if (!tmp) if (!tmp)
{ {
grub_free (direl); grub_free (direl);
@@ -2078,6 +2093,7 @@ grub_btrfs_dir (grub_device_t device, const char *path,
grub_uint64_t tree; grub_uint64_t tree;
grub_uint8_t type; grub_uint8_t type;
grub_size_t est_size = 0; grub_size_t est_size = 0;
grub_size_t sz;
if (!data) if (!data)
return grub_errno; return grub_errno;
@@ -2119,9 +2135,15 @@ grub_btrfs_dir (grub_device_t device, const char *path,
} }
if (elemsize > allocated) if (elemsize > allocated)
{ {
allocated = 2 * elemsize; if (grub_mul (2, elemsize, &allocated) ||
grub_add (allocated, 1, &sz))
{
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("directory element size overflow"));
r = -grub_errno;
break;
}
grub_free (direl); grub_free (direl);
direl = grub_malloc (allocated + 1); direl = grub_malloc (sz);
if (!direl) if (!direl)
{ {
r = -grub_errno; r = -grub_errno;
+14 -2
View File
@@ -24,6 +24,7 @@
#include <grub/dl.h> #include <grub/dl.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/archelp.h> #include <grub/archelp.h>
#include <grub/safemath.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@@ -48,6 +49,7 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
struct head hd; struct head hd;
grub_size_t namesize; grub_size_t namesize;
grub_uint32_t modeval; grub_uint32_t modeval;
grub_size_t sz;
data->hofs = data->next_hofs; data->hofs = data->next_hofs;
@@ -76,7 +78,10 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
*mode = modeval; *mode = modeval;
*name = grub_malloc (namesize + 1); if (grub_add (namesize, 1, &sz))
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("file name size overflow"));
*name = grub_malloc (sz);
if (*name == NULL) if (*name == NULL)
return grub_errno; return grub_errno;
@@ -110,10 +115,17 @@ grub_cpio_get_link_target (struct grub_archelp_data *data)
{ {
char *ret; char *ret;
grub_err_t err; grub_err_t err;
grub_size_t sz;
if (data->size == 0) if (data->size == 0)
return grub_strdup (""); return grub_strdup ("");
ret = grub_malloc (data->size + 1);
if (grub_add (data->size, 1, &sz))
{
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("target data size overflow"));
return NULL;
}
ret = grub_malloc (sz);
if (!ret) if (!ret)
return NULL; return NULL;
+7 -2
View File
@@ -681,7 +681,7 @@ static char *
erofs_read_symlink (grub_fshelp_node_t node) erofs_read_symlink (grub_fshelp_node_t node)
{ {
char *symlink; char *symlink;
grub_size_t sz; grub_size_t sz, lsz;
grub_err_t err; grub_err_t err;
if (node->inode_loaded == false) if (node->inode_loaded == false)
@@ -699,7 +699,12 @@ erofs_read_symlink (grub_fshelp_node_t node)
return NULL; return NULL;
} }
symlink = grub_malloc (sz + 1); if (grub_add (sz, 1, &lsz))
{
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("symlink size overflow"));
return NULL;
}
symlink = grub_malloc (lsz);
if (symlink == NULL) if (symlink == NULL)
return NULL; return NULL;
+15 -2
View File
@@ -28,6 +28,7 @@
#include <grub/types.h> #include <grub/types.h>
#include <grub/charset.h> #include <grub/charset.h>
#include <grub/fshelp.h> #include <grub/fshelp.h>
#include <grub/safemath.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@@ -958,6 +959,7 @@ grub_f2fs_read_symlink (grub_fshelp_node_t node)
char *symlink; char *symlink;
struct grub_fshelp_node *diro = node; struct grub_fshelp_node *diro = node;
grub_uint64_t filesize; grub_uint64_t filesize;
grub_size_t sz;
if (!diro->inode_read) if (!diro->inode_read)
{ {
@@ -968,7 +970,12 @@ grub_f2fs_read_symlink (grub_fshelp_node_t node)
filesize = grub_f2fs_file_size(&diro->inode.i); filesize = grub_f2fs_file_size(&diro->inode.i);
symlink = grub_malloc (filesize + 1); if (grub_add (filesize, 1, &sz))
{
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("symlink size overflow"));
return 0;
}
symlink = grub_malloc (sz);
if (!symlink) if (!symlink)
return 0; return 0;
@@ -997,6 +1004,7 @@ grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx *ctx)
enum FILE_TYPE ftype; enum FILE_TYPE ftype;
int name_len; int name_len;
int ret; int ret;
int sz;
if (grub_f2fs_test_bit_le (i, ctx->bitmap) == 0) if (grub_f2fs_test_bit_le (i, ctx->bitmap) == 0)
{ {
@@ -1010,7 +1018,12 @@ grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx *ctx)
if (name_len >= F2FS_NAME_LEN) if (name_len >= F2FS_NAME_LEN)
return 0; return 0;
filename = grub_malloc (name_len + 1); if (grub_add (name_len, 1, &sz))
{
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("directory entry name length overflow"));
return 0;
}
filename = grub_malloc (sz);
if (!filename) if (!filename)
return 0; return 0;
+8 -1
View File
@@ -22,6 +22,7 @@
#include <grub/disk.h> #include <grub/disk.h>
#include <grub/dl.h> #include <grub/dl.h>
#include <grub/ntfs.h> #include <grub/ntfs.h>
#include <grub/safemath.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@@ -310,6 +311,7 @@ ntfscomp (grub_uint8_t *dest, grub_disk_addr_t ofs,
{ {
grub_err_t ret; grub_err_t ret;
grub_disk_addr_t vcn; grub_disk_addr_t vcn;
int log_sz;
if (ctx->attr->sbuf) if (ctx->attr->sbuf)
{ {
@@ -349,7 +351,12 @@ ntfscomp (grub_uint8_t *dest, grub_disk_addr_t ofs,
} }
ctx->comp.comp_head = ctx->comp.comp_tail = 0; ctx->comp.comp_head = ctx->comp.comp_tail = 0;
ctx->comp.cbuf = grub_malloc (1 << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR)); if (grub_add (ctx->comp.log_spc, GRUB_NTFS_BLK_SHR, &log_sz))
{
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("compression buffer size overflow"));
return 0;
}
ctx->comp.cbuf = grub_malloc (1 << log_sz);
if (!ctx->comp.cbuf) if (!ctx->comp.cbuf)
return 0; return 0;
+9 -3
View File
@@ -460,11 +460,11 @@ grub_squash_read_symlink (grub_fshelp_node_t node)
{ {
char *ret; char *ret;
grub_err_t err; grub_err_t err;
grub_size_t sz; grub_uint32_t sz;
if (grub_add (grub_le_to_cpu32 (node->ino.symlink.namelen), 1, &sz)) if (grub_add (grub_le_to_cpu32 (node->ino.symlink.namelen), 1, &sz))
{ {
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); grub_error (GRUB_ERR_OUT_OF_RANGE, N_("symlink name length overflow"));
return NULL; return NULL;
} }
@@ -580,6 +580,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
struct grub_squash_dirent di; struct grub_squash_dirent di;
struct grub_squash_inode ino; struct grub_squash_inode ino;
grub_size_t sz; grub_size_t sz;
grub_uint16_t nlen;
err = read_chunk (dir->data, &di, sizeof (di), err = read_chunk (dir->data, &di, sizeof (di),
grub_le_to_cpu64 (dir->data->sb.diroffset) grub_le_to_cpu64 (dir->data->sb.diroffset)
@@ -595,7 +596,12 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
if (err) if (err)
return 0; return 0;
buf = grub_malloc (grub_le_to_cpu16 (di.namelen) + 2); if (grub_add (grub_le_to_cpu16 (di.namelen), 2, &nlen))
{
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("name length overflow"));
return 0;
}
buf = grub_malloc (nlen);
if (!buf) if (!buf)
return 0; return 0;
err = read_chunk (dir->data, buf, err = read_chunk (dir->data, buf,
+15 -2
View File
@@ -718,6 +718,7 @@ static char *
grub_xfs_read_symlink (grub_fshelp_node_t node) grub_xfs_read_symlink (grub_fshelp_node_t node)
{ {
grub_ssize_t size = grub_be_to_cpu64 (node->inode.size); grub_ssize_t size = grub_be_to_cpu64 (node->inode.size);
grub_size_t sz;
if (size < 0) if (size < 0)
{ {
@@ -739,7 +740,12 @@ grub_xfs_read_symlink (grub_fshelp_node_t node)
if (node->data->hascrc) if (node->data->hascrc)
off = 56; off = 56;
symlink = grub_malloc (size + 1); if (grub_add (size, 1, &sz))
{
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("symlink size overflow"));
return 0;
}
symlink = grub_malloc (sz);
if (!symlink) if (!symlink)
return 0; return 0;
@@ -789,8 +795,15 @@ static int iterate_dir_call_hook (grub_uint64_t ino, const char *filename,
{ {
struct grub_fshelp_node *fdiro; struct grub_fshelp_node *fdiro;
grub_err_t err; grub_err_t err;
grub_size_t sz;
fdiro = grub_malloc (grub_xfs_fshelp_size(ctx->diro->data) + 1); if (grub_add (grub_xfs_fshelp_size(ctx->diro->data), 1, &sz))
{
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("directory data size overflow"));
grub_print_error ();
return 0;
}
fdiro = grub_malloc (sz);
if (!fdiro) if (!fdiro)
{ {
grub_print_error (); grub_print_error ();