SECURITY - why zgv is setuid root, etc.
---------------------------------------

This file is an attempt to explain the approach zgv takes to security.
I know setuid binaries are scary things, but zgv isn't half as
insecure as some people seem to think. I wouldn't claim it's 100%
secure either, of course, but no-one with a clue would claim that of
anything. You could switch your box off permanently and seal it in
concrete, but you'd still be prone to explosives, for example. :-)

The discussion here is Linux-centric, but I'm assured that the
basic reasoning applies to FreeBSD too despite it dealing with
effective-ID a bit differently.


Now, zgv uses svgalib, and svgalib programs must be setuid root (or
otherwise run as root), that is, they must have rights to do just
about anything on the system. (There are certain exceptions - for
example, even root can't overwrite an immutable file without
explicitly clearing the immutable flag first.)

*However*, svgalib only needs root permissions for long enough to sort
a few things out :-), and ensure it has access to certain memory, I/O
ports, that sort of thing. It then uses setuid(getuid()) to
irretrievably drop root permissions. (svgalib 1.2.10 and earlier did
this incorrectly, but this has long since been fixed.) From the setuid
man page:

>        Under  Linux, setuid is implemented like the POSIX version
>        with the _POSIX_SAVED_IDS feature.  This allows  a  setuid
>        (other  than  root) program to drop all of its user privi-
>        leges, do some un-privileged work, and then re-engage  the
>        original effective user ID in a secure manner.

This sounds scary - a cracker (one with shell access, that is - and if
they're that far in you have problems already ;-)) could potentially
take advantage of a bug in zgv to get a root shell, right? Couldn't
they? Well, note the "other than root" above, and read on:

>        If the user is root or the program is setuid root, special
>        care must be taken. The setuid function checks the  effec-
>        tive  uid  of  the  caller and if it is the superuser, all
>        process related user ID's are set to uid.  After this  has
>        occurred,  it is impossible for the program to regain root
>        privileges.

Note the word "impossible" there. :-) This is not the seteuid()
scheme, where you can restore the root privileges; this is a
`trapdoor' approach. This limits greatly the amount of trouble a
cracker can cause with zgv - at most they can cause a
denial-of-service by leaving the console in graphics mode.

However, zgv has an additional early check (before doing anything
svgalib-related) to try and limit trouble further. It checks (for
users other than root) that the user running zgv owns the
currently-active console, i.e. *that they are logged in on it*. If
not, they don't get to run zgv at all, no matter what. So not only do
we have the `only runs as root very briefly' thing, but you can't even
run zgv in the first place unless you're *logged in at the console*!
And if you have a cracker logged in at the console, you *really* have
problems already! ;-)

I do recognise that you could have `untrusted' people logged in at the
console in certain circumstances - universities spring instantly to
mind. :-) And being able to leave the console in graphics mode would
be bad (m'kay). So zgv does take a certain amount of care to avoid at
least the obvious problems, like buffer overruns. (I think these are
all nailed now, but it's always possible I've missed one.)

So, no, zgv probably isn't the most secure program in the world. But
please let's not claim J. Random Cracker can walk all over it without
bothering to look at the code, eh? :^)

If you still don't feel like trusting zgv, you may want to try xzgv,
which lets you worry about trusting X instead. ;-)

Comments on/criticisms of/bugfixes for this file welcome.

-Rus.
