<sect>Priveleges and Running as User<label id="priv">
This section written by Hans Lermen 
<htmlurl url="mailto:lermen@fgan.de" name="&lt;lermen@fgan.de&gt;">
, Apr 6, 1997.
And updated by Eric Biederman
<htmlurl url="mailto:ebiederm+eric@npwt.net" name="&lt;ebiederm+eric@npwt.net&gt;">
30 Nov 1997.


<p>
<sect1>What we were suffering from
<p>
   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 <em/where/ we need to handle privs was a great work and is yet worth.
   ... but sorry, <em/how/ it was handled didn't work.
<p>
   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.
<p>   
   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 <em/default/ one.
<p>
   (promise: I'll also will run dosemu as user before releasing,
    so that I can see, if something goes wrong with it ;-)

<p>
<verb>Enter Eric: </verb>
<p>
   What we have been suffering from lately is that threads were added to
   dosemu, and the stacks Hans added when he did it 'the right way (tm)'
   were all of a sudden large static variables that could not be kept
   consistent.  That and hans added caching of the curent uids for
   efficiency in dosemu, again more static variables.  
<p>
   When I went through the first time and added all of the strange
   unmaintainable things Hans complains of above, and found where
   priveleges where actually needed I hand't thought it was as bad as Hans
   perceived it, so I had taken the lazy way out.  That and my main concern
   was to make the privelege setting consistent enough to not give
   mysterous erros in dosemu.  But I had comtemplated doing it 'the right
   way (tm)' and my scheme for doing it was a bit different from the way
   Hans did it. 
<p>
   With Hans the stack was explicit but hidden behind the scenes.  With my
   latest incarnation the stack is even more explicit.  The elements of the
   privelege stack are now local variables in subroutines.  And these local
   variables need to be declared explicitly in a given subroutine.  This
   method isn't quite a fool proof as Han's method, but a fool could mess up
   Hans's method up as well.  And any competent person should be able to
   handle a local variable, safely.
<p>
   For the case of the static cached uid I have simply placed them in the
   thread control block.  The real challenge in integrating the with the
   thread code is the thread code was using root priveleges and changing
   it's priveleges with the priv code during it's initialization.   For the
   time being I have disabled all of the thread code's mucking with root
   priveleges, and placed it's initialization before the privelege code's
   initialization.  We can see later if I can make Han's thread code work
   `the right way (tm)' as he did for my privelege code.

<p>
<verb>ReEnter Hans:  ;-) </verb>
<p>

   In order to have more checking wether we (not an anonymous fool) are
   forgetting something on the road, I modified Erics method such that
   the local variable is declared by a macro and preset with a magic,
   that is checked in priv.c. The below explanations reflect this change.


<sect1>The new 'priv stuff'
<p>
This works as follows

<itemize>
   <item> All settings have to be done in 'pairs' such as

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

   <item> On enter_priv_XXX() the current state will be saved (pushed) on a
      local variable on the stack and later restored from that on
      leave_priv_setting(). This variable is has to be defined at
      entry of each function (or block), that uses a enter/leave_priv bracket.
      To avoid errors it has to be defined via the macro PRIV_SAVE_AREA.
      The 'stack depth' is just _one_ and is checked to not overflow.
      The enter/leave_priv_* in fact are macros, that pass a pointer to
      the local privs save area to the appropriate 'real_' functions.
      ( this way, we can't forget to include priv.h and PRIV_SAVE_AREA )
      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.

   <item> We now have the system calls (getuid, setreuid, etc.) <em/only/ in
      src/base/misc/priv.c. We cash the setting and don't do unnecessary
      systemcalls. Hence NEVER call 'getuid', 'setreuid' etc. 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 <em/real/ and the cached one).

   <item> In case of dosemu was started out of a root login, we skip 
      <em/all/ priv-settings. There is a new variable 'under_root_login'
      which is only set when dosemu is started from a root login.

   <item> 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.
</itemize>

   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' ;-)
<p>
   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 ;-)

<p>
<verb>Enter Eric: </verb>
<p>
   The current goal is to have a non suid-root dosemu atleast in X,
   lacking some features. But the reason I disabled it when I first introduced
   the infamous in this file priv_on/priv_default mechanism is that it hasn't
   been tested yet, still stands.  What remains to do is an audit of what
   code _needs_ root permissions, what code could benefit with a sgid dosemu,
   and what code just uses root permissions because when we are suid root some
   operations can only been done as root.
<p>
   When the audit is done (which has started with my most recent patch (I
   now know what code to look at)).  It should be possible to disable
   options that are only possible when we are suid root, at dosemu
   configuration time.  Then will be the task of finding ways to do things
   without root permissions.

<p>
<verb>Enter Hans (960626): </verb>
<p>
   Last <em/act/ of this story: DOSEMU now can run <em/non-/suid root and
   though it looses a lot of features because of not beeing able to run on
   console in this mode or not able to do any ports stuff e.t.c., its quite
   useable under X (I was even able to run win31, hence  DPMI is secure now
   with the s-bit off).

   The names of some variables where changed, such that it conforms more
   to what they now do: i_am_root became can_do_root_stuff, and
   under_root_login was splitted into the static skip_priv_setting,
   while the global valiable under_root_login keeps its meaning.

   skip_priv_setting is set for both: running as root <em/and/ running as
   user non-suid root. can_do_root_stuff is global and used in the same
   places were i_am_root was used before.

   On start of DOSEMU, we now call parse_dosemu_users() directly
   after priv_init(), and this is top of main(). This way we catch any
   hacker attack quite early and should be <em/much/ securer as ever before.

   Additionally, parse_dosemu_users now checks for the keyword `nosuidroot'
   in /etc/dosemu.users and if this is found for a user, this user is not
   allowed to execute DOSEMU on a suid root binary (though he can use
   a non-suid root copy of it) and dosemu will exit in this case.
   Dropping all priviledges on a suid root binary and continue (as if
   the -s bit wasn't set) is not possible, because /proc/self/mem has
   the ownership of the suid binary (hence root) and dosemu would crash
   later, when trying to open it. Do a chown on /proc/self/mem doesn't
   work either.

   The last action to make the non-suid root stuff working, was moving
   the files from /var/run/* to some user accessable location. This
   now is ~/.dosemu/* and dosdebug was adapted to support that.

