Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

# jitter.c

Go to the documentation of this file.

    00001 /*
    00002  * Copyright (c) 2002 - 2003
    00003  * NetGroup, Politecnico di Torino (Italy)
    00004  * All rights reserved.
    00005  *
    00006  * Redistribution and use in source and binary forms, with or without
    00007  * modification, are permitted provided that the following conditions
    00008  * are met:
    00009  *
    00010  * 1. Redistributions of source code must retain the above copyright
    00011  * notice, this list of conditions and the following disclaimer.
    00012  * 2. Redistributions in binary form must reproduce the above copyright
    00013  * notice, this list of conditions and the following disclaimer in the
    00014  * documentation and/or other materials provided with the distribution.
    00015  * 3. Neither the name of the Politecnico di Torino nor the names of its
    00016  * contributors may be used to endorse or promote products derived from
    00017  * this software without specific prior written permission.
    00018  *
    00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    00020  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    00022  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    00023  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    00024  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    00025  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    00026  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    00027  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00028  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    00029  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00030  *
    00031  */
    00032
    00033 #include "stdarg.h"
    00034 #include "ntddk.h"
    00035 #include "ntiologc.h"
    00036 #include "ndis.h"
    00037
    00038 #include "packet.h"
    00039 #include "win_bpf.h"
    00040
    00041 //
    00042 // emit routine to update the jump table
    00043 //
    00044 void emit_lenght(binary_stream *stream, ULONG value, UINT len)
    00045 {
    00046     (stream->refs)[stream->bpf_pc]+=len;
    00047     stream->cur_ip+=len;
    00048 }
    00049
    00050 //
    00051 // emit routine to output the actual binary code
    00052 //
    00053 void emit_code(binary_stream *stream, ULONG value, UINT len)
    00054 {
    00055
    00056     switch (len){
    00057
    00058     case 1:
    00059         stream->ibuf[stream->cur_ip]=(UCHAR)value;
    00060         stream->cur_ip++;
    00061         break;
    00062
    00063     case 2:
    00064         *((USHORT*)(stream->ibuf+stream->cur_ip))=(USHORT)value;
    00065         stream->cur_ip+=2;
    00066         break;
    00067
    00068     case 4:
    00069         *((ULONG*)(stream->ibuf+stream->cur_ip))=value;
    00070         stream->cur_ip+=4;
    00071         break;
    00072
    00073     default:;
    00074
    00075     }
    00076
    00077     return;
    00078
    00079 }
    00080
    00081 //
    00082 // Function that does the real stuff
    00083 //
    00084 BPF_filter_function BPFtoX86(struct bpf_insn *prog, UINT nins, INT *mem)
    00085 {
    00086     struct bpf_insn *ins;
    00087     UINT i, pass;
    00088     binary_stream stream;
    00089
    00090     //NOTE: do not modify the name of this variable, as it's used by the macros to emit code.
    00091     emit_func emitm;
    00092
    00093
    00094     // Allocate the reference table for the jumps
    00095 #ifdef NTKERNEL
    00096     stream.refs=(UINT *)ExAllocatePoolWithTag(NonPagedPool, (nins + 1)*sizeof(UINT), '0JWA');
    00097 #else
    00098     stream.refs=(UINT *)malloc((nins + 1)*sizeof(UINT));
    00099 #endif
    00100     if(stream.refs==NULL)
    00101     {
    00102         return NULL;
    00103     }
    00104
    00105     // Reset the reference table
    00106     for(i=0; i< nins + 1; i++)
    00107         stream.refs[i]=0;
    00108
    00109     stream.cur_ip=0;
    00110     stream.bpf_pc=0;
    00111
    00112     // the first pass will emit the lengths of the instructions
    00113     // to create the reference table
    00114     emitm=emit_lenght;
    00115
    00116     for(pass=0;;){
    00117
    00118         ins = prog;
    00119
    00120         /* create the procedure header */
    00121         PUSH(EBP)
    00122         MOVrd(EBP,ESP)
    00123         PUSH(EBX)
    00124         PUSH(ECX)
    00125         PUSH(EDX)
    00126         PUSH(ESI)
    00127         PUSH(EDI)
    00128         MOVodd(EBX, EBP, 8)
    00129
    00130         for(i=0;i<nins;i++){
    00131
    00132             stream.bpf_pc++;
    00133
    00134             switch (ins->code) {
    00135
    00136             default:
    00137
    00138                 return NULL;
    00139
    00140             case BPF_RET|BPF_K:
    00141
    00142                 MOVid(EAX,ins->k)
    00143                 POP(EDI)
    00144                 POP(ESI)
    00145                 POP(EDX)
    00146                 POP(ECX)
    00147                 POP(EBX)
    00148                 POP(EBP)
    00149                 RET()
    00150
    00151                 break;
    00152
    00153
    00154             case BPF_RET|BPF_A:
    00155
    00156                 POP(EDI)
    00157                 POP(ESI)
    00158                 POP(EDX)
    00159                 POP(ECX)
    00160                 POP(EBX)
    00161                 POP(EBP)
    00162                 RET()
    00163
    00164                 break;
    00165
    00166
    00167             case BPF_LD|BPF_W|BPF_ABS:
    00168
    00169                 MOVid(ECX,ins->k)
    00170                 MOVrd(ESI,ECX)
    00171                 ADDib(ECX,sizeof(INT))
    00172                 CMPodd(ECX, EBP, 0x10)
    00173                 JLEb(12)
    00174                 POP(EDI)
    00175                 POP(ESI)
    00176                 POP(EDX)
    00177                 POP(ECX)
    00178                 POP(EBX)
    00179                 POP(EBP)
    00180                 MOVid(EAX,0)  //this can be optimized with xor eax,eax
    00181                 RET()
    00182                 MOVobd(EAX, EBX, ESI)
    00183                 BSWAP(EAX)
    00184
    00185                 break;
    00186
    00187             case BPF_LD|BPF_H|BPF_ABS:
    00188
    00189                 MOVid(ECX,ins->k)
    00190                 MOVrd(ESI,ECX)
    00191                 ADDib(ECX,sizeof(SHORT))
    00192                 CMPodd(ECX, EBP, 0x10)
    00193                 JLEb(12)
    00194                 POP(EDI)
    00195                 POP(ESI)
    00196                 POP(EDX)
    00197                 POP(ECX)
    00198                 POP(EBX)
    00199                 POP(EBP)
    00200                 MOVid(EAX,0)
    00201                 RET()
    00202                 MOVid(EAX,0)
    00203                 MOVobw(AX, EBX, ESI)
    00204                 SWAP_AX()
    00205
    00206                 break;
    00207
    00208             case BPF_LD|BPF_B|BPF_ABS:
    00209
    00210                 MOVid(ECX,ins->k)
    00211                 CMPodd(ECX, EBP, 0x10)
    00212                 JLEb(12)
    00213                 POP(EDI)
    00214                 POP(ESI)
    00215                 POP(EDX)
    00216                 POP(ECX)
    00217                 POP(EBX)
    00218                 POP(EBP)
    00219                 MOVid(EAX,0)
    00220                 RET()
    00221                 MOVid(EAX,0)
    00222                 MOVobb(AL,EBX,ECX)
    00223
    00224                 break;
    00225
    00226             case BPF_LD|BPF_W|BPF_LEN:
    00227
    00228                 MOVodd(EAX, EBP, 0xc)
    00229
    00230                 break;
    00231
    00232             case BPF_LDX|BPF_W|BPF_LEN:
    00233
    00234                 MOVodd(EDX, EBP, 0xc)
    00235
    00236                 break;
    00237
    00238             case BPF_LD|BPF_W|BPF_IND:
    00239
    00240                 MOVid(ECX,ins->k)
    00241                 ADDrd(ECX,EDX)
    00242                 MOVrd(ESI,ECX)
    00243                 ADDib(ECX,sizeof(INT))
    00244                 CMPodd(ECX, EBP, 0x10)
    00245                 JLEb(12)
    00246                 POP(EDI)
    00247                 POP(ESI)
    00248                 POP(EDX)
    00249                 POP(ECX)
    00250                 POP(EBX)
    00251                 POP(EBP)
    00252                 MOVid(EAX,0)
    00253                 RET()
    00254                 MOVobd(EAX, EBX, ESI)
    00255                 BSWAP(EAX)
    00256
    00257                 break;
    00258
    00259             case BPF_LD|BPF_H|BPF_IND:
    00260
    00261                 MOVid(ECX,ins->k)
    00262                 ADDrd(ECX,EDX)
    00263                 MOVrd(ESI,ECX)
    00264                 ADDib(ECX,sizeof(SHORT))
    00265                 CMPodd(ECX, EBP, 0x10)
    00266                 JLEb(12)
    00267                 POP(EDI)
    00268                 POP(ESI)
    00269                 POP(EDX)
    00270                 POP(ECX)
    00271                 POP(EBX)
    00272                 POP(EBP)
    00273                 MOVid(EAX,0)
    00274                 RET()
    00275                 MOVid(EAX,0)
    00276                 MOVobw(AX, EBX, ESI)
    00277                 SWAP_AX()
    00278
    00279                 break;
    00280
    00281             case BPF_LD|BPF_B|BPF_IND:
    00282
    00283                 MOVid(ECX,ins->k)
    00284                 ADDrd(ECX,EDX)
    00285                 CMPodd(ECX, EBP, 0x10)
    00286                 JLEb(12)
    00287                 POP(EDI)
    00288                 POP(ESI)
    00289                 POP(EDX)
    00290                 POP(ECX)
    00291                 POP(EBX)
    00292                 POP(EBP)
    00293                 MOVid(EAX,0)
    00294                 RET()
    00295                 MOVid(EAX,0)
    00296                 MOVobb(AL,EBX,ECX)
    00297
    00298                 break;
    00299
    00300             case BPF_LDX|BPF_MSH|BPF_B:
    00301
    00302                 MOVid(ECX,ins->k)
    00303                 CMPodd(ECX, EBP, 0x10)
    00304                 JLEb(12)
    00305                 POP(EDI)
    00306                 POP(ESI)
    00307                 POP(EDX)
    00308                 POP(ECX)
    00309                 POP(EBX)
    00310                 POP(EBP)
    00311                 MOVid(EAX,0)
    00312                 RET()
    00313                 MOVid(EDX,0)
    00314                 MOVobb(DL,EBX,ECX)
    00315                 ANDib(DL, 0xf)
    00316                 SHLib(EDX, 2)
    00317
    00318                 break;
    00319
    00320             case BPF_LD|BPF_IMM:
    00321
    00322                 MOVid(EAX,ins->k)
    00323
    00324                 break;
    00325
    00326             case BPF_LDX|BPF_IMM:
    00327
    00328                 MOVid(EDX,ins->k)
    00329
    00330                 break;
    00331
    00332             case BPF_LD|BPF_MEM:
    00333
    00334                 MOVid(ECX,(INT)mem)
    00335                 MOVid(ESI,ins->k*4)
    00336                 MOVobd(EAX, ECX, ESI)
    00337
    00338                 break;
    00339
    00340             case BPF_LDX|BPF_MEM:
    00341
    00342                 MOVid(ECX,(INT)mem)
    00343                 MOVid(ESI,ins->k*4)
    00344                 MOVobd(EDX, ECX, ESI)
    00345
    00346                 break;
    00347
    00348             case BPF_ST:
    00349
    00350                 // XXX: this command and the following could be optimized if the previous
    00351                 // instruction was already of this type
    00352                 MOVid(ECX,(INT)mem)
    00353                 MOVid(ESI,ins->k*4)
    00354                 MOVomd(ECX, ESI, EAX)
    00355
    00356                 break;
    00357
    00358             case BPF_STX:
    00359
    00360                 MOVid(ECX,(INT)mem)
    00361                 MOVid(ESI,ins->k*4)
    00362                 MOVomd(ECX, ESI, EDX)
    00363                 break;
    00364
    00365             case BPF_JMP|BPF_JA:
    00366
    00367                 JMP(stream.refs[stream.bpf_pc+ins->k]-stream.refs[stream.bpf_pc])
    00368
    00369                 break;
    00370
    00371             case BPF_JMP|BPF_JGT|BPF_K:
    00372
    00373                 CMPid(EAX, ins->k)
    00374                 JG(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) // 5 is the size of the following JMP
    00375                 JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
    00376                 break;
    00377
    00378             case BPF_JMP|BPF_JGE|BPF_K:
    00379
    00380                 CMPid(EAX, ins->k)
    00381                 JGE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
    00382                 JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
    00383
    00384                 break;
    00385
    00386             case BPF_JMP|BPF_JEQ|BPF_K:
    00387
    00388                 CMPid(EAX, ins->k)
    00389                 JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
    00390                 JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
    00391
    00392                 break;
    00393
    00394             case BPF_JMP|BPF_JSET|BPF_K:
    00395
    00396                 MOVrd(ECX,EAX)
    00397                 ANDid(ECX,ins->k)
    00398                 JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5)
    00399                 JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc])
    00400
    00401                 break;
    00402
    00403             case BPF_JMP|BPF_JGT|BPF_X:
    00404
    00405                 CMPrd(EAX, EDX)
    00406                 JA(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
    00407                 JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
    00408                 break;
    00409
    00410             case BPF_JMP|BPF_JGE|BPF_X:
    00411
    00412                 CMPrd(EAX, EDX)
    00413                 JAE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
    00414                 JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
    00415
    00416                 break;
    00417
    00418             case BPF_JMP|BPF_JEQ|BPF_X:
    00419
    00420                 CMPrd(EAX, EDX)
    00421                 JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
    00422                 JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
    00423
    00424                 break;
    00425
    00426             case BPF_JMP|BPF_JSET|BPF_X:
    00427
    00428                 MOVrd(ECX,EAX)
    00429                 ANDrd(ECX,EDX)
    00430                 JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5)
    00431                 JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc])
    00432
    00433                 break;
    00434
    00435             case BPF_ALU|BPF_ADD|BPF_X:
    00436
    00437                 ADDrd(EAX,EDX)
    00438
    00439                 break;
    00440
    00441             case BPF_ALU|BPF_SUB|BPF_X:
    00442
    00443                 SUBrd(EAX,EDX)
    00444
    00445                 break;
    00446
    00447             case BPF_ALU|BPF_MUL|BPF_X:
    00448
    00449                 MOVrd(ECX,EDX)
    00450                 MULrd(EDX)
    00451                 MOVrd(EDX,ECX)
    00452                 break;
    00453
    00454             case BPF_ALU|BPF_DIV|BPF_X:
    00455
    00456                 CMPid(EDX, 0)
    00457                 JNEb(12)
    00458                 POP(EDI)
    00459                 POP(ESI)
    00460                 POP(EDX)
    00461                 POP(ECX)
    00462                 POP(EBX)
    00463                 POP(EBP)
    00464                 MOVid(EAX,0)
    00465                 RET()
    00466                 MOVrd(ECX,EDX)
    00467                 MOVid(EDX,0)
    00468                 DIVrd(ECX)
    00469                 MOVrd(EDX,ECX)
    00470
    00471                 break;
    00472
    00473             case BPF_ALU|BPF_AND|BPF_X:
    00474
    00475                 ANDrd(EAX,EDX)
    00476
    00477                 break;
    00478
    00479             case BPF_ALU|BPF_OR|BPF_X:
    00480
    00481                 ORrd(EAX,EDX)
    00482
    00483                 break;
    00484
    00485             case BPF_ALU|BPF_LSH|BPF_X:
    00486
    00487                 MOVrd(ECX,EDX)
    00488                 SHL_CLrb(EAX)
    00489
    00490                 break;
    00491
    00492             case BPF_ALU|BPF_RSH|BPF_X:
    00493
    00494                 MOVrd(ECX,EDX)
    00495                 SHR_CLrb(EAX)
    00496
    00497                 break;
    00498
    00499             case BPF_ALU|BPF_ADD|BPF_K:
    00500
    00501                 ADD_EAXi(ins->k)
    00502
    00503                 break;
    00504
    00505             case BPF_ALU|BPF_SUB|BPF_K:
    00506
    00507                 SUB_EAXi(ins->k)
    00508
    00509                 break;
    00510
    00511             case BPF_ALU|BPF_MUL|BPF_K:
    00512
    00513                 MOVrd(ECX,EDX)
    00514                 MOVid(EDX,ins->k)
    00515                 MULrd(EDX)
    00516                 MOVrd(EDX,ECX)
    00517
    00518                 break;
    00519
    00520             case BPF_ALU|BPF_DIV|BPF_K:
    00521
    00522                 MOVrd(ECX,EDX)
    00523                 MOVid(EDX,0)
    00524                 MOVid(ESI,ins->k)
    00525                 DIVrd(ESI)
    00526                 MOVrd(EDX,ECX)
    00527
    00528                 break;
    00529
    00530             case BPF_ALU|BPF_AND|BPF_K:
    00531
    00532                 ANDid(EAX, ins->k)
    00533
    00534                 break;
    00535
    00536             case BPF_ALU|BPF_OR|BPF_K:
    00537
    00538                 ORid(EAX, ins->k)
    00539
    00540                 break;
    00541
    00542             case BPF_ALU|BPF_LSH|BPF_K:
    00543
    00544                 SHLib(EAX, (ins->k) & 255)
    00545
    00546                 break;
    00547
    00548             case BPF_ALU|BPF_RSH|BPF_K:
    00549
    00550                 SHRib(EAX, (ins->k) & 255)
    00551
    00552                 break;
    00553
    00554             case BPF_ALU|BPF_NEG:
    00555
    00556                 NEGd(EAX)
    00557
    00558                 break;
    00559
    00560             case BPF_MISC|BPF_TAX:
    00561
    00562                 MOVrd(EDX,EAX)
    00563
    00564                 break;
    00565
    00566             case BPF_MISC|BPF_TXA:
    00567
    00568                 MOVrd(EAX,EDX)
    00569
    00570                 break;
    00571
    00572
    00573
    00574             }
    00575
    00576             ins++;
    00577         }
    00578
    00579         pass++;
    00580         if(pass == 2) break;
    00581
    00582 #ifdef NTKERNEL
    00583         stream.ibuf=(CHAR*)ExAllocatePoolWithTag(NonPagedPool, stream.cur_ip, '1JWA');
    00584 #else
    00585         stream.ibuf=(CHAR*)malloc(stream.cur_ip);
    00586 #endif
    00587         if(stream.ibuf==NULL)
    00588         {
    00589 #ifdef NTKERNEL
    00590             ExFreePool(stream.refs);
    00591 #else
    00592             free(stream.refs);
    00593 #endif
    00594             return NULL;
    00595         }
    00596
    00597         // modify the reference table to contain the offsets and not the lengths of the instructions
    00598         for(i=1; i< nins + 1; i++)
    00599             stream.refs[i]+=stream.refs[i-1];
    00600
    00601         // Reset the counters
    00602         stream.cur_ip=0;
    00603         stream.bpf_pc=0;
    00604         // the second pass creates the actual code
    00605         emitm=emit_code;
    00606
    00607     }
    00608
    00609     // the reference table is needed only during compilation, now we can free it
    00610 #ifdef NTKERNEL
    00611     ExFreePool(stream.refs);
    00612 #else
    00613     free(stream.refs);
    00614 #endif
    00615     return (BPF_filter_function)stream.ibuf;
    00616
    00617 }
    00618
    00619
    00620 JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins)
    00621 {
    00622     JIT_BPF_Filter *Filter;
    00623
    00624
    00625     // Allocate the filter structure
    00626 #ifdef NTKERNEL
    00627     Filter=(struct JIT_BPF_Filter*)ExAllocatePoolWithTag(NonPagedPool, sizeof(struct JIT_BPF_Filter), '2JWA');
    00628 #else
    00629     Filter=(struct JIT_BPF_Filter*)malloc(sizeof(struct JIT_BPF_Filter));
    00630 #endif
    00631     if(Filter==NULL)
    00632     {
    00633         return NULL;
    00634     }
    00635
    00636     // Allocate the filter's memory
    00637 #ifdef NTKERNEL
    00638     Filter->mem=(INT*)ExAllocatePoolWithTag(NonPagedPool, BPF_MEMWORDS*sizeof(INT), '3JWA');
    00639 #else
    00640     Filter->mem=(INT*)malloc(BPF_MEMWORDS*sizeof(INT));
    00641 #endif
    00642     if(Filter->mem==NULL)
    00643     {
    00644 #ifdef NTKERNEL
    00645         ExFreePool(Filter);
    00646 #else
    00647         free(Filter);
    00648 #endif
    00649         return NULL;
    00650     }
    00651
    00652     // Create the binary
    00653     if((Filter->Function = BPFtoX86(fp, nins, Filter->mem))==NULL)
    00654     {
    00655 #ifdef NTKERNEL
    00656         ExFreePool(Filter->mem);
    00657         ExFreePool(Filter);
    00658 #else
    00659         free(Filter->mem);
    00660         free(Filter);
    00661 #endif
    00662         return NULL;
    00663     }
    00664
    00665     return Filter;
    00666
    00667 }
    00668
    00670
    00671 void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter){
    00672
    00673 #ifdef NTKERNEL
    00674     ExFreePool(Filter->mem);
    00675     ExFreePool(Filter->Function);
    00676     ExFreePool(Filter);
    00677 #else
    00678     free(Filter->mem);
    00679     free(Filter->Function);
    00680     free(Filter);
    00681 #endif
    00682
    00683 }

documentation. Copyright (c) 2002-2003 Politecnico di Torino. All rights reserved.