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.