Why don’t we create a special class of programs which can break the normal rules?


In response to a discussion of why the window handle limit is 10,000, commenter Juan wondered why we don't create a special class of programs which can exceed the 10,000 handle limit and otherwise bypass the normal operation of the system.

This is another case of the tragedy of special treatment: Eventually, nothing is special any more.

If there were a way for an application to say, "Hey, I don't want to be constrained by the normal rules that apply to your everyday boring applications," then every application would simply say it, and the net effect would be that the constraint no longer applies to anybody.

Task Manager conforms to the normal rules for GUI programs because if it marked itself as special, soon everybody would mark themselves as special in order to get the same special treatment. (Besides, the special treatment doesn't help Task Manager at all, since Task Manager doesn't create 10,000 handles. The specific issue in the comment is not something Task Manager even knows that it needs to opt out of. All it did was call CreateWindow; Task Manager shouldn't need to know about the internal implementation of CreateWindow.)

Bonus chatter

: There is already one mechanism for applications to say that a particular class of restrictions should not apply to them.

Comments (20)
  1. MItaly says:

    Still, it would be nice to have the task manager executed in a protected environment, or, maybe, the GINA CTRL-ALT-CANC window could provide some magic “panic button” to pause all the user processes (or maybe only the CPU/memory hogging ones) before starting the task manager.

    [But what if it paused a process while it owned a mutex that Task Manager needs? -Raymond]
  2. bozox says:

    In Windows Mobile, there are privileged apps and unprivileged ones. The list of available API differs.

  3. Alexander Grigoriev says:

    1. It makes sense to implement code-based permissions. Kind of like what .NET does, but for native code. UAC does a bit of that, but in ugly way.

    2. A concept of global window handles and USER/GDI resources should be revised. There is no reason every process need to be able to access all windows of other processes. Window/GDI handles and the associated data should be allocated inprocess, without affecting other processes resosurces. Only some special windows (top level) should allow cross-process access for query and WM_CLOSE and other limited set of messages. All other messages should be quietly dropped.

    [Code-based permissions in native code cannot be applied at a level finer than the process, which limits what you can do. And many programs don’t use window handles for child controls. Mind you, there are also lots of people who expect to be able to screw with the windows of other processes. Just look at all the people trying to hack Explorer’s listview. -Raymond]
  4. Billy O'Neal says:

    @Teo:

    Some applications might have such a flag, but UAC will not automatically elevate an application unless that application’s executable passes a hash check.

  5. Leo Davidson says:

    @Teo:

    Not just explorer.exe but other important processes like calc.exe and notepad.exe.

    (Though calling them "auto-elevating" is wrong. They’re flagged as special in that they can auto-elevate specific COM objects but they don’t auto-elevate themselves. There’s another set of processes which do do that, though.)

    @Billy O’Neal:

    But it’s also trivial to inject code into those processes, so the exe signature check isn’t worth much.

    Similar to what Raymond says in the root, you make one thing "special" and anything can make itself special as well.

  6. Teo says:

    Interestingly enough, noone bothered to mention the self-elevating executables in WIndows 2088 R2. They just toggle a flag in their manifests which says "wee, I am special, I am *the* king!" But imho Explorer.exe is not *a* process, it is the upper layer of the OS, so it is expected to be able to and to have to do things other processes should not.

  7. MItaly says:

    [But imho Explorer.exe is not *a* process, it is the upper layer of the OS, so it is expected to be able to and to have to do things other processes should not.]

    Explorer.exe runs also a lot of shell extensions, that in this way would gain extra powers.

    [But what if it paused a process while it owned a mutex that Task Manager needs? -Raymond]

    Are you talking about an OS internal mutex?

    Well, maybe a "KILL all the user’s CPU hogging processes" may do the trick, even if I realize that it would still be a suboptimal solution.

  8. Aaron says:

    If it was absolutely necessary to make Task Manager "special" without extending the ability to any other processes, couldn’t task manager be rewritten inside of win32k.sys?  I mean, it might have to drop all of its dependencies and be a major pain in the ass since it wouldn’t be able to use CreateWindow or any of the normal APIs, but it would basically gain the ability to "do special stuff" that no process would be able to do.

  9. Alexander Grigoriev says:

    @Leo Davidson,

    You cannot inject code to an elevated process.

  10. Dan says:

    @Alex

    Beat me to it.  In order to inject code into an elevated process, first you have to elevate yourself.  Once you’re elevated, then you can inject code into the other process which will run elev… oh wait…

  11. Leo Davidson says:

    @Alexander Grigoriev & @Dan:

    Explorer.exe isn’t elevated so you can inject into that.

    You can then use Explorer’s ability to write to protected folders to drop a DLL somewhere which an auto-elevated process will load.

    You then run the auto-elevated process. The code in your DLL is now elevated, even though the thing triggering all of this never required elevation.

    This isn’t just in theory; I’ve proved it.

    (Only on Win7 when running as admin under the default UAC settings, though. It’s not the end of the world and you can stop it being possible if you modify your configuration.)

  12. Anonymous Coward says:

    One slight nitpick: it is possible to mark processes special in a way that not every process can do. To take the task manager example, you could let the kernel start the Ctrl-Alt-Del process in a special way (i.e. with a function unavailable to user mode code), for example storing a flag in some internal kernel data structure related to the process that enables some functions that other programs can’t call. That way, you could give task manager (or ProcessExplorer or some other task manager replacement) extra powers.

    Of course that doesn’t solve the mutex problem mentioned. At first glance it would appear to be bad design if a program could lock up all processes with higher priority by simply arranging to take a certain mutex, so let’s hope that this isn’t the case. But if it is, you could let the code that takes the mutex kill whoever’s got it if it doesn’t give it up within, say, three seconds. That functionality would only be available to special programs of course.

  13. Anonymous Coward says:

    I’ve thought about the mutex problem for a bit. The only situation where task manager would have to wait for a mutex to become available is where it needs access to a data structure (or similar shared resource) that is currently in an inconsistent state.

    Two observations: 1) All other situations can be rewritten without the mutex. 2) Killing the offender makes the situation worse.

    Since task manager can be written in such a way that it doesn’t share any of its own data structures, it follows that the data structure must be a system data structure (perhaps a structure of the kernel or some other system component; all other data structures that could be forced upon it could be warded off using the task manager’s special status). Therefore the mutex should be managed by the system and you can therefore design things in such a way that no process can monopolize it if a process with higher priority needs it.

    [The mutexes are indeed designed so no process holds it for very long, but if you suspend the thread while it owns the mutex, it never gets a chace to release it. -Raymond]
  14. avek says:

    >couldn’t task manager be rewritten inside of win32k.sys?

    Oh no!!! How will it be replaced then? It would be unbearable to go back to Task Manager from Process Explorer…

    Won’t save from mutex problem anyway.

    > But imho Explorer.exe is not *a* process, it is the upper layer of the OS

    "Upper layer of the OS" is something blurry in any OS influenced by microkernel ideas. Explorer is application-like in many ways. It can be replaced, and sometimes is. It’s also a thing that apps can easily mess with.

    > It makes sense to implement code-based permissions.

    In .NET style? Not very, as Raymond already pointed several times. Stacks within single process can be easily forged by unmanaged code.

    Still, it can be done at the level of executable images: CreateProcess, LoadLibrary, etc. become checkable barriers, and the .dll loads/process starts only if the file is both:

    – allowed to use for the caller of CreateProcess/LoadLibrary and

    – unchanged from the last time when the "allowed" setting was recorded.

    If any of the checks fails, user is asked to "allow" the executable/dll to be used again.

    There are personal firewalls and security software that do exactly this check. It works because the kernel and kernel-mode drivers can ensure the check, user-mode cannot fake it anymore.

    But this scheme alone isn’t very useful; those firewalls need to hook additional security-sensitive functions (both in kernel and user mode) to actually protect you. That’s because in WinAPI, the functions that need to be secured are not separated into their own .dlls.

    I think that’s why Windows itself doesn’t implement this scheme. Maybe MinWin will change that, but unlikely.

  15. Alexander Grigoriev says:

    @Leo Davidson,

    "(Only on Win7 when running as admin under the default UAC settings, though. It’s not the end of the world and you can stop it being possible if you modify your configuration.)"

    As Raymond likes to say, you’re already on another side of an airtight hatch…

  16. Teo says:

    The gory details about self-elevation are irrevelant. My point is that since 2009 vintage Windows *has* special executables that creates special processes. Which proves Raymond wrong.

  17. jon says:

    @Alexandor Grigoriev: Since anyone can get through the airtight hatch if they want, what’s the point of the hatch being there?

  18. Leo Davidson says:

    @Alexander Grigoriev:

    I’m not arguing about airtight hatches here; I’m saying that, like the example in the root post, you can’t give a processes special powers without effectively giving those powers to all processes (which are peers of the special process).

    (In my example, some processes are marked "special" while someone has gone out of their way to prevent other processes from being marked as special, yet those other processes can still become special by manipulating an existing special process.)

    So there’s little point in giving specific processes special powers via flags/checks which *aren’t* an airtight hatch. If you’re going to allow one process to bypass certain limits then you might as well allow all processes to do the same and save yourself a lot of needless complexity.

    (Another benefit is it makes things smoother for tools which augment or replace the ‘special’ processes, e.g. Task Manager / Process Explorer or Explorer / other file managers.)

  19. Anonymous Coward says:

    [The mutexes are … to release it. -Raymond]

    Phew! That’s a relief.

    So the only real way in which a mutex can screw up task manager is if you manage to suspend it just as it owns some user mode mutex (a mutex set by user mode code – as far as I know it’s normally impossible to suspend a thread while it’s in kernel mode) that task manager needs too.

    To solve that, you would need to make sure that task manager cannot be made to wait on a mutex possibly owned by suspendable code, which may be difficult if for example uxTheme is doing some internal locking. Still, if something like that can happen, something should be done about it, since I suspect the entire system would deadlock, not just task manager.

    But until such a situation is found the discussion is academic; I’ve suspended and resumed processes a lot and never had unrelated processes lock up on me.

    >>couldn’t task manager be rewritten inside of win32k.sys?

    >Oh no!!! How will it be replaced then? It would be unbearable to go back to Task Manager from Process Explorer…

    Indeed. Besides, I think my scheme would be more elegant.

    >I’m saying that, like the example in the root post, you can’t give a processes special powers without effectively giving those powers to all processes (which are peers of the special process).

    That is false. The IA32 architecture supports that since the nineties or so. The rest is merely a question of design and implementation. I’ve given a possible scheme in a previous post. I don’t know if it’s the absolute best way, but I think it’s workable.

    [While it could be done, making lower-level components aware of higher-level components would also be a violation of general engineering principles. Windows has been working to eradicate these violations not introduce new ones! -Raymond]
  20. Anonymous Coward says:

    [While it could … introduce new ones! -Raymond]

    That was not what I was suggesting; I apologize if I was unclear. I was merely suggesting that it is a) possible to give a process special powers (Windows already does this; for example there are processes running on my computer at the moment that don’t have regular file access) and b) that you could grant some of those powers if you start a process using Ctrl-Alt-Del. I don’t see why that would be a violation of ‘general engineering principles’ since there is nothing particular about the process started that the kernel needs to know, neither does the process need to know anything special to be able to use its special powers. It’s just good old permissions.

Comments are closed.