Arp_antidote port for 2.6 kernel

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
This is a multi-part message in MIME format.
--------------060706020906030006020309
Content-Type: text/plain; charset=ISO-8859-7
Content-Transfer-Encoding: 7bit

Here is a port of the arp_antidote (antidote2) patch for the 2.6.18
linux kernel. The patch is tested and seems to work.

It has been authored by Alexandros Stergiakis as part of the AspisOS
embedded linux distro project.

alex


--------------060706020906030006020309
Content-Type: text/x-patch;
 name="arp_antidote-2.6.18.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="arp_antidote-2.6.18.patch"

diff -N -c -r linux-2.6.18/include/linux/sysctl.h
linux-2.6.18-patched/include/linux/sysctl.h
*** linux-2.6.18/include/linux/sysctl.h    2006-09-20 06:42:06.000000000 +0300
--- linux-2.6.18-patched/include/linux/sysctl.h    2006-09-29 00:38:46.000000000
+0300
***************
*** 574,585 ****
      NET_NEIGH_ANYCAST_DELAY10%,
      NET_NEIGH_PROXY_DELAY11%,
      NET_NEIGH_LOCKTIME12%,
!     NET_NEIGH_GC_INTERVAL13%,
!     NET_NEIGH_GC_THRESH114%,
!     NET_NEIGH_GC_THRESH215%,
!     NET_NEIGH_GC_THRESH316%,
!     NET_NEIGH_RETRANS_TIME_MS17%,
!     NET_NEIGH_REACHABLE_TIME_MS18%,
      __NET_NEIGH_MAX
  };
  
--- 574,586 ----
      NET_NEIGH_ANYCAST_DELAY10%,
      NET_NEIGH_PROXY_DELAY11%,
      NET_NEIGH_LOCKTIME12%,
!     NET_NEIGH_ARP_ANTIDOTE13%,
!     NET_NEIGH_GC_INTERVAL14%,
!     NET_NEIGH_GC_THRESH115%,
!     NET_NEIGH_GC_THRESH216%,
!     NET_NEIGH_GC_THRESH317%,
!     NET_NEIGH_RETRANS_TIME_MS18%,
!     NET_NEIGH_REACHABLE_TIME_MS19%,
      __NET_NEIGH_MAX
  };
  
diff -N -c -r linux-2.6.18/include/net/neighbour.h
linux-2.6.18-patched/include/net/neighbour.h
*** linux-2.6.18/include/net/neighbour.h    2006-09-20 06:42:06.000000000 +0300
--- linux-2.6.18-patched/include/net/neighbour.h    2006-09-29 00:38:46.000000000
+0300
***************
*** 35,40 ****
--- 35,42 ----
  #define NUD_DELAY    0x08
  #define NUD_PROBE    0x10
  #define NUD_FAILED    0x20
+ #define NUD_VERIFY    0x100
+ #define NUD_BANNED    0x200
  
  /* Dummy states */
  #define NUD_NOARP    0x40
***************
*** 57,63 ****
  #include <linux/err.h>
  #include <linux/sysctl.h>
  
! #define NUD_IN_TIMER    (NUD_INCOMPLETE|NUD_REACHABLE|NUD_DELAY|NUD_PROBE)
  #define
NUD_VALID    (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE|NUD_PROBE|NUD_STALE|NUD_DELAY)
  #define NUD_CONNECTED    (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE)
  
--- 59,65 ----
  #include <linux/err.h>
  #include <linux/sysctl.h>
  
! #define
NUD_IN_TIMER    (NUD_INCOMPLETE|NUD_REACHABLE|NUD_DELAY|NUD_PROBE|NUD_VERIFY)
  #define
NUD_VALID    (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE|NUD_PROBE|NUD_STALE|NUD_DELAY)
  #define NUD_CONNECTED    (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE)
  
***************
*** 91,96 ****
--- 93,99 ----
      int    proxy_delay;
      int    proxy_qlen;
      int    locktime;
