From: Yunseong Kim <ysk@kzalloc.com>
To: Dmitry Vyukov <dvyukov@google.com>,
Andrey Konovalov <andreyknvl@gmail.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>,
Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>,
Byungchul Park <byungchul@sk.com>,
max.byungchul.park@gmail.com, Yeoreum Yun <yeoreum.yun@arm.com>,
ppbuk5246@gmail.com, linux-usb@vger.kernel.org,
linux-rt-devel@lists.linux.dev, syzkaller@googlegroups.com,
linux-kernel@vger.kernel.org, stable@vger.kernel.org,
Yunseong Kim <ysk@kzalloc.com>
Subject: [PATCH 4/4] kcov: move remote handle allocation outside raw spinlock
Date: Sun, 3 Aug 2025 07:20:49 +0000 [thread overview]
Message-ID: <20250803072044.572733-10-ysk@kzalloc.com> (raw)
In-Reply-To: <20250803072044.572733-2-ysk@kzalloc.com>
To comply with raw spinlock constraints, move allocation of kcov_remote
structs out of the critical section in the KCOV_REMOTE_ENABLE path.
Memory is now pre-allocated in kcov_ioctl() before taking any locks,
and passed down to the locked section for insertion into the hash table.
error handling is updated to release the memory on failure.
This aligns with the non-sleeping requirement of raw spinlocks
introduced earlier in the series.
Signed-off-by: Yunseong Kim <ysk@kzalloc.com>
---
kernel/kcov.c | 81 +++++++++++++++++++++++++++++----------------------
1 file changed, 46 insertions(+), 35 deletions(-)
diff --git a/kernel/kcov.c b/kernel/kcov.c
index 1e7f08ddf0e8..46d36e0146cc 100644
--- a/kernel/kcov.c
+++ b/kernel/kcov.c
@@ -113,15 +113,9 @@ static struct kcov_remote *kcov_remote_find(u64 handle)
}
/* Must be called with kcov_remote_lock locked. */
-static struct kcov_remote *kcov_remote_add(struct kcov *kcov, u64 handle)
+static struct kcov_remote *kcov_remote_add(struct kcov *kcov, u64 handle,
+ struct kcov_remote *remote)
{
- struct kcov_remote *remote;
-
- if (kcov_remote_find(handle))
- return ERR_PTR(-EEXIST);
- remote = kmalloc(sizeof(*remote), GFP_ATOMIC);
- if (!remote)
- return ERR_PTR(-ENOMEM);
remote->handle = handle;
remote->kcov = kcov;
hash_add(kcov_remote_map, &remote->hnode, handle);
@@ -580,13 +574,14 @@ static inline bool kcov_check_handle(u64 handle, bool common_valid,
}
static int kcov_ioctl_locked_remote_enabled(struct kcov *kcov,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg,
+ struct kcov_remote *remote_handles,
+ struct kcov_remote *remote_common_handle)
{
struct task_struct *t;
unsigned long flags;
- int mode, i;
+ int mode, i, ret;
struct kcov_remote_arg *remote_arg;
- struct kcov_remote *remote;
if (kcov->mode != KCOV_MODE_INIT || !kcov->area)
return -EINVAL;
@@ -610,41 +605,43 @@ static int kcov_ioctl_locked_remote_enabled(struct kcov *kcov,
for (i = 0; i < remote_arg->num_handles; i++) {
if (!kcov_check_handle(remote_arg->handles[i],
false, true, false)) {
- raw_spin_unlock_irqrestore(&kcov_remote_lock,
- flags);
- kcov_disable(t, kcov);
- return -EINVAL;
+ ret = -EINVAL;
+ goto err;
}
- remote = kcov_remote_add(kcov, remote_arg->handles[i]);
- if (IS_ERR(remote)) {
- raw_spin_unlock_irqrestore(&kcov_remote_lock,
- flags);
- kcov_disable(t, kcov);
- return PTR_ERR(remote);
+ if (kcov_remote_find(remote_arg->handles[i])) {
+ ret = -EEXIST;
+ goto err;
}
+ kcov_remote_add(kcov, remote_arg->handles[i],
+ &remote_handles[i]);
}
if (remote_arg->common_handle) {
if (!kcov_check_handle(remote_arg->common_handle,
true, false, false)) {
- raw_spin_unlock_irqrestore(&kcov_remote_lock,
- flags);
- kcov_disable(t, kcov);
- return -EINVAL;
+ ret = -EINVAL;
+ goto err;
}
- remote = kcov_remote_add(kcov,
- remote_arg->common_handle);
- if (IS_ERR(remote)) {
- raw_spin_unlock_irqrestore(&kcov_remote_lock,
- flags);
- kcov_disable(t, kcov);
- return PTR_ERR(remote);
+ if (kcov_remote_find(remote_arg->common_handle)) {
+ ret = -EEXIST;
+ goto err;
}
+ kcov_remote_add(kcov,
+ remote_arg->common_handle, remote_common_handle);
t->kcov_handle = remote_arg->common_handle;
}
raw_spin_unlock_irqrestore(&kcov_remote_lock, flags);
+
/* Put either in kcov_task_exit() or in KCOV_DISABLE. */
kcov_get(kcov);
return 0;
+
+err:
+ raw_spin_unlock_irqrestore(&kcov_remote_lock, flags);
+ kcov_disable(t, kcov);
+ kfree(remote_common_handle);
+ kfree(remote_handles);
+
+ return ret;
}
static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd,
@@ -702,6 +699,7 @@ static long kcov_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
struct kcov_remote_arg *remote_arg = NULL;
unsigned int remote_num_handles;
unsigned long remote_arg_size;
+ struct kcov_remote *remote_handles, *remote_common_handle;
unsigned long size, flags;
void *area;
@@ -748,11 +746,22 @@ static long kcov_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
return -EINVAL;
}
arg = (unsigned long)remote_arg;
+ remote_handles = kmalloc_array(remote_arg->num_handles,
+ sizeof(struct kcov_remote), GFP_KERNEL);
+ if (!remote_handles)
+ return -ENOMEM;
+ remote_common_handle = kmalloc(sizeof(struct kcov_remote), GFP_KERNEL);
+ if (!remote_common_handle) {
+ kfree(remote_handles);
+ return -ENOMEM;
+ }
+
raw_spin_lock_irqsave(&kcov->lock, flags);
- res = kcov_ioctl_locked_remote_enabled(kcov, cmd, arg);
+ res = kcov_ioctl_locked_remote_enabled(kcov, cmd, arg,
+ remote_handles, remote_common_handle);
raw_spin_unlock_irqrestore(&kcov->lock, flags);
kfree(remote_arg);
- return res;
+ break;
default:
/*
* KCOV_ENABLE and KCOV_DISABLE commands can be normally executed under
@@ -762,8 +771,10 @@ static long kcov_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
raw_spin_lock_irqsave(&kcov->lock, flags);
res = kcov_ioctl_locked(kcov, cmd, arg);
raw_spin_unlock_irqrestore(&kcov->lock, flags);
- return res;
+ break;
}
+
+ return res;
}
static const struct file_operations kcov_fops = {
--
2.50.0
next prev parent reply other threads:[~2025-08-03 7:23 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-03 7:20 [PATCH v3 0/4] kcov, usb: Fix invalid context sleep in softirq path on PREEMPT_RT Yunseong Kim
2025-08-03 7:20 ` [PATCH 1/4] kcov: Use raw_spinlock_t for kcov->lock and kcov_remote_lock Yunseong Kim
2025-08-03 7:23 ` kernel test robot
2025-08-04 16:27 ` Steven Rostedt
2025-08-05 15:33 ` Yunseong Kim
2025-08-03 7:20 ` [PATCH 2/4] kcov: Replace per-CPU local_lock with local_irq_save/restore Yunseong Kim
2025-08-04 16:37 ` Steven Rostedt
2025-08-05 15:41 ` Yunseong Kim
2025-08-03 7:20 ` [PATCH 3/4] kcov: Separate KCOV_REMOTE_ENABLE ioctl helper function Yunseong Kim
2025-08-03 7:20 ` Yunseong Kim [this message]
2025-08-04 16:24 ` [PATCH v3 0/4] kcov, usb: Fix invalid context sleep in softirq path on PREEMPT_RT Steven Rostedt
2025-08-05 15:27 ` Yunseong Kim
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250803072044.572733-10-ysk@kzalloc.com \
--to=ysk@kzalloc.com \
--cc=andreyknvl@gmail.com \
--cc=bigeasy@linutronix.de \
--cc=byungchul@sk.com \
--cc=dvyukov@google.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rt-devel@lists.linux.dev \
--cc=linux-usb@vger.kernel.org \
--cc=max.byungchul.park@gmail.com \
--cc=penguin-kernel@i-love.sakura.ne.jp \
--cc=ppbuk5246@gmail.com \
--cc=stable@vger.kernel.org \
--cc=syzkaller@googlegroups.com \
--cc=tglx@linutronix.de \
--cc=yeoreum.yun@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox