From owner-svn-doc-all@FreeBSD.ORG Sun Mar 17 02:06:37 2013 Return-Path: Delivered-To: svn-doc-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id A87A8779; Sun, 17 Mar 2013 02:06:37 +0000 (UTC) (envelope-from eadler@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 8082BC2E; Sun, 17 Mar 2013 02:06:37 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.6/8.14.6) with ESMTP id r2H26bIk097874; Sun, 17 Mar 2013 02:06:37 GMT (envelope-from eadler@svn.freebsd.org) Received: (from eadler@localhost) by svn.freebsd.org (8.14.6/8.14.5/Submit) id r2H26buj097873; Sun, 17 Mar 2013 02:06:37 GMT (envelope-from eadler@svn.freebsd.org) Message-Id: <201303170206.r2H26buj097873@svn.freebsd.org> From: Eitan Adler Date: Sun, 17 Mar 2013 02:06:37 +0000 (UTC) To: doc-committers@freebsd.org, svn-doc-all@freebsd.org, svn-doc-head@freebsd.org Subject: svn commit: r41250 - head/en_US.ISO8859-1/books/arch-handbook/driverbasics X-SVN-Group: doc-head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-doc-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire doc trees \(except for " user" , " projects" , and " translations" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 17 Mar 2013 02:06:37 -0000 Author: eadler Date: Sun Mar 17 02:06:36 2013 New Revision: 41250 URL: http://svnweb.freebsd.org/changeset/doc/41250 Log: Some additional changes from jhb: - It now initializes the buffer to a known-good state (length of 0) so that you can't do a buffer overrun by reading it without writing to it. - It doesn't include the trailing null character in 'len' and always leaves room for it during writes by restricting writes to writing only 255 chars, but letting reads read 256 chars. This means after init you can do a read of one byte to get an empty string, and if you write "foo" (3 bytes) you can read back "foo\0" (I think this is the original intent). Letting 'len' not hold the null simplifies a fair bit of logic in write. - Use 'td' for thread pointers, not 'p' (which is from when this was a 'struct proc *'). - Some style fixes. - Don't ever set uio_offset directly, uiomove() already changes it, and in fact we should read it after the write to handle partial writes. Submitted by: jhb Approved by: bcr (mentor, implicit) Modified: head/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.xml Modified: head/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.xml ============================================================================== --- head/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.xml Sat Mar 16 22:58:14 2013 (r41249) +++ head/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.xml Sun Mar 17 02:06:36 2013 (r41250) @@ -188,7 +188,7 @@ KMOD=skeleton #include <sys/uio.h> /* uio struct */ #include <sys/malloc.h> -#define BUFFERSIZE 256 +#define BUFFERSIZE 255 /* Function prototypes */ static d_open_t echo_open; @@ -207,7 +207,7 @@ static struct cdevsw echo_cdevsw = { }; struct s_echo { - char msg[BUFFERSIZE]; + char msg[BUFFERSIZE + 1]; int len; }; @@ -222,7 +222,6 @@ MALLOC_DEFINE(M_ECHOBUF, "echobuffer", " * This function is called by the kld[un]load(2) system calls to * determine what actions to take when a module is loaded or unloaded. */ - static int echo_loader(struct module *m __unused, int what, void *arg __unused) { @@ -241,8 +240,8 @@ echo_loader(struct module *m __unused, i if (error != 0) break; - /* kmalloc memory for use by this driver */ - echomsg = malloc(sizeof(*echomsg), M_ECHOBUF, M_WAITOK); + echomsg = malloc(sizeof(*echomsg), M_ECHOBUF, M_WAITOK | + M_ZERO); printf("Echo device loaded.\n"); break; case MOD_UNLOAD: @@ -258,7 +257,8 @@ echo_loader(struct module *m __unused, i } static int -echo_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused, struct thread *p __unused) +echo_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused, + struct thread *td __unused) { int error = 0; @@ -267,7 +267,8 @@ echo_open(struct cdev *dev __unused, int } static int -echo_close(struct cdev *dev __unused, int fflag __unused, int devtype __unused, struct thread *p __unused) +echo_close(struct cdev *dev __unused, int fflag __unused, int devtype __unused, + struct thread *td __unused) { uprintf("Closing device \"echo\".\n"); @@ -279,19 +280,20 @@ echo_close(struct cdev *dev __unused, in * echo_write() and returns it to userland for accessing. * uio(9) */ - static int echo_read(struct cdev *dev __unused, struct uio *uio, int ioflag __unused) { - int error, amt; + size_t amt; + int error; /* * How big is this read operation? Either as big as the user wants, - * or as big as the remaining data + * or as big as the remaining data. Note that the 'len' does not + * include the trailing null character. */ + amt = MIN(uio->uio_resid, uio->uio_offset >= echomsg->len + 1 ? 0 : + echomsg->len + 1 - uio->uio_offset); - amt = MIN(uio->uio_resid, echomsg->len - uio->uio_offset); - uio->uio_offset += amt; if ((error = uiomove(echomsg->msg, amt, uio)) != 0) uprintf("uiomove failed!\n"); @@ -302,13 +304,11 @@ echo_read(struct cdev *dev __unused, str * echo_write takes in a character string and saves it * to buf for later accessing. */ - static int echo_write(struct cdev *dev __unused, struct uio *uio, int ioflag __unused) { - int error, amt; - - /* Copy the string in from user memory to kernel memory */ + size_t amt; + int error; /* * We either write from the beginning or are appending -- do @@ -317,32 +317,25 @@ echo_write(struct cdev *dev __unused, st if (uio->uio_offset != 0 && (uio->uio_offset != echomsg->len)) return (EINVAL); - /* - * This is new message, reset length - */ + /* This is a new message, reset length */ if (uio->uio_offset == 0) echomsg->len = 0; - /* NULL character should be overridden */ - if (echomsg->len != 0) - echomsg->len--; - /* Copy the string in from user memory to kernel memory */ amt = MIN(uio->uio_resid, (BUFFERSIZE - echomsg->len)); error = uiomove(echomsg->msg + uio->uio_offset, amt, uio); - /* Now we need to null terminate, then record the length */ - echomsg->len += amt + 1; - uio->uio_offset += amt + 1; - echomsg->msg[echomsg->len - 1] = 0; + /* Now we need to null terminate and record the length */ + echomsg->len = uio->uio_offset; + echomsg->msg[echomsg->len] = 0; if (error != 0) uprintf("Write failed: bad address!\n"); return (error); } -DEV_MODULE(echo,echo_loader,NULL); +DEV_MODULE(echo, echo_loader, NULL); With this driver loaded try: