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

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