From 4c2c4f0fdc54f9bdb5371a108c3dc7886e6c81ec Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 9 May 2017 13:59:56 +0100 Subject: [PATCH] [Fix] Allow to follow symlinks when safe Issue: #1625 --- src/client/rspamc.c | 2 +- src/client/rspamdclient.c | 3 ++- src/fuzzy_storage.c | 5 +++-- src/libserver/dkim.c | 2 +- src/libserver/re_cache.c | 2 +- src/libutil/map.c | 4 ++-- src/libutil/multipattern.c | 4 ++-- src/libutil/util.c | 20 +++++++++++++------- src/libutil/util.h | 7 ++++--- src/lua/lua_cryptobox.c | 6 +++--- src/lua/lua_fann.c | 2 +- src/lua/lua_task.c | 2 +- src/lua/lua_util.c | 2 +- src/rspamadm/lua_repl.c | 2 +- src/rspamadm/signtool.c | 19 ++++++++++--------- src/rspamd_proxy.c | 6 +++--- 16 files changed, 49 insertions(+), 39 deletions(-) diff --git a/src/client/rspamc.c b/src/client/rspamc.c index 21b3fd6a3..2f09956ca 100644 --- a/src/client/rspamc.c +++ b/src/client/rspamc.c @@ -340,7 +340,7 @@ rspamc_password_callback (const gchar *option_name, if (value != NULL) { if (value[0] == '/' || value[0] == '.') { /* Try to open file */ - map = rspamd_file_xmap (value, PROT_READ, &sz); + map = rspamd_file_xmap (value, PROT_READ, &sz, 0); if (map == NULL) { /* Just use it as a string */ diff --git a/src/client/rspamdclient.c b/src/client/rspamdclient.c index 6ccdce5f5..7ea096183 100644 --- a/src/client/rspamdclient.c +++ b/src/client/rspamdclient.c @@ -352,7 +352,8 @@ rspamd_client_command (struct rspamd_client_connection *conn, } else { if (comp_dictionary) { - dict = rspamd_file_xmap (comp_dictionary, PROT_READ, &dict_len); + dict = rspamd_file_xmap (comp_dictionary, PROT_READ, &dict_len, + TRUE); if (dict == NULL) { g_set_error (err, RCLIENT_ERROR, errno, diff --git a/src/fuzzy_storage.c b/src/fuzzy_storage.c index 90f283b4a..50bc864bc 100644 --- a/src/fuzzy_storage.c +++ b/src/fuzzy_storage.c @@ -2762,7 +2762,8 @@ start_fuzzy (struct rspamd_worker *worker) if (ctx->collection_id_file) { gint fd; - fd = rspamd_file_xopen (ctx->collection_id_file, O_RDONLY, 0); + fd = rspamd_file_xopen (ctx->collection_id_file, O_RDONLY, 0, + FALSE); if (fd == -1) { if (errno != ENOENT) { @@ -2862,7 +2863,7 @@ start_fuzzy (struct rspamd_worker *worker) /* Try to save collection id */ fd = rspamd_file_xopen (ctx->collection_id_file, - O_WRONLY | O_CREAT | O_TRUNC, 00644); + O_WRONLY | O_CREAT | O_TRUNC, 00644, 0); if (fd == -1) { msg_err ("cannot open collection id to store in %s: %s", diff --git a/src/libserver/dkim.c b/src/libserver/dkim.c index eb8c193b5..3a314cac9 100644 --- a/src/libserver/dkim.c +++ b/src/libserver/dkim.c @@ -1973,7 +1973,7 @@ rspamd_dkim_sign_key_load (const gchar *what, gsize len, gchar fpath[PATH_MAX]; rspamd_snprintf (fpath, sizeof (fpath), "%*s", (gint)len, what); - map = rspamd_file_xmap (fpath, PROT_READ, &map_len); + map = rspamd_file_xmap (fpath, PROT_READ, &map_len, TRUE); if (map == NULL) { g_set_error (err, dkim_error_quark (), DKIM_SIGERROR_KEYFAIL, diff --git a/src/libserver/re_cache.c b/src/libserver/re_cache.c index 8d914c93a..2302ea8c8 100644 --- a/src/libserver/re_cache.c +++ b/src/libserver/re_cache.c @@ -1744,7 +1744,7 @@ rspamd_re_cache_is_valid_hyperscan_file (struct rspamd_re_cache *cache, close (fd); if (try_load) { - map = rspamd_file_xmap (path, PROT_READ, &len); + map = rspamd_file_xmap (path, PROT_READ, &len, TRUE); if (map == NULL) { msg_err_re_cache ("cannot mmap hyperscan cache file %s: " diff --git a/src/libutil/map.c b/src/libutil/map.c index c6a7189a8..1855ca5d5 100644 --- a/src/libutil/map.c +++ b/src/libutil/map.c @@ -180,7 +180,7 @@ rspamd_map_check_file_sig (const char *fname, if (bk->trusted_pubkey == NULL) { /* Try to load and check pubkey */ rspamd_snprintf (fpath, sizeof (fpath), "%s.pub", fname); - data = rspamd_file_xmap (fpath, PROT_READ, &len); + data = rspamd_file_xmap (fpath, PROT_READ, &len, TRUE); if (data == NULL) { msg_err_map ("can't open pubkey %s: %s", fpath, strerror (errno)); @@ -628,7 +628,7 @@ read_map_file (struct rspamd_map *map, struct file_map_data *data, return TRUE; } - bytes = rspamd_file_xmap (data->filename, PROT_READ, &len); + bytes = rspamd_file_xmap (data->filename, PROT_READ, &len, TRUE); if (bytes == NULL) { msg_err_map ("can't open map %s: %s", data->filename, strerror (errno)); diff --git a/src/libutil/multipattern.c b/src/libutil/multipattern.c index 35ef51a70..508ffcda9 100644 --- a/src/libutil/multipattern.c +++ b/src/libutil/multipattern.c @@ -470,7 +470,7 @@ rspamd_multipattern_try_load_hs (struct rspamd_multipattern *mp, rspamd_snprintf (fp, sizeof (fp), "%s/%*xs.hsmp", hs_cache_dir, (gint)rspamd_cryptobox_HASHBYTES / 2, hash); - if ((map = rspamd_file_xmap (fp, PROT_READ, &len)) != NULL) { + if ((map = rspamd_file_xmap (fp, PROT_READ, &len, TRUE)) != NULL) { if (hs_deserialize_database (map, len, &mp->db) == HS_SUCCESS) { munmap (map, len); return TRUE; @@ -500,7 +500,7 @@ rspamd_multipattern_try_save_hs (struct rspamd_multipattern *mp, rspamd_snprintf (fp, sizeof (fp), "%s/%*xs.hsmp.tmp", hs_cache_dir, (gint)rspamd_cryptobox_HASHBYTES / 2, hash); - if ((fd = rspamd_file_xopen (fp, O_WRONLY|O_CREAT|O_EXCL, 00644)) != -1) { + if ((fd = rspamd_file_xopen (fp, O_WRONLY | O_CREAT | O_EXCL, 00644, 0)) != -1) { if (hs_serialize_database (mp->db, &bytes, &len) == HS_SUCCESS) { if (write (fd, bytes, len) == -1) { msg_warn ("cannot write hyperscan cache to %s: %s", diff --git a/src/libutil/util.c b/src/libutil/util.c index 704d65041..593baf522 100644 --- a/src/libutil/util.c +++ b/src/libutil/util.c @@ -2114,7 +2114,7 @@ rspamd_open_zstd_dictionary (const char *path) struct zstd_dictionary *dict; dict = g_slice_alloc0 (sizeof (*dict)); - dict->dict = rspamd_file_xmap (path, PROT_READ, &dict->size); + dict->dict = rspamd_file_xmap (path, PROT_READ, &dict->size, TRUE); if (dict->dict == NULL) { g_slice_free1 (sizeof (*dict), dict); @@ -2418,7 +2418,8 @@ event_get_base (struct event *ev) #endif int -rspamd_file_xopen (const char *fname, int oflags, guint mode) +rspamd_file_xopen (const char *fname, int oflags, guint mode, + gboolean allow_symlink) { struct stat sb; int fd; @@ -2434,7 +2435,12 @@ rspamd_file_xopen (const char *fname, int oflags, guint mode) } #ifdef HAVE_ONOFOLLOW - fd = open (fname, oflags | O_NOFOLLOW, mode); + if (!allow_symlink) { + fd = open (fname, oflags | O_NOFOLLOW, mode); + } + else { + fd = open (fname, oflags, mode); + } #else fd = open (fname, oflags, mode); #endif @@ -2443,8 +2449,8 @@ rspamd_file_xopen (const char *fname, int oflags, guint mode) } gpointer -rspamd_file_xmap (const char *fname, guint mode, - gsize *size) +rspamd_file_xmap (const char *fname, guint mode, gsize *size, + gboolean allow_symlink) { gint fd; struct stat sb; @@ -2454,10 +2460,10 @@ rspamd_file_xmap (const char *fname, guint mode, g_assert (size != NULL); if (mode & PROT_WRITE) { - fd = rspamd_file_xopen (fname, O_RDWR, 0); + fd = rspamd_file_xopen (fname, O_RDWR, 0, allow_symlink); } else { - fd = rspamd_file_xopen (fname, O_RDONLY, 0); + fd = rspamd_file_xopen (fname, O_RDONLY, 0, allow_symlink); } if (fd == -1) { diff --git a/src/libutil/util.h b/src/libutil/util.h index 605822fee..7f6ccc2f6 100644 --- a/src/libutil/util.h +++ b/src/libutil/util.h @@ -479,7 +479,8 @@ struct event_base * event_get_base (struct event *ev); * @param mode mode to open * @return fd or -1 in case of error */ -int rspamd_file_xopen (const char *fname, int oflags, guint mode); +int rspamd_file_xopen (const char *fname, int oflags, guint mode, + gboolean allow_symlink); /** * Map file without following symlinks or special stuff @@ -488,8 +489,8 @@ int rspamd_file_xopen (const char *fname, int oflags, guint mode); * @param size target size (must NOT be NULL) * @return pointer to memory (should be freed using munmap) or NULL in case of error */ -gpointer rspamd_file_xmap (const char *fname, guint mode, - gsize *size); +gpointer rspamd_file_xmap (const char *fname, guint mode, gsize *size, + gboolean allow_symlink); /** * Map named shared memory segment diff --git a/src/lua/lua_cryptobox.c b/src/lua/lua_cryptobox.c index 0e28e52bb..4a2c62f8b 100644 --- a/src/lua/lua_cryptobox.c +++ b/src/lua/lua_cryptobox.c @@ -190,7 +190,7 @@ lua_cryptobox_pubkey_load (lua_State *L) filename = luaL_checkstring (L, 1); if (filename != NULL) { - map = rspamd_file_xmap (filename, PROT_READ, &len); + map = rspamd_file_xmap (filename, PROT_READ, &len, TRUE); if (map == NULL) { msg_err ("cannot open pubkey from file: %s, %s", @@ -1230,7 +1230,7 @@ lua_cryptobox_verify_file (lua_State *L) signature = lua_check_cryptobox_sign (L, 2); fname = luaL_checkstring (L, 3); - map = rspamd_file_xmap (fname, PROT_READ, &len); + map = rspamd_file_xmap (fname, PROT_READ, &len, TRUE); if (map != NULL && pk != NULL && signature != NULL) { ret = rspamd_cryptobox_verify (signature->str, map, len, @@ -1331,7 +1331,7 @@ lua_cryptobox_sign_file (lua_State *L) return luaL_error (L, "invalid arguments"); } - data = rspamd_file_xmap (filename, PROT_READ, &len); + data = rspamd_file_xmap (filename, PROT_READ, &len, TRUE); if (data == NULL) { msg_err ("cannot mmap file %s: %s", filename, strerror (errno)); diff --git a/src/lua/lua_fann.c b/src/lua/lua_fann.c index 7315de7ad..b74174fb7 100644 --- a/src/lua/lua_fann.c +++ b/src/lua/lua_fann.c @@ -493,7 +493,7 @@ lua_fann_data (lua_State *L) (void)lseek (fd, 0, SEEK_SET); - map = rspamd_file_xmap (fpath, PROT_READ, &sz); + map = rspamd_file_xmap (fpath, PROT_READ, &sz, TRUE); unlink (fpath); close (fd); diff --git a/src/lua/lua_task.c b/src/lua/lua_task.c index 4ca66bbb4..f58a6068e 100644 --- a/src/lua/lua_task.c +++ b/src/lua/lua_task.c @@ -4351,7 +4351,7 @@ lua_text_save_in_file (lua_State *L) mode = lua_tonumber (L, 3); } - fd = rspamd_file_xopen (fname, O_CREAT | O_WRONLY | O_EXCL, mode); + fd = rspamd_file_xopen (fname, O_CREAT | O_WRONLY | O_EXCL, mode, 0); if (fd == -1) { lua_pushboolean (L, false); diff --git a/src/lua/lua_util.c b/src/lua/lua_util.c index 6c6a4201f..4c674def8 100644 --- a/src/lua/lua_util.c +++ b/src/lua/lua_util.c @@ -1632,7 +1632,7 @@ lua_util_create_file (lua_State *L) mode = lua_tonumber (L, 2); } - fd = rspamd_file_xopen (fpath, O_RDWR|O_CREAT|O_EXCL, mode); + fd = rspamd_file_xopen (fpath, O_RDWR | O_CREAT | O_EXCL, mode, 0); if (fd == -1) { lua_pushnil (L); diff --git a/src/rspamadm/lua_repl.c b/src/rspamadm/lua_repl.c index 58c803e3e..e3656e8c9 100644 --- a/src/rspamadm/lua_repl.c +++ b/src/rspamadm/lua_repl.c @@ -352,7 +352,7 @@ rspamadm_lua_message_handler (lua_State *L, gint argc, gchar **argv) func_idx = lua_gettop (L); for (i = 2; argv[i] != NULL; i ++) { - map = rspamd_file_xmap (argv[i], PROT_READ, &len); + map = rspamd_file_xmap (argv[i], PROT_READ, &len, TRUE); if (map == NULL) { rspamd_printf ("cannot open %s: %s\n", argv[i], strerror (errno)); diff --git a/src/rspamadm/signtool.c b/src/rspamadm/signtool.c index 5965a736b..1acd46745 100644 --- a/src/rspamadm/signtool.c +++ b/src/rspamadm/signtool.c @@ -133,7 +133,8 @@ rspamadm_edit_file (const gchar *fname) map = NULL; /* Try to touch source anyway */ - fd_out = rspamd_file_xopen (fname, O_WRONLY|O_CREAT|O_EXCL, 00644); + fd_out = rspamd_file_xopen (fname, O_WRONLY | O_CREAT | O_EXCL, 00644, + 0); if (fd_out == -1) { rspamd_fprintf (stderr, "cannot open %s: %s\n", fname, @@ -144,7 +145,7 @@ rspamadm_edit_file (const gchar *fname) close (fd_out); } else { - map = rspamd_file_xmap (fname, PROT_READ, &len); + map = rspamd_file_xmap (fname, PROT_READ, &len, TRUE); if (map == NULL) { rspamd_fprintf (stderr, "cannot open %s: %s\n", fname, @@ -231,7 +232,7 @@ rspamadm_edit_file (const gchar *fname) } #endif - map = rspamd_file_xmap (tmppath, PROT_READ, &len); + map = rspamd_file_xmap (tmppath, PROT_READ, &len, TRUE); if (map == NULL) { rspamd_fprintf (stderr, "cannot map %s: %s\n", tmppath, @@ -241,8 +242,8 @@ rspamadm_edit_file (const gchar *fname) } rspamd_snprintf (run_cmdline, sizeof (run_cmdline), "%s.new", fname); - fd_out = rspamd_file_xopen (run_cmdline, O_RDWR|O_CREAT|O_TRUNC, - 00600); + fd_out = rspamd_file_xopen (run_cmdline, O_RDWR | O_CREAT | O_TRUNC, 00600, + 0); if (fd_out == -1) { rspamd_fprintf (stderr, "cannot open new file %s: %s\n", run_cmdline, @@ -288,7 +289,7 @@ rspamadm_sign_file (const gchar *fname, struct rspamd_cryptobox_keypair *kp) fd_input = rspamadm_edit_file (fname); } else { - fd_input = rspamd_file_xopen (fname, O_RDONLY, 0); + fd_input = rspamd_file_xopen (fname, O_RDONLY, 0, TRUE); } if (fd_input == -1) { @@ -300,7 +301,7 @@ rspamadm_sign_file (const gchar *fname, struct rspamd_cryptobox_keypair *kp) g_assert (fstat (fd_input, &st) != -1); rspamd_snprintf (sigpath, sizeof (sigpath), "%s%s", fname, suffix); - fd_sig = rspamd_file_xopen (sigpath, O_WRONLY | O_CREAT | O_TRUNC, 00644); + fd_sig = rspamd_file_xopen (sigpath, O_WRONLY | O_CREAT | O_TRUNC, 00644, 0); if (fd_sig == -1) { close (fd_input); @@ -392,7 +393,7 @@ rspamadm_verify_file (const gchar *fname, const guchar *pk) suffix = ".sig"; } - fd_input = rspamd_file_xopen (fname, O_RDONLY, 0); + fd_input = rspamd_file_xopen (fname, O_RDONLY, 0, TRUE); if (fd_input == -1) { rspamd_fprintf (stderr, "cannot open %s: %s\n", fname, @@ -403,7 +404,7 @@ rspamadm_verify_file (const gchar *fname, const guchar *pk) g_assert (fstat (fd_input, &st) != -1); rspamd_snprintf (sigpath, sizeof (sigpath), "%s%s", fname, suffix); - fd_sig = rspamd_file_xopen (sigpath, O_RDONLY, 0); + fd_sig = rspamd_file_xopen (sigpath, O_RDONLY, 0, TRUE); if (fd_sig == -1) { close (fd_input); diff --git a/src/rspamd_proxy.c b/src/rspamd_proxy.c index 71d3ecaab..e9858b0ba 100644 --- a/src/rspamd_proxy.c +++ b/src/rspamd_proxy.c @@ -1061,8 +1061,8 @@ proxy_check_file (struct rspamd_http_message *msg, if (tok) { file_str = rspamd_mempool_ftokdup (session->pool, tok); - session->map = rspamd_file_xmap (file_str, PROT_READ, - &session->map_len); + session->map = rspamd_file_xmap (file_str, PROT_READ, &session->map_len, + TRUE); if (session->map == NULL) { msg_err_session ("cannot map %s: %s", file_str, strerror (errno)); @@ -1091,7 +1091,7 @@ proxy_check_file (struct rspamd_http_message *msg, if (tok) { file_str = rspamd_mempool_ftokdup (session->pool, tok); session->map = rspamd_file_xmap (file_str, PROT_READ, - &session->map_len); + &session->map_len, TRUE); if (session->map == NULL) { msg_err_session ("cannot map %s: %s", file_str, strerror (errno)); -- 2.39.5