summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Layton <jlayton@samba.org>2017-02-15 10:00:45 -0500
committerJeff Layton <jlayton@samba.org>2017-02-15 11:07:01 -0500
commit109c189bf4720b0d7ed43113e1e26c89c8b15ada (patch)
tree94200c846f9a4f2d2bf08d27fe7abf4f415d23b2
parenta6662edb12b267e12bd67424e485ca081a97beb3 (diff)
downloadcifs-utils-109c189bf4720b0d7ed43113e1e26c89c8b15ada.tar.gz
cifs-utils-109c189bf4720b0d7ed43113e1e26c89c8b15ada.tar.bz2
cifs-utils-109c189bf4720b0d7ed43113e1e26c89c8b15ada.zip
cifs.upcall: drop capabilities early in program
Much of cifs.upcall can and should be run without elevated privileges. On entry into the program, drop as many capabilities as we can get away with, and then always drop any remaining caps after calling setuid(). Signed-off-by: Jeff Layton <jlayton@samba.org>
-rw-r--r--Makefile.am2
-rw-r--r--cifs.upcall.c64
2 files changed, 65 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 2e99e60..4823b63 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,7 +16,7 @@ clean-local: clean-local-upcall clean-local-idmap clean-local-cifsacl
if CONFIG_CIFSUPCALL
sbin_PROGRAMS += cifs.upcall
cifs_upcall_SOURCES = cifs.upcall.c data_blob.c asn1.c spnego.c
-cifs_upcall_LDADD = -ltalloc -lkeyutils $(KRB5_LDADD)
+cifs_upcall_LDADD = -ltalloc -lkeyutils $(KRB5_LDADD) $(CAPNG_LDADD)
man_MANS += cifs.upcall.8
#
diff --git a/cifs.upcall.c b/cifs.upcall.c
index 2b535a1..0bd3dcb 100644
--- a/cifs.upcall.c
+++ b/cifs.upcall.c
@@ -54,6 +54,10 @@
#include "spnego.h"
#include "cifs_spnego.h"
+#ifdef HAVE_LIBCAP_NG
+#include <cap-ng.h>
+#endif
+
static krb5_context context;
static const char *prog = "cifs.upcall";
@@ -63,6 +67,59 @@ typedef enum _sectype {
MS_KRB5
} sectype_t;
+#ifdef HAVE_LIBCAP_NG
+static int
+trim_capabilities(bool need_ptrace)
+{
+ capng_clear(CAPNG_SELECT_BOTH);
+
+ /*
+ * Need PTRACE and DAC_OVERRIDE for environment scraping, SETGID to
+ * change gid and grouplist, and SETUID to change uid.
+ */
+ if (capng_updatev(CAPNG_ADD, CAPNG_PERMITTED|CAPNG_EFFECTIVE,
+ CAP_SETUID, CAP_SETGID, CAP_DAC_OVERRIDE, -1)) {
+ syslog(LOG_ERR, "%s: Unable to update capability set: %m\n", __func__);
+ return 1;
+ }
+
+ if (need_ptrace &&
+ capng_update(CAPNG_ADD, CAPNG_PERMITTED|CAPNG_EFFECTIVE, CAP_SYS_PTRACE)) {
+ syslog(LOG_ERR, "%s: Unable to update capability set: %m\n", __func__);
+ return 1;
+ }
+
+ if (capng_apply(CAPNG_SELECT_BOTH)) {
+ syslog(LOG_ERR, "%s: Unable to apply capability set: %m\n", __func__);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+drop_all_capabilities(void)
+{
+ capng_clear(CAPNG_SELECT_BOTH);
+ if (capng_apply(CAPNG_SELECT_BOTH)) {
+ syslog(LOG_ERR, "%s: Unable to apply capability set: %m\n", __func__);
+ return 1;
+ }
+ return 0;
+}
+#else /* HAVE_LIBCAP_NG */
+static int
+trim_capabilities(void)
+{
+ return 0;
+}
+
+static int
+drop_all_capabilities(void)
+{
+ return 0;
+}
+#endif /* HAVE_LIBCAP_NG */
+
/*
* smb_krb5_principal_get_realm
*
@@ -733,6 +790,9 @@ int main(const int argc, char *const argv[])
}
}
+ if (trim_capabilities(false))
+ goto out;
+
/* is there a key? */
if (argc <= optind) {
usage();
@@ -837,6 +897,10 @@ int main(const int argc, char *const argv[])
goto out;
}
+ rc = drop_all_capabilities();
+ if (rc)
+ goto out;
+
rc = krb5_init_context(&context);
if (rc) {
syslog(LOG_ERR, "unable to init krb5 context: %ld", rc);