Skip to content

Int 24h abort will abort self-parented process on lDOS, MS-DOS, not on FreeDOS and EDR-DOS #213

@ecm-pushbx

Description

@ecm-pushbx

The following test program causes FreeDOS and current Enhanced DR-DOS to differ from MS-DOS and lDOS. As usual the test requires lmacros to build with NASM.

What this does:

  1. Squirrel away the original Parent Return Address and Parent fields of our PSP.
  2. Set us up as self-parented and point the Parent Return Address into our code section.
  3. Find NUL device header.
  4. Insert a new character device what lives in our code section.
  5. Read from the device.
  6. Device causes an error (device return code 8103h "unknown command") on the first attempt to read from it (device function 04h).
  7. Interrupt 24h handler says "Abort" (return code 02h).
  8. Expected: Process is aborted, so that our hooked Parent Return Address code runs.
  9. Not expected: Int 21h DOS call returns an error return with CY and ax = error code.
  10. Even less expected: Int 21h DOS call returns success.
  11. In the unexpected cases, explicitly terminate.
  12. In the PRA handler, restore the parent and PRA and undo the insertion of our character device, then terminate the application for good.

; Public Domain

%include "lmacros3.mac"

	cpu 386
	org 256
start:
	mov eax, dword [0Ah]		; PRA
	mov dword [origpra], eax
	mov ax, word [16h]		; parent
	mov word [origparent], ax
	mov word [16h], ds
	push ds
	push word i22
	pop dword [0Ah]

	mov dx, i24
	mov ax, 2524h
	int 21h

	mov ah, 52h
	int 21h
	cmp dword [es:bx + 22h + 10], "NUL "
	jne error

	push dword [es:bx + 22h]
	pop dword [deviceheader.link]
	mov word [list], bx
	mov word [list + 2], es
	push cs
	push word deviceheader
	pop dword [es:bx + 22h]

	mov dx, i23
	mov ax, 2523h
	int 21h

	mov ax, 3D00h
	mov dx, name
	int 21h
	jc error

	xchg bx, ax
	mov dx, buffer
	mov cx, 1
	mov ah, 3Fh
	not byte [isabortflag]
	int 21h
	jnc .success
.fail:
	not byte [isabortflag]
	push cs
	pop es
	mov di, msg.fail.code
	call hexword
	mov ah, 09h
	mov dx, msg.fail
	int 21h
	mov ax, 4C00h
	int 21h


.success:
	not byte [isabortflag]
	mov ah, 09h
	mov dx, msg.success
	int 21h
	mov ax, 4C00h
	int 21h


error:
	mov ah, 09h
	mov dx, msg.error
	int 21h

	mov ax, 4CFFh
	int 21h

mismatch:
	je .ret
	mov ah, 09h
	int 21h
.ret:
	retn

i22:
	push cs
	pop ds
	mov eax, dword [origpra]
	mov dword [0Ah], eax
	mov ax, word [origparent]
	mov word [16h], ax

	rol byte [isabortflag], 1
	jnc .notabort
	push cs
	pop es
	mov di, msg.abort.code
	mov ah, 4Dh
	int 21h
	call hexword
	mov dx, msg.abort
	mov ah, 09h
	int 21h
.notabort:
	les bx, [list]
	push dword [deviceheader.link]
	pop dword [es:bx + 22h]
	mov ax, 4C26h
	int 21h


i24:
	mov al, 02h		; abort
	iret

i23:
	stc
	retf


hexword:
	xchg al, ah
	call hexbyte
	xchg al, ah

hexbyte:
	rol al, 4
	call hexnybble
	rol al, 4

hexnybble:
	push ax
	and al, 15
	add al, '0'
	cmp al, '9'
	jbe .got
	add al, -'9'-1+'A'
.got:
	stosb
	pop ax
	retn


isabortflag:	db 0

msg:
.error:		ascic "Error!",13,10
.abort:		db "Process aborted from i24, term code="
.abort.code:	ascic "----h.",13,10
.fail:		db "DOS call returned failure, error code="
.fail.code:	ascic "----h.",13,10
.success:	ascic "DOS call returned success. How?!",13,10

name:
	asciz "TEST$$"

	align 2, nop
buffer:
.size equ 64
	times .size db 0

	align 4, nop
list:	dd 0
origpra:	dd 0
origparent:	dw 0

deviceheader:
.link:	dd -1
.attr:	dw 8000h
.strat:	dw deviceentry
.int:	dw retf_instruction
.name:	fill 8, 32, db "TEST$$"

deviceentry:
	push ax
	push bx
	push cx
	push dx
	push ds
	push si
	push es
	push di

	xor ax, ax
	mov al, [es:bx + 2]
	add ax, ax
	mov si, ax
	mov dx, deviceerror
	cmp si, devicetable.end - devicetable
	jae .dispatch
	mov dx, [cs:devicetable + si]
.dispatch:
	call dx

	pop di
	pop es
	pop si
	pop ds
	pop dx
	pop cx
	pop bx
	pop ax
retf_instruction:
	retf

	align 2
devicetable:
	dw deviceinit
	dw devicemediacheck
	dw devicegetbpb
	dw devicereadioctl
	dw deviceread
	dw devicereadnd
	dw deviceinputstatus
	dw deviceinputflush
	dw devicewrite
	dw devicewritev
	dw deviceoutputstatus
	dw deviceoutputflush
	dw devicewriteioctl
	dw deviceopen
	dw deviceclose
	dw deviceremovable
.end:

data:
.:	db "Hello world!",13,10
	db "123"
.end:
.size equ .end - .

deviceinit:
devicemediacheck:
devicegetbpb:
devicereadioctl:
deviceinputstatus:
deviceinputflush:
devicewrite:
devicewritev:
deviceoutputstatus:
deviceoutputflush:
devicewriteioctl:
deviceopen:
deviceclose:
deviceremovable:

deviceerror:
	mov word [es:bx + 3], 8103h
	retn

deviceread:
	 push cs
	 pop ds
	rol byte [flag], 1
	jc .read
	not byte [flag]
	jmp deviceerror

.read:
	push es
	mov cx, [es:bx + 12h]
	les di, [es:bx + 0Eh]

	mov si, word [pointer]
	mov ax, data.end
	sub ax, si
	cmp cx, ax
	jb @F
	mov cx, ax
@@:
	mov ax, cx
	rep movsb
	mov word [pointer], si
	pop es
	mov word [es:bx + 12h], ax
deviceok:
	mov word [es:bx + 3], 0100h
	retn

	align 2, nop
pointer:	dw data
flag:		db 0

devicereadnd:
	mov si, word [cs:pointer]
	cmp si, data.end
	jae .busy
	cs lodsb
	mov byte [es:bx + 0Dh], al
	jmp deviceok

.busy:
	mov word [es:bx + 3], 0300h
	retn

Results:

MS-DOS v7, MS-DOS v5, lDOS 2025 August:

C:\>testabrt
Process aborted from i24, term code=0200h.

FreeDOS:

C:\>testabrt
DOS call returned failure, error code=000Ch.

Enhanced DR-DOS:

C:\>testabrt
DOS call returned failure, error code=0053h.

The FreeDOS code is in

kernel/kernel/entry.asm

Lines 723 to 731 in 032523a

;
; Abort processing.
;
CritErrAbort:
mov ax,[_cu_psp]
mov es,ax
cmp ax,[es:PSP_PARENT]
mov al,FAIL
jz CritErrExit

The EDR-DOS code is very similar: https://hg.pushbx.org/ecm/edrdos/file/6c174e5361fb/drdos/pcmif.nas#l806

di24_abort:				; Abort this Process
	mov	ax,[current_psp]		; check not root application because
	mov	es,ax			; it must not be terminated so force
	cmp	ax,[es:PSP_PARENT]	; Is this the root Process
	mov	al,ERR_FAIL		; convert the error to FAIL
	 je	di24_40			; if not we terminate

It's essentially unchanged (modulo the RASM-86 to JWasm to NASM port) from the OpenDOS v7.01 code in https://hg.pushbx.org/ecm/edrdos/file/d4aed5f1b3e6/ibmdos/pcmif.a86#l778

Additional oddity: EDR-DOS returns error code 53h which means "fail on INT 24h". FreeDOS instead returns the error code 0Ch meaning "access code invalid".

Metadata

Metadata

Assignees

No one assigned

    Labels

    compatibilityissue may effect compatibility

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions