Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Make struct disklabel 8 byte aligned. This increases it...



details:   https://anonhg.NetBSD.org/src/rev/97eb78964585
branches:  trunk
changeset: 761009:97eb78964585
user:      matt <matt%NetBSD.org@localhost>
date:      Tue Jan 18 19:52:23 2011 +0000

description:
Make struct disklabel 8 byte aligned.  This increases its size by 4 bytes
on IPL32 platforms so add code in sys_ioctl (and netbsd32_ioctl) to deal
with the older/smaller diskabel size.  This change makes disklabel the
same for both IPL32 and LP64 platforms.

diffstat:

 sys/compat/netbsd32/netbsd32_ioctl.c |  119 ++++++++++++++++++++++++----------
 sys/kern/sys_generic.c               |   51 ++++++++++++--
 sys/sys/disklabel.h                  |    3 +-
 sys/sys/dkio.h                       |    3 +-
 4 files changed, 127 insertions(+), 49 deletions(-)

diffs (truncated from 327 to 300 lines):

diff -r c5955f837b22 -r 97eb78964585 sys/compat/netbsd32/netbsd32_ioctl.c
--- a/sys/compat/netbsd32/netbsd32_ioctl.c      Tue Jan 18 19:41:02 2011 +0000
+++ b/sys/compat/netbsd32/netbsd32_ioctl.c      Tue Jan 18 19:52:23 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: netbsd32_ioctl.c,v 1.51 2010/09/24 13:12:53 njoly Exp $        */
+/*     $NetBSD: netbsd32_ioctl.c,v 1.52 2011/01/18 19:52:24 matt Exp $ */
 
 /*
  * Copyright (c) 1998, 2001 Matthew R. Green
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_ioctl.c,v 1.51 2010/09/24 13:12:53 njoly Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_ioctl.c,v 1.52 2011/01/18 19:52:24 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -437,10 +437,11 @@
        struct filedesc *fdp;
        u_long com;
        int error = 0;
-       u_int size, size32;
+       size_t size;
+       size_t alloc_size32, size32;
        void *data, *memp = NULL;
        void *data32, *memp32 = NULL;
-       unsigned fd;
+       unsigned int fd;
        fdfile_t *ff;
        int tmp;
 #define STK_PARAMS     128
@@ -453,17 +454,26 @@
         */
 #if 0
        {
-char *dirs[8] = { "NONE!", "VOID", "OUT", "VOID|OUT!", "IN", "VOID|IN!",
-               "INOUT", "VOID|IN|OUT!" };
+               const char * const dirs[8] = {
+                   "NONE!", "VOID", "OUT", "VOID|OUT!", "IN", "VOID|IN!",
+                   "INOUT", "VOID|IN|OUT!"
+               };
 
-printf("netbsd32_ioctl(%d, %x, %x): %s group %c base %d len %d\n",
-       SCARG(uap, fd), SCARG(uap, com), SCARG(uap, data),
-       dirs[((SCARG(uap, com) & IOC_DIRMASK)>>29)],
-       IOCGROUP(SCARG(uap, com)), IOCBASECMD(SCARG(uap, com)),
-       IOCPARM_LEN(SCARG(uap, com)));
+               printf("netbsd32_ioctl(%d, %x, %x): "
+                   "%s group %c base %d len %d\n",
+                   SCARG(uap, fd), SCARG(uap, com), SCARG(uap, data).i32,
+                   dirs[((SCARG(uap, com) & IOC_DIRMASK)>>29)],
+                   IOCGROUP(SCARG(uap, com)), IOCBASECMD(SCARG(uap, com)),
+                   IOCPARM_LEN(SCARG(uap, com)));
        }
 #endif
 
+       memp = NULL;
+       memp32 = NULL;
+       alloc_size32 = 0;
+       size32 = 0;
+       size = 0;
+
        fdp = p->p_fd;
        fd = SCARG(uap, fd);
        if ((fp = fd_getfile(fd)) == NULL)
@@ -489,37 +499,72 @@
         * Interpret high order word to find amount of data to be
         * copied to/from the user's address space.
         */
-       size = 0;
        size32 = IOCPARM_LEN(com);