+     int arp_antidote;
  };
  
  struct neigh_statistics
***************
*** 128,139 ****
      unsigned long        confirmed;
      unsigned long        updated;
      __u8            flags;
!     __u8            nud_state;
      __u8            type;
      __u8            dead;
      atomic_t        probes;
      rwlock_t        lock;
      unsigned char        ha[(MAX_ADDR_LEN+sizeof(unsigned long)-1)&~(sizeof(unsigned
long)-1)];
      struct hh_cache        *hh;
      atomic_t        refcnt;
      int            (*output)(struct sk_buff *skb);
--- 131,143 ----
      unsigned long        confirmed;
      unsigned long        updated;
      __u8            flags;
!     __u16            nud_state;
      __u8            type;
      __u8            dead;
      atomic_t        probes;
      rwlock_t        lock;
      unsigned char        ha[(MAX_ADDR_LEN+sizeof(unsigned long)-1)&~(sizeof(unsigned
long)-1)];
+     unsigned char       twin_ha[(MAX_ADDR_LEN+sizeof(unsigned
long)-1)&~(sizeof(unsigned long)-1)];
      struct hh_cache        *hh;
      atomic_t        refcnt;
      int            (*output)(struct sk_buff *skb);
***************
*** 223,230 ****
                           struct net_device *dev);
  extern void            neigh_destroy(struct neighbour *neigh);
  extern int            __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb);
! extern int            neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
!                          u32 flags);
  extern void            neigh_changeaddr(struct neigh_table *tbl, struct net_device
*dev);
  extern int            neigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
  extern int            neigh_resolve_output(struct sk_buff *skb);
--- 227,233 ----
                           struct net_device *dev);
  extern void            neigh_destroy(struct neighbour *neigh);
  extern int            __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb);
! extern int            neigh_update(struct neighbour *neigh, const u8 *lladdr, u16 new,
u32 flags);
  extern void            neigh_changeaddr(struct neigh_table *tbl, struct net_device
*dev);
  extern int            neigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
  extern int            neigh_resolve_output(struct sk_buff *skb);
diff -N -c -r linux-2.6.18/net/core/neighbour.c
linux-2.6.18-patched/net/core/neighbour.c
*** linux-2.6.18/net/core/neighbour.c    2006-09-20 06:42:06.000000000 +0300
--- linux-2.6.18-patched/net/core/neighbour.c    2006-09-29 00:43:56.000000000 +0300
***************
*** 738,743 ****
--- 738,746 ----
          goto out;
      }
  
