Fri Mar 18 15:26:31 2011 UTC ()
Memory allocation hygiene fix from PR pkg/44704.

spamass-milter forks, allocates memory and then execs, violating
locking rules.  This commit adds a patch from Juergen Hannken-Illjes
that moves the allocation above the fork.

TODO: upstream is recently alive again, after 5 years with no
releases.  Push these fixes upstream.


(gdt)
diff -r1.30 -r1.31 pkgsrc/mail/spamass-milter/Makefile
diff -r1.10 -r1.11 pkgsrc/mail/spamass-milter/distinfo
diff -r1.4 -r1.5 pkgsrc/mail/spamass-milter/patches/patch-aa

cvs diff -r1.30 -r1.31 pkgsrc/mail/spamass-milter/Makefile (expand / switch to unified diff)

--- pkgsrc/mail/spamass-milter/Makefile 2010/06/10 12:30:21 1.30
+++ pkgsrc/mail/spamass-milter/Makefile 2011/03/18 15:26:30 1.31
@@ -1,18 +1,18 @@ @@ -1,18 +1,18 @@
1# $NetBSD: Makefile,v 1.30 2010/06/10 12:30:21 gdt Exp $ 1# $NetBSD: Makefile,v 1.31 2011/03/18 15:26:30 gdt Exp $
2# 2#
3 3
4DISTNAME= spamass-milter-0.3.1 4DISTNAME= spamass-milter-0.3.1
5PKGREVISION= 3 5PKGREVISION= 4
6CATEGORIES= mail 6CATEGORIES= mail
7MASTER_SITES= http://savannah.nongnu.org/download/spamass-milt/ 7MASTER_SITES= http://savannah.nongnu.org/download/spamass-milt/
8 8
9# This patch is taken from upstream CVS, and is from the 0.3.1 release 9# This patch is taken from upstream CVS, and is from the 0.3.1 release
10# tag to head of CVS on 5 Jun 2010, although CVS last changed on 24 10# tag to head of CVS on 5 Jun 2010, although CVS last changed on 24
11# Jul 2006. The patch fixes an error in formatting of the synthetic 11# Jul 2006. The patch fixes an error in formatting of the synthetic
12# Received: line. The patch is a patchfile (hosted on ftp.netbsd.org) 12# Received: line. The patch is a patchfile (hosted on ftp.netbsd.org)
13# instead of a pkgsrc patch because it is something upstream would 13# instead of a pkgsrc patch because it is something upstream would
14# have released if upstream were still maintaining this code. 14# have released if upstream were still maintaining this code.
15PATCHFILES= spamass-milter-001.patch 15PATCHFILES= spamass-milter-001.patch
16 16
17MAINTAINER= gdt@NetBSD.org 17MAINTAINER= gdt@NetBSD.org
18HOMEPAGE= http://savannah.nongnu.org/projects/spamass-milt/ 18HOMEPAGE= http://savannah.nongnu.org/projects/spamass-milt/

cvs diff -r1.10 -r1.11 pkgsrc/mail/spamass-milter/distinfo (expand / switch to unified diff)

--- pkgsrc/mail/spamass-milter/distinfo 2010/09/10 23:33:42 1.10
+++ pkgsrc/mail/spamass-milter/distinfo 2011/03/18 15:26:30 1.11
@@ -1,11 +1,11 @@ @@ -1,11 +1,11 @@
1$NetBSD: distinfo,v 1.10 2010/09/10 23:33:42 gdt Exp $ 1$NetBSD: distinfo,v 1.11 2011/03/18 15:26:30 gdt Exp $
2 2
3SHA1 (spamass-milter-0.3.1.tar.gz) = dd488eb9ab1f230440fba8a729bee80550f2fbff 3SHA1 (spamass-milter-0.3.1.tar.gz) = dd488eb9ab1f230440fba8a729bee80550f2fbff
4RMD160 (spamass-milter-0.3.1.tar.gz) = 5db6af6b31de1bf83eafbd9713d81cdc957b5033 4RMD160 (spamass-milter-0.3.1.tar.gz) = 5db6af6b31de1bf83eafbd9713d81cdc957b5033
5Size (spamass-milter-0.3.1.tar.gz) = 141144 bytes 5Size (spamass-milter-0.3.1.tar.gz) = 141144 bytes
6SHA1 (spamass-milter-001.patch) = d37227f95808479dc4d6ba5c76ddd2413b4530d3 6SHA1 (spamass-milter-001.patch) = d37227f95808479dc4d6ba5c76ddd2413b4530d3
7RMD160 (spamass-milter-001.patch) = eef17cb4506e6f5c0908b6872b7fb5dcd8bc2e16 7RMD160 (spamass-milter-001.patch) = eef17cb4506e6f5c0908b6872b7fb5dcd8bc2e16
8Size (spamass-milter-001.patch) = 2435 bytes 8Size (spamass-milter-001.patch) = 2435 bytes
9SHA1 (patch-aa) = 13ba0413c28d14cd1a18d42a0b09ca26b358d913 9SHA1 (patch-aa) = f5fd2951082c916e3cae1746f8921793ff09b567
10SHA1 (patch-ab) = 03f7d4abc24e950fd44a4adbb708f3433d111643 10SHA1 (patch-ab) = 03f7d4abc24e950fd44a4adbb708f3433d111643
11SHA1 (patch-ac) = 851cbceab64b1a391cfe0aad0ba5a86c88218eb0 11SHA1 (patch-ac) = 851cbceab64b1a391cfe0aad0ba5a86c88218eb0

