summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2003-04-16 10:33:17 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2003-04-16 10:33:17 +0000
commit4322274a0d898ba4a32ceac31ac732e1e79aa085 (patch)
treeef76a66590c46bc2191961ce9f1a7be2a6f27cec
parent0a426a4c3cd06fa9384598731c4c11e6213d53ef (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@
-rw-r--r--sbin/newfs/mkfs.c41
-rw-r--r--sbin/newfs/newfs.c74
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);