From 266d945d9c6432fc5746fa46e3e3ace2518600db Mon Sep 17 00:00:00 2001
From: Ivan Vecera <ivecera@redhat.com>
Date: Fri, 18 Mar 2016 12:50:43 +0100
Subject: [PATCH] ethtool.c: fix memory leaks
Memory allocated at several places is not appropriately freed.
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
---
ethtool.c | 60 +++++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 45 insertions(+), 15 deletions(-)
diff --git a/ethtool.c b/ethtool.c
index 0cd0d4f..ca0bf28 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -2065,10 +2065,14 @@ static int do_gfeatures(struct cmd_context *ctx)
features = get_features(ctx, defs);
if (!features) {
fprintf(stdout, "no feature info available\n");
+ free(defs);
return 1;
}
dump_features(defs, features, NULL);
+
+ free(features);
+ free(defs);
return 0;
}
@@ -2078,11 +2082,11 @@ static int do_sfeatures(struct cmd_context *ctx)
int any_changed = 0, any_mismatch = 0;
u32 off_flags_wanted = 0;
u32 off_flags_mask = 0;
- struct ethtool_sfeatures *efeatures;
+ struct ethtool_sfeatures *efeatures = NULL;
struct cmdline_info *cmdline_features;
- struct feature_state *old_state, *new_state;
+ struct feature_state *old_state = NULL, *new_state = NULL;
struct ethtool_value eval;
- int err;
+ int err, retval = 1;
int i, j;
defs = get_feature_defs(ctx);
@@ -2096,7 +2100,7 @@ static int do_sfeatures(struct cmd_context *ctx)
sizeof(efeatures->features[0]));
if (!efeatures) {
perror("Cannot parse arguments");
- return 1;
+ goto finish;
}
efeatures->cmd = ETHTOOL_SFEATURES;
efeatures->size = FEATURE_BITS_TO_BLOCKS(defs->n_features);
@@ -2114,7 +2118,7 @@ static int do_sfeatures(struct cmd_context *ctx)
sizeof(cmdline_features[0]));
if (!cmdline_features) {
perror("Cannot parse arguments");
- return 1;
+ goto finish;
}
for (i = 0; i < ARRAY_SIZE(off_flag_def); i++)
flag_to_cmdline_info(off_flag_def[i].short_name,
@@ -2133,12 +2137,13 @@ static int do_sfeatures(struct cmd_context *ctx)
if (!any_changed) {
fprintf(stdout, "no features changed\n");
- return 0;
+ retval = 0;
+ goto finish;
}
old_state = get_features(ctx, defs);
if (!old_state)
- return 1;
+ goto finish;
if (efeatures) {
/* For each offload that the user specified, update any
@@ -2182,7 +2187,7 @@ static int do_sfeatures(struct cmd_context *ctx)
err = send_ioctl(ctx, efeatures);
if (err < 0) {
perror("Cannot set device feature settings");
- return 1;
+ goto finish;
}
} else {
for (i = 0; i < ARRAY_SIZE(off_flag_def); i++) {
@@ -2197,7 +2202,7 @@ static int do_sfeatures(struct cmd_context *ctx)
fprintf(stderr,
"Cannot set device %s settings: %m\n",
off_flag_def[i].long_name);
- return 1;
+ goto finish;
}
}
}
@@ -2211,7 +2216,8 @@ static int do_sfeatures(struct cmd_context *ctx)
err = send_ioctl(ctx, &eval);
if (err) {
perror("Cannot set device flag settings");
- return 92;
+ retval = 92;
+ goto finish;
}
}
}
@@ -2219,7 +2225,7 @@ static int do_sfeatures(struct cmd_context *ctx)
/* Compare new state with requested state */
new_state = get_features(ctx, defs);
if (!new_state)
- return 1;
+ goto finish;
any_changed = new_state->off_flags != old_state->off_flags;
any_mismatch = (new_state->off_flags !=
((old_state->off_flags & ~off_flags_mask) |
@@ -2238,13 +2244,19 @@ static int do_sfeatures(struct cmd_context *ctx)
if (!any_changed) {
fprintf(stderr,
"Could not change any device features\n");
- return 1;
+ goto finish;
}
printf("Actual changes:\n");
dump_features(defs, new_state, old_state);
}
- return 0;
+ retval = 0;
+finish:
+ free(new_state);
+ free(old_state);
+ free(efeatures);
+ free(defs);
+ return retval;
}
static int do_gset(struct cmd_context *ctx)
@@ -2705,8 +2717,18 @@ static int do_gregs(struct cmd_context *ctx)
return 75;
}
- regs = realloc(regs, sizeof(*regs) + st.st_size);
- regs->len = st.st_size;
+ if (regs->len != st.st_size) {
+ struct ethtool_regs *new_regs;
+ new_regs = realloc(regs, sizeof(*regs) + st.st_size);
+ if (!new_regs) {
+ perror("Cannot allocate memory for register "
+ "dump");
+ free(regs);
+ return 73;
+ }
+ regs = new_regs;
+ regs->len = st.st_size;
+ }
nread = fread(regs->data, regs->len, 1, f);
fclose(f);
if (nread != 1) {
@@ -3775,6 +3797,7 @@ static int do_gprivflags(struct cmd_context *ctx)
}
if (strings->len == 0) {
fprintf(stderr, "No private flags defined\n");
+ free(strings);
return 1;
}
if (strings->len > 32) {
@@ -3786,6 +3809,7 @@ static int do_gprivflags(struct cmd_context *ctx)
flags.cmd = ETHTOOL_GPFLAGS;
if (send_ioctl(ctx, &flags)) {
perror("Cannot get private flags");
+ free(strings);
return 1;
}
@@ -3804,6 +3828,7 @@ static int do_gprivflags(struct cmd_context *ctx)
(const char *)strings->data + i * ETH_GSTRING_LEN,
(flags.data & (1U << i)) ? "on" : "off");
+ free(strings);
return 0;
}
@@ -3825,6 +3850,7 @@ static int do_sprivflags(struct cmd_context *ctx)
}
if (strings->len == 0) {
fprintf(stderr, "No private flags defined\n");
+ free(strings);
return 1;
}
if (strings->len > 32) {
@@ -3836,6 +3862,7 @@ static int do_sprivflags(struct cmd_context *ctx)
cmdline = calloc(strings->len, sizeof(*cmdline));
if (!cmdline) {
perror("Cannot parse arguments");
+ free(strings);
return 1;
}
for (i = 0; i < strings->len; i++) {
@@ -3852,6 +3879,7 @@ static int do_sprivflags(struct cmd_context *ctx)
flags.cmd = ETHTOOL_GPFLAGS;
if (send_ioctl(ctx, &flags)) {
perror("Cannot get private flags");
+ free(strings);
return 1;
}
@@ -3859,9 +3887,11 @@ static int do_sprivflags(struct cmd_context *ctx)
flags.data = (flags.data & ~seen_flags) | wanted_flags;
if (send_ioctl(ctx, &flags)) {
perror("Cannot set private flags");
+ free(strings);
return 1;
}
+ free(strings);
return 0;
}
--
2.7.3