summaryrefslogtreecommitdiff
path: root/libelf
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2022-03-20 22:21:05 +0100
committerMark Wielaard <mark@klomp.org>2022-03-20 22:21:05 +0100
commit2785ba7ad21e3f28949c7333d48412122ebbcfa2 (patch)
tree8c524b6596f57ea1504ba97c80296c06f65f7df4 /libelf
parent3b878cfe71b5637ad043382e8c300233cff89f6e (diff)
downloadelfutils-2785ba7ad21e3f28949c7333d48412122ebbcfa2.tar.gz
libelf: Don't overflow offsets in elf_cvt_Verneed and elf_cvt_Verdef
The conversion functions for Verdef and Verneed keep offsets to the next structure. Make sure that following vd_aux, vda_next, vd_next, vn_aux, vna_next and vn_next don't overflow (and wrap around) the offsets. Signed-off-by: Mark Wielaard <mark@klomp.org>
Diffstat (limited to 'libelf')
-rw-r--r--libelf/ChangeLog7
-rw-r--r--libelf/version_xlate.h56
2 files changed, 55 insertions, 8 deletions
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index f6b47c68..ea204e2b 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,10 @@
+2022-03-20 Mark Wielaard <mark@klomp.org>
+
+ * version_xlate.h (elf_cvt_Verdef): Make sure aux_offset and
+ def_offset don't overflow.
+ (elf_cvt_Verneed): Make sure aux_offset and need_offset don't
+ overflow.
+
2022-03-18 Mark Wielaard <mark@klomp.org>
* version_xlate.h (elf_cvt_Verdef): Check alignment of def_offset
diff --git a/libelf/version_xlate.h b/libelf/version_xlate.h
index b7bd301d..97f3b730 100644
--- a/libelf/version_xlate.h
+++ b/libelf/version_xlate.h
@@ -87,10 +87,16 @@ elf_cvt_Verdef (void *dest, const void *src, size_t len, int encode)
ddest->vd_aux = bswap_32 (dsrc->vd_aux);
ddest->vd_next = bswap_32 (dsrc->vd_next);
+ if (ddest->vd_aux > len - def_offset)
+ return;
aux_offset = def_offset + ddest->vd_aux;
}
else
- aux_offset = def_offset + dsrc->vd_aux;
+ {
+ if (dsrc->vd_aux > len - def_offset)
+ return;
+ aux_offset = def_offset + dsrc->vd_aux;
+ }
/* Handle all the auxiliary records belonging to this definition. */
do
@@ -107,19 +113,29 @@ elf_cvt_Verdef (void *dest, const void *src, size_t len, int encode)
asrc = (GElf_Verdaux *) ((char *) src + aux_offset);
if (encode)
- aux_offset += asrc->vda_next;
+ {
+ if (asrc->vda_next > len - aux_offset)
+ return;
+ aux_offset += asrc->vda_next;
+ }
adest->vda_name = bswap_32 (asrc->vda_name);
adest->vda_next = bswap_32 (asrc->vda_next);
if (! encode)
- aux_offset += adest->vda_next;
+ {
+ if (adest->vda_next > len - aux_offset)
+ return;
+ aux_offset += adest->vda_next;
+ }
}
while (asrc->vda_next != 0);
/* Encode now if necessary. */
if (encode)
{
+ if (dsrc->vd_next > len - def_offset)
+ return;
def_offset += dsrc->vd_next;
ddest->vd_version = bswap_16 (dsrc->vd_version);
@@ -131,7 +147,11 @@ elf_cvt_Verdef (void *dest, const void *src, size_t len, int encode)
ddest->vd_next = bswap_32 (dsrc->vd_next);
}
else
- def_offset += ddest->vd_next;
+ {
+ if (ddest->vd_next > len - def_offset)
+ return;
+ def_offset += ddest->vd_next;
+ }
}
while (dsrc->vd_next != 0);
}
@@ -188,10 +208,16 @@ elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
ndest->vn_aux = bswap_32 (nsrc->vn_aux);
ndest->vn_next = bswap_32 (nsrc->vn_next);
+ if (ndest->vn_aux > len - need_offset)
+ return;
aux_offset = need_offset + ndest->vn_aux;
}
else
- aux_offset = need_offset + nsrc->vn_aux;
+ {
+ if (nsrc->vn_aux > len - need_offset)
+ return;
+ aux_offset = need_offset + nsrc->vn_aux;
+ }
/* Handle all the auxiliary records belonging to this requirement. */
do
@@ -208,7 +234,11 @@ elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
asrc = (GElf_Vernaux *) ((char *) src + aux_offset);
if (encode)
- aux_offset += asrc->vna_next;
+ {
+ if (asrc->vna_next > len - aux_offset)
+ return;
+ aux_offset += asrc->vna_next;
+ }
adest->vna_hash = bswap_32 (asrc->vna_hash);
adest->vna_flags = bswap_16 (asrc->vna_flags);
@@ -217,13 +247,19 @@ elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
adest->vna_next = bswap_32 (asrc->vna_next);
if (! encode)
- aux_offset += adest->vna_next;
+ {
+ if (adest->vna_next > len - aux_offset)
+ return;
+ aux_offset += adest->vna_next;
+ }
}
while (asrc->vna_next != 0);
/* Encode now if necessary. */
if (encode)
{
+ if (nsrc->vn_next > len - need_offset)
+ return;
need_offset += nsrc->vn_next;
ndest->vn_version = bswap_16 (nsrc->vn_version);
@@ -233,7 +269,11 @@ elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
ndest->vn_next = bswap_32 (nsrc->vn_next);
}
else
- need_offset += ndest->vn_next;
+ {
+ if (ndest->vn_next > len - need_offset)
+ return;
+ need_offset += ndest->vn_next;
+ }
}
while (nsrc->vn_next != 0);
}