Browse code

Limit RLIMIT_DATA to 2GB on 32-bit processes (bb #1941).

With RLIMIT_DATA > 2GB a 32-bit FreeBSD 7.3 allows ~120M memory to be allocated
via mmap before failing.
With RLIMIT_DATA set to 2GB it allows ~890M memory.
So check the RLIMIT_DATA and set it just below 2G.

You can also just do 'ulimit -d 2097151' to get the effects of this patch.

Török Edvin authored on 2010/08/31 21:10:56
Showing 2 changed files
... ...
@@ -1,3 +1,7 @@
1
+Tue Aug 31 15:10:29 EEST 2010 (edwin)
2
+-------------------------------------
3
+ * clamd/clamd.c: limit RLIMIT_DATA to 2GB on 32-bit processes (bb #1941).
4
+
1 5
 Tue Aug 31 11:13:44 EEST 2010 (edwin)
2 6
 -------------------------------------
3 7
  * libclamav/regex/regexec.c: fix regex when sizeof(void*) != sizeof(long) (bb #2232).
... ...
@@ -30,6 +30,7 @@
30 30
 #endif
31 31
 #ifndef _WIN32
32 32
 #include <sys/time.h>
33
+#include <sys/resource.h>
33 34
 #endif
34 35
 #include <sys/types.h>
35 36
 #include <sys/stat.h>
... ...
@@ -108,6 +109,7 @@ int main(int argc, char **argv)
108 108
 #ifndef	_WIN32
109 109
         struct passwd *user = NULL;
110 110
 	struct sigaction sa;
111
+	struct rlimit rlim;
111 112
 #endif
112 113
 	time_t currtime;
113 114
 	const char *dbdir, *cfgfile;
... ...
@@ -295,6 +297,26 @@ int main(int argc, char **argv)
295 295
 	logg("#Running as user %s (UID %u, GID %u)\n", user->pw_name, user->pw_uid, user->pw_gid);
296 296
 #endif
297 297
 
298
+#ifdef RLIMIT_DATA
299
+    if (getrlimit(RLIMIT_DATA, &rlim) == 0) {
300
+       /* bb #1941.
301
+        * On 32-bit FreeBSD if you set ulimit -d to >2GB then mmap() will fail
302
+        * too soon (after ~120 MB).
303
+        * Set limit lower than 2G if on 32-bit */
304
+       uint64_t lim = rlim.rlim_cur;
305
+       lim = (int32_t) lim;
306
+       if (sizeof(void*) == 4 &&
307
+           lim != rlim.rlim_cur) {
308
+           rlim.rlim_cur = 2048*1024-1;
309
+           if (setrlimit(RLIMIT_DATA, &rlim) < 0)
310
+               logg("!setrlimit(RLIMIT_DATA) failed: %s\n", strerror(errno));
311
+           else
312
+               logg("^Running on 32-bit system, and RLIMIT_DATA > 2GB, lowering to 2GB!\n");
313
+       }
314
+    }
315
+#endif
316
+
317
+
298 318
     if(logg_size)
299 319
 	logg("#Log file size limited to %d bytes.\n", logg_size);
300 320
     else