pkgsrc-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
pkg/49064: mail/spamass-milter zombie children & ipv6 support
>Number: 49064
>Category: pkg
>Synopsis: mail/spamass-milter zombie children & ipv6 support
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: pkg-manager
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Aug 01 22:55:00 +0000 2014
>Originator: Todd Kover
>Release: NetBSD 6.1_STABLE
>Organization:
Omniscient Technologies
>Environment:
System: NetBSD guinness.omniscient.com 6.1_STABLE NetBSD 6.1_STABLE (GENERIC)
#1: Thu Jun 26 20:47:09 EDT 2014
kovert%guinness.omniscient.com@localhost:/usr/obj/6.0-stable/amd64/usr/src/os/NetBSD-6.0-branch/src/sys/arch/amd64/compile/GENERIC
amd64
Architecture: x86_64
Machine: amd64
>Description:
I combining two unrelated issues to the same port since its a minor
pkg and I sorted them out together. I can split if need be.
Issue 1) A previous fix for a CVE that replaced popen lost the child
reaping that pclose has. This causes sendmail processes to hang
around until spamass-milter is closed.
Issue 2) No Ipv6 support
>How-To-Repeat:
Issue 1) install port, tie into sendmail, start milter with -x,
watch mail come in and sendmail processes hang around
Issue 2) start spamass milter with an ipv6 addressed passed to -i,
such as -i 2001:1900:2209:a/64, watch it not start
>Fix:
patch-ad is just a copy of the FreeBSD ports patch for fixing IPv6.
Seems to work fine. This tweaks the same file as patch-aa and
patch-ab
patch-ae and patch-af fix the popenv issue and touch the same files
as patch-aa and patch-ab respectively. I separated them in the
interest of making it easier to patch.
Thanks,
-Todd
---<snip>-- patch-ad start ---<snip>---
This came from FreeBSD
diff -ur orig/spamass-milter.cpp spamass-milter.cpp
--- spamass-milter.cpp 2010-01-31 11:35:47.000000000 +0000
+++ spamass-milter.cpp 2008-01-09 01:20:38.000000000 +0000
@@ -88,6 +88,7 @@
#include "subst_poll.h"
#endif
#include <errno.h>
+#include <netdb.h>
// C++ includes
#include <cstdio>
@@ -721,12 +722,19 @@
sctx = (struct context *)malloc(sizeof(*sctx));
if (!hostaddr)
{
+ static struct sockaddr_in localhost;
+
/* not a socket; probably a local user calling sendmail
directly */
/* set to 127.0.0.1 */
- sctx->connect_ip.s_addr = htonl(INADDR_LOOPBACK);
+ strcpy(sctx->connect_ip, "127.0.0.1");
+ localhost.sin_family = AF_INET;
+ localhost.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ hostaddr = (struct sockaddr*) &localhost;
} else
{
- sctx->connect_ip = ((struct sockaddr_in *) hostaddr)->sin_addr;
+ getnameinfo(hostaddr, sizeof(struct sockaddr_in6),
+ sctx->connect_ip, 63, NULL, 0, NI_NUMERICHOST);
+ debug(D_FUNC, "Remote address: %s", sctx->connect_ip);
}
sctx->assassin = NULL;
sctx->helo = NULL;
@@ -740,10 +748,12 @@
}
/* debug(D_ALWAYS, "ZZZ set private context to %p", sctx); */
- if (ip_in_networklist(sctx->connect_ip, &ignorenets))
+ //debug(D_FUNC, "sctx->connect_ip: `%d'", sctx->connect_ip.sin_family);
+
+ if (ip_in_networklist(hostaddr, &ignorenets))
{
debug(D_NET, "%s is in our ignore list - accepting message",
- inet_ntoa(sctx->connect_ip));
+ sctx->connect_ip);
debug(D_FUNC, "mlfi_connect: exit ignore");
return SMFIS_ACCEPT;
}
@@ -815,7 +825,7 @@
return SMFIS_TEMPFAIL;
};
- assassin->set_connectip(string(inet_ntoa(sctx->connect_ip)));
+ assassin->set_connectip(string(sctx->connect_ip));
// Store a pointer to the assassin object in our context struct
sctx->assassin = assassin;
@@ -2089,69 +2099,119 @@
{
char *tnet = strsep(&token, "/");
char *tmask = token;
- struct in_addr net, mask;
+ struct in_addr net;
+ struct in6_addr net6;
if (list->num_nets % 10 == 0)
- list->nets = (struct net*)realloc(list->nets,
sizeof(*list->nets) * (list->num_nets + 10));
+ list->nets = (union net*)realloc(list->nets,
sizeof(*list->nets) * (list->num_nets + 10));
- if (!inet_aton(tnet, &net))
+ if (inet_pton(AF_INET, tnet, &net))
{
- fprintf(stderr, "Could not parse \"%s\" as a
network\n", tnet);
- exit(1);
- }
+ struct in_addr mask;
+
+ if (tmask)
+ {
+ if (strchr(tmask, '.') == NULL)
+ {
+ /* CIDR */
+ unsigned int bits;
+ int ret;
+ ret = sscanf(tmask, "%u", &bits);
+ if (ret != 1 || bits > 32)
+ {
+ fprintf(stderr,"%s: bad CIDR
value", tmask);
+ exit(1);
+ }
+ mask.s_addr = htonl(~((1L << (32 -
bits)) - 1) & 0xffffffff);
+ } else if (!inet_pton(AF_INET6, tmask, &mask))
+ {
+ fprintf(stderr, "Could not parse \"%s\"
as a netmask\n", tmask);
+ exit(1);
+ }
+ } else
+ mask.s_addr = 0xffffffff;
+
+ {
+ char *snet = strdup(inet_ntoa(net));
+ debug(D_MISC, "Adding %s/%s to network list",
snet, inet_ntoa(mask));
+ free(snet);
+ }
- if (tmask)
+ net.s_addr = net.s_addr & mask.s_addr;
+ list->nets[list->num_nets].net4.af = AF_INET;
+ list->nets[list->num_nets].net4.network = net;
+ list->nets[list->num_nets].net4.netmask = mask;
+ list->num_nets++;
+ } else if (inet_pton(AF_INET6, tnet, &net6))
{
- if (strchr(tmask, '.') == NULL)
+ int mask;
+
+ if (tmask)
{
- /* CIDR */
- unsigned int bits;
- int ret;
- ret = sscanf(tmask, "%u", &bits);
- if (ret != 1 || bits > 32)
+ if (sscanf(tmask, "%d", &mask) != 1 || mask >
128)
{
fprintf(stderr,"%s: bad CIDR value",
tmask);
exit(1);
}
- mask.s_addr = htonl(~((1L << (32 - bits)) - 1)
& 0xffffffff);
- } else if (!inet_aton(tmask, &mask))
- {
- fprintf(stderr, "Could not parse \"%s\" as a
netmask\n", tmask);
- exit(1);
- }
+ } else
+ mask = 128;
+
+ list->nets[list->num_nets].net6.af = AF_INET6;
+ list->nets[list->num_nets].net6.network = net6;
+ list->nets[list->num_nets].net6.netmask = mask;
+ list->num_nets++;
} else
- mask.s_addr = 0xffffffff;
-
{
- char *snet = strdup(inet_ntoa(net));
- debug(D_MISC, "Adding %s/%s to network list", snet,
inet_ntoa(mask));
- free(snet);
+ fprintf(stderr, "Could not parse \"%s\" as a
network\n", tnet);
+ exit(1);
}
- net.s_addr = net.s_addr & mask.s_addr;
- list->nets[list->num_nets].network = net;
- list->nets[list->num_nets].netmask = mask;
- list->num_nets++;
}
free(string);
}
-int ip_in_networklist(struct in_addr ip, struct networklist *list)
+int ip_in_networklist(struct sockaddr *addr, struct networklist *list)
{
int i;
if (list->num_nets == 0)
return 0;
-
- debug(D_NET, "Checking %s against:", inet_ntoa(ip));
+
+ //debug(D_NET, "Checking %s against:", inet_ntoa(ip));
for (i = 0; i < list->num_nets; i++)
{
- debug(D_NET, "%s", inet_ntoa(list->nets[i].network));
- debug(D_NET, "/%s", inet_ntoa(list->nets[i].netmask));
- if ((ip.s_addr & list->nets[i].netmask.s_addr) ==
list->nets[i].network.s_addr)
- {
- debug(D_NET, "Hit!");
- return 1;
+ if (list->nets[i].net.af == AF_INET && addr->sa_family ==
AF_INET)
+ {
+ struct in_addr ip = ((struct sockaddr_in
*)addr)->sin_addr;
+
+ debug(D_NET, "%s",
inet_ntoa(list->nets[i].net4.network));
+ debug(D_NET, "/%s",
inet_ntoa(list->nets[i].net4.netmask));
+ if ((ip.s_addr & list->nets[i].net4.netmask.s_addr) ==
list->nets[i].net4.network.s_addr)
+ {
+ debug(D_NET, "Hit!");
+ return 1;
+ }
+ } else if (list->nets[i].net.af == AF_INET6 && addr->sa_family
== AF_INET6)
+ {
+ u_int8_t *ip = ((struct sockaddr_in6
*)addr)->sin6_addr.s6_addr;
+ int mask, j;
+
+ mask = list->nets[i].net6.netmask;
+ for (j = 0; j < 16 && mask > 0; j++, mask -= 8)
+ {
+ unsigned char bytemask;
+
+ bytemask = (mask < 8) ? ~((1L << (8 - mask)) -
1) : 0xff;
+
+ if ((ip[j] & bytemask) !=
(list->nets[i].net6.network.s6_addr[j] & bytemask))
+ break;
+ }
+
+ if (mask <= 0)
+ {
+ debug(D_NET, "Hit!");
+ return 1;
+ }
}
}
diff -ur orig/spamass-milter.h spamass-milter.h
--- spamass-milter.h 2006-03-23 22:07:55.000000000 +0000
+++ spamass-milter.h 2008-01-01 23:55:44.000000000 +0000
@@ -56,16 +56,30 @@
extern struct smfiDesc smfilter;
/* struct describing a single network */
-struct net
+union net
{
- struct in_addr network;
- struct in_addr netmask;
+ struct
+ {
+ uint8_t af;
+ } net;
+ struct
+ {
+ uint8_t af;
+ struct in_addr network;
+ struct in_addr netmask;
+ } net4;
+ struct
+ {
+ uint8_t af;
+ struct in6_addr network;
+ int netmask; /* Just the number of bits for IPv6 */
+ } net6;
};
/* an array of networks */
struct networklist
{
- struct net *nets;
+ union net *nets;
int num_nets;
};
@@ -165,7 +179,7 @@
/* Private data structure to carry per-client data between calls */
struct context
{
- struct in_addr connect_ip; // remote IP address
+ char connect_ip[64]; // remote IP address
char *helo;
SpamAssassin *assassin; // pointer to the SA object if we're processing
a message
};
@@ -182,7 +196,7 @@
int cmp_nocase_partial(const string&, const string&);
void closeall(int fd);
void parse_networklist(char *string, struct networklist *list);
-int ip_in_networklist(struct in_addr ip, struct networklist *list);
+int ip_in_networklist(struct sockaddr *addr, struct networklist *list);
void parse_debuglevel(char* string);
char *strlwr(char *str);
void warnmacro(char *macro, char *scope);
---<snip>-- patch-ad end ---<snip>---
---<snip>-- patch-ae start ---<snip>---
--- spamass-milter.cpp 2014-08-01 09:03:23.000000000 -0400
+++ spamass-milter.cpp 2014-08-01 09:02:19.000000000 -0400
@@ -464,13 +464,14 @@
the only way to do it. */
char *popen_argv[3];
FILE *p;
+ pid_t pid;
popen_argv[0] = SENDMAIL;
popen_argv[1] = spambucket;
popen_argv[2] = NULL;
debug(D_COPY, "calling %s %s", SENDMAIL, spambucket);
- p = popenv(popen_argv, "w");
+ p = popenv(popen_argv, "w", &pid);
if (!p)
{
debug(D_COPY, "popenv failed(%s). Will not
send a copy to spambucket", strerror(errno));
@@ -479,6 +480,7 @@
// Send message provided by SpamAssassin
fwrite(assassin->d().c_str(),
assassin->d().size(), 1, p);
fclose(p); p = NULL;
+ waitpid(pid, NULL, 0);
}
}
return SMFIS_REJECT;
@@ -824,9 +826,11 @@
popen_argv[2] = envrcpt[0];
popen_argv[3] = NULL;
+ pid_t pid;
+
debug(D_RCPT, "calling %s -bv %s", SENDMAIL, envrcpt[0]);
- p = popenv(popen_argv, "r");
+ p = popenv(popen_argv, "r", &pid);
if (!p)
{
debug(D_RCPT, "popenv failed(%s). Will not expand
aliases", strerror(errno));
@@ -855,6 +859,7 @@
}
}
fclose(p); p = NULL;
+ waitpid(pid, NULL, 0);
}
} else
{
@@ -2113,11 +2118,12 @@
for simplicity, and always reads stdout and stderr in "r" mode. Call
fclose to close the FILE.
*/
-FILE *popenv(char *const argv[], const char *type)
+FILE *popenv(char *const argv[], const char *type, pid_t *pid)
{
FILE *iop;
int pdes[2];
int save_errno;
+ pid_t kidpid;
if ((*type != 'r' && *type != 'w') || type[1])
{
errno = EINVAL;
@@ -2125,7 +2131,7 @@
}
if (pipe(pdes) < 0)
return (NULL);
- switch (fork()) {
+ switch ( (kidpid = fork()) ) {
case -1: /* Error. */
save_errno = errno;
@@ -2171,6 +2177,13 @@
(void)close(pdes[0]);
}
+ /*
+ * so caller can reap children and not leave zombies
+ */
+ if(kidpid) {
+ *pid = kidpid;
+ }
+
return (iop);
}
---<snip>-- patch-ae end ---<snip>---
---<snip>-- patch-af start ---<snip>---
--- spamass-milter.h 2014-08-01 09:03:23.000000000 -0400
+++ spamass-milter.h 2014-08-01 09:02:32.000000000 -0400
@@ -186,6 +186,6 @@
void parse_debuglevel(char* string);
char *strlwr(char *str);
void warnmacro(char *macro, char *scope);
-FILE *popenv(char *const argv[], const char *type);
+FILE *popenv(char *const argv[], const char *type, pid_t *pid);
#endif
---<snip>-- patch-af end ---<snip>---
------- =_aaaaaaaaaa0
Content-Type: text/plain; name="patch-ad"; charset="us-ascii"
Content-ID: <62332.1406933442.2%guinness.omniscient.com@localhost>
This came from FreeBSD
diff -ur orig/spamass-milter.cpp spamass-milter.cpp
--- spamass-milter.cpp 2010-01-31 11:35:47.000000000 +0000
+++ spamass-milter.cpp 2008-01-09 01:20:38.000000000 +0000
@@ -88,6 +88,7 @@
#include "subst_poll.h"
#endif
#include <errno.h>
+#include <netdb.h>
// C++ includes
#include <cstdio>
@@ -721,12 +722,19 @@
sctx = (struct context *)malloc(sizeof(*sctx));
if (!hostaddr)
{
+ static struct sockaddr_in localhost;
+
/* not a socket; probably a local user calling sendmail
directly */
/* set to 127.0.0.1 */
- sctx->connect_ip.s_addr = htonl(INADDR_LOOPBACK);
+ strcpy(sctx->connect_ip, "127.0.0.1");
+ localhost.sin_family = AF_INET;
+ localhost.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ hostaddr = (struct sockaddr*) &localhost;
} else
{
- sctx->connect_ip = ((struct sockaddr_in *) hostaddr)->sin_addr;
+ getnameinfo(hostaddr, sizeof(struct sockaddr_in6),
+ sctx->connect_ip, 63, NULL, 0, NI_NUMERICHOST);
+ debug(D_FUNC, "Remote address: %s", sctx->connect_ip);
}
sctx->assassin = NULL;
sctx->helo = NULL;
@@ -740,10 +748,12 @@
}
/* debug(D_ALWAYS, "ZZZ set private context to %p", sctx); */
- if (ip_in_networklist(sctx->connect_ip, &ignorenets))
+ //debug(D_FUNC, "sctx->connect_ip: `%d'", sctx->connect_ip.sin_family);
+
+ if (ip_in_networklist(hostaddr, &ignorenets))
{
debug(D_NET, "%s is in our ignore list - accepting message",
- inet_ntoa(sctx->connect_ip));
+ sctx->connect_ip);
debug(D_FUNC, "mlfi_connect: exit ignore");
return SMFIS_ACCEPT;
}
@@ -815,7 +825,7 @@
return SMFIS_TEMPFAIL;
};
- assassin->set_connectip(string(inet_ntoa(sctx->connect_ip)));
+ assassin->set_connectip(string(sctx->connect_ip));
// Store a pointer to the assassin object in our context struct
sctx->assassin = assassin;
@@ -2089,69 +2099,119 @@
{
char *tnet = strsep(&token, "/");
char *tmask = token;
- struct in_addr net, mask;
+ struct in_addr net;
+ struct in6_addr net6;
if (list->num_nets % 10 == 0)
- list->nets = (struct net*)realloc(list->nets,
sizeof(*list->nets) * (list->num_nets + 10));
+ list->nets = (union net*)realloc(list->nets,
sizeof(*list->nets) * (list->num_nets + 10));
- if (!inet_aton(tnet, &net))
+ if (inet_pton(AF_INET, tnet, &net))
{
- fprintf(stderr, "Could not parse \"%s\" as a
network\n", tnet);
- exit(1);
- }
+ struct in_addr mask;
+
+ if (tmask)
+ {
+ if (strchr(tmask, '.') == NULL)
+ {
+ /* CIDR */
+ unsigned int bits;
+ int ret;
+ ret = sscanf(tmask, "%u", &bits);
+ if (ret != 1 || bits > 32)
+ {
+ fprintf(stderr,"%s: bad CIDR
value", tmask);
+ exit(1);
+ }
+ mask.s_addr = htonl(~((1L << (32 -
bits)) - 1) & 0xffffffff);
+ } else if (!inet_pton(AF_INET6, tmask, &mask))
+ {
+ fprintf(stderr, "Could not parse \"%s\"
as a netmask\n", tmask);
+ exit(1);
+ }
+ } else
+ mask.s_addr = 0xffffffff;
+
+ {
+ char *snet = strdup(inet_ntoa(net));
+ debug(D_MISC, "Adding %s/%s to network list",
snet, inet_ntoa(mask));
+ free(snet);
+ }
- if (tmask)
+ net.s_addr = net.s_addr & mask.s_addr;
+ list->nets[list->num_nets].net4.af = AF_INET;
+ list->nets[list->num_nets].net4.network = net;
+ list->nets[list->num_nets].net4.netmask = mask;
+ list->num_nets++;
+ } else if (inet_pton(AF_INET6, tnet, &net6))
{
- if (strchr(tmask, '.') == NULL)
+ int mask;
+
+ if (tmask)
{
- /* CIDR */
- unsigned int bits;
- int ret;
- ret = sscanf(tmask, "%u", &bits);
- if (ret != 1 || bits > 32)
+ if (sscanf(tmask, "%d", &mask) != 1 || mask >
128)
{
fprintf(stderr,"%s: bad CIDR value",
tmask);
exit(1);
}
- mask.s_addr = htonl(~((1L << (32 - bits)) - 1)
& 0xffffffff);
- } else if (!inet_aton(tmask, &mask))
- {
- fprintf(stderr, "Could not parse \"%s\" as a
netmask\n", tmask);
- exit(1);
- }
+ } else
+ mask = 128;
+
+ list->nets[list->num_nets].net6.af = AF_INET6;
+ list->nets[list->num_nets].net6.network = net6;
+ list->nets[list->num_nets].net6.netmask = mask;
+ list->num_nets++;
} else
- mask.s_addr = 0xffffffff;
-
{
- char *snet = strdup(inet_ntoa(net));
- debug(D_MISC, "Adding %s/%s to network list", snet,
inet_ntoa(mask));
- free(snet);
+ fprintf(stderr, "Could not parse \"%s\" as a
network\n", tnet);
+ exit(1);
}
- net.s_addr = net.s_addr & mask.s_addr;
- list->nets[list->num_nets].network = net;
- list->nets[list->num_nets].netmask = mask;
- list->num_nets++;
}
free(string);
}
-int ip_in_networklist(struct in_addr ip, struct networklist *list)
+int ip_in_networklist(struct sockaddr *addr, struct networklist *list)
{
int i;
if (list->num_nets == 0)
return 0;
-
- debug(D_NET, "Checking %s against:", inet_ntoa(ip));
+
+ //debug(D_NET, "Checking %s against:", inet_ntoa(ip));
for (i = 0; i < list->num_nets; i++)
{
- debug(D_NET, "%s", inet_ntoa(list->nets[i].network));
- debug(D_NET, "/%s", inet_ntoa(list->nets[i].netmask));
- if ((ip.s_addr & list->nets[i].netmask.s_addr) ==
list->nets[i].network.s_addr)
- {
- debug(D_NET, "Hit!");
- return 1;
+ if (list->nets[i].net.af == AF_INET && addr->sa_family ==
AF_INET)
+ {
+ struct in_addr ip = ((struct sockaddr_in
*)addr)->sin_addr;
+
+ debug(D_NET, "%s",
inet_ntoa(list->nets[i].net4.network));
+ debug(D_NET, "/%s",
inet_ntoa(list->nets[i].net4.netmask));
+ if ((ip.s_addr & list->nets[i].net4.netmask.s_addr) ==
list->nets[i].net4.network.s_addr)
+ {
+ debug(D_NET, "Hit!");
+ return 1;
+ }
+ } else if (list->nets[i].net.af == AF_INET6 && addr->sa_family
== AF_INET6)
+ {
+ u_int8_t *ip = ((struct sockaddr_in6
*)addr)->sin6_addr.s6_addr;
+ int mask, j;
+
+ mask = list->nets[i].net6.netmask;
+ for (j = 0; j < 16 && mask > 0; j++, mask -= 8)
+ {
+ unsigned char bytemask;
+
+ bytemask = (mask < 8) ? ~((1L << (8 - mask)) -
1) : 0xff;
+
+ if ((ip[j] & bytemask) !=
(list->nets[i].net6.network.s6_addr[j] & bytemask))
+ break;
+ }
+
+ if (mask <= 0)
+ {
+ debug(D_NET, "Hit!");
+ return 1;
+ }
}
}
diff -ur orig/spamass-milter.h spamass-milter.h
--- spamass-milter.h 2006-03-23 22:07:55.000000000 +0000
+++ spamass-milter.h 2008-01-01 23:55:44.000000000 +0000
@@ -56,16 +56,30 @@
extern struct smfiDesc smfilter;
/* struct describing a single network */
-struct net
+union net
{
- struct in_addr network;
- struct in_addr netmask;
+ struct
+ {
+ uint8_t af;
+ } net;
+ struct
+ {
+ uint8_t af;
+ struct in_addr network;
+ struct in_addr netmask;
+ } net4;
+ struct
+ {
+ uint8_t af;
+ struct in6_addr network;
+ int netmask; /* Just the number of bits for IPv6 */
+ } net6;
};
/* an array of networks */
struct networklist
{
- struct net *nets;
+ union net *nets;
int num_nets;
};
@@ -165,7 +179,7 @@
/* Private data structure to carry per-client data between calls */
struct context
{
- struct in_addr connect_ip; // remote IP address
+ char connect_ip[64]; // remote IP address
char *helo;
SpamAssassin *assassin; // pointer to the SA object if we're processing
a message
};
@@ -182,7 +196,7 @@
int cmp_nocase_partial(const string&, const string&);
void closeall(int fd);
void parse_networklist(char *string, struct networklist *list);
-int ip_in_networklist(struct in_addr ip, struct networklist *list);
+int ip_in_networklist(struct sockaddr *addr, struct networklist *list);
void parse_debuglevel(char* string);
char *strlwr(char *str);
void warnmacro(char *macro, char *scope);
------- =_aaaaaaaaaa0
Content-Type: text/plain; name="patch-ae"; charset="us-ascii"
Content-ID: <62332.1406933442.3%guinness.omniscient.com@localhost>
--- spamass-milter.cpp 2014-08-01 09:03:23.000000000 -0400
+++ spamass-milter.cpp 2014-08-01 09:02:19.000000000 -0400
@@ -464,13 +464,14 @@
the only way to do it. */
char *popen_argv[3];
FILE *p;
+ pid_t pid;
popen_argv[0] = SENDMAIL;
popen_argv[1] = spambucket;
popen_argv[2] = NULL;
debug(D_COPY, "calling %s %s", SENDMAIL, spambucket);
- p = popenv(popen_argv, "w");
+ p = popenv(popen_argv, "w", &pid);
if (!p)
{
debug(D_COPY, "popenv failed(%s). Will not
send a copy to spambucket", strerror(errno));
@@ -479,6 +480,7 @@
// Send message provided by SpamAssassin
fwrite(assassin->d().c_str(),
assassin->d().size(), 1, p);
fclose(p); p = NULL;
+ waitpid(pid, NULL, 0);
}
}
return SMFIS_REJECT;
@@ -824,9 +826,11 @@
popen_argv[2] = envrcpt[0];
popen_argv[3] = NULL;
+ pid_t pid;
+
debug(D_RCPT, "calling %s -bv %s", SENDMAIL, envrcpt[0]);
- p = popenv(popen_argv, "r");
+ p = popenv(popen_argv, "r", &pid);
if (!p)
{
debug(D_RCPT, "popenv failed(%s). Will not expand
aliases", strerror(errno));
@@ -855,6 +859,7 @@
}
}
fclose(p); p = NULL;
+ waitpid(pid, NULL, 0);
}
} else
{
@@ -2113,11 +2118,12 @@
for simplicity, and always reads stdout and stderr in "r" mode. Call
fclose to close the FILE.
*/
-FILE *popenv(char *const argv[], const char *type)
+FILE *popenv(char *const argv[], const char *type, pid_t *pid)
{
FILE *iop;
int pdes[2];
int save_errno;
+ pid_t kidpid;
if ((*type != 'r' && *type != 'w') || type[1])
{
errno = EINVAL;
@@ -2125,7 +2131,7 @@
}
if (pipe(pdes) < 0)
return (NULL);
- switch (fork()) {
+ switch ( (kidpid = fork()) ) {
case -1: /* Error. */
save_errno = errno;
@@ -2171,6 +2177,13 @@
(void)close(pdes[0]);
}
+ /*
+ * so caller can reap children and not leave zombies
+ */
+ if(kidpid) {
+ *pid = kidpid;
+ }
+
return (iop);
}
------- =_aaaaaaaaaa0
Content-Type: text/plain; name="patch-af"; charset="us-ascii"
Content-ID: <62332.1406933442.4%guinness.omniscient.com@localhost>
--- spamass-milter.h 2014-08-01 09:03:23.000000000 -0400
+++ spamass-milter.h 2014-08-01 09:02:32.000000000 -0400
@@ -186,6 +186,6 @@
void parse_debuglevel(char* string);
char *strlwr(char *str);
void warnmacro(char *macro, char *scope);
-FILE *popenv(char *const argv[], const char *type);
+FILE *popenv(char *const argv[], const char *type, pid_t *pid);
#endif
------- =_aaaaaaaaaa0--
>Unformatted:
------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <62332.1406933442.1%guinness.omniscient.com@localhost>
Home |
Main Index |
Thread Index |
Old Index