The `__monstartup()` allocates a buffer used to store all the data accumulated by the monitor. The size of this buffer depends on the size of the internal structures used and the address range for which the monitor is activated, as well as on the maximum density of call instuctions and/or callable functions that could be potentially on a segment of executable code. In particular a hash table of arcs is placed at the end of this buffer. The size of this hash table is calculated in bytes as `p->fromssize = p->textsize / HASHFRACTION`, but actually should be `p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms))`. This results in writing beyond the end of the allocated buffer when an added arc corresponds to a call near from the end of the monitored address range, since `_mcount()` check the incoming caller address for monitored range but not the intermediate result hash-like index that uses to write into the table. It should be noted that when the results are output to `gmon.out`, the table is read to the last element calculated from the allocated size in bytes, so the arcs stored outside the buffer boundary did not fall into `gprof` for analysis. Thus this "feature" help me to found this bug during working with Bug 29438. Another minor error seems a related typo in the calculation of `kcountsize`.
Created attachment 14253 [details] the patch
Just in case, I will explicitly note that the problem breaks the `make test t=gmon/tst-gmon-dso` added for Bug 29438. There, the arc of the `f3()` call disappears from the output, since in the DSO case, the call to `f3` is located close to the end of the monitored range.
Please review the attached patch and apply. It just fixes an allocated buffer overrun issue, i.e. the memory corruption!
(In reply to Leo Yuriev from comment #3) > Please review the attached patch and apply. > It just fixes an allocated buffer overrun issue, i.e. the memory corruption! Patch reviews are done through libc-alpha email list, could you please sent the patch following the contribution guidelines [1]? [1] https://sourceware.org/glibc/wiki/Contribution%20checklist
https://patchwork.sourceware.org/project/glibc/patch/20230204114138.5436-1-leo@yuriev.ru/
CVE-ID was requested via submission to VulDB.
CVE-2023-0687 https://vuldb.com/?id.220246
Will the glibc maintainers reject the assigned CVE? I don't see how this is exploitable.
(In reply to Ismail Donmez from comment #8) > Will the glibc maintainers reject the assigned CVE? I don't see how this is > exploitable. Agreed. I expect us to file a DISPUTE request with MITRE later today.
(In reply to Florian Weimer from comment #9) > (In reply to Ismail Donmez from comment #8) > > Will the glibc maintainers reject the assigned CVE? I don't see how this is > > exploitable. > > Agreed. I expect us to file a DISPUTE request with MITRE later today. Yes, it is not exploitable in usual/common cases. However, this bug can be exploited in rare specific scenarios when monstartup() and moncontrol() are called explicitly to collect statistics from a part of modules compiled with the corresponding options (nonetheless, I cannot disclose information about affected software either show the exploit). During submission for CVE-ID, I noted about that the bug could be exploited only when gmon activated, but such note is not included into CVE for now.
The only way to induce this buffer overflow is to modify the callgraph of an application that is built with these options(In reply to Leo Yuriev from comment #10) > (In reply to Florian Weimer from comment #9) > > (In reply to Ismail Donmez from comment #8) > > > Will the glibc maintainers reject the assigned CVE? I don't see how this is > > > exploitable. > > > > Agreed. I expect us to file a DISPUTE request with MITRE later today. > > Yes, it is not exploitable in usual/common cases. > > However, this bug can be exploited in rare specific scenarios when > monstartup() and moncontrol() are called explicitly to collect statistics > from a part of modules compiled with the corresponding options (nonetheless, > I cannot disclose information about affected software either show the > exploit). The inputs that induce this buffer overflow are basically addresses of the running application that is built with gmon enabled *and* with the patch for bug 29438, so it's basically trusted input or input that needs an actual security flaw to be compromised or controlled. The bug needs to be fixed, but there's no security issue here.
(In reply to Siddhesh Poyarekar from comment #11) > The inputs that induce this buffer overflow are basically addresses of the > running application that is built with gmon enabled *and* with the patch for > bug 29438, so it's basically trusted input or input that needs an actual > security flaw to be compromised or controlled. The bug needs to be fixed, > but there's no security issue here. The patch for Bug 29438 not needed to exploitation, but gmon must be enabled. Initially I discovered this issue while working on Bug 29438. But later it was re-noticed in another environment, where it is exploitable. Briefly: 1) Prerequirement: - a web service users gmon to collect statistics on the performance of its module(s); - OR an attacker can enable the collection of such statistics; 2) By manipulating requests, the attacker achieves a function call that is at the end of the monitored addresses and is usually never called. T 3) The attacker continue an attack using memory corruption. Yes, this is a very specific scenario with a very low probability of exploitation. However, we reproduced it in a prepared environment.
(In reply to Leo Yuriev from comment #12) > 2) By manipulating requests, the attacker achieves a function call that is > at the end of the monitored addresses and is usually never called. T My point is that this step above needs specific knowledge of the address space *and* control over execution to make this happen. Without such control, there's no exploitation vector.
(In reply to Siddhesh Poyarekar from comment #13) > (In reply to Leo Yuriev from comment #12) > > 2) By manipulating requests, the attacker achieves a function call that is > > at the end of the monitored addresses and is usually never called. > > My point is that this step above needs specific knowledge of the address > space *and* control over execution to make this happen. Without such > control, there's no exploitation vector. There is the effect of a "critical mass" of vulnerabilities - when exploitation is possible only if there is a set of vulnerabilities, but not one or even two. In my case, it took a couple more vulnerabilities in the application code to exploit this bug. However, without this issue, exploiting is also impossible. My point is: we cannot assume all use cases and scenarios for a widely used library, therefore a use-after-free, off-by-one, buffer overflow, memory corruption, using/reading uninitialized, race condition, etc... in a such library is always a CVE. No options.
(In reply to Leo Yuriev from comment #14) > There is the effect of a "critical mass" of vulnerabilities - when > exploitation is possible only if there is a set of vulnerabilities, but not > one or even two. > > In my case, it took a couple more vulnerabilities in the application code to > exploit this bug. However, without this issue, exploiting is also impossible. Please explain how, remember that the input has to be *untrusted* for it to be considered a security issue. > My point is: we cannot assume all use cases and scenarios for a widely used > library, therefore a use-after-free, off-by-one, buffer overflow, memory > corruption, using/reading uninitialized, race condition, etc... in a such > library is always a CVE. > No options. You're free to consider every memory or synchronization bug in libraries you use as a security issue and deal with it as such. In the glibc project we have well defined rules as to what we consider security issues: https://sourceware.org/glibc/wiki/Security%20Process
Sorry, but I don't have time for useless discuss.
Keeping the bug open since we obviously want to fix it.
Florian, Regarding the DISPUTE (or reject?) for the CVE as mentioned in https://sourceware.org/bugzilla/show_bug.cgi?id=29444#c9 : Schould the request actually go to VulDB instead of MITRE, as VulDB was the assigning CNA? Regards, Salvatore
I already submitted the rejection request to Mitre. VulDB has a login barrier to even view the CVE, so I didn't bother with it. If Mitre refuses to handle it I'll retry with vuldb.
Fixed by commit 801af9fafd4689337ebf27260aa115335a0cb2bc https://sourceware.org/git/?p=glibc.git;a=commit;h=801af9fafd4689337ebf27260aa115335a0cb2bc Thanks to DJ Delorie <dj@redhat.com>. Please close as FIXED.
Fixed in rawhide.
(In reply to account disabled by myself since useless from comment #20) > Fixed by commit 801af9fafd4689337ebf27260aa115335a0cb2bc > https://sourceware.org/git/?p=glibc.git;a=commit; > h=801af9fafd4689337ebf27260aa115335a0cb2bc > > Thanks to DJ Delorie <dj@redhat.com>. > > Please close as FIXED. This fix calls ROUNDUP to address memory alignment and does not limit the buffer size to the specified range.
Could you be more specific? (In reply to lin zhuorong from comment #22) > This fix calls ROUNDUP to address memory alignment and does not limit the > buffer size to the specified range. Could you be more specific? The fix increases the buffer size enough to prevent a partial record from being written past the end of the allocated buffer. The memory alignment was already in there. Which range should the buffer size be limited to?