aboutsummaryrefslogtreecommitdiffstats
diff options
authorKarel Zak <kzak@redhat.com>2026-03-25 11:54:42 +0100
committerKarel Zak <kzak@redhat.com>2026-04-01 10:48:06 +0200
commit699d086fa5f24651b375e5909c27e14a16ceb4b9 (patch)
tree8e29c75943ce1ccccdee876ca36223469c4074d6
parente9d544d013267ea86b70ee8ff78abd280e6641af (diff)
downloadutil-linux-master.tar.gz
libfdisk: dos: validate EBR link within extended partition boundsHEADmaster
The read_extended() function follows EBR chain links without checking that the target offset falls within the master extended partition. A malformed EBR link can point outside the extended area. Add a bounds check before read_pte() to stop the chain walk when the next EBR offset is outside [ext_start, ext_end]. This is self-defense during parsing; it does not restrict what the user can create. Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r--libfdisk/src/dos.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/libfdisk/src/dos.c b/libfdisk/src/dos.c
index d1fb77315..99208c3eb 100644
--- a/libfdisk/src/dos.c
+++ b/libfdisk/src/dos.c
@@ -527,6 +527,7 @@ static void read_extended(struct fdisk_context *cxt, size_t ext)
struct pte *pex, *pe;
struct dos_partition *p, *q;
struct fdisk_dos_label *l = self_label(cxt);
+ fdisk_sector_t ext_start, ext_end;
if (fdisk_is_listonly(cxt) &&
!sysfs_devno_is_wholedisk(fdisk_get_devno(cxt))) {
@@ -549,9 +550,14 @@ static void read_extended(struct fdisk_context *cxt, size_t ext)
return;
}
+ ext_start = get_abs_partition_start(pex);
+ ext_end = get_abs_partition_end(pex);
+
DBG(LABEL, ul_debug("DOS: Reading extended %zu", ext));
while (IS_EXTENDED (p->sys_ind)) {
+ fdisk_sector_t next;
+
if (cxt->label->nparts_max >= MAXIMUM_PARTS) {
/* This is not a Linux restriction, but
this program uses arrays of size MAXIMUM_PARTS.
@@ -575,8 +581,17 @@ static void read_extended(struct fdisk_context *cxt, size_t ext)
if (!pe)
return;
- if (read_pte(cxt, cxt->label->nparts_max, l->ext_offset +
- dos_partition_get_start(p)))
+ next = l->ext_offset + dos_partition_get_start(p);
+ if (next < ext_start || next > ext_end) {
+ DBG(LABEL, ul_debug("DOS: EBR link %ju outside "
+ "extended partition <%ju-%ju> -- stop",
+ (uintmax_t) next,
+ (uintmax_t) ext_start,
+ (uintmax_t) ext_end));
+ break;
+ }
+
+ if (read_pte(cxt, cxt->label->nparts_max, next))
return;
if (!l->ext_offset)