Re: [PATCH] io_uring: annotate remote tasks for kcoverage
Andrey Konovalov <[email protected]>
| Newsgroups | org.kernel.vger.io-uring |
|---|---|
| Message-ID | <CA+fCnZcHbkT=knNbOnAAmrbhx+8+WdcshLty84S_0UbYWVL-=A@mail.gmail.com> |
On Wed, May 20, 2026 at 5:41 PM Robert Femmer <[email protected]> wrote: > > Fuzzers use coverage information to guide generation of test cases > towards new or interesting code paths. Syzkaller, specifically, makes > use kcoverage (CONFIG_KCOV). Coverage information is not collected for > kernel tasks unless annotated by kcov_remote_start and kcov_remote_stop. > This patch annotates io-uring's work queue and sqpoll tasks. > > The value of the handle needs to be passed by userspace when enabling > remote coverage collection. I chose the cgroup ns inum, because it is > predictable and flexible enough for consumers to control which group of > processes should be included for remote coverage collection, should they > create an instance of io-uring. > > Signed-off-by: Robert Femmer <[email protected]> > --- > include/linux/io_uring_types.h | 4 ++++ > include/uapi/linux/kcov.h | 1 + > io_uring/io-wq.c | 4 ++++ > io_uring/io_uring.c | 18 ++++++++++++++++++ > io_uring/io_uring.h | 22 ++++++++++++++++++++++ > io_uring/sqpoll.c | 4 ++++ > kernel/kcov.c | 2 ++ > 7 files changed, 55 insertions(+) > > diff --git a/include/linux/io_uring_types.h b/include/linux/io_uring_types.h > index 244392026c6d..b92b8e7169ea 100644 > --- a/include/linux/io_uring_types.h > +++ b/include/linux/io_uring_types.h > @@ -504,6 +504,10 @@ struct io_ring_ctx { > struct io_mapped_region ring_region; > /* used for optimised request parameter and wait argument passing */ > struct io_mapped_region param_region; > + > +#ifdef CONFIG_KCOV > + u64 kcov_handle; > +#endif > }; > > /* > diff --git a/include/uapi/linux/kcov.h b/include/uapi/linux/kcov.h > index ed95dba9fa37..15bbce4569b1 100644 > --- a/include/uapi/linux/kcov.h > +++ b/include/uapi/linux/kcov.h > @@ -49,6 +49,7 @@ enum { > > #define KCOV_SUBSYSTEM_COMMON (0x00ull << 56) > #define KCOV_SUBSYSTEM_USB (0x01ull << 56) > +#define KCOV_SUBSYSTEM_IOURING (0x02ull << 56) Hi Robet, Would it be possible to use the common_handle functionality of KCOV for io_uring? The global KCOV handles were not the best design decision. They arguably make sense for kernel tasks that get created during boot. But if a kernel task gets spawned as a result of a user task actions, the common handles are a better approach. > > #define KCOV_SUBSYSTEM_MASK (0xffull << 56) > #define KCOV_INSTANCE_MASK (0xffffffffull) > diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c > index 8cc7b47d3089..bb89d3f4b3dc 100644 > --- a/io_uring/io-wq.c > +++ b/io_uring/io-wq.c > @@ -639,6 +639,7 @@ static void io_worker_handle_work(struct io_wq_acct *acct, > /* handle a whole dependent link */ > do { > struct io_wq_work *next_hashed, *linked; > + struct io_kiocb *req; > unsigned int work_flags = atomic_read(&work->flags); > unsigned int hash = __io_wq_is_hashed(work_flags) > ? __io_get_work_hash(work_flags) > @@ -649,7 +650,10 @@ static void io_worker_handle_work(struct io_wq_acct *acct, > if (do_kill && > (work_flags & IO_WQ_WORK_UNBOUND)) > atomic_or(IO_WQ_WORK_CANCEL, &work->flags); > + req = container_of(work, struct io_kiocb, work); > + io_kcov_remote_start(req->ctx); > io_wq_submit_work(work); > + io_kcov_remote_stop(); > io_assign_current_work(worker, NULL); > > linked = io_wq_free_work(work); > diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c > index 036145ee466c..71478e6ccae4 100644 > --- a/io_uring/io_uring.c > +++ b/io_uring/io_uring.c > @@ -222,6 +222,21 @@ static void io_free_alloc_caches(struct io_ring_ctx *ctx) > io_rsrc_cache_free(ctx); > } > > +#ifdef CONFIG_KCOV > +static __cold u64 io_ring_get_kcov_handle(void) > +{ > + struct nsproxy *ns_proxy = current->nsproxy; > + struct ns_common *ns; > + u64 inst = 0; > + > + if (ns_proxy) { > + ns = to_ns_common(ns_proxy->cgroup_ns); > + inst = ns->inum; > + } > + return kcov_remote_handle(KCOV_SUBSYSTEM_IOURING, inst); > +} > +#endif > + > static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p) > { > struct io_ring_ctx *ctx; > @@ -293,6 +308,9 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p) > INIT_HLIST_HEAD(&ctx->cancelable_uring_cmd); > io_napi_init(ctx); > mutex_init(&ctx->mmap_lock); > +#ifdef CONFIG_KCOV > + ctx->kcov_handle = io_ring_get_kcov_handle(); > +#endif > > return ctx; > > diff --git a/io_uring/io_uring.h b/io_uring/io_uring.h > index e612a66ee80e..cb03df877456 100644 > --- a/io_uring/io_uring.h > +++ b/io_uring/io_uring.h > @@ -7,6 +7,7 @@ > #include <linux/resume_user_mode.h> > #include <linux/poll.h> > #include <linux/io_uring_types.h> > +#include <linux/kcov.h> > #include <uapi/linux/eventpoll.h> > #include "alloc_cache.h" > #include "io-wq.h" > @@ -581,4 +582,25 @@ static inline bool io_has_work(struct io_ring_ctx *ctx) > return test_bit(IO_CHECK_CQ_OVERFLOW_BIT, &ctx->check_cq) || > io_local_work_pending(ctx); > } > + > +#ifdef CONFIG_KCOV > +static inline void io_kcov_remote_start(struct io_ring_ctx *ctx) > +{ > + kcov_remote_start(ctx->kcov_handle); > +} > + > +static inline void io_kcov_remote_stop(void) > +{ > + kcov_remote_stop(); > +} > +#else > +static inline void io_kcov_remote_start(struct io_ring_ctx *ctx) > +{ > +} > + > +static inline void io_kcov_remote_stop(void) > +{ > +} > +#endif > + > #endif > diff --git a/io_uring/sqpoll.c b/io_uring/sqpoll.c > index 46c12afec73e..b244abd37a27 100644 > --- a/io_uring/sqpoll.c > +++ b/io_uring/sqpoll.c > @@ -342,19 +342,23 @@ static int io_sq_thread(void *data) > > cap_entries = !list_is_singular(&sqd->ctx_list); > list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) { > + io_kcov_remote_start(ctx); > int ret = __io_sq_thread(ctx, sqd, cap_entries, &ist); > > if (!sqt_spin && (ret > 0 || !list_empty(&ctx->iopoll_list))) > sqt_spin = true; > + io_kcov_remote_stop(); > } > if (io_sq_tw(&retry_list, IORING_TW_CAP_ENTRIES_VALUE)) > sqt_spin = true; > > list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) { > + io_kcov_remote_start(ctx); > if (io_napi(ctx)) { > io_sq_start_worktime(&ist); > io_napi_sqpoll_busy_poll(ctx); > } > + io_kcov_remote_stop(); > } > > io_sq_update_worktime(sqd, &ist); > diff --git a/kernel/kcov.c b/kernel/kcov.c > index 0b369e88c7c9..6df04581a126 100644 > --- a/kernel/kcov.c > +++ b/kernel/kcov.c > @@ -585,6 +585,8 @@ static inline bool kcov_check_handle(u64 handle, bool common_valid, > common_valid : zero_valid; > case KCOV_SUBSYSTEM_USB: > return uncommon_valid; > + case KCOV_SUBSYSTEM_IOURING: > + return uncommon_valid; > default: > return false; > } > -- > 2.54.0 >