commit 0257ca0c6ce27cc8d48323f5fc4f079c7f455b93
parent f05b37667624eb178a0d856da339d003f7d63b6e
Author: Laurent Bercot <ska-skaware@skarnet.org>
Date: Thu, 29 Jan 2015 11:49:26 +0000
I changed my mind. Added access control for listing to s6-fdholderd.
Diffstat:
2 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/doc/s6-fdholderd.html b/doc/s6-fdholderd.html
@@ -186,8 +186,11 @@ rulesdir as an example, but a rulesfile works the same way):
<ul>
<li> Connect to the server. This is a prerequisite for
doing anything. It will allow a client to perform "public" operations,
-ones that do not require specific access rights other than connecting:
-for instance, listing all identifiers. This right is given if an
+ones that do not require specific access rights other than connecting.
+(There are no such operations for now, but it could change in the
+future; for now, when you allow a client to connect to the server,
+make sure to give him other rights too.)
+ This right is given if an
<tt>allow</tt> file is found in one of the subdirectories checked by
<a href="libs6/accessrules.html#uidgid">s6_accessrules_keycheck_uidgid</a>.
For instance, to allow everyone to connect, touch
@@ -223,6 +226,11 @@ set of identifiers that the client is allowed to use to retrieve file
descriptors. For instance, <tt>^unix:/tmp/</tt> indicates that a client
that matches this rule will be allowed to retrieve file descriptors that are
identified by strings starting with <tt>unix:/tmp/</tt>. </li>
+ <li> Listing rights. This will be checked for clients wanting to list
+the identifiers of the descriptors currently stored in the server. This
+right is given if a non-empty file named <tt>S6_FDHOLDER_LIST</tt> is
+found in the <tt>env/</tt> subdirectory of one of the subdirectories checked by
+<a href="libs6/accessrules.html#uidgid">s6_accessrules_keycheck_uidgid</a>. </li>
<li> Dump reading rights. This will be checked for clients wanting to
copy the whole state of the server. This right is given if a non-empty
file named <tt>S6_FDHOLDER_GETDUMP</tt> is found is the <tt>env/</tt>
@@ -298,9 +306,8 @@ hand, it makes little sense to fd-hold regular files, and if done anyway,
the results can be surprising, because the read/write file offset is
stored with the descriptor, and no automatic rewind is performed by the
daemon. </li>
- <li> Anyone that is allowed to connect is allowed to read the whole list
-of identifiers. This is intentional: identifiers should be public and
-well-known, and the security of the system should not depend on a client
+ <li> Despite there being access control for listing, the security of the
+system should not depend on a client
not knowing what identifier a certain descriptor is stored under. If you
need to hold descriptors that only a few programs are supposed to access,
you can always run a separate s6-fdholderd instance in a private directory
diff --git a/src/fdholder/s6-fdholderd.c b/src/fdholder/s6-fdholderd.c
@@ -316,6 +316,7 @@ static int do_list (unsigned int cc, unixmessage_t const *m)
siovec_t *vp = v + 1 ;
char pack[5] = "" ;
if (c->dumping || m->len || m->nfds) return (errno = EPROTO, 0) ;
+ if (!(c->flags & 4)) return answer(c, EPERM) ;
uint32_pack_big(pack + 1, (uint32)numfds) ;
v[0].s = pack ; v[0].len = 5 ;
genset_iter(fdstore, &fill_siovec_with_ids_iter, &vp) ;
@@ -554,6 +555,7 @@ static inline int parse_env (char const *const *envp, regex_t *rre, regex_t *wre
{
if (str_start(*envp, "S6_FDHOLDER_GETDUMP=")) fl |= 1 ;
if (str_start(*envp, "S6_FDHOLDER_SETDUMP=")) fl |= 2 ;
+ if (str_start(*envp, "S6_FDHOLDER_LIST=")) fl |= 4 ;
if (!rre_done)
{
rre_done = makere(rre, *envp, "S6_FDHOLDER_RETRIEVE_REGEX") ;
@@ -675,9 +677,9 @@ int main (int argc, char const *const *argv, char const *const *envp)
strerr_diefu1sys(111, "getrlimit") ;
if (fdlimit.rlim_cur != RLIM_INFINITY)
{
- if (fdlimit.rlim_cur < 6)
+ if (fdlimit.rlim_cur < 7)
strerr_dief1x(111, "open file limit too low") ;
- if (maxfds > fdlimit.rlim_cur) maxfds = fdlimit.rlim_cur - 5 ;
+ if (maxfds > fdlimit.rlim_cur) maxfds = fdlimit.rlim_cur - 6 ;
}
}
if (!maxfds) maxfds = 1 ;