Module: xenomai-forge
Branch: next
Commit: 896e5dada38eb0f11183a5349278ee550701f3b9
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=896e5dada38eb0f11183a5349278ee550701f3b9

Author: Philippe Gerum <r...@xenomai.org>
Date:   Tue Jan  7 13:15:49 2014 +0100

cobalt/shadow: sanitize ppd retrieval

---

 include/cobalt/kernel/assert.h         |    2 +-
 include/cobalt/kernel/ppd.h            |   15 ++-
 include/cobalt/kernel/rtdm/Makefile.am |    1 +
 include/cobalt/kernel/rtdm/Makefile.in |    1 +
 include/cobalt/kernel/rtdm/audis.h     |  225 ++++++++++++++++++++++++++++++++
 kernel/cobalt/debug.c                  |    3 -
 kernel/cobalt/posix/internal.h         |    9 +-
 kernel/cobalt/shadow.c                 |   17 +--
 8 files changed, 251 insertions(+), 22 deletions(-)

diff --git a/include/cobalt/kernel/assert.h b/include/cobalt/kernel/assert.h
index 63886a1..775ae1f 100644
--- a/include/cobalt/kernel/assert.h
+++ b/include/cobalt/kernel/assert.h
@@ -83,7 +83,7 @@
 #define primary_mode_only()    XENO_BUGON(CONTEXT, ipipe_root_p)
 #define secondary_mode_only()  XENO_BUGON(CONTEXT, !ipipe_root_p)
 #define interrupt_only()       XENO_BUGON(CONTEXT, !xnsched_interrupt_p())
-#define atomic_only()          XENO_BUGON(CONTEXT, (xnlock_is_owner(&nklock) 
&& spltest()) == 0)
+#define atomic_only()          XENO_BUGON(CONTEXT, (xnlock_is_owner(&nklock) 
&& hard_irqs_disabled()) == 0)
 #define realtime_cpu_only()    XENO_BUGON(CONTEXT, 
!xnsched_supported_cpu(ipipe_processor_id()))
 
 void __xnsys_assert_failed(const char *file, int line, const char *msg);
diff --git a/include/cobalt/kernel/ppd.h b/include/cobalt/kernel/ppd.h
index 05e32b3..937f998 100644
--- a/include/cobalt/kernel/ppd.h
+++ b/include/cobalt/kernel/ppd.h
@@ -23,6 +23,7 @@
 
 #include <cobalt/kernel/list.h>
 #include <cobalt/kernel/shadow.h>
+#include <cobalt/kernel/lock.h>
 #include <cobalt/kernel/heap.h>
 
 struct mm_struct;
@@ -53,7 +54,7 @@ struct xnsys_ppd {
 
 extern struct xnsys_ppd __xnsys_global_ppd;
 
-static inline struct xnsys_ppd *xnsys_ppd_get(int global)
+static inline struct xnsys_ppd *__xnsys_ppd_get(int global)
 {
        struct xnshadow_ppd *ppd;
 
@@ -63,4 +64,16 @@ static inline struct xnsys_ppd *xnsys_ppd_get(int global)
        return container_of(ppd, struct xnsys_ppd, ppd);
 }
 
+static inline struct xnsys_ppd *xnsys_ppd_get(int global)
+{
+       struct xnsys_ppd *ppd;
+       spl_t s;
+
+       xnlock_get_irqsave(&nklock, s);
+       ppd = __xnsys_ppd_get(global);
+       xnlock_put_irqrestore(&nklock, s);
+
+       return ppd;
+}
+
 #endif /* _COBALT_KERNEL_PPD_H */
diff --git a/include/cobalt/kernel/rtdm/Makefile.am 
b/include/cobalt/kernel/rtdm/Makefile.am
index b15eac8..148a3ef 100644
--- a/include/cobalt/kernel/rtdm/Makefile.am
+++ b/include/cobalt/kernel/rtdm/Makefile.am
@@ -1,5 +1,6 @@
 
 noinst_HEADERS =       \
+       audis.h         \
        can.h           \
        cobalt.h        \
        driver.h        \
diff --git a/include/cobalt/kernel/rtdm/Makefile.in 
b/include/cobalt/kernel/rtdm/Makefile.in
index df8397f..de1bb04 100644
--- a/include/cobalt/kernel/rtdm/Makefile.in
+++ b/include/cobalt/kernel/rtdm/Makefile.in
@@ -304,6 +304,7 @@ top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 noinst_HEADERS = \
+       audis.h         \
        can.h           \
        cobalt.h        \
        driver.h        \
diff --git a/include/cobalt/kernel/rtdm/audis.h 
b/include/cobalt/kernel/rtdm/audis.h
new file mode 100644
index 0000000..08aa58b
--- /dev/null
+++ b/include/cobalt/kernel/rtdm/audis.h
@@ -0,0 +1,225 @@
+/**
+ * @author Philippe Gerum
+ * @note Copyright (C) 2013 Siemens
+ * @brief Kernel interface for AuDis-based drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef _COBALT_RTDM_AUDIS_H
+#define _COBALT_RTDM_AUDIS_H
+
+#include <linux/list.h>
+#include <rtdm/driver.h>
+#include <cobalt/kernel/clock.h>
+#include <cobalt/uapi/rtdm/audis.h>
+
+struct audis_process;
+
+/**
+ * @anchor audis_context
+ * @brief AuDis context descriptor.
+ *
+ * The core AuDis context descriptor holds the AuDis-specific data for
+ * each open file. For this reason, it should be part of each
+ * driver-specific context descriptor.  e.g.
+ *
+ * @code
+ * struct fpga_user {
+ *      struct user_state some_state;
+ *      struct audis_context audis_context;
+ * };
+ *
+ * struct rtdm_device fpga_device {
+ *      ...
+ *      .context_size = sizeof(struct fpga_user);
+ *      .open_nrt = foo_open,
+ *      .ops = {
+ *              .close_nrt = foo_close,
+ *              .ioctl_nrt = foo_ioctl_nrt,
+ *              ...
+ *      },
+ * };
+ * @endcode
+ *
+ * The AuDis kernel API requires this information to be initialized by
+ * a call to audis_init_context() when opening a new channel, then
+ * passed to context-sensitive services, including for releasing the
+ * context upon close request, e.g.
+ *
+ * @code
+ * static int foo_open(struct rtdm_dev_context *context,
+ *                     rtdm_user_info_t *user_info,
+ *                     int flags)
+ * {
+ *      struct audis_context *ac;
+ *
+ *      ac = &rtdm_context_to_private(context)->audis_context;
+ *
+ *      return audis_init_context(ac);
+ * }
+ *
+ * static int foo_close(struct rtdm_dev_context *context,
+ *                      rtdm_user_info_t *user_info)
+ * {
+ *      struct audis_context *ac;
+ *
+ *      ac = &rtdm_context_to_private(context)->audis_context;
+ *
+ *      return audis_destroy_context(ac);
+ * }
+ *
+ * static int foo_ioctl_nrt(struct rtdm_dev_context *context,
+ *                          rtdm_user_info_t *user_info,
+ *                          unsigned int request, void *arg)
+ * {
+ *      struct audis_event_config cfg;
+ *      struct audis_context *ac;
+ *      int ret;
+ *
+ *      ac = &rtdm_context_to_private(context)->audis_context;
+ *
+ *      switch (request) {
+ *      case IOCAUD_REGISTER_EVENT:
+ *              ret = rtdm_copy_from_user(user_info, &cfg, arg, sizeof(cfg));
+ *              if (ret)
+ *                      return ret;
+ *              ret = audis_register_event(ac, &foo_evlist, &cfg);
+ *       ...
+ * }
+ * @endcode
+ */
+struct audis_context {
+       struct list_head evhandlers; /* audis_event_handler */
+       struct audis_process *process;
+       struct list_head clocks;   /* struct audis_sync_clock */
+       int stale;
+       struct list_head next;
+};
+
+struct audis_event_list {
+       struct list_head events; /* audis_event */
+       rtdm_lock_t lock;
+};
+
+#define AUDIS_DEFINE_EVENT_LIST(__list)                                \
+       struct audis_event_list __list = {                      \
+               .events = LIST_HEAD_INIT(__list.events),        \
+               .lock = RTDM_LOCK_UNLOCKED,                     \
+       }
+
+struct audis_event {
+       /** Event identifier. */
+       eventid_t evid;
+       /** Enabling callback. */
+       int (*ev_disable)(struct audis_event *ev);
+       /** Disabling callback. */
+       int (*ev_enable)(struct audis_event *ev);
+       /** Next event in audis_event_list. */
+       struct list_head next;
+       /** Consumer list (audis_event_handler) */
+       struct list_head consumers;
+       /** Owner context. */
+       struct audis_process *owner;
+};
+
+struct audis_sync_clock {
+       /**
+        * Activation date of this clock, in core clock ticks
+        * (i.e. xnclock_read_raw(&nkclock)).
+        */
+       xnticks_t epoch;
+       /** Base Xenomai clock we derive from. */
+       struct xnclock base_clock;
+       /** Started timers this clock currently runs. */
+       struct list_head timers;
+       /** Owner context. */
+       struct audis_process *owner;
+       /** Enable call when arming timers. */
+       void (*enable)(struct audis_sync_clock *synclock,
+                      xnticks_t period);
+       /** Disable call when disarming timers. */
+       void (*disable)(struct audis_sync_clock *synclock);
+       /** Destructor. */
+       void (*dtor)(struct audis_sync_clock *synclock);
+       /** Next in per-process queue. */
+       struct list_head next; 
+       /** Number of timers this clock manages. */
+       int nrtimers;
+};
+
+struct audis_sync_clock_device {
+       struct audis_sync_clock clock;
+};
+
+struct audis_sync_clock_timer {
+       struct audis_sync_clock clock;
+       struct xntimer base_timer;
+};
+
+#define audis_enter_atomic(lockctx)    xnlock_get_irqsave(&nklock, (lockctx))
+#define audis_leave_atomic(lockctx)    xnlock_put_irqrestore(&nklock, 
(lockctx))
+
+int audis_init_context(struct audis_context *ac);
+
+int audis_destroy_context(struct audis_context *ac);
+
+void audis_declare_event(struct audis_event_list *evlist,
+                        struct audis_event *ev);
+
+static inline
+void __audis_declare_event_array(struct audis_event_list *evlist,
+                                struct audis_event *ev, int nr)
+{
+       struct audis_event *evstart = ev;
+
+       while (ev < evstart + nr)
+               audis_declare_event(evlist, ev++);
+}
+
+#define audis_declare_event_array(__evlist, __evarray)         \
+       __audis_declare_event_array(__evlist, __evarray,        \
+                                   ARRAY_SIZE(__evarray))
+
+int audis_register_event(struct audis_context *ac,
+                        struct audis_event_list *evlist,
+                        const struct audis_event_config *cfg);
+
+int audis_unregister_event(struct audis_context *ac,
+                          struct audis_event *ev);
+
+int audis_send_event(struct audis_event_list *evlist,
+                    eventid_t evid);
+
+int audis_register_sync_clock_device(struct audis_context *ac,
+                                    struct audis_sync_clock_device *clockdev,
+                                    struct audis_clock_config *cfg,
+                                    const char *name,
+                                    clockid_t *clk_id);
+
+int audis_register_sync_clock_timer(struct audis_context *ac,
+                                   struct audis_sync_clock_timer *clocktm,
+                                   struct audis_clock_config *cfg,
+                                   const char *name,
+                                   clockid_t *clk_id);
+
+int audis_deregister_sync_clock_device(struct audis_context *ac,
+                                      struct audis_sync_clock_device 
*clockdev);
+
+int audis_deregister_sync_clock(struct audis_context *ac,
+                               clockid_t clock_id);
+
+void audis_sync_clock_tick(struct audis_sync_clock *synclock);
+
+#endif /* !_COBALT_RTDM_AUDIS_H */
diff --git a/kernel/cobalt/debug.c b/kernel/cobalt/debug.c
index 226c5ee..10fbb53 100644
--- a/kernel/cobalt/debug.c
+++ b/kernel/cobalt/debug.c
@@ -618,11 +618,8 @@ void xndebug_shadow_init(struct xnthread *thread)
 {
        struct xnsys_ppd *sys_ppd;
        size_t len;
-       spl_t s;
 
-       xnlock_get_irqsave(&nklock, s);
        sys_ppd = xnsys_ppd_get(0);
-       xnlock_put_irqrestore(&nklock, s);
        /*
         * The caller is current, so we know for sure that sys_ppd
         * will still be valid after we dropped the lock.
diff --git a/kernel/cobalt/posix/internal.h b/kernel/cobalt/posix/internal.h
index bf73ea3..9102e27 100644
--- a/kernel/cobalt/posix/internal.h
+++ b/kernel/cobalt/posix/internal.h
@@ -67,9 +67,16 @@ static inline struct cobalt_process 
*cobalt_process_context(void)
 static inline struct cobalt_kqueues *cobalt_kqueues(int pshared)
 {
        struct xnshadow_ppd *ppd;
+       spl_t s;
+
+       xnlock_get_irqsave(&nklock, s);
 
-       if (pshared || (ppd = xnshadow_ppd_get(cobalt_muxid)) == NULL)
+       if (pshared || (ppd = xnshadow_ppd_get(cobalt_muxid)) == NULL) {
+               xnlock_put_irqrestore(&nklock, s);
                return &cobalt_global_kqueues;
+       }
+
+       xnlock_put_irqrestore(&nklock, s);
 
        return &container_of(ppd, struct cobalt_process, ppd)->kqueues;
 }
diff --git a/kernel/cobalt/shadow.c b/kernel/cobalt/shadow.c
index 4fc51ca..8f53474 100644
--- a/kernel/cobalt/shadow.c
+++ b/kernel/cobalt/shadow.c
@@ -919,7 +919,6 @@ int xnshadow_map_user(struct xnthread *thread,
        struct xnthread_start_attr attr;
        struct xnsys_ppd *sys_ppd;
        struct xnheap *sem_heap;
-       spl_t s;
        int ret;
 
        if (!xnthread_test_state(thread, XNUSER))
@@ -953,10 +952,7 @@ int xnshadow_map_user(struct xnthread *thread,
        }
 #endif /* CONFIG_MMU */
 
-       xnlock_get_irqsave(&nklock, s);
        sys_ppd = xnsys_ppd_get(0);
-       xnlock_put_irqrestore(&nklock, s);
-
        sem_heap = &sys_ppd->sem_heap;
        u_window = xnheap_alloc(sem_heap, sizeof(*u_window));
        if (u_window == NULL) {
@@ -1323,7 +1319,7 @@ static int handle_mayday_event(struct pt_regs *regs)
 
        /* We enter the mayday handler with hw IRQs off. */
        xnlock_get(&nklock);
-       sys_ppd = xnsys_ppd_get(0);
+       sys_ppd = __xnsys_ppd_get(0);
        xnlock_put(&nklock);
 
        xnarch_handle_mayday(tcb, regs, sys_ppd->mayday_addr);
@@ -1551,9 +1547,6 @@ static int xnshadow_sys_heap_info(struct xnheap_desc 
__user *u_hd,
 {
        struct xnheap_desc hd;
        struct xnheap *heap;
-       spl_t s;
-
-       xnlock_get_irqsave(&nklock, s);
 
        switch(heap_nr) {
        case XNHEAP_PROC_PRIVATE_HEAP:
@@ -1564,7 +1557,6 @@ static int xnshadow_sys_heap_info(struct xnheap_desc 
__user *u_hd,
                heap = &kheap;
                break;
        default:
-               xnlock_put_irqrestore(&nklock, s);
                return -EINVAL;
        }
 
@@ -1572,7 +1564,6 @@ static int xnshadow_sys_heap_info(struct xnheap_desc 
__user *u_hd,
        hd.size = xnheap_extentsize(heap);
        hd.area = xnheap_base_memory(heap);
        hd.used = xnheap_used_mem(heap);
-       xnlock_put_irqrestore(&nklock, s);
 
        return __xn_safe_copy_to_user(u_hd, &hd, sizeof(*u_hd));
 }
@@ -2279,7 +2270,6 @@ static int handle_taskexit_event(struct task_struct *p) 
/* p == current */
        struct xnsys_ppd *sys_ppd;
        struct xnthread *thread;
        struct mm_struct *mm;
-       spl_t s;
 
        /*
         * We are called for both kernel and user shadows over the
@@ -2302,9 +2292,7 @@ static int handle_taskexit_event(struct task_struct *p) 
/* p == current */
        xnsched_run();
 
        if (xnthread_test_state(thread, XNUSER)) {
-               xnlock_get_irqsave(&nklock, s);
                sys_ppd = xnsys_ppd_get(0);
-               xnlock_put_irqrestore(&nklock, s);
                xnheap_free(&sys_ppd->sem_heap, thread->u_window);
                thread->u_window = NULL;
                mm = xnshadow_current_mm();
@@ -2486,15 +2474,12 @@ static int handle_cleanup_event(struct mm_struct *mm)
        struct xnsys_ppd *sys_ppd;
        struct xnthread *thread;
        struct mm_struct *old;
-       spl_t s;
 
        /* We are NOT called for exiting kernel shadows. */
 
        old = xnshadow_swap_mm(mm);
 
-       xnlock_get_irqsave(&nklock, s);
        sys_ppd = xnsys_ppd_get(0);
-       xnlock_put_irqrestore(&nklock, s);
        if (sys_ppd != &__xnsys_global_ppd) {
                /*
                 * Detect a userland shadow running exec(), i.e. still


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to