Provide netbsd32 compat for bpf. Beside the ioctls, the structure
returned to userland by read(2) also needs to be converted. For this, the bpf descriptor is flagged as compat32 (or not) in the open and ioctl functions (where the user process's pid is also updated in the descriptor). When the bpf buffer is filled in, the 32bits or native header is used depending on the information stored in the descriptor. This won't work if a 64bit binary does the open and ioctls, and then exec a 32bit program which will do the read. But this is very unlikely to happen in real life ... Tested on i386 and loongson; with these changes my loongson can run dhclient and tcpdump with a n32 userland.
This commit is contained in:
parent
2afb25b13d
commit
ccc8030189
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: netbsd32_ioctl.c,v 1.59 2011/08/30 07:54:15 macallan Exp $ */
|
||||
/* $NetBSD: netbsd32_ioctl.c,v 1.60 2011/08/30 14:22:22 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001 Matthew R. Green
|
||||
@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: netbsd32_ioctl.c,v 1.59 2011/08/30 07:54:15 macallan Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: netbsd32_ioctl.c,v 1.60 2011/08/30 14:22:22 bouyer Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -61,6 +61,7 @@ __KERNEL_RCSID(0, "$NetBSD: netbsd32_ioctl.c,v 1.59 2011/08/30 07:54:15 macallan
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <net/bpf.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/igmp.h>
|
||||
@ -294,6 +295,22 @@ netbsd32_to_wdog_conf(struct netbsd32_wdog_conf *s32p, struct wdog_conf *p, u_lo
|
||||
p->wc_count = s32p->wc_count;
|
||||
}
|
||||
|
||||
static inline void
|
||||
netbsd32_to_bpf_program(struct netbsd32_bpf_program *s32p, struct bpf_program *p, u_long cmd)
|
||||
{
|
||||
|
||||
p->bf_insns = (void *)NETBSD32PTR64(s32p->bf_insns);
|
||||
p->bf_len = s32p->bf_len;
|
||||
}
|
||||
|
||||
static inline void
|
||||
netbsd32_to_bpf_dltlist(struct netbsd32_bpf_dltlist *s32p, struct bpf_dltlist *p, u_long cmd)
|
||||
{
|
||||
|
||||
p->bfl_list = (void *)NETBSD32PTR64(s32p->bfl_list);
|
||||
p->bfl_len = s32p->bfl_len;
|
||||
}
|
||||
|
||||
/* wsdisplay stuff */
|
||||
static inline void
|
||||
netbsd32_to_wsdisplay_addscreendata(struct netbsd32_wsdisplay_addscreendata *asd32,
|
||||
@ -514,6 +531,22 @@ netbsd32_from_ieee80211_nwkey(struct ieee80211_nwkey *nwk,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
netbsd32_from_bpf_program(struct bpf_program *p, struct netbsd32_bpf_program *s32p, u_long cmd)
|
||||
{
|
||||
|
||||
NETBSD32PTR32(s32p->bf_insns, p->bf_insns);
|
||||
s32p->bf_len = p->bf_len;
|
||||
}
|
||||
|
||||
static inline void
|
||||
netbsd32_from_bpf_dltlist(struct bpf_dltlist *p, struct netbsd32_bpf_dltlist *s32p, u_long cmd)
|
||||
{
|
||||
|
||||
NETBSD32PTR32(s32p->bfl_list, p->bfl_list);
|
||||
s32p->bfl_len = p->bfl_len;
|
||||
}
|
||||
|
||||
static inline void
|
||||
netbsd32_from_u_long(u_long *p, netbsd32_u_long *s32p, u_long cmd)
|
||||
{
|
||||
@ -825,6 +858,15 @@ netbsd32_ioctl(struct lwp *l, const struct netbsd32_ioctl_args *uap, register_t
|
||||
case WDOGIOC_GWDOGS32:
|
||||
IOCTL_STRUCT_CONV_TO(WDOGIOC_GWDOGS, wdog_conf);
|
||||
|
||||
case BIOCSETF32:
|
||||
IOCTL_STRUCT_CONV_TO(BIOCSETF, bpf_program);
|
||||
case BIOCSTCPF32:
|
||||
IOCTL_STRUCT_CONV_TO(BIOCSTCPF, bpf_program);
|
||||
case BIOCSUDPF32:
|
||||
IOCTL_STRUCT_CONV_TO(BIOCSUDPF, bpf_program);
|
||||
case BIOCGDLTLIST32:
|
||||
IOCTL_STRUCT_CONV_TO(BIOCGDLTLIST, bpf_dltlist);
|
||||
|
||||
case WSDISPLAYIO_ADDSCREEN32:
|
||||
IOCTL_STRUCT_CONV_TO(WSDISPLAYIO_ADDSCREEN, wsdisplay_addscreendata);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: netbsd32_ioctl.h,v 1.38 2011/08/30 07:54:15 macallan Exp $ */
|
||||
/* $NetBSD: netbsd32_ioctl.h,v 1.39 2011/08/30 14:22:22 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001 Matthew R. Green
|
||||
@ -90,6 +90,23 @@ struct netbsd32_format_op {
|
||||
#define DIOCWFORMAT32 _IOWR('d', 106, struct netbsd32_format_op)
|
||||
#endif
|
||||
|
||||
/* from <net/bpf.h> */
|
||||
struct netbsd32_bpf_program {
|
||||
u_int bf_len;
|
||||
netbsd32_pointer_t bf_insns;
|
||||
};
|
||||
|
||||
struct netbsd32_bpf_dltlist {
|
||||
u_int bfl_len;
|
||||
netbsd32_pointer_t bfl_list;
|
||||
};
|
||||
|
||||
#define BIOCSETF32 _IOW('B',103, struct netbsd32_bpf_program)
|
||||
#define BIOCSTCPF32 _IOW('B',114, struct netbsd32_bpf_program)
|
||||
#define BIOCSUDPF32 _IOW('B',115, struct netbsd32_bpf_program)
|
||||
#define BIOCGDLTLIST32 _IOWR('B',119, struct netbsd32_bpf_dltlist)
|
||||
|
||||
|
||||
struct netbsd32_wsdisplay_addscreendata {
|
||||
int idx; /* screen index */
|
||||
netbsd32_charp screentype;
|
||||
@ -129,9 +146,6 @@ dev/wscons/wsconsio.h:228:#define WSDISPLAYIO_SCURSOR _IOW('W', 74, struct wsdis
|
||||
|
||||
dev/wscons/wsconsio.h:241:#define WSDISPLAYIO_SFONT _IOW('W', 77, struct wsdisplay_font)
|
||||
|
||||
net/bpf.h:127:#define BIOCSETF _IOW('B',103, struct bpf_program)
|
||||
net/bpf.h:138:#define BIOCSTCPF _IOW('B',114, struct bpf_program)
|
||||
net/bpf.h:139:#define BIOCSUDPF _IOW('B',115, struct bpf_program)
|
||||
net/if_ppp.h:110:#define PPPIOCSPASS _IOW('t', 71, struct bpf_program) /* set pass filter */
|
||||
net/if_ppp.h:111:#define PPPIOCSACTIVE _IOW('t', 70, struct bpf_program) /* set active filt */
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: bpf.c,v 1.165 2011/06/10 00:10:35 christos Exp $ */
|
||||
/* $NetBSD: bpf.c,v 1.166 2011/08/30 14:22:22 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1990, 1991, 1993
|
||||
@ -39,7 +39,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.165 2011/06/10 00:10:35 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.166 2011/08/30 14:22:22 bouyer Exp $");
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_bpf.h"
|
||||
@ -142,6 +142,7 @@ static int bpf_setif(struct bpf_d *, struct ifreq *);
|
||||
static void bpf_timed_out(void *);
|
||||
static inline void
|
||||
bpf_wakeup(struct bpf_d *);
|
||||
static int bpf_hdrlen(struct bpf_d *);
|
||||
static void catchpacket(struct bpf_d *, u_char *, u_int, u_int,
|
||||
void *(*)(void *, const void *, size_t), struct timespec *);
|
||||
static void reset_d(struct bpf_d *);
|
||||
@ -409,6 +410,10 @@ bpfopen(dev_t dev, int flag, int mode, struct lwp *l)
|
||||
d->bd_seesent = 1;
|
||||
d->bd_feedback = 0;
|
||||
d->bd_pid = l->l_proc->p_pid;
|
||||
#ifdef _LP64
|
||||
if (curproc->p_flag & PK_32)
|
||||
d->bd_compat32 = 1;
|
||||
#endif
|
||||
getnanotime(&d->bd_btime);
|
||||
d->bd_atime = d->bd_mtime = d->bd_btime;
|
||||
callout_init(&d->bd_callout, 0);
|
||||
@ -738,6 +743,12 @@ bpf_ioctl(struct file *fp, u_long cmd, void *addr)
|
||||
*/
|
||||
KERNEL_LOCK(1, NULL);
|
||||
d->bd_pid = curproc->p_pid;
|
||||
#ifdef _LP64
|
||||
if (curproc->p_flag & PK_32)
|
||||
d->bd_compat32 = 1;
|
||||
else
|
||||
d->bd_compat32 = 0;
|
||||
#endif
|
||||
|
||||
s = splnet();
|
||||
if (d->bd_state == BPF_WAITING)
|
||||
@ -1519,6 +1530,23 @@ _bpf_mtap_sl_out(struct bpf_if *bp, u_char *chdr, struct mbuf *m)
|
||||
m_freem(m);
|
||||
}
|
||||
|
||||
static int
|
||||
bpf_hdrlen(struct bpf_d *d)
|
||||
{
|
||||
int hdrlen = d->bd_bif->bif_hdrlen;
|
||||
/*
|
||||
* Compute the length of the bpf header. This is not necessarily
|
||||
* equal to SIZEOF_BPF_HDR because we want to insert spacing such
|
||||
* that the network layer header begins on a longword boundary (for
|
||||
* performance reasons and to alleviate alignment restrictions).
|
||||
*/
|
||||
#ifdef _LP64
|
||||
if (d->bd_compat32)
|
||||
return (BPF_WORDALIGN32(hdrlen + SIZEOF_BPF_HDR32) - hdrlen);
|
||||
else
|
||||
#endif
|
||||
return (BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen);
|
||||
}
|
||||
/*
|
||||
* Move the packet data from interface memory (pkt) into the
|
||||
* store buffer. Return 1 if it's time to wakeup a listener (buffer full),
|
||||
@ -1532,8 +1560,11 @@ catchpacket(struct bpf_d *d, u_char *pkt, u_int pktlen, u_int snaplen,
|
||||
void *(*cpfn)(void *, const void *, size_t), struct timespec *ts)
|
||||
{
|
||||
struct bpf_hdr *hp;
|
||||
#ifdef _LP64
|
||||
struct bpf_hdr32 *hp32;
|
||||
#endif
|
||||
int totlen, curlen;
|
||||
int hdrlen = d->bd_bif->bif_hdrlen;
|
||||
int hdrlen = bpf_hdrlen(d);
|
||||
int do_wakeup = 0;
|
||||
|
||||
++d->bd_ccount;
|
||||
@ -1551,7 +1582,12 @@ catchpacket(struct bpf_d *d, u_char *pkt, u_int pktlen, u_int snaplen,
|
||||
/*
|
||||
* Round up the end of the previous packet to the next longword.
|
||||
*/
|
||||
curlen = BPF_WORDALIGN(d->bd_slen);
|
||||
#ifdef _LP64
|
||||
if (d->bd_compat32)
|
||||
curlen = BPF_WORDALIGN32(d->bd_slen);
|
||||
else
|
||||
#endif
|
||||
curlen = BPF_WORDALIGN(d->bd_slen);
|
||||
if (curlen + totlen > d->bd_bufsize) {
|
||||
/*
|
||||
* This packet will overflow the storage buffer.
|
||||
@ -1582,15 +1618,33 @@ catchpacket(struct bpf_d *d, u_char *pkt, u_int pktlen, u_int snaplen,
|
||||
/*
|
||||
* Append the bpf header.
|
||||
*/
|
||||
hp = (struct bpf_hdr *)((char *)d->bd_sbuf + curlen);
|
||||
hp->bh_tstamp.tv_sec = ts->tv_sec;
|
||||
hp->bh_tstamp.tv_usec = ts->tv_nsec / 1000;
|
||||
hp->bh_datalen = pktlen;
|
||||
hp->bh_hdrlen = hdrlen;
|
||||
/*
|
||||
* Copy the packet data into the store buffer and update its length.
|
||||
*/
|
||||
(*cpfn)((u_char *)hp + hdrlen, pkt, (hp->bh_caplen = totlen - hdrlen));
|
||||
#ifdef _LP64
|
||||
if (d->bd_compat32) {
|
||||
hp32 = (struct bpf_hdr32 *)((char *)d->bd_sbuf + curlen);
|
||||
hp32->bh_tstamp.tv_sec = ts->tv_sec;
|
||||
hp32->bh_tstamp.tv_usec = ts->tv_nsec / 1000;
|
||||
hp32->bh_datalen = pktlen;
|
||||
hp32->bh_hdrlen = hdrlen;
|
||||
/*
|
||||
* Copy the packet data into the store buffer and update its length.
|
||||
*/
|
||||
(*cpfn)((u_char *)hp32 + hdrlen, pkt,
|
||||
(hp32->bh_caplen = totlen - hdrlen));
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
hp = (struct bpf_hdr *)((char *)d->bd_sbuf + curlen);
|
||||
hp->bh_tstamp.tv_sec = ts->tv_sec;
|
||||
hp->bh_tstamp.tv_usec = ts->tv_nsec / 1000;
|
||||
hp->bh_datalen = pktlen;
|
||||
hp->bh_hdrlen = hdrlen;
|
||||
/*
|
||||
* Copy the packet data into the store buffer and update
|
||||
* its length.
|
||||
*/
|
||||
(*cpfn)((u_char *)hp + hdrlen, pkt,
|
||||
(hp->bh_caplen = totlen - hdrlen));
|
||||
}
|
||||
d->bd_slen = curlen + totlen;
|
||||
|
||||
/*
|
||||
@ -1667,14 +1721,7 @@ _bpfattach(struct ifnet *ifp, u_int dlt, u_int hdrlen, struct bpf_if **driverp)
|
||||
|
||||
*bp->bif_driverp = 0;
|
||||
|
||||
/*
|
||||
* Compute the length of the bpf header. This is not necessarily
|
||||
* equal to SIZEOF_BPF_HDR because we want to insert spacing such
|
||||
* that the network layer header begins on a longword boundary (for
|
||||
* performance reasons and to alleviate alignment restrictions).
|
||||
*/
|
||||
bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen;
|
||||
|
||||
bp->bif_hdrlen = hdrlen;
|
||||
#if 0
|
||||
printf("bpf: %s attached\n", ifp->if_xname);
|
||||
#endif
|
||||
@ -1732,13 +1779,7 @@ _bpf_change_type(struct ifnet *ifp, u_int dlt, u_int hdrlen)
|
||||
|
||||
bp->bif_dlt = dlt;
|
||||
|
||||
/*
|
||||
* Compute the length of the bpf header. This is not necessarily
|
||||
* equal to SIZEOF_BPF_HDR because we want to insert spacing such
|
||||
* that the network layer header begins on a longword boundary (for
|
||||
* performance reasons and to alleviate alignment restrictions).
|
||||
*/
|
||||
bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen;
|
||||
bp->bif_hdrlen = hdrlen;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: bpf.h,v 1.57 2010/12/05 02:40:40 christos Exp $ */
|
||||
/* $NetBSD: bpf.h,v 1.58 2011/08/30 14:22:22 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1990, 1991, 1993
|
||||
@ -53,7 +53,10 @@ typedef u_int bpf_u_int32;
|
||||
* even multiple of BPF_ALIGNMENT.
|
||||
*/
|
||||
#define BPF_ALIGNMENT sizeof(long)
|
||||
#define BPF_ALIGNMENT32 sizeof(int)
|
||||
|
||||
#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1))
|
||||
#define BPF_WORDALIGN32(x) (((x)+(BPF_ALIGNMENT32-1))&~(BPF_ALIGNMENT32-1))
|
||||
|
||||
#define BPF_MAXINSNS 512
|
||||
#define BPF_DFLTBUFSIZE (1024*1024) /* default static upper limit */
|
||||
@ -152,6 +155,11 @@ struct bpf_timeval {
|
||||
long tv_usec;
|
||||
};
|
||||
|
||||
struct bpf_timeval32 {
|
||||
int32_t tv_sec;
|
||||
int32_t tv_usec;
|
||||
};
|
||||
|
||||
struct bpf_hdr {
|
||||
struct bpf_timeval bh_tstamp; /* time stamp */
|
||||
uint32_t bh_caplen; /* length of captured portion */
|
||||
@ -159,6 +167,14 @@ struct bpf_hdr {
|
||||
uint16_t bh_hdrlen; /* length of bpf header (this struct
|
||||
plus alignment padding) */
|
||||
};
|
||||
|
||||
struct bpf_hdr32 {
|
||||
struct bpf_timeval32 bh_tstamp; /* time stamp */
|
||||
uint32_t bh_caplen; /* length of captured portion */
|
||||
uint32_t bh_datalen; /* original length of packet */
|
||||
uint16_t bh_hdrlen; /* length of bpf header (this struct
|
||||
plus alignment padding) */
|
||||
};
|
||||
/*
|
||||
* Because the structure above is not a multiple of 4 bytes, some compilers
|
||||
* will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work.
|
||||
@ -172,8 +188,10 @@ struct bpf_hdr {
|
||||
defined(__mips__) || defined(__ns32k__) || defined(__vax__) || \
|
||||
defined(__sh__) || (defined(__sparc__) && !defined(__sparc64__))
|
||||
#define SIZEOF_BPF_HDR 18
|
||||
#define SIZEOF_BPF_HDR32 18
|
||||
#else
|
||||
#define SIZEOF_BPF_HDR sizeof(struct bpf_hdr)
|
||||
#define SIZEOF_BPF_HDR32 sizeof(struct bpf_hdr32)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: bpfdesc.h,v 1.32 2010/03/13 20:38:48 christos Exp $ */
|
||||
/* $NetBSD: bpfdesc.h,v 1.33 2011/08/30 14:22:22 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1990, 1991, 1993
|
||||
@ -97,6 +97,9 @@ struct bpf_d {
|
||||
struct timespec bd_atime; /* access time */
|
||||
struct timespec bd_mtime; /* modification time */
|
||||
struct timespec bd_btime; /* birth time */
|
||||
#ifdef _LP64
|
||||
int bd_compat32; /* 32-bit stream on LP64 system */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user