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
 };
 
 

Reply via email to