1From 952aff5c00ad7c6b83c3f310f2643939538827f8 Mon Sep 17 00:00:00 2001 2From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= 3 =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= <leo@yuriev.ru> 4Date: Sat, 4 Feb 2023 14:41:38 +0300 5Subject: [PATCH] gmon: Fix allocated buffer overflow (bug 29444) 6MIME-Version: 1.0 7Content-Type: text/plain; charset=UTF-8 8Content-Transfer-Encoding: 8bit 9 10The `__monstartup()` allocates a buffer used to store all the data 11accumulated by the monitor. 12 13The size of this buffer depends on the size of the internal structures 14used and the address range for which the monitor is activated, as well 15as on the maximum density of call instructions and/or callable functions 16that could be potentially on a segment of executable code. 17 18In particular a hash table of arcs is placed at the end of this buffer. 19The size of this hash table is calculated in bytes as 20 p->fromssize = p->textsize / HASHFRACTION; 21 22but actually should be 23 p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms)); 24 25This results in writing beyond the end of the allocated buffer when an 26added arc corresponds to a call near from the end of the monitored 27address range, since `_mcount()` check the incoming caller address for 28monitored range but not the intermediate result hash-like index that 29uses to write into the table. 30 31It should be noted that when the results are output to `gmon.out`, the 32table is read to the last element calculated from the allocated size in 33bytes, so the arcs stored outside the buffer boundary did not fall into 34`gprof` for analysis. Thus this "feature" help me to found this bug 35during working with https://sourceware.org/bugzilla/show_bug.cgi?id=29438 36 37Just in case, I will explicitly note that the problem breaks the 38`make test t=gmon/tst-gmon-dso` added for Bug 29438. 39There, the arc of the `f3()` call disappears from the output, since in 40the DSO case, the call to `f3` is located close to the end of the 41monitored range. 42 43Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru> 44 45Another minor error seems a related typo in the calculation of 46`kcountsize`, but since kcounts are smaller than froms, this is 47actually to align the p->froms data. 48 49Co-authored-by: DJ Delorie <dj@redhat.com> 50Reviewed-by: Carlos O'Donell <carlos@redhat.com> 51 52Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commit;h=801af9fafd4689337ebf27260aa115335a0cb2bc] 53CVE: CVE-2023-0687 54Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com> 55--- 56 gmon/gmon.c | 4 +++- 57 1 file changed, 3 insertions(+), 1 deletion(-) 58 59diff --git a/gmon/gmon.c b/gmon/gmon.c 60index dee6480..bf76358 100644 61--- a/gmon/gmon.c 62+++ b/gmon/gmon.c 63@@ -132,6 +132,8 @@ __monstartup (u_long lowpc, u_long highpc) 64 p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER)); 65 p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER)); 66 p->textsize = p->highpc - p->lowpc; 67+ /* This looks like a typo, but it's here to align the p->froms 68+ section. */ 69 p->kcountsize = ROUNDUP(p->textsize / HISTFRACTION, sizeof(*p->froms)); 70 p->hashfraction = HASHFRACTION; 71 p->log_hashfraction = -1; 72@@ -142,7 +144,7 @@ __monstartup (u_long lowpc, u_long highpc) 73 instead of integer division. Precompute shift amount. */ 74 p->log_hashfraction = ffs(p->hashfraction * sizeof(*p->froms)) - 1; 75 } 76- p->fromssize = p->textsize / HASHFRACTION; 77+ p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms)); 78 p->tolimit = p->textsize * ARCDENSITY / 100; 79 if (p->tolimit < MINARCS) 80 p->tolimit = MINARCS; 81-- 822.7.4 83