Tue Jul 10 01:23:13 2018 UTC ()
Don't overwrite an existing llentry on RTM_ADD to avoid race conditions

Reported and tested by christos@


(ozaki-r)
diff -r1.27 -r1.28 src/sys/net/if_llatbl.c

cvs diff -r1.27 -r1.28 src/sys/net/if_llatbl.c (expand / switch to unified diff)

--- src/sys/net/if_llatbl.c 2018/06/05 01:25:59 1.27
+++ src/sys/net/if_llatbl.c 2018/07/10 01:23:13 1.28
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if_llatbl.c,v 1.27 2018/06/05 01:25:59 nonaka Exp $ */ 1/* $NetBSD: if_llatbl.c,v 1.28 2018/07/10 01:23:13 ozaki-r Exp $ */
2/* 2/*
3 * Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved. 3 * Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved.
4 * Copyright (c) 2004-2008 Qing Li. All rights reserved. 4 * Copyright (c) 2004-2008 Qing Li. All rights reserved.
5 * Copyright (c) 2008 Kip Macy. All rights reserved. 5 * Copyright (c) 2008 Kip Macy. All rights reserved.
6 * Copyright (c) 2015 The NetBSD Foundation, Inc. 6 * Copyright (c) 2015 The NetBSD Foundation, Inc.
7 * All rights reserved. 7 * All rights reserved.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -662,40 +662,50 @@ lla_rt_output(const u_char rtm_type, con @@ -662,40 +662,50 @@ lla_rt_output(const u_char rtm_type, con
662 KASSERTMSG(llt != NULL, "Yep, ugly hacks are bad"); 662 KASSERTMSG(llt != NULL, "Yep, ugly hacks are bad");
663 663
664 error = 0; 664 error = 0;
665 665
666 switch (rtm_type) { 666 switch (rtm_type) {
667 case RTM_ADD: { 667 case RTM_ADD: {
668 struct rtentry *rt; 668 struct rtentry *rt;
669 669
670 /* Never call rtalloc1 with IF_AFDATA_WLOCK */ 670 /* Never call rtalloc1 with IF_AFDATA_WLOCK */
671 rt = rtalloc1(dst, 0); 671 rt = rtalloc1(dst, 0);
672 672
673 /* Add static LLE */ 673 /* Add static LLE */
674 IF_AFDATA_WLOCK(ifp); 674 IF_AFDATA_WLOCK(ifp);
675 lle = lla_lookup(llt, 0, dst); 675 lle = lla_lookup(llt, LLE_EXCLUSIVE, dst);
676 676
677 /* Cannot overwrite an existing static entry */ 677 /* Cannot overwrite an existing static entry */
678 if (lle != NULL && 678 if (lle != NULL &&
679 (lle->la_flags & LLE_STATIC || lle->la_expire == 0)) { 679 (lle->la_flags & LLE_STATIC || lle->la_expire == 0)) {
680 LLE_RUNLOCK(lle); 680 LLE_RUNLOCK(lle);
681 IF_AFDATA_WUNLOCK(ifp); 681 IF_AFDATA_WUNLOCK(ifp);
682 if (rt != NULL) 682 if (rt != NULL)
683 rt_unref(rt); 683 rt_unref(rt);
684 error = EEXIST; 684 error = EEXIST;
685 goto out; 685 goto out;
686 } 686 }
687 if (lle != NULL) 687
688 LLE_RUNLOCK(lle); 688 /*
 689 * We can't overwrite an existing entry to avoid race
 690 * conditions so remove it first.
 691 */
 692 if (lle != NULL) {
 693 size_t pkts_dropped = llentry_free(lle);
 694 if (dst->sa_family == AF_INET) {
 695 arp_stat_add(ARP_STAT_DFRDROPPED,
 696 (uint64_t)pkts_dropped);
 697 }
 698 }
689 699
690 lle = lla_create(llt, 0, dst, rt); 700 lle = lla_create(llt, 0, dst, rt);
691 if (lle == NULL) { 701 if (lle == NULL) {
692 IF_AFDATA_WUNLOCK(ifp); 702 IF_AFDATA_WUNLOCK(ifp);
693 if (rt != NULL) 703 if (rt != NULL)
694 rt_unref(rt); 704 rt_unref(rt);
695 error = ENOMEM; 705 error = ENOMEM;
696 goto out; 706 goto out;
697 } 707 }
698 708
699 KASSERT(ifp->if_addrlen <= sizeof(lle->ll_addr)); 709 KASSERT(ifp->if_addrlen <= sizeof(lle->ll_addr));
700 memcpy(&lle->ll_addr, CLLADDR(dl), ifp->if_addrlen); 710 memcpy(&lle->ll_addr, CLLADDR(dl), ifp->if_addrlen);
701 if ((rtm_flags & RTF_ANNOUNCE)) 711 if ((rtm_flags & RTF_ANNOUNCE))