cvs diff -r1.4 -r1.5 pkgsrc/mail/spamass-milter/patches/Attic/patch-aa (expand / switch to unified diff)

--- pkgsrc/mail/spamass-milter/patches/Attic/patch-aa 2010/09/10 23:33:42 1.4
+++ pkgsrc/mail/spamass-milter/patches/Attic/patch-aa 2011/03/18 15:26:30 1.5
@@ -1,29 +1,31 @@ @@ -1,29 +1,31 @@
1$NetBSD: patch-aa,v 1.4 2010/09/10 23:33:42 gdt Exp $ 1$NetBSD: patch-aa,v 1.5 2011/03/18 15:26:30 gdt Exp $
2 2
3This patch has hunks for three separate reasons: 3This patch has hunks for multiple reasons:
4 4
51) Ancient fix to avoid going beyond s2. 51) Ancient fix to avoid going beyond s2.
6 6
72) Added CVE-2010-1132 patch from: 72) Added CVE-2010-1132 patch from:
8 8
9 https://bugzilla.redhat.com/attachment.cgi?id=401011 9 https://bugzilla.redhat.com/attachment.cgi?id=401011
10 10
113) (Most of, some in .h) patch to add option to not scan mail from 113) (Most of, some in .h) patch to add option to not scan mail from
12authenticated users, from: 12authenticated users, from:
13 13
14 http://lists.freebsd.org/pipermail/freebsd-ports-bugs/2006-November/106024.html 14 http://lists.freebsd.org/pipermail/freebsd-ports-bugs/2006-November/106024.html
15 15
16--- spamass-milter.cpp.orig 2010-09-10 15:50:58.000000000 +0000 164) Avoid memory allocation in after fork and before exec. From PR pkg/44704.
 17
 18--- spamass-milter.cpp.orig 2011-03-18 15:15:56.000000000 +0000
