Reuse the buffer for getline and track buffer allocation
separately from the string length to prevent unlikely
out-of-bounds memory access.
This fixes the following leak that happened when zero bytes were read:
==404== 120 bytes in 1 blocks are definitely lost in loss record 1,344 of 1,671
==404== at 0x4C2C71B: malloc (in
/usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==404== by 0x906F862: getdelim (iogetdelim.c:68)
==404== by 0x52A48FB: virCgroupPartitionNeedsEscaping (vircgroup.c:1136)
==404== by 0x52A0FB4: virCgroupPartitionEscape (vircgroup.c:1171)
==404== by 0x52A0EA4: virCgroupNewDomainPartition (vircgroup.c:1450)
---
v1: cgroup: Free line even if no characters were read
https://www.redhat.com/archives/libvir-list/2013-July/msg01030.html
src/util/vircgroup.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
index 5a98393..9dfe98d 100644
--- a/src/util/vircgroup.c
+++ b/src/util/vircgroup.c
@@ -1098,13 +1098,13 @@ cleanup:
#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
static int virCgroupPartitionNeedsEscaping(const char *path)
{
FILE *fp = NULL;
int ret = 0;
char *line = NULL;
- size_t len;
+ size_t buflen;
/* If it starts with 'cgroup.' or a '_' of any
* of the controller names from /proc/cgroups,
* then we must prefix a '_'
*/
if (STRPREFIX(path, "cgroup."))
@@ -1130,37 +1130,37 @@ static int virCgroupPartitionNeedsEscaping(const char *path)
* cpuacct 3 48 1
* memory 4 4 1
* devices 5 4 1
* freezer 6 4 1
* net_cls 7 1 1
*/
- while (getline(&line, &len, fp) > 0) {
- if (STRPREFIX(line, "#subsys_name")) {
- VIR_FREE(line);
+ while (getline(&line, &buflen, fp) > 0) {
+ char *tmp;
+ size_t len;
+
+ if (STRPREFIX(line, "#subsys_name"))
continue;
- }
- char *tmp = strchr(line, ' ');
- if (tmp)
- *tmp = '\0';
+
+ tmp = strchrnul(line, ' ');
+ *tmp = '\0';
len = tmp - line;
if (STRPREFIX(path, line) &&
path[len] == '.') {
ret = 1;
- VIR_FREE(line);
goto cleanup;
}
- VIR_FREE(line);
}
if (ferror(fp)) {
ret = -EIO;
goto cleanup;
}
cleanup:
+ VIR_FREE(line);
VIR_FORCE_FCLOSE(fp);
return ret;
}
static int virCgroupPartitionEscape(char **path)
{
--
1.8.1.5