Hi.

A bug in sysctl_sysctl_next_ls() makes the kernel panic, if an empty
node is passed to it, because the value of 'namelen' is statically
assigned 1 at the end of the routine.

I finally got my head around this issue, and I thought I would submit a
fix.  Yesterday, I found out that there is PR for this issue, since
4.4-RELEASE, which means, that the bug is old, so the fix will need to
be MFC'ed.

Test code: http://www.unixdaemons.com/~hiten/work/misc/sysctlbug1.c
Patch: http://www.unixdaemons.com/~hiten/work/diffs/kern_sysctl.c.patch

I also have a screenshot of my VMware FreeBSD-CURRENT installation, in
which I wrote the test code.  Compile the test code as a KLD, and then
load it, after that, execute:

        # sysctl -a bugfoo

Screenshot, http://www.unixdaemons.com/~hiten/work/misc/sysctl-bug.gif,
and PR kern/31490.  If you have any questions or comments regarding this
bug, please do not hesitate to contact me for more information.

Cheers.

P.S. Patch and test code attached with this mail.

-- 
Hiten Pandya ([EMAIL PROTECTED], [EMAIL PROTECTED])
http://www.unixdaemons.com/~hiten/
/*
 * Code for reproducing Sysctl (empty node) bug.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
#include <sys/kernel.h>
#include <sys/module.h>

static int bug_load(module_t, int, void *);

SYSCTL_DECL(_bugfoo);

SYSCTL_NODE(, 0, bugfoo, CTLFLAG_RW, 0, "Bugfoo and Family");
SYSCTL_NODE(_bugfoo, OID_AUTO, mac, CTLFLAG_RW, 0, "Bugfoo and Family");
SYSCTL_NODE(_bugfoo_mac, OID_AUTO, debug, CTLFLAG_RW, 0, "BF [1]");
SYSCTL_NODE(_bugfoo_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, "BF [2]");

static int      mac_debug_label_fallback = 0;
SYSCTL_INT(_bugfoo_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
&mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
"when label is corrupted.");

TUNABLE_INT("bugfoo.mac.debug_label_fallback", &mac_debug_label_fallback);

/* Module initialisation stuff */
static moduledata_t bugctl_mod = {
        "bugctl",
        bug_load,
        0
};

static int
bug_load(module_t mod, int cmd, void *arg)
{
    int  err = 0;

    switch (cmd) {
    case MOD_LOAD:

                printf("Sysctl Bug Manipulation\n");
                break;          /* Success*/
            
    case MOD_UNLOAD:
            
                break;          /* Success */
        
    default: 
        err = EINVAL;
        break;
    }

    return(err);
}

/* Now declare the module to the system */
DECLARE_MODULE(bugctl, bugctl_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
Index: kern_sysctl.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_sysctl.c,v
retrieving revision 1.135
diff -u -r1.135 kern_sysctl.c
--- kern_sysctl.c       2002/10/27 07:12:34     1.135
+++ kern_sysctl.c       2002/12/03 14:51:07
@@ -538,7 +538,10 @@
        int *next, int *len, int level, struct sysctl_oid **oidpp)
 {
        struct sysctl_oid *oidp;
+       int i_namelen;
 
+       i_namelen = namelen ? 1 : 0;
+       
        *len = level;
        SLIST_FOREACH(oidp, lsp, oid_link) {
                *next = oidp->oid_number;
@@ -585,7 +588,7 @@
                        len, level+1, oidpp))
                        return (0);
        next:
-               namelen = 1;
+               namelen = i_namelen;
                *len = level;
        }
        return 1;

Reply via email to