Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Provide netbsd32 compat for bpf. Beside the ioctls, the ...



details:   https://anonhg.NetBSD.org/src/rev/7cd31ca2558f
branches:  trunk
changeset: 769036:7cd31ca2558f
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Tue Aug 30 14:22:22 2011 +0000

description:
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.

diffstat:

 sys/compat/netbsd32/netbsd32_ioctl.c |  46 ++++++++++++++++-
 sys/compat/netbsd32/netbsd32_ioctl.h |  22 ++++++-
 sys/net/bpf.c                        |  97 +++++++++++++++++++++++++----------
 sys/net/bpf.h                        |  20 +++++++-
 sys/net/bpfdesc.h                    |   5 +-
 5 files changed, 154 insertions(+), 36 deletions(-)

diffs (truncated from 383 to 300 lines):

diff -r 07ed07a02a60 -r 7cd31ca2558f sys/compat/netbsd32/netbsd32_ioctl.c
--- a/sys/compat/netbsd32/netbsd32_ioctl.c      Tue Aug 30 13:07:30 2011 +0000
+++ b/sys/compat/netbsd32/netbsd32_ioctl.c      Tue Aug 30 14:22:22 2011 +0000
@@ -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);
 
diff -r 07ed07a02a60 -r 7cd31ca2558f sys/compat/netbsd32/netbsd32_ioctl.h
--- a/sys/compat/netbsd32/netbsd32_ioctl.h      Tue Aug 30 13:07:30 2011 +0000
+++ b/sys/compat/netbsd32/netbsd32_ioctl.h      Tue Aug 30 14:22:22 2011 +0000
@@ -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 */
 
diff -r 07ed07a02a60 -r 7cd31ca2558f sys/net/bpf.c
--- a/sys/net/bpf.c     Tue Aug 30 13:07:30 2011 +0000
+++ b/sys/net/bpf.c     Tue Aug 30 14:22:22 2011 +0000
@@ -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).



Home | Main Index | Thread Index | Old Index