Module Name: src Committed By: bouyer Date: Tue Aug 30 14:22:22 UTC 2011
Modified Files: src/sys/compat/netbsd32: netbsd32_ioctl.c netbsd32_ioctl.h src/sys/net: bpf.c bpf.h bpfdesc.h Log Message: 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. To generate a diff of this commit: cvs rdiff -u -r1.59 -r1.60 src/sys/compat/netbsd32/netbsd32_ioctl.c cvs rdiff -u -r1.38 -r1.39 src/sys/compat/netbsd32/netbsd32_ioctl.h cvs rdiff -u -r1.165 -r1.166 src/sys/net/bpf.c cvs rdiff -u -r1.57 -r1.58 src/sys/net/bpf.h cvs rdiff -u -r1.32 -r1.33 src/sys/net/bpfdesc.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/compat/netbsd32/netbsd32_ioctl.c diff -u src/sys/compat/netbsd32/netbsd32_ioctl.c:1.59 src/sys/compat/netbsd32/netbsd32_ioctl.c:1.60 --- src/sys/compat/netbsd32/netbsd32_ioctl.c:1.59 Tue Aug 30 07:54:15 2011 +++ src/sys/compat/netbsd32/netbsd32_ioctl.c Tue Aug 30 14:22:22 2011 @@ -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 @@ #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 @@ 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, @@ -515,6 +532,22 @@ } 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 @@ 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); Index: src/sys/compat/netbsd32/netbsd32_ioctl.h diff -u src/sys/compat/netbsd32/netbsd32_ioctl.h:1.38 src/sys/compat/netbsd32/netbsd32_ioctl.h:1.39 --- src/sys/compat/netbsd32/netbsd32_ioctl.h:1.38 Tue Aug 30 07:54:15 2011 +++ src/sys/compat/netbsd32/netbsd32_ioctl.h Tue Aug 30 14:22:22 2011 @@ -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 @@ #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: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 */ Index: src/sys/net/bpf.c diff -u src/sys/net/bpf.c:1.165 src/sys/net/bpf.c:1.166 --- src/sys/net/bpf.c:1.165 Fri Jun 10 00:10:35 2011 +++ src/sys/net/bpf.c Tue Aug 30 14:22:22 2011 @@ -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 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 @@ 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 @@ */ 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 @@ 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 @@ 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 @@ /* * 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 @@ /* * 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 @@ *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 @@ 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; } /* Index: src/sys/net/bpf.h diff -u src/sys/net/bpf.h:1.57 src/sys/net/bpf.h:1.58 --- src/sys/net/bpf.h:1.57 Sun Dec 5 02:40:40 2010 +++ src/sys/net/bpf.h Tue Aug 30 14:22:22 2011 @@ -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 @@ * 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 @@ 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 @@ 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 @@ 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 Index: src/sys/net/bpfdesc.h diff -u src/sys/net/bpfdesc.h:1.32 src/sys/net/bpfdesc.h:1.33 --- src/sys/net/bpfdesc.h:1.32 Sat Mar 13 20:38:48 2010 +++ src/sys/net/bpfdesc.h Tue Aug 30 14:22:22 2011 @@ -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 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 };