On 06/14/2011 03:40 AM, Daniel P. Berrange wrote: > On Tue, Jun 14, 2011 at 10:15:36AM +0100, Daniel P. Berrange wrote: >> On Tue, Jun 07, 2011 at 10:02:55AM +0900, Minoru Usui wrote: >>> virNodeGetCPUStats: Implement linux support >>> >>> Signed-off-by: Minoru Usui <usui@xxxxxxxxxxxxxxxxx> >>> +#define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / sysconf(_SC_CLK_TCK)) >>> +#define CPU_HEADER_LEN 8 >>> + >>> +int linuxNodeGetCPUStats(FILE *procstat, >>> + int cpuNum, >>> + virCPUStatsPtr params, >>> + int *nparams) >>> +{ >>> + int ret = -1; >>> + char line[1024]; >>> + unsigned long long usr, ni, sys, idle, iowait; >>> + unsigned long long irq, softirq, steal, guest, guest_nice; >>> + char cpu_header[CPU_HEADER_LEN]; >>> + } else { >>> + sprintf(cpu_header, "cpu%d", cpuNum); >>> + } >> >> cpu_header is declared to be 8 bytes in size, which only allows >> for integers upto 4 digits long, before we get a buffer overflow >> here. >> >> gnulib has some macro which can be used to declare a string buffer >> large enough to hold an integer, but I can't remember what the >> macro is called right now. Hopefully Eric will remind us shortly.... > > Jim Meyering reminded me that it is INT_BUFSIZE_BOUND. So eg you > want todo > > char cpu_header[3 + INT_BUFSIZE_BOUND(cpuNum) + 1]; > > to allow enough space for 'cpu' + any cpuNum value formatted as > a string + the trailing NULL. Actually, INT_BUFSIZE_BOUND already includes space for the trailing NUL, so the +1 is not needed. > ACK if the buffer overflow problem is solved Also, 'make syntax-check' complained about cppi indentation, and the fact that we've blacklisted sprintf (use snprintf instead). Plus you had some weird indentation. Here's what I squashed before pushing: diff --git i/src/nodeinfo.c w/src/nodeinfo.c index 235a68a..bdf8f8a 100644 --- i/src/nodeinfo.c +++ w/src/nodeinfo.c @@ -66,10 +66,10 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo, virNodeInfoPtr nodeinfo, bool need_hyperthreads); -int linuxNodeGetCPUStats(FILE *procstat, - int cpuNum, - virCPUStatsPtr params, - int *nparams); +static int linuxNodeGetCPUStats(FILE *procstat, + int cpuNum, + virCPUStatsPtr params, + int *nparams); /* Return the positive decimal contents of the given * CPU_SYS_PATH/cpu%u/FILE, or -1 on error. If MISSING_OK and the @@ -384,8 +384,7 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo, return 0; } -#define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / sysconf(_SC_CLK_TCK)) -#define CPU_HEADER_LEN 8 +# define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / sysconf(_SC_CLK_TCK)) int linuxNodeGetCPUStats(FILE *procstat, int cpuNum, @@ -396,7 +395,7 @@ int linuxNodeGetCPUStats(FILE *procstat, char line[1024]; unsigned long long usr, ni, sys, idle, iowait; unsigned long long irq, softirq, steal, guest, guest_nice; - char cpu_header[CPU_HEADER_LEN]; + char cpu_header[3 + INT_BUFSIZE_BOUND(cpuNum)]; if ((*nparams) == 0) { /* Current number of cpu stats supported by linux */ @@ -414,7 +413,7 @@ int linuxNodeGetCPUStats(FILE *procstat, if (cpuNum == VIR_CPU_STATS_ALL_CPUS) { strcpy(cpu_header, "cpu"); } else { - sprintf(cpu_header, "cpu%d", cpuNum); + snprintf(cpu_header, sizeof(cpu_header), "cpu%d", cpuNum); } while (fgets(line, sizeof(line), procstat) != NULL) { @@ -436,7 +435,7 @@ int linuxNodeGetCPUStats(FILE *procstat, switch (i) { case 0: /* fill kernel cpu time here */ - if (virStrcpyStatic(param->field, VIR_CPU_STATS_KERNEL)== NULL) { + if (virStrcpyStatic(param->field, VIR_CPU_STATS_KERNEL) == NULL) { nodeReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Field kernel cpu time too long for destination")); goto cleanup; @@ -528,22 +527,23 @@ int nodeGetCPUStats(virConnectPtr conn ATTRIBUTE_UNUSED, int cpuNum, virCPUStatsPtr params, int *nparams, - unsigned int flags ATTRIBUTE_UNUSED) + unsigned int flags) { + virCheckFlags(0, -1); #ifdef __linux__ { - int ret; - FILE *procstat = fopen(PROCSTAT_PATH, "r"); - if (!procstat) { - virReportSystemError(errno, - _("cannot open %s"), PROCSTAT_PATH); - return -1; - } - ret = linuxNodeGetCPUStats(procstat, cpuNum, params, nparams); - VIR_FORCE_FCLOSE(procstat); + int ret; + FILE *procstat = fopen(PROCSTAT_PATH, "r"); + if (!procstat) { + virReportSystemError(errno, + _("cannot open %s"), PROCSTAT_PATH); + return -1; + } + ret = linuxNodeGetCPUStats(procstat, cpuNum, params, nparams); + VIR_FORCE_FCLOSE(procstat); - return ret; + return ret; } #else nodeReportError(VIR_ERR_NO_SUPPORT, "%s", -- Eric Blake eblake@xxxxxxxxxx +1-801-349-2682 Libvirt virtualization library http://libvirt.org
Attachment:
signature.asc
Description: OpenPGP digital signature
-- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list