.title INIT_DRIVER - patch UCX$DEVICE .ident /V2.1/ ; */ ; Copyright (©) Ecole Nationale Supérieure des Télécommunications */ ; */ ; programmme pour filtrer les appels TCP/IP sortants */ ; */ ; 21-oct-1992: Guillaume gérard */ ; */ ; Ce logiciel est fourni gratuitement et ne peut faire */ ; l'objet d'aucune commercialisation */ ; */ ; Aucune garantie d'utilisation, ni implicite, */ ; ni explicite, n'est fournie avec ce logiciel. */ ; Utilisez-le à vos risques et périls */ ; */ ; ; 02-oct-1992 gg v2.0 utilisation d'une table de securite ; 14-oct-1991 GG v1.0-1 utilisation de deanonpaged plutot que deanonpgdisz ; raz du driver dans unload au cas ou pas unloadable ; 7-oct-1991 GG v1.0: création ; ; Ce programme ne permet les connextions sortantes que ; pour les appels sur les addresses autorisees en fonction ; des ACL et/ou des images effectuant l'appel ; .disable global .library /[-]tcpfilter/ .library /sys$share:lib/ .link @sys$system:sys.stb@/se $DDBDEF $DDTDEF $DPTDEF $DYNDEF $FDTDEF $IODEF $LDRIMGDEF $NAMDEF $PDSCDEF $SSDEF .page .external sch$iolockr,sch$iounlock,sch$lockr,sch$lockw,sch$unlock .external ioc$searchdev,ioc$gl_dptlist .external exe$alonpagvar,exe$deanonpaged .external exe$prober .external lib$put_output ; .external krnlsize,krnlstart,krnlcode,krnldata,krnlallocsz .external drv_accessfdt,drv_unload,drv_fdtadr .external ret_accessfdt,unload_pd,access_pd .external dbgdata,mutex,access_table,objprot,objowner ; act_def ; ; unload code when reloading driver. ; conditional assembly since rather hairy ; we use inittab to store code to call us in case of ; a driver reload, to allow us to leave memory ; UNLOAD=1 ; ; .page ; ; ; .psect rdonly,rd,nowrt,long devnam: .ascid /UCX$DEVICE/ replace:.ascid /%TCPLOAD-I-REPLACED, previous code replaced./ kernel_inadr: .address kernel_lock,- mod_drv_accessfdt_end ; .psect code,rd,nowrt,long,shr,pic ; LOADCODE::.call_entry MAX_ARGS=4,HOME_ARGS=TRUE ; $CMKRNL_S routin=mod_drv_accessfdt,- arglst=<(AP)> cmpl #9,r0 bneq dehors pushal replace calls #1,G^LIB$PUT_OUTPUT movl #9,r0 dehors: ret .page ; ; translate kernel into system space ; replace ACCESS FDT entry by ours ; ; P1: size of table ; P2: address of table ; P3: address of diag buffer (optional) ; P4: reload code (optional and NOT protected (CRASHES)) ; 0 or absent: don't reload code ; 1: reload code without any synchronization ; 2: reload code and synchronize with old mutex ; R4 @PCB ; mod_drv_accessfdt: .call_entry MAX_ARGS=4,HOME_ARGS=TRUE,input= clrl r10 cmpl (ap),#2 blssu insfarg cmpl (ap),#4 bgtru maxarg cmpl (ap),#3 blssu 1$ movl 12(ap),r10 ifnowrt #<6*4>,(r10),accvio 1$: movzbl #1,r5 movl 4(ap),r7 cmpl r7,#<1@18> bgtru badpar cmpl r7,#32 bleq badpar incl r5 movl 8(ap),r6 bleq badpar movq r6,r0 clrl r3 jsb G^EXE$PROBER blbc r0,retdiag addl #2,r5 clrl r9 cmpl (ap),#4 blssu 2$ movl 16(ap),r9 cmpl r9,#2 bgtru badpar 2$: ; callg (ap),check_table blbc r0,ret $LKWSET_S inadr=kernel_inadr blbs r0,kernel_lock brb retdiag ret: ret insfarg:movl #SS$_INSFARG,r0 brb ret maxarg: movl #SS$_OVRMAXARG,r0 brb ret accvio: movl #SS$_INVARG,r0 brb ret badpar: movl #SS$_BADPARAM,r0 retdiag:movl r10,r3 beql ret .disable flagging movq r0,(r3)+ movq r2,(r3)+ movq r5,(r3)+ .enable flagging brb ret ; kernel_lock: jsb G^SCH$IOLOCKR ; for IOC$SEARCHDEV *AND* protection against ; unload moval devnam,r1 ; IPL: ASTDEL jsb G^IOC$SEARCHDEV ; search specific device blbc r0,133$ ; ; R1 UCB ; R2 DDB ; R3 SB ; movl DDB$L_DDT(r2),r0 ; @ of DDT movl DDT$PS_FDT_2(r0),R3 ; @ of FDT addl #<4*IO$_ACCESS+FDT$PS_FUNC_RTN>,r3 ; @ of PD for access_fdt bsbw find_dpt blbc r0,133$ ; ; first FDT valid for access; replace its entry ; movl (r3),drv_accessfdt ; update drv_accessfdt from driver movl #-1,drv_accessfdt+4 .IF DF,UNLOAD movl dpt$ps_unload(r5),r1 beql 100$ ; no unload routine movl r1,drv_unload ; update drv_unload from driver movl #-1,drv_unload+4 100$: .ENDC ; bsbw alloc_table blbs r0,140$ 133$: brw 433$ ; 140$: bsbw check_replace ; may update drv_accessfdt and drv_unload ; ; R2 @ of previous kernel data block (0 if none) ; R3 @ of FDT entry ; movl r2,r8 ; save for later tstl r9 ; reload flag bneq 200$ ; reload code 150$: tstl r2 ; if code already loaded, do not bneq 300$ ; reload it 200$: movl #krnlsize,r1 jsb G^EXE$ALONPAGVAR ; ; r2 @ allouee ; r1 taille ; blbc r0,133$ ; subl3 #krnlstart,access_pd+PDSC$Q_ENTRY,r28 ; update procedure addl3 r2,r28,access_pd+PDSC$Q_ENTRY ; descriptors movl #-1,access_pd+PDSC$Q_ENTRY+4 subl3 #krnlstart,unload_pd+PDSC$Q_ENTRY,r28 ; before moving addl3 r2,r28,unload_pd+PDSC$Q_ENTRY ; code in system space.. movl #-1,unload_pd+PDSC$Q_ENTRY+4 ; movw r1,krnlallocsz ; save size pushr #^M ; save R4 for SCH$IOUNLOCK movc3 #krnlsize,krnlstart,(r2) popr #^M ; .IF DF,UNLOAD ; we are protected by the IO MUTEX moval (r2),DPT$PS_UNLOAD(r5) movl r3,(r2); save FDT routine pointer addr movl #-1,(r2) .ENDC ; 300$: ; ; R2 now points to valid code ; R3 points to the FDT entry to be replaced ; R8 points to old code, if any ; R9 is the reload flag ; tstl r8 beql 310$ ; br if no old code was found movl (r8),r6 blbs r9,310$ ; skip mutex moval (r8),r0 ; synchronize on old mutex jsb G^SCH$LOCKW 310$: ; movl access_table,r10 movl r10,(r2) movl #-1,(r2) moval (r2),(r2) ;;; DBG bbc #act$v_owner,act$w_ctl(r10),311$ movl act$l_owner(r10),(r2); update default owner 311$: bbc #act$v_prot,act$w_ctl(r10),312$ movw act$w_prot(r10),(r2) ; update default prot. 312$: moval (r2),(R3) ; update FDT entry ; tstl r8 beql 450$ ; no previous code, all done blbs r9,320$ movl r2,r7 jsb G^SCH$UNLOCK ; wipes out r1-r3 320$: ; ; free old table ; movl r6,r0 jsb G^EXE$DEANONPAGED ; wipes out r1-r2 ; cmpl r8,r7 ; same code ? beql 455$ ; br if yes ; ; free old kernel fragment ; movl r8,r0 jsb G^EXE$DEANONPAGED ; ; R1,R2 destroyed movl #9,r0 ; replaced brb 500$ ; 433$: movl r0,-(SP) movl access_table,r0 ; error exit beql 510$ jsb G^EXE$DEANONPAGED brb 510$ 450$: movl #1,r0 ; created brb 500$ 455$: movl #3,r0 ; table changed ; ; save status, unlock io database & return ; 500$: movl r0,-(SP) 510$: jsb G^SCH$IOUNLOCK movl (SP)+,r0 ret ; ; inputs R3 @FDT entry ; R10 Diag buffer, if any ; ; output R0 SS$_BUGCHECK R5=0 ; R0 SS$_NORMAL R5= @DPT R8= @LDRIMG ; ; R1 scratch ; ; we find the DPT thinking the FDT address is in its space. ; (the DPT list is locked by the io mutex) ; find_dpt: .jsb32_entry movl G^IOC$GL_DPTLIST,R5 movl r5,r0 ; end marker clrl r28 1$: movl DPT$IL_LOADER_HANDLE+4(r5),r8 beql 10$ ; no LDRIMG... possible... bgeq 33$ cmpb LDRIMG$B_TYPE(r8),#DYN$C_LOADCODE bneq 33$ cmpl r3,LDRIMG$L_NONPAG_W_BASE(r8) ; assume FDT is in nonpag area blssu 10$ ; too low addl3 LDRIMG$L_NONPAG_W_BASE(r8),LDRIMG$L_NONPAG_W_END(r8),r1 cmpl r3,r1 blequ 20$ ; ok 10$: movl DPT$L_FLINK(r5),r5 incl r28 cmpl r5,r0 bneq 1$ 33$: tstl r10 beql 331$ movl r1,(r10) movl r3,4(r10) movl r5,8(r10) movl r10,12(r10) addl2 #8,12(r10) movl r28,16(r10) movl r8,20(r10) 331$: movl #SS$_BUGCHECK,R0 clrl r5 clrl r8 rsb 20$: movzbl #SS$_NORMAL,R0 rsb ; ; check_replace: .jsb32_entry ; ; check for replacement of code ; inputs: ; R3 @ fdt table entry ; R5 @DPT ; R8 @LDRIMG ; old code: krnlstart, ; krnlcode, ; drv_accessfdt, ; ret_accessfdt, ; drv_unload ; output r2 0: no replacement ; #0: @ of old block ; updates new kernel code/data ; - drv_unload ; - drv_accessfdt ; scratch R0,R1 ; ; first check: FDT routine pd address must not be within the driver movl (r3),r1 movl LDRIMG$L_NONPAG_R_BASE(r8),r2 cmpl PDSC$Q_ENTRY(r1),r2 ; saved FDT rtn addr blssu 1$ addl LDRIMG$L_NONPAG_R_END(r8),r2 cmpl PDSC$Q_ENTRY(r1),r2 blequ 20$ ; FDT routine within the driver. not ours 1$: ; second check: the saved FDT rtn addr must point on the same code movl PDSC$Q_ENTRY(r1),r1 ; assumedly points to krnlcode cmpl (r1),ret_accessfdt bneq 20$ ; different code .IF DF,UNLOAD ; if the unload feature has been inited, then the unload code must ; be at the place where the inittab was. movl DPT$PS_UNLOAD(r5),r0 movl LDRIMG$L_NONPAG_R_BASE(r8),r2 cmpl PDSC$Q_ENTRY(r0),r2 ; saved FDT rtn addr blssu 2$ addl LDRIMG$L_NONPAG_R_END(r8),r2 cmpl PDSC$Q_ENTRY(r0),r2 blequ 10$ ; within driver... not ours 2$: ; ; update driver unload code from original address in previous code ; movq (r1),drv_unload 10$: .ENDC ; ; update driver FDT rtn address from original address in previous code ; movl (r1),drv_accessfdt moval (r1),r2 ; previous code addr. rsb 20$: clrl r2 ; no previous code rsb ; ; inputs: r6, r7 ; outputs:access_&table able address ; r0: status; ; ; alloc_table: .jsb_entry pushr #^M movl r7,r1 jsb G^EXE$ALONPAGVAR blbc r0,33$ movl r1,-(sp) movl r2,access_table movl #-1,access_table+4 movc3 r7,(r6),(r2) movl access_table,r2 movl (SP)+,r1 movw r1,act$w_size(r2) movw #<1@8+DYN$C_BUFIO>,act$w_type(r2) movzbl #SS$_NORMAL,r0 33$: popr #^M rsb mod_drv_accessfdt_end= . ; ; P1 size (in bytes) of table ; P2: address of table ; ; check user table validity ; .entry check_table,^M movl 8(ap),r0 ; table address; movab @4(ap)[r0],r2 ; address max tstl act$w_size(r0) ; reserved bneq 33$ bicw3 #act$m_valctl,act$w_ctl(r0),r3 bneq 33$ movl act$l_aq(r0),r1 bsbb check_list blbc r0,330$ ret 33$: movzwl #SS$_BADPARAM,r0 330$: movl r10,r3 beql 331$ .disable flagging movq r0,(r3)+ movq r2,(r3)+ movq r4,(r3)+ .enable flagging 331$: ret ; check_list: .jsb32_entry tstl r1 beql 20$ moval (r0)[r1],r1 ; first entry address 1$: movab acte$k_length(r1),r4 cmpl r4,r2 bgtru 33$ ; invalid entry movzwl acte$wh_index(r1),r4 beql 20$ ; end of list moval (r1)[r4],r5 movzwl acte$wl_size(r1),r4 addl r5,r4 cmpl r4,r2 bgtru 33$ ; invalid entry tstw acte$wh_type(r1) beql 10$ 2$: cmpb actimg$t_devnam(r5),#NAM$C_DVI bgtru 33$ addl #actimg$k_length,r5 cmpl r5,r4 blssu 2$ bneq 33$ 10$: addl #acte$k_length,r1 brb 1$ 20$: movzbl #SS$_NORMAL,r0 rsb 33$: movzbl #SS$_BADPARAM,r0 rsb .end