What we were suffering from
---------------------------

   Well, I got sick with the complaints about 'have problems running as user'
   and did much effort to 'learn' about what we were doing with priv-settings.
   To make it short: It was a real mess, there was the whole dosemu history
   of different strategies to reach the same aim. Well, this didn't make
   it clearer. I appreciate all the efforts that were done by a lot of people
   in the team to make that damn stuff working, and atleast finding all those
   places _where_ we need to handle privs was a great work and is yet worth.
   ... but sorry, _whow_ it was handled didn't work.

   The main odds happened because sometimes functions, that were called
   within a priv_on/off()...priv_default() brackets were calling
   priv_on/off()...priv_default() themselves. And with introduction of this
   priv_default() macro, which handled the 'default' case (run as user or
   run as root) the confusion was complete. Conclusion: recursive settings
   were not handled, and you always had to manually keep track of wether
   privs were on or off. ... terrible and not maintainable.
   
   Therefore I decided to do it 'the right way (tm)' and overworked it
   completely. The only thing that now remains to do, is to check for more
   places where we have to temporary allow/disallow root priviledges. I also
   decided to be a good boy and make 'RUN_AS_ROOT' a compile time option
   and 'run as user' the _default_ one.
   (promise: I'll also will run dosemu as user before releasing,
    so that I can see, if something goes wrong with it ;-)


The new 'priv stuff' works as follows:
-------------------------------------

   1. All settings have to be done in 'pairs' such as

        enter_priv_on();   /* need to have root access for 'do_something' */
        do_something();
        leave_priv_setting();
      or
        enter_priv_off();  /* need pure user access for 'do_something' */
        do_something();
        leave_priv_setting();

   2. On enter_priv_XXX() the current state will be saved (pushed) on a
      socalled 'privilege stack' and restored (popped) by leave_priv_setting();
      Hence, you never again have to worry about previous priv settings,
      and whenever you feel you need to switch off or on privs, you can do it
      without coming into trouble.

   3. We now have the system calls (getuid, setreuid, e.t.c) _only_ in
      src/base/misc/priv.c. We cash the setting and don't do unnecessary
      systemcalls. Hence NEVER call 'getuid', 'setreuid' e.t.c yourself,
      instead use the above supplied functions. The only places where I
      broke this 'holy law' myself was when printing the log, showing both
      values (the _real_ and the cashed on).

   4. In case of dosemu was startet out of a root login, we skip 
      _all_ priv-settings. There is a new variable 'under_root_login'
      which is only set when dosemu is started from a root login.

   5. On all places were iopl() is called outside a enter_priv...leave_priv
      bracket, the new priv_iopl() function is to be used in order to
      force privileges.

   This is much cleaner and 'automagically' also solves the problem
   with the old 'priv_off/default' sheme. Because, 'running as user' just
   needs to do _one_ priv_off at start of dosemu, if we don't do it we are
   'running as root' ;-)

   A last remark: Though it may be desirable to have a non suid root dosemu,
   this is not possible. Even if we get GGI in the official kernel, we can't
   solve the problems with port access (which we need for a lot of DOS apps)
   ... and ioperm() / iopl() need root privileges.
   This leads to the fact that 'i_am_root' will be always '1', makeing
   it a macro gives GCC a changes optimize away the checks for it.
   We will leave 'i_am_root' in, maybe there is some day in the future
   that gives us a kernel allowing a ports stuff without root privilege,
   ... never say never ;-)


Hans Lermen, Apr 6, 1997
