Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 22 Sep 2002 16:14:53 +0200
From:      Paul Schenkeveld <fb-hackers@psconsult.nl>
To:        FreeBSD Hackers <freebsd-hackers@freebsd.org>
Subject:   Just a wild idea
Message-ID:  <20020922161453.A13323@psconsult.nl>

next in thread | raw e-mail | index | archive | help
Hi All,

I've been playing with jails for over 2 years now.  I really like
them but we often use them to run a process as root with reduced
power only to get access to TCP and UDP ports below 1024.

For many applications however, for example lpd, named, sendmail,
tac_plus and others, it would be more than good enough to run that
program as a normal, non-root user provided there is a way to bind
to that single low TCP and/or UDP port that the program needs access
to.

So I was wondering if we couldn't come up with a method to allow the
startup of a normal non-root process with the only increased power
of being able to bind to a specific port.  This would be the opposite
of jail which allows the startup of a program as root and then tries
to revoke many powers.

I envision a system call (only accessible to root) that will grant
bind access to a single TCP or UDP port, which will persist even
after set*[ug]id calls and will be inherited by child processes and
a very small setuid root wrapper program to exercise that system
call, become a non-root user and then exec the real program.

The synopsis for the system call could be something like this:

    int portaccess(int version, int protocol, const struct sockaddr *addr);

where version works like with jail, protocol is either IPPROTO_TCP or
IPPROTO_UDP and the addr structure holds the port number (1 .. 1023)
and either INADDR_ANY or the ip address of one of the interfaces.
Multiple calls should accumulate access rights so programs like bind
could get access to both a UDP and TCP port.

The wrapper program then should be something like:

    portaccess [-i user:group] -{u|t} [address:]port ... cmd args

Where -i selects the identity obtained after all portaccess system calls
have been made (nobody/nogroup if omitted) and -u and -t add access to a
single port.  Finally if all portaccess and set*[ug]id calls have been
made an no error occured, execv is called with the remaining arguments
starting at cmd.

I understand that implementing this has quite some impact as we would
have to carry around all accumulated access rights in or near the proc
structure, the fork and exec calls need to be aware of this extra data
and the bind system call needs to do additional checking before refusing
access to a low TCP or UDP port but I think it's worth the efford.

I still like jail(2) and jail(8) very much for bigger purposes like
virtual hosts for shell logins or web hosting but I feel they are too
heavy for small problems like named which only needs access to UDP and
TCP ports 53 but can do everything else as a normal user.

Any thoughts?  Am I inventing something nobody is waiting for?  Is
something going on already that I am not aware of?

Please let me know.

Paul Schenkeveld, Consultant
PSconsult ICT Services BV

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020922161453.A13323>