From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX"  9-MAR-1991 21:08:53.30
To:	ARISIA::EVERHART
CC:	
Subj:	VALIDATE_TT_VEC -- see if WATCH is running on a system (part 1 of 1)

From:	RELAY-INFO-VAX@CRVAX.SRI.COM@SMTP@CRDGW2
To:	Everhart@Arisia@MRGATE

Received:  by crdgw1.ge.com (5.57/GE 1.89)
	 id AA08863; Sat, 9 Mar 91 20:45:40 EST
Received: From UCBVAX.BERKELEY.EDU by CRVAX.SRI.COM with TCP; Fri,  8 MAR 91 16:28:49 PST
Received: by ucbvax.Berkeley.EDU (5.63/1.42)
	id AA28658; Fri, 8 Mar 91 16:10:39 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 8 Mar 91 23:43:57 GMT
From: peirce@gumby.wisc.edu  (Leonard Peirce)
Organization: Western Michigan University Academic Computing Services
Subject: VALIDATE_TT_VEC -- see if WATCH is running on a system (part 1 of 1)
Message-Id: <1991Mar8.234357.3777@gumby.cc.wmich.edu>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com

NOTE:  I am posting this for a friend.  I didn't write it and I haven't tested
       it yet (see warning in following paragraph) so USE IT AT YOUR OWN RISK.
       I've included a small BUILD.COM to help build it but you're on your own if
       you use it.

       BE AWARE THAT, AS IS, THIS PROGRAM CAN CRASH YOUR SYSTEM.  Actually,
       it was originally designed that way (see note from author below).  If
       you want to use it, you should modify the code that forces the bugcheck
       and change it to something less deadly.  A message to the console might
       be a nice idea.  Other ideas and subsequent coding are left as an
       exercise for the user. ;-}

       To build it, run the BUILD.COM to create VALIDATE_TT_VEC.EXE.

       Again, there is no documentation included other than the source.

--
Leonard Peirce                  Internet:  peirce@gumby.cc.wmich.edu
Western Michigan University                peirce@gw.wmich.edu
Academic Computing Services     UUCP:      ...!uunet!sharkey!wmichgw!peirce
Kalamazoo, MI  49008            Phone:     (616) 387-5469

==================================================================================

    The attached code was written to detect if a terminal had the port and
    class vectors replaced.  It was originally written to detect if the
    WATCH program was being used on a workstation to break into a cluster. 
    If it detects that the vectors have been replaced it crashes the
    system.  Before running it on anything but a standalone system I would
    strongly suggest changing this to something less severe.  It will allow
    the TFF code, and the TDSMP code to work and will allow you to add
    other similar device drivers to the list of approved mid drivers.

    Forrest


$! ------------------ CUT HERE -----------------------
$ v='f$verify(f$trnlnm("SHARE_VERIFY"))'
$!
$! This archive created by VMS_SHARE Version 7.2-007  22-FEB-1990
$!   On  8-MAR-1991 17:59:23.06   By user PEIRCE 
$!
$! This VMS_SHARE Written by:
$!    Andy Harper, Kings College London UK
$!
$! Acknowledgements to:
$!    James Gray       - Original VMS_SHARE
$!    Michael Bednarek - Original Concept and implementation
$!
$! TO UNPACK THIS SHARE FILE, CONCATENATE ALL PARTS IN ORDER
$! AND EXECUTE AS A COMMAND PROCEDURE  (  @name  )
$!
$! THE FOLLOWING FILE(S) WILL BE CREATED AFTER UNPACKING:
$!       1. BUILD.COM;10
$!       2. VALIDATE_TT_VEC.C;2
$!       3. VALIDATE_VEC.MAR;2
$!
$set="set"
$set symbol/scope=(nolocal,noglobal)
$f=f$parse("SHARE_TEMP","SYS$SCRATCH:.TMP_"+f$getjpi("","PID"))
$e="write sys$error  ""%UNPACK"", "
$w="write sys$output ""%UNPACK"", "
$ if f$trnlnm("SHARE_LOG") then $ w = "!"
$ ve=f$getsyi("version")
$ if ve-f$extract(0,1,ve) .ges. "4.4" then $ goto START
$ e "-E-OLDVER, Must run at least VMS 4.4"
$ v=f$verify(v)
$ exit 44
$UNPACK: SUBROUTINE ! P1=filename, P2=checksum
$ if f$search(P1) .eqs. "" then $ goto file_absent
$ e "-W-EXISTS, File ''P1' exists. Skipped."
$ delete 'f'*
$ exit
$file_absent:
$ if f$parse(P1) .nes. "" then $ goto dirok
$ dn=f$parse(P1,,,"DIRECTORY")
$ w "-I-CREDIR, Creating directory ''dn'."
$ create/dir 'dn'
$ if $status then $ goto dirok
$ e "-E-CREDIRFAIL, Unable to create ''dn'. File skipped."
$ delete 'f'*
$ exit
$dirok:
$ w "-I-PROCESS, Processing file ''P1'."
$ if .not. f$verify() then $ define/user sys$output nl:
$ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT 'f'/OUT='P1'
PROCEDURE Unpacker ON_ERROR ENDON_ERROR;SET(FACILITY_NAME,"UNPACK");SET(
SUCCESS,OFF);SET(INFORMATIONAL,OFF);f:=GET_INFO(COMMAND_LINE,"file_name");b:=
CREATE_BUFFER(f,f);p:=SPAN(" ")@r&LINE_END;POSITION(BEGINNING_OF(b));
LOOP EXITIF SEARCH(p,FORWARD)=0;POSITION(r);ERASE(r);ENDLOOP;POSITION(
BEGINNING_OF(b));g:=0;LOOP EXITIF MARK(NONE)=END_OF(b);x:=ERASE_CHARACTER(1);
IF g=0 THEN IF x="X" THEN MOVE_VERTICAL(1);ENDIF;IF x="V" THEN APPEND_LINE;
MOVE_HORIZONTAL(-CURRENT_OFFSET);MOVE_VERTICAL(1);ENDIF;IF x="+" THEN g:=1;
ERASE_LINE;ENDIF;ELSE IF x="-" THEN IF INDEX(CURRENT_LINE,"+-+-+-+-+-+-+-+")=
1 THEN g:=0;ENDIF;ENDIF;ERASE_LINE;ENDIF;ENDLOOP;t:="0123456789ABCDEF";
POSITION(BEGINNING_OF(b));LOOP r:=SEARCH("`",FORWARD);EXITIF r=0;POSITION(r);
ERASE(r);x1:=INDEX(t,ERASE_CHARACTER(1))-1;x2:=INDEX(t,ERASE_CHARACTER(1))-1;
COPY_TEXT(ASCII(16*x1+x2));ENDLOOP;WRITE_FILE(b,GET_INFO(COMMAND_LINE,
"output_file"));ENDPROCEDURE;Unpacker;QUIT;
$ delete/nolog 'f'*
$ CHECKSUM 'P1'
$ IF CHECKSUM$CHECKSUM .eqs. P2 THEN $ EXIT
$ e "-E-CHKSMFAIL, Checksum of ''P1' failed."
$ ENDSUBROUTINE
$START:
$ create 'f'
X$ CC VALIDATE_TT_VEC.C
X$ MACRO VALIDATE_VEC.MAR
X$ LINK VALIDATE_TT_VEC,VALIDATE_VEC,SYS$SYSTEM:SYS.STB/SELECT,SYS$INPUT:/OPT
XSYS$SHARE:VAXCRTL/SHARE
X$ exit
$ CALL UNPACK BUILD.COM;10 1229983894
$ create 'f'
X/*
X ++
XFACILITY:
X`20
X `09VALIDATE_TT_VEC
X`20
XABSTRACT:
X`20
X `09This program will build and load a piece of code into nonpaged pool that
Xverifies that the terminal pointers in TT UCB's are still valid.  The progra
Vm`20
Xwill crash the system with a TTDRVR1 bugcheck if an invalid set of pointers
V are
Xfound.  The program comes with a list of two acceptable terminal MID drivers
V,`20
Xand allows the user to add more.  The program requires that all MID drivers
V be
Xloaded before it is run.  Failure to do so will result in an error and the u
Vser
Xwill be given to opportunity to exit the program.  An additional capability
V has
Xbeen added that allows the verification to be disabled.  The only valid reas
Von to`20
Xdo this would be to add another MID driver to the list.  To use this program
V a`20
Xuser must have CMKRNL priviledge, and PSWAPM priv.
X`20
XAUTHOR:
X`20
X `09F. Kenney`09`0912-December-1988
X`20
XRevision history:
X`20
X `09X-XX`09XXXnnn`09`09Xxxxxxx X. Xxxxxx`09DD-MMMMMMM-YYYY
X `09`09Explain change
X`20
X--
X*/
X`0C
X/* Constant definitions */
X
X#define`09`09DRIVER_TABLE_LEN`0912
X#define`09`09DRIVER_NAME_LEN `0912
X
X
X/* Included files */
X
X#include`09ctype
X#include`09ssdef
X#include`09stdio
X
X
X/* Global variables */
Xchar`09`09driver_names`5BDRIVER_TABLE_LEN`5D`5BDRIVER_NAME_LEN+1`5D;
X
X
Xshort int`09driver_name_lens`5BDRIVER_TABLE_LEN`5D;
X
Xint`09`09driver_entries;
X
Xstruct
X`7B
Xint`09`09start;
Xint`09`09end;
X`7D`09driver_table`5BDRIVER_TABLE_LEN`5D;
X
X`0C
X/* Main program */
Xvalidate_tt_vec()
X`7B
Xchar`09`09resp;
Xchar`09`09trash;
X
Xint`09`09*disable_tt_watching();
Xint`09`09*enable_tt_watching();
Xint`09`09get_driver_names();
Xint`09`09lock_code();`20
Xint`09`09status;
X
Xstruct
X`7B
Xshort int`09num_args;
Xshort int`09unused;`20
Xint`09`09num_entries;
Xint`09`09*driver_table;
X`7D`09arglist = `7B2, 0, 0, &driver_table`5B0`5D`7D;
X
X
Xstatus = lock_code();
Xif ((status & SS$_NORMAL) != SS$_NORMAL) LIB$SIGNAL(status);
X
X
X/* Fill in known driver names and figure out what to do */
Xdo
X`7B
X   driver_name_lens`5B0`5D = (short int)sprintf(&driver_names`5B0`5D`5B0`5D,
V"%s", "FBDRIVER");
X   driver_name_lens`5B1`5D = (short int)sprintf(&driver_names`5B1`5D`5B0`5D,
V"%s", "TDDRIVER");
X
X   driver_entries = 2;
X   printf("\n\n\nEnter E to enable, D to diable TT vector checking, or CTRL-
VZ to exit: ");
X   status = scanf("%c", &resp);
X
X   if (status != EOF)
X   `7B
X      do
X      `7B
X`09 trash = (char)getchar();
X      `7D while (trash != '\n');
X
X      resp = _toupper(resp);
X      if (resp == 'E')
X      `7B
X`09 status = get_driver_names();
X         if (status & 1)`20
X         `7B
X`09    arglist.num_entries = driver_entries;
X`09    status = SYS$CMKRNL(&enable_tt_watching, &arglist);
X`09    if (status == SS$_DEVACTIVE)
X`09    `7B
X`09      printf("\nYou must disable the current watching code before enablin
Vg new watching code.\n");
X`09    `7D
X            else if ((status & SS$_NORMAL) != SS$_NORMAL) LIB$SIGNAL(status)
V;
X         `7D
X      `7D
X      else if (resp == 'D')`20
X      `7B
X`09 status = SYS$CMKRNL(&disable_tt_watching, 0);
X`09 if (status == SS$_NOTINSTALL)
X`09 `7B
X`09   printf("\nTT Watching code is not enabled...\n");
X`09 `7D
X         else if ((status & SS$_NORMAL) != SS$_NORMAL) LIB$SIGNAL(status);
X      `7D
X      else
X      `7B
X`09 printf("\nIllegal command try again!\n");
X      `7D `20
X   `7D
X`7D while (!feof(stdin));
X
Xprintf("\nUser requested EXIT!.");
Xreturn(1);
X
X`7D
X`0C
X/* Get an additional MID driver names and build fill in "driver_table" */
Xint get_driver_names()
X`7B
Xchar`09`09buffer`5BDRIVER_NAME_LEN`5D;
Xchar`09`09resp;
Xchar`09`09trash;
X
Xint`09`09actual_driver_entries = 0;
Xint`09`09*get_driver_addresses();
Xint`09`09i;
Xint`09`09status;
X
Xstruct
X`7B
Xshort int`09arg_count;
Xshort int`09unused;
Xint`09`09entries;
Xint`09`09*names;
Xint`09`09*lens;
Xint`09`09*table;
X`7D`09arglist = `7B4, 0, 0, &driver_names`5B0`5D`5B0`5D, &driver_name_lens`5
VB0`5D, &driver_table`5B0`5D`7D;
X
X
X/* Print out provided MID driver names */
Xprintf("\n\nThe following MID drivers are provided:\n");
Xfor (i=0; i<driver_entries; i++)
X`7B
X   printf("\t%s\n", &driver_names`5Bi`5D`5B0`5D);
X`7D
X
X/* Now find out if they want more driver names */
Xprintf("\nDo you want to add more mid drivers (y/n): ");
Xstatus = scanf("%c", &resp);
Xif (status != EOF)
X`7B
X   do
X   `7B
X      trash = (char)getchar();
X   `7D while (trash != '\n');
X
X   resp = _toupper(resp);
X   if (resp == 'Y')
X   `7B
X      /* Now get additional driver names */
X      do
X      `7B
X`09 printf("Enter device name maximum of 12 characers (<cr> to end list): ")
V;
X         for (i=0; i<DRIVER_NAME_LEN; i++)
X         `7B
X            buffer`5Bi`5D = (char)getchar();
X            if ((buffer`5Bi`5D == '\n') `7C`7C (feof(stdin)))
X            `7B
X               buffer`5Bi`5D = (char)0;
X               break;
X            `7D
X         `7D
X
X         if ((!feof(stdin)) && (buffer`5B0`5D != 0))
X         `7B
X`09    if (buffer`5B0`5D == '\n') break;
X            for (i=0; i<strlen(buffer); i++) buffer`5Bi`5D = _toupper(buffer
V`5Bi`5D);
X`09    driver_name_lens`5Bdriver_entries`5D = (short int)sprintf(&driver_nam
Ves`5Bdriver_entries`5D`5B0`5D, "%s", buffer);
X`09    driver_entries += 1;
X         `7D
X         else
X         `7B
X            break;
X         `7D
X      `7D while (driver_entries < DRIVER_TABLE_LEN);
X   `7D
X
X   /* Get the driver addresse and fill in table of drivers */
X
X   arglist.entries = driver_entries;
X   status = SYS$CMKRNL (&get_driver_addresses, &arglist);
X   if ((status & SS$_NORMAL) != SS$_NORMAL) LIB$SIGNAL(status);
X
X
X   /* Now actually display drivers and idicate if we found an entry for them
V */
X   printf("\n\nThe list belows tells the status of the drivers you requested
V:");
X   for (i=0; i<driver_entries; i++)
X   `7B
X      if (driver_name_lens`5Bi`5D != 0)
X      `7B
X`09actual_driver_entries += 1;
X        printf("\n\t%s is loaded", &driver_names`5Bi`5D`5B0`5D);
X      `7D
X      else
X      `7B
X        printf("\n\t%s is not loaded", &driver_names`5Bi`5D`5B0`5D);
X      `7D
X   `7D
X
X   /* See if they want to use this set of drivers */
X   printf("\n\nDo you want to use these driver (y/n): ");
X   status = scanf("%c", &resp);
X   if (status != EOF)
X   `7B
X      do
X      `7B
X         trash = (char)getchar();
X      `7D while (trash != '\n');
X
X      resp = _toupper(resp);
X      if (resp == 'Y')
X      `7B
X`09driver_entries = actual_driver_entries;
X`09return(1);
X      `7D
X   `7D
X`7D`09   `20
X
Xdriver_entries = 0;
Xreturn(0);
X
X`7D
$ CALL UNPACK VALIDATE_TT_VEC.C;2 454248284
$ create 'f'
X`09.TITLE`09VALIDATE_VEC - Make sure pointers in UCB are ok
X`09.IDENT`09'X-1'
X`09.LIBRARY /SYS$LIBRARY:LIB.MLB/
X
X;++
X; FACILITY:
X;
X;`09VAX/VMS TERMINAL DRIVER
X;
X; ABSTRACT:
X;
X;`09This routine will make sure that the class driver pointers really point
X;`09at the VMS class driver.  If they do not then it will look to see if
X;`09they point into a couple of trusted drivers.
X;
X; AUTHOR:
X;
X;`09F. Kenney`09`0913-December-1988
X;
X; Revision history:
X;
X;`09X-XX`09XXXnnn`09`09Xxxxxxx X. Xxxxxx`09DD-MMMMMMM-YYYY
X;`09`09Explain change
X;
X;--
X;
X`0C
X`09.SBTTL`09Declarations
X
X;
X; EXTERNAL SYMBOLS
X;
X`09$DDTDEF`09`09`09`09; DEFINE DDT OFFSETS
X`09$DPTDEF`09`09`09`09; DEFINE DPT OFFSETS
X`09$IPLDEF`09`09`09`09; IPL definitions
X`09$IRPDEF`09`09`09`09; I/O request packet size
X`09$SPLCODDEF`09`09`09; SPINLOCK definitions
X`09$TTYDEFS`09`09`09; DEFINE TERMINAL DEFINITIONS
X`09$TTYMACS`09`09`09; DEFINE TERMINAL MACROS
X`09$UCBDEF`09`09`09`09; DEFINE UCB
X`09$VECDEF`09`09`09`09; DEFINE CRB VECTOR OFFSETS
X
X`09P1 = 0`09`09`09`09; First argument off of the AP`20
X`09P2 = 4`09`09`09`09; Second argument off of the AP`20
X`09P3 = 8`09`09`09`09; Third argument off of the AP`20
X`09P4 = 12`09`09`09`09; Fourth argument off of the AP`20
X`09P5 = 16`09`09`09`09; Fifth argument off of the AP`20
X`09P6 = 20`09`09`09`09; Sixht argument off of the AP`20
X`09DRIVER_NAME_LEN`09= 13`09`09; Size of a driver name slot
X`09TABLE_SIZE = 12`09`09`09; Number of optional MID drivers
X
X
X`09.PSECT`09_CODE`09LONG,RD,NOWRT,EXE,PIC
X`0C
X`09.SBTTL`09LOOKUP_DPT - Find specified DPT
X;++
X; LOOKUP_DPT - Find specified DPT`20
X;
X; FUNCTIONAL DESCRIPTION:
X;
X;`09This routine will look up the specified DPT and and compute the driver
X; start and points. `20
X;
X; INPUTS:
X;
X;`09P1(AP)`09- Number of arguments (not used)
X;`09P2(AP)`09- Number of driver to look for
X;`09P3(AP)`09- Address of list of names`09`09(13 byte strings)
X;`09P4(AP)`09- Address of list of name lengths`09(longwords)
X;`09P5(AP)`09- Address of list of driver addresses`09(two longword per entry
V 12)
X;
X; OUTPUTS:
X;
X;`09P4(AP)`09- Driver whoes names are not found will be zeroed
X;`09P5(AP)`09- List of driver addresses pairs filled in one per entry
X;
X; IMPLICIT INPUTS:
X;
X;`09Must be in KERNEL mode with R4 -> PCB
X;--
X
X`09.ENTRY`09GET_DRIVER_ADDRESSES, -`09; Save registers used by routine
X`09`09`5EM<R2,R3,R5,R6, - `09;
X`09`09   R7,R8,R9>`09`09;
X`09PUSHL`09R4`09`09`09; Save PCB address
X`09JSB`09G`5ESCH$IOLOCKW`09`09; Lock the I/O database for write access
X`09MOVL`09P2(AP),R4`09`09; Get count of entries
X`09MOVL`09P3(AP),R5`09`09; Get address of strings
X`09MOVL`09P4(AP),R6`09`09; Get address of name string
X`09MOVL`09P5(AP),R7`09`09; Get address of driver table
X`09MOVAL`09G`5EIOC$GL_DPTLIST,R8`09; Get DPT list head address
X10$:
X`09MOVL`09(R8),R9`09`09`09; Get first element
X20$:
X`09CMPC3`09(R6),(R5),`09-`09; Compare names
X`09`09DPT$T_NAME+1(R9)`09;
X`09BEQL`0930$`09`09`09; EQL go compute addresses
X`09MOVL`09(R9),R9`09`09`09; Find next entry
X`09CMPL`09(R9),R8`09`09`09; See if list done
X`09BNEQ`0920$`09`09`09; Try next entry
X`09CLRW`09(R6)+`09`09`09; Signal no driver of this name
X`09ADDL`09#DRIVER_NAME_LEN,R5`09; Point to next driver name
X`09SOBGTR`09R4,10$`09`09`09; See if another driver to look for
X`09BRB`0940$`09`09`09; Exit
X30$:
X`09MOVL`09R9,(R7)+`09`09; Store starting Address
X`09CVTWL`09DPT$W_SIZE(R9),R2`09; Get driver length
X`09ADDL3`09R2,R9,(R7)+`09`09; Compute ending address
X`09ADDL`09#2,R6`09`09`09; Point to next string length
X`09ADDL`09#DRIVER_NAME_LEN,R5`09; Point to next string
X`09SOBGTR`09R4,10$`09`09`09; See if another driver to look for
X40$:
X`09POPL`09R4
X`09JSB`09G`5ESCH$IOUNLOCK`09`09; Unlock I/O database
X`09MOVL`09#SS$_NORMAL,R0`09`09; Signal success
X`09RET
X`0C
X`09.SBTTL`09LOCK_CODE - Lock HIGH IPL code into memory
X;++
X; LOCK_CODE - Lock the code that needs to run at IPL 8 into memory
X;
X; FUNCTIONAL DESCRIPTION:
X;
X;`09This routine will lock the enable_tt_watching, diable_tt_watching,
X; and validate_vec routines into memory.  This is necessary to prevent a`20
X; pagefault at high IPL crash.
X;
X; INPUTS:
X;
X;`09None
X;
X; OUTPUTS:
X;
X;`09None
X;
X; IMPLICIT INPUTS:
X;
X;`09Starting address to be locked down
X;`09Ending address to be locked down
X;
X;--
X`09.ENTRY`09LOCK_CODE,`5EM<>
X`09PUSHAL`09LOCK_END`09`09; Ending address lock down
X`09PUSHAL`09LOCK_BEGIN`09`09; Stating address to lock down
X`09MOVL`09SP,R0`09`09`09; Save addresses used
X`09CLRQ`09-(SP)`09`09`09; Clear off top of stack
X`09PUSHL`09R0`09`09`09; Pointer to pages to lock down
X`09CALLS`09#3,G`5ESYS$LCKPAG`09`09; Lock pages down
X`09RET
X`0C
X`09.SBTTL`09ENABLE_TT_WATCHING - Put in place watching code
X;++
X; ENABLE_TT_WATCHING - Place code in place to prevent terminal watching
X;
X;FUNCTIONAL DESCRIPTION:
X;
X;`09This routine will load a piece of code into pool that prevents
X; MID drivers and MID driver like code from working.  It works by replacing
X; the STARTIO pointer in the DDT.  This routine will first check that`20
X; a copy of itself is not already loaded.  While having two copies in`20
X; place is not fatal it is dumb. `20
X;
X; INPUTS:
X;
X;`09P1(AP)`09- Number arguments not used
X;`09P2(AP)`09- Number of entries in MID driver table
X;`09P3(AP) - Address of MID driver table
X;
X; OUTPUTS:
X;
X;`09R0`09- SS$_NORMAL all worked ok
X;`09`09  SS$_DEVACTIVE watching already active
X;
X; NOTES:
X;`09This code assumes that all users of TTDRIVER use IO_LOCK8
X;`09for forking.
X;
X;--
X`09.PSECT`09LOCK_CODE`09PAGE,RD,NOWRT,EXE,PIC
XLOCK_BEGIN:
X
X
X`09.ENTRY`09ENABLE_TT_WATCHING, -`09; Entry mask`20
X`09`09`5EM<R2,R3>`09`09;
X`09MOVL`09#TABLE_SIZE,R0`09`09; Store size of table of alternate drivers
X`09MOVAL`09TABLE,R2`09`09; Get address of loaded MID driver tables
X10$:
X`09CLRQ`09(R2)+`09`09`09; Zero the entries
X`09SOBGTR`09R0,10$`09`09`09; Loop until table is zeroed
X`09MOVL`09P2(AP),R0`09`09; Get number of entries in user table
X`09BEQL`0930$`09`09`09; EQL no table entries
X`09MOVL`09P3(AP),R1`09`09; Get address of users MID driver table
X`09BEQL`0930$`09`09`09; Programmers error no use table
X`09MOVAL`09TABLE,R2`09`09; Get address of STATIC table
X20$:
X`09MOVQ`09(R1)+,(R2)+`09`09; Move user table to static table
X`09SOBGTR`09R0,20$`09`09`09; Loop until done
X30$:
X`09MOVL`09G`5ETTY$GL_DPT,R1`09`09; Get TTDRIVER DPT address
X`09CVTWL`09DPT$W_VECTOR(R1),R0`09; Get VECTOR offset
X`09ADDL3`09R0,R1,R2`09`09; Compute TABLE offset
X`09MOVL`09R2,CLASS_VEC`09`09; Fill in class vector offset
X`09MOVL`09CLASS_GETNXT(R2),GETNXT`09; Fill in class GETNXT routine address
X`09MOVL`09CLASS_PUTNXT(R2),PUTNXT`09; Fill in class PUTNXT routine address
X`09MOVL`09CLASS_DDT(R2),R3`09; Get DDT address
X;+
X; This code must be done whild holding the FORKLOCK to prevent any changes
X; while we are fiddeling around.
X;-
X`09FORKLOCK LOCK=#SPL$C_IOLOCK8, -`09; Take I/O lock 8
X`09`09LOCKIPL=#IPL$_IOLOCK8,-`09;`20
X`09`09SAVIPL=-(SP),`09-`09;
X`09`09PRESERVE=NO`09`09;
X`09CMPL`09DDT$L_START(R3),R2`09; See if start address is after DDT
X`09BLSSU`0940$`09`09`09; LSS error exit
X`09CVTWL`09DPT$W_SIZE(R1),R0`09; Get Driver size
X`09ADDL`09R0,R1`09`09`09; Compute end of driver address
X`09CMPL`09DDT$L_START(R3),R1`09; Is start address before end of driver
X`09BGTRU`0940$`09`09`09; GTR error exit
X`09MOVL`09DDT$L_START(R3),STARTIO`09; Store TTDRIVER STARTIO address
X`09MOVL`09#LOAD_LEN,R1`09`09; Size of loaded code
X`09JSB`09G`5EEXE$ALONPAGVAR`09; Allocate block of memory to hold loaded code
X`09BLBC`09R0,50$`09`09`09; LBC signal error
X`09PUSHR`09#`5EM<R2,R3,R4,R5>`09; Save registes we care about
X`09MOVL`09R1,LOAD_SIZE`09`09; Save size of block allocated
X`09MOVC3`09#LOAD_LEN,LOAD_START, -`09; Move code into block
X`09`09(R2)`09`09`09;
X`09POPR`09#`5EM<R2,R3,R4,R5>`09; Restore registers
X`09ADDL3`09#NEW_STARTIO_OFFSET, -`09; Store new STARTIO address in DDT
X`09`09R2,DDT$L_START(R3)`09;
X`09FORKUNLOCK `09`09-`09; Release I/O lock 8
X`09`09LOCK=#SPL$C_IOLOCK8, -`09;
X`09`09NEWIPL=(SP)+,`09-`09;
X`09`09CONDITION=RESTORE, -`09;
X`09`09PRESERVE=NO`09`09;`20
X`09MOVZWL`09#SS$_NORMAL,R0`09`09; Signal success
X`09RET
X
X40$:
X`09MOVZWL`09#SS$_DEVACTIVE,R0`09; Signal that watching is already active
X50$:
X`09FORKUNLOCK `09`09-`09; Release I/O lock 8
X`09`09LOCK=#SPL$C_IOLOCK8, -`09;
X`09`09NEWIPL=(SP)+,`09-`09;
X`09`09CONDITION=RESTORE, -`09;
X`09`09PRESERVE=YES`09`09;`20
X`09RET
X`0C
X`09.SBTTL`09DISABLE_TT_WATCHING - Remove watching code from STARTIO path
X;++
X; DISABLE_TT_WATCHING - Remove watching code from STARTIO path
X;
X; FUNCTIONAL DESCRIPTION:
X;
X;`09This routine will examine the the STARTIO address to see if it points to
X; the TTDRIVER.  If the STARTIO address in the DDT is not inside the driver
V then
X; additional checks will be made.  If it is detemined that the TT vector
X; validation code is loaded it will be removed.
X;
X; INPUTS:
X;
X;`09None
X;
X; OUTPUTS:
X;
X;`09R0 - SS$_NORMAL removed watching code
X;`09   - SS$_NOTINSTALL watching code not enables this could occur for
X;`09                    a number of reasons.
X;
X; IMPLICIT INPUTS:
X;
X;`09None
X;
X; NOTE:
X;`09This code assumes that all users of the terminal driver use IO_LOCK8`20
X;`09for forking. `20
X;
X;--
X`09.ENTRY`09DISABLE_TT_WATCHING, -`09;
X`09`09`5EM<R2,R3,R5,R6>`09`09;
X`09MOVL`09G`5ETTY$GL_DPT,R1`09`09; Get DPT address
X`09CVTWL`09DPT$W_VECTOR(R1),R2`09; Get the VECTOR size
X`09ADDL`09R1,R2`09`09`09; Get vector address
X`09MOVL`09CLASS_DDT(R2),R6`09; Get DDT address
X`09CVTWL`09DPT$W_SIZE(R1),R2`09; Get driver size
X`09ADDL`09R1,R2`09`09`09; Compute driver ending address
X;+
X; We need to block out access to TTDRIVER DDT, use FORKLOCK to do this
X;-
X`09FORKLOCK LOCK=#SPL$C_IOLOCK8, -`09; Take I/O lock 8
X`09`09LOCKIPL=#IPL$_IOLOCK8,-`09;`20
X`09`09SAVIPL=-(SP),`09-`09;
X`09`09PRESERVE=NO`09`09;
X`09CMPL`09DDT$L_START(R6),R1`09; Is STARTIO inside TTDRIVER
X`09BLSS`0920$`09`09`09; LSS no assume watching enabled
X`09CMPL`09DDT$L_START(R6),R2`09;`20
X`09BGTR`0920$`09`09`09; GTR no assume watching enabled
X10$:
X`09FORKUNLOCK `09`09-`09; Release I/O lock 8
X`09`09LOCK=#SPL$C_IOLOCK8, -`09;
X`09`09NEWIPL=(SP)+,`09-`09;
X`09`09CONDITION=RESTORE, -`09;
X`09`09PRESERVE=NO`09`09;`20
X`09MOVZWL`09#SS$_NOTINSTALL,R0`09; Signal not able to disable
X`09RET
X
X;+
X; STARTIO points outside of TTDRIVER see if it points to our code.  If not
X; signal inability to disable.  Otherwise remove it.
X;-
X20$:
X`09MOVL`09DDT$L_START(R6),R5`09; Get STARTIO address
X`09CMPC3`09#LOAD_CODE_LEN,`09-`09; Compare loaded code against expected
X`09`09VALIDATE_VEC,(R5)`09; code
X`09BNEQ`0910$`09`09`09; NEQ cannot match exit
X`09SUBL3`09#SAVED_STARTIO_LOC, -`09; Find location of saved STARTIO routine
X`09`09R5,R0`09`09`09;`20
X`09MOVL`09(R0),DDT$L_START(R6)`09; Restore STARTIO address
X`09FORKUNLOCK `09`09-`09; Release I/O lock 8
X`09`09LOCK=#SPL$C_IOLOCK8, -`09;
X`09`09NEWIPL=(SP)+,`09-`09;
X`09`09CONDITION=RESTORE, -`09;
X`09`09PRESERVE=NO`09`09;
X`09SUBL3`09#NEW_STARTIO_OFFSET, -`09; Get starting address of loaded code
X`09`09R5,R0`09`09`09; block
X`09MOVL`09(R0),IRP$W_SIZE(R0)`09; Fill in size of block where deallocate cod
Ve want it
X`09JSB`09G`5EEXE$DEANONPAGED`09; Return block to pool
X`09MOVZWL`09#SS$_NORMAL,R0`09`09; Signal success
X`09RET`09`09`09`09;
X`0C
X`09.SBTTL`09VALIDATE_VEC - Validate UCB
X;++
X; VALIDATE_VEC - Validate the pointers in the UCB`20
X;
X; FUNCTIONAL DESCRIPTION:
X;
X;`09This routine will exampine the CLASS, GETNXT, and the PUTNXT pointers
X; in the UCB.  If the CLASS, PUTNXT, or the GETNXT pointers point to the cla
Vss`20
X; driver.  IF these tests fail it will then check against a list of trusted
X; drivers.  If it fails this test then it will BUGCHECK the system with the
X; reason TTDRVR1 bugcheck.
X;
X;`09This code will be loaded into NONPAGED Pool and will be called in place`
V20
X; of the normal TTDRIVER STARTIO routine.  It will then validate the request
V and
X; jump to the real terminal driver STARTIO routine.  This approach was choos
Ven to
X; minimize the impact on overall system performance.  Ideally it should add
V only`20
X; ten or eleven instructions to the normal STARTIO path.
X;
X; INPUTS:
X;
X;`09R3 = IRP
X;`09R5 = LOGUCB
X;
X; OUTPUTS:
X;
X;`09None
X;
X; IMPLICIT IMPUTS:
X;
X;`09The fork lock must be held.
X;
X; NOTE:
X;`09This code assumes that all users of the terminal driver use IO_LOCK8`20
X;`09for forking. `20
X;
X;--
X`09.PSECT`09_LOAD$CODE      PAGE,RD,WRT,EXE,PIC
X
XLOAD_START:
X
XLOAD_SIZE:`09`09`09`09; Size of block to be returned
X`09.LONG`090`09`09`09;
XSTARTIO:`09`09`09`09; TTDRIVER STARTIO address
X`09.LONG`090`09`09`09;
XCLASS_VEC:`09`09`09`09; Address of CLASS driver VECTOR
X`09.LONG`090`09`09`09; table
XGETNXT:`09`09`09`09`09; Address of CLASS driver GET NEXT
X`09.LONG`090`09`09`09; routine
XPUTNXT:`09`09`09`09`09; Address of CLASS driver PUT NEXT`20
X`09.LONG`090`09`09`09; routine
XTABLE:`09`09`09`09`09; Table of alternate GET and PUT NEXT
X`09.BLKL`09<TABLE_SIZE*2>`09`09; routines
X`09.LONG`090`09`09`09; End of table slot
X
XVALIDATE_VEC::
X`09PUSHL`09R5`09`09`09; Save LOGUCB address
X`09MOVL`09UCB$L_TL_PHYUCB(R5),R5`09; Get PHYUCB address
X`09CMPL`09CLASS_VEC,`09-`09; Compare CLASS vector table address
X`09`09UCB$L_TT_CLASS(R5)`09;
X`09BNEQ`0920$`09`09`09; NEQ next level test
X`09CMPL`09GETNXT, `09-`09; Compare GETNXT address
X`09`09UCB$L_TT_GETNXT(R5)`09;
X`09BNEQ`0920$`09`09`09; NEQ next level test
X`09CMPL`09PUTNXT, `09-`09; Compare PUTNXT address
X`09`09UCB$L_TT_PUTNXT(R5)`09;
X`09BNEQ`0920$`09`09`09; NEQ next level test
X10$:
X`09POPL`09R5`09`09`09; Restore LOGUCB address
X`09JMP`09@STARTIO`09`09; Jump to real TTDRIVER startio
X
X20$:
X`09MOVAL`09TABLE,R2`09`09; Get address of alternate drivers
X30$:
X`09MOVL`09(R2)+,R0`09`09; Get driver start address
X`09BEQL`0940$`09`09`09; EQL enpty table
X`09MOVL`09(R2)+,R1`09`09; Get driver ending address
X`09BEQL`0940$`09`09`09; EQL enpty table
X
X`09CMPL`09UCB$L_TT_GETNXT(R5),R0`09; See if GETNXT is in driver
X`09BLSS`0930$`09`09`09; LSS no try next driver
X`09CMPL`09UCB$L_TT_GETNXT(R5),R1`09; See if GETNXT is in driver
X`09BGTR`0930$`09`09`09; GTR no try next driver
X`09CMPL`09UCB$L_TT_PUTNXT(R5),R0`09; See if PUTNXT is in driver
X`09BLSS`0930$`09`09`09; LSS try next driver
X`09CMPL`09UCB$L_TT_PUTNXT(R5),R1`09; See if PUTNXT is in driver
X`09BGTR`0930$`09`09`09; GTR no try next entry
X`09BRB`0910$`09`09`09; Match so use TTDRIVER STARTIO`20
X
X40$:
X`09POPL`09R5`09`09`09; Restore LOGUCB address
X`09BUG_CHECK`09TTDRVR1,FATAL`09; Crash with TTDRVR fatal error
X
XLOAD_END:
XLOCK_END:
XLOAD_CODE_LEN = . - VALIDATE_VEC
XLOAD_LEN = .- LOAD_START
X
XNEW_STARTIO_OFFSET = VALIDATE_VEC - LOAD_SIZE
XSAVED_STARTIO_LOC = VALIDATE_VEC - STARTIO
X
X`09.END
$ CALL UNPACK VALIDATE_VEC.MAR;2 439322046
$ v=f$verify(v)
$ EXIT

