From de91f43eb80eecf118bae252ecce36aa4a1268a2 Mon Sep 17 00:00:00 2001 From: Petter Reinholdtsen Date: Sun, 22 Nov 2009 21:03:03 +0000 Subject: [PATCH] Fix race condition in utmp writing. Patch from Gil Kloepfer via Mike Frysinger and Gentoo. --- doc/Changelog | 2 ++ src/init.c | 29 ++++++++++++++++++++--------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/doc/Changelog b/doc/Changelog index 89f5bb3..18cd20b 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -17,6 +17,8 @@ sysvinit (2.88dsf) UNRELEASED; urgency=low Patch from Mike Frysinger and Gentoo. * Sync shutdown manual page and usage information. Patch from Mike Frysinger and Gentoo. + * Fix race condition in utmp writing. Patch from Gil Kloepfer via + Mike Frysinger and Gentoo. -- Petter Reinholdtsen Sun, 12 Jul 2009 19:58:10 +0200 diff --git a/src/init.c b/src/init.c index 81ecf4c..30592da 100644 --- a/src/init.c +++ b/src/init.c @@ -967,6 +967,25 @@ int spawn(CHILD *ch, int *res) sigprocmask(SIG_SETMASK, &omask, NULL); + /* + * Update utmp/wtmp file prior to starting + * any child. This MUST be done right here in + * the child process in order to prevent a race + * condition that occurs when the child + * process' time slice executes before the + * parent (can and does happen in a uniprocessor + * environment). If the child is a getty and + * the race condition happens, then init's utmp + * update will happen AFTER the getty runs + * and expects utmp to be updated already! + * + * Do NOT log if process field starts with '+' + * FIXME: that's for compatibility with *very* + * old getties - probably it can be taken out. + */ + if (ch->action == RESPAWN && ch->process[0] != '+') + write_utmp_wtmp("", ch->id, getpid(), INIT_PROCESS, ""); + /* * In sysinit, boot, bootwait or single user mode: * for any wait-type subprocess we _force_ the console @@ -1109,15 +1128,7 @@ void startup(CHILD *ch) case ONDEMAND: case RESPAWN: ch->flags |= RUNNING; - if (spawn(ch, &(ch->pid)) < 0) break; - /* - * Do NOT log if process field starts with '+' - * FIXME: that's for compatibility with *very* - * old getties - probably it can be taken out. - */ - if (ch->process[0] != '+') - write_utmp_wtmp("", ch->id, ch->pid, - INIT_PROCESS, ""); + (void)spawn(ch, &(ch->pid)); break; } }