During if_vmove() we call if_detach_internal() which in turn calls the event
handler notifying about interface departure and one of the consumers will detach if_bpf. There is no way for us to re-attach this easily as the DLT and hdrlen are only given on interface creation. Add a function to allow us to query the DLT and hdrlen from a current BPF attachment and after if_attach_internal() manually re-add the if_bpf attachment using these values. Found by panics triggered by nd6 packets running past BPF_MTAP() with no proper if_bpf pointer on the interface. Also add a basic DDB show function to investigate the if_bpf attachment of an interface. Reviewed by: gnn MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D5896
This commit is contained in:
parent
9859c43dfe
commit
05fc416403
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=297816
@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_bpf.h"
|
||||
#include "opt_compat.h"
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_netgraph.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
@ -67,6 +68,10 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#ifdef DDB
|
||||
#include <ddb/ddb.h>
|
||||
#endif
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/if_dl.h>
|
||||
@ -2569,6 +2574,32 @@ bpfattach2(struct ifnet *ifp, u_int dlt, u_int hdrlen, struct bpf_if **driverp)
|
||||
if_printf(ifp, "bpf attached\n");
|
||||
}
|
||||
|
||||
#ifdef VIMAGE
|
||||
/*
|
||||
* When moving interfaces between vnet instances we need a way to
|
||||
* query the dlt and hdrlen before detach so we can re-attch the if_bpf
|
||||
* after the vmove. We unfortunately have no device driver infrastructure
|
||||
* to query the interface for these values after creation/attach, thus
|
||||
* add this as a workaround.
|
||||
*/
|
||||
int
|
||||
bpf_get_bp_params(struct bpf_if *bp, u_int *bif_dlt, u_int *bif_hdrlen)
|
||||
{
|
||||
|
||||
if (bp == NULL)
|
||||
return (ENXIO);
|
||||
if (bif_dlt == NULL && bif_hdrlen == NULL)
|
||||
return (0);
|
||||
|
||||
if (bif_dlt != NULL)
|
||||
*bif_dlt = bp->bif_dlt;
|
||||
if (bif_hdrlen != NULL)
|
||||
*bif_hdrlen = bp->bif_hdrlen;
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Detach bpf from an interface. This involves detaching each descriptor
|
||||
* associated with the interface. Notify each descriptor as it's detached
|
||||
@ -2977,3 +3008,34 @@ bpf_validate(const struct bpf_insn *f, int len)
|
||||
}
|
||||
|
||||
#endif /* !DEV_BPF && !NETGRAPH_BPF */
|
||||
|
||||
#ifdef DDB
|
||||
static void
|
||||
bpf_show_bpf_if(struct bpf_if *bpf_if)
|
||||
{
|
||||
|
||||
if (bpf_if == NULL)
|
||||
return;
|
||||
db_printf("%p:\n", bpf_if);
|
||||
#define BPF_DB_PRINTF(f, e) db_printf(" %s = " f "\n", #e, bpf_if->e);
|
||||
/* bif_ext.bif_next */
|
||||
/* bif_ext.bif_dlist */
|
||||
BPF_DB_PRINTF("%#x", bif_dlt);
|
||||
BPF_DB_PRINTF("%u", bif_hdrlen);
|
||||
BPF_DB_PRINTF("%p", bif_ifp);
|
||||
/* bif_lock */
|
||||
/* bif_wlist */
|
||||
BPF_DB_PRINTF("%#x", bif_flags);
|
||||
}
|
||||
|
||||
DB_SHOW_COMMAND(bpf_if, db_show_bpf_if)
|
||||
{
|
||||
|
||||
if (!have_addr) {
|
||||
db_printf("usage: show bpf_if <struct bpf_if *>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bpf_show_bpf_if((struct bpf_if *)addr);
|
||||
}
|
||||
#endif
|
||||
|
@ -1469,6 +1469,9 @@ void bpf_mtap2(struct bpf_if *, void *, u_int, struct mbuf *);
|
||||
void bpfattach(struct ifnet *, u_int, u_int);
|
||||
void bpfattach2(struct ifnet *, u_int, u_int, struct bpf_if **);
|
||||
void bpfdetach(struct ifnet *);
|
||||
#ifdef VIMAGE
|
||||
int bpf_get_bp_params(struct bpf_if *, u_int *, u_int *);
|
||||
#endif
|
||||
|
||||
void bpfilterattach(int);
|
||||
u_int bpf_filter(const struct bpf_insn *, u_char *, u_int, u_int);
|
||||
|
11
sys/net/if.c
11
sys/net/if.c
@ -1021,8 +1021,16 @@ void
|
||||
if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
|
||||
{
|
||||
struct if_clone *ifc;
|
||||
u_int bif_dlt, bif_hdrlen;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* if_detach_internal() will call the eventhandler to notify
|
||||
* interface departure. That will detach if_bpf. We need to
|
||||
* safe the dlt and hdrlen so we can re-attach it later.
|
||||
*/
|
||||
bpf_get_bp_params(ifp->if_bpf, &bif_dlt, &bif_hdrlen);
|
||||
|
||||
/*
|
||||
* Detach from current vnet, but preserve LLADDR info, do not
|
||||
* mark as dead etc. so that the ifnet can be reattached later.
|
||||
@ -1062,6 +1070,9 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
|
||||
|
||||
if_attach_internal(ifp, 1, ifc);
|
||||
|
||||
if (ifp->if_bpf == NULL)
|
||||
bpfattach(ifp, bif_dlt, bif_hdrlen);
|
||||
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user