[exim-cvs] first go. crashes in 0003

トップ ページ
このメッセージを削除
このメッセージに返信
著者: Exim Git Commits Mailing List
日付:  
To: exim-cvs
題目: [exim-cvs] first go. crashes in 0003
Gitweb: https://git.exim.org/exim.git/commitdiff/d56e798eb66ac044ff22f0daa2185549f5d49632
Commit:     d56e798eb66ac044ff22f0daa2185549f5d49632
Parent:     3109898a5e815a04f505c73b67493ef15d9f0665
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Mon May 10 22:47:01 2021 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Mon Jun 28 00:30:02 2021 +0100


    first go.  crashes in 0003
---
 src/src/exim.c      |  29 +++++++++++----
 src/src/functions.h |   1 +
 src/src/readconf.c  | 104 +++++++++++++++++++++++++---------------------------
 src/src/store.c     |  41 ++++++++++++++++++---
 src/src/store.h     |   4 +-
 5 files changed, 111 insertions(+), 68 deletions(-)


diff --git a/src/src/exim.c b/src/src/exim.c
index 6a9a147..eb1d834 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -3688,7 +3688,7 @@ else
{
struct rlimit rlp;

-  #ifdef RLIMIT_NOFILE
+#ifdef RLIMIT_NOFILE
   if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
     {
     log_write(0, LOG_MAIN|LOG_PANIC, "getrlimit(RLIMIT_NOFILE) failed: %s",
@@ -3711,9 +3711,9 @@ else
           strerror(errno));
       }
     }
-  #endif
+#endif


-  #ifdef RLIMIT_NPROC
+#ifdef RLIMIT_NPROC
   if (getrlimit(RLIMIT_NPROC, &rlp) < 0)
     {
     log_write(0, LOG_MAIN|LOG_PANIC, "getrlimit(RLIMIT_NPROC) failed: %s",
@@ -3721,20 +3721,20 @@ else
     rlp.rlim_cur = rlp.rlim_max = 0;
     }


-  #ifdef RLIM_INFINITY
+# ifdef RLIM_INFINITY
   if (rlp.rlim_cur != RLIM_INFINITY && rlp.rlim_cur < 1000)
     {
     rlp.rlim_cur = rlp.rlim_max = RLIM_INFINITY;
-  #else
+# else
   if (rlp.rlim_cur < 1000)
     {
     rlp.rlim_cur = rlp.rlim_max = 1000;
-  #endif
+# endif
     if (setrlimit(RLIMIT_NPROC, &rlp) < 0)
       log_write(0, LOG_MAIN|LOG_PANIC, "setrlimit(RLIMIT_NPROC) failed: %s",
         strerror(errno));
     }
-  #endif
+#endif
   }


/* Exim is normally entered as root (but some special configurations are
@@ -3857,6 +3857,7 @@ is equivalent to the ability to modify a setuid binary!
This needs to happen before we read the main configuration. */
init_lookup_list();

+/*XXX this excrescence could move to the testsuite standard config setup file */
#ifdef SUPPORT_I18N
if (f.running_in_test_harness) smtputf8_advertise_hosts = NULL;
#endif
@@ -3895,19 +3896,21 @@ issues (currently about tls_advertise_hosts and keep_environment not being
defined) */

{
+ int old_pool = store_pool;
#ifdef MEASURE_TIMING
struct timeval t0, diff;
(void)gettimeofday(&t0, NULL);
#endif

+ store_pool = POOL_CONFIG;
readconf_main(checking || list_options);
+ store_pool = old_pool;

#ifdef MEASURE_TIMING
report_time_since(&t0, US"readconf_main (delta)");
#endif
}

-
/* Now in directory "/" */

if (cleanup_environment() == FALSE)
@@ -4494,7 +4497,13 @@ if (msg_action_arg > 0 && msg_action != MSG_DELIVER && msg_action != MSG_LOAD)
event_action gets expanded */

   if (msg_action == MSG_REMOVE)
+    {
+    int old_pool = store_pool;
+    store_pool = POOL_CONFIG;
     readconf_rest();
+    store_pool = old_pool;
+    store_writeprotect(POOL_CONFIG);
+    }


   if (!one_msg_action)
     {
@@ -4519,12 +4528,16 @@ Now, since the intro of the ${acl } expansion, ACL definitions may be
 needed in transports so we lost the optimisation. */


{
+ int old_pool = store_pool;
#ifdef MEASURE_TIMING
struct timeval t0, diff;
(void)gettimeofday(&t0, NULL);
#endif

+ store_pool = POOL_CONFIG;
readconf_rest();
+ store_pool = old_pool;
+ store_writeprotect(POOL_CONFIG);

 #ifdef MEASURE_TIMING
   report_time_since(&t0, US"readconf_rest (delta)");
diff --git a/src/src/functions.h b/src/src/functions.h
index e349721..38c8e40 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -527,6 +527,7 @@ extern int     stdin_ungetc(int);


 extern void    store_exit(void);
 extern void    store_init(void);
+extern void    store_writeprotect(int);


extern gstring *string_append(gstring *, int, ...) WARN_UNUSED_RESULT;
extern gstring *string_append_listele(gstring *, uschar, const uschar *) WARN_UNUSED_RESULT;
diff --git a/src/src/readconf.c b/src/src/readconf.c
index 34ebf87..4602dd2 100644
--- a/src/src/readconf.c
+++ b/src/src/readconf.c
@@ -3142,55 +3142,54 @@ while((filename = string_nextinlist(&list, &sep, big_buffer, big_buffer_size)))

/* Cut out all the fancy processing unless specifically wanted */

- #if defined(CONFIGURE_FILE_USE_NODE) || defined(CONFIGURE_FILE_USE_EUID)
+#if defined(CONFIGURE_FILE_USE_NODE) || defined(CONFIGURE_FILE_USE_EUID)
uschar *suffix = filename + Ustrlen(filename);

/* Try for the node-specific file if a node name exists */

-  #ifdef CONFIGURE_FILE_USE_NODE
+# ifdef CONFIGURE_FILE_USE_NODE
   struct utsname uts;
   if (uname(&uts) >= 0)
     {
-    #ifdef CONFIGURE_FILE_USE_EUID
+#  ifdef CONFIGURE_FILE_USE_EUID
     sprintf(CS suffix, ".%ld.%.256s", (long int)original_euid, uts.nodename);
-    config_file = Ufopen(filename, "rb");
-    if (config_file == NULL)
-    #endif  /* CONFIGURE_FILE_USE_EUID */
+    if (!(config_file = Ufopen(filename, "rb")))
+#  endif  /* CONFIGURE_FILE_USE_EUID */
       {
       sprintf(CS suffix, ".%.256s", uts.nodename);
       config_file = Ufopen(filename, "rb");
       }
     }
-  #endif  /* CONFIGURE_FILE_USE_NODE */
+# endif  /* CONFIGURE_FILE_USE_NODE */


/* Otherwise, try the generic name, possibly with the euid added */

-  #ifdef CONFIGURE_FILE_USE_EUID
-  if (config_file == NULL)
+# ifdef CONFIGURE_FILE_USE_EUID
+  if (!config_file)
     {
     sprintf(CS suffix, ".%ld", (long int)original_euid);
     config_file = Ufopen(filename, "rb");
     }
-  #endif  /* CONFIGURE_FILE_USE_EUID */
+# endif  /* CONFIGURE_FILE_USE_EUID */


/* Finally, try the unadorned name */

-  if (config_file == NULL)
+  if (!config_file)
     {
     *suffix = 0;
     config_file = Ufopen(filename, "rb");
     }
-  #else  /* if neither defined */
+#else  /* if neither defined */


/* This is the common case when the fancy processing is not included. */

config_file = Ufopen(filename, "rb");
- #endif
+#endif

/* If the file does not exist, continue to try any others. For any other
error, break out (and die). */

- if (config_file != NULL || errno != ENOENT) break;
+ if (config_file || errno != ENOENT) break;
}

 /* On success, save the name for verification; config_filename is used when
@@ -3213,39 +3212,37 @@ if (config_file)
     config_main_directory = last_slash == filename ? US"/" : string_copyn(filename, last_slash - filename);
   else
     {
-      /* relative configuration file name: working dir + / + basename(filename) */
+    /* relative configuration file name: working dir + / + basename(filename) */


-      uschar buf[PATH_MAX];
-      gstring * g;
+    uschar buf[PATH_MAX];
+    gstring * g;


-      if (os_getcwd(buf, PATH_MAX) == NULL)
-        {
-        perror("exim: getcwd");
-        exit(EXIT_FAILURE);
-        }
-      g = string_cat(NULL, buf);
+    if (os_getcwd(buf, PATH_MAX) == NULL)
+      {
+      perror("exim: getcwd");
+      exit(EXIT_FAILURE);
+      }
+    g = string_cat(NULL, buf);


-      /* If the dir does not end with a "/", append one */
-      if (g->s[g->ptr-1] != '/')
-        g = string_catn(g, US"/", 1);
+    /* If the dir does not end with a "/", append one */
+    if (g->s[g->ptr-1] != '/')
+      g = string_catn(g, US"/", 1);


-      /* If the config file contains a "/", extract the directory part */
-      if (last_slash)
-        g = string_catn(g, filename, last_slash - filename);
+    /* If the config file contains a "/", extract the directory part */
+    if (last_slash)
+      g = string_catn(g, filename, last_slash - filename);


-      config_main_directory = string_from_gstring(g);
+    config_main_directory = string_from_gstring(g);
     }
   config_directory = config_main_directory;
   }
 else
-  {
   if (!filename)
     log_write(0, LOG_MAIN|LOG_PANIC_DIE, "non-existent configuration file(s): "
       "%s", config_main_filelist);
   else
     log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s",
       string_open_failed("configuration file %s", filename));
-  }


 /* Now, once we found and opened our configuration file, we change the directory
 to a safe place. Later we change to $spool_directory. */
@@ -3265,19 +3262,19 @@ if (f.trusted_config && Ustrcmp(filename, US"/dev/null"))
     log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to stat configuration file %s",
       big_buffer);


-  if ((statbuf.st_uid != root_uid                /* owner not root */
-       #ifdef CONFIGURE_OWNER
-       && statbuf.st_uid != config_uid           /* owner not the special one */
-       #endif
-         ) ||                                    /* or */
-      (statbuf.st_gid != root_gid                /* group not root & */
-       #ifdef CONFIGURE_GROUP
-       && statbuf.st_gid != config_gid           /* group not the special one */
-       #endif
-       && (statbuf.st_mode & 020) != 0) ||       /* group writeable  */
-                                                 /* or */
-      ((statbuf.st_mode & 2) != 0))              /* world writeable  */
-
+  if (    statbuf.st_uid != root_uid        /* owner not root */
+#ifdef CONFIGURE_OWNER
+       && statbuf.st_uid != config_uid        /* owner not the special one */
+#endif
+     ||                        /* or */
+      statbuf.st_gid != root_gid        /* group not root & */
+#ifdef CONFIGURE_GROUP
+       && statbuf.st_gid != config_gid        /* group not the special one */
+#endif
+       && (statbuf.st_mode & 020) != 0        /* group writeable  */
+     ||                        /* or */
+       (statbuf.st_mode & 2) != 0        /* world writeable  */
+     )
     log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Exim configuration file %s has the "
       "wrong owner, group, or mode", big_buffer);


@@ -3324,11 +3321,11 @@ while ((s = get_config_line()))
     read_named_list(&hostlist_anchor, &hostlist_count,
       MAX_NAMED_LIST, t+8, US"host list", hide);


-  else if (Ustrncmp(t, US"addresslist", 11) == 0)
+  else if (Ustrncmp(t, "addresslist", 11) == 0)
     read_named_list(&addresslist_anchor, &addresslist_count,
       MAX_NAMED_LIST, t+11, US"address list", hide);


-  else if (Ustrncmp(t, US"localpartlist", 13) == 0)
+  else if (Ustrncmp(t, "localpartlist", 13) == 0)
     read_named_list(&localpartlist_anchor, &localpartlist_count,
       MAX_NAMED_LIST, t+13, US"local part list", hide);


@@ -3347,7 +3344,7 @@ if (local_sender_retain && local_from_check)
/* If the timezone string is empty, set it to NULL, implying no TZ variable
wanted. */

-if (timezone_string != NULL && *timezone_string == 0) timezone_string = NULL;
+if (timezone_string && !*timezone_string) timezone_string = NULL;

/* The max retry interval must not be greater than 24 hours. */

@@ -3492,7 +3489,7 @@ if (syslog_facility_str)

/* Expand pid_file_path */

-if (*pid_file_path != 0)
+if (*pid_file_path)
   {
   if (!(s = expand_string(pid_file_path)))
     log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to expand pid_file_path "
@@ -3502,7 +3499,7 @@ if (*pid_file_path != 0)


/* Set default value of process_log_path */

-if (!process_log_path || *process_log_path =='\0')
+if (!process_log_path || !*process_log_path)
process_log_path = string_sprintf("%s/exim-process.info", spool_directory);

 /* Compile the regex for matching a UUCP-style "From_" line in an incoming
@@ -3554,7 +3551,7 @@ if (errors_reply_to)
     log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
       "error in errors_reply_to (%s): %s", errors_reply_to, errmess);


-  if (domain == 0)
+  if (!domain)
     log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
       "errors_reply_to (%s) does not contain a domain", errors_reply_to);
   }
@@ -3562,8 +3559,7 @@ if (errors_reply_to)
 /* If smtp_accept_queue or smtp_accept_max_per_host is set, then
 smtp_accept_max must also be set. */


-if (smtp_accept_max == 0 &&
-    (smtp_accept_queue > 0 || smtp_accept_max_per_host != NULL))
+if (smtp_accept_max == 0 && (smtp_accept_queue > 0 || smtp_accept_max_per_host))
   log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
     "smtp_accept_max must be set if smtp_accept_queue or "
     "smtp_accept_max_per_host is set");
@@ -3584,7 +3580,7 @@ if (host_number_string)
         host_number_string, expand_string_message);
   n = Ustrtol(s, &end, 0);
   while (isspace(*end)) end++;
-  if (*end != 0)
+  if (*end)
     log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
       "localhost_number value is not a number: %s", s);
   if (n > LOCALHOST_MAX)
diff --git a/src/src/store.c b/src/src/store.c
index 2a32e9b..ad4da3c 100644
--- a/src/src/store.c
+++ b/src/src/store.c
@@ -41,6 +41,9 @@ The following different types of store are recognized:
   a single message transaction but needed for longer than the use of the main
   pool permits.  Currently this means only receive-time DKIM information.