+     if(state & NUD_VERIFY)
+         neigh->nud_state=NUD_INCOMPLETE;
+
      if (state & NUD_REACHABLE) {
          if (time_before_eq(now,
                     neigh->confirmed + neigh->parms->reachable_time)) {
***************
*** 839,844 ****
--- 842,852 ----
  
      write_lock_bh(&neigh->lock);
  
+     if(neigh->nud_state & NUD_BANNED){
+         write_unlock_bh(&neigh->lock);
+         return 1;
+     }
+
      rc = 0;
      if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
          goto out_unlock_bh;
***************
*** 848,854 ****
      if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
          if (neigh->parms->mcast_probes + neigh->parms->app_probes) {
              atomic_set(&neigh->probes, neigh->parms->ucast_probes);
!             neigh->nud_state     = NUD_INCOMPLETE;
              neigh->updated = jiffies;
              neigh_hold(neigh);
              neigh_add_timer(neigh, now + 1);
--- 856,863 ----
      if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
          if (neigh->parms->mcast_probes + neigh->parms->app_probes) {
              atomic_set(&neigh->probes, neigh->parms->ucast_probes);
!             if(!(neigh->nud_state & NUD_VERIFY))
!                 neigh->nud_state     = NUD_INCOMPLETE;
              neigh->updated = jiffies;
              neigh_hold(neigh);
              neigh_add_timer(neigh, now + 1);
***************
*** 929,936 ****
  int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
           u32 flags)
  {
!     u8 old;
      int err;
      int notify = 0;
      struct net_device *dev;
      int update_isrouter = 0;
--- 938,946 ----
  int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
           u32 flags)
  {
!     u16 old;
      int err;
+     int t;
      int notify = 0;
      struct net_device *dev;
      int update_isrouter = 0;
***************
*** 942,948 ****
      err    = -EPERM;
  
      if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
!         (old & (NUD_NOARP | NUD_PERMANENT)))
          goto out;
  
      if (!(new & NUD_VALID)) {
--- 952,958 ----
      err    = -EPERM;
  
      if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
!         (old & (NUD_NOARP | NUD_PERMANENT | NUD_BANNED)))
          goto out;
  
      if (!(new & NUD_VALID)) {
***************
*** 965,973 ****
             - compare new & old
             - if they are different, check override flag
           */
!         if ((old & NUD_VALID) &&
!             !memcmp(lladdr, neigh->ha, dev->addr_len))
!             lladdr = neigh->ha;
      } else {
          /* No address is supplied; if we know something,
             use it, otherwise discard the request.
--- 975,1025 ----
             - compare new & old
             - if they are different, check override flag
           */
!         if (old & (NUD_VALID|NUD_VERIFY)) {
!             if (!memcmp(lladdr, neigh->ha, dev->addr_len)) {
!                 lladdr = neigh->ha;
!                 if(neigh->nud_state & NUD_VERIFY){
!                     printk("ARP_ANTIDOTE: possible MITM attempt!\ncached haddr");
!                     for(t=0;t<dev->addr_len;t++)
!                     printk(":%02X",lladdr[t]);
!                     printk(" twin haddr");
!                     for(t=0;t<dev->addr_len;t++)
!                     printk(":%02X",neigh->twin_ha[t]);
!                     printk("\n");
!
!                     if(neigh->parms->arp_antidote==2)
!                     new = NUD_PERMANENT;
!                     if(neigh->parms->arp_antidote==3){
!                         neigh_del_timer(neigh);
!                         neigh_suspect(neigh);
!                         neigh->nud_state=NUD_BANNED;
! #ifdef CONFIG_ARPD
!                         notify = 0;
! #endif
!                         err = 0;
!                         goto out;
!                     }
!                 };
!             }
!             else {
!                 if ((!(flags & NEIGH_UPDATE_F_OVERRIDE)) || (neigh->nud_state==NUD_VERIFY))
!                     goto out;
!                 /* If address changed and antidote enabled and arp != 0
!                    change state to VERIFY to test if old address still valid */
!                 if((!(flags & NEIGH_UPDATE_F_ADMIN)) && neigh->parms->arp_antidote){
!                     neigh_del_timer(neigh);
!                     if (old&NUD_CONNECTED)
!                         neigh_suspect(neigh);
!                     err = 0;
! #ifdef CONFIG_ARPD
!                     notify = old&NUD_VALID;
! #endif
!                     neigh->nud_state = NUD_VERIFY;
!                     memcpy(&neigh->twin_ha, lladdr, dev->addr_len);
!                     goto out;
!                 }
!             }
!         }
      } else {
          /* No address is supplied; if we know something,
             use it, otherwise discard the request.
***************
*** 2476,2481 ****
--- 2528,2540 ----
              .proc_handler    = &proc_dointvec_userhz_jiffies,
          },
          {
+             .ctl_name    = NET_NEIGH_ARP_ANTIDOTE,
+             .procname    = "arp_antidote",
+             .maxlen        = sizeof(int),
+             .mode        = 0644,
+             .proc_handler    = &proc_dointvec,
+         },
+         {
              .ctl_name    = NET_NEIGH_GC_INTERVAL,
              .procname    = "gc_interval",
              .maxlen        = sizeof(int),
***************
*** 2572,2595 ****
      t->neigh_vars[9].data  = &p->anycast_delay;
      t->neigh_vars[10].data = &p->proxy_delay;
      t->neigh_vars[11].data = &p->locktime;
  
      if (dev) {
          dev_name_source = dev->name;
          t->neigh_dev[0].ctl_name = dev->ifindex;
-         t->neigh_vars[12].procname = NULL;
          t->neigh_vars[13].procname = NULL;
          t->neigh_vars[14].procname = NULL;
          t->neigh_vars[15].procname = NULL;
      } else {
           dev_name_source = t->neigh_dev[0].procname;
!         t->neigh_vars[12].data = (int *)(p + 1);
!         t->neigh_vars[13].data = (int *)(p + 1) + 1;
!         t->neigh_vars[14].data = (int *)(p + 1) + 2;
!         t->neigh_vars[15].data = (int *)(p + 1) + 3;
      }
  
!     t->neigh_vars[16].data  = &p->retrans_time;
!     t->neigh_vars[17].data  = &p->base_reachable_time;
  
      if (handler || strategy) {
          /* RetransTime */
--- 2631,2655 ----
      t->neigh_vars[9].data  = &p->anycast_delay;
      t->neigh_vars[10].data = &p->proxy_delay;
      t->neigh_vars[11].data = &p->locktime;
+     t->neigh_vars[12].data = &p->arp_antidote;
  
      if (dev) {
          dev_name_source = dev->name;
          t->neigh_dev[0].ctl_name = dev->ifindex;
          t->neigh_vars[13].procname = NULL;
          t->neigh_vars[14].procname = NULL;
          t->neigh_vars[15].procname = NULL;
+         t->neigh_vars[16].procname = NULL;
      } else {
           dev_name_source = t->neigh_dev[0].procname;
!         t->neigh_vars[13].data = (int *)(p + 1);
!         t->neigh_vars[14].data = (int *)(p + 1) + 1;
!         t->neigh_vars[15].data = (int *)(p + 1) + 2;
!         t->neigh_vars[16].data = (int *)(p + 1) + 3;
      }
  
!     t->neigh_vars[17].data  = &p->retrans_time;
!     t->neigh_vars[18].data  = &p->base_reachable_time;
  
      if (handler || strategy) {
          /* RetransTime */
***************
*** 2601,2613 ****
          t->neigh_vars[4].strategy = strategy;
          t->neigh_vars[4].extra1 = dev;
          /* RetransTime (in milliseconds)*/
-         t->neigh_vars[16].proc_handler = handler;
-         t->neigh_vars[16].strategy = strategy;
-         t->neigh_vars[16].extra1 = dev;
-         /* ReachableTime (in milliseconds) */
          t->neigh_vars[17].proc_handler = handler;
          t->neigh_vars[17].strategy = strategy;
          t->neigh_vars[17].extra1 = dev;
      }
  
      dev_name = kstrdup(dev_name_source, GFP_KERNEL);
--- 2661,2673 ----
          t->neigh_vars[4].strategy = strategy;
          t->neigh_vars[4].extra1 = dev;
          /* RetransTime (in milliseconds)*/
          t->neigh_vars[17].proc_handler = handler;
          t->neigh_vars[17].strategy = strategy;
          t->neigh_vars[17].extra1 = dev;
+         /* ReachableTime (in milliseconds) */
+         t->neigh_vars[18].proc_handler = handler;
+         t->neigh_vars[18].strategy = strategy;
+         t->neigh_vars[18].extra1 = dev;
      }
  
      dev_name = kstrdup(dev_name_source, GFP_KERNEL);

--------------060706020906030006020309--

Re: Arp_antidote port for 2.6 kernel
References:
  http://www.securityfocus.com/archive/1/299929
  http://www.aspisos.org

alex

Site Timeline