lkml.org 
[lkml]   [2021]   [Nov]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    Subject[PATCH v2 10/23] kcsan: test: Match reordered or normal accesses
    From
    Due to reordering accesses with weak memory modeling, any access can now
    appear as "(reordered)".

    Match any permutation of accesses if CONFIG_KCSAN_WEAK_MEMORY=y, so that
    we effectively match an access if it is denoted "(reordered)" or not.

    Signed-off-by: Marco Elver <elver@google.com>
    ---
    kernel/kcsan/kcsan_test.c | 92 +++++++++++++++++++++++++++------------
    1 file changed, 63 insertions(+), 29 deletions(-)

    diff --git a/kernel/kcsan/kcsan_test.c b/kernel/kcsan/kcsan_test.c
    index 6e3c2b8bc608..ec054879201b 100644
    --- a/kernel/kcsan/kcsan_test.c
    +++ b/kernel/kcsan/kcsan_test.c
    @@ -151,7 +151,7 @@ struct expect_report {

    /* Check observed report matches information in @r. */
    __no_kcsan
    -static bool report_matches(const struct expect_report *r)
    +static bool __report_matches(const struct expect_report *r)
    {
    const bool is_assert = (r->access[0].type | r->access[1].type) & KCSAN_ACCESS_ASSERT;
    bool ret = false;
    @@ -253,6 +253,40 @@ static bool report_matches(const struct expect_report *r)
    return ret;
    }

    +static __always_inline const struct expect_report *
    +__report_set_scoped(struct expect_report *r, int accesses)
    +{
    + BUILD_BUG_ON(accesses > 3);
    +
    + if (accesses & 1)
    + r->access[0].type |= KCSAN_ACCESS_SCOPED;
    + else
    + r->access[0].type &= ~KCSAN_ACCESS_SCOPED;
    +
    + if (accesses & 2)
    + r->access[1].type |= KCSAN_ACCESS_SCOPED;
    + else
    + r->access[1].type &= ~KCSAN_ACCESS_SCOPED;
    +
    + return r;
    +}
    +
    +__no_kcsan
    +static bool report_matches_any_reordered(struct expect_report *r)
    +{
    + return __report_matches(__report_set_scoped(r, 0)) ||
    + __report_matches(__report_set_scoped(r, 1)) ||
    + __report_matches(__report_set_scoped(r, 2)) ||
    + __report_matches(__report_set_scoped(r, 3));
    +}
    +
    +#ifdef CONFIG_KCSAN_WEAK_MEMORY
    +/* Due to reordering accesses, any access may appear as "(reordered)". */
    +#define report_matches report_matches_any_reordered
    +#else
    +#define report_matches __report_matches
    +#endif
    +
    /* ===== Test kernels ===== */

    static long test_sink;
    @@ -438,13 +472,13 @@ static noinline void test_kernel_xor_1bit(void)
    __no_kcsan
    static void test_basic(struct kunit *test)
    {
    - const struct expect_report expect = {
    + struct expect_report expect = {
    .access = {
    { test_kernel_write, &test_var, sizeof(test_var), KCSAN_ACCESS_WRITE },
    { test_kernel_read, &test_var, sizeof(test_var), 0 },
    },
    };
    - static const struct expect_report never = {
    + struct expect_report never = {
    .access = {
    { test_kernel_read, &test_var, sizeof(test_var), 0 },
    { test_kernel_read, &test_var, sizeof(test_var), 0 },
    @@ -469,14 +503,14 @@ static void test_basic(struct kunit *test)
    __no_kcsan
    static void test_concurrent_races(struct kunit *test)
    {
    - const struct expect_report expect = {
    + struct expect_report expect = {
    .access = {
    /* NULL will match any address. */
    { test_kernel_rmw_array, NULL, 0, __KCSAN_ACCESS_RW(KCSAN_ACCESS_WRITE) },
    { test_kernel_rmw_array, NULL, 0, __KCSAN_ACCESS_RW(0) },
    },
    };
    - static const struct expect_report never = {
    + struct expect_report never = {
    .access = {
    { test_kernel_rmw_array, NULL, 0, 0 },
    { test_kernel_rmw_array, NULL, 0, 0 },
    @@ -498,13 +532,13 @@ static void test_concurrent_races(struct kunit *test)
    __no_kcsan
    static void test_novalue_change(struct kunit *test)
    {
    - const struct expect_report expect_rw = {
    + struct expect_report expect_rw = {
    .access = {
    { test_kernel_write_nochange, &test_var, sizeof(test_var), KCSAN_ACCESS_WRITE },
    { test_kernel_read, &test_var, sizeof(test_var), 0 },
    },
    };
    - const struct expect_report expect_ww = {
    + struct expect_report expect_ww = {
    .access = {
    { test_kernel_write_nochange, &test_var, sizeof(test_var), KCSAN_ACCESS_WRITE },
    { test_kernel_write_nochange, &test_var, sizeof(test_var), KCSAN_ACCESS_WRITE },
    @@ -530,13 +564,13 @@ static void test_novalue_change(struct kunit *test)
    __no_kcsan
    static void test_novalue_change_exception(struct kunit *test)
    {
    - const struct expect_report expect_rw = {
    + struct expect_report expect_rw = {
    .access = {
    { test_kernel_write_nochange_rcu, &test_var, sizeof(test_var), KCSAN_ACCESS_WRITE },
    { test_kernel_read, &test_var, sizeof(test_var), 0 },
    },
    };
    - const struct expect_report expect_ww = {
    + struct expect_report expect_ww = {
    .access = {
    { test_kernel_write_nochange_rcu, &test_var, sizeof(test_var), KCSAN_ACCESS_WRITE },
    { test_kernel_write_nochange_rcu, &test_var, sizeof(test_var), KCSAN_ACCESS_WRITE },
    @@ -556,7 +590,7 @@ static void test_novalue_change_exception(struct kunit *test)
    __no_kcsan
    static void test_unknown_origin(struct kunit *test)
    {
    - const struct expect_report expect = {
    + struct expect_report expect = {
    .access = {
    { test_kernel_read, &test_var, sizeof(test_var), 0 },
    { NULL },
    @@ -578,7 +612,7 @@ static void test_unknown_origin(struct kunit *test)
    __no_kcsan
    static void test_write_write_assume_atomic(struct kunit *test)
    {
    - const struct expect_report expect = {
    + struct expect_report expect = {
    .access = {
    { test_kernel_write, &test_var, sizeof(test_var), KCSAN_ACCESS_WRITE },
    { test_kernel_write, &test_var, sizeof(test_var), KCSAN_ACCESS_WRITE },
    @@ -604,7 +638,7 @@ static void test_write_write_assume_atomic(struct kunit *test)
    __no_kcsan
    static void test_write_write_struct(struct kunit *test)
    {
    - const struct expect_report expect = {
    + struct expect_report expect = {
    .access = {
    { test_kernel_write_struct, &test_struct, sizeof(test_struct), KCSAN_ACCESS_WRITE },
    { test_kernel_write_struct, &test_struct, sizeof(test_struct), KCSAN_ACCESS_WRITE },
    @@ -626,7 +660,7 @@ static void test_write_write_struct(struct kunit *test)
    __no_kcsan
    static void test_write_write_struct_part(struct kunit *test)
    {
    - const struct expect_report expect = {
    + struct expect_report expect = {
    .access = {
    { test_kernel_write_struct, &test_struct, sizeof(test_struct), KCSAN_ACCESS_WRITE },
    { test_kernel_write_struct_part, &test_struct.val[3], sizeof(test_struct.val[3]), KCSAN_ACCESS_WRITE },
    @@ -658,7 +692,7 @@ static void test_read_atomic_write_atomic(struct kunit *test)
    __no_kcsan
    static void test_read_plain_atomic_write(struct kunit *test)
    {
    - const struct expect_report expect = {
    + struct expect_report expect = {
    .access = {
    { test_kernel_read, &test_var, sizeof(test_var), 0 },
    { test_kernel_write_atomic, &test_var, sizeof(test_var), KCSAN_ACCESS_WRITE | KCSAN_ACCESS_ATOMIC },
    @@ -679,7 +713,7 @@ static void test_read_plain_atomic_write(struct kunit *test)
    __no_kcsan
    static void test_read_plain_atomic_rmw(struct kunit *test)
    {
    - const struct expect_report expect = {
    + struct expect_report expect = {
    .access = {
    { test_kernel_read, &test_var, sizeof(test_var), 0 },
    { test_kernel_atomic_rmw, &test_var, sizeof(test_var),
    @@ -701,13 +735,13 @@ static void test_read_plain_atomic_rmw(struct kunit *test)
    __no_kcsan
    static void test_zero_size_access(struct kunit *test)
    {
    - const struct expect_report expect = {
    + struct expect_report expect = {
    .access = {
    { test_kernel_write_struct, &test_struct, sizeof(test_struct), KCSAN_ACCESS_WRITE },
    { test_kernel_write_struct, &test_struct, sizeof(test_struct), KCSAN_ACCESS_WRITE },
    },
    };
    - const struct expect_report never = {
    + struct expect_report never = {
    .access = {
    { test_kernel_write_struct, &test_struct, sizeof(test_struct), KCSAN_ACCESS_WRITE },
    { test_kernel_read_struct_zero_size, &test_struct.val[3], 0, 0 },
    @@ -741,7 +775,7 @@ static void test_data_race(struct kunit *test)
    __no_kcsan
    static void test_assert_exclusive_writer(struct kunit *test)
    {
    - const struct expect_report expect = {
    + struct expect_report expect = {
    .access = {
    { test_kernel_assert_writer, &test_var, sizeof(test_var), KCSAN_ACCESS_ASSERT },
    { test_kernel_write_nochange, &test_var, sizeof(test_var), KCSAN_ACCESS_WRITE },
    @@ -759,7 +793,7 @@ static void test_assert_exclusive_writer(struct kunit *test)
    __no_kcsan
    static void test_assert_exclusive_access(struct kunit *test)
    {
    - const struct expect_report expect = {
    + struct expect_report expect = {
    .access = {
    { test_kernel_assert_access, &test_var, sizeof(test_var), KCSAN_ACCESS_ASSERT | KCSAN_ACCESS_WRITE },
    { test_kernel_read, &test_var, sizeof(test_var), 0 },
    @@ -777,19 +811,19 @@ static void test_assert_exclusive_access(struct kunit *test)
    __no_kcsan
    static void test_assert_exclusive_access_writer(struct kunit *test)
    {
    - const struct expect_report expect_access_writer = {
    + struct expect_report expect_access_writer = {
    .access = {
    { test_kernel_assert_access, &test_var, sizeof(test_var), KCSAN_ACCESS_ASSERT | KCSAN_ACCESS_WRITE },
    { test_kernel_assert_writer, &test_var, sizeof(test_var), KCSAN_ACCESS_ASSERT },
    },
    };
    - const struct expect_report expect_access_access = {
    + struct expect_report expect_access_access = {
    .access = {
    { test_kernel_assert_access, &test_var, sizeof(test_var), KCSAN_ACCESS_ASSERT | KCSAN_ACCESS_WRITE },
    { test_kernel_assert_access, &test_var, sizeof(test_var), KCSAN_ACCESS_ASSERT | KCSAN_ACCESS_WRITE },
    },
    };
    - const struct expect_report never = {
    + struct expect_report never = {
    .access = {
    { test_kernel_assert_writer, &test_var, sizeof(test_var), KCSAN_ACCESS_ASSERT },
    { test_kernel_assert_writer, &test_var, sizeof(test_var), KCSAN_ACCESS_ASSERT },
    @@ -813,7 +847,7 @@ static void test_assert_exclusive_access_writer(struct kunit *test)
    __no_kcsan
    static void test_assert_exclusive_bits_change(struct kunit *test)
    {
    - const struct expect_report expect = {
    + struct expect_report expect = {
    .access = {
    { test_kernel_assert_bits_change, &test_var, sizeof(test_var), KCSAN_ACCESS_ASSERT },
    { test_kernel_change_bits, &test_var, sizeof(test_var),
    @@ -844,13 +878,13 @@ static void test_assert_exclusive_bits_nochange(struct kunit *test)
    __no_kcsan
    static void test_assert_exclusive_writer_scoped(struct kunit *test)
    {
    - const struct expect_report expect_start = {
    + struct expect_report expect_start = {
    .access = {
    { test_kernel_assert_writer_scoped, &test_var, sizeof(test_var), KCSAN_ACCESS_ASSERT | KCSAN_ACCESS_SCOPED },
    { test_kernel_write_nochange, &test_var, sizeof(test_var), KCSAN_ACCESS_WRITE },
    },
    };
    - const struct expect_report expect_inscope = {
    + struct expect_report expect_inscope = {
    .access = {
    { test_enter_scope, &test_var, sizeof(test_var), KCSAN_ACCESS_ASSERT | KCSAN_ACCESS_SCOPED },
    { test_kernel_write_nochange, &test_var, sizeof(test_var), KCSAN_ACCESS_WRITE },
    @@ -871,16 +905,16 @@ static void test_assert_exclusive_writer_scoped(struct kunit *test)
    __no_kcsan
    static void test_assert_exclusive_access_scoped(struct kunit *test)
    {
    - const struct expect_report expect_start1 = {
    + struct expect_report expect_start1 = {
    .access = {
    { test_kernel_assert_access_scoped, &test_var, sizeof(test_var), KCSAN_ACCESS_ASSERT | KCSAN_ACCESS_WRITE | KCSAN_ACCESS_SCOPED },
    { test_kernel_read, &test_var, sizeof(test_var), 0 },
    },
    };
    - const struct expect_report expect_start2 = {
    + struct expect_report expect_start2 = {
    .access = { expect_start1.access[0], expect_start1.access[0] },
    };
    - const struct expect_report expect_inscope = {
    + struct expect_report expect_inscope = {
    .access = {
    { test_enter_scope, &test_var, sizeof(test_var), KCSAN_ACCESS_ASSERT | KCSAN_ACCESS_WRITE | KCSAN_ACCESS_SCOPED },
    { test_kernel_read, &test_var, sizeof(test_var), 0 },
    @@ -985,7 +1019,7 @@ static void test_atomic_builtins(struct kunit *test)
    __no_kcsan
    static void test_1bit_value_change(struct kunit *test)
    {
    - const struct expect_report expect = {
    + struct expect_report expect = {
    .access = {
    { test_kernel_read, &test_var, sizeof(test_var), 0 },
    { test_kernel_xor_1bit, &test_var, sizeof(test_var), __KCSAN_ACCESS_RW(KCSAN_ACCESS_WRITE) },
    --
    2.34.0.rc2.393.gf8c9666880-goog
    \
     
     \ /
      Last update: 2021-11-18 09:12    [W:3.429 / U:0.708 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site