git://git.exim.org
/
exim.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Logging: millisecond QT and DT. Bug 2102
[exim.git]
/
src
/
src
/
spool_in.c
diff --git
a/src/src/spool_in.c
b/src/src/spool_in.c
index 7eb42907c6e40aa324fd3c2b581c31cf516af766..a5b14959fa4c2fcc347125bcc0f58994100f9c3d 100644
(file)
--- a/
src/src/spool_in.c
+++ b/
src/src/spool_in.c
@@
-25,6
+25,8
@@
fact it won't be written to. Just in case there's a major disaster (e.g.
overwriting some other file descriptor with the value of this one), open it
with append.
overwriting some other file descriptor with the value of this one), open it
with append.
+As called by deliver_message() (at least) we are operating as root.
+
Argument: the id of the message
Returns: fd if file successfully opened and locked, else -1
Argument: the id of the message
Returns: fd if file successfully opened and locked, else -1
@@
-51,11
+53,15
@@
for (i = 0; i < 2; i++)
uschar * fname;
int save_errno;
uschar * fname;
int save_errno;
- message_subdir[0] = split_spool_directory == i
== 0 ? id[5] : 0
;
+ message_subdir[0] = split_spool_directory == i
? '\0' : id[5]
;
fname = spool_fname(US"input", message_subdir, id, US"-D");
DEBUG(D_deliver) debug_printf("Trying spool file %s\n", fname);
fname = spool_fname(US"input", message_subdir, id, US"-D");
DEBUG(D_deliver) debug_printf("Trying spool file %s\n", fname);
- if ((fd = Uopen(fname, O_RDWR | O_APPEND, 0)) >= 0)
+ if ((fd = Uopen(fname,
+#ifdef O_CLOEXEC
+ O_CLOEXEC |
+#endif
+ O_RDWR | O_APPEND, 0)) >= 0)
break;
save_errno = errno;
if (errno == ENOENT)
break;
save_errno = errno;
if (errno == ENOENT)
@@
-63,8
+69,8
@@
for (i = 0; i < 2; i++)
if (i == 0) continue;
if (!queue_running)
log_write(0, LOG_MAIN, "Spool%s%s file %s-D not found",
if (i == 0) continue;
if (!queue_running)
log_write(0, LOG_MAIN, "Spool%s%s file %s-D not found",
- *queue_name ?
" Q=" :
"",
- *queue_name ? queue_name : "",
+ *queue_name ?
US" Q=" : US
"",
+ *queue_name ? queue_name :
US
"",
id);
}
else
id);
}
else
@@
-81,8
+87,9
@@
an open file descriptor (at least, I think that's the Cygwin story). On real
Unix systems it doesn't make any difference as long as Exim is consistent in
what it locks. */
Unix systems it doesn't make any difference as long as Exim is consistent in
what it locks. */
-(void)fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) |
- FD_CLOEXEC);
+#ifndef O_CLOEXEC
+(void)fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+#endif
lock_data.l_type = F_WRLCK;
lock_data.l_whence = SEEK_SET;
lock_data.l_type = F_WRLCK;
lock_data.l_whence = SEEK_SET;
@@
-215,6
+222,8
@@
have been the cause of that incident, but in any case, this code must be robust
against such an event, and if such a file is encountered, it must be treated as
malformed.
against such an event, and if such a file is encountered, it must be treated as
malformed.
+As called from deliver_message() (at least) we are running as root.
+
Arguments:
name name of the header file, including the -H
read_headers TRUE if in-store header structures are to be built
Arguments:
name name of the header file, including the -H
read_headers TRUE if in-store header structures are to be built
@@
-223,7
+232,7
@@
Arguments:
Returns: spool_read_OK success
spool_read_notopen open failed
spool_read_enverror error in the envelope portion
Returns: spool_read_OK success
spool_read_notopen open failed
spool_read_enverror error in the envelope portion
- spool_read_hdr
d
rror error in the header portion
+ spool_read_hdr
e
rror error in the header portion
*/
int
*/
int
@@
-275,6
+284,9
@@
sender_ident = NULL;
sender_local = FALSE;
sender_set_untrusted = FALSE;
smtp_active_hostname = primary_hostname;
sender_local = FALSE;
sender_set_untrusted = FALSE;
smtp_active_hostname = primary_hostname;
+#ifndef COMPILE_UTILITY
+spool_file_wireformat = FALSE;
+#endif
tree_nonrecipients = NULL;
#ifdef EXPERIMENTAL_BRIGHTMAIL
tree_nonrecipients = NULL;
#ifdef EXPERIMENTAL_BRIGHTMAIL
@@
-385,10
+397,11
@@
sender_address[n-3] = 0;
/* time */
if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
/* time */
if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
-if (sscanf(CS big_buffer,
"%d %d", &received_time
, &warning_count) != 2)
+if (sscanf(CS big_buffer,
TIME_T_FMT " %d", &received_time.tv_sec
, &warning_count) != 2)
goto SPOOL_FORMAT_ERROR;
goto SPOOL_FORMAT_ERROR;
+received_time.tv_usec = 0;
-message_age = time(NULL) - received_time;
+message_age = time(NULL) - received_time
.tv_sec
;
#ifndef COMPILE_UTILITY
DEBUG(D_deliver) debug_printf("user=%s uid=%ld gid=%ld sender=%s\n",
#ifndef COMPILE_UTILITY
DEBUG(D_deliver) debug_printf("user=%s uid=%ld gid=%ld sender=%s\n",
@@
-476,21
+489,24
@@
for (;;)
else if (Ustrncmp(p, "cl ", 3) == 0)
{
else if (Ustrncmp(p, "cl ", 3) == 0)
{
-
int
index, count;
- uschar name[20]; /* Need plenty of space for %
d
format */
- tree_node *node;
- if ( sscanf(CS big_buffer + 5, "%
d %d
", &index, &count) != 2
+
unsigned
index, count;
+ uschar name[20]; /* Need plenty of space for %
u
format */
+ tree_node *
node;
+ if ( sscanf(CS big_buffer + 5, "%
u %u
", &index, &count) != 2
|| index >= 20
|| index >= 20
+ || count > 16384 /* arbitrary limit on variable size */
)
goto SPOOL_FORMAT_ERROR;
if (index < 10)
)
goto SPOOL_FORMAT_ERROR;
if (index < 10)
- (void) string_format(name, sizeof(name), "%c%
d
", 'c', index);
+ (void) string_format(name, sizeof(name), "%c%
u
", 'c', index);
else
else
- (void) string_format(name, sizeof(name), "%c%
d
", 'm', index - 10);
+ (void) string_format(name, sizeof(name), "%c%
u
", 'm', index - 10);
node = acl_var_create(name);
node->data.ptr = store_get(count + 1);
node = acl_var_create(name);
node->data.ptr = store_get(count + 1);
+ /* We sanity-checked the count, so disable the Coverity error */
+ /* coverity[tainted_data] */
if (fread(node->data.ptr, 1, count+1, f) < count) goto SPOOL_READ_ERROR;
if (fread(node->data.ptr, 1, count+1, f) < count) goto SPOOL_READ_ERROR;
- (
(uschar*)node->data.ptr)[count] = 0
;
+ (
US node->data.ptr)[count] = '\0'
;
}
break;
}
break;
@@
-558,7
+574,8
@@
for (;;)
break;
case 'l':
break;
case 'l':
- if (Ustrcmp(p, "ocal") == 0) sender_local = TRUE;
+ if (Ustrcmp(p, "ocal") == 0)
+ sender_local = TRUE;
else if (Ustrcmp(big_buffer, "-localerror") == 0)
local_error_message = TRUE;
else if (Ustrncmp(p, "ocal_scan ", 10) == 0)
else if (Ustrcmp(big_buffer, "-localerror") == 0)
local_error_message = TRUE;
else if (Ustrncmp(p, "ocal_scan ", 10) == 0)
@@
-578,6
+595,12
@@
for (;;)
case 'r':
if (Ustrncmp(p, "eceived_protocol", 16) == 0)
received_protocol = string_copy(big_buffer + 19);
case 'r':
if (Ustrncmp(p, "eceived_protocol", 16) == 0)
received_protocol = string_copy(big_buffer + 19);
+ else if (Ustrncmp(p, "eceived_time_usec", 17) == 0)
+ {
+ unsigned usec;
+ if (sscanf(CS big_buffer + 21, "%u", &usec) == 1)
+ received_time.tv_usec = usec;
+ }
break;
case 's':
break;
case 's':
@@
-591,6
+614,10
@@
for (;;)
else if (Ustrncmp(p, "pam_score_int ", 14) == 0)
spam_score_int = string_copy(big_buffer + 16);
#endif
else if (Ustrncmp(p, "pam_score_int ", 14) == 0)
spam_score_int = string_copy(big_buffer + 16);
#endif
+#ifndef COMPILE_UTILITY
+ else if (Ustrncmp(p, "pool_file_wireformat", 20) == 0)
+ spool_file_wireformat = TRUE;
+#endif
#if defined(SUPPORT_I18N) && !defined(COMPILE_UTILITY)
else if (Ustrncmp(p, "mtputf8", 7) == 0)
message_smtputf8 = TRUE;
#if defined(SUPPORT_I18N) && !defined(COMPILE_UTILITY)
else if (Ustrncmp(p, "mtputf8", 7) == 0)
message_smtputf8 = TRUE;
@@
-660,10
+687,12
@@
DEBUG(D_deliver)
#endif /* COMPILE_UTILITY */
/* After reading the tree, the next line has not yet been read into the
#endif /* COMPILE_UTILITY */
/* After reading the tree, the next line has not yet been read into the
-buffer. It contains the count of recipients which follow on separate lines. */
+buffer. It contains the count of recipients which follow on separate lines.
+Apply an arbitrary sanity check.*/
if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
-if (sscanf(CS big_buffer, "%d", &rcount) != 1) goto SPOOL_FORMAT_ERROR;
+if (sscanf(CS big_buffer, "%d", &rcount) != 1 || rcount > 16384)
+ goto SPOOL_FORMAT_ERROR;
#ifndef COMPILE_UTILITY
DEBUG(D_deliver) debug_printf("recipients_count=%d\n", rcount);
#ifndef COMPILE_UTILITY
DEBUG(D_deliver) debug_printf("recipients_count=%d\n", rcount);
@@
-672,6
+701,10
@@
DEBUG(D_deliver) debug_printf("recipients_count=%d\n", rcount);
recipients_list_max = rcount;
recipients_list = store_get(rcount * sizeof(recipient_item));
recipients_list_max = rcount;
recipients_list = store_get(rcount * sizeof(recipient_item));
+/* We sanitised the count and know we have enough memory, so disable
+the Coverity error on recipients_count */
+/* coverity[tainted_data] */
+
for (recipients_count = 0; recipients_count < rcount; recipients_count++)
{
int nn;
for (recipients_count = 0; recipients_count < rcount; recipients_count++)
{
int nn;