Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 3 Jun 2009 13:03:08 +1000
From:      Benno Rice <benno@jeamland.net>
To:        current@freebsd.org
Subject:   CFR: sanity checking arguments to kldload(8)
Message-ID:  <B8E26963-4413-499B-A512-A5ECF997D11A@jeamland.net>

next in thread | raw e-mail | index | archive | help

--Apple-Mail-4--596983795
Content-Type: text/plain;
	charset=US-ASCII;
	format=flowed;
	delsp=yes
Content-Transfer-Encoding: 7bit

The attached patch performs some sanity checking on arguments passed  
to kldload(8).  Specifically, if an argument looks like a filename but  
lacks a path (eg, 'xfs.ko' as opposed to 'xfs' or './xfs.ko') it  
checks to see if a file with that name is in the current directory.   
If it is, it checks the current module path to see if a file with that  
name also exists there (possibly in an earlier entry if the current  
directory is in the module path), if so it warns the user that that  
module will be loaded and not the one in the current directory.  If  
not, it tells the user how to use a path to load the module.

A -q option is added to quieten the output if desired.

Sample output:

# sysctl kern.module_path
kern.module_path: /boot/kernel;/boot/modules
# kldstat
Id Refs Address    Size     Name
  1    1 0xc0400000 cc016c   kernel
# pwd
/boot/kernel
# kldload xfs.ko
# kldstat
Id Refs Address    Size     Name
  1    3 0xc0400000 cc016c   kernel
  2    1 0xc3a09000 b0000    xfs.ko
# kldunload xfs
# cd /boot/modules
# pwd
/boot/modules
# ls
xfs.ko*		xfs.ko.symbols*
# kldload xfs.ko
kldload: xfs.ko will be loaded from /boot/kernel, not the current  
directory
kldload: to load from the current directory use ./xfs.ko
# kldstat
Id Refs Address    Size     Name
  1    3 0xc0400000 cc016c   kernel
  2    1 0xc3a09000 b0000    xfs.ko
# kldunload xfs
# kldload -q xfs.ko
# kldstat
Id Refs Address    Size     Name
  1    3 0xc0400000 cc016c   kernel
  2    1 0xc3a09000 b0000    xfs.ko
# kldunload xfs
# kldstat
Id Refs Address    Size     Name
  1    1 0xc0400000 cc016c   kernel
# cd fnord
# pwd
/boot/modules/fnord
# ls
ibcs2.ko*		ibcs2.ko.symbols*
# ls /boot/kernel/ibcs2.ko
ls: /boot/kernel/ibcs2.ko: No such file or directory
# ls /boot/modules/ibcs2.ko
ls: /boot/modules/ibcs2.ko: No such file or directory
# kldload ibcs2.ko
kldload: ibcs2.ko is not in the module path
kldload: to load from the current directory use ./ibcs2.ko
# kldstat
Id Refs Address    Size     Name
  1    1 0xc0400000 cc016c   kernel
# kldload -q ibcs2.ko
# kldstat
Id Refs Address    Size     Name
  1    1 0xc0400000 cc016c   kernel
# kldload ./ibcs2.ko
# kldstat
Id Refs Address    Size     Name
  1    6 0xc0400000 cc016c   kernel
  2    1 0xc3a09000 b000     ibcs2.ko
# kldunload ibcs2
# kldstat
Id Refs Address    Size     Name
  1    1 0xc0400000 cc016c   kernel


--Apple-Mail-4--596983795
Content-Disposition: attachment;
	filename=kldload.diff
Content-Type: application/octet-stream; x-unix-mode=0644; name="kldload.diff"
Content-Transfer-Encoding: 7bit

Index: sbin/kldload/kldload.c
===================================================================
--- sbin/kldload/kldload.c	(revision 193292)
+++ sbin/kldload/kldload.c	(working copy)
@@ -30,10 +30,103 @@
 #include <err.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 #include <sys/param.h>
 #include <sys/linker.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
