af_packet: bug #2422.

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.
pull/3184/head
Alexander Gozman 8 years ago committed by Eric Leblond
parent 790ef2701a
commit cba41207b3

@ -252,6 +252,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 *);
@ -1155,6 +1158,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;
}
@ -1321,7 +1325,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;
@ -1533,9 +1536,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;
}
@ -1681,8 +1684,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;
@ -1802,19 +1803,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;
@ -1827,7 +1828,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 {
@ -1842,7 +1843,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;
@ -1857,7 +1858,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)
@ -1907,7 +1908,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;
@ -1920,6 +1927,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));
@ -1993,26 +2019,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)

Loading…
Cancel
Save