]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
af_packet: bug #2422.
authorAlexander Gozman <a.gozman@securitycode.ru>
Thu, 18 Jan 2018 09:05:15 +0000 (09:05 +0000)
committerVictor Julien <victor@inliniac.net>
Tue, 30 Jan 2018 09:32:17 +0000 (10:32 +0100)
This commit fixes a leak of mmap'ed ring buffer that was not
unmaped when a socket was closed. In addition, the leak could
break an inline channel on certain configurations.

Also slightly changed AFPCreateSocket():
1. If an interface is not up, it does not try to apply any
   settings to a socket. This reduces a number of error messages
   while an interface is down.
2. Interface is considered active if both IFF_UP and IFF_RUNNING
   are present.

src/source-af-packet.c

index 02e9b0b0d24cbc3a0b64dcf4d4c93a579032328d..f1cfb908ec5da704485503b0dcac657257df2b95 100644 (file)
@@ -264,6 +264,9 @@ typedef struct AFPThreadVars_
     /* IPS output iface */
     char out_iface[AFP_IFACE_NAME_LENGTH];
 
+    /* mmap'ed ring buffer */
+    unsigned int ring_buflen;
+    uint8_t *ring_buf;
 } AFPThreadVars;
 
 TmEcode ReceiveAFP(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
@@ -1167,6 +1170,7 @@ static void AFPSwitchState(AFPThreadVars *ptv, int state)
             /* we need to wait for all packets to return data */
             if (SC_ATOMIC_SUB(ptv->mpeer->sock_usage, 1) == 0) {
                 SCLogInfo("Cleaning socket connected to '%s'", ptv->iface);
+                munmap(ptv->ring_buf, ptv->ring_buflen);
                 close(ptv->socket);
                 ptv->socket = -1;
             }
@@ -1333,7 +1337,6 @@ static int AFPTryReopen(AFPThreadVars *ptv)
 
     ptv->down_count++;
 
-
     /* Don't reconnect till we have packet that did not release data */
     if (SC_ATOMIC_GET(ptv->mpeer->sock_usage) != 0) {
         return -1;
@@ -1545,9 +1548,9 @@ static int AFPGetIfnumByDev(int fd, const char *ifname, int verbose)
     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
 
     if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
-           if (verbose)
-               SCLogError(SC_ERR_AFP_CREATE, "Unable to find iface %s: %s",
-                          ifname, strerror(errno));
+        if (verbose)
+            SCLogError(SC_ERR_AFP_CREATE, "Unable to find iface %s: %s",
+                       ifname, strerror(errno));
         return -1;
     }
 
@@ -1693,8 +1696,6 @@ static int AFPSetupRing(AFPThreadVars *ptv, char *devname)
 {
     int val;
     unsigned int len = sizeof(val), i;
-    unsigned int ring_buflen;
-    uint8_t * ring_buf;
     int order;
     int r, mmap_flag;
 
@@ -1814,19 +1815,19 @@ static int AFPSetupRing(AFPThreadVars *ptv, char *devname)
     /* Allocate the Ring */
 #ifdef HAVE_TPACKET_V3
     if (ptv->flags & AFP_TPACKET_V3) {
-        ring_buflen = ptv->req3.tp_block_nr * ptv->req3.tp_block_size;
+        ptv->ring_buflen = ptv->req3.tp_block_nr * ptv->req3.tp_block_size;
     } else {
 #endif
-        ring_buflen = ptv->req.tp_block_nr * ptv->req.tp_block_size;
+        ptv->ring_buflen = ptv->req.tp_block_nr * ptv->req.tp_block_size;
 #ifdef HAVE_TPACKET_V3
     }
 #endif
     mmap_flag = MAP_SHARED;
     if (ptv->flags & AFP_MMAP_LOCKED)
         mmap_flag |= MAP_LOCKED;
-    ring_buf = mmap(0, ring_buflen, PROT_READ|PROT_WRITE,
+    ptv->ring_buf = mmap(0, ptv->ring_buflen, PROT_READ|PROT_WRITE,
             mmap_flag, ptv->socket, 0);
-    if (ring_buf == MAP_FAILED) {
+    if (ptv->ring_buf == MAP_FAILED) {
         SCLogError(SC_ERR_MEM_ALLOC, "Unable to mmap, error %s",
                    strerror(errno));
         goto mmap_err;
@@ -1839,7 +1840,7 @@ static int AFPSetupRing(AFPThreadVars *ptv, char *devname)
             goto postmmap_err;
         }
         for (i = 0; i < ptv->req3.tp_block_nr; ++i) {
-            ptv->ring_v3[i].iov_base = ring_buf + (i * ptv->req3.tp_block_size);
+            ptv->ring_v3[i].iov_base = ptv->ring_buf + (i * ptv->req3.tp_block_size);
             ptv->ring_v3[i].iov_len = ptv->req3.tp_block_size;
         }
     } else {
@@ -1854,7 +1855,7 @@ static int AFPSetupRing(AFPThreadVars *ptv, char *devname)
         /* fill the header ring with proper frame ptr*/
         ptv->frame_offset = 0;
         for (i = 0; i < ptv->req.tp_block_nr; ++i) {
-            void *base = &ring_buf[i * ptv->req.tp_block_size];
+            void *base = &(ptv->ring_buf[i * ptv->req.tp_block_size]);
             unsigned int j;
             for (j = 0; j < ptv->req.tp_block_size / ptv->req.tp_frame_size; ++j, ++ptv->frame_offset) {
                 (((union thdr **)ptv->ring_v2)[ptv->frame_offset]) = base;
@@ -1869,7 +1870,7 @@ static int AFPSetupRing(AFPThreadVars *ptv, char *devname)
     return 0;
 
 postmmap_err:
-    munmap(ring_buf, ring_buflen);
+    munmap(ptv->ring_buf, ptv->ring_buflen);
     if (ptv->ring_v2)
         SCFree(ptv->ring_v2);
     if (ptv->ring_v3)
@@ -1919,7 +1920,13 @@ static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
         SCLogError(SC_ERR_AFP_CREATE, "Couldn't create a AF_PACKET socket, error %s", strerror(errno));
         goto error;
     }
+
     if_idx = AFPGetIfnumByDev(ptv->socket, devname, verbose);
+
+    if (if_idx == -1) {
+        goto error;
+    }
+
     /* bind socket */
     memset(&bind_address, 0, sizeof(bind_address));
     bind_address.sll_family = AF_PACKET;
@@ -1932,6 +1939,25 @@ static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
         goto socket_err;
     }
 
+    int if_flags = AFPGetDevFlags(ptv->socket, ptv->iface);
+    if (if_flags == -1) {
+        if (verbose) {
+            SCLogError(SC_ERR_AFP_READ,
+                    "Couldn't get flags for interface '%s'",
+                    ptv->iface);
+        }
+        ret = AFP_RECOVERABLE_ERROR;
+        goto socket_err;
+    } else if ((if_flags & (IFF_UP | IFF_RUNNING)) == 0) {
+        if (verbose) {
+            SCLogError(SC_ERR_AFP_READ,
+                    "Interface '%s' is down",
+                    ptv->iface);
+        }
+        ret = AFP_RECOVERABLE_ERROR;
+        goto socket_err;
+    }
+
     if (ptv->promisc != 0) {
         /* Force promiscuous mode */
         memset(&sock_params, 0, sizeof(sock_params));
@@ -2005,26 +2031,6 @@ static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
     }
 #endif
 
-    int if_flags = AFPGetDevFlags(ptv->socket, ptv->iface);
-    if (if_flags == -1) {
-        if (verbose) {
-            SCLogError(SC_ERR_AFP_READ,
-                    "Couldn't get flags for interface '%s'",
-                    ptv->iface);
-        }
-        ret = AFP_RECOVERABLE_ERROR;
-        goto socket_err;
-    }
-    if ((if_flags & IFF_UP) == 0) {
-        if (verbose) {
-            SCLogError(SC_ERR_AFP_READ,
-                    "Interface '%s' is down",
-                    ptv->iface);
-        }
-        ret = AFP_RECOVERABLE_ERROR;
-        goto socket_err;
-    }
-
     if (ptv->flags & AFP_RING_MODE) {
         ret = AFPSetupRing(ptv, devname);
         if (ret != 0)