Permalink
Browse files

Complete DAC bypass feature

Fix a bug in the last commit that prevented DAC_BYPASS from taking
effect.  Also set CAP_MKDIR.  Revert changes to fstest as all the
supplementary group tests can pass now (issue 37).

Drop supplementary group regression tests.
  • Loading branch information...
1 parent 46bacf4 commit 4604f3f08ca15aa63cea8d18331d51737a27a11a @garlick garlick committed Jun 16, 2011
View
@@ -5,14 +5,18 @@
To build all of diod's features, you need a few prerequisites:
lua, lua-devel (version 5.1 or better) [on debian/ubuntu liblua5.1-dev]
- For config file support.
+ For /etc/diod.conf config file support.
munge, munge-libs, munge-devel
- For authentication support.
+ For MUNGE authentication support.
tcp_wrappers, tcp_wrappers-libs, tcp_wrappers-devel
For TCP wrapper support.
+ libcap, libcap-devel
+ Necessary for correct handling of supplemental groups when
+ server is running as root (DAC check is delegated to client).
+
Note: on Debian/Ubuntu, LUA requires the following configure flags:
./configure CPPFLAGS="-I/usr/include/lua5.1" --with-lua-suffix=5.1
View
@@ -194,6 +194,7 @@ struct Npwthread {
pthread_t thread;
u32 fsuid;
u32 fsgid;
+ int privcap;
Npwthread *next;
};
View
@@ -231,6 +231,7 @@ np_wthread_create(Nptpool *tp)
wt->shutdown = 0;
wt->fsuid = geteuid ();
wt->fsgid = getegid ();
+ wt->privcap = (wt->fsuid == 0 ? 1 : 0);
if ((err = pthread_create(&wt->thread, NULL, np_wthread_proc, wt))) {
np_uerror (err);
goto error;
View
@@ -36,7 +36,7 @@
#include <sys/fsuid.h>
#include <pwd.h>
#include <grp.h>
-#if HAVE_LIBPCAP
+#if HAVE_LIBCAP
#include <sys/capability.h>
#endif
#include <assert.h>
@@ -520,6 +520,58 @@ np_afid2user (Npfid *afid, Npstr *uname, u32 n_uname)
return u;
}
+#if HAVE_LIBCAP
+/* When handling requests on connections authenticated as root, we consider
+ * it safe to disable DAC checks on the server and presume the client is
+ * doing it. This is done to fix a problem - no supplemental group eqiuvalent
+ * to setfsgid. Punt supplemental group checks to the client.
+ * N.B. if not on a connection that is root-authenticated, DAC checks will be
+ * performed using the primary uid:gid only.
+ */
+static int
+_chg_privcap (Npsrv *srv, cap_flag_value_t val)
+{
+ cap_t cap;
+ cap_flag_value_t cur;
+ cap_value_t cf[] = { CAP_DAC_OVERRIDE, CAP_CHOWN };
+ int need_set = 0;
+ int i, ret = -1;
+
+ if (!(cap = cap_get_proc ())) {
+ np_uerror (errno);
+ np_logerr (srv, "cap_get_proc failed");
+ goto done;
+ }
+ for (i = 0; i < sizeof(cf) / sizeof(cf[0]); i++) {
+ if (cap_get_flag (cap, cf[i], CAP_EFFECTIVE, &cur) < 0) {
+ np_uerror (errno);
+ np_logerr (srv, "cap_get_flag failed");
+ goto done;
+ }
+ if (cur == val)
+ continue;
+ need_set = 1;
+ if (cap_set_flag (cap, CAP_EFFECTIVE, 1, &cf[i], val) < 0) {
+ np_uerror (errno);
+ np_logerr (srv, "cap_set_flag failed");
+ goto done;
+ }
+ }
+ if (need_set && cap_set_proc (cap) < 0) {
+ np_uerror (errno);
+ np_logerr (srv, "cap_set_proc failed");
+ goto done;
+ }
+ ret = 0;
+done:
+ if (cap != NULL && cap_free (cap) < 0) {
+ np_uerror (errno);
+ np_logerr (srv, "cap_free failed");
+ }
+ return ret;
+}
+#endif
+
/* Note: it is possible for setfsuid/setfsgid to fail silently,
* e.g. if user doesn't have CAP_SETUID/CAP_SETGID.
* That should be checked at server startup.
@@ -536,7 +588,10 @@ np_setfsid (Npreq *req, Npuser *u, u32 gid_override)
np_conn_get_authuser(req->conn, &authuid);
if ((srv->flags & SRV_FLAGS_SETFSID)) {
- if (gid_override != -1 && u->uid != 0
+ /* gid_override must be one of user's suppl. groups unless
+ * connection was originally authed as root (trusted).
+ */
+ if (gid_override != -1 && u->uid != 0 && authuid != 0
&& !(srv->flags & SRV_FLAGS_NOUSERDB)) {
for (i = 0; i < u->nsg; i++) {
if (u->sg[i] == gid_override)
@@ -589,37 +644,25 @@ np_setfsid (Npreq *req, Npuser *u, u32 gid_override)
wt->fsuid = P9_NONUNAME;
goto done;
}
+ if (u->uid == 0)
+ wt->privcap = 1; /* transiton to 0 sets caps */
+ else if (u->uid != 0 && wt->fsuid == 0)
+ wt->privcap = 0; /* trans from 0 clears caps */
wt->fsuid = u->uid;
}
}
-#if HAVE_LIBPCAP
+#if HAVE_LIBCAP
if ((srv->flags & SRV_FLAGS_DAC_BYPASS) && wt->fsuid != 0) {
- cap_t cap;
- cap_flag_value_t val;
- cap_flag_value_t wantval = (authuid == 0 ? CAP_SET : CAP_CLEAR);
- cap_value_t capflag = CAP_DAC_OVERRIDE;
-
- if (!(cap = cap_get_proc ())) {
- np_uerror (errno);
- np_logerr (srv, "cap_get_proc failed");
- goto done;
- }
- if (cap_get_flag (cap, capflag, CAP_EFFECTIVE, &val) < 0) {
- np_uerror (errno);
- np_logerr (srv, "cap_get_flag failed");
- goto done;
- }
- if (val != wantval && cap_set_flag (cap, CAP_EFFECTIVE,
- 1, &capflag, wantval) < 0) {
- np_uerror (errno);
- np_logerr (srv, "cap_set_flag failed");
- goto done;
+ if (!wt->privcap && authuid == 0) {
+ if (_chg_privcap (srv, CAP_SET) < 0)
+ goto done;
+ wt->privcap = 1;
+ } else if (wt->privcap && authuid != 0) {
+ if (_chg_privcap (srv, CAP_CLEAR) < 0)
+ goto done;
+ wt->privcap = 0;
}
- if (cap_free (cap) < 0) {
- np_uerror (errno);
- np_logerr (srv, "cap_free failed");
- goto done;
- }
+
}
#endif
ret = 0;
@@ -1,31 +1,3 @@
-fstest modified for diod - distributed I/O daemon.
-
-fstest uncovered a problem with diod: switching effective group id or
-supplemental groups and expecting that change to affect the result of
-an p9_lopen or p9_setattr call does not work. A number of tests,
-documented in diod issue 37 on google code, expect this to work.
-It is a legitimate POSIX expectation.
-
-http://code.google.com/p/diod/issues/detail?id=37
-
-In the interest of making fstest a viable regression test for diod,
-this copy has been modified so the tests that had that particular
-expectation now pass. Some remain effective tests, some are now rendered
-ineffective.
-
-To run fstest, "remount" an ext3 file system like say /tmp on /mnt
-with diod running with the --no-auth) and --no-userdb options, e.g.
-
- # diod -N -n -e /tmp
- # mount -t diod localhost:/tmp /mnt
- # cd /mnt
- # prove -r /path/to/fstest
-
-Jim Garlick
-10 May 2011
-
----------
-
$FreeBSD: src/tools/regression/fstest/README,v 1.1 2007/01/28 00:10:28 pjd Exp $
Few notes on how to use fstest in short steps:
Oops, something went wrong.

0 comments on commit 4604f3f

Please sign in to comment.