17+++ spamass-milter.cpp 19+++ spamass-milter.cpp
18@@ -170,10 +170,7 @@ char *spambucket; 20@@ -170,10 +170,7 @@ char *spambucket;
19 bool flag_full_email = false; /* pass full email address to spamc */ 21 bool flag_full_email = false; /* pass full email address to spamc */
20 bool flag_expand = false; /* alias/virtusertable expansion */ 22 bool flag_expand = false; /* alias/virtusertable expansion */
21 bool warnedmacro = false; /* have we logged that we couldn't fetch a macro? */ 23 bool warnedmacro = false; /* have we logged that we couldn't fetch a macro? */
22- 24-
23-#if defined(__FreeBSD__) /* popen bug - see PR bin/50770 */ 25-#if defined(__FreeBSD__) /* popen bug - see PR bin/50770 */
24-static pthread_mutex_t popen_mutex = PTHREAD_MUTEX_INITIALIZER; 26-static pthread_mutex_t popen_mutex = PTHREAD_MUTEX_INITIALIZER;
25-#endif 27-#endif
26+bool auth = false; /* don't scan authenticated users */ 28+bool auth = false; /* don't scan authenticated users */
27  29
28 // {{{ main() 30 // {{{ main()
29  31
@@ -150,45 +152,45 @@ authenticated users, from: @@ -150,45 +152,45 @@ authenticated users, from:
150 // launch new SpamAssassin 152 // launch new SpamAssassin
151@@ -842,30 +817,19 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp 153@@ -842,30 +817,19 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp
152 /* open a pipe to sendmail so we can do address expansion */ 154 /* open a pipe to sendmail so we can do address expansion */
153  155
154 char buf[1024]; 156 char buf[1024];
155- char *fmt="%s -bv \"%s\" 2>&1"; 157- char *fmt="%s -bv \"%s\" 2>&1";
156- 158-
157-#if defined(HAVE_SNPRINTF) 159-#if defined(HAVE_SNPRINTF)
158- snprintf(buf, sizeof(buf)-1, fmt, SENDMAIL, envrcpt[0]); 160- snprintf(buf, sizeof(buf)-1, fmt, SENDMAIL, envrcpt[0]);
159-#else 161-#else
160- /* XXX possible buffer overflow here */ 162- /* XXX possible buffer overflow here */
161- sprintf(buf, fmt, SENDMAIL, envrcpt[0]); 163- sprintf(buf, fmt, SENDMAIL, envrcpt[0]);
162-#endif 164-#endif
163- 
164- debug(D_RCPT, "calling %s", buf); 
165+ char *popen_argv[4]; 165+ char *popen_argv[4];
166+  166+
167+ popen_argv[0] = SENDMAIL; 167+ popen_argv[0] = SENDMAIL;
168+ popen_argv[1] = "-bv"; 168+ popen_argv[1] = "-bv";
169+ popen_argv[2] = envrcpt[0]; 169+ popen_argv[2] = envrcpt[0];
170+ popen_argv[3] = NULL; 170+ popen_argv[3] = NULL;
171  171
 172- debug(D_RCPT, "calling %s", buf);
 173+ debug(D_RCPT, "calling %s -bv %s", SENDMAIL, envrcpt[0]);
 174
