Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit af91a811 authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge branch 'for-mingo' of...

Merge branch 'for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu

 into core/rcu

Pull RCU updates from Paul E. McKenney:

 - Documentation updates, yet again just simple changes.

 - Miscellaneous fixes, including a change to call_rcu()'s
   rcu_head alignment check.

 - Security-motivated list consistency checks, which are
   disabled by default behind DEBUG_LIST.

 - Torture-test updates.

Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 23400ac9 6190aaaf
Loading
Loading
Loading
Loading
+24 −1
Original line number Diff line number Diff line
@@ -547,7 +547,7 @@ The <tt>rcu_access_pointer()</tt> on line&nbsp;6 is similar to
	It could reuse a value formerly fetched from this same pointer.
	It could also fetch the pointer from <tt>gp</tt> in a byte-at-a-time
	manner, resulting in <i>load tearing</i>, in turn resulting a bytewise
	mash-up of two distince pointer values.
	mash-up of two distinct pointer values.
	It might even use value-speculation optimizations, where it makes
	a wrong guess, but by the time it gets around to checking the
	value, an update has changed the pointer to match the wrong guess.
@@ -659,6 +659,29 @@ systems with more than one CPU:
	In other words, a given instance of <tt>synchronize_rcu()</tt>
	can avoid waiting on a given RCU read-side critical section only
	if it can prove that <tt>synchronize_rcu()</tt> started first.

	<p>
	A related question is &ldquo;When <tt>rcu_read_lock()</tt>
	doesn't generate any code, why does it matter how it relates
	to a grace period?&rdquo;
	The answer is that it is not the relationship of
	<tt>rcu_read_lock()</tt> itself that is important, but rather
	the relationship of the code within the enclosed RCU read-side
	critical section to the code preceding and following the
	grace period.
	If we take this viewpoint, then a given RCU read-side critical
	section begins before a given grace period when some access
	preceding the grace period observes the effect of some access
	within the critical section, in which case none of the accesses
	within the critical section may observe the effects of any
	access following the grace period.

	<p>
	As of late 2016, mathematical models of RCU take this
	viewpoint, for example, see slides&nbsp;62 and&nbsp;63
	of the
	<a href="http://www2.rdrop.com/users/paulmck/scalability/paper/LinuxMM.2016.10.04c.LCE.pdf">2016 LinuxCon EU</a>
	presentation.
</font></td></tr>
<tr><td>&nbsp;</td></tr>
</table>
+1 −1
Original line number Diff line number Diff line
@@ -237,7 +237,7 @@ rcu_dereference()

	The reader uses rcu_dereference() to fetch an RCU-protected
	pointer, which returns a value that may then be safely
	dereferenced.  Note that rcu_deference() does not actually
	dereferenced.  Note that rcu_dereference() does not actually
	dereference the pointer, instead, it protects the pointer for
	later dereferencing.  It also executes any needed memory-barrier
	instructions for a given CPU architecture.  Currently, only Alpha
+2 −0
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ void lkdtm_SPINLOCKUP(void);
void lkdtm_HUNG_TASK(void);
void lkdtm_ATOMIC_UNDERFLOW(void);
void lkdtm_ATOMIC_OVERFLOW(void);
void lkdtm_CORRUPT_LIST_ADD(void);
void lkdtm_CORRUPT_LIST_DEL(void);

/* lkdtm_heap.c */
void lkdtm_OVERWRITE_ALLOCATION(void);
+68 −0
Original line number Diff line number Diff line
@@ -5,8 +5,13 @@
 * test source files.
 */
#include "lkdtm.h"
#include <linux/list.h>
#include <linux/sched.h>

struct lkdtm_list {
	struct list_head node;
};

/*
 * Make sure our attempts to over run the kernel stack doesn't trigger
 * a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we
@@ -146,3 +151,66 @@ void lkdtm_ATOMIC_OVERFLOW(void)
	pr_info("attempting bad atomic overflow\n");
	atomic_inc(&over);
}

void lkdtm_CORRUPT_LIST_ADD(void)
{
	/*
	 * Initially, an empty list via LIST_HEAD:
	 *	test_head.next = &test_head
	 *	test_head.prev = &test_head
	 */
	LIST_HEAD(test_head);
	struct lkdtm_list good, bad;
	void *target[2] = { };
	void *redirection = &target;

	pr_info("attempting good list addition\n");

	/*
	 * Adding to the list performs these actions:
	 *	test_head.next->prev = &good.node
	 *	good.node.next = test_head.next
	 *	good.node.prev = test_head
	 *	test_head.next = good.node
	 */
	list_add(&good.node, &test_head);

	pr_info("attempting corrupted list addition\n");
	/*
	 * In simulating this "write what where" primitive, the "what" is
	 * the address of &bad.node, and the "where" is the address held
	 * by "redirection".
	 */
	test_head.next = redirection;
	list_add(&bad.node, &test_head);

	if (target[0] == NULL && target[1] == NULL)
		pr_err("Overwrite did not happen, but no BUG?!\n");
	else
		pr_err("list_add() corruption not detected!\n");
}

void lkdtm_CORRUPT_LIST_DEL(void)
{
	LIST_HEAD(test_head);
	struct lkdtm_list item;
	void *target[2] = { };
	void *redirection = &target;

	list_add(&item.node, &test_head);

	pr_info("attempting good list removal\n");
	list_del(&item.node);

	pr_info("attempting corrupted list removal\n");
	list_add(&item.node, &test_head);

	/* As with the list_add() test above, this corrupts "next". */
	item.node.next = redirection;
	list_del(&item.node);

	if (target[0] == NULL && target[1] == NULL)
		pr_err("Overwrite did not happen, but no BUG?!\n");
	else
		pr_err("list_del() corruption not detected!\n");
}
+2 −0
Original line number Diff line number Diff line
@@ -197,6 +197,8 @@ struct crashtype crashtypes[] = {
	CRASHTYPE(EXCEPTION),
	CRASHTYPE(LOOP),
	CRASHTYPE(OVERFLOW),
	CRASHTYPE(CORRUPT_LIST_ADD),
	CRASHTYPE(CORRUPT_LIST_DEL),
	CRASHTYPE(CORRUPT_STACK),
	CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
	CRASHTYPE(OVERWRITE_ALLOCATION),
Loading