Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

542 lines
11 KiB

  1. ; gpfix.asm - pointer validation routines
  2. include gpfix.inc
  3. include kernel.inc
  4. include tdb.inc
  5. include newexe.inc
  6. sBegin GPFIX0
  7. __GP label word
  8. ;gpbeg dw 0, 0, 0, 0 ; for use in handler
  9. public __GP
  10. sEnd GPFIX0
  11. sBegin GPFIX1
  12. gpend dw 0
  13. sEnd GPFIX1
  14. sBegin DATA
  15. ;this segment is page locked and will be accessible during a GP fault
  16. ;has the names of modules that are allowed to use our funky GP fault handling
  17. ; mechanism. Format: length byte, module name. The table is zero-terminated.
  18. gp_valid_modules label byte
  19. db 3, "GDI"
  20. db 4, "USER"
  21. db 6, "KERNEL"
  22. db 6, "PENWIN"
  23. db 7, "DISPLAY"
  24. db 8, "MMSYSTEM"
  25. db 0 ;end of table
  26. sEnd DATA
  27. ifdef DISABLE
  28. sBegin DATA
  29. ;ExternW wErrorOpts
  30. sEnd DATA
  31. endif
  32. ;public gpbeg, gpend
  33. sBegin CODE
  34. assumes CS,CODE
  35. externA __AHINCR
  36. externNP GetOwner
  37. externNP EntProcAddress
  38. externFP GetExePtr
  39. externFP SetSelectorLimit
  40. ;===============================================================
  41. ;
  42. ;
  43. cProc IsBadReadPtr,<PUBLIC,FAR,NONWIN>
  44. ParmD lp
  45. ParmW cb
  46. cBegin
  47. beg_fault_trap BadRead1
  48. les bx,lp ; check selector
  49. mov cx,cb
  50. jcxz ReadDone1
  51. dec cx
  52. add bx,cx
  53. jc BadRead ; check 16 bit overflow
  54. mov al,es:[bx] ; check read permission, limit
  55. end_fault_trap
  56. ReadDone1:
  57. xor ax,ax
  58. ReadDone:
  59. cEnd
  60. BadRead1:
  61. fault_fix_stack
  62. BadRead:
  63. mov ax,1
  64. jmp short ReadDone
  65. ;===============================================================
  66. ;
  67. ;
  68. cProc IsBadWritePtr,<PUBLIC,FAR,NONWIN>
  69. ParmD lp
  70. ParmW cb
  71. cBegin
  72. beg_fault_trap BadWrite1
  73. les bx,lp ; check selector
  74. mov cx,cb
  75. jcxz WriteDone1
  76. dec cx
  77. add bx,cx
  78. jc BadWrite ; check 16 bit overflow
  79. or es:byte ptr [bx],0 ; check write permission, limit
  80. end_fault_trap
  81. WriteDone1:
  82. xor ax, ax
  83. WriteDone:
  84. cEnd
  85. BadWrite1:
  86. fault_fix_stack
  87. BadWrite:
  88. mov ax,1
  89. jmp short WriteDone
  90. ;===============================================================
  91. ; BOOL IsBadFlatReadWritePtr(VOID HUGE*lp, DWORD cb, WORD fWrite)
  92. ; This will validate a Flat pointer plus a special hack for Fox Pro
  93. ; to detect their poorly tiled selector (ie. all n selector with
  94. ; limit of 64K) (Our tiling is such that you can access up to end of
  95. ; the block using any one of the intermediate selectors flat)
  96. ; if we detect such a case we will fix up the limit on the first sel
  97. ; so GDI can access all of the memory as a 1st_sel:32-bit offset
  98. cProc IsBadFlatReadWritePtr,<PUBLIC,FAR,NONWIN>
  99. ParmD lp
  100. ParmD cb
  101. ParmW fWrite
  102. cBegin
  103. beg_fault_trap frp_trap
  104. les bx,lp ; check selector
  105. .386p
  106. mov eax,cb
  107. movzx ebx, bx
  108. test eax,eax ; cb == 0, all done.
  109. jz frp_ok
  110. add ebx,eax
  111. dec ebx
  112. cmp fWrite, 0
  113. jne frp_write
  114. mov al,es:[ebx] ; read last byte
  115. jmp frp_ok
  116. frp_write:
  117. or byte ptr es:[ebx], 0 ; write last byte
  118. frp_ok:
  119. xor ax,ax
  120. end_fault_trap
  121. frp_exit:
  122. cEnd
  123. frp_trap:
  124. fault_fix_stack
  125. frp_bad:
  126. push ebx
  127. mov ecx, ebx ; get cb
  128. shr ecx, 16 ; get high word
  129. jecxz frp_bade ; if < 64K then bad ptr
  130. mov ax, es
  131. lsl eax, eax ; get limit on 1st sel
  132. jnz frp_bade ; bad sel?
  133. cmp ax, 0ffffh ; 1st of poorly tiled sels?
  134. jne frp_bade ; N: return bad ptr
  135. ; now we have to confirm that this is indeed the first of a bunch
  136. ; of poorly tiled sels and fix up the limit correctly of the first sel
  137. movzx ebx, ax ; ebx = lim total of tiled sels
  138. inc ebx ; make it 10000
  139. mov dx, es
  140. frp_loop:
  141. add dx,__AHINCR ; next sel in array
  142. lsl eax, edx
  143. jnz frp_bade
  144. cmp ecx, 1 ; last sel?
  145. je @f
  146. ; if its not the last sel, then its limit has to be ffffh
  147. ; otherwise it probably is not a poorly tiled sel.
  148. cmp eax, 0ffffh
  149. jne frp_bade
  150. @@:
  151. add ebx, eax ; upd total limit
  152. inc ebx ; add 1 for middle sels
  153. loop frp_loop
  154. dec ebx ; take exact limit of last sel
  155. pop edx ; get cb
  156. cmp edx, ebx
  157. jg frp_bade_cleaned
  158. ; set limit of 1st sel to be ebx
  159. push es
  160. push ebx
  161. call SetSelectorLimit
  162. if KDEBUG
  163. mov ax, es
  164. krDebugOut DEB_WARN, "Fixing poorly tiled selector #AX for flat access"
  165. endif
  166. jmp frp_ok
  167. frp_bade:
  168. pop ebx
  169. frp_bade_cleaned:
  170. .286p
  171. mov ax,1
  172. jmp frp_exit
  173. ;===============================================================
  174. ; BOOL IsBadHugeReadPtr(VOID HUGE*lp, DWORD cb)
  175. ;
  176. cProc IsBadHugeReadPtr,<PUBLIC,FAR,NONWIN>
  177. ParmD lp
  178. ParmD cb
  179. cBegin
  180. beg_fault_trap hrp_trap
  181. les bx,lp ; check selector
  182. mov ax,off_cb
  183. mov cx,seg_cb
  184. mov dx,ax ; if cb == 0, then all done.
  185. or dx,cx
  186. jz hrp_ok
  187. sub ax,1 ; decrement the count
  188. sbb cx,0
  189. add bx,ax ; adjust cx:bx by pointer offset
  190. adc cx,0
  191. jc hrp_bad ; (bug #10446, pass in -1L as count)
  192. jcxz hrplast ; deal with leftover
  193. hrploop:
  194. mov al,es:[0ffffh] ; touch complete segments.
  195. mov dx,es
  196. add dx,__AHINCR
  197. mov es,dx
  198. loop hrploop
  199. hrplast:
  200. mov al,es:[bx]
  201. hrp_ok:
  202. xor ax,ax
  203. end_fault_trap
  204. hrp_exit:
  205. cEnd
  206. hrp_trap:
  207. fault_fix_stack
  208. hrp_bad:
  209. mov ax,1
  210. jmp hrp_exit
  211. ;===============================================================
  212. ; BOOL IsBadHugeWritePtr(VOID HUGE*lp, DWORD cb)
  213. ;
  214. cProc IsBadHugeWritePtr,<PUBLIC,FAR,NONWIN>
  215. ParmD lp
  216. ParmD cb
  217. cBegin
  218. beg_fault_trap hwp_trap
  219. les bx,lp ; check selector
  220. mov ax,off_cb
  221. mov cx,seg_cb
  222. mov dx,ax ; if cb == 0, then all done.
  223. or dx,cx
  224. jz hwp_ok
  225. sub ax,1 ; decrement the count
  226. sbb cx,0
  227. add bx,ax ; adjust cx:bx by pointer offset
  228. adc cx,0
  229. jc hwp_bad ; (bug #10446, pass in -1L as count)
  230. jcxz hwplast ; deal with leftover
  231. hwploop:
  232. or byte ptr es:[0ffffh],0 ; touch complete segments.
  233. mov dx,es
  234. add dx,__AHINCR
  235. mov es,dx
  236. loop hwploop
  237. hwplast:
  238. or byte ptr es:[bx],0
  239. hwp_ok:
  240. xor ax,ax
  241. end_fault_trap
  242. hwp_exit:
  243. cEnd
  244. hwp_trap:
  245. fault_fix_stack
  246. hwp_bad:
  247. mov ax,1
  248. jmp hwp_exit
  249. ;===============================================================
  250. ;
  251. ;
  252. cProc IsBadCodePtr,<PUBLIC,FAR,NONWIN>
  253. ParmD lpfn
  254. cBegin
  255. beg_fault_trap BadCode1
  256. mov cx,seg_lpfn
  257. lar ax,cx
  258. jnz BadCode ; Oh no, this isn't a selector!
  259. test ah, 8
  260. jz BadCode ; Oh no, this isn't code!
  261. mov es,cx ; Validate the pointer
  262. mov bx,off_lpfn
  263. mov al,es:[bx]
  264. end_fault_trap
  265. xor ax, ax
  266. CodeDone:
  267. cEnd
  268. BadCode1:
  269. fault_fix_stack
  270. BadCode:
  271. mov ax,1
  272. jmp short CodeDone
  273. ;========================================================
  274. ;
  275. ; BOOL IsBadStringPtr(LPSTR lpsz, UINT cch);
  276. ;
  277. cProc IsBadStringPtr,<PUBLIC,FAR,NONWIN>,<DI>
  278. ParmD lpsz
  279. ParmW cchMax
  280. cBegin
  281. beg_fault_trap BadStr1
  282. les di,lpsz ; Scan the string.
  283. xor ax,ax
  284. mov cx,-1
  285. cld
  286. repnz scasb
  287. end_fault_trap
  288. neg cx ; cx = string length + 1
  289. dec cx
  290. cmp cx,cchMax
  291. ja BadStr ; if string length > cchMax, then bad string.
  292. bspexit:
  293. cEnd
  294. BadStr1:
  295. fault_fix_stack
  296. BadStr:
  297. mov ax,1
  298. jmp bspexit
  299. ;-----------------------------------------------------------------------;
  300. ; HasGPHandler ;
  301. ; ;
  302. ; See if GP fault handler is registered for faulting address. ;
  303. ; ;
  304. ; This scheme can only be used by registered modules. You register ;
  305. ; a module by adding an entry containing a length byte followed by ;
  306. ; the module name in the gp_valid_modules table defined above. ;
  307. ; ;
  308. ; Arguments: ;
  309. ; parmD lpFaultAdr ;
  310. ; ;
  311. ; Returns: ;
  312. ; AX = New IP of handler ;
  313. ; AX = 0 if no handler registered ;
  314. ; ;
  315. ; Error Returns: ;
  316. ; ;
  317. ; Registers Preserved: ;
  318. ; DI,SI,DS ;
  319. ; ;
  320. ; Registers Destroyed: ;
  321. ; AX,BX,CX,DX,ES ;
  322. ; ;
  323. ; Calls: ;
  324. ; GetOwner ;
  325. ; EntProcAddress ;
  326. ; ;
  327. ; The __GP table has the format of 4 words per entry, plus a ;
  328. ; zero word to terminate the table. The 'seg' value should be ;
  329. ; the actual selector (it must be fixed up by the linker), ;
  330. ; and the offset values should be relative to the start of the ;
  331. ; segment or group. The handler must be in the same code segment ;
  332. ; as the fault range (this ensures that the handler is present ;
  333. ; at GP fault time). ;
  334. ; ;
  335. ; __GP label word ;
  336. ; public __GP ;
  337. ; seg, offset begin, offset end, handler ;
  338. ; ... ;
  339. ; 0 ;
  340. ; ;
  341. ; The symbol '__GP' needs to be in the resident name table, so ;
  342. ; it should be added to the DEF file like this (with an ;
  343. ; appropriate ordinal value): ;
  344. ; ;
  345. ; EXPORTS ;
  346. ; __GP @??? RESIDENTNAME ;
  347. ; ;
  348. ; ;
  349. ; History: ;
  350. ; ?? Jun 91 Don Corbitt [donc] Wrote it ;
  351. ; 30 Jul 91 Don Corbitt [donc] Added support for __GP table ;
  352. ;-----------------------------------------------------------------------;
  353. cProc HasGPHandler,<PUBLIC,FAR,NONWIN>,<ds,si,di>
  354. ParmD lpfn
  355. cBegin
  356. cCall GetOwner, <SEG_lpfn> ; find owner of faulting code
  357. or ax, ax
  358. jz to_fail ;HH_fail
  359. lar bx, ax ; make sure segment is present
  360. jnz to_fail ;HH_fail
  361. test bx, 8000h
  362. jz to_fail ;HH_fail
  363. mov es, ax
  364. cmp es:[ne_magic], NEMAGIC
  365. jz @f
  366. to_fail:
  367. jmp HH_fail
  368. @@:
  369. ; check if the faulting module is allowed to use this scheme
  370. SetKernelDS
  371. mov di, es:[ne_restab]
  372. mov bx, di
  373. inc bx ; save ptr to module name
  374. xor cx,cx
  375. xor ax,ax
  376. mov si, offset gp_valid_modules
  377. mov al, es:[di]
  378. cld
  379. friend_or_fiend:
  380. mov cl, [si]
  381. jcxz HH_fail
  382. cmp al,cl
  383. jnz next_friend
  384. mov di, bx ; need to keep restoring di
  385. inc si ; skip len byte
  386. repe cmpsb
  387. jz we_know_this_chap
  388. dec si ; point to the mismatch
  389. next_friend:
  390. add si, cx
  391. inc si
  392. jmp short friend_or_fiend
  393. we_know_this_chap:
  394. xor cx, cx
  395. mov si, es:[ne_restab] ; restore si
  396. jmp short @F ; start in middle of code
  397. HH_nextSym:
  398. add si, cx ; skip name
  399. add si, 3 ; and entry point
  400. @@: mov cl, es:[si] ; get length of symbol
  401. jcxz HH_fail ; end of table - not found
  402. cmp cl, 4 ; name length
  403. jnz HH_nextSym
  404. cmp es:[si+1], '__' ; look for '__GP'
  405. jnz HH_nextSym
  406. cmp es:[si+3], 'PG'
  407. jnz HH_nextSym
  408. mov ax, es:[si+5] ; get ordinal for '__GP'
  409. if KDEBUG
  410. cCall EntProcAddress,<es,ax,1>
  411. else
  412. cCall EntProcAddress,<es,ax> ; I hate conditional assembly....
  413. endif
  414. mov cx, ax
  415. or cx, dx
  416. jz HH_fail ; This shouldn't ever fail, but...
  417. lar bx, dx ; make sure segment is present
  418. jnz HH_fail
  419. test bx, 8000h
  420. jz HH_fail
  421. mov ds, dx
  422. mov si, ax
  423. mov ax, SEG_lpfn
  424. mov dx, OFF_lpfn
  425. next_fault_val:
  426. mov cx, [si]
  427. jcxz HH_fail
  428. cmp cx, ax ; does segment match?
  429. jnz gp_mismatch
  430. cmp [si+2], dx ; block start
  431. ja gp_mismatch
  432. cmp [si+4], dx ; block end
  433. jbe gp_mismatch
  434. mov ax, [si+6] ; get new IP
  435. jmp short HH_done
  436. gp_mismatch:
  437. add si, 8
  438. jmp short next_fault_val
  439. HH_fail:
  440. xor ax, ax
  441. HH_done:
  442. cEnd
  443. ;========================================================================
  444. ;
  445. ; BOOL IsSharedSelector(HGLOBAL h);
  446. ;
  447. ; Makes sure the given selector is shareable. Currently, we just check
  448. ; if it is owned by a DLL. We also need to check GMEM_SHARE bit but
  449. ; this isn't saved...
  450. ;
  451. cProc IsSharedSelector,<PUBLIC,FAR,NOWIN>
  452. ParmW sharedsel
  453. cBegin
  454. push sharedsel
  455. call GetExePtr
  456. or ax,ax ; bogus handle: exit.
  457. jz ISS_Done
  458. mov es,ax
  459. xor ax,ax
  460. test es:[ne_flags],NENOTP
  461. jz ISS_Done ; Not a DLL
  462. inc ax ; Yup a DLL
  463. ISS_Done:
  464. cEnd
  465. sEnd CODE
  466. end