172-#if defined(__FreeBSD__) /* popen bug - see PR bin/50770 */ 175-#if defined(__FreeBSD__) /* popen bug - see PR bin/50770 */
173- rv = pthread_mutex_lock(&popen_mutex); 176- rv = pthread_mutex_lock(&popen_mutex);
174- if (rv) 177- if (rv)
175- { 178- {
176- debug(D_ALWAYS, "Could not lock popen mutex: %s", strerror(rv)); 179- debug(D_ALWAYS, "Could not lock popen mutex: %s", strerror(rv));
177- abort(); 180- abort();
178- }  181- }
179-#endif 182-#endif
180+ debug(D_RCPT, "calling %s -bv %s", SENDMAIL, envrcpt[0]); 183-
181  
182- p = popen(buf, "r"); 184- p = popen(buf, "r");
183+ p = popenv(popen_argv, "r"); 185+ p = popenv(popen_argv, "r");
184 if (!p) 186 if (!p)
185 { 187 {
186- debug(D_RCPT, "popen failed(%s). Will not expand aliases", strerror(errno)); 188- debug(D_RCPT, "popen failed(%s). Will not expand aliases", strerror(errno));
187+ debug(D_RCPT, "popenv failed(%s). Will not expand aliases", strerror(errno)); 189+ debug(D_RCPT, "popenv failed(%s). Will not expand aliases", strerror(errno));
188 assassin->expandedrcpt.push_back(envrcpt[0]); 190 assassin->expandedrcpt.push_back(envrcpt[0]);
189 } else 191 } else
190 { 192 {
191@@ -890,16 +854,8 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp 193@@ -890,16 +854,8 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp
192 assassin->expandedrcpt.push_back(p+7); 194 assassin->expandedrcpt.push_back(p+7);
193 } 195 }
194 } 196 }
@@ -196,36 +198,95 @@ authenticated users, from: @@ -196,36 +198,95 @@ authenticated users, from:
196+ fclose(p); p = NULL; 198+ fclose(p); p = NULL;
197 } 199 }
198-#if defined(__FreeBSD__) 200-#if defined(__FreeBSD__)
199- rv = pthread_mutex_unlock(&popen_mutex); 201- rv = pthread_mutex_unlock(&popen_mutex);
200- if (rv) 202- if (rv)
201- { 203- {
202- debug(D_ALWAYS, "Could not unlock popen mutex: %s", strerror(rv)); 204- debug(D_ALWAYS, "Could not unlock popen mutex: %s", strerror(rv));
203- abort(); 205- abort();
204- }  206- }
205-#endif 207-#endif
206 } else 208 } else
207 { 209 {
208 assassin->expandedrcpt.push_back(envrcpt[0]); 210 assassin->expandedrcpt.push_back(envrcpt[0]);
209@@ -2033,7 +1989,7 @@ cmp_nocase_partial(const string& s, cons 211@@ -1343,6 +1299,22 @@ SpamAssassin::~SpamAssassin()
 212
 213 void SpamAssassin::Connect()
 214 {
 215+ int argc;
 216+ char *argv[100];
 217+ char spamc_user[64];
 218+
 219+ if (expandedrcpt.size() != 1) {
 220+ debug(D_RCPT, "%d recipients; spamc gets default username %s", (int)expandedrcpt.size(), defaultuser);
 221+ strlcpy(spamc_user, defaultuser, sizeof(spamc_user));
 222+ } else {
 223+ if (flag_full_email)
 224+ strlcpy(spamc_user, full_user().c_str(), sizeof(spamc_user));
 225+ else
 226+ strlcpy(spamc_user, local_user().c_str(), sizeof(spamc_user));
 227+ strlwr(spamc_user);
 228+ debug(D_RCPT, "spamc gets %s", spamc_user);
 229+ }
 230+
 231 // set up pipes for in- and output
 232 if (pipe(pipe_io[0]))
 233 throw string(string("pipe error: ")+string(strerror(errno)));
 234@@ -1376,33 +1348,12 @@ void SpamAssassin::Connect()
 235 // absolute path (determined in autoconf)
 236 // should be a little more secure
 237 // XXX arbitrary 100-argument max
 238- int argc = 0;
 239- char** argv = (char**) malloc(100*sizeof(char*));
 240+ argc = 0;
 241 argv[argc++] = SPAMC;
 242 if (flag_sniffuser)
 243 {
 244 argv[argc++] = "-u";
 245- if ( expandedrcpt.size() != 1 )
 246- {
 247- // More (or less?) than one recipient, so we pass the default
 248- // username to SPAMC. This way special rules can be defined for
 249- // multi recipient messages.
 250- debug(D_RCPT, "%d recipients; spamc gets default username %s", (int)expandedrcpt.size(), defaultuser);
 251- argv[argc++] = defaultuser;
 252- } else
 253- {
 254- // There is only 1 recipient so we pass the username
 255- // (converted to lowercase) to SPAMC. Don't worry about
 256- // freeing this memory as we're exec()ing anyhow.
 257- if (flag_full_email)
 258- argv[argc] = strlwr(strdup(full_user().c_str()));
 259- else
 260- argv[argc] = strlwr(strdup(local_user().c_str()));
 261-
 262- debug(D_RCPT, "spamc gets %s", argv[argc]);
 263-
 264- argc++;
 265- }
 266+ argv[argc++] = spamc_user;
 267 }
 268 if (spamdhost)
 269 {
 270@@ -2033,7 +1984,7 @@ cmp_nocase_partial(const string& s, cons
210 string::const_iterator p=s.begin(); 271 string::const_iterator p=s.begin();
211 string::const_iterator p2=s2.begin(); 272 string::const_iterator p2=s2.begin();
212  273
213- while ( p != s.end() && p2 <= s2.end() ) { 274- while ( p != s.end() && p2 <= s2.end() ) {
214+ while ( p != s.end() ) { 275+ while ( p != s.end() ) {
215 if (toupper(*p) != toupper(*p2)) 276 if (toupper(*p) != toupper(*p2))
216 { 277 {
217 debug(D_STR, "c_nc_p: <%s><%s> : miss", s.c_str(), s2.c_str()); 278 debug(D_STR, "c_nc_p: <%s><%s> : miss", s.c_str(), s2.c_str());
218@@ -2157,5 +2113,71 @@ void warnmacro(char *macro, char *scope) 279@@ -2157,5 +2108,71 @@ void warnmacro(char *macro, char *scope)
219 warnedmacro = true; 280 warnedmacro = true;
220 } 281 }
221  282
222+/* 283+/*
223+ untrusted-argument-safe popen function - only supports "r" and "w" modes 284+ untrusted-argument-safe popen function - only supports "r" and "w" modes
224+ for simplicity, and always reads stdout and stderr in "r" mode. Call 285+ for simplicity, and always reads stdout and stderr in "r" mode. Call
225+ fclose to close the FILE. 286+ fclose to close the FILE.
226+*/ 287+*/
227+FILE *popenv(char *const argv[], const char *type) 288+FILE *popenv(char *const argv[], const char *type)
228+{ 289+{
229+ FILE *iop; 290+ FILE *iop;
230+ int pdes[2]; 291+ int pdes[2];
231+ int save_errno; 292+ int save_errno;