-       if (size32 > IOCPARM_MAX) {
+       alloc_size32 = size32;
+
+       /*
+        * The disklabel is now padded to a multiple of 8 bytes however the old
+        * disklabel on 32bit platforms wasn't.  This leaves a difference in
+        * size of 4 bytes between the two but are otherwise identical.
+        * To deal with this, we allocate enough space for the new disklabel
+        * but only copyin/out the smaller amount.
+        */
+       if (IOCGROUP(com) == 'd') {
+               u_long ncom = com ^ (DIOCGDINFO ^ DIOCGDINFO32);
+               switch (ncom) {
+               case DIOCGDINFO:
+               case DIOCWDINFO:
+               case DIOCSDINFO:
+               case DIOCGDEFLABEL:
+                       com = ncom;
+                       if (IOCPARM_LEN(DIOCGDINFO32) < IOCPARM_LEN(DIOCGDINFO))
+                               alloc_size32 = IOCPARM_LEN(DIOCGDINFO);
+                       break;
+               }
+       }
+       if (alloc_size32 > IOCPARM_MAX) {
                error = ENOTTY;
                goto out;
        }
-       if (size32 > sizeof(stkbuf)) {
-               memp32 = kmem_alloc((size_t)size32, KM_SLEEP);
+       if (alloc_size32 > sizeof(stkbuf)) {
+               memp32 = kmem_alloc(alloc_size32, KM_SLEEP);
                data32 = memp32;
        } else
                data32 = (void *)stkbuf32;
-       if (com&IOC_IN) {
-               if (size32) {
-                       error = copyin(SCARG_P32(uap, data), data32, size32);
-                       if (error) {
-                               if (memp32)
-                                       kmem_free(memp32, (size_t)size32);
-                               goto out;
-                       }
-                       ktrgenio(fd, UIO_WRITE, SCARG_P32(uap, data),
-                           size32, 0);
-               } else
+       if ((com >> IOCPARM_SHIFT) == 0)  {
+               /* UNIX-style ioctl. */
+               data32 = SCARG_P32(uap, data);
+       } else {
+               if (com&IOC_IN) {
+                       if (size32) {
+                               error = copyin(SCARG_P32(uap, data), data32,
+                                   size32);
+                               if (error) {
+                                       goto out;
+                               }
+                               /*
+                                * The data between size and alloc_size has
+                                * not been overwritten.  It shouldn't matter
+                                * but let's clear that anyway.
+                                */
+                               if (__predict_false(size32 < alloc_size32)) {
+                                       memset((char *)data32+size32, 0,
+                                           alloc_size32 - size32);
+                               }
+                               ktrgenio(fd, UIO_WRITE, SCARG_P32(uap, data),
+                                   size32, 0);
+                       } else
+                               *(void **)data32 = SCARG_P32(uap, data);
+               } else if ((com&IOC_OUT) && size32) {
+                       /*
+                        * Zero the buffer so the user always
+                        * gets back something deterministic.
+                        */
+                       memset(data32, 0, alloc_size32);
+               } else if (com&IOC_VOID) {
                        *(void **)data32 = SCARG_P32(uap, data);
-       } else if ((com&IOC_OUT) && size32)
-               /*
-                * Zero the buffer so the user always
-                * gets back something deterministic.
-                */
-               memset(data32, 0, size32);
-       else if (com&IOC_VOID)
-               *(void **)data32 = SCARG_P32(uap, data);
+               }
+       }
 
        /*
         * convert various structures, pointers, and other objects that
@@ -690,12 +735,12 @@
                    size32, error);
        }
 
+ out:
        /* If we allocated data, free it here. */
        if (memp32)
-               kmem_free(memp32, (size_t)size32);
+               kmem_free(memp32, alloc_size32);
        if (memp)
-               kmem_free(memp, (size_t)size);
- out:
+               kmem_free(memp32, size);
        fd_putfile(fd);
        return (error);
 }
diff -r c5955f837b22 -r 97eb78964585 sys/kern/sys_generic.c
--- a/sys/kern/sys_generic.c    Tue Jan 18 19:41:02 2011 +0000
+++ b/sys/kern/sys_generic.c    Tue Jan 18 19:52:23 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sys_generic.c,v 1.124 2009/08/13 08:57:43 haad Exp $   */
+/*     $NetBSD: sys_generic.c,v 1.125 2011/01/18 19:52:23 matt Exp $   */
 
 /*-
  * Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_generic.c,v 1.124 2009/08/13 08:57:43 haad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_generic.c,v 1.125 2011/01/18 19:52:23 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -90,6 +90,7 @@
 #include <sys/syscallargs.h>
 #include <sys/ktrace.h>
 #include <sys/atomic.h>
+#include <sys/disklabel.h>
 
 #include <uvm/uvm_extern.h>
 
@@ -524,12 +525,14 @@
        struct filedesc *fdp;
        u_long          com;
        int             error;
-       u_int           size;
+       size_t          size, alloc_size;
        void            *data, *memp;
 #define        STK_PARAMS      128
        u_long          stkbuf[STK_PARAMS/sizeof(u_long)];
        fdfile_t        *ff;
 
+       memp = NULL;
+       alloc_size = 0;
        error = 0;
        p = l->l_proc;
        fdp = p->p_fd;
@@ -560,6 +563,28 @@
         * copied to/from the user's address space.
         */
        size = IOCPARM_LEN(com);
+       alloc_size = size;
+
+       /*
+        * The disklabel is now padded to a multiple of 8 bytes however the old
+        * disklabel on 32bit platforms wasn't.  This leaves a difference in
+        * size of 4 bytes between the two but are otherwise identical.
+        * To deal with this, we allocate enough space for the new disklabel
+        * but only copyin/out the smaller amount.
+        */
+       if (IOCGROUP(com) == 'd') {
+               u_long ncom = com ^ (DIOCGDINFO ^ DIOCGDINFO32);
+               switch (ncom) {
+               case DIOCGDINFO:
+               case DIOCWDINFO:
+               case DIOCSDINFO:
+               case DIOCGDEFLABEL:
+                       com = ncom;
+                       if (IOCPARM_LEN(DIOCGDINFO32) < IOCPARM_LEN(DIOCGDINFO))
+                               alloc_size = IOCPARM_LEN(DIOCGDINFO);
+                       break;
+               }
+       }
        if (size > IOCPARM_MAX) {
                error = ENOTTY;
                goto out;
@@ -569,8 +594,8 @@
                /* UNIX-style ioctl. */
                data = SCARG(uap, data);
        } else {
-               if (size > sizeof(stkbuf)) {
-                       memp = kmem_alloc(size, KM_SLEEP);
+               if (alloc_size > sizeof(stkbuf)) {
+                       memp = kmem_alloc(alloc_size, KM_SLEEP);
                        data = memp;
                } else {
                        data = (void *)stkbuf;
@@ -579,11 +604,17 @@
                        if (size) {
                                error = copyin(SCARG(uap, data), data, size);
                                if (error) {
-                                       if (memp) {
-                                               kmem_free(memp, size);
-                                       }
                                        goto out;
                                }
+                               /*
+                                * The data between size and alloc_size has
+                                * not been overwritten.  It shouldn't matter
+                                * but let's clear that anyway.
+                                */
+                               if (__predict_false(size < alloc_size)) {
+                                       memset((char *)data+size, 0,
+                                           alloc_size - size);
+                               }
                                ktrgenio(SCARG(uap, fd), UIO_WRITE,
                                    SCARG(uap, data), size, 0);
                        } else {
@@ -633,9 +664,9 @@
                }
                break;
        }
+ out:
        if (memp)
-               kmem_free(memp, size);
- out:
+               kmem_free(memp, alloc_size);
        fd_putfile(SCARG(uap, fd));
        switch (error) {
        case -1:
diff -r c5955f837b22 -r 97eb78964585 sys/sys/disklabel.h
--- a/sys/sys/disklabel.h       Tue Jan 18 19:41:02 2011 +0000
+++ b/sys/sys/disklabel.h       Tue Jan 18 19:52:23 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: disklabel.h,v 1.107 2009/12/22 18:55:25 pooka Exp $    */
+/*     $NetBSD: disklabel.h,v 1.108 2011/01/18 19:52:24 matt Exp $     */
 



Home | Main Index | Thread Index | Old Index