]> git.proxmox.com Git - mirror_iproute2.git/commitdiff
libnetlink.c, ss.c: properly handle fread() errors
authorMichał Łyszczek <michal.lyszczek@bofc.pl>
Tue, 29 Oct 2019 11:13:11 +0000 (12:13 +0100)
committerStephen Hemminger <stephen@networkplumber.org>
Fri, 1 Nov 2019 16:05:41 +0000 (09:05 -0700)
fread(3) returns size_t data type which is unsigned, thus check
`if (fread(...) < 0)' is always false. To check if fread(3) has
failed, user should check error indicator with ferror(3).

This commit also changes read logic a little bit by being less
forgiving for errors. Previous logic was checking if fread(3)
read *at least* required ammount of data, now code checks if
fread(3) read *exactly* expected ammount of data. This makes
sense because code parses very specific binary file, and reading
even 1 less/more byte than expected, will later corrupt data anyway.

Signed-off-by: Michał Łyszczek <michal.lyszczek@bofc.pl>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
lib/libnetlink.c
misc/ss.c

index 6ce8b199f4419e55441532d6d25fb5a074b114e1..e02d6294b02e6ea29b2a079fa6702b16b0412e02 100644 (file)
@@ -1174,7 +1174,7 @@ int rtnl_listen(struct rtnl_handle *rtnl,
 int rtnl_from_file(FILE *rtnl, rtnl_listen_filter_t handler,
                   void *jarg)
 {
-       int status;
+       size_t status;
        char buf[16384];
        struct nlmsghdr *h = (struct nlmsghdr *)buf;
 
@@ -1184,14 +1184,15 @@ int rtnl_from_file(FILE *rtnl, rtnl_listen_filter_t handler,
 
                status = fread(&buf, 1, sizeof(*h), rtnl);
 
-               if (status < 0) {
-                       if (errno == EINTR)
-                               continue;
-                       perror("rtnl_from_file: fread");
+               if (status == 0 && feof(rtnl))
+                       return 0;
+               if (status != sizeof(*h)) {
+                       if (ferror(rtnl))
+                               perror("rtnl_from_file: fread");
+                       if (feof(rtnl))
+                               fprintf(stderr, "rtnl-from_file: truncated message\n");
                        return -1;
                }
-               if (status == 0)
-                       return 0;
 
                len = h->nlmsg_len;
                l = len - sizeof(*h);
@@ -1204,12 +1205,11 @@ int rtnl_from_file(FILE *rtnl, rtnl_listen_filter_t handler,
 
                status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl);
 
-               if (status < 0) {
-                       perror("rtnl_from_file: fread");
-                       return -1;
-               }
-               if (status < l) {
-                       fprintf(stderr, "rtnl-from_file: truncated message\n");
+               if (status != NLMSG_ALIGN(l)) {
+                       if (ferror(rtnl))
+                               perror("rtnl_from_file: fread");
+                       if (feof(rtnl))
+                               fprintf(stderr, "rtnl-from_file: truncated message\n");
                        return -1;
                }
 
index 363b4c8d87cd36f8b112a37156e68992d9f0a39c..efa8778160e3fda91daeab782fe071f1d065ac61 100644 (file)
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -3329,28 +3329,28 @@ static int tcp_show_netlink_file(struct filter *f)
        }
 
        while (1) {
-               int status, err2;
+               int err2;
+               size_t status, nitems;
                struct nlmsghdr *h = (struct nlmsghdr *)buf;
                struct sockstat s = {};
 
                status = fread(buf, 1, sizeof(*h), fp);
-               if (status < 0) {
-                       perror("Reading header from $TCPDIAG_FILE");
-                       break;
-               }
                if (status != sizeof(*h)) {
-                       perror("Unexpected EOF reading $TCPDIAG_FILE");
+                       if (ferror(fp))
+                               perror("Reading header from $TCPDIAG_FILE");
+                       if (feof(fp))
+                               fprintf(stderr, "Unexpected EOF reading $TCPDIAG_FILE");
                        break;
                }
 
-               status = fread(h+1, 1, NLMSG_ALIGN(h->nlmsg_len-sizeof(*h)), fp);
+               nitems = NLMSG_ALIGN(h->nlmsg_len - sizeof(*h));
+               status = fread(h+1, 1, nitems, fp);
 
-               if (status < 0) {
-                       perror("Reading $TCPDIAG_FILE");
-                       break;
-               }
-               if (status + sizeof(*h) < h->nlmsg_len) {
-                       perror("Unexpected EOF reading $TCPDIAG_FILE");
+               if (status != nitems) {
+                       if (ferror(fp))
+                               perror("Reading $TCPDIAG_FILE");
+                       if (feof(fp))
+                               fprintf(stderr, "Unexpected EOF reading $TCPDIAG_FILE");
                        break;
                }