diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2003-04-16 10:33:17 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2003-04-16 10:33:17 +0000 |
commit | 4322274a0d898ba4a32ceac31ac732e1e79aa085 (patch) | |
tree | ef76a66590c46bc2191961ce9f1a7be2a6f27cec /sbin | |
parent | 0a426a4c3cd06fa9384598731c4c11e6213d53ef (diff) |
fix race between mount(2) and exit(2) for mount_mfs.
from netbsd (drochner, newfs.c 1.30, mkfs.c 1.29, no copyright changes)
ok tedu@
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/newfs/mkfs.c | 41 | ||||
-rw-r--r-- | sbin/newfs/newfs.c | 74 |
2 files changed, 69 insertions, 46 deletions
diff --git a/sbin/newfs/mkfs.c b/sbin/newfs/mkfs.c index 670fb41251a..b290d00fda7 100644 --- a/sbin/newfs/mkfs.c +++ b/sbin/newfs/mkfs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mkfs.c,v 1.23 2003/02/19 00:57:14 millert Exp $ */ +/* $OpenBSD: mkfs.c,v 1.24 2003/04/16 10:33:16 markus Exp $ */ /* $NetBSD: mkfs.c,v 1.25 1995/06/18 21:35:38 cgd Exp $ */ /* @@ -38,13 +38,12 @@ #if 0 static char sccsid[] = "@(#)mkfs.c 8.3 (Berkeley) 2/3/94"; #else -static char rcsid[] = "$OpenBSD: mkfs.c,v 1.23 2003/02/19 00:57:14 millert Exp $"; +static char rcsid[] = "$OpenBSD: mkfs.c,v 1.24 2003/04/16 10:33:16 markus Exp $"; #endif #endif /* not lint */ #include <sys/param.h> #include <sys/time.h> -#include <sys/wait.h> #include <sys/resource.h> #include <ufs/ufs/dinode.h> #include <ufs/ufs/dir.h> @@ -54,7 +53,6 @@ static char rcsid[] = "$OpenBSD: mkfs.c,v 1.23 2003/02/19 00:57:14 millert Exp $ #include <string.h> #include <stdlib.h> -#include <signal.h> #include <unistd.h> #ifndef STANDALONE @@ -159,7 +157,6 @@ mkfs(pp, fsys, fi, fo) int status; time_t utime; quad_t sizepb; - void started(); int width; char tmpbuf[100]; /* XXX this will break in about 2,500 years */ @@ -175,18 +172,6 @@ mkfs(pp, fsys, fi, fo) time(&utime); #endif if (mfs) { - ppid = getpid(); - (void) signal(SIGUSR1, started); - if ((i = fork())) { - if (i == -1) { - perror("mfs"); - exit(10); - } - if (waitpid(i, &status, 0) != -1 && WIFEXITED(status)) - exit(WEXITSTATUS(status)); - exit(11); - /* NOTREACHED */ - } (void)malloc(0); if (fssize * sectorsize > memleft) fssize = (memleft - 16384) / sectorsize; @@ -701,18 +686,6 @@ next: pp->p_fsize = sblock.fs_fsize; pp->p_frag = sblock.fs_frag; pp->p_cpg = sblock.fs_cpg; - /* - * Notify parent process of success. - * Dissociate from session and tty. - */ - if (mfs) { - kill(ppid, SIGUSR1); - (void) setsid(); - (void) close(0); - (void) close(1); - (void) close(2); - (void) chdir("/"); - } } /* @@ -1089,16 +1062,6 @@ iput(ip, ino) } /* - * Notify parent process that the filesystem has created itself successfully. - */ -void -started() -{ - - _exit(0); -} - -/* * Replace libc function with one suited to our needs. */ static void * diff --git a/sbin/newfs/newfs.c b/sbin/newfs/newfs.c index 7ab1d2755aa..12d50e6efd7 100644 --- a/sbin/newfs/newfs.c +++ b/sbin/newfs/newfs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: newfs.c,v 1.36 2003/03/13 09:09:26 deraadt Exp $ */ +/* $OpenBSD: newfs.c,v 1.37 2003/04/16 10:33:16 markus Exp $ */ /* $NetBSD: newfs.c,v 1.20 1996/05/16 07:13:03 thorpej Exp $ */ /* @@ -44,7 +44,7 @@ static char copyright[] = #if 0 static char sccsid[] = "@(#)newfs.c 8.8 (Berkeley) 4/18/94"; #else -static char rcsid[] = "$OpenBSD: newfs.c,v 1.36 2003/03/13 09:09:26 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: newfs.c,v 1.37 2003/04/16 10:33:16 markus Exp $"; #endif #endif /* not lint */ @@ -57,6 +57,7 @@ static char rcsid[] = "$OpenBSD: newfs.c,v 1.36 2003/03/13 09:09:26 deraadt Exp #include <sys/disklabel.h> #include <sys/mount.h> #include <sys/sysctl.h> +#include <sys/wait.h> #include <ufs/ufs/dir.h> #include <ufs/ffs/fs.h> @@ -71,6 +72,7 @@ static char rcsid[] = "$OpenBSD: newfs.c,v 1.36 2003/03/13 09:09:26 deraadt Exp #include <string.h> #include <syslog.h> #include <unistd.h> +#include <signal.h> #include <util.h> #include <err.h> @@ -202,7 +204,13 @@ main(argc, argv) struct stat st; struct statfs *mp; int fsi = -1, fso, len, n, maxpartitions; - char *cp, *s1, *s2, *special, *opstring, buf[BUFSIZ]; + char *cp, *s1, *s2, *special, *opstring; +#ifdef MFS + char mountfromname[BUFSIZ]; + pid_t pid, res; + struct statfs sf; + int status; +#endif char *fstype = NULL; char **saveargv = argv; int ffs = 1; @@ -588,9 +596,61 @@ havelabel: #ifdef MFS if (mfs) { struct mfs_args args; - - snprintf(buf, sizeof buf, "mfs:%ld", (long)getpid()); - args.fspec = buf; + + switch (pid = fork()) { + case -1: + perror("mfs"); + exit(10); + case 0: + snprintf(mountfromname, sizeof(mountfromname), + "mfs:%d", getpid()); + break; + default: + snprintf(mountfromname, sizeof(mountfromname), + "mfs:%d", pid); + for (;;) { + /* + * spin until the mount succeeds + * or the child exits + */ + usleep(1); + + /* + * XXX Here is a race condition: another process + * can mount a filesystem which hides our + * ramdisk before we see the success. + */ + if (statfs(argv[1], &sf) < 0) + err(88, "statfs %s", argv[1]); + if (!strcmp(sf.f_mntfromname, mountfromname) && + !strncmp(sf.f_mntonname, argv[1], + MNAMELEN) && + !strcmp(sf.f_fstypename, "mfs")) + exit(0); + + res = waitpid(pid, &status, WNOHANG); + if (res == -1) + err(11, "waitpid"); + if (res != pid) + continue; + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) == 0) + exit(0); + errx(1, "%s: mount: %s", argv[1], + strerror(WEXITSTATUS(status))); + } else + errx(11, "abnormal termination"); + } + /* NOTREACHED */ + } + + (void) setsid(); + (void) close(0); + (void) close(1); + (void) close(2); + (void) chdir("/"); + + args.fspec = mountfromname; args.export_info.ex_root = -2; if (mntflags & MNT_RDONLY) args.export_info.ex_flags = MNT_EXRDONLY; @@ -599,7 +659,7 @@ havelabel: args.base = membase; args.size = fssize * sectorsize; if (mount(MOUNT_MFS, argv[1], mntflags, &args) < 0) - fatal("%s: %s", argv[1], strerror(errno)); + exit(errno); /* parent prints message */ } #endif exit(0); |