Subject: bin/15142: cron doesn't use login.conf process limits.
To: None <gnats-bugs@gnats.netbsd.org>
From: None <kpn@neutralgood.org>
List: netbsd-bugs
Date: 01/04/2002 21:11:23
>Number:         15142
>Category:       bin
>Synopsis:       cron doesn't use login.conf process limits.
>Confidential:   yes
>Severity:       critical
>Priority:       high
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Jan 04 18:12:00 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Kevin P. Neal
>Release:        NetBSD 1.5.2
>Organization:
-- 
Kevin P. Neal                                http://www.pobox.com/~kpn/

"You know, I think I can hear the machine screaming from here...  \
'help me! hellpp meeee!'"  - Heather Flanagan, 14:52:23 Wed Jun 10 1998
>Environment:

NetBSD 1.5.2, Alpha

>Description:

When cron fires off a process for a user it doesn't first set the login.conf 
limits for that user process. If the user already has too many processes 
running then the cron job fails. 

>How-To-Repeat:

Have a whole bunch of processes running, like dozens of xterms or compiles
or something. Leave overnight. Get email in the morning complaining of
a failure to fork(). 

>Fix:

--- usr.sbin/cron/do_command.c.old	Fri Jan  4 20:47:55 2002
+++ usr.sbin/cron/do_command.c.new	Fri Jan  4 20:38:29 2002
@@ -36,6 +36,10 @@
 # include <syslog.h>
 #endif
 
+#ifdef LOGIN_CAP
+# include <pwd.h>
+# include <login_cap.h>
+#endif
 
 static void		child_process __P((entry *, user *)),
 			do_univ __P((user *));
@@ -89,6 +93,10 @@
 	(void) &mailto;
 	(void) &children;
 #endif
+#ifdef LOGIN_CAP
+	login_cap_t *lc;
+	struct passwd *pwd;
+#endif
 	Debug(DPROC, ("[%d] child_process('%s')\n", getpid(), e->cmd))
 
 	/* mark ourselves as different to PS command watchers by upshifting
@@ -215,6 +223,21 @@
 		 */
 		do_univ(u);
 
+#ifdef LOGIN_CAP
+		pwd = getpwnam(env_get("LOGNAME", e->envp));
+
+		/* Note that pwd can be NULL since it falls back to 
+		 * the "default" class if it is.
+		 */
+
+		lc = login_getclass(pwd ? pwd->pw_class : NULL);
+
+		if (setusercontext(lc, pwd, e->uid,
+		    LOGIN_SETALL & ~LOGIN_SETPATH) != 0) {
+			syslog(LOG_ERR, "setusercontext failed");
+			_exit(ERROR_EXIT);
+		}
+#else
 		/* set our directory, uid and gid.  Set gid first, since once
 		 * we set uid, we've lost root privledges.
 		 */
@@ -223,6 +246,8 @@
 		initgroups(env_get("LOGNAME", e->envp), e->gid);
 # endif
 		setuid(e->uid);		/* we aren't root after this... */
+#endif /* LOGIN_CAP */
+
 		chdir(env_get("HOME", e->envp));
 
 #ifdef USE_SIGCHLD
>Release-Note:
>Audit-Trail:
>Unformatted: