* [PATCH v2 0/2] libceph: validate OSD sparse-read extent maps (+KUnit) @ 2026-07-14 11:51 Michael Bommarito 2026-07-14 11:51 ` [PATCH v2 1/2] libceph: validate OSD extent maps before cursor advance Michael Bommarito 2026-07-14 11:51 ` [PATCH v2 2/2] libceph: add KUnit coverage for OSD sparse-read extent validation Michael Bommarito 0 siblings, 2 replies; 5+ messages in thread From: Michael Bommarito @ 2026-07-14 11:51 UTC (permalink / raw) To: Ilya Dryomov; +Cc: Viacheslav Dubeyko, ceph-devel, linux-kernel, stable Patch 1 is the fix from v1 (unchanged), now carrying Viacheslav Dubeyko's Reviewed-by. Patch 2 adds the KUnit coverage he asked for. osd_sparse_read() checks that the sparse-read data length matches the summed extent lengths but never checks that each OSD-supplied extent is monotonic and stays inside the original request range, so a malformed authenticated OSD reply can advance the message-data cursor past the request buffer and hit the BUG_ON(!*length) in ceph_msg_data_next(). Patch 1 rejects such maps before advancing the cursor. The KUnit suite in patch 2 drives the real osd_sparse_read() state machine over a synthesized reply (no OSD, no network). Confirmed before/after on v7.2-rc3: without patch 1 the out-of-range case faults in ceph_msg_data_next() while the in-range control passes (1 pass, 1 fail); with patch 1 both pass. v1: https://lore.kernel.org/ceph-devel/20260710022837.libceph-sparse-v1@bommarito/ Michael Bommarito (2): libceph: validate OSD extent maps before cursor advance libceph: add KUnit coverage for OSD sparse-read extent validation net/ceph/Kconfig | 12 +++ net/ceph/osd_client-kunit.c | 146 ++++++++++++++++++++++++++++++++++++ net/ceph/osd_client.c | 34 +++++++++ 3 files changed, 192 insertions(+) create mode 100644 net/ceph/osd_client-kunit.c -- 2.53.0 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 1/2] libceph: validate OSD extent maps before cursor advance 2026-07-14 11:51 [PATCH v2 0/2] libceph: validate OSD sparse-read extent maps (+KUnit) Michael Bommarito @ 2026-07-14 11:51 ` Michael Bommarito 2026-07-14 11:51 ` [PATCH v2 2/2] libceph: add KUnit coverage for OSD sparse-read extent validation Michael Bommarito 1 sibling, 0 replies; 5+ messages in thread From: Michael Bommarito @ 2026-07-14 11:51 UTC (permalink / raw) To: Ilya Dryomov; +Cc: Viacheslav Dubeyko, ceph-devel, linux-kernel, stable net/ceph/osd_client.c:osd_sparse_read() validates that the sparse-read data length matches the summed extent lengths, but it does not validate that each OSD-supplied extent is monotonic and lies inside the original request range. A malformed authenticated OSD reply can advertise a far-forward nonzero extent offset with a matching data length and make the client advance the message-data cursor beyond the request buffer. This reaches the BUG_ON(!*length) assertion in ceph_msg_data_next() from the client receive path. Impact: A malicious or compromised authenticated Ceph OSD peer can crash a kernel Ceph client via a malformed sparse-read reply. Reject sparse extent maps that overflow, move backwards, overlap, or extend outside the original sparse-read request before advancing the cursor. Fixes: f628d7999727 ("libceph: add sparse read support to OSD client") Cc: stable@vger.kernel.org Reviewed-by: Viacheslav Dubeyko <slava@dubeyko.com> Assisted-by: Codex:gpt-5-5-xhigh Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com> --- net/ceph/osd_client.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 2ff00070c1810..76ba3abdad9b1 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -6,6 +6,7 @@ #include <linux/err.h> #include <linux/highmem.h> #include <linux/mm.h> +#include <linux/overflow.h> #include <linux/pagemap.h> #include <linux/slab.h> #include <linux/uaccess.h> @@ -5799,6 +5800,31 @@ static inline void convert_extent_map(struct ceph_sparse_read *sr) } #endif +static bool sparse_extent_map_valid(struct ceph_sparse_read *sr) +{ + u64 req_end, pos; + int i; + + if (check_add_overflow(sr->sr_req_off, sr->sr_req_len, &req_end)) + return false; + + pos = sr->sr_req_off; + for (i = 0; i < sr->sr_count; i++) { + struct ceph_sparse_extent *ext = &sr->sr_extent[i]; + u64 end; + + if (ext->off < pos) + return false; + if (check_add_overflow(ext->off, ext->len, &end)) + return false; + if (end > req_end) + return false; + pos = end; + } + + return true; +} + static int osd_sparse_read(struct ceph_connection *con, struct ceph_msg_data_cursor *cursor, char **pbuf) @@ -5856,6 +5882,10 @@ static int osd_sparse_read(struct ceph_connection *con, case CEPH_SPARSE_READ_DATA_PRE: /* Convert sr_datalen to host-endian */ sr->sr_datalen = le32_to_cpu((__force __le32)sr->sr_datalen); + if (!sparse_extent_map_valid(sr)) { + pr_warn_ratelimited("invalid sparse extent map\n"); + return -EREMOTEIO; + } for (i = 0; i < count; i++) len += sr->sr_extent[i].len; if (sr->sr_datalen != len) { -- 2.53.0 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 2/2] libceph: add KUnit coverage for OSD sparse-read extent validation 2026-07-14 11:51 [PATCH v2 0/2] libceph: validate OSD sparse-read extent maps (+KUnit) Michael Bommarito 2026-07-14 11:51 ` [PATCH v2 1/2] libceph: validate OSD extent maps before cursor advance Michael Bommarito @ 2026-07-14 11:51 ` Michael Bommarito 2026-07-14 17:43 ` Viacheslav Dubeyko 2026-08-11 16:55 ` Alex Markuze 1 sibling, 2 replies; 5+ messages in thread From: Michael Bommarito @ 2026-07-14 11:51 UTC (permalink / raw) To: Ilya Dryomov; +Cc: Viacheslav Dubeyko, ceph-devel, linux-kernel, stable Add KUnit coverage for the sparse-read extent-map validation added by the previous patch. The tests drive the real osd_sparse_read() state machine over a synthesized OSD reply (no OSD or network): an in-range single extent is accepted and advances the cursor, and an extent whose offset lies outside the original request range is rejected with -EREMOTEIO before the message-data cursor is advanced. The suite is included from osd_client.c so it can exercise the static sparse-read parser and cursor-advance helpers without exporting test-only symbols, guarded by CONFIG_CEPH_LIB_KUNIT_TEST. Assisted-by: Codex:gpt-5-5-xhigh Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com> --- net/ceph/Kconfig | 12 +++ net/ceph/osd_client-kunit.c | 146 ++++++++++++++++++++++++++++++++++++ net/ceph/osd_client.c | 4 + 3 files changed, 162 insertions(+) create mode 100644 net/ceph/osd_client-kunit.c diff --git a/net/ceph/Kconfig b/net/ceph/Kconfig index 7e2528cde4b94..6b78fe4a0f8a4 100644 --- a/net/ceph/Kconfig +++ b/net/ceph/Kconfig @@ -45,3 +45,15 @@ config CEPH_LIB_USE_DNS_RESOLVER Documentation/networking/dns_resolver.rst If unsure, say N. + +config CEPH_LIB_KUNIT_TEST + bool "KUnit tests for the Ceph core library" if !KUNIT_ALL_TESTS + depends on CEPH_LIB && KUNIT + default KUNIT_ALL_TESTS + help + This builds KUnit coverage for selected Ceph core-library parser + and state-machine helpers. The tests exercise internal libceph + behavior with synthesized state and are intended for developer + validation rather than production systems. + + If unsure, say N. diff --git a/net/ceph/osd_client-kunit.c b/net/ceph/osd_client-kunit.c new file mode 100644 index 0000000000000..713f24675f68f --- /dev/null +++ b/net/ceph/osd_client-kunit.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * KUnit coverage for net/ceph/osd_client.c internals. + * + * Included from osd_client.c so the test can drive the real static sparse-read + * parser and cursor-advance helper without exporting test-only symbols. + */ + +#include <kunit/test.h> + +struct ceph_osd_sparse_read_test { + struct ceph_osd osd; + struct ceph_connection con; + struct ceph_msg *msg; + struct ceph_msg_data_cursor cursor; + struct ceph_osd_request *req; + struct page **pages; + struct page *page; +}; + +static int ceph_osd_sparse_read_test_init(struct kunit *test) +{ + struct ceph_osd_sparse_read_test *ctx; + + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx); + + ctx->req = kunit_kzalloc(test, struct_size(ctx->req, r_ops, 1), + GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx->req); + + ctx->pages = kunit_kcalloc(test, 1, sizeof(*ctx->pages), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx->pages); + + ctx->page = alloc_page(GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx->page); + ctx->pages[0] = ctx->page; + + ctx->msg = ceph_msg_new2(CEPH_MSG_OSD_OPREPLY, 0, 1, GFP_KERNEL, true); + KUNIT_ASSERT_NOT_NULL(test, ctx->msg); + + osd_init(&ctx->osd); + ctx->osd.o_sparse_op_idx = -1; + ceph_init_sparse_read(&ctx->osd.o_sparse_read); + + request_init(ctx->req); + ctx->req->r_tid = 1; + ctx->req->r_num_ops = 1; + osd_req_op_extent_init(ctx->req, 0, CEPH_OSD_OP_SPARSE_READ, + 0, PAGE_SIZE, 0, 0); + KUNIT_ASSERT_EQ(test, ctx->req->r_ops[0].op, CEPH_OSD_OP_SPARSE_READ); + + insert_request(&ctx->osd.o_requests, ctx->req); + + ctx->msg->hdr.tid = cpu_to_le64(ctx->req->r_tid); + ceph_msg_data_add_pages(ctx->msg, ctx->pages, PAGE_SIZE, 0, false); + ceph_msg_data_cursor_init(&ctx->cursor, ctx->msg, PAGE_SIZE); + + ctx->con.private = &ctx->osd; + ctx->con.in_msg = ctx->msg; + + test->priv = ctx; + return 0; +} + +static void ceph_osd_sparse_read_test_exit(struct kunit *test) +{ + struct ceph_osd_sparse_read_test *ctx = test->priv; + + if (!ctx) + return; + + if (ctx->req && !RB_EMPTY_NODE(&ctx->req->r_node)) + erase_request(&ctx->osd.o_requests, ctx->req); + ceph_init_sparse_read(&ctx->osd.o_sparse_read); + if (ctx->msg) + ceph_msg_put(ctx->msg); + if (ctx->page) + __free_page(ctx->page); +} + +static int ceph_osd_sparse_read_feed_one_extent(struct kunit *test, + u64 off, u64 len, u32 datalen) +{ + struct ceph_osd_sparse_read_test *ctx = test->priv; + struct ceph_sparse_read *sr = &ctx->osd.o_sparse_read; + char *buf = NULL; + int ret; + + ret = osd_sparse_read(&ctx->con, &ctx->cursor, &buf); + KUNIT_ASSERT_EQ(test, ret, (int)sizeof(sr->sr_count)); + KUNIT_ASSERT_PTR_EQ(test, buf, (char *)&sr->sr_count); + + sr->sr_count = (__force u32)cpu_to_le32(1); + ret = osd_sparse_read(&ctx->con, &ctx->cursor, &buf); + KUNIT_ASSERT_EQ(test, ret, (int)sizeof(*sr->sr_extent)); + KUNIT_ASSERT_NOT_NULL(test, sr->sr_extent); + KUNIT_ASSERT_PTR_EQ(test, buf, (char *)sr->sr_extent); + + sr->sr_extent[0].off = (__force u64)cpu_to_le64(off); + sr->sr_extent[0].len = (__force u64)cpu_to_le64(len); + ret = osd_sparse_read(&ctx->con, &ctx->cursor, &buf); + KUNIT_ASSERT_EQ(test, ret, (int)sizeof(sr->sr_datalen)); + KUNIT_ASSERT_PTR_EQ(test, buf, (char *)&sr->sr_datalen); + + sr->sr_datalen = (__force u32)cpu_to_le32(datalen); + return osd_sparse_read(&ctx->con, &ctx->cursor, &buf); +} + +static void ceph_osd_sparse_read_in_range_extent(struct kunit *test) +{ + struct ceph_osd_sparse_read_test *ctx = test->priv; + struct ceph_sparse_read *sr = &ctx->osd.o_sparse_read; + int ret; + + ret = ceph_osd_sparse_read_feed_one_extent(test, 0, 16, 16); + + KUNIT_EXPECT_EQ(test, ret, 16); + KUNIT_EXPECT_EQ(test, sr->sr_pos, 16); + KUNIT_EXPECT_EQ(test, ctx->cursor.sr_resid, 16); + KUNIT_EXPECT_EQ(test, ctx->cursor.resid, PAGE_SIZE); +} + +static void ceph_osd_sparse_read_rejects_out_of_range_extent(struct kunit *test) +{ + int ret; + + ret = ceph_osd_sparse_read_feed_one_extent(test, PAGE_SIZE + 16, 16, 16); + + KUNIT_EXPECT_EQ(test, ret, -EREMOTEIO); +} + +static struct kunit_case ceph_osd_sparse_read_test_cases[] = { + KUNIT_CASE(ceph_osd_sparse_read_in_range_extent), + KUNIT_CASE(ceph_osd_sparse_read_rejects_out_of_range_extent), + {} +}; + +static struct kunit_suite ceph_osd_sparse_read_test_suite = { + .name = "ceph_osd_sparse_read", + .init = ceph_osd_sparse_read_test_init, + .exit = ceph_osd_sparse_read_test_exit, + .test_cases = ceph_osd_sparse_read_test_cases, +}; + +kunit_test_suite(ceph_osd_sparse_read_test_suite); diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 76ba3abdad9b1..b9ab9608ec88e 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -5951,3 +5951,7 @@ static const struct ceph_connection_operations osd_con_ops = { .handle_auth_done = osd_handle_auth_done, .handle_auth_bad_method = osd_handle_auth_bad_method, }; + +#ifdef CONFIG_CEPH_LIB_KUNIT_TEST +#include "osd_client-kunit.c" +#endif -- 2.53.0 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] libceph: add KUnit coverage for OSD sparse-read extent validation 2026-07-14 11:51 ` [PATCH v2 2/2] libceph: add KUnit coverage for OSD sparse-read extent validation Michael Bommarito @ 2026-07-14 17:43 ` Viacheslav Dubeyko 2026-08-11 16:55 ` Alex Markuze 1 sibling, 0 replies; 5+ messages in thread From: Viacheslav Dubeyko @ 2026-07-14 17:43 UTC (permalink / raw) To: Michael Bommarito, Ilya Dryomov; +Cc: ceph-devel, linux-kernel, stable On Tue, 2026-07-14 at 07:51 -0400, Michael Bommarito wrote: > Add KUnit coverage for the sparse-read extent-map validation added by > the > previous patch. The tests drive the real osd_sparse_read() state > machine > over a synthesized OSD reply (no OSD or network): an in-range single > extent is accepted and advances the cursor, and an extent whose > offset > lies outside the original request range is rejected with -EREMOTEIO > before > the message-data cursor is advanced. > > The suite is included from osd_client.c so it can exercise the static > sparse-read parser and cursor-advance helpers without exporting test- > only > symbols, guarded by CONFIG_CEPH_LIB_KUNIT_TEST. > > Assisted-by: Codex:gpt-5-5-xhigh > Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com> > --- > net/ceph/Kconfig | 12 +++ > net/ceph/osd_client-kunit.c | 146 > ++++++++++++++++++++++++++++++++++++ > net/ceph/osd_client.c | 4 + > 3 files changed, 162 insertions(+) > create mode 100644 net/ceph/osd_client-kunit.c > > diff --git a/net/ceph/Kconfig b/net/ceph/Kconfig > index 7e2528cde4b94..6b78fe4a0f8a4 100644 > --- a/net/ceph/Kconfig > +++ b/net/ceph/Kconfig > @@ -45,3 +45,15 @@ config CEPH_LIB_USE_DNS_RESOLVER > Documentation/networking/dns_resolver.rst > > If unsure, say N. > + > +config CEPH_LIB_KUNIT_TEST > + bool "KUnit tests for the Ceph core library" if > !KUNIT_ALL_TESTS > + depends on CEPH_LIB && KUNIT > + default KUNIT_ALL_TESTS > + help > + This builds KUnit coverage for selected Ceph core-library > parser > + and state-machine helpers. The tests exercise internal > libceph > + behavior with synthesized state and are intended for > developer > + validation rather than production systems. > + > + If unsure, say N. > diff --git a/net/ceph/osd_client-kunit.c b/net/ceph/osd_client- > kunit.c > new file mode 100644 > index 0000000000000..713f24675f68f > --- /dev/null > +++ b/net/ceph/osd_client-kunit.c > @@ -0,0 +1,146 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * KUnit coverage for net/ceph/osd_client.c internals. > + * > + * Included from osd_client.c so the test can drive the real static > sparse-read > + * parser and cursor-advance helper without exporting test-only > symbols. > + */ > + > +#include <kunit/test.h> > + > +struct ceph_osd_sparse_read_test { > + struct ceph_osd osd; > + struct ceph_connection con; > + struct ceph_msg *msg; > + struct ceph_msg_data_cursor cursor; > + struct ceph_osd_request *req; > + struct page **pages; > + struct page *page; > +}; > + > +static int ceph_osd_sparse_read_test_init(struct kunit *test) > +{ > + struct ceph_osd_sparse_read_test *ctx; > + > + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); > + KUNIT_ASSERT_NOT_NULL(test, ctx); > + > + ctx->req = kunit_kzalloc(test, struct_size(ctx->req, r_ops, > 1), > + GFP_KERNEL); > + KUNIT_ASSERT_NOT_NULL(test, ctx->req); > + > + ctx->pages = kunit_kcalloc(test, 1, sizeof(*ctx->pages), > GFP_KERNEL); > + KUNIT_ASSERT_NOT_NULL(test, ctx->pages); > + > + ctx->page = alloc_page(GFP_KERNEL); > + KUNIT_ASSERT_NOT_NULL(test, ctx->page); > + ctx->pages[0] = ctx->page; > + > + ctx->msg = ceph_msg_new2(CEPH_MSG_OSD_OPREPLY, 0, 1, > GFP_KERNEL, true); > + KUNIT_ASSERT_NOT_NULL(test, ctx->msg); > + > + osd_init(&ctx->osd); > + ctx->osd.o_sparse_op_idx = -1; > + ceph_init_sparse_read(&ctx->osd.o_sparse_read); > + > + request_init(ctx->req); > + ctx->req->r_tid = 1; > + ctx->req->r_num_ops = 1; > + osd_req_op_extent_init(ctx->req, 0, CEPH_OSD_OP_SPARSE_READ, > + 0, PAGE_SIZE, 0, 0); > + KUNIT_ASSERT_EQ(test, ctx->req->r_ops[0].op, > CEPH_OSD_OP_SPARSE_READ); > + > + insert_request(&ctx->osd.o_requests, ctx->req); > + > + ctx->msg->hdr.tid = cpu_to_le64(ctx->req->r_tid); > + ceph_msg_data_add_pages(ctx->msg, ctx->pages, PAGE_SIZE, 0, > false); > + ceph_msg_data_cursor_init(&ctx->cursor, ctx->msg, > PAGE_SIZE); > + > + ctx->con.private = &ctx->osd; > + ctx->con.in_msg = ctx->msg; > + > + test->priv = ctx; > + return 0; > +} > + > +static void ceph_osd_sparse_read_test_exit(struct kunit *test) > +{ > + struct ceph_osd_sparse_read_test *ctx = test->priv; > + > + if (!ctx) > + return; > + > + if (ctx->req && !RB_EMPTY_NODE(&ctx->req->r_node)) > + erase_request(&ctx->osd.o_requests, ctx->req); > + ceph_init_sparse_read(&ctx->osd.o_sparse_read); > + if (ctx->msg) > + ceph_msg_put(ctx->msg); > + if (ctx->page) > + __free_page(ctx->page); > +} > + > +static int ceph_osd_sparse_read_feed_one_extent(struct kunit *test, > + u64 off, u64 len, > u32 datalen) > +{ > + struct ceph_osd_sparse_read_test *ctx = test->priv; > + struct ceph_sparse_read *sr = &ctx->osd.o_sparse_read; > + char *buf = NULL; > + int ret; > + > + ret = osd_sparse_read(&ctx->con, &ctx->cursor, &buf); > + KUNIT_ASSERT_EQ(test, ret, (int)sizeof(sr->sr_count)); > + KUNIT_ASSERT_PTR_EQ(test, buf, (char *)&sr->sr_count); > + > + sr->sr_count = (__force u32)cpu_to_le32(1); > + ret = osd_sparse_read(&ctx->con, &ctx->cursor, &buf); > + KUNIT_ASSERT_EQ(test, ret, (int)sizeof(*sr->sr_extent)); > + KUNIT_ASSERT_NOT_NULL(test, sr->sr_extent); > + KUNIT_ASSERT_PTR_EQ(test, buf, (char *)sr->sr_extent); > + > + sr->sr_extent[0].off = (__force u64)cpu_to_le64(off); > + sr->sr_extent[0].len = (__force u64)cpu_to_le64(len); > + ret = osd_sparse_read(&ctx->con, &ctx->cursor, &buf); > + KUNIT_ASSERT_EQ(test, ret, (int)sizeof(sr->sr_datalen)); > + KUNIT_ASSERT_PTR_EQ(test, buf, (char *)&sr->sr_datalen); > + > + sr->sr_datalen = (__force u32)cpu_to_le32(datalen); > + return osd_sparse_read(&ctx->con, &ctx->cursor, &buf); > +} > + > +static void ceph_osd_sparse_read_in_range_extent(struct kunit *test) > +{ > + struct ceph_osd_sparse_read_test *ctx = test->priv; > + struct ceph_sparse_read *sr = &ctx->osd.o_sparse_read; > + int ret; > + > + ret = ceph_osd_sparse_read_feed_one_extent(test, 0, 16, 16); > + > + KUNIT_EXPECT_EQ(test, ret, 16); > + KUNIT_EXPECT_EQ(test, sr->sr_pos, 16); > + KUNIT_EXPECT_EQ(test, ctx->cursor.sr_resid, 16); > + KUNIT_EXPECT_EQ(test, ctx->cursor.resid, PAGE_SIZE); > +} > + > +static void ceph_osd_sparse_read_rejects_out_of_range_extent(struct > kunit *test) > +{ > + int ret; > + > + ret = ceph_osd_sparse_read_feed_one_extent(test, PAGE_SIZE + > 16, 16, 16); > + > + KUNIT_EXPECT_EQ(test, ret, -EREMOTEIO); > +} > + > +static struct kunit_case ceph_osd_sparse_read_test_cases[] = { > + KUNIT_CASE(ceph_osd_sparse_read_in_range_extent), > + KUNIT_CASE(ceph_osd_sparse_read_rejects_out_of_range_extent) > , > + {} > +}; > + > +static struct kunit_suite ceph_osd_sparse_read_test_suite = { > + .name = "ceph_osd_sparse_read", > + .init = ceph_osd_sparse_read_test_init, > + .exit = ceph_osd_sparse_read_test_exit, > + .test_cases = ceph_osd_sparse_read_test_cases, > +}; > + > +kunit_test_suite(ceph_osd_sparse_read_test_suite); > diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c > index 76ba3abdad9b1..b9ab9608ec88e 100644 > --- a/net/ceph/osd_client.c > +++ b/net/ceph/osd_client.c > @@ -5951,3 +5951,7 @@ static const struct ceph_connection_operations > osd_con_ops = { > .handle_auth_done = osd_handle_auth_done, > .handle_auth_bad_method = osd_handle_auth_bad_method, > }; > + > +#ifdef CONFIG_CEPH_LIB_KUNIT_TEST > +#include "osd_client-kunit.c" > +#endif Usually, KUnit test requires .kunitconfig file and I don't see it. Because, there are several ways to run Kunit tests: (1) python script, (2) running kernel module. The osd_client-kunit.c should contains: MODULE_LICENSE() MODULE_AUTHOR() MODULE_DESCRIPTION() MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); The tested function needs to be properly exported: EXPORT_SYMBOL_IF_KUNIT(<function_name>); Thanks, Slava. ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] libceph: add KUnit coverage for OSD sparse-read extent validation 2026-07-14 11:51 ` [PATCH v2 2/2] libceph: add KUnit coverage for OSD sparse-read extent validation Michael Bommarito 2026-07-14 17:43 ` Viacheslav Dubeyko @ 2026-08-11 16:55 ` Alex Markuze 1 sibling, 0 replies; 5+ messages in thread From: Alex Markuze @ 2026-08-11 16:55 UTC (permalink / raw) To: michael.bommarito; +Cc: slava, idryomov, ceph-devel Hi Michael, A few issues with the test code: The test suite leaks the page allocated in osd_sparse_read_test_init() when an early assertion fails before cleanup runs. The insert_request() and erase_request() calls in the test body also lack the locking that the production code requires around them. Also, Slava raised a concern about the KUnit integration approach that hasn't been addressed — please make sure that's resolved before v3. Could you respin? -- Alex Markuze ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-08-11 16:55 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-07-14 11:51 [PATCH v2 0/2] libceph: validate OSD sparse-read extent maps (+KUnit) Michael Bommarito 2026-07-14 11:51 ` [PATCH v2 1/2] libceph: validate OSD extent maps before cursor advance Michael Bommarito 2026-07-14 11:51 ` [PATCH v2 2/2] libceph: add KUnit coverage for OSD sparse-read extent validation Michael Bommarito 2026-07-14 17:43 ` Viacheslav Dubeyko 2026-08-11 16:55 ` Alex Markuze
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox