Source-Changes-HG archive

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

[src/trunk]: src/sys/kern - don't return ENOMEM for errors not related to memory



details:   https://anonhg.NetBSD.org/src/rev/02250055cfc8
branches:  trunk
changeset: 829396:02250055cfc8
user:      christos <christos%NetBSD.org@localhost>
date:      Sun Jan 28 22:24:58 2018 +0000

description:
- don't return ENOMEM for errors not related to memory
- don't overload return values (-error/+size)
- don't allocate kernel memory from user supplied length.

diffstat:

 sys/kern/subr_interrupt.c |  89 +++++++++++++++++++---------------------------
 1 files changed, 37 insertions(+), 52 deletions(-)

diffs (207 lines):

diff -r 19c4fd94c8f6 -r 02250055cfc8 sys/kern/subr_interrupt.c
--- a/sys/kern/subr_interrupt.c Sun Jan 28 18:31:41 2018 +0000
+++ b/sys/kern/subr_interrupt.c Sun Jan 28 22:24:58 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: subr_interrupt.c,v 1.3 2018/01/13 13:53:36 reinoud Exp $       */
+/*     $NetBSD: subr_interrupt.c,v 1.4 2018/01/28 22:24:58 christos Exp $      */
 
 /*
  * Copyright (c) 2015 Internet Initiative Japan Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_interrupt.c,v 1.3 2018/01/13 13:53:36 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_interrupt.c,v 1.4 2018/01/28 22:24:58 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -133,7 +133,7 @@
 
        ii_handler = interrupt_construct_intrids(cpuset);
        if (ii_handler == NULL) {
-               error = ENOMEM;
+               error = EINVAL;
                goto out;
        }
        nids = ii_handler->iih_nids;
@@ -180,25 +180,24 @@
  * Return the size of interrupts list data on success.
  * Reterun 0 on failed.
  */
-static size_t
-interrupt_intrio_list_size(void)
+static int
+interrupt_intrio_list_size(size_t *ilsize)
 {
        struct intrids_handler *ii_handler;
-       size_t ilsize;
 
-       ilsize = 0;
+       *ilsize = 0;
 
        /* buffer header */
-       ilsize += sizeof(struct intrio_list);
+       *ilsize += sizeof(struct intrio_list);
 
        /* il_line body */
        ii_handler = interrupt_construct_intrids(kcpuset_running);
        if (ii_handler == NULL)
-               return 0;
-       ilsize += interrupt_intrio_list_line_size() * (ii_handler->iih_nids);
+               return EOPNOTSUPP;
+       *ilsize += interrupt_intrio_list_line_size() * ii_handler->iih_nids;
 
        interrupt_destruct_intrids(ii_handler);
-       return ilsize;
+       return 0;
 }
 
 /*
@@ -207,28 +206,17 @@
  * If "data" == NULL, simply return list structure bytes.
  */
 static int
-interrupt_intrio_list(struct intrio_list *il, int length)
+interrupt_intrio_list(struct intrio_list *il, size_t ilsize)
 {
        struct intrio_list_line *illine;
        kcpuset_t *assigned, *avail;
        struct intrids_handler *ii_handler;
        intrid_t *ids;
-       size_t ilsize;
        u_int cpu_idx;
-       int nids, intr_idx, ret, line_size;
-
-       ilsize = interrupt_intrio_list_size();
-       if (ilsize == 0)
-               return -ENOMEM;
-
-       if (il == NULL)
-               return ilsize;
-
-       if (length < ilsize)
-               return -ENOMEM;
+       int nids, intr_idx, error, line_size;
 
        illine = (struct intrio_list_line *)
-               ((char *)il + sizeof(struct intrio_list));
+           ((char *)il + sizeof(struct intrio_list));
        il->il_lineoffset = (off_t)((uintptr_t)illine - (uintptr_t)il);
 
        kcpuset_create(&avail, true);
@@ -238,19 +226,19 @@
        ii_handler = interrupt_construct_intrids(kcpuset_running);
        if (ii_handler == NULL) {
                DPRINTF(("%s: interrupt_construct_intrids() failed\n",
-                       __func__));
-               ret = -ENOMEM;
+                   __func__));
+               error = EOPNOTSUPP;
                goto out;
        }
 
        line_size = interrupt_intrio_list_line_size();
-       /* ensure interrupts are not added after interrupt_intrio_list_size(). */
+       /* ensure interrupts are not added after interrupt_intrio_list_size() */
        nids = ii_handler->iih_nids;
        ids = ii_handler->iih_intrids;
        if (ilsize < sizeof(struct intrio_list) + line_size * nids) {
                DPRINTF(("%s: interrupts are added during execution.\n",
-                       __func__));
-               ret = -ENOMEM;
+                   __func__));
+               error = EAGAIN;
                goto destruct_out;
        }
 
@@ -264,19 +252,19 @@
                interrupt_get_assigned(ids[intr_idx], assigned);
                for (cpu_idx = 0; cpu_idx < ncpu; cpu_idx++) {
                        struct intrio_list_line_cpu *illcpu =
-                               &illine->ill_cpu[cpu_idx];
+                           &illine->ill_cpu[cpu_idx];
 
                        illcpu->illc_assigned =
-                               kcpuset_isset(assigned, cpu_idx) ? true : false;
+                           kcpuset_isset(assigned, cpu_idx);
                        illcpu->illc_count =
-                               interrupt_get_count(ids[intr_idx], cpu_idx);
+                           interrupt_get_count(ids[intr_idx], cpu_idx);
                }
 
                illine = (struct intrio_list_line *)
-                       ((char *)illine + line_size);
+                   ((char *)illine + line_size);
        }
 
-       ret = ilsize;
+       error = 0;
        il->il_version = INTRIO_LIST_VERSION;
        il->il_ncpus = ncpu;
        il->il_nintrs = nids;
@@ -289,7 +277,7 @@
        kcpuset_destroy(assigned);
        kcpuset_destroy(avail);
 
-       return ret;
+       return error;
 }
 
 /*
@@ -298,42 +286,39 @@
 static int
 interrupt_intrio_list_sysctl(SYSCTLFN_ARGS)
 {
-       int ret, error;
+       int error;
        void *buf;
+       size_t ilsize;
 
        if (oldlenp == NULL)
                return EINVAL;
 
+       if ((error = interrupt_intrio_list_size(&ilsize)) != 0)
+               return error;
+
        /*
         * If oldp == NULL, the sysctl(8) caller process want to get the size of
         * intrctl list data only.
         */
        if (oldp == NULL) {
-               ret = interrupt_intrio_list(NULL, 0);
-               if (ret < 0)
-                       return -ret;
-
-               *oldlenp = ret;
+               *oldlenp = ilsize;
                return 0;
        }
 
        /*
-        * If oldp != NULL, the sysctl(8) caller process want to get both the size
-        * and the contents of intrctl list data.
+        * If oldp != NULL, the sysctl(8) caller process want to get both the
+        * size and the contents of intrctl list data.
         */
-       if (*oldlenp == 0)
+       if (*oldlenp < ilsize)
                return ENOMEM;
 
-       buf = kmem_zalloc(*oldlenp, KM_SLEEP);
-       ret = interrupt_intrio_list(buf, *oldlenp);
-       if (ret < 0) {
-               error = -ret;
+       buf = kmem_zalloc(ilsize, KM_SLEEP);
+       if ((error = interrupt_intrio_list(buf, ilsize)) != 0)
                goto out;
-       }
-       error = copyout(buf, oldp, *oldlenp);
 
+       error = copyout(buf, oldp, ilsize);
  out:
-       kmem_free(buf, *oldlenp);
+       kmem_free(buf, ilsize);
        return error;
 }
 



Home | Main Index | Thread Index | Old Index