Re: bpfilter_create kassert panic

2016-07-24 Thread Martin Natano
On Sun, Jul 24, 2016 at 09:31:08AM -0400, Ted Unangst wrote:
> Alexander Bluhm wrote:
> > Hi,
> > 
> > When running some scapy regression tests, a current i386 machine
> > triggered this panic.
> 
> dunno if this is best. maybe. the refcounting of units implies that they can
> last longer than close(). therefore, if open() is expecting close() to remove
> the unit from the list, we must make sure close does that. dangling refs then
> will be freed when the refcount drops.
> 
> The bpfilter_destory function is obfuscation at this point.
> 
> Alas, no time to test right now.

I completely missed that bpf devices can hang around after close. With
that in mind your diff makes sense to me. I think it would be wise to
remove the dependency from bpfdetach() on the bpf_d_list, as it is not
actually required since the introduction of bd_unit, to make sure the
early LIST_REMOVE() doesn't produce any side-effects. See updated diff
below.

Alexander, could you verify this fixes the panic on your i386 machine?

natano


Index: net/bpf.c
===
RCS file: /cvs/src/sys/net/bpf.c,v
retrieving revision 1.142
diff -u -p -r1.142 bpf.c
--- net/bpf.c   10 Jun 2016 20:33:29 -  1.142
+++ net/bpf.c   24 Jul 2016 16:30:30 -
@@ -117,7 +117,6 @@ int bpf_sysctl_locked(int *, u_int, void
 
 struct bpf_d *bpfilter_lookup(int);
 struct bpf_d *bpfilter_create(int);
-void bpfilter_destroy(struct bpf_d *);
 
 /*
  * Reference count access to descriptor buffers
@@ -368,6 +367,7 @@ bpfclose(dev_t dev, int flag, int mode, 
if (d->bd_bif)
bpf_detachd(d);
bpf_wakeup(d);
+   LIST_REMOVE(d, bd_list);
D_PUT(d);
splx(s);
 
@@ -1494,7 +1494,7 @@ bpf_freed(struct bpf_d *d)
srp_update_locked(_insn_gc, >bd_rfilter, NULL);
srp_update_locked(_insn_gc, >bd_wfilter, NULL);
 
-   bpfilter_destroy(d);
+   free(d, M_DEVBUF, sizeof(*d));
 }
 
 /*
@@ -1548,20 +1548,8 @@ bpfdetach(struct ifnet *ifp)
if (cdevsw[maj].d_open == bpfopen)
break;
 
-   while ((bd = SRPL_FIRST_LOCKED(>bif_dlist))) {
-   struct bpf_d *d;
-
-   /*
-* Locate the minor number and nuke the vnode
-* for any open instance.
-*/
-   LIST_FOREACH(d, _d_list, bd_list)
-   if (d == bd) {
-   vdevgone(maj, d->bd_unit,
-   d->bd_unit, VCHR);
-   break;
-   }
-   }
+   while ((bd = SRPL_FIRST_LOCKED(>bif_dlist)))
+   vdevgone(maj, bd->bd_unit, bd->bd_unit, VCHR);
 
free(bp, M_DEVBUF, sizeof *bp);
} else
@@ -1649,13 +1637,6 @@ bpfilter_create(int unit)
LIST_INSERT_HEAD(_d_list, bd, bd_list);
}
return (bd);
-}
-
-void
-bpfilter_destroy(struct bpf_d *bd)
-{
-   LIST_REMOVE(bd, bd_list);
-   free(bd, M_DEVBUF, sizeof(*bd));
 }
 
 /*



Re: bpfilter_create kassert panic

2016-07-24 Thread Ted Unangst
Alexander Bluhm wrote:
> Hi,
> 
> When running some scapy regression tests, a current i386 machine
> triggered this panic.

dunno if this is best. maybe. the refcounting of units implies that they can
last longer than close(). therefore, if open() is expecting close() to remove
the unit from the list, we must make sure close does that. dangling refs then
will be freed when the refcount drops.

The bpfilter_destory function is obfuscation at this point.

Alas, no time to test right now.

Index: bpf.c
===
RCS file: /cvs/src/sys/net/bpf.c,v
retrieving revision 1.142
diff -u -p -r1.142 bpf.c
--- bpf.c   10 Jun 2016 20:33:29 -  1.142
+++ bpf.c   24 Jul 2016 13:30:29 -
@@ -117,7 +117,6 @@ int bpf_sysctl_locked(int *, u_int, void
 
 struct bpf_d *bpfilter_lookup(int);
 struct bpf_d *bpfilter_create(int);
-void bpfilter_destroy(struct bpf_d *);
 
 /*
  * Reference count access to descriptor buffers
@@ -368,6 +367,7 @@ bpfclose(dev_t dev, int flag, int mode, 
if (d->bd_bif)
bpf_detachd(d);
bpf_wakeup(d);
+   LIST_REMOVE(d, bd_list);
D_PUT(d);
splx(s);
 
@@ -1494,7 +1494,7 @@ bpf_freed(struct bpf_d *d)
srp_update_locked(_insn_gc, >bd_rfilter, NULL);
srp_update_locked(_insn_gc, >bd_wfilter, NULL);
 
-   bpfilter_destroy(d);
+   free(d, M_DEVBUF, sizeof(*d));
 }
 
 /*
@@ -1651,12 +1651,6 @@ bpfilter_create(int unit)
return (bd);
 }
 
-void
-bpfilter_destroy(struct bpf_d *bd)
-{
-   LIST_REMOVE(bd, bd_list);
-   free(bd, M_DEVBUF, sizeof(*bd));
-}
 
 /*
  * Get a list of available data link type of the interface.



bpfilter_create kassert panic

2016-07-24 Thread Alexander Bluhm
Hi,

When running some scapy regression tests, a current i386 machine
triggered this panic.

bluhm

panic: kernel diagnostic assertion "bpfilter_lookup(unit) == NULL" failed: file 
"../../../../net/bpf.c", line 1645
Stopped at  Debugger+0x7:   leave
   TIDPIDUID PRFLAGS PFLAGS  CPU  COMMAND
*18583  18583  0 0x2  01  python2.7
 39680  39680  0 0x14000  0x2102  softnet
Debugger(d0a01fd4,f570cb98,d09dca30,f570cb98,20) at Debugger+0x7
panic(d09dca30,d0959766,d09e37dc,d09e37fa,66d) at panic+0x71
__assert(d0959766,d09e37fa,66d,d09e37dc,db60f7c0) at __assert+0x2e
bpfilter_create(200,3f8,f570cc5c,db529af4,db6f0cec) at bpfilter_create+0x8b
bpfopen(21700,2,2000,db6f0cec,f570ce48) at bpfopen+0x29
spec_open_clone(f570ccb8,2180,0,0,db6f0cec) at spec_open_clone+0x158
spec_open(f570ccb8,48,f570ccd8,f570ccd4,5d568c47) at spec_open+0x1c3
VOP_OPEN(db529af4,2,db7ee960,db6f0cec,dad6d424) at VOP_OPEN+0x3f
vn_open(f570ce48,2,0,0,ff9c) at vn_open+0x16b
doopenat(db6f0cec,ff9c,cf7cbe68,1,0) at doopenat+0x176
sys_open(db6f0cec,f570cf5c,f570cf7c,0,f570cfa8) at sys_open+0x37
syscall() at syscall+0x24c
--- syscall (number 1) ---
0x7:
http://www.openbsd.org/ddb.html describes the minimum info required in bug
reports.  Insufficient info makes it difficult to find and fix bugs.

ddb{1}> show register
ds  0x10
es  0x10
fs  0x20clean_idt
gs 0
edi0x100clean_idt+0xe0
esi   0xd09dca30__func__.6218+0x27d
ebp   0xf570cb4c
ebx   0xf570cb98
edx  0x1
ecx   0xd0b5727ckprintf_mutex
eax  0x1
eip   0xd055fe27Debugger+0x7
cs   0x8
eflags  0x200286start_phys+0x1a6
esp   0xf570cb3c
ss  0x10
Debugger+0x7:   leave

ddb{1}> ps
   TID   PPID   PGRPUID  S   FLAGS  WAIT  COMMAND
*18583  59926  82362  0  7 0x2python2.7
 59926   6716  82362  0  30x10008a  pause sh
  6716  16109  82362  0  30x100082  piperdmake
 16109  82362  82362  0  30x10008a  pause sh
 97424  87959  87959 57  30x100083  netio ftp
 87959  42203  87959  0  30x83  piperdperl
 82362  96135  82362  0  30x10008a  pause make
 43744  26800   7482  0  30x100082  piperdgzip
 26800  96135   7482  0  30x100082  piperdpax
 96135   7482   7482  0  30x82  piperdperl
  7482  50744   7482  0  30x10008a  pause ksh
 50744   6457  50744  0  30x92  selectsshd
 42203  59249  42203  0  30x10008b  pause ksh
 59249   6457  59249  0  30x92  selectsshd
 91019  95762  95762 73  30x100090  kqreadsyslogd
 95762  1  95762  0  30x100080  netio syslogd
 63490  1  63490  0  30x100090  kqreadinetd
  6457  1   6457  0  30x80  selectsshd
  3755  1   3755  0  30x100083  ttyin ksh
 94216  1  94216  0  30x100083  ttyin getty
 84616  1  84616  0  30x100083  ttyin getty
 99119  1  99119  0  30x100083  ttyin getty
 37582  1  37582  0  30x100083  ttyin getty
 61646  1  61646  0  30x100083  ttyin getty
 77551  1  77551  0  30x100098  poll  cron
 92485  1  92485 99  30x100090  poll  sndiod
 19492  1  19492110  30x100090  poll  sndiod
 75722  80348  80348 95  30x100092  kqreadsmtpd
 13828  80348  80348103  30x100092  kqreadsmtpd
 97935  80348  80348 95  30x100092  kqreadsmtpd
 12504  80348  80348 95  30x100092  kqreadsmtpd
  5603  80348  80348 95  30x100092  kqreadsmtpd
 90661  80348  80348 95  30x100092  kqreadsmtpd
 80348  1  80348  0  30x100080  kqreadsmtpd
 55186  0  0  0  3 0x14280  nfsidlnfsio
 56545  0  0  0  3 0x14280  nfsidlnfsio
 48066  0  0  0  3 0x14280  nfsidlnfsio
 45832  0  0  0  3 0x14280  nfsidlnfsio
 61138  97667  84727 83  30x100090  poll  ntpd
 97667  84727  84727 83  30x100090  poll  ntpd
 84727  1  84727  0  30x80  poll  ntpd
 54276  34610  34610 74  30x100090  bpf   pflogd
 34610  1  34610  0  30x80  netio pflogd
 40161  0  0  0  3 0x14200  pgzerozerothread
 86681  0  0  0  3 0x14200  aiodoned  aiodoned
  2152  0  0  0  3 0x14200  syncerupdate
 32663  0  0  0  3 0x14200  cleaner   cleaner
 15241