[rtems-libbsd commit] Critical bug fix for callouts

Sebastian Huber sebh at rtems.org
Thu Jul 26 12:17:16 UTC 2018


Module:    rtems-libbsd
Branch:    master
Commit:    6d9d7b195621ffda676eda0154ebb8ee24dc3186
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=6d9d7b195621ffda676eda0154ebb8ee24dc3186

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Thu Jul 26 14:12:46 2018 +0200

Critical bug fix for callouts

FreeBSD has two callout executors, one in software and one in hardware
interrupt context.  In libbsd, all callouts are executed by the timer
server.  Entirely remove the different execution contexts for libbsd.
Previously, this was not properly done which could result an invalid
callout_drain() sequence leading to system memory corruption.

---

 freebsd/sys/kern/kern_timeout.c | 32 +++++++++++++++++++++++++++++++-
 freebsd/sys/sys/callout.h       |  2 ++
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/freebsd/sys/kern/kern_timeout.c b/freebsd/sys/kern/kern_timeout.c
index 813580f..2b08d5c 100644
--- a/freebsd/sys/kern/kern_timeout.c
+++ b/freebsd/sys/kern/kern_timeout.c
@@ -164,7 +164,11 @@ struct cc_exec {
  */
 struct callout_cpu {
 	struct mtx_padalign	cc_lock;
+#ifndef __rtems__
 	struct cc_exec 		cc_exec_entity[2];
+#else /* __rtems__ */
+	struct cc_exec 		cc_exec_entity;
+#endif /* __rtems__ */
 	struct callout		*cc_next;
 	struct callout		*cc_callout;
 	struct callout_list	*cc_callwheel;
@@ -182,11 +186,21 @@ struct callout_cpu {
 
 #define	callout_migrating(c)	((c)->c_iflags & CALLOUT_DFRMIGRATION)
 
+#ifndef __rtems__
 #define	cc_exec_curr(cc, dir)		cc->cc_exec_entity[dir].cc_curr
 #define	cc_exec_drain(cc, dir)		cc->cc_exec_entity[dir].cc_drain
+#else /* __rtems__ */
+#define	cc_exec_curr(cc, dir)		cc->cc_exec_entity.cc_curr
+#define	cc_exec_drain(cc, dir)		cc->cc_exec_entity.cc_drain
+#endif /* __rtems__ */
 #define	cc_exec_next(cc)		cc->cc_next
+#ifndef __rtems__
 #define	cc_exec_cancel(cc, dir)		cc->cc_exec_entity[dir].cc_cancel
 #define	cc_exec_waiting(cc, dir)	cc->cc_exec_entity[dir].cc_waiting
+#else /* __rtems__ */
+#define	cc_exec_cancel(cc, dir)		cc->cc_exec_entity.cc_cancel
+#define	cc_exec_waiting(cc, dir)	cc->cc_exec_entity.cc_waiting
+#endif /* __rtems__ */
 #ifdef SMP
 #define	cc_migration_func(cc, dir)	cc->cc_exec_entity[dir].ce_migration_func
 #define	cc_migration_arg(cc, dir)	cc->cc_exec_entity[dir].ce_migration_arg
@@ -497,7 +511,11 @@ callout_get_bucket(sbintime_t sbt)
 void
 callout_process(sbintime_t now)
 {
+#ifndef __rtems__
 	struct callout *tmp, *tmpn;
+#else /* __rtems__ */
+	struct callout *tmp;
+#endif /* __rtems__ */
 	struct callout_cpu *cc;
 	struct callout_list *sc;
 	sbintime_t first, last, max, tmp_max;
@@ -665,8 +683,10 @@ callout_cc_add(struct callout *c, struct callout_cpu *cc,
 	c->c_iflags |= CALLOUT_PENDING;
 	c->c_iflags &= ~CALLOUT_PROCESSED;
 	c->c_flags |= CALLOUT_ACTIVE;
+#ifndef __rtems__
 	if (flags & C_DIRECT_EXEC)
 		c->c_iflags |= CALLOUT_DIRECT;
+#endif /* __rtems__ */
 	c->c_func = func;
 	c->c_time = sbt;
 	c->c_precision = precision;
@@ -1097,7 +1117,11 @@ callout_reset_sbt_on(struct callout *c, sbintime_t sbt, sbintime_t prec,
 {
 	sbintime_t to_sbt, precision;
 	struct callout_cpu *cc;
+#ifndef __rtems__
 	int cancelled, direct;
+#else /* __rtems__ */
+	int cancelled;
+#endif /* __rtems__ */
 	int ignore_cpu=0;
 
 	cancelled = 0;
@@ -1110,6 +1134,7 @@ callout_reset_sbt_on(struct callout *c, sbintime_t sbt, sbintime_t prec,
 	}
 	callout_when(sbt, prec, flags, &to_sbt, &precision);
 
+#ifndef __rtems__
 	/* 
 	 * This flag used to be added by callout_cc_add, but the
 	 * first time you call this we could end up with the
@@ -1122,6 +1147,7 @@ callout_reset_sbt_on(struct callout *c, sbintime_t sbt, sbintime_t prec,
 	}
 	KASSERT(!direct || c->c_lock == NULL,
 	    ("%s: direct callout %p has lock", __func__, c));
+#endif /* __rtems__ */
 	cc = callout_lock(c);
 	/*
 	 * Don't allow migration of pre-allocated callouts lest they
@@ -1260,7 +1286,11 @@ _callout_stop_safe(struct callout *c, int flags, void (*drain)(void *))
 {
 	struct callout_cpu *cc, *old_cc;
 	struct lock_class *class;
+#ifndef __rtems__
 	int direct, sq_locked, use_lock;
+#else /* __rtems__ */
+	int sq_locked, use_lock;
+#endif /* __rtems__ */
 	int cancelled, not_on_a_list;
 #ifdef __rtems__
 	(void)old_cc;
@@ -1285,13 +1315,13 @@ _callout_stop_safe(struct callout *c, int flags, void (*drain)(void *))
 		}
 	} else
 		use_lock = 0;
+#ifndef __rtems__
 	if (c->c_iflags & CALLOUT_DIRECT) {
 		direct = 1;
 	} else {
 		direct = 0;
 	}
 
-#ifndef __rtems__
 	sq_locked = 0;
 	old_cc = NULL;
 again:
diff --git a/freebsd/sys/sys/callout.h b/freebsd/sys/sys/callout.h
index b219052..eee6884 100644
--- a/freebsd/sys/sys/callout.h
+++ b/freebsd/sys/sys/callout.h
@@ -48,7 +48,9 @@
 #define	CALLOUT_SHAREDLOCK	0x0020 /* callout lock held in shared mode */
 #define	CALLOUT_DFRMIGRATION	0x0040 /* callout in deferred migration mode */
 #define	CALLOUT_PROCESSED	0x0080 /* callout in wheel or processing list? */
+#ifndef __rtems__
 #define	CALLOUT_DIRECT 		0x0100 /* allow exec from hw int context */
+#endif /* __rtems__ */
 
 #define	C_DIRECT_EXEC		0x0001 /* direct execution of callout */
 #define	C_PRELBITS		7



More information about the vc mailing list