Message ID | 1457138533-2417-5-git-send-email-ddecotig@gmail.com |
---|---|
State | Not Applicable, archived |
Delegated to: | David Miller |
Headers | show |
On Fri, 2016-03-04 at 16:42 -0800, David Decotigny wrote: > From: David Decotigny <decot@googlers.com> > > Tested: > On qemu e1000: > $ dd if=/dev/zero bs=2 count=5 | /mnt/ethtool -E eth0 length 9 > too much data from stdin > $ dd if=/dev/zero bs=2 count=5 | /mnt/ethtool -E eth0 length 11 > not enough data from stdin > $ dd if=/dev/zero bs=2 count=5 | /mnt/ethtool -E eth0 length 10 > Cannot set EEPROM data: Bad address > > > Signed-off-by: David Decotigny <decot@googlers.com> > --- > ethtool.c | 24 ++++++++++++++++++++---- > 1 file changed, 20 insertions(+), 4 deletions(-) > > diff --git a/ethtool.c b/ethtool.c > index c64b962..19f479c 100644 > --- a/ethtool.c > +++ b/ethtool.c > @@ -2828,8 +2828,14 @@ static int do_seeprom(struct cmd_context *ctx) > if (seeprom_length == -1) > seeprom_length = drvinfo.eedump_len; > > - if (drvinfo.eedump_len < seeprom_offset + seeprom_length) > - seeprom_length = drvinfo.eedump_len - seeprom_offset; > + if (drvinfo.eedump_len < seeprom_offset + seeprom_length) { > + if (drvinfo.eedump_len > seeprom_offset) > + seeprom_length = drvinfo.eedump_len - seeprom_offset; Don't silently truncate - treat this as an error too. > + else { > + fprintf(stderr, "offset & length out of bounds\n"); > + return 75; Use the default error code of 1 rather than making 75 even less meaningful. > + } > + } > > eeprom = calloc(1, sizeof(*eeprom)+seeprom_length); > if (!eeprom) { > @@ -2844,8 +2850,18 @@ static int do_seeprom(struct cmd_context *ctx) > eeprom->data[0] = seeprom_value; > > /* Multi-byte write: read input from stdin */ > - if (!seeprom_value_seen) > - eeprom->len = fread(eeprom->data, 1, eeprom->len, stdin); > + if (!seeprom_value_seen) { > + if (1 != fread(eeprom->data, eeprom->len, 1, stdin)) { > + fprintf(stderr, "not enough data from stdin\n"); > + free(eeprom); > + return 75; > + } > + if ((EOF != fgetc(stdin)) || !feof(stdin)) { Comparisons are the wrong way round. Ben. > + fprintf(stderr, "too much data from stdin\n"); > + free(eeprom); > + return 75; > + } > + } > > err = send_ioctl(ctx, eeprom); > if (err < 0) {
diff --git a/ethtool.c b/ethtool.c index c64b962..19f479c 100644 --- a/ethtool.c +++ b/ethtool.c @@ -2828,8 +2828,14 @@ static int do_seeprom(struct cmd_context *ctx) if (seeprom_length == -1) seeprom_length = drvinfo.eedump_len; - if (drvinfo.eedump_len < seeprom_offset + seeprom_length) - seeprom_length = drvinfo.eedump_len - seeprom_offset; + if (drvinfo.eedump_len < seeprom_offset + seeprom_length) { + if (drvinfo.eedump_len > seeprom_offset) + seeprom_length = drvinfo.eedump_len - seeprom_offset; + else { + fprintf(stderr, "offset & length out of bounds\n"); + return 75; + } + } eeprom = calloc(1, sizeof(*eeprom)+seeprom_length); if (!eeprom) { @@ -2844,8 +2850,18 @@ static int do_seeprom(struct cmd_context *ctx) eeprom->data[0] = seeprom_value; /* Multi-byte write: read input from stdin */ - if (!seeprom_value_seen) - eeprom->len = fread(eeprom->data, 1, eeprom->len, stdin); + if (!seeprom_value_seen) { + if (1 != fread(eeprom->data, eeprom->len, 1, stdin)) { + fprintf(stderr, "not enough data from stdin\n"); + free(eeprom); + return 75; + } + if ((EOF != fgetc(stdin)) || !feof(stdin)) { + fprintf(stderr, "too much data from stdin\n"); + free(eeprom); + return 75; + } + } err = send_ioctl(ctx, eeprom); if (err < 0) {