From owner-freebsd-current@FreeBSD.ORG Wed Jun 3 03:18:49 2009 Return-Path: Delivered-To: current@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3F920106564A for ; Wed, 3 Jun 2009 03:18:49 +0000 (UTC) (envelope-from benno@jeamland.net) Received: from mail.jeamland.net (rafe.jeamland.net [203.20.99.33]) by mx1.freebsd.org (Postfix) with ESMTP id B140C8FC19 for ; Wed, 3 Jun 2009 03:18:48 +0000 (UTC) (envelope-from benno@jeamland.net) Received: from mail.jeamland.net (localhost [127.0.0.1]) by mail.jeamland.net (Postfix) with ESMTP id 489C71CD7F for ; Wed, 3 Jun 2009 13:03:16 +1000 (EST) X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on rafe.jeamland.net X-Spam-Level: X-Spam-Status: No, score=-6.5 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_00 autolearn=ham version=3.2.5 Received: from [10.1.7.168] (ppp154-45.static.internode.on.net [150.101.154.45]) by mail.jeamland.net (Postfix) with ESMTPSA id C1CEF1CD7D for ; Wed, 3 Jun 2009 13:03:15 +1000 (EST) Message-Id: From: Benno Rice To: current@freebsd.org Content-Type: multipart/mixed; boundary=Apple-Mail-4--596983795 Mime-Version: 1.0 (Apple Message framework v935.3) Date: Wed, 3 Jun 2009 13:03:08 +1000 X-Mailer: Apple Mail (2.935.3) X-Virus-Scanned: ClamAV using ClamSMTP at rafe.jeamland.net Cc: Subject: CFR: sanity checking arguments to kldload(8) X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 03 Jun 2009 03:18:49 -0000 --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 #include #include +#include #include #include #include +#include +#include +#include +#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--