+- There is a dedicated pool for configuration data read from the config file(s).
+  Once complete, it is made readonly.
+
 . Orthogonal to the three pool types, there are two classes of memory: untainted
   and tainted.  The latter is used for values derived from untrusted input, and
   the string-expansion mechanism refuses to operate on such values (obviously,
@@ -165,21 +168,24 @@ static int max_nonpool_malloc;    /* max value for nonpool_malloc */
 static const uschar * pooluse[NPOOLS] = {
 [POOL_MAIN] =        US"main",
 [POOL_PERM] =        US"perm",
+[POOL_CONFIG] =        US"config",
 [POOL_SEARCH] =        US"search",
 [POOL_MESSAGE] =    US"message",
 [POOL_TAINT_MAIN] =    US"main",
 [POOL_TAINT_PERM] =    US"perm",
-[POOL_TAINT_SEARCH] =    US"search",
+[POOL_TAINT_CONFIG] =    US"config",
 [POOL_TAINT_SEARCH] =    US"search",
 [POOL_TAINT_MESSAGE] =    US"message",
 };
 static const uschar * poolclass[NPOOLS] = {
 [POOL_MAIN] =        US"untainted",
 [POOL_PERM] =        US"untainted",
+[POOL_CONFIG] =        US"untainted",
 [POOL_SEARCH] =        US"untainted",
 [POOL_MESSAGE] =    US"untainted",
 [POOL_TAINT_MAIN] =    US"tainted",
 [POOL_TAINT_PERM] =    US"tainted",
+[POOL_TAINT_CONFIG] =    US"tainted",
 [POOL_TAINT_SEARCH] =    US"tainted",
 [POOL_TAINT_MESSAGE] =    US"tainted",
 };
@@ -245,6 +251,22 @@ log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Taint mismatch, %s: %s %d\n",




+/******************************************************************************/
+void
+store_writeprotect(int pool)
+{
+for (storeblock * b = chainbase[pool]; b; b = b->next)
+  {
+#ifndef COMPILE_UTILITY
+  if (mprotect(b, ALIGNED_SIZEOF_STOREBLOCK + b->length, PROT_READ) != 0)
+    DEBUG(D_any) debug_printf("config block mprotect: (%d) %s\n", errno, strerror(errno))
+#endif
+    ;
+  }
+}
+
+/******************************************************************************/
+
 /*************************************************
 *       Get a block from the current pool        *
 *************************************************/
@@ -324,7 +346,13 @@ if (size > yield_length[pool])
     if (++nblocks[pool] > maxblocks[pool])
       maxblocks[pool] = nblocks[pool];


-    newblock = internal_store_malloc(mlength, func, linenumber);
+    if (pool == POOL_CONFIG)
+      {
+      long pgsize = sysconf(_SC_PAGESIZE);
+      posix_memalign((void **)&newblock, pgsize, (mlength + pgsize - 1) & ~(pgsize - 1));
+      }
+    else
+      newblock = internal_store_malloc(mlength, func, linenumber);
     newblock->next = NULL;
     newblock->length = length;
 #ifndef RESTRICTED_MEMORY
@@ -483,7 +511,8 @@ not call with a pointer returned by store_get().  Both the untainted and tainted
 pools corresposding to store_pool are reset.


 Arguments:
-  r           place to back up to
+  ptr         place to back up to
+  pool          pool holding the pointer
   func        function from which called
   linenumber  line number in source file


@@ -561,7 +590,8 @@ if ( yield_length[pool] < STOREPOOL_MIN_SIZE
}

bb = b->next;
-b->next = NULL;
+if (pool != POOL_CONFIG)
+ b->next = NULL;

 while ((b = bb))
   {
@@ -576,7 +606,8 @@ while ((b = bb))
   nbytes[pool] -= siz;
   pool_malloc -= siz;
   nblocks[pool]--;
-  internal_store_free(b, func, linenumber);
+  if (pool != POOL_CONFIG)
+    internal_store_free(b, func, linenumber);


#ifndef RESTRICTED_MEMORY
if (store_block_order[pool] > 13) store_block_order[pool]--;
diff --git a/src/src/store.h b/src/src/store.h
index 92deabf..58561ac 100644
--- a/src/src/store.h
+++ b/src/src/store.h
@@ -13,9 +13,10 @@

/* Define symbols for identifying the store pools. */

-#define NPOOLS 8
+#define NPOOLS 10
 enum { POOL_MAIN,
        POOL_PERM,
+       POOL_CONFIG,
        POOL_SEARCH,
        POOL_MESSAGE,


@@ -23,6 +24,7 @@ enum { POOL_MAIN,

        POOL_TAINT_MAIN = POOL_TAINT_BASE,
        POOL_TAINT_PERM,
+       POOL_TAINT_CONFIG,
        POOL_TAINT_SEARCH,
        POOL_TAINT_MESSAGE };