Yahoo Groups archive

Milter-greylist

Index last updated: 2026-04-28 23:32 UTC

Message

[PATCH] Set CLOEXEC flags for sockets

2010-06-09 by Enrico Scholz

Set CLOEXEC flags for sockets

Subprocesses spawned by 'stat "| ..."' inherited all open sockets.
This wastes resources because it keeps lot of half-open sockets in the
system, can cause problems with SELinux and cause misbehavior because
sockets seems to be still open for the other side.

E.g. on my system, the stat logger consumes

 # ls /proc/10204/fd | wc -l
 166

sockets.

Index: milter-greylist/milter-greylist.h
===================================================================
--- milter-greylist.orig/milter-greylist.h
+++ milter-greylist/milter-greylist.h
@@ -270,6 +270,16 @@ char *fstring_escape(char *);
 size_t mystrlcat(char *, const char *src, size_t size);
 #endif
 
+#ifdef USE_CLOEXEC
+/* This requires Linux 2.6.27+ and the conditional must be set manually */
+#define socket_cloexec(_domain, _type, _protocol) \
+	socket(_domain, (_type) | SOCK_CLOEXEC, _protocol)
+#else
+int socket_cloexec(int domain, int type, int protocol);
+#endif
+
+int set_cloexec_flag(int fd, int value);
+
 /*
  * Locking management
  */
Index: milter-greylist/p0f.c
===================================================================
--- milter-greylist.orig/p0f.c
+++ milter-greylist/p0f.c
@@ -268,7 +268,7 @@ p0f_connect(void)
 	if (!conf.c_p0fsock[0])
 		return -1;
 
-	if ((p0fsock = socket(PF_UNIX,SOCK_STREAM,0)) == -1) {
+	if ((p0fsock = socket_cloexec(PF_UNIX,SOCK_STREAM,0)) == -1) {
 		mg_log(LOG_ERR, "socket(PF_UNIX, SOCK_STREAM, 0) failed");
 		exit(EX_OSERR);
 	}
Index: milter-greylist/spamd.c
===================================================================
--- milter-greylist.orig/spamd.c
+++ milter-greylist/spamd.c
@@ -441,7 +441,7 @@ spamd_unix_socket(path)
 	sun.sun_family = AF_UNIX;
 	strncpy(sun.sun_path, path, sizeof(sun.sun_path) - 1);
 
-	if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+	if ((sock = socket_cloexec(AF_UNIX, SOCK_STREAM, 0)) == -1) {
 		mg_log(LOG_ERR, "spamd socket failed: %s", strerror(errno));
 		return -1;
 	}
@@ -478,9 +478,9 @@ spamd_inet_socket(host, port)
 	}
 
 	for (res = ai; res != NULL; res = res->ai_next) {
-		sock = socket(res->ai_family, 
-			      res->ai_socktype, 
-			      res->ai_protocol);
+		sock = socket_cloexec(res->ai_family,
+				      res->ai_socktype,
+				      res->ai_protocol);
 		if (sock == -1)
 			continue;
 
Index: milter-greylist/sync.c
===================================================================
--- milter-greylist.orig/sync.c
+++ milter-greylist/sync.c
@@ -456,7 +456,8 @@ peer_connect(peer)	/* peer list is read-
 
 	for (res = res0; res; res = res->ai_next) {
 		/*We only test an address family which kernel supports. */
-		s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+		s = socket_cloexec(res->ai_family, res->ai_socktype,
+				   res->ai_protocol);
 		if (s == -1)
 			continue;
 		close(s);
@@ -469,7 +470,8 @@ peer_connect(peer)	/* peer list is read-
 	}
 
 	for (res = res0; res; res = res->ai_next) {
-		s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+		s = socket_cloexec(res->ai_family, res->ai_socktype,
+				   res->ai_protocol);
 		if (s == -1)
 			continue;
 
@@ -548,7 +550,8 @@ peer_connect(peer)	/* peer list is read-
 	else
 		proto = pe->p_proto;
 
-	if ((s = socket(SA(&raddr)->sa_family, SOCK_STREAM, proto)) == -1) {
+	if ((s = socket_cloexec(SA(&raddr)->sa_family, SOCK_STREAM,
+				proto)) == -1) {
 		mg_log(LOG_ERR, "cannot sync with peer %s, "
 		    "socket failed: %s (%d entries queued)", 
 		    peer->p_name, strerror(errno), peer->p_qlen);
@@ -786,6 +789,7 @@ sync_master(arg)
 
 
 		}
+		set_cloexec_flag(fd, 1);
 		unmappedaddr(SA(&raddr), &raddrlen);
 
 		conf_release();
@@ -952,7 +956,7 @@ sync_listen(addr, port, sms)
 		return;
 	}
 
-	if ((s = socket(SA(&laddr)->sa_family, SOCK_STREAM, proto)) == -1) {
+	if ((s = socket_cloexec(SA(&laddr)->sa_family, SOCK_STREAM, proto)) == -1) {
 		sms->runs = SMS_DISABLED;
 		return;
 	}
@@ -1515,7 +1519,7 @@ local_addr(sa, salen)
 		break;
 	}
 
-	if ((sfd = socket(sa->sa_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+	if ((sfd = socket_cloexec(sa->sa_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
 		mg_log(LOG_ERR, "local_addr: socket failed: %s",
 		    strerror(errno));
 		return -1;
Index: milter-greylist/conf.c
===================================================================
--- milter-greylist.orig/conf.c
+++ milter-greylist/conf.c
@@ -185,6 +185,7 @@ conf_load_internal(timestamp)
 		if (conf_cold)
 			exit(EX_OSERR);
 	} else {
+		set_cloexec_flag(fileno(stream), 1);
 		TSS_SET(conf_key, newconf);
 
 		peer_clear();
Index: milter-greylist/fd_pool.c
===================================================================
--- milter-greylist.orig/fd_pool.c
+++ milter-greylist/fd_pool.c
@@ -122,6 +122,7 @@ int fd_new_desc() {
                         strerror(errno));
                 return -1;
         }
+	set_cloexec_flag(descriptor, 1);
 	return descriptor;
 }
 
@@ -340,6 +341,7 @@ FILE *fopen_ext(char *path, char *mode) 
 	err = errno;
 
 	if (stream != NULL) {
+		set_cloexec_flag(fileno(stream), 1);
 		if ( descriptor == fileno(stream) ) {
 			/* we are in luck, fopen has successfully aquired our low descriptor ... */
 			return stream;
Index: milter-greylist/milter-greylist.c
===================================================================
--- milter-greylist.orig/milter-greylist.c
+++ milter-greylist/milter-greylist.c
@@ -3386,3 +3386,29 @@ mg_setreply(ctx, priv, rcpt)
 	return r;
 }
 
+#ifndef USE_CLOEXEC
+int socket_cloexec(int domain, int type, int protocol)
+{
+	int		fd = socket(domain, type, protocol);
+
+	if (fd >= 0)
+		set_cloexec_flag(fd, 1);
+
+	return fd;
+}
+#endif
+
+int set_cloexec_flag (int fd, int value)
+{
+	int oldflags = fcntl(fd, F_GETFD, 0);
+
+	if (oldflags < 0)
+		return oldflags;
+
+	if (value)
+		oldflags |= FD_CLOEXEC;
+	else
+		oldflags &= ~FD_CLOEXEC;
+
+	return fcntl(fd, F_SETFD, oldflags);
+}
Index: milter-greylist/stat.c
===================================================================
--- milter-greylist.orig/stat.c
+++ milter-greylist/stat.c
@@ -126,6 +126,8 @@ mg_stat_def(output, fstring)
 		return;
 	}
 
+	set_cloexec_flag(fileno(outfp), 1);
+
 	if ((format = fstring_escape(strdup(fstring))) == NULL) {
 		mg_log(LOG_ERR, "strdup failed: %s", strerror(errno));
 		exit(EX_OSERR);

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.