On Mon, Sep 01, 2003 at 11:31:51PM +0000, Andreas Schwarz wrote:
> > The way to do it safely is for the program to bind to the port
> > early and then set its effective user id to something else before
> > doing anything else.
> 
> Thanks, "Process.euid = 1000" works. What is the difference between uid
> and euid?

The euid is the one that matters for permission checks.  The real uid
is primarily informative, but it's also a constraint on the legal values
of the euid.

When you start up a new process on UNIX, that process inherits both uids
from its parent.  The effective uid is normally the same as the real uid;
however, if a process exec()s a program which is owned by a different uid
and has the setuid bit set, then the effective uid is set to match the owner
of the executable file instead.

You can actually change both values.  If either uid is root, then
you can set either uid to anything you want.   If neither uid is
root, then the only legal values for either uid are the current
values of those uids.  

However, on modern POSIX-compliant systems, there's also a third uid,
which is not directly accessible to the process, but is available as
a legal value of the other uids.  This is called the "saved" uid.
It allows a program to start up as root, set both the real and
effective uids to a non-root value, and then later set either one
back to root, because the OS remembers that the process used to
have a root uid.

So for example, if I'm logged in as 'mreed' and I execute a program
owned by 'aschwarz' that's setuid, then the new process will have
a real uid of 'mreed' and an effective uid of 'aschwarz'.  All
file access checks, etc., made by that program will check against
the permissions applicable to 'aschwarz', not 'mreed'.  The
program can then set its real uid to 'aschwarz' or its effective
uid to 'mreed', or both simultaneously (via a system call called
setreuid(2) that lets you set both values at once).  Once the two
values match, however, the program can no longer change either one.

> I'm also interested in examples of some "real world" ruby servers,
> because I would like to know how to limit the number of threads per
> client, the number of total threads and things like that.

I don't have any TCP servers written in Ruby, I'm afraid.  But 
it seems like you can have a single process do the accept(),
then check the configuration parameters and only start up a new
Thread if within the limits.  Serializing the accept()s within
a single thread might be a performance bottleneck if you have a
large number of nearly simultaneous requests, but if you're worried
about DoS attacks, that's a good thing.