From ae4e21c93f81c8d612e4c72df44c2a1dc971a863 Mon Sep 17 00:00:00 2001 From: Andreas Henriksson Date: Wed, 23 Aug 2017 14:47:51 +0200 Subject: [PATCH 01/21] ss: fix help/man TCP-STATE description for listening There's some misleading information in --help and ss(8) manpage about TCP-STATE named 'listen'. ss doesn't know such a state, but it knows 'listening' state. $ ss -tua state listen ss: wrong state name: listen $ ss -tua state listening [...] Addresses: https://bugs.debian.org/872990 Reported-by: Pavel Lyulchenko Signed-off-by: Andreas Henriksson --- man/man8/ss.8 | 4 ++-- misc/ss.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/man/man8/ss.8 b/man/man8/ss.8 index 81de69de..3bec97f0 100644 --- a/man/man8/ss.8 +++ b/man/man8/ss.8 @@ -153,14 +153,14 @@ Available identifiers are: All standard TCP states: .BR established ", " syn-sent ", " syn-recv ", " fin-wait-1 ", " fin-wait-2 ", " time-wait ", " closed ", " close-wait ", " last-ack ", " -.BR listen " and " closing. +.BR listening " and " closing. .B all - for all the states .B connected - all the states except for -.BR listen " and " closed +.BR listening " and " closed .B synchronized - all the diff --git a/misc/ss.c b/misc/ss.c index 34c6da54..c197e075 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -3922,11 +3922,11 @@ static void _usage(FILE *dest) " -F, --filter=FILE read filter information from FILE\n" " FILTER := [ state STATE-FILTER ] [ EXPRESSION ]\n" " STATE-FILTER := {all|connected|synchronized|bucket|big|TCP-STATES}\n" -" TCP-STATES := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|closed|close-wait|last-ack|listen|closing}\n" +" TCP-STATES := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|closed|close-wait|last-ack|listening|closing}\n" " connected := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|close-wait|last-ack|closing}\n" " synchronized := {established|syn-recv|fin-wait-{1,2}|time-wait|close-wait|last-ack|closing}\n" " bucket := {syn-recv|time-wait}\n" -" big := {established|syn-sent|fin-wait-{1,2}|closed|close-wait|last-ack|listen|closing}\n" +" big := {established|syn-sent|fin-wait-{1,2}|closed|close-wait|last-ack|listening|closing}\n" ); } From 6d02518fdc37eb12abff67b6f8c741fbd81dce72 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 24 Aug 2017 11:46:31 +0200 Subject: [PATCH 02/21] ifstat, nstat: Check fdopen() return value Prevent passing NULL FILE pointer to fgets() later. Fix both tools in a single patch since the code changes are basically identical. Signed-off-by: Phil Sutter --- misc/ifstat.c | 16 +++++++++++----- misc/nstat.c | 16 +++++++++++----- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/misc/ifstat.c b/misc/ifstat.c index 1be21703..ac3eff6b 100644 --- a/misc/ifstat.c +++ b/misc/ifstat.c @@ -992,12 +992,18 @@ int main(int argc, char *argv[]) && verify_forging(fd) == 0) { FILE *sfp = fdopen(fd, "r"); - load_raw_table(sfp); - if (hist_db && source_mismatch) { - fprintf(stderr, "ifstat: history is stale, ignoring it.\n"); - hist_db = NULL; + if (!sfp) { + fprintf(stderr, "ifstat: fdopen failed: %s\n", + strerror(errno)); + close(fd); + } else { + load_raw_table(sfp); + if (hist_db && source_mismatch) { + fprintf(stderr, "ifstat: history is stale, ignoring it.\n"); + hist_db = NULL; + } + fclose(sfp); } - fclose(sfp); } else { if (fd >= 0) close(fd); diff --git a/misc/nstat.c b/misc/nstat.c index 1212b1f2..a4dd405d 100644 --- a/misc/nstat.c +++ b/misc/nstat.c @@ -706,12 +706,18 @@ int main(int argc, char *argv[]) && verify_forging(fd) == 0) { FILE *sfp = fdopen(fd, "r"); - load_good_table(sfp); - if (hist_db && source_mismatch) { - fprintf(stderr, "nstat: history is stale, ignoring it.\n"); - hist_db = NULL; + if (!sfp) { + fprintf(stderr, "nstat: fdopen failed: %s\n", + strerror(errno)); + close(fd); + } else { + load_good_table(sfp); + if (hist_db && source_mismatch) { + fprintf(stderr, "nstat: history is stale, ignoring it.\n"); + hist_db = NULL; + } + fclose(sfp); } - fclose(sfp); } else { if (fd >= 0) close(fd); From a754de3ccd937500940c6fcd0ad043855f56862d Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 24 Aug 2017 11:46:32 +0200 Subject: [PATCH 03/21] tc/q_netem: Don't dereference possibly NULL pointer Assuming 'opt' might be NULL, move the call to RTA_PAYLOAD to after the check since it dereferences its parameter. Signed-off-by: Phil Sutter --- tc/q_netem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tc/q_netem.c b/tc/q_netem.c index 0975ae11..5a9e7474 100644 --- a/tc/q_netem.c +++ b/tc/q_netem.c @@ -538,7 +538,7 @@ static int netem_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) int *ecn = NULL; struct tc_netem_qopt qopt; const struct tc_netem_rate *rate = NULL; - int len = RTA_PAYLOAD(opt) - sizeof(qopt); + int len; __u64 rate64 = 0; SPRINT_BUF(b1); @@ -546,6 +546,7 @@ static int netem_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) if (opt == NULL) return 0; + len = RTA_PAYLOAD(opt) - sizeof(qopt); if (len < 0) { fprintf(stderr, "options size error\n"); return -1; From 75716932a0af28da207aa57c212794ab28ce9036 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 24 Aug 2017 11:46:33 +0200 Subject: [PATCH 04/21] tc/tc_filter: Make sure filter name is not empty The later check for 'k[0] != 0' requires a non-empty filter name, otherwise NULL pointer dereference in 'q' might happen. Signed-off-by: Phil Sutter --- tc/tc_filter.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tc/tc_filter.c b/tc/tc_filter.c index b13fb918..cf290ae8 100644 --- a/tc/tc_filter.c +++ b/tc/tc_filter.c @@ -412,6 +412,9 @@ static int tc_filter_get(int cmd, unsigned int flags, int argc, char **argv) usage(); return 0; } else { + if (!**argv) + invarg("invalid filter name", *argv); + strncpy(k, *argv, sizeof(k)-1); q = get_filter_kind(k); From 70a6df3962b8448fc9c28d72606828a004ed5b6b Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 24 Aug 2017 11:46:34 +0200 Subject: [PATCH 05/21] tipc/bearer: Prevent NULL pointer dereference Signed-off-by: Phil Sutter --- tipc/bearer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tipc/bearer.c b/tipc/bearer.c index c3d4491f..0d845701 100644 --- a/tipc/bearer.c +++ b/tipc/bearer.c @@ -439,7 +439,7 @@ static int cmd_bearer_enable(struct nlmsghdr *nlh, const struct cmd *cmd, return err; opt = get_opt(opts, "media"); - if (strcmp(opt->val, "udp") == 0) { + if (opt && strcmp(opt->val, "udp") == 0) { err = nl_add_udp_enable_opts(nlh, opts, cmdl); if (err) return err; From 45c2ec9e95fef8eb6f0807d9a7e5f14c14313c7e Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 24 Aug 2017 11:51:45 +0200 Subject: [PATCH 06/21] ipntable: Avoid memory allocation for filter.name The original issue was that filter.name might end up unterminated if user provided string was too long. But in fact it is not necessary to copy the commandline parameter at all: just make filter.name point to it instead. Signed-off-by: Phil Sutter --- ip/ipntable.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ip/ipntable.c b/ip/ipntable.c index 1837909f..88236ce0 100644 --- a/ip/ipntable.c +++ b/ip/ipntable.c @@ -37,7 +37,7 @@ static struct int family; int index; #define NONE_DEV (-1) - char name[1024]; + const char *name; } filter; static void usage(void) __attribute__((noreturn)); @@ -367,7 +367,7 @@ static int print_ntable(const struct sockaddr_nl *who, struct nlmsghdr *n, void if (tb[NDTA_NAME]) { const char *name = rta_getattr_str(tb[NDTA_NAME]); - if (strlen(filter.name) > 0 && strcmp(filter.name, name)) + if (filter.name && strcmp(filter.name, name)) return 0; } if (tb[NDTA_PARMS]) { @@ -631,7 +631,7 @@ static int ipntable_show(int argc, char **argv) } else if (strcmp(*argv, "name") == 0) { NEXT_ARG(); - strncpy(filter.name, *argv, sizeof(filter.name)); + filter.name = *argv; } else invarg("unknown", *argv); From eab450789829e33a64dbd08dced3438d580d5179 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 24 Aug 2017 11:51:46 +0200 Subject: [PATCH 07/21] lib/fs: Fix format string in find_fs_mount() A field width of 4096 allows fscanf() to store that amount of characters into the given buffer, though that doesn't include the terminating NULL byte. Decrease the value by one to leave space for it. Signed-off-by: Phil Sutter --- lib/fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fs.c b/lib/fs.c index c59ac564..1ff881ec 100644 --- a/lib/fs.c +++ b/lib/fs.c @@ -45,7 +45,7 @@ static char *find_fs_mount(const char *fs_to_find) return NULL; } - while (fscanf(fp, "%*s %4096s %127s %*s %*d %*d\n", + while (fscanf(fp, "%*s %4095s %127s %*s %*d %*d\n", path, fstype) == 2) { if (strcmp(fstype, fs_to_find) == 0) { mnt = strdup(path); From cfda500a7d808a6e0f3eca47abd75c22cfe716e5 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 24 Aug 2017 11:51:47 +0200 Subject: [PATCH 08/21] lib/inet_proto: Review inet_proto_{a2n,n2a}() The original intent was to make sure strings written by those functions are NUL-terminated at all times, though it was suggested to get rid of the 15 char protocol name limit as well which this patch accomplishes. In addition to that, simplify inet_proto_a2n() a bit: Use the error checking in get_u8() to find out whether passed 'buf' contains a valid decimal number instead of checking the first character's value manually. Signed-off-by: Phil Sutter --- lib/inet_proto.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/inet_proto.c b/lib/inet_proto.c index ceda082b..53c02903 100644 --- a/lib/inet_proto.c +++ b/lib/inet_proto.c @@ -25,7 +25,7 @@ const char *inet_proto_n2a(int proto, char *buf, int len) { - static char ncache[16]; + static char *ncache; static int icache = -1; struct protoent *pe; @@ -34,9 +34,12 @@ const char *inet_proto_n2a(int proto, char *buf, int len) pe = getprotobynumber(proto); if (pe) { + if (icache != -1) + free(ncache); icache = proto; - strncpy(ncache, pe->p_name, 16); - strncpy(buf, pe->p_name, len); + ncache = strdup(pe->p_name); + strncpy(buf, pe->p_name, len - 1); + buf[len - 1] = '\0'; return buf; } snprintf(buf, len, "ipproto-%d", proto); @@ -45,24 +48,23 @@ const char *inet_proto_n2a(int proto, char *buf, int len) int inet_proto_a2n(const char *buf) { - static char ncache[16]; + static char *ncache; static int icache = -1; struct protoent *pe; + __u8 ret; - if (icache>=0 && strcmp(ncache, buf) == 0) + if (icache != -1 && strcmp(ncache, buf) == 0) return icache; - if (buf[0] >= '0' && buf[0] <= '9') { - __u8 ret; - if (get_u8(&ret, buf, 10)) - return -1; + if (!get_u8(&ret, buf, 10)) return ret; - } pe = getprotobyname(buf); if (pe) { + if (icache != -1) + free(ncache); icache = pe->p_proto; - strncpy(ncache, pe->p_name, 16); + ncache = strdup(pe->p_name); return pe->p_proto; } return -1; From bc27878d21909b110dd21eea0c3505d023f29dc2 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 24 Aug 2017 11:51:48 +0200 Subject: [PATCH 09/21] lnstat_util: Simplify alloc_and_open() a bit Relying upon callers and using unsafe strcpy() is probably not the best idea. Aside from that, using snprintf() allows to format the string for lf->path in one go. Signed-off-by: Phil Sutter --- misc/lnstat_util.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/misc/lnstat_util.c b/misc/lnstat_util.c index cc54598f..ec19238c 100644 --- a/misc/lnstat_util.c +++ b/misc/lnstat_util.c @@ -180,11 +180,8 @@ static struct lnstat_file *alloc_and_open(const char *path, const char *file) } /* initialize */ - /* de->d_name is guaranteed to be <= NAME_MAX */ - strcpy(lf->basename, file); - strcpy(lf->path, path); - strcat(lf->path, "/"); - strcat(lf->path, lf->basename); + snprintf(lf->basename, sizeof(lf->basename), "%s", file); + snprintf(lf->path, sizeof(lf->path), "%s/%s", path, file); /* initialize to default */ lf->interval.tv_sec = 1; From 56270e54661e8ca51d4b3661b9f9bb12a0a40d95 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 24 Aug 2017 11:51:49 +0200 Subject: [PATCH 10/21] tc/m_xt: Fix for potential string buffer overflows - Use strncpy() when writing to target->t->u.user.name and make sure the final byte remains untouched (xtables_calloc() set it to zero). - 'tname' length sanitization was completely wrong: If it's length exceeded the 16 bytes available in 'k', passing a length value of 16 to strncpy() would overwrite the previously NULL'ed 'k[15]'. Also, the sanitization has to happen if 'tname' is exactly 16 bytes long as well. Signed-off-by: Phil Sutter --- tc/m_xt.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tc/m_xt.c b/tc/m_xt.c index ad52d239..9218b145 100644 --- a/tc/m_xt.c +++ b/tc/m_xt.c @@ -95,7 +95,8 @@ build_st(struct xtables_target *target, struct xt_entry_target *t) if (t == NULL) { target->t = xtables_calloc(1, size); target->t->u.target_size = size; - strcpy(target->t->u.user.name, target->name); + strncpy(target->t->u.user.name, target->name, + sizeof(target->t->u.user.name) - 1); target->t->u.user.revision = target->revision; if (target->init != NULL) @@ -277,8 +278,8 @@ static int parse_ipt(struct action_util *a, int *argc_p, } fprintf(stdout, " index %d\n", index); - if (strlen(tname) > 16) { - size = 16; + if (strlen(tname) >= 16) { + size = 15; k[15] = 0; } else { size = 1 + strlen(tname); From 4b9e91782269fc871d158ed4f11bfcfe4e3b8bf7 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 24 Aug 2017 11:51:50 +0200 Subject: [PATCH 11/21] lib/ll_map: Choose size of new cache items at run-time Instead of having a fixed buffer of 16 bytes for the interface name, tailor size of new ll_cache entry using the interface name's actual length. This also makes sure the following call to strcpy() is safe. Signed-off-by: Phil Sutter --- lib/ll_map.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ll_map.c b/lib/ll_map.c index 4e4556c9..70684b02 100644 --- a/lib/ll_map.c +++ b/lib/ll_map.c @@ -30,7 +30,7 @@ struct ll_cache { unsigned flags; unsigned index; unsigned short type; - char name[IFNAMSIZ]; + char name[]; }; #define IDXMAP_SIZE 1024 @@ -120,7 +120,7 @@ int ll_remember_index(const struct sockaddr_nl *who, return 0; } - im = malloc(sizeof(*im)); + im = malloc(sizeof(*im) + strlen(ifname) + 1); if (im == NULL) return 0; im->index = ifi->ifi_index; From 8f478ec2b3dabdc5d667a0de8997c5660e2b118d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 24 Aug 2017 15:00:59 -0700 Subject: [PATCH 12/21] rdma: fix duplicate initialization in port_names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Build with warnings enable spotted this. link.c:51:58: note: (near initialization for ‘rdma_port_names[23]’) rdma_port_names[] = { RDMA_PORT_FLAGS(RDMA_BITMAP_NAMES) }; Assume that fields were in order and 25 is the missing value. Signed-off-by: Stephen Hemminger --- rdma/link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rdma/link.c b/rdma/link.c index eae96cd8..3a4b00bd 100644 --- a/rdma/link.c +++ b/rdma/link.c @@ -42,7 +42,7 @@ static const char *caps_to_str(uint32_t idx) x(CAP_MASK_NOTICE, 22) \ x(BOOT_MGMT, 23) \ x(LINK_LATENCY, 24) \ - x(CLIENT_REG, 23) \ + x(CLIENT_REG, 25) \ x(IP_BASED_GIDS, 26) enum { RDMA_PORT_FLAGS(RDMA_BITMAP_ENUM) }; From 0efa625765b4481e1e474526eb0feda747b720e5 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 24 Aug 2017 15:02:32 -0700 Subject: [PATCH 13/21] libnetlink: drop unused parameter to rtnl_dump_done Signed-off-by: Stephen Hemminger --- lib/libnetlink.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/libnetlink.c b/lib/libnetlink.c index 874e660b..00c85377 100644 --- a/lib/libnetlink.c +++ b/lib/libnetlink.c @@ -354,8 +354,7 @@ int rtnl_dump_request_n(struct rtnl_handle *rth, struct nlmsghdr *n) return sendmsg(rth->fd, &msg, 0); } -static int rtnl_dump_done(const struct rtnl_handle *rth, - struct nlmsghdr *h) +static int rtnl_dump_done(struct nlmsghdr *h) { int len = *(int *)NLMSG_DATA(h); @@ -462,7 +461,7 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth, dump_intr = 1; if (h->nlmsg_type == NLMSG_DONE) { - err = rtnl_dump_done(rth, h); + err = rtnl_dump_done(h); if (err < 0) return -1; From 0b5eadc54f3890db6b5bba10d42c70616714bee8 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 24 Aug 2017 15:02:58 -0700 Subject: [PATCH 14/21] bpf: drop unused parameter to bpf_report_map_in_map Signed-off-by: Stephen Hemminger --- lib/bpf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/bpf.c b/lib/bpf.c index 1dcb261d..09551990 100644 --- a/lib/bpf.c +++ b/lib/bpf.c @@ -1516,7 +1516,7 @@ static int bpf_find_map_id(const struct bpf_elf_ctx *ctx, uint32_t id) return -ENOENT; } -static void bpf_report_map_in_map(int outer_fd, int inner_fd, uint32_t idx) +static void bpf_report_map_in_map(int outer_fd, uint32_t idx) { struct bpf_elf_map outer_map; int ret; @@ -1683,7 +1683,7 @@ static int bpf_maps_attach_all(struct bpf_elf_ctx *ctx) &inner_fd, BPF_ANY); if (ret < 0) { bpf_report_map_in_map(ctx->map_fds[j], - inner_fd, inner_idx); + inner_idx); return ret; } } From 4cbf5224f2b50a24e1873508e7a0f1f81cc81a81 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 24 Aug 2017 11:41:26 +0200 Subject: [PATCH 15/21] ss: Make struct tcpstat fields 'timer' and 'timeout' unsigned Both 'timer' and 'timeout' variables of struct tcpstat are either scanned as unsigned values from /proc/net/tcp{,6} or copied from 'idiag_timer' and 'idiag_expries' fields of struct inet_diag_msg, which itself are unsigned. Therefore they may be unsigned as well, which eliminates the need to check for negative values. Signed-off-by: Phil Sutter --- misc/ss.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/misc/ss.c b/misc/ss.c index c197e075..be498ebe 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -697,8 +697,8 @@ struct dctcpstat { struct tcpstat { struct sockstat ss; - int timer; - int timeout; + unsigned int timer; + unsigned int timeout; int probes; char cong_alg[16]; double rto, ato, rtt, rttvar; @@ -869,13 +869,11 @@ static void sock_addr_print(const char *addr, char *delim, const char *port, sock_addr_print_width(addr_width, addr, delim, serv_width, port, ifname); } -static const char *print_ms_timer(int timeout) +static const char *print_ms_timer(unsigned int timeout) { static char buf[64]; int secs, msecs, minutes; - if (timeout < 0) - timeout = 0; secs = timeout/1000; minutes = secs/60; secs = secs%60; From 0aa03350c00d70edbbdab0662a2d8262be2bb68d Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 24 Aug 2017 11:41:27 +0200 Subject: [PATCH 16/21] ss: Make sure scanned index value to unix_state_map is sane Signed-off-by: Phil Sutter --- misc/ss.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/misc/ss.c b/misc/ss.c index be498ebe..fcc3cf92 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -3148,7 +3148,8 @@ static int unix_show(struct filter *f) if (flags & (1 << 16)) { u->state = SS_LISTEN; - } else { + } else if (u->state > 0 && + u->state <= ARRAY_SIZE(unix_state_map)) { u->state = unix_state_map[u->state-1]; if (u->type == SOCK_DGRAM && u->state == SS_CLOSE && u->rport) u->state = SS_ESTABLISHED; From 92963d136de8c370324716add98888b2ce6e6a94 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 24 Aug 2017 11:41:28 +0200 Subject: [PATCH 17/21] netem/maketable: Check return value of fscanf() Signed-off-by: Phil Sutter --- netem/maketable.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/netem/maketable.c b/netem/maketable.c index ad660e7d..ccb8f0c6 100644 --- a/netem/maketable.c +++ b/netem/maketable.c @@ -38,8 +38,8 @@ readdoubles(FILE *fp, int *number) } for (i=0; i Date: Thu, 24 Aug 2017 11:41:29 +0200 Subject: [PATCH 18/21] lib/bpf: Check return value of write() This is merely to silence the compiler warning. If write to stderr failed, assume that printing an error message will fail as well so don't even try. Signed-off-by: Phil Sutter --- lib/bpf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/bpf.c b/lib/bpf.c index 09551990..0bd0a95e 100644 --- a/lib/bpf.c +++ b/lib/bpf.c @@ -591,7 +591,8 @@ int bpf_trace_pipe(void) ret = read(fd, buff, sizeof(buff) - 1); if (ret > 0) { - write(2, buff, ret); + if (write(STDERR_FILENO, buff, ret) != ret) + return -1; fflush(stderr); } } From ac3415f5c1b1df2d6a4bf770ad52e2e14c09e58e Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 24 Aug 2017 11:41:30 +0200 Subject: [PATCH 19/21] lib/fs: Fix and simplify make_path() Calling stat() before mkdir() is racey: The entry might change in between. Also, the call to stat() seems to exist only to check if the directory exists already. So simply call mkdir() unconditionally and catch only errors other than EEXIST. Signed-off-by: Phil Sutter --- lib/fs.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/lib/fs.c b/lib/fs.c index 1ff881ec..ebe05cd4 100644 --- a/lib/fs.c +++ b/lib/fs.c @@ -102,7 +102,6 @@ out: int make_path(const char *path, mode_t mode) { char *dir, *delim; - struct stat sbuf; int rc = -1; delim = dir = strdup(path); @@ -120,20 +119,11 @@ int make_path(const char *path, mode_t mode) if (delim) *delim = '\0'; - if (stat(dir, &sbuf) != 0) { - if (errno != ENOENT) { - fprintf(stderr, - "stat failed for %s: %s\n", - dir, strerror(errno)); - goto out; - } - - if (mkdir(dir, mode) != 0) { - fprintf(stderr, - "mkdir failed for %s: %s\n", - dir, strerror(errno)); - goto out; - } + rc = mkdir(dir, mode); + if (mkdir(dir, mode) != 0 && errno != EEXIST) { + fprintf(stderr, "mkdir failed for %s: %s\n", + dir, strerror(errno)); + goto out; } if (delim == NULL) From 893deac4c43b57ae49f736ec050724b6de181062 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 24 Aug 2017 11:41:31 +0200 Subject: [PATCH 20/21] lib/libnetlink: Don't pass NULL parameter to memcpy() Both addattr_l() and rta_addattr_l() may be called with NULL data pointer and 0 alen parameters. Avoid calling memcpy() in that case. Signed-off-by: Phil Sutter --- lib/libnetlink.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/libnetlink.c b/lib/libnetlink.c index 00c85377..be7ac865 100644 --- a/lib/libnetlink.c +++ b/lib/libnetlink.c @@ -870,7 +870,8 @@ int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, rta = NLMSG_TAIL(n); rta->rta_type = type; rta->rta_len = len; - memcpy(RTA_DATA(rta), data, alen); + if (alen) + memcpy(RTA_DATA(rta), data, alen); n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); return 0; } @@ -957,7 +958,8 @@ int rta_addattr_l(struct rtattr *rta, int maxlen, int type, subrta = (struct rtattr *)(((char *)rta) + RTA_ALIGN(rta->rta_len)); subrta->rta_type = type; subrta->rta_len = len; - memcpy(RTA_DATA(subrta), data, alen); + if (alen) + memcpy(RTA_DATA(subrta), data, alen); rta->rta_len = NLMSG_ALIGN(rta->rta_len) + RTA_ALIGN(len); return 0; } From c4fc474b889aa17ada813018aae6b20030e9c58e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 24 Aug 2017 15:27:35 -0700 Subject: [PATCH 21/21] tc: use named initializer for default mqprio options Use C99 initializer Signed-off-by: Stephen Hemminger --- tc/q_mqprio.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tc/q_mqprio.c b/tc/q_mqprio.c index fa1022be..d6718fb1 100644 --- a/tc/q_mqprio.c +++ b/tc/q_mqprio.c @@ -34,10 +34,12 @@ static int mqprio_parse_opt(struct qdisc_util *qu, int argc, { int idx; struct tc_mqprio_qopt opt = { - 8, - {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 1, 1, 3, 3, 3, 3}, - 1, - }; + .num_tc = 8, + .prio_tc_map = { 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 1, 1, 3, 3, 3, 3 }, + .hw = 1, + .count = { }, + .offset = { }, + }; while (argc > 0) { idx = 0;