lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <4e0db5bc0907130939k48b16256j8f60c786a7e5e44c@mail.gmail.com>
Date:	Mon, 13 Jul 2009 09:39:56 -0700
From:	Gautam Kachroo <gk@...stanetworks.com>
To:	netdev@...r.kernel.org
Subject: [PATCH] iproute2 flush: handle larger tables and deleted entries

use a new netlink socket when sending flush messages to avoid reading
any pending data on the existing netlink socket.

read all of the response from the netlink request -- this response can
be split over multiple recv calls, pretty much one per netlink request
message. ENOENT errors, which correspond to attempts to delete an
already deleted entry, are ignored. Other errors are not ignored.

Signed-off-by: Gautam Kachroo <gk@...stanetworks.com>
---

resending in plain text format

rtnl_send_check calls recv after sending the delete messages. It does
this to catch errors, e.g. user doesn't have permissions to send
netlink messages. It treats *any* response as an error, even if the
message is not an NLMSG_ERROR. However, this doesn't work if the dump
is in the middle of being processed. recv will return the next chunk
of the dump. This was causing the flush operation to bail early, e.g.
when there is a large arp cache.

Ignoring ENOENT lets flush succeed even if entries have been deleted
from underneath the flush.


--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -111,7 +111,10 @@ int rtnl_send(struct rtnl_handle *rth, const char
*buf, int len)
        return send(rth->fd, buf, len, 0);
 }

-int rtnl_send_check(struct rtnl_handle *rth, const char *buf, int len)
+/* send the message in buf using the socket in rth and check for errors
+   (ignoring ENOENT errors)
+*/
+int rtnl_send_check_impl(struct rtnl_handle *rth, const char *buf, int len)
 {
        struct nlmsghdr *h;
        int status;
@@ -122,28 +125,51 @@ int rtnl_send_check(struct rtnl_handle *rth,
const char *buf, int len)
                return status;

        /* Check for errors */
-       status = recv(rth->fd, resp, sizeof(resp), MSG_DONTWAIT);
-       if (status < 0) {
-               if (errno == EAGAIN)
-                       return 0;
-               return -1;
-       }
+       for (;;) {
+               status = recv(rth->fd, resp, sizeof(resp), MSG_DONTWAIT);
+               if (status < 0) {
+                       if (errno == EAGAIN)
+                               return 0;
+                       return -1;
+               }

-       for (h = (struct nlmsghdr *)resp; NLMSG_OK(h, status);
-            h = NLMSG_NEXT(h, status)) {
-               if (h->nlmsg_type == NLMSG_ERROR) {
-                       struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
-                       if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct
nlmsgerr)))
-                               fprintf(stderr, "ERROR truncated\n");
-                       else
-                               errno = -err->error;
+               for (h = (struct nlmsghdr *)resp; NLMSG_OK(h, status);
+                    h = NLMSG_NEXT(h, status)) {
+                       if (h->nlmsg_type == NLMSG_ERROR) {
+                               struct nlmsgerr *err = (struct
nlmsgerr*)NLMSG_DATA(h);
+                               if (h->nlmsg_len <
NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
+                                       fprintf(stderr, "ERROR truncated\n");
+                                       return -1;
+                               }
+                               else {
+                                       if (err->error != -ENOENT) {
+                                               errno = -err->error;
+                                               return -1;
+                                       }
+                               }
+                       }
                }
-               return -1;
        }

        return 0;
 }

+/* creates a netlink socket and passes it to rtnl_send_check_impl to send the
+   message in buf
+*/
+int rtnl_send_check(struct rtnl_handle *unused, const char *buf, int len)
+{
+       struct rtnl_handle rth = { .fd = -1 };
+       int ret;
+       if (rtnl_open(&rth, 0) < 0) {
+               fprintf(stderr, "Cannot open rtnetlink\n");
+               return -1;
+       }
+       ret = rtnl_send_check_impl(&rth, buf, len);
+       rtnl_close(&rth);
+       return ret;
+}
+
 int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len)
 {
        struct nlmsghdr nlh;
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