+#define	PATHCTL	"kern.module_path"
+
+/*
+ * Check to see if the requested module is specified as a filename with no
+ * path.  If so and if a file by the same name exists in the module path,
+ * warn the user that the module in the path will be used in preference.
+ */
+static int
+path_check(const char *kldname, int quiet)
+{
+	int	mib[5], found;
+	size_t	miblen, pathlen;
+	char	kldpath[MAXPATHLEN];
+	char	*path, *tmppath, *element;
+	struct	stat sb;
+	dev_t	dev;
+	ino_t	ino;
+
+	if (strchr(kldname, '/') != NULL) {
+		return (0);
+	}
+	if (strstr(kldname, ".ko") == NULL) {
+		return (0);
+	}
+	if (stat(kldname, &sb) != 0) {
+		return (0);
+	}
+
+	found = 0;
+	dev = sb.st_dev;
+	ino = sb.st_ino;
+
+	miblen = sizeof(mib) / sizeof(mib[0]);
+	if (sysctlnametomib(PATHCTL, mib, &miblen) != 0) {
+		err(1, "sysctlnametomib(%s)", PATHCTL);
+	}
+	if (sysctl(mib, miblen, NULL, &pathlen, NULL, 0) == -1) {
+		err(1, "getting path: sysctl(%s) - size only", PATHCTL);
+	}
+	path = malloc(pathlen + 1);
+	if (path == NULL) {
+		err(1, "allocating %lu bytes for the path",
+		    (unsigned long)pathlen + 1);
+	}
+	if (sysctl(mib, miblen, path, &pathlen, NULL, 0) == -1) {
+		err(1, "getting path: sysctl(%s)", PATHCTL);
+	}
+	tmppath = path;
+
+	while ((element = strsep(&tmppath, ";")) != NULL) {
+		strlcpy(kldpath, element, MAXPATHLEN);
+		if (kldpath[strlen(kldpath) - 1] != '/') {
+			strlcat(kldpath, "/", MAXPATHLEN);
+		}
+		strlcat(kldpath, kldname, MAXPATHLEN);
+				
+		if (stat(kldpath, &sb) == -1) {
+			continue;
+		}	
+
+		found = 1;
+
+		if (sb.st_dev != dev || sb.st_ino != ino) {
+			if (!quiet) {
+				warnx("%s will be loaded from %s, not the "
+				    "current directory", kldname, element);
+				warnx("to load from the current directory use "
+				    "./%s", kldname);
+			}
+			break;
+		} else if (sb.st_dev == dev && sb.st_ino == ino) {
+			return (0);
+		}
+	}
+
+	free(path);
+	
+	if (!found) {
+		if (!quiet) {
+			warnx("%s is not in the module path", kldname);
+			warnx("to load from the current directory use ./%s",
+			    kldname);
+		}
+		return (-1);
+	}
+	
+	return (0);
+}
+
 static void
 usage(void)
 {
@@ -48,14 +141,21 @@
     int errors;
     int fileid;
     int verbose;
+    int quiet;
 
     errors = 0;
     verbose = 0;
-
-    while ((c = getopt(argc, argv, "v")) != -1)
+    quiet = 0;
+    
+    while ((c = getopt(argc, argv, "qv")) != -1)
 	switch (c) {
+	case 'q':
+	    quiet = 1;
+	    verbose = 0;
+	    break;
 	case 'v':
 	    verbose = 1;
+	    quiet = 0;
 	    break;
 	default:
 	    usage();
@@ -67,13 +167,17 @@
 	usage();
 
     while (argc-- != 0) {
-	fileid = kldload(argv[0]);
-	if (fileid < 0) {
-	    warn("can't load %s", argv[0]);
-	    errors++;
-	} else
-	    if (verbose)
-		printf("Loaded %s, id=%d\n", argv[0], fileid);
+	if (path_check(argv[0], quiet) == 0) {
+		fileid = kldload(argv[0]);
+		if (fileid < 0) {
+		    warn("can't load %s", argv[0]);
+		    errors++;
+		} else
+		    if (verbose)
+			printf("Loaded %s, id=%d\n", argv[0], fileid);
+	} else {
+		errors++;
+	}
 	argv++;
     }
 

--Apple-Mail-4--596983795
Content-Type: text/plain;
	charset=US-ASCII;
	format=flowed
Content-Transfer-Encoding: 7bit



-- 
Benno Rice
benno@jeamland.net




--Apple-Mail-4--596983795--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?B8E26963-4413-499B-A512-A5ECF997D11A>