What specifically causes EPrivilege to be raised?

2020-08-14 10:44发布

问题:

I'm getting a bug report that some functionality in some music-playing code in an external DLL (SDL_Mixer, in case it helps) that my program uses is raising EPrivilege. The DLL is written in C, so I can't get useful stack trace information out of it with MadExcept, and the problem is not reproducible on my end. And just to make things worse, I don't even know what EPrivilege is.

I've never seen it come up in my own code, there's very little information about it available online, and what there is is contradictory. (One explanation says it's raised by the OS if you try to do something with a limited account that requires privileges that aren't available, another says that it's raised by the CPU if you try to execute an instruction that's above your privilege level.)

Does anyone have an authoritative explanation for what causes EPrivilege? And does anyone have any idea how it could be raised by music-playing code on one Windows 7 64-bit machine under a non-admin account but not be raised when running the same code on my Windows 7 64-bit machine under a non-admin account?

回答1:

EPrivilege is raised when the hardware objects to you trying to run a privileged instruction in user mode. These privileged instructions are restricted to supervisor mode, a.k.a. ring 0.

The hardware raises the error and then the RTL catches it and maps it to a RTL exception, just like all the EExternal exceptions, e.g. EAccessViolation, EStackOverflow etc.

Admin rights are not relevant here. That is something that is enforced by the OS software. Instruction privilege is controlled at the hardware level.

You see such an error if you attempt to execute garbage (i.e. corrupted function pointer) which just happens to spell a privileged instruction. Memory corruption is the only sane explanation. Only compilers that target kernel mode code will emit privileged instructions.



回答2:

We do a lot of real-time hardware control using Delphi. This involves reading and writing I/O ports. If you dont have permission (or a kernel driver) to do this, you get EPrivilege.

For example this bit of code:

procedure   WriteIOByte( AData : byte; AAddress : word); assembler;
asm
  out dx,al
end;

under W98 needed nothing to allow it to write a byte to an I/O address, eg the PC parallel port. Under NT and on it will generate EPrivilege unless that address has been 'opened' in some way eg using gwiopm. Thus EPrivilege can be an indicator of a 'garbage read/write' (as David suggests) or of an incomplete setup that read / writes incorrectly setup hardware.