[klibc] [PATCH] kinit

Volker Dormeyer volker at ixolution.de
Fri Mar 12 22:04:01 PST 2004


Hello,

On Wed, Mar 10, 2004 at 10:28:30AM -0800,
H. Peter Anvin <hpa at zytor.com> wrote:
 > Volker Dormeyer wrote:
 > >try_name () determined "part" with minor 3 and "res" contained major 3.
 > >Now, try_name () returned "6" and mknod () created /dev/root with
 > >major 0 and minor 6. I did a left shift of 8 bits, to give mknod () an
 > >appropriate 16 bit value of type dev_t.
 > 
 > NO NO NO NO NO NO NO NO NO NO NO NO NO...
 > 
 > First of all, dev_t is 32 bits not 16.  Use makedev() to create one.

using makedev() works fine.

Here is another patch, which should solve the problem. This code was
mostly derived from a recent 2.6 kernel. The older code seemed to be
derived from an 2.5 kernel some time ago.

The patch changes the following:

    * Determine the root device (major, minor) from sysfs
      of recent 2.6.x kernels.

    * It removes the pivot_root call, because it doesn't work
      anymore in recent 2.6 kernels. It mounts the real root
      over the ramfs root. But it does not contain a cleanup
      of the ramfs.

Regards,
Volker
-------------- next part --------------
diff -upr klibc-0.115/kinit/do_mounts.c klibc-0.115_dev/kinit/do_mounts.c
--- klibc-0.115/kinit/do_mounts.c	2003-06-01 08:21:09.000000000 +0200
+++ klibc-0.115_dev/kinit/do_mounts.c	2004-03-12 21:31:34.000000000 +0100
@@ -17,8 +17,7 @@ static const char *progname = "VFS";
 static const int do_devfs; // FIXME
 
 /* Find dev_t for e.g. "hda,NULL" or "hdb,2" */
-static dev_t
-try_name(char *name, int part)
+static dev_t try_name(char *name, int part)
 {
 	char path[BUF_SZ];
 	char buf[BUF_SZ];
@@ -27,34 +26,46 @@ try_name(char *name, int part)
 	char *s;
 	int len;
 	int fd;
+	int maj, min;
 
 	/* read device number from /sys/block/.../dev */
-	snprintf(path, sizeof(path), "/sys/block/%s/dev", name);
+	sprintf(path, "/sys/block/%s/dev", name);
 	fd = open(path, 0, 0);
 	if (fd < 0)
 		goto fail;
 	len = read(fd, buf, BUF_SZ);
 	close(fd);
-
 	if (len <= 0 || len == BUF_SZ || buf[len - 1] != '\n')
 		goto fail;
 	buf[len - 1] = '\0';
-	res = (dev_t) strtoul(buf, &s, 16);
-	if (*s)
-		goto fail;
+	if (sscanf(buf, "%u:%u", &maj, &min) == 2) {
+		/*
+		 * Try the %u:%u format -- see print_dev_t()
+		 */
+	  	res = makedev(maj, min);
+		if (maj != major(res) || min != minor(res))
+			goto fail;
+	} else {
+		/*
+		 * Try old-style "0321"
+		 */
+	  	res = (dev_t) strtoul(buf, &s, 16);
+		if (*s)
+		  	goto fail;
+	}
 
 	/* if it's there and we are not looking for a partition - that's it */
 	if (!part)
 		return res;
 
 	/* otherwise read range from .../range */
-	snprintf(path, sizeof(path), "/sys/block/%s/range", name);
+	sprintf(path, "/sys/block/%s/range", name);
 	fd = open(path, 0, 0);
 	if (fd < 0)
 		goto fail;
-	len = read(fd, buf, 32);
+	len = read(fd, buf, BUF_SZ);
 	close(fd);
-	if (len <= 0 || len == 32 || buf[len - 1] != '\n')
+	if (len <= 0 || len == BUF_SZ || buf[len - 1] != '\n')
 		goto fail;
 	buf[len - 1] = '\0';
 	range = strtoul(buf, &s, 10);
@@ -73,7 +84,7 @@ fail:
  *	Convert a name into device number.  We accept the following variants:
  *
  *	1) device number in hexadecimal	represents itself
- *	2) /dev/nfs represents Root_NFS
+ *	2) /dev/nfs represents Root_NFS (0xff)
  *	3) /dev/<disk_name> represents the device number of disk
  *	4) /dev/<disk_name><decimal> represents the device number
  *         of partition - device number of disk plus the partition number
@@ -84,12 +95,11 @@ fail:
  *	Driverfs is used to check if something is a disk name - it has
  *	all known disks under bus/block/devices.  If the disk name
  *	contains slashes, name of driverfs node has them replaced with
- *	dots.  try_name() does the actual checks, assuming that driverfs
+ *	bangs.  try_name() does the actual checks, assuming that driverfs
  *	is mounted on rootfs /sys.
  */
 
