From: VMSSPT::DIFABIO 11-MAR-1997 13:05:43.85 To: STAR::EVERHART CC: STAR::COUGHLAN Subj: Issue found in DK_AUDIO, you input appreciated Glenn, I've been working some issues concering the IO$_AUDIO function with a customer. Most of the issues have been cleared up using your rewrite of the audio code. One more issue exists. I wanted to run it by you. Since you know the code, you might be able to detect a flaw in the issue/resolution I have come up with. If a programmer does an IO$_AUDIO function to a DK device that does not contain a valid AUCB (Sense buffer address and size are invalid), the system can crash with various pool deallocation crashes. (Double Dealloc, REFCNTNEG). The device in question must NOT be subject to mount verification. The program uses just tmpmbx and netmbx. Information about the conditions reproduced to verify this are at the end of the mail message. The program submitted the job via batch, and was doing a QIO READ_PROMPT specifying a P1 parameter that was allocated off the heap. (P1 space address and space [20's] filled.) This could happen with a IO$_AUDIO QIO as well, since they are the same function value. Basically the P1 buffer parameter was allocated from P1 space, and filled with Spaces. This P1 buffer contained the AUCB, with all fields filled with space characters. DKDRIVER allocated an IRPE since the size of the Sense Buffer specified in the ACUB was 20202020. (Both Address and size of Sense buffer was 20202020). DK_AUDIO verifies that the device is mounted, but NOT subject to mount verification. The P1 buffer (AUCB_ADDR) is then locked and mapped. Since the AUCB size was specified in P2 as 100 hex, this succeeds. Next the size of the AUCB is verified to make sure it is at least 34 hex. It is, so we continue. Next we get the CD_SENSE_ADDR (20202020) into R0, and branch to SETUP_SENSE_BUFFER. Here an IRPE is allocated and an attempt is made to lock and map the buffer by calling AUDIO_MAP_PAGE with the buffer (20202020) and it's size (20202020). In AUDIO_MAP_PAGE a call to EXE_STD$MODIFYLOCK fails, R0 = ACCVIO, since we cannot access the buffer at address 20202020. This causes us to execute the LOCK_ERR routine in DKDRIVER. LOCK_ERR calls AUDIO_CLEANUP with the IRP (not the IRPE) passed in R2. AUDIO_CLEANUP calls LDR$DEALLOC_PT to deallocate the buffers mapped for the IRP and any of it's extensions. At this point I'm a little fuzzy since the fields used for comparisons (IRP$L_WIND,IRP$L_OBCNT,IRP$L_SEGVBN of IRPE) get cleared in this routine, but it appears that one of these three is 0 so we branch to 50$, clear all the fields, and RSB to LOCK_ERROR. LOCK_ERR then does a RET to AUDIO_MAP_PAGE. Since R0 status was ACCVIO (from EXE_STD$MODIFYLOCK) we RSB to SETUP_SENSE_BUFFER. Again, since R0 is failure we RSB to DK_AUDIO. In DK_AUDIO, since R0 is STILL failure, we branch to AUDIO_EXIT_FDT. Here we deallocate any resources locked and mapped against the IRP (not IRPE). I don't believe there are any, at this point. At any rate we branch to 50$ and CALL_ABORTIO. We go through EXE_STD$ABORTIO and to IOPOST. We still have the IRP with an IRPE.(Even though the resources were never locked or allocated for the IRPE.) Finally we attempt to deallocate the resources for the IRPE and crash with a REFCNTNEG in MMG_STD$UNLOCK trying to deallocate the IRPE resources. I made the following change(s) to DKDRIVER, which appear to operate: In LOCK_ERROR: LOCK_ERROR: $DRIVER_ERRRTN_ENTRY PUSHR #^M ;U A; Save I/O status TSTL IRP$L_SEQNUM(R3) ;U A; Is this an IRPE? BEQL 100$ ;U A; Nope, this is the origina ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Code change starts here: ; ; Since we did not lock down nor allocate resources for our IRPE dellocate ; it now, rather than letting ABORTIO crash trying to unlock our buffer. MOVZWL IRPE$W_SIZE(R3),-(SP) ; Set block size parameter PUSHL R3 ; Set block address parameter CALLS #2,g^EXE_STD$DEANONPGDSIZ ; Call deallocation routine ; ; Code change ends here. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; MOVL IRPE$L_DRIVER_P1(R3),R3 ;U A; Restore original IRP BICL #IRP$M_EXTEND,IRP$L_STS(R3) ; Clear IRPE bit. MOVL R3,@ERRARG$_STATUS+4(AP) ;U A; Original IRP, not IRPE, m 100$: PUSHL R2 ;U A; Save R2 Testing with that change prevented the system from crashing when the program was run through batch. The program was also tested against a CD device with the invalid P1 parameter. Again, this operation aborted fine. I also put in a check for a valid AUCB, but I see this was never checked for /enforced before so I'm not sure it it would break current programs that do not have the CD_AUCB_VERSION number correct. In DK_AUDIO: CLRL IRP$L_SEQNUM(R3) ;U A; Clear for starters, no pa MOVL IRP$L_QIO_P1(R3),R0 ;U A; Get user descriptor addre MOVL IRP$L_QIO_P2(R3),R1 ;U A; Get user descriptor length BSBW AUDIO_MAP_PAGE ;U A; Locks and Maps AUCB. BLBC R0,AUDIO_EXIT_FDT ;U A; Exit FDT routine on error ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Start of new code: ; MOVL IRP$L_QIO_P1(R3),R0 ; Get user descriptor address CMPW CD_AUCB_VERSION(R0),- ; Make sure this is a valid #CD_AUCB_CUR_VERSION ; AUCB structure. BNEQ 40$ ; Drop out if not. ; ; End of code change. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CMPL #CD_AUCB_SIZE,IRP$L_QIO_P2(R3) ;U A; There must be an AUCB BGTR 40$ ;U A; The AUCB must be at least Initially for the customer I had put a check in DK_AUDIO to make sure this was a CDROM device and if not, exit. That kept the customer from crashing, but would not work if the operation was done to a CDROM. I had no intentions of putting that change into the code. I would like to put a change similar to what I have above into the code, but would like your input on whether the above would be adequate or not. Any input appreciated, Mark d. The following conditions caused various Double Deallocation and REFCNTNEG bugchecks: C program containing a READ_PROMPT command and allocating a P1 buffer from the heap. P2 buffer of size > 34 hex Default directory of a COM file is a DK device DK Device is mounted/nomountver Submit the COM procedure that runs the C program: $ SET DEF $2$dka300:[crashes] $ SET PROC/PRIV=(noall,tmpmbx,netmbx) $ RUN $2$dka0:[programs]READ2 $ EXIT $STATUS