BPF indexed byte load can sign extend

Sepherosa Ziehau sepherosa at gmail.com
Wed Jan 2 03:24:15 PST 2008


On Jan 2, 2008 10:56 AM, Guy Harris <guy at alum.mit.edu> wrote:
> The code to handle BPF non-indexed loads in bpf_filter() in bpf_filter.c is:
>
>                 case BPF_LD|BPF_B|BPF_ABS:
>                         k = pc->k;
>                         if (k > buflen) {
> #ifdef _KERNEL
>                                 struct mbuf *m;
>
>                                 if (buflen != 0)
>                                         return 0;
>                                 m = (struct mbuf *)p;
>                                 MINDEX(m, k);
>                                 A = mtod(m, u_char *)[k];
>                                 continue;
> #else
>                                 return 0;
>                         }
>
>
> which will load the byte at the offset in the instruction into the
> accumulator, zero-extending it.
>
> The code to handle indexed loads is
>
>                 case BPF_LD|BPF_B|BPF_IND:
>                         k = X + pc->k;
>                         if (pc->k >= buflen || X >= buflen - pc->k) {
> #ifdef _KERNEL
>                                 struct mbuf *m;
>
>                                 if (buflen != 0)
>                                         return 0;
>                                 m = (struct mbuf *)p;
>                                 MINDEX(m, k);
>                                 A = mtod(m, char *)[k];
>                                 continue;
> #else
>                                 return 0;
>                         }
>
>
> which will load the byte at the offset that's the sum of the offset in
> the instruction and the contents of the index register; if buflen is 0,
> as is the case when this is called from bpf_mtap(), it will sign-extend
> it on most if not all platforms, as the mbuf data pointer is cast to
> "char *" rather than "u_char *". Otherwise, as is the case when this is
> called from bpf_tap(), it'll zero-extend it, as "p" is a "u_char *".
>
> Presumably those semantics are not intended, as the same instruction
> behaves differently depending on how the tapping is being done, and on
> whether the load is indexed or not. (In libpcap's user-mode filter, it's
> never sign-extended.)
>
> In current NetBSD, OpenBSD, and FreeBSD, it's "u_char" in both "mtod()"
> calls, fixing that.
>
> Here's a patch:

Committed.  Thanks!
BTW, please create a unified patch next time :)

Best Regards,
sephe

>
> *** bpf_filter.c        Tue Jan  1 18:46:19 2008
> --- bpf_filter.c.UNSIGNED       Tue Jan  1 18:44:03 2008
> ***************
> *** 326,332 ****
>                                         return 0;
>                                 m = (struct mbuf *)p;
>                                 MINDEX(m, k);
> !                               A = mtod(m, char *)[k];
>                                 continue;
>    #else
>                                 return 0;
> --- 326,332 ----
>                                         return 0;
>                                 m = (struct mbuf *)p;
>                                 MINDEX(m, k);
> !                               A = mtod(m, u_char *)[k];
>                                 continue;
>    #else
>                                 return 0;
>



-- 
Live Free or Die





More information about the Bugs mailing list