-static dev_t
-name_to_dev_t(const char *name)
+static dev_t name_to_dev_t(const char *name)
 {
 	char *p;
 	dev_t res = 0;
@@ -97,9 +107,17 @@ name_to_dev_t(const char *name)
 	int part;
 
 	if (strncmp(name, "/dev/", 5) != 0) {
-		res = (dev_t) strtoul(name, &p, 16);
-		if (*p)
-			goto fail;
+		int maj, min;
+
+		if (sscanf(name, "%u:%u", &maj, &min) == 2) {
+			res = makedev(maj, min);
+			if (maj != major(res) || min != minor(res))
+				goto fail;
+		} else {
+			res = (dev_t) strtoul(name, &p, 16);
+			if (*p)
+				goto fail;
+		}
 		goto done;
 	}
 	name += 5;
@@ -113,7 +131,7 @@ name_to_dev_t(const char *name)
 
 	for (p = s; *p; p++)
 		if (*p == '/')
-			*p = '.';
+			*p = '!';
 	res = try_name(s, 0);
 	if (res)
 		goto done;
@@ -132,15 +150,14 @@ name_to_dev_t(const char *name)
 		goto fail;
 	p[-1] = '\0';
 	res = try_name(s, part);
- done:
+done:
 	return res;
- fail:
+fail:
 	res = (dev_t) 0;
 	goto done;
 }
 
-static int
-find_in_devfs(char *path, dev_t dev)
+static int find_in_devfs(char *path, dev_t dev)
 {
 	(void) path;
 	(void) dev;
@@ -190,8 +207,7 @@ find_in_devfs(char *path, dev_t dev)
 }
 
 /* Create the device node "name" */
-static int
-create_dev(const char *name, dev_t dev, const char *devfs_name)
+static int create_dev(const char *name, dev_t dev, const char *devfs_name)
 {
 	char path[BUF_SZ];
 
@@ -217,8 +233,7 @@ create_dev(const char *name, dev_t dev, 
 }
 
 /* get a list of all filesystems to try to mount root with */
-static void
-get_fs_names(int argc, char *argv[], char *buf)
+static void get_fs_names(int argc, char *argv[], char *buf)
 {
 	char *s, *p;
 	char line[BUF_SZ];
@@ -255,8 +270,7 @@ get_fs_names(int argc, char *argv[], cha
 }
 
 /* mount the root filesystem from a block device */
-static int
-mount_block_root(int argc, char *argv[],
+static int mount_block_root(int argc, char *argv[],
 		 dev_t root_dev, const char *root_dev_name, int flags)
 {
 	char fs_names[BUF_SZ];
@@ -298,8 +312,7 @@ out:
 	return 0;
 }
 
-int
-do_mounts(int argc, char *argv[])
+int do_mounts(int argc, char *argv[])
 {
 	const char *root_dev_name = get_arg(argc, argv, "root=");
 	int flags = MS_RDONLY | MS_VERBOSE;
diff -upr klibc-0.115/kinit/kinit.c klibc-0.115_dev/kinit/kinit.c
--- klibc-0.115/kinit/kinit.c	2003-06-01 08:18:41.000000000 +0200
+++ klibc-0.115_dev/kinit/kinit.c	2004-03-12 21:26:26.000000000 +0100
@@ -182,7 +182,7 @@ char *get_arg(int argc, char *argv[], co
 
 	for (i = 1; i < argc; i++) {
 		if (argv[i] && strncmp(argv[i], name, len) == 0 &&
-		    (argv[i][len] == '\0')) {
+		    (argv[i][len] != '\0')) {
 			ret = argv[i] + len;
 			break;
 		}
@@ -260,22 +260,18 @@ int main(int argc, char *argv[])
 
 	restore_cmdline(saved, cmdc, cmdv);
 	check_path("/root");
-	check_path("/old_root");
 	do_mounts(cmdc, cmdv);
 
 #ifndef INI_DEBUG
-	if (pivot_root(".", "old_root") == -1) {
-		perror("pivot_root");
-		ret = 2;
-		goto bail;
-	}
-
 	if (mnt_procfs == 1)
 		umount2("/proc", 0);
 
 	if (mnt_sysfs == 1)
 		umount2("/sys", 0);
 
+	mount(".", "/", NULL, MS_MOVE, NULL);
+	chroot(".");
+
 	for (i = 1; i < cmdc; i++) {
 		if (strncmp(cmdv[i], "kinit=", 6) == 0) {
 			kinit = cmdv[i] + 6;
@@ -298,7 +294,7 @@ int main(int argc, char *argv[])
 	ret = 2;
 	goto done;
 #else
-	printf("%s: imagine pivot_root and exec\n", progname);
+	printf("%s: imagine mount, chroot and exec\n", progname);
 #endif
 
  bail:


More information about the klibc mailing list