Snort 2.9.2.3 pkg v. 2.4.2: ioctl() DIOCRADDADDRS issue



  • Recently, several messages were posted about snort crashing due to an ioctl() error. Maybe it worthwile to give this issue its own threat. So far I haven't found a patch, but I'd like to post what I've found so far.

    DIOCRADDADDRS is a command for ioctl() that is used to add addresses to a table, which looks like an elementary operation. The fatal error message seems to come from the spoink/snort2c package where the function s2c_pf_block() is defined. It looks as if the snort package of pfsense is custom made, with the side effect that someone with a lot of knowledge most likely has to fix this issue.

    With some luck, DIOCRADDADDRS is not the problem, but the struct pfioc_table io contains bogus data such that ioctl(dev, DIOCRADDADDRS, &io) fails (but I haven't found the source lines yet which could be responsible for this). Comments are welcome.



  • To help track this down. I'm having issues with 2.1.. Is anyone having issues with 2.0.x?

    I'm starting to think this could be a core issue with 2.1 since miniupnpd is having a similar issue also (ioctl(dev, DIOCCHANGERULE,), where it can't add IPs to the pf table.. I could be totally wrong but wanted to throw that out there.



  • Cino,

    I am using pfSense 2.0.1-RELEASE (i386).



  • scratch that idea out… then I'm thinking its with the pf patch that is needed for snort to add IPs to the snort2c table or snort's binaries itself.

    strange, its hit and miss with my setup. Sometimes snort dies, other times it blocks correctly.. its 50/50 so far.. But I dont get a lot of alerts since tuning the alerts.



  • Cino,

    it is still possible that a tiny change in one of the php scripts could be responsible to ultimately feed ioctl() with bogus data. As far as I remember, Snort 2.9.0.x worked fine for me on pfSense 2.0.1.



  • Snort itself cannot be responsible, as there is no call to ioctl() using the DIOCRADDADDRS command.



  • @Fesoj:

    Snort itself cannot be responsible, as there is no call to ioctl() using the DIOCRADDADDRS command.

    I may be way off on this. But is this related to the Cron job that removes the blocked ip's after a set time. Cron runs this command /usr/bin/nice -n20 /usr/local/sbin/expiretable -t 3600 snort2c  expiretables ->  uses ioctl_helpers.c

    /* $Id: ioctl_helpers.c,v 1.1 2005/08/18 19:39:55 jeb-c4 Exp $ */

    /*

    • Copyright © 2005 Henrik Gustafsson henrik.gustafsson@fnord.se*
    • Permission to use, copy, modify, and distribute this software for any
    • purpose with or without fee is hereby granted, provided that the above
    • copyright notice and this permission notice appear in all copies.
    • THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    • WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    • MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    • ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    • WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    • ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    • OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      */

    #include "ioctl_helpers.h"
    #include <sys ioctl.h="">#include <stdlib.h>#include <string.h>int
    radix_ioctl(int dev, unsigned long request, struct pfioc_table *pt) {
    void *inbuf, *newinbuf;
    size_t len = 0;
    inbuf = newinbuf = NULL;

    for(;;) {
    pt->pfrio_size = len;
    if (len) {
    newinbuf = realloc(inbuf, len * pt->pfrio_esize);
    if (newinbuf == NULL) {
    if (inbuf != NULL) {
    free(inbuf);
    inbuf = newinbuf = NULL;
    return (-1);
    }
    }
    pt->pfrio_buffer = newinbuf;
    }
    if (ioctl(dev, request, pt) < 0) {
    if (inbuf != NULL) {
    free(inbuf);
    inbuf = newinbuf = NULL;
    }
    return (-1);
    }
    if (pt->pfrio_size + 1 < len)
    break;
    if (pt->pfrio_size == 0)
    return (0);
    if (len == 0)
    len = pt->pfrio_size;
    len *= 2;
    }

    return pt->pfrio_size;
    }

    int
    radix_get_astats(int dev, struct pfr_astats **astats, const struct pfr_table *filter, int flags) {
    struct pfioc_table pt;

    memset(&pt, 0, sizeof(struct pfioc_table));
    pt.pfrio_esize = sizeof(struct pfr_astats);
    pt.pfrio_flags = flags;

    if (filter != NULL) {
    pt.pfrio_table = filter;
    pt.pfrio_table.pfrt_flags = 0; /
    No flags are allowed in this context */
    }

    if (radix_ioctl(dev, DIOCRGETASTATS, &pt) < 0)
    return (-1);

    *astats = (struct pfr_astats *)pt.pfrio_buffer;
    return pt.pfrio_size;
    }

    int
    radix_del_addrs(int dev, const struct pfr_table *table, struct pfr_addr *addrs, int addr_count, int flags) {
    struct pfioc_table pt;

    memset(&pt, 0, sizeof(struct pfioc_table));
    pt.pfrio_size = addr_count;
    pt.pfrio_esize = sizeof(struct pfr_addr);
    pt.pfrio_flags = flags;

    pt.pfrio_table = *table;
    pt.pfrio_buffer = addrs;

    if (ioctl(dev, DIOCRDELADDRS, &pt) < 0) {
    return (-1);
    }
    else {
    return pt.pfrio_ndel;
    }
    }

    int
    radix_get_tables(int dev, struct pfr_table **tables, const struct pfr_table *filter, int flags) {
    struct pfioc_table pt;

    memset(&pt, 0, sizeof(struct pfioc_table));
    pt.pfrio_esize = sizeof(struct pfr_table);
    pt.pfrio_flags = flags;
    if (filter != NULL)
    pt.pfrio_table = *filter;

    if (radix_ioctl(dev, DIOCRGETTABLES, &pt) < 0)
    return (-1);

    *tables = (struct pfr_table *)pt.pfrio_buffer;
    return pt.pfrio_size;
    }

    int
    radix_get_tstats(int dev, struct pfr_tstats **tstats, const struct pfr_table *filter, int flags) {
    struct pfioc_table pt;

    memset(&pt, 0, sizeof(struct pfioc_table));
    pt.pfrio_esize = sizeof(struct pfr_tstats);
    pt.pfrio_flags = flags;
    if (filter != NULL)
    pt.pfrio_table = *filter;

    if (radix_ioctl(dev, DIOCRGETTSTATS, &pt) < 0)
    return (-1);

    *tstats = (struct pfr_tstats *)pt.pfrio_buffer;
    return pt.pfrio_size;
    }

    int
    get_states(int dev, struct pf_state **states) {
    struct pfioc_states ps;
    caddr_t inbuf, newinbuf;
    size_t len = 0;

    inbuf = newinbuf = NULL;
    memset(&ps, 0, sizeof(struct pfioc_states));
    states = NULL;
    for (;;) {
    ps.ps_len = len;
    if (len) {
    newinbuf = realloc(inbuf, len);
    if (newinbuf == NULL) {
    if (inbuf != NULL) {
    free(inbuf);
    inbuf = newinbuf = NULL;
    return (-1);
    }
    }
    ps.ps_buf = inbuf = newinbuf;
    }
    if (ioctl(dev, DIOCGETSTATES, &ps) < 0) {
    if (inbuf != NULL) {
    free(inbuf);
    inbuf = newinbuf = NULL;
    }
    return (-1);
    }
    if (ps.ps_len + sizeof(struct pfioc_states) < len)
    break; /
    We have states! /
    if (ps.ps_len == 0)
    return (0); /
    No states available */
    if (len == 0)
    len = ps.ps_len;
    len *= 2;
    }

    *states = ps.ps_states;
    return ps.ps_len / sizeof(struct pf_state);
    }</string.h></stdlib.h></sys>/henrik.gustafsson@fnord.se



  • Just reinstall snort and it should be behaving better in this regard.


Log in to reply