summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Landden <slandden@gmail.com>2017-11-21 19:40:40 -0800
committerShawn Landden <slandden@gmail.com>2018-02-26 15:19:54 -0800
commitdfb45b528746bf89c030fccac307ebcf7c988511 (patch)
treebe304288a6e27d29f0460f049acd8123a6882ea7
parent23d362910b1a6b2dca8a8d49e84620dce7a1345a (diff)
downloaddistcc-git-dfb45b528746bf89c030fccac307ebcf7c988511.tar.gz
access control on having masquerade set up for binary
fixes the very old CVE-2004-2687 https://github.com/distcc/distcc/issues/155 at least unless gcc or clang can be exploited into executing arbitrary code-- but that is much more difficult than the current exploit. (C++ templates are turing complete [1], so it is probably possible) [1] http://web.archive.org/web/20131101122512/http://ubietylab.net/ubigraph/content/Papers/pdf/CppTuring.pdf
-rw-r--r--src/serve.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/src/serve.c b/src/serve.c
index 336a491..c9df132 100644
--- a/src/serve.c
+++ b/src/serve.c
@@ -357,6 +357,52 @@ static int dcc_check_compiler_masq(char *compiler_name)
return 0;
}
+/**
+ * Make sure there is a masquerade to distcc in /usr/lib/distcc in order to
+ * execute a binary of the same name.
+ *
+ * Before this it was possible to execute arbitrary command after connecting
+ * to distcc, which is quite a security risk when combined with any local root
+ * privledge escalation exploit. See CVE 2004-2687
+ *
+ * https://nvd.nist.gov/vuln/detail/CVE-2004-2687
+ * https://github.com/distcc/distcc/issues/155
+ **/
+static int dcc_check_compiler_whitelist(char *compiler_name)
+{
+ int dirfd = -1;
+ ssize_t len;
+ struct stat sb;
+ char linkbuf[MAXPATHLEN];
+
+ if (strchr(compiler_name, '/'))
+ return EXIT_BAD_ARGUMENTS;
+
+ dirfd = open("/usr/lib/distcc", O_RDONLY);
+ if (dirfd < 0) {
+ if (errno == ENOENT)
+ rs_log_crit("no %s", "/usr/lib/distcc");
+ return EXIT_DISTCC_FAILED;
+ }
+
+ if (fstatat(dirfd, compiler_name, &sb, AT_SYMLINK_NOFOLLOW) == -1)
+ return EXIT_BAD_ARGUMENTS; /* ENOENT, EACCESS, etc */
+ if (!S_ISLNK(sb.st_mode)) {
+ rs_trace("%s/%s is not a symlink", "/usr/lib/distcc", compiler_name);
+ return EXIT_BAD_ARGUMENTS;
+ }
+ if ((len = readlinkat(dirfd, compiler_name, linkbuf, sizeof linkbuf)) <= 0)
+ return EXIT_BAD_ARGUMENTS;
+ linkbuf[len] = '\0';
+
+ if (strstr(linkbuf, "distcc")) {
+ rs_trace("%s in /usr/lib/distcc whitelist", compiler_name);
+ return 0;
+ } else {
+ return EXIT_BAD_ARGUMENTS;
+ }
+}
+
static const char *include_options[] = {
"-I",
"-include",
@@ -669,11 +715,14 @@ static int dcc_run_job(int in_fd,
}
if (!dcc_remap_compiler(&argv[0]))
- goto out_cleanup;
+ goto out_cleanup;
if ((ret = dcc_check_compiler_masq(argv[0])))
goto out_cleanup;
+ if (dcc_check_compiler_whitelist(argv[0]))
+ goto out_cleanup;
+
if ((compile_ret = dcc_spawn_child(argv, &cc_pid,
"/dev/null", out_fname, err_fname))
|| (compile_ret = dcc_collect_child("cc", cc_pid, &status, in_fd))) {