Date: Fri, 23 Mar 2001 10:57:34 -0800 (PST) From: jtrainor@fastekintl.com To: freebsd-gnats-submit@FreeBSD.org Subject: kern/26034: kldload() panics if error code is returned from <module_name>_load(). Message-ID: <200103231857.f2NIvY209246@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 26034
>Category: kern
>Synopsis: kldload() panics if error code is returned from <module_name>_load().
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Fri Mar 23 11:00:03 PST 2001
>Closed-Date:
>Last-Modified:
>Originator: Jim Trainor
>Release: FreeBSD 4.2-RELEASE #0: 11/20/2000
>Organization:
Fastek International Ltd.
>Environment:
FreeBSD BSDDEV.fastekintl.com 4.2-RELEASE FreeBSD 4.2-RELEASE #0: Mon Nov 20 13:02:55 GMT 2000 jkh@bento.FreeBSD.org:/usr/src/sys/compile/GENERIC i386
>Description:
panic trap 12 (page fault) in kldload while attempting to return an error from <module_name>_load. If I set the return value prior to entering the case statement, proper behavior is observed. If I set the return value inside the case statement, panic occurs. See code below.
>How-To-Repeat:
/* =============================================================== */
/* Program..... KLD Character Device Implementation Skeleton */
/* Version..... 1.0 */
/* File........ CDEVEXAM.C */
/* Date........ 03/04/2001 */
/* Programmer.. Jim Trainor */
/* Copyright (c)2001 Fastek International Ltd. */
/* --------------------------------------------------------------- */
/* */
/* --------------------------------------------------------------- */
/* This code is from the article "Dynamic Kernel Linker (KLD) */
/* Facility Programming Tutorial" by Andrew Reiter. The article */
/* was in "daemonnews" October 2000. */
/* The module is loaded with "kldload ./cdev_exam.ko" */
/* --------------------------------------------------------------- */
/* $Header$ */
/* --------------------------------------------------------------- */
/* <revision comments in the form> */
/* mm/dd/yyyy - pid - comment */
/* =============================================================== */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/uio.h>
#include <sys/conf.h> /* for macro DEV_MODULE */
/* --------------------------------------------------------------- */
/* Device access function declarations */
/* --------------------------------------------------------------- */
int example_open(dev_t dev, int oflags, int devtype, struct proc *p);
int example_close(dev_t dev, int fflag, int devtype, struct proc *p);
int example_read(dev_t dev, struct uio *uio, int ioflag);
int example_write(dev_t dev, struct uio *uio, int ioflag);
/* --------------------------------------------------------------- */
/* Define global variables. */
/* --------------------------------------------------------------- */
/* Stores string recv'd by _write() */
static char buf[512+1];
static int len;
/*
* Used as the variable that is the reference to our device
* in devfs... we must keep this variable sane until we
* call kldunload.
*/
static dev_t sdev;
/* --------------------------------------------------------------- */
/* File operations supported by our device driver */
/* --------------------------------------------------------------- */
static struct cdevsw example_cdevsw =
{
example_open,
example_close,
example_read,
example_write,
noioctl,
nopoll,
nommap,
nostrategy,
"example",
34, /* /usr/src/sys/conf/majors */
nodump,
nopsize,
D_TTY,
-1
};
/* --------------------------------------------------------------- */
/* chardev_example_load() */
/* */
/* This is used as the function that handles what is to occur */
/* when the KLD binary is loaded and unloaded via the kldload */
/* and kldunload programs. */
/* --------------------------------------------------------------- */
static int
chardev_example_load(struct module *m, int what, void *arg)
{
int err = 0;
/* Test load failure case 1 - before case */
/* err = EINVAL; */
if(!err)
{
switch (what)
{
case MOD_LOAD: /* kldload */
/* Test load failure case 2 - inside case */
err = EINVAL;
if(!err)
{
sdev = make_dev(&example_cdevsw, /* explained below */
0,
UID_ROOT,
GID_WHEEL,
0600,
"example");
printf("Example device loaded.\n");
}
break;
case MOD_UNLOAD:
destroy_dev(sdev); /* explained below */
printf("Example device unloaded.\n");
break;
default:
err = EINVAL;
break;
}
}
return(err);
}
/* --------------------------------------------------------------- */
/* example_open() */
/* */
/* This open function solely checks for open(2) flags. We are only */
/* allowing for the flags to be O_RDWR for the purpose of showing */
/* how one could only allow a read-only device, for example. */
/* --------------------------------------------------------------- */
int example_open(dev_t dev, int oflags, int devtype, struct proc *p)
{
int err = 0;
memset(&buf, '\0', 513);
len = 0;
uprintf("Opened device \"example\" successfully.\n");
return(err);
}
/* --------------------------------------------------------------- */
/* example_close() */
/* */
/* Simply "closes" our device that was opened with example_open. */
/* --------------------------------------------------------------- */
int example_close(dev_t dev, int fflag, int devtype, struct proc *p)
{
memset(&buf, '\0', 513);
len = 0;
uprintf("Closing device \"example.\"\n");
return(0);
}
/* --------------------------------------------------------------- */
/* example_write() */
/* */
/* The read function just takes the buf that was saved */
/* via example_write() and returns it to userland for */
/* accessing. */
/* --------------------------------------------------------------- */
int example_read(dev_t dev, struct uio *uio, int ioflag)
{
int err = 0;
if (len <= 0)
{
err = -1;
}
else
{/* copy buf to userland */
err = copystr(&buf, uio->uio_iov->iov_base, 513, &len);
}
return(err);
}
/* --------------------------------------------------------------- */
/* example_write() */
/* */
/* example_write takes in a character string and saves it to buf */
/* for later accessing. */
/* --------------------------------------------------------------- */
int example_write(dev_t dev, struct uio *uio, int ioflag)
{
int err = 0;
err = copyinstr(uio->uio_iov->iov_base, &buf, 512, &len);
if (err != 0)
{
uprintf("Write to \"example\" failed.\n");
}
return(err);
}
DEV_MODULE(chardev_example, chardev_example_load, NULL);
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200103231857.f2NIvY209246>
