From nobody Sun Feb 8 12:14:52 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5A1652D8DDF; Tue, 28 Oct 2025 08:46:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641164; cv=none; b=s2I6dG32rNn0SO9jjaoz0GtnDkIbEQ5bZeHYHJWPGwsvDwDwJ49OaEfOO4be8Oqmy3PjhV/IGqrEDbpHehWVXcVlBkRflMNMQzMeyOgEIGT4C1YC11Hdz6sAiEIfvnRZtkBV9OCUxTamA7ngDG3kBEl2WrubBh16P01UyBNCMjU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641164; c=relaxed/simple; bh=iCVEjflOE4r84IPd8NVIEeGZIqP+XdFrXHNnZM49L+Y=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HFildR+Bx5US/WpC0iGiW6rRGvgQGHznc3t5A9vkNGuFsM+bAxTPuu+O2+lx0Fcgd2CAgEROwRljxsdQgZgaRZHxQVU/5Vv4qGl9ab2x6cqcZPTPPotVD+VpLiu+RzAEqTIQc+VZqKZC2TOZfalaVNTtRCch1rO4uKU6rzCNfU4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ugptnf0t; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Ugptnf0t" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2FB76C4CEFF; Tue, 28 Oct 2025 08:46:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641163; bh=iCVEjflOE4r84IPd8NVIEeGZIqP+XdFrXHNnZM49L+Y=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Ugptnf0tSHJEUrKUliV4GGWQz6fHj/ybnNqPXoad0oDYPVyWmQerbnbwr5ef/vrQ7 SYAWC+IO2N/6ENvLAKRuo3+iT4sse5f66asP0I+r1Gs9HDK8URON5W0GvSnBeRBY+4 dnJi24b1OhphzMSB2ZBhThL14Eyxt3te2aP2dWvqAsH6nVDmyvReU/l9fxKDGPSxMV jtjkhT5AOklZWmpCE3VGFTAoUwMN6/5Wb30VfDHJOKp6GC1CcpDgoPPkfJSeZS+8rJ exybIP/Q++/ttcCSpQ2/AdGVcXTTG0hdRsV1USgXbimFw7s3ngwo5mm+mIElJjZPpa 6Fy6FriStOmpw== From: Christian Brauner Date: Tue, 28 Oct 2025 09:45:46 +0100 Subject: [PATCH 01/22] pidfs: use guard() for task_lock Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-1-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=787; i=brauner@kernel.org; h=from:subject:message-id; bh=iCVEjflOE4r84IPd8NVIEeGZIqP+XdFrXHNnZM49L+Y=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB2c4NiXnaRaN3lJxAePfRkHNNQFv8dbXetONkz5t vaKkt3ljlIWBjEuBlkxRRaHdpNwueU8FZuNMjVg5rAygQxh4OIUgImYZjMyPGa/+o9X3Oiq69yN lg3bqzh2qIZuL1ks/5ud2ffyCv8TNxgZLizTPzSrOe5OvVSdg773u/zt6VZtL6qCpiVkrswPdCr hAAA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Use a guard(). Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- fs/pidfs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/pidfs.c b/fs/pidfs.c index 0ef5b47d796a..c2f0b7091cd7 100644 --- a/fs/pidfs.c +++ b/fs/pidfs.c @@ -356,13 +356,12 @@ static long pidfd_info(struct file *file, unsigned in= t cmd, unsigned long arg) return -ESRCH; =20 if ((kinfo.mask & PIDFD_INFO_COREDUMP) && !(kinfo.coredump_mask)) { - task_lock(task); + guard(task_lock)(task); if (task->mm) { unsigned long flags =3D __mm_flags_get_dumpable(task->mm); =20 kinfo.coredump_mask =3D pidfs_coredump_mask(flags); } - task_unlock(task); } =20 /* Unconditionally return identifiers and credentials, the rest only on r= equest */ --=20 2.47.3 From nobody Sun Feb 8 12:14:52 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 18996201278; Tue, 28 Oct 2025 08:46:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641169; cv=none; b=BFC/K+1Pi9XMZ7XDrlO/i3xjDub091wRe+KLgkWoFAOuenVuk/3GEqcE/MyBR1GMJJOJvjs5oF5bpz7FxokWSBoEfyF7miK+5Iw2XspWTSMlMjwjfHG0+0jpu5wERRFk8r2bbZkvzdAAcSlYmS3vlgvV2vg7jjT3/vBkSRcTcwg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641169; c=relaxed/simple; bh=gKW3Kch+DxwyOQ6E7K86XC06vlBSYTzRLn7iujbu9A0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=i7Kj5D/g9GiHXiNGxHfuqlJtIMUfU/rUuORfuu7ohyZC/tD+X4Il6wanKk9FMvwFO3QaQ3hUsOxh1qiaMDbymY4/VDu+ENtyhhreFXTfBXOiVqOnPAswuHpC5WejBJIpGfkFDOZm5Ejj2/CTCGvXjy+m93z3eB8q6CHyXe/214k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=opZtxCUz; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="opZtxCUz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5B2B5C4CEE7; Tue, 28 Oct 2025 08:46:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641168; bh=gKW3Kch+DxwyOQ6E7K86XC06vlBSYTzRLn7iujbu9A0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=opZtxCUzzJ/2kSKbZ3zAcnoKuWThg4OLPSoBuDBv6BJxsEbhlozP0bAWJuFhLXWw6 LFeSA9z+wcWLwapl+CuH/Jkvd9AeOnv+SRGhtOIUfWTTpKnGkvxWpRGYU690PtpbBA LbFHfImuKq8yTKJedTe+AE7sBkLSUeKju1pIOHULLeEXy00MIEb/ChkNKmd05zpxe1 dPFoafggWacHsD6J1cR14GJMQrL3Qg8TVilMmGsh9VvO92XPK8Am/rVRGcRCw9JGn1 CixBSkA70Ta3+l7Obzqxdewt0E+DaQ5MjkUDXnQ9sSNySoyUu5GwC9kdwYjII5g+Ez YHrCUfdyKg9qA== From: Christian Brauner Date: Tue, 28 Oct 2025 09:45:47 +0100 Subject: [PATCH 02/22] pidfs: fix PIDFD_INFO_COREDUMP handling Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-2-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=1573; i=brauner@kernel.org; h=from:subject:message-id; bh=gKW3Kch+DxwyOQ6E7K86XC06vlBSYTzRLn7iujbu9A0=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB38dubvguT8tefdd3G0GkjmR+ad2hzmGe7jmiyRz c9zaF9kRykLgxgXg6yYIotDu0m43HKeis1GmRowc1iZQIYwcHEKwERYvjEyrGmwmGe44ec07onx LTOWqJt+5PjyOeyPg+OyEj/ddf3f7zAy/Iw4kZHus9rgg1+N1Hz3cK0Pc2wct7/mPrAsr+LCFK6 THAA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 When PIDFD_INFO_COREDUMP is requested we raise it unconditionally in the returned mask even if no coredump actually did take place. This was done because we assumed that the later check whether ->coredump_mask as non-zero detects that it is zero and then retrieves the dumpability settings from the task's mm. This has issues though becuase there are tasks that might not have any mm. Also it's just not very cleanly implemented. Fix this. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- fs/pidfs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/pidfs.c b/fs/pidfs.c index c2f0b7091cd7..c0f410903c3f 100644 --- a/fs/pidfs.c +++ b/fs/pidfs.c @@ -335,8 +335,9 @@ static long pidfd_info(struct file *file, unsigned int = cmd, unsigned long arg) } =20 if (mask & PIDFD_INFO_COREDUMP) { - kinfo.mask |=3D PIDFD_INFO_COREDUMP; kinfo.coredump_mask =3D READ_ONCE(attr->__pei.coredump_mask); + if (kinfo.coredump_mask) + kinfo.mask |=3D PIDFD_INFO_COREDUMP; } =20 task =3D get_pid_task(pid, PIDTYPE_PID); @@ -355,12 +356,13 @@ static long pidfd_info(struct file *file, unsigned in= t cmd, unsigned long arg) if (!c) return -ESRCH; =20 - if ((kinfo.mask & PIDFD_INFO_COREDUMP) && !(kinfo.coredump_mask)) { + if ((mask & PIDFD_INFO_COREDUMP) && !kinfo.coredump_mask) { guard(task_lock)(task); if (task->mm) { unsigned long flags =3D __mm_flags_get_dumpable(task->mm); =20 kinfo.coredump_mask =3D pidfs_coredump_mask(flags); + kinfo.mask |=3D PIDFD_INFO_COREDUMP; } } =20 --=20 2.47.3 From nobody Sun Feb 8 12:14:52 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 464742D73A4; Tue, 28 Oct 2025 08:46:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641174; cv=none; b=BdjkTSS2QUmt1IMH185n7xlPrLIG5yAWAux3BlSRnBy19evfxwrh8axtGLiDeYJEPr0O311cWLpNcF/XRf4aozF451Gi+ywU+YGAVmcknsKoHHsYYWeayZEVCPzYF4Cw6L4N239xGkE8NBXW8YIg2UfDHvcbQ0ZCJc8UfoNoCBY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641174; c=relaxed/simple; bh=Q8nIJCP/MWRKfTorXwE5BdMuUQyCSfVb9hCE6/9Dt4c=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=AfY37rPmwUnuh37smAEE2EGdgcdKBdMel/3wf9qAVCXwwtv73v6zc1Mz3kP6kL5olScHmwJOoA5LGf3SUPnEOhsVe80uXUOkNO4tQJhnBdVoF1SFSwUI5qiPH1WDvYFaeFPmuj62PC9s9mciHuqm7l8ibBx2dmOYv/gdrdyWD+o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PwWiK92n; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="PwWiK92n" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 66350C4CEFF; Tue, 28 Oct 2025 08:46:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641173; bh=Q8nIJCP/MWRKfTorXwE5BdMuUQyCSfVb9hCE6/9Dt4c=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=PwWiK92nKxAiq2UBfl7HGnZpQa7iU9nsp6Nj0te6N0+tq0S/uGKtCWhspirfESJ/q Rsh3+yjqN8IKDRitbMAKD/YuBfGv/lZhkqSylR4wYyDVpZXVVg8ZTDAuqQMKlx0XO+ jXEKunO5Ez2kCcog8P4B28WbCWcPDhh6cWV+a7PupiBJrfiLjlfcCEnC0TGDgiha5B 9MnaTTqATHr/wUaMMTqD0ZZ7eHAOv1HLcZOZOWj8GtkhVOnVwlZXnhUs5plsKF4Dng Rg59sNj7EctpCWhryj9JFSkUldqHKF07Cq3gayLXmt1wZynCzJ6ycOKUzRKatMqWke qhPMkAzWZwOhg== From: Christian Brauner Date: Tue, 28 Oct 2025 09:45:48 +0100 Subject: [PATCH 03/22] pidfs: add missing PIDFD_INFO_SIZE_VER1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-3-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=732; i=brauner@kernel.org; h=from:subject:message-id; bh=Q8nIJCP/MWRKfTorXwE5BdMuUQyCSfVb9hCE6/9Dt4c=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB2c//vE9ImCLMsOxwopWAp1fOwpPseh09z0Ni5Wl /f1ByPZjlIWBjEuBlkxRRaHdpNwueU8FZuNMjVg5rAygQxh4OIUgImYSTMy9C1/bLlxJ2PdrdjE UOsjt0QTqm4c6TmYyHJP6r6AedMGWYb/IbvKLONjZkw0Tp7949+X6bmn2NUyQz7c0f8UXn1D57I bKwA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 We grew struct pidfd_info not too long ago. Fixes: 1d8db6fd698d ("pidfs, coredump: add PIDFD_INFO_COREDUMP") Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- include/uapi/linux/pidfd.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/uapi/linux/pidfd.h b/include/uapi/linux/pidfd.h index 957db425d459..6ccbabd9a68d 100644 --- a/include/uapi/linux/pidfd.h +++ b/include/uapi/linux/pidfd.h @@ -28,6 +28,7 @@ #define PIDFD_INFO_COREDUMP (1UL << 4) /* Only returned if requested. */ =20 #define PIDFD_INFO_SIZE_VER0 64 /* sizeof first published struct */ +#define PIDFD_INFO_SIZE_VER1 72 /* sizeof second published struct */ =20 /* * Values for @coredump_mask in pidfd_info. --=20 2.47.3 From nobody Sun Feb 8 12:14:52 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 25D7C18B47D; Tue, 28 Oct 2025 08:46:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641178; cv=none; b=H0QndVqnIP6QeK8L2vRlx0KV4VLKX9OrVyt1U3t/qQNsJESWKvGfzBDE0A9loLnLdV5cYFU2qfIJk9R+20OxPI7KitM8SnmcxxHEnGGoKfVfaq7SgLHdx9uaOZYfkTlGASB2mPgLXDb+LCUjFF9trbQ4CYWJdYwfBZMUEeWvbhA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641178; c=relaxed/simple; bh=xLaA3mHVs1PMWvjVhO98eDYbhDOhetr0dEi8bwXPzZc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=BTBApQ7Ayb4E5Z/oTXcu85r9KjW65YyO85e4mY5kbHFYTpjqKNzLue+OCjb7nf6C/eiXj/tkD4vFwCGGJZLQZFTmt5Hn9pm66ZWmPX7x9r0ITWSqlYO+lcHZjU+2Y6ccC7FhlZyrTHeZNVdLb1BHxlrCDjGuCurUZboR6gZJDB8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Mk7DvoA6; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Mk7DvoA6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 332C3C4CEE7; Tue, 28 Oct 2025 08:46:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641177; bh=xLaA3mHVs1PMWvjVhO98eDYbhDOhetr0dEi8bwXPzZc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Mk7DvoA6EhCNm1jFYTvCH3G5KY7t1ywC9Vd7qKgNddwPRDmdZZUZz8CobWfys8fee ifnwRDEed7xhcCaBxqeSQqLjLPWRMwd6dm4sd8oIEplhzvn0HnOje6Vumb9ZEN/qbq LvcVIgcpBwVa+4GaQ/O/Mxn7E4rrNJjDkXvIr4FPcH/w3Ug7cWWKeWwr4Af9UvCmu4 Fyedkf7nEkuZHg8cf6qWBxxNE7zgb4titNMig9fU1HfFrmY5L5wxHbPTJC4wUNdSEU qPvGELV82guJrt8bkYdoelNTHMasMAnjHPdSYRhOYukAd/SBJWPw+6++jNu2UNJH1L nLpWacEvINoyw== From: Christian Brauner Date: Tue, 28 Oct 2025 09:45:49 +0100 Subject: [PATCH 04/22] pidfs: add missing BUILD_BUG_ON() assert on struct pidfd_info Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-4-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=667; i=brauner@kernel.org; h=from:subject:message-id; bh=xLaA3mHVs1PMWvjVhO98eDYbhDOhetr0dEi8bwXPzZc=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB2s68rPfbujfu9VE8Ee8dZr86cmb900/dFsxhXBL ZNmO+Vf7ShlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZjIJB+GPxxcybprV7BIZqqv WSORN/Pf0p9ruFW13ylypZvr7+pWqGD4pya0d8biZzvsvgm43g3QSOHM2Vr+yvLuWQ9njYZW3k/ LmAA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Validate that the size of struct pidfd_info is correctly updated. Fixes: 1d8db6fd698d ("pidfs, coredump: add PIDFD_INFO_COREDUMP") Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- fs/pidfs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/pidfs.c b/fs/pidfs.c index c0f410903c3f..7e4d90cc74ff 100644 --- a/fs/pidfs.c +++ b/fs/pidfs.c @@ -306,6 +306,8 @@ static long pidfd_info(struct file *file, unsigned int = cmd, unsigned long arg) const struct cred *c; __u64 mask; =20 + BUILD_BUG_ON(sizeof(struct pidfd_info) !=3D PIDFD_INFO_SIZE_VER1); + if (!uinfo) return -EINVAL; if (usize < PIDFD_INFO_SIZE_VER0) --=20 2.47.3 From nobody Sun Feb 8 12:14:52 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 60E1C2D978C; Tue, 28 Oct 2025 08:46:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641184; cv=none; b=dO6UP0ldbWUhXdG14pmYmzl2mgK8dsTETfMuxRNNK3UUKOZnDJOPnSbC8633LnFvydIpJ8K54Qr+gHjsYVRiCG+Ziq1XWM3DpNt8Q1+WGHRIHTAeEpHRCiMRYiDI14XQSQVuwN1QFu18zcKJy4cTfM43oaVje+IBwc/MTJ6YPdY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641184; c=relaxed/simple; bh=5bvn5pDHWFfYoNTwh3Tkn+1Oem0Xb9reqUBXveK/Isw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Qdvolf+VAlBR4vG/z9sa+TirQapdpToX+2SzzOOX08+OmkcpvRQM68KjvCDsSiTcjACQjKoSEKF2K83gpU9FtCXxLhDMZIicrWMO74s1C154wxKC8H3PZwonYNR2TAtcVSI6HgJ4h56OrDChsZIYuzJFtR9nLVVCAERnVIaiOYM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lVVK8yJB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="lVVK8yJB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6392DC4CEE7; Tue, 28 Oct 2025 08:46:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641183; bh=5bvn5pDHWFfYoNTwh3Tkn+1Oem0Xb9reqUBXveK/Isw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=lVVK8yJBAk5tACBhO5qZTavS4Uu+uKeSsytmdXGlq15nzndR4bO5IGbmw1WhAyxlI VTpTzjFfPtWgTY1fxyqskyRCqwnQTtH724Ml0aGQQIuPDHBLFRNWnEyt3EkKnAYFz+ s81YwaLZd8TOY/d7c9b7fcc3TWNDfEmGe1xCbAlmnoY027HUI8jGTzXQIw5s2361UR h0CgJhz7Yx5uvQfRsFCR5A+yQ71Z5pd700EuCStFBmTfGisCFYM4akJVEnBPbezBLK CzgMphXmoCf2A0AS4PcZ036TR+pIdK04kciyMj47rBTpHvPJq5bKwc1Ixh5gYHcBpe G3kuJJC0dtRxA== From: Christian Brauner Date: Tue, 28 Oct 2025 09:45:50 +0100 Subject: [PATCH 05/22] pidfd: add a new supported_mask field Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-5-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=3362; i=brauner@kernel.org; h=from:subject:message-id; bh=5bvn5pDHWFfYoNTwh3Tkn+1Oem0Xb9reqUBXveK/Isw=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB1c2vvWVWDb1UilqctLtXQnJrl3vX6ynE210nFmX Fa13P7ejlIWBjEuBlkxRRaHdpNwueU8FZuNMjVg5rAygQxh4OIUgIkofmT4H7Qp/86MSz+lJAIF wvL+v5p12SdrmrSWGrvh1s23F6Zn8jH8r5Xjy6iqb3yZx2p+Uv2a9m3hkJRy73C99ZENM4x7I4q 5AQ== X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Some of the future fields in struct pidfd_info can be optional. If the kernel has nothing to emit in that field, then it doesn't set the flag in the reply. This presents a problem: There is currently no way to know what mask flags the kernel supports since one can't always count on them being in the reply. Add a new PIDFD_INFO_SUPPORTED_MASK flag and field that the kernel can set in the reply. Userspace can use this to determine if the fields it requires from the kernel are supported. This also gives us a way to deprecate fields in the future, if that should become necessary. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- fs/pidfs.c | 17 ++++++++++++++++- include/uapi/linux/pidfd.h | 3 +++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/fs/pidfs.c b/fs/pidfs.c index 7e4d90cc74ff..204ebd32791a 100644 --- a/fs/pidfs.c +++ b/fs/pidfs.c @@ -293,6 +293,14 @@ static __u32 pidfs_coredump_mask(unsigned long mm_flag= s) return 0; } =20 +/* This must be updated whenever a new flag is added */ +#define PIDFD_INFO_SUPPORTED (PIDFD_INFO_PID | \ + PIDFD_INFO_CREDS | \ + PIDFD_INFO_CGROUPID | \ + PIDFD_INFO_EXIT | \ + PIDFD_INFO_COREDUMP | \ + PIDFD_INFO_SUPPORTED_MASK) + static long pidfd_info(struct file *file, unsigned int cmd, unsigned long = arg) { struct pidfd_info __user *uinfo =3D (struct pidfd_info __user *)arg; @@ -306,7 +314,7 @@ static long pidfd_info(struct file *file, unsigned int = cmd, unsigned long arg) const struct cred *c; __u64 mask; =20 - BUILD_BUG_ON(sizeof(struct pidfd_info) !=3D PIDFD_INFO_SIZE_VER1); + BUILD_BUG_ON(sizeof(struct pidfd_info) !=3D PIDFD_INFO_SIZE_VER2); =20 if (!uinfo) return -EINVAL; @@ -412,6 +420,13 @@ static long pidfd_info(struct file *file, unsigned int= cmd, unsigned long arg) return -ESRCH; =20 copy_out: + if (mask & PIDFD_INFO_SUPPORTED_MASK) { + kinfo.mask |=3D PIDFD_INFO_SUPPORTED_MASK; + kinfo.supported_mask =3D PIDFD_INFO_SUPPORTED; + } + + /* Are there bits in the return mask not present in PIDFD_INFO_SUPPORTED?= */ + WARN_ON_ONCE(~PIDFD_INFO_SUPPORTED & kinfo.mask); /* * If userspace and the kernel have the same struct size it can just * be copied. If userspace provides an older struct, only the bits that diff --git a/include/uapi/linux/pidfd.h b/include/uapi/linux/pidfd.h index 6ccbabd9a68d..e05caa0e00fe 100644 --- a/include/uapi/linux/pidfd.h +++ b/include/uapi/linux/pidfd.h @@ -26,9 +26,11 @@ #define PIDFD_INFO_CGROUPID (1UL << 2) /* Always returned if available, e= ven if not requested */ #define PIDFD_INFO_EXIT (1UL << 3) /* Only returned if requested. */ #define PIDFD_INFO_COREDUMP (1UL << 4) /* Only returned if requested. */ +#define PIDFD_INFO_SUPPORTED_MASK (1UL << 5) /* Want/got supported mask fl= ags */ =20 #define PIDFD_INFO_SIZE_VER0 64 /* sizeof first published struct */ #define PIDFD_INFO_SIZE_VER1 72 /* sizeof second published struct */ +#define PIDFD_INFO_SIZE_VER2 80 /* sizeof third published struct */ =20 /* * Values for @coredump_mask in pidfd_info. @@ -94,6 +96,7 @@ struct pidfd_info { __s32 exit_code; __u32 coredump_mask; __u32 __spare1; + __u64 supported_mask; /* Mask flags that this kernel supports */ }; =20 #define PIDFS_IOCTL_MAGIC 0xFF --=20 2.47.3 From nobody Sun Feb 8 12:14:52 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 47F082D8791; Tue, 28 Oct 2025 08:46:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641188; cv=none; b=eE9Bf2q+wIFmdhcIxQkoUlQVrZMR62o6yjVF7bvNHBYgtOkdZB2ASMR7MqciQF04R1HsCURrLadciLcR7e+bwd3xNnXxl5AVgvoJWhxXMJw0m5IbCOcyaE4MEmZiQPK2pJop4TXBzOE0hOa/TINDLy9W1+2QKCSD/aAxxpF2Im0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641188; c=relaxed/simple; bh=w3mtdowJsCvEuLqwOzwn6IjUjzAdTS1pCL4gwDenbjo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Q+ZesuKzt9ivMueIxyDDuLUupaxVm6U9PfNsC+buAG7bBm/m4C2n3cgiWL7ys31mh6MuiPCQbfyPtuRL1BaGfEIyQxWwaCB3gkqnS2ou4M5NgwIqwrkHwTBzjoe6zBxEVwrO9TAyccmp2khwjEzK7n5Sp4VEiUDLjH6PvWoHPG8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NsSiVYwB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NsSiVYwB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 60A93C4CEFF; Tue, 28 Oct 2025 08:46:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641188; bh=w3mtdowJsCvEuLqwOzwn6IjUjzAdTS1pCL4gwDenbjo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=NsSiVYwBlzvdK6Rq2oeeLyKzJqBBz9CPvNFsXiPidXOihnwm2mNE+Nazae5wx+QWg cl16T+P0+pdMB7gsW/Uv1Dh6UIeL0fp3uKtHn1Rk03aXC1x9eTb1JCSZU7IJcYaeYn UPX0b4VOS7ttsQVbNp0VlV7DdxfSVcYB74wFjsXDPdmeBEcTgnUfjkTY7YgnS4im3Z FiFTiu5egObCgDB/LH7yyUGjbmiAzC/z3nM2MYiuvG3Y5lsU8Af5UZqfrfyb91qvZw evT1rvN4uemhiwRPCy8cgv9yD48Sp6UXxSvQcD5gJL3VfVKehGo9h61p0v3/0kmqzs Ca/bVbwGpt1ww== From: Christian Brauner Date: Tue, 28 Oct 2025 09:45:51 +0100 Subject: [PATCH 06/22] pidfs: prepare to drop exit_info pointer Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-6-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=1742; i=brauner@kernel.org; h=from:subject:message-id; bh=w3mtdowJsCvEuLqwOzwn6IjUjzAdTS1pCL4gwDenbjo=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB0slj56964GC+vVa39brUqWn1L9yTBr5dNn/wU5r TO2yC+f3lHKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjCRGcsYGT79mtxuNrtUzdxa 1PnbAbGy1abVTbtNlx8+cbXF7MGUIl1Ghq0yiZv05Dn3nvd53e4+RUtv6/kbvwyLPQKPmVz6dsV DlhsA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 There will likely be more info that we need to store in struct pidfs_attr. We need to make sure that some of the information such as exit info or coredump info that consists of multiple bits is either available completely or not at all, but never partially. Currently we use a pointer that we assign to. That doesn't scale. We can't waste a pointer for each mulit-part information struct we want to expose. Use a bitmask instead. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- fs/pidfs.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/fs/pidfs.c b/fs/pidfs.c index 204ebd32791a..0fad0c969b7a 100644 --- a/fs/pidfs.c +++ b/fs/pidfs.c @@ -49,7 +49,12 @@ struct pidfs_exit_info { __u32 coredump_mask; }; =20 +enum pidfs_attr_mask_bits { + PIDFS_ATTR_BIT_EXIT =3D 0, +}; + struct pidfs_attr { + unsigned long attr_mask; struct simple_xattrs *xattrs; struct pidfs_exit_info __pei; struct pidfs_exit_info *exit_info; @@ -333,8 +338,8 @@ static long pidfd_info(struct file *file, unsigned int = cmd, unsigned long arg) =20 attr =3D READ_ONCE(pid->attr); if (mask & PIDFD_INFO_EXIT) { - exit_info =3D READ_ONCE(attr->exit_info); - if (exit_info) { + if (test_bit(PIDFS_ATTR_BIT_EXIT, &attr->attr_mask)) { + smp_rmb(); kinfo.mask |=3D PIDFD_INFO_EXIT; #ifdef CONFIG_CGROUPS kinfo.cgroupid =3D exit_info->cgroupid; @@ -663,7 +668,8 @@ void pidfs_exit(struct task_struct *tsk) exit_info->exit_code =3D tsk->exit_code; =20 /* Ensure that PIDFD_GET_INFO sees either all or nothing. */ - smp_store_release(&attr->exit_info, &attr->__pei); + smp_wmb(); + set_bit(PIDFS_ATTR_BIT_EXIT, &attr->attr_mask); } =20 #ifdef CONFIG_COREDUMP --=20 2.47.3 From nobody Sun Feb 8 12:14:52 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 364C22D595B; Tue, 28 Oct 2025 08:46:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641193; cv=none; b=CkPQdJfWIGUhYaO28t7h+oUYRhLyEifNhZYb28JTn9VFWQ0euHVKTF88z26oDKKw6+fmZvsC4ilK1oOqz/b5L0mbQlUOSRMHLVFWWBggfF8wWSa2EZiUrz1C7gUEzHrNBj5knS+Ei5tHgQcdyufI1GXSDQWvdEDseDIxDYMOTY0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641193; c=relaxed/simple; bh=RVh2i7HDkT2NYWf85JxVPLYfSr8x+7ix55FiOfx/B10=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LO35tF6XphBD8oJqqxnSZr8v9syM53K+XFyEH5/0gmAjV/5bLSfYqrS+mr4FdGskHo+pbubw1X9hPGYOdt+3v8ybAL7hogUJyrKGq2fEcfzs/ZM6vtOFa0PPi1I6fGRpTOrmf137iKG7wfN+J+Gdik81KruhmTXZfQHG9MJc3Kw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DAJIBJnd; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DAJIBJnd" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C9F0CC4CEE7; Tue, 28 Oct 2025 08:46:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641193; bh=RVh2i7HDkT2NYWf85JxVPLYfSr8x+7ix55FiOfx/B10=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=DAJIBJndvBisOf4GuvYK0Vghj8duRR9e0IUFTF9GlKbOOu8bLPYV6dRO9lyEdHDOu JN5EtzdzxBTGUUU9MAfRmFxBekfcYv7Gfb3lVE1Ie3On/jgJDqiUiBetioJuBzFlIg R/780TvwL9Ry+uDK4lhel1yf13wkFRcKh1jYWEDyCqeJAX1QtW+SdpNtVhmhfK/IEf k3acPFvqpj90cKTk1umxqrYGKPh4tPqTfWgWEoK+lCtJpR1dRZyRL41Z5TPuePCWA1 zS3cAiV5crVzRCfZydRT64Gub2EuVLitf+8B0YMt1DSGAHygiC6XViKwiLH4Gg5/g0 OMWC1shm32RKA== From: Christian Brauner Date: Tue, 28 Oct 2025 09:45:52 +0100 Subject: [PATCH 07/22] pidfs: drop struct pidfs_exit_info Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-7-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=3668; i=brauner@kernel.org; h=from:subject:message-id; bh=RVh2i7HDkT2NYWf85JxVPLYfSr8x+7ix55FiOfx/B10=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB2c+2VvD7/movDad0nb2Kc5HC7dxdcbeiBPxFa2e k3pu/cHOkpZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACYyPZKR4fSm70zGtc+2Ga+o 0jT7JnKVv0OLJU9jl0DlxY8L3vywiWH4Z5MwO/9SrrG3c+WtIKf7p6bNNg73K3CMj2A9JuYdotz OBgA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 This is not needed anymore now that we have the new scheme to guarantee all-or-nothing information exposure. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- fs/pidfs.c | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/fs/pidfs.c b/fs/pidfs.c index 0fad0c969b7a..a3b80be3b98b 100644 --- a/fs/pidfs.c +++ b/fs/pidfs.c @@ -39,16 +39,6 @@ void pidfs_get_root(struct path *path) path_get(path); } =20 -/* - * Stashes information that userspace needs to access even after the - * process has been reaped. - */ -struct pidfs_exit_info { - __u64 cgroupid; - __s32 exit_code; - __u32 coredump_mask; -}; - enum pidfs_attr_mask_bits { PIDFS_ATTR_BIT_EXIT =3D 0, }; @@ -56,8 +46,11 @@ enum pidfs_attr_mask_bits { struct pidfs_attr { unsigned long attr_mask; struct simple_xattrs *xattrs; - struct pidfs_exit_info __pei; - struct pidfs_exit_info *exit_info; + struct /* exit info */ { + __u64 cgroupid; + __s32 exit_code; + }; + __u32 coredump_mask; }; =20 static struct rb_root pidfs_ino_tree =3D RB_ROOT; @@ -313,7 +306,6 @@ static long pidfd_info(struct file *file, unsigned int = cmd, unsigned long arg) struct pid *pid =3D pidfd_pid(file); size_t usize =3D _IOC_SIZE(cmd); struct pidfd_info kinfo =3D {}; - struct pidfs_exit_info *exit_info; struct user_namespace *user_ns; struct pidfs_attr *attr; const struct cred *c; @@ -342,15 +334,15 @@ static long pidfd_info(struct file *file, unsigned in= t cmd, unsigned long arg) smp_rmb(); kinfo.mask |=3D PIDFD_INFO_EXIT; #ifdef CONFIG_CGROUPS - kinfo.cgroupid =3D exit_info->cgroupid; + kinfo.cgroupid =3D attr->cgroupid; kinfo.mask |=3D PIDFD_INFO_CGROUPID; #endif - kinfo.exit_code =3D exit_info->exit_code; + kinfo.exit_code =3D attr->exit_code; } } =20 if (mask & PIDFD_INFO_COREDUMP) { - kinfo.coredump_mask =3D READ_ONCE(attr->__pei.coredump_mask); + kinfo.coredump_mask =3D READ_ONCE(attr->coredump_mask); if (kinfo.coredump_mask) kinfo.mask |=3D PIDFD_INFO_COREDUMP; } @@ -629,7 +621,6 @@ void pidfs_exit(struct task_struct *tsk) { struct pid *pid =3D task_pid(tsk); struct pidfs_attr *attr; - struct pidfs_exit_info *exit_info; #ifdef CONFIG_CGROUPS struct cgroup *cgrp; #endif @@ -657,15 +648,13 @@ void pidfs_exit(struct task_struct *tsk) * is put */ =20 - exit_info =3D &attr->__pei; - #ifdef CONFIG_CGROUPS rcu_read_lock(); cgrp =3D task_dfl_cgroup(tsk); - exit_info->cgroupid =3D cgroup_id(cgrp); + attr->cgroupid =3D cgroup_id(cgrp); rcu_read_unlock(); #endif - exit_info->exit_code =3D tsk->exit_code; + attr->exit_code =3D tsk->exit_code; =20 /* Ensure that PIDFD_GET_INFO sees either all or nothing. */ smp_wmb(); @@ -676,7 +665,6 @@ void pidfs_exit(struct task_struct *tsk) void pidfs_coredump(const struct coredump_params *cprm) { struct pid *pid =3D cprm->pid; - struct pidfs_exit_info *exit_info; struct pidfs_attr *attr; __u32 coredump_mask =3D 0; =20 @@ -685,14 +673,13 @@ void pidfs_coredump(const struct coredump_params *cpr= m) VFS_WARN_ON_ONCE(!attr); VFS_WARN_ON_ONCE(attr =3D=3D PIDFS_PID_DEAD); =20 - exit_info =3D &attr->__pei; /* Note how we were coredumped. */ coredump_mask =3D pidfs_coredump_mask(cprm->mm_flags); /* Note that we actually did coredump. */ coredump_mask |=3D PIDFD_COREDUMPED; /* If coredumping is set to skip we should never end up here. */ VFS_WARN_ON_ONCE(coredump_mask & PIDFD_COREDUMP_SKIP); - smp_store_release(&exit_info->coredump_mask, coredump_mask); + smp_store_release(&attr->coredump_mask, coredump_mask); } #endif =20 --=20 2.47.3 From nobody Sun Feb 8 12:14:52 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 816DC2DAFA1; Tue, 28 Oct 2025 08:46:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641197; cv=none; b=S8bHqFeWmAa43qNa8dx/gjIUUcJeSaW4+eMUpWDy0tgs2EnmAqwmq+FWjNzPgXqEC0IzxkR8HTy280qsp0Jp+ABP2fE2D8cZlNFNIEDlNxOb4hulNXHqJaG3rKq7i16Oh2oSv9lUqVpYwOa+TNJOLc5Bdmo6IcpZNiVkSTjx/mI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641197; c=relaxed/simple; bh=CqBLua7mC1jnX91nIzWy68mJTdDx9M0GCh7rqkQtFj4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NBcghZqQgixBjTUF/WIo79Kafwo8fRyuzdZ36zYgXES2RvqSNdOyuuzYJuz2WW3ZqCMCR7w2fFEHBiIyS4H5wpxLQR5hl4zWgfx99v3g2d93rfst5eFDsaBL3VZtIBUtmlBAZUXZVgVQFeG7yc1sGlJZMQT5/Icn3ukNMaqiqc0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TaG8r5Cw; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="TaG8r5Cw" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7DF5CC4CEE7; Tue, 28 Oct 2025 08:46:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641197; bh=CqBLua7mC1jnX91nIzWy68mJTdDx9M0GCh7rqkQtFj4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=TaG8r5CwImD2ut7WGFRwKxHNou55SZHOpBjSUdIZ1qoxM7vj+Zw6ZtByujlkjrgJM K4EqIFWMfnEEhCk119s02QqkQtp3es0bRtBqn1rX2fyN/5/JrrR911UleSlspbGxR5 MsQgQYWSew3LfjajJ0M0qsnYF3pa+d3vbz/Ksl4poqk9s3CgGxSDVYwjVYfDC0yzoR rE4cMMTB6tuZSeb/beL/RYUskJ7/hN+0dYSM8SxBTfgWznILE3sOpbq3VoYNylGlZ/ 87thZk5+joxFEMjWNgXiyTjNQh+y0FfD23/SN3FnqYvsW42IitZGiSKM/RqhYOYGIl 0qZiRZa1mxUXA== From: Christian Brauner Date: Tue, 28 Oct 2025 09:45:53 +0100 Subject: [PATCH 08/22] pidfs: expose coredump signal Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-8-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=4285; i=brauner@kernel.org; h=from:subject:message-id; bh=CqBLua7mC1jnX91nIzWy68mJTdDx9M0GCh7rqkQtFj4=; b=kA0DAAoWkcYbwGV43KIByyZiAGkAgsGic1ncXqnT9faYYabTX80a5gw0OGbFlvIbAF3/0UPAc oh1BAAWCgAdFiEEQIc0Vx6nDHizMmkokcYbwGV43KIFAmkAgsEACgkQkcYbwGV43KLUmAD+LqY5 B0JB0lVYhW0lcAWiEY7RemBxIpe+xvr7Chw4uU8A/199f95a6vHxn2d5lcYXyfiBXSzsSxRc/Kb 82zAHt2AM X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Userspace needs access to the signal that caused the coredump before the coredumping process has been reaped. Expose it as part of the coredump information in struct pidfd_info. After the process has been reaped that info is also available as part of PIDFD_INFO_EXIT's exit_code field. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- fs/pidfs.c | 30 +++++++++++++++++++----------- include/uapi/linux/pidfd.h | 7 +++++-- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/fs/pidfs.c b/fs/pidfs.c index a3b80be3b98b..354ceb2126e7 100644 --- a/fs/pidfs.c +++ b/fs/pidfs.c @@ -41,6 +41,7 @@ void pidfs_get_root(struct path *path) =20 enum pidfs_attr_mask_bits { PIDFS_ATTR_BIT_EXIT =3D 0, + PIDFS_ATTR_BIT_COREDUMP =3D 1, }; =20 struct pidfs_attr { @@ -51,6 +52,7 @@ struct pidfs_attr { __s32 exit_code; }; __u32 coredump_mask; + __u32 coredump_signal; }; =20 static struct rb_root pidfs_ino_tree =3D RB_ROOT; @@ -297,7 +299,8 @@ static __u32 pidfs_coredump_mask(unsigned long mm_flags) PIDFD_INFO_CGROUPID | \ PIDFD_INFO_EXIT | \ PIDFD_INFO_COREDUMP | \ - PIDFD_INFO_SUPPORTED_MASK) + PIDFD_INFO_SUPPORTED_MASK | \ + PIDFD_INFO_COREDUMP_SIGNAL) =20 static long pidfd_info(struct file *file, unsigned int cmd, unsigned long = arg) { @@ -342,9 +345,12 @@ static long pidfd_info(struct file *file, unsigned int= cmd, unsigned long arg) } =20 if (mask & PIDFD_INFO_COREDUMP) { - kinfo.coredump_mask =3D READ_ONCE(attr->coredump_mask); - if (kinfo.coredump_mask) - kinfo.mask |=3D PIDFD_INFO_COREDUMP; + if (test_bit(PIDFS_ATTR_BIT_COREDUMP, &attr->attr_mask)) { + smp_rmb(); + kinfo.mask |=3D PIDFD_INFO_COREDUMP | PIDFD_INFO_COREDUMP_SIGNAL; + kinfo.coredump_mask =3D attr->coredump_mask; + kinfo.coredump_signal =3D attr->coredump_signal; + } } =20 task =3D get_pid_task(pid, PIDTYPE_PID); @@ -370,6 +376,7 @@ static long pidfd_info(struct file *file, unsigned int = cmd, unsigned long arg) =20 kinfo.coredump_mask =3D pidfs_coredump_mask(flags); kinfo.mask |=3D PIDFD_INFO_COREDUMP; + /* No coredump actually took place, so no coredump signal. */ } } =20 @@ -666,20 +673,21 @@ void pidfs_coredump(const struct coredump_params *cpr= m) { struct pid *pid =3D cprm->pid; struct pidfs_attr *attr; - __u32 coredump_mask =3D 0; =20 attr =3D READ_ONCE(pid->attr); =20 VFS_WARN_ON_ONCE(!attr); VFS_WARN_ON_ONCE(attr =3D=3D PIDFS_PID_DEAD); =20 - /* Note how we were coredumped. */ - coredump_mask =3D pidfs_coredump_mask(cprm->mm_flags); - /* Note that we actually did coredump. */ - coredump_mask |=3D PIDFD_COREDUMPED; + /* Note how we were coredumped and that we coredumped. */ + attr->coredump_mask =3D pidfs_coredump_mask(cprm->mm_flags) | + PIDFD_COREDUMPED; /* If coredumping is set to skip we should never end up here. */ - VFS_WARN_ON_ONCE(coredump_mask & PIDFD_COREDUMP_SKIP); - smp_store_release(&attr->coredump_mask, coredump_mask); + VFS_WARN_ON_ONCE(attr->coredump_mask & PIDFD_COREDUMP_SKIP); + /* Expose the signal number that caused the coredump. */ + attr->coredump_signal =3D cprm->siginfo->si_signo; + smp_wmb(); + set_bit(PIDFS_ATTR_BIT_COREDUMP, &attr->attr_mask); } #endif =20 diff --git a/include/uapi/linux/pidfd.h b/include/uapi/linux/pidfd.h index e05caa0e00fe..ea9a6811fc76 100644 --- a/include/uapi/linux/pidfd.h +++ b/include/uapi/linux/pidfd.h @@ -27,6 +27,7 @@ #define PIDFD_INFO_EXIT (1UL << 3) /* Only returned if requested. */ #define PIDFD_INFO_COREDUMP (1UL << 4) /* Only returned if requested. */ #define PIDFD_INFO_SUPPORTED_MASK (1UL << 5) /* Want/got supported mask fl= ags */ +#define PIDFD_INFO_COREDUMP_SIGNAL (1UL << 6) /* Always returned if PIDFD_= INFO_COREDUMP is requested. */ =20 #define PIDFD_INFO_SIZE_VER0 64 /* sizeof first published struct */ #define PIDFD_INFO_SIZE_VER1 72 /* sizeof second published struct */ @@ -94,8 +95,10 @@ struct pidfd_info { __u32 fsuid; __u32 fsgid; __s32 exit_code; - __u32 coredump_mask; - __u32 __spare1; + struct /* coredump info */ { + __u32 coredump_mask; + __u32 coredump_signal; + }; __u64 supported_mask; /* Mask flags that this kernel supports */ }; =20 --=20 2.47.3 From nobody Sun Feb 8 12:14:52 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1E8C82E0905; Tue, 28 Oct 2025 08:46:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641202; cv=none; b=khvfrRqVsiGSCDEfd/AIN6t371trXIk3DfyUUHNyx+nm4y/h8GVqL/DMKZ8sHoM4a52mpGY1D8sUNplZGVfSGXwFGaeK98u/XMmYZ1qbwf4Mvo2asyH+UOqokKpUeYoAZ5YHVO3QV6W3oopZPn7yQYU5blHen2VmCkWlXWw8zbU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641202; c=relaxed/simple; bh=98RE6pSg3hj80UMXIP92HOFlizvMalrKpuNL5KlJm2s=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Bm/RT7VedNX94pS21NqTLEOwjfsJ9T1GvpWv3cR3jdIDwG9cVRc9ttvN/LwURQZz52WqFwTqkqYcjrZ4aAv4QENDhY5HwItbadPmGi8yyMzLRvXsvZ2AV4CSJP/iTpPdHIrzFSpmNO7ONoeWmSRcRPTnSQI/xrmIk/e8gEZpHzU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=r0yXSNMS; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="r0yXSNMS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D40E1C113D0; Tue, 28 Oct 2025 08:46:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641201; bh=98RE6pSg3hj80UMXIP92HOFlizvMalrKpuNL5KlJm2s=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=r0yXSNMSuP55Jdxh60luUdA6SPfKho92ePJjq4Ekl0YL+n0Jcd69MnqsIHctTRF0/ 77jPeQx861sIDAWBTYl4a21RpdECMW/UB/j9YVeWwHIG+tTvYPKWCfvnC7gRLsBouN 1Ecvxgn16NgijyXVsYwPi7xh0R/hFiOaoqP0amliwPclwlMt5/q/QXi4/kzp/EBTz5 tUouudO1wEo9qCuXCZc8W8N8mFK5eT6fVUx2MceKTSxaSjCh26P+lZM6TLPrAuNBHn ziLYGEKowIzBkp9PNtagsBUpevC/16tlqbR24cODEY/owNo286pAFpwJbT2AyG+/yd ms6y78qlqIEvA== From: Christian Brauner Date: Tue, 28 Oct 2025 09:45:54 +0100 Subject: [PATCH 09/22] selftests/pidfd: update pidfd header Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-9-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=1060; i=brauner@kernel.org; h=from:subject:message-id; bh=98RE6pSg3hj80UMXIP92HOFlizvMalrKpuNL5KlJm2s=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB1sz19zTGnPv4Zn60NyxdwXxwT9vBxb3WzIP1Pg0 X6JCRbnO0pZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACayMpfhf9yykmVaFtlz1xsU 6NvErXmU0TP76DKP/ONNUjFWXw5oxTD8L0/TrxOvt/zrV73oUWfDxprL86rX8Zf8eXj48olMjuN efAA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Include the new defines and members. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- tools/testing/selftests/pidfd/pidfd.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/pidfd/pidfd.h b/tools/testing/selftest= s/pidfd/pidfd.h index f87993def738..d60f10a873bb 100644 --- a/tools/testing/selftests/pidfd/pidfd.h +++ b/tools/testing/selftests/pidfd/pidfd.h @@ -148,6 +148,14 @@ #define PIDFD_INFO_COREDUMP (1UL << 4) #endif =20 +#ifndef PIDFD_INFO_SUPPORTED_MASK +#define PIDFD_INFO_SUPPORTED_MASK (1UL << 5) +#endif + +#ifndef PIDFD_INFO_COREDUMP_SIGNAL +#define PIDFD_INFO_COREDUMP_SIGNAL (1UL << 6) +#endif + #ifndef PIDFD_COREDUMPED #define PIDFD_COREDUMPED (1U << 0) /* Did crash and... */ #endif @@ -183,8 +191,11 @@ struct pidfd_info { __u32 fsuid; __u32 fsgid; __s32 exit_code; - __u32 coredump_mask; - __u32 __spare1; + struct { + __u32 coredump_mask; + __u32 coredump_signal; + }; + __u64 supported_mask; }; =20 /* --=20 2.47.3 From nobody Sun Feb 8 12:14:52 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E33992E2665; Tue, 28 Oct 2025 08:46:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641206; cv=none; b=jVazlyrRWXvzq5aO7J+Xg5nooDrE/C0mpOLRxsJFGwiHHSISPT3EolfFA/s+1RMyfzvEd5yPZ3vX3kVioIxqVbq72teiXGjbcEtowDHc/yc1n2sYkMMQzSvt2QlJUAjQ0k1M6GRV+jsnLoFTKZdlStq5z23HpWByqxyegW0NBbU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641206; c=relaxed/simple; bh=hhfR84YF5lZTjazsMeCF8Xrlqvbl2cEysbsmUtLrx3s=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=uyFCk6P2rM//GcYB6BQ7NwglX4GgGXtrP9IWbsdC9LuM+0gqpD1LSWdd/8qnAIiXm9IjlWoiVr7xwMY7mHsAKJRIt6uxv1MpVfK+9bfYa2V7+SaRc+u7HjPq/v777tnk4kY8r7kmxM0zmncPqHepMNKp3XLzWsKd6RMG5aQCMmI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DVf0g1Aj; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DVf0g1Aj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 31A32C4CEE7; Tue, 28 Oct 2025 08:46:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641205; bh=hhfR84YF5lZTjazsMeCF8Xrlqvbl2cEysbsmUtLrx3s=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=DVf0g1Aj/lcgvXRH2S7/oytpHkW7+MGxwzeyVWxBsxjqwSoCVXIzWKJb9ucnugVaq kKUzsW7p8nU1ps6B0oahs3dwXiCxAu0clV3UUoFH7rnOfMWF0XRhCqeu76C+9/0xGO RpAMZLqXUs2FiB+dJ3uunvRgu7jlJLn34gjV25hldv4UyU8rh65us5Xerf5j8kazbH LQwxWrofsolk+buB4n7JGPHaH7OsXvPF85ykmYfqDlKDLLOIbUroqUV2GKzpZ1Pcwp trGxHdvX8YGs6zo0zqVzBQB8EChyKspxNWipiqreuFx/kcCKw0ZWRRhpl/QGWKvZcm iksQJO/Xvdk7g== From: Christian Brauner Date: Tue, 28 Oct 2025 09:45:55 +0100 Subject: [PATCH 10/22] selftests/pidfd: add first supported_mask test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-10-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=2041; i=brauner@kernel.org; h=from:subject:message-id; bh=hhfR84YF5lZTjazsMeCF8Xrlqvbl2cEysbsmUtLrx3s=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB36EHeqVnl/94z2lA6Js/8Pdb6YlS5abc5zOXEn8 yM32+dlHaUsDGJcDLJiiiwO7Sbhcst5KjYbZWrAzGFlAhnCwMUpABPRfsjIMHnVG+tDWWxdD2qC eVQad+ydYnb8ls/ETTYyX82eLWw8uISRYUd7zc4qnt2vTq0/1ML1lWOn5+MXBQduNJ3lXr3y3R7 OLA4A X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Verify that when PIDFD_INFO_SUPPORTED_MASK is requested, the kernel returns the supported_mask field indicating which flags the kernel supports. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- tools/testing/selftests/pidfd/pidfd_info_test.c | 41 +++++++++++++++++++++= ++++ 1 file changed, 41 insertions(+) diff --git a/tools/testing/selftests/pidfd/pidfd_info_test.c b/tools/testin= g/selftests/pidfd/pidfd_info_test.c index a0eb6e81eaa2..b31a0597fbae 100644 --- a/tools/testing/selftests/pidfd/pidfd_info_test.c +++ b/tools/testing/selftests/pidfd/pidfd_info_test.c @@ -690,4 +690,45 @@ TEST_F(pidfd_info, thread_group_exec_thread) EXPECT_EQ(close(pidfd_thread), 0); } =20 +/* + * Test: PIDFD_INFO_SUPPORTED_MASK field + * + * Verify that when PIDFD_INFO_SUPPORTED_MASK is requested, the kernel + * returns the supported_mask field indicating which flags the kernel supp= orts. + */ +TEST(supported_mask_field) +{ + struct pidfd_info info =3D { + .mask =3D PIDFD_INFO_SUPPORTED_MASK, + }; + int pidfd; + pid_t pid; + + pid =3D create_child(&pidfd, 0); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) + pause(); + + /* Request supported_mask field */ + ASSERT_EQ(ioctl(pidfd, PIDFD_GET_INFO, &info), 0); + + /* Verify PIDFD_INFO_SUPPORTED_MASK is set in the reply */ + ASSERT_TRUE(!!(info.mask & PIDFD_INFO_SUPPORTED_MASK)); + + /* Verify supported_mask contains expected flags */ + ASSERT_TRUE(!!(info.supported_mask & PIDFD_INFO_PID)); + ASSERT_TRUE(!!(info.supported_mask & PIDFD_INFO_CREDS)); + ASSERT_TRUE(!!(info.supported_mask & PIDFD_INFO_CGROUPID)); + ASSERT_TRUE(!!(info.supported_mask & PIDFD_INFO_EXIT)); + ASSERT_TRUE(!!(info.supported_mask & PIDFD_INFO_COREDUMP)); + ASSERT_TRUE(!!(info.supported_mask & PIDFD_INFO_SUPPORTED_MASK)); + ASSERT_TRUE(!!(info.supported_mask & PIDFD_INFO_COREDUMP_SIGNAL)); + + /* Clean up */ + sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0); + sys_waitid(P_PIDFD, pidfd, NULL, WEXITED); + close(pidfd); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 12:14:52 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5838E2DAFA1; Tue, 28 Oct 2025 08:46:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641210; cv=none; b=mFkZK1ob1X7wDKAav7mtjcBZh7rHpdH2mn3qaHfAPInEJrMEy8pi8lqUz1HwdDqWROiryDsvDLaF6pMfLVNXVnFUNap0HY40WGwoKvp/0Rd5eenMVonZOAef+B+xK/3CnrCUbY6Ewy3gXzwsKykURhl9/fswFVWUUBxG/mEsQIM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641210; c=relaxed/simple; bh=2e6DA30gxSXi8cjOewZa+j3/ROxol/MC+sx0d2mHTZc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=f5EqtYBiWPGLv/OduoCu4A5ZnKt/qfXK+2xxXyywKUDtK7/IybFK357rsUE2DOBE2KXgYPONsFDvxfrU4i/IOF6GXYjbvADHAPui1I8ncVg40/LBGVWhYJk2LjA13nP2NmHVK2sAeVZr9VSNoBTsiaVTLeaegYiifSvnH9BsNqY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sijCbF9V; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="sijCbF9V" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0BE94C4CEFF; Tue, 28 Oct 2025 08:46:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641210; bh=2e6DA30gxSXi8cjOewZa+j3/ROxol/MC+sx0d2mHTZc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=sijCbF9Vi7FDmoS+XPuM5PQIG8yjIGkWSbyU9T1ArTM9EztOj0XYFcMjWb0O/RB6i V4NG6cJC0SWokwiBiQnhUj8xadr7SgfZhvJI/IpMLdWKXZxjuwhzaN16f7Jzc56lQ9 VRjKjlMw2ksZ08ZYvSIh2q88840wpDpeOnv1ZQpccBYCYj7gNURGwoFw3thkk5wPgH Sdiame94egeioTZgWWpt4URBQ9k07r4uZxMEKQmo9lHTEvCt2EpgDZQT2OyERIDgT3 pK/x4Fd3+i+xZZSG1RpiWf2A+zfONJRf9CHOcqC9G5oSeIPI6x03SsEmA3jhOYJshn jxdOd9+iuZRLQ== From: Christian Brauner Date: Tue, 28 Oct 2025 09:45:56 +0100 Subject: [PATCH 11/22] selftests/pidfd: add second supported_mask test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-11-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=1435; i=brauner@kernel.org; h=from:subject:message-id; bh=2e6DA30gxSXi8cjOewZa+j3/ROxol/MC+sx0d2mHTZc=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB1aeeDoz6KpLzTutFQ85Ziz8zq72A+LEPMdKlfnx 7zYfWfm7I5SFgYxLgZZMUUWh3aTcLnlPBWbjTI1YOawMoEMYeDiFICJJAgz/NOfc831scntbnH5 zQycRkunOsj/FQyaecm/Rir3q5GWrRAjQ9dHtf87D3yNKb75YML95nV+Mo+v28x0XWVkO0PPWP3 oUkYA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Verify that supported_mask is returned even when other fields are requested. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- tools/testing/selftests/pidfd/pidfd_info_test.c | 32 +++++++++++++++++++++= ++++ 1 file changed, 32 insertions(+) diff --git a/tools/testing/selftests/pidfd/pidfd_info_test.c b/tools/testin= g/selftests/pidfd/pidfd_info_test.c index b31a0597fbae..cb5430a2fd75 100644 --- a/tools/testing/selftests/pidfd/pidfd_info_test.c +++ b/tools/testing/selftests/pidfd/pidfd_info_test.c @@ -731,4 +731,36 @@ TEST(supported_mask_field) close(pidfd); } =20 +/* + * Test: PIDFD_INFO_SUPPORTED_MASK always available + * + * Verify that supported_mask is returned even when other fields are reque= sted. + */ +TEST(supported_mask_with_other_fields) +{ + struct pidfd_info info =3D { + .mask =3D PIDFD_INFO_CGROUPID | PIDFD_INFO_SUPPORTED_MASK, + }; + int pidfd; + pid_t pid; + + pid =3D create_child(&pidfd, 0); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) + pause(); + + ASSERT_EQ(ioctl(pidfd, PIDFD_GET_INFO, &info), 0); + + /* Both fields should be present */ + ASSERT_TRUE(!!(info.mask & PIDFD_INFO_CGROUPID)); + ASSERT_TRUE(!!(info.mask & PIDFD_INFO_SUPPORTED_MASK)); + ASSERT_NE(info.supported_mask, 0); + + /* Clean up */ + sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0); + sys_waitid(P_PIDFD, pidfd, NULL, WEXITED); + close(pidfd); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 12:14:52 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C4E792DC788; Tue, 28 Oct 2025 08:46:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641214; cv=none; b=MNbpMsb9kEe6gxKTvFKuuekZbicKMi/F5ktSuzRuWXdfu/lvo9m5gP6KGBVdtDRQwWizpLQRDzRy5aCHh+0L87N1F2mD8RagFOoH4FGkAQcwuDzDIGFoyjF7YfMKabRnSbMlGcnkMljNzHOXBx44boe3zdb4EClaAu8BRC8nHvA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641214; c=relaxed/simple; bh=FwnhSeUpMJ1tAdcg19JI78pH/nDPUL5EgJwp1VH7TuI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=uidHVddt2XEm8pM7+3hiAhpCn4rMsdoOhPtEjGM+k6J6u1w7I+wcBHrAS5s8T4VtKZEi2mYVnU9/MaSf3E4ddvD608Oma1qevinS2yl2XNFvpsMH++Hqs5PuyWfZQWvTCN2koQfWhMqvh5RiShHqDtFB1loRRj7DOyBTnjzAMmM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=oGHBIng/; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="oGHBIng/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6ABF3C4CEE7; Tue, 28 Oct 2025 08:46:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641214; bh=FwnhSeUpMJ1tAdcg19JI78pH/nDPUL5EgJwp1VH7TuI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=oGHBIng/5HNz/DCg0bWmDJN/xaWWqH1H+MPJigI/HhZeMuQlLHdBwStlKjePkBi/K G4Ir1a44yomFy+XbJqVSd+qlfWJJgwhsurxgwfcUik7GIkwlIC54G4rV/U8JQb7pAB pS9RvisBNCQzFnmTiAWoR7dJyIb6KRdNxmQ9JeTmRzwveyqN7gOAFtiW8ZBtaZ1AkK /clTlHNWA8EbZogfLWZj6CEApIwCtf4vAvUh4ejUzVXirZZtqEkPVYCEaTY1bKyedL i2dE5R/IWad3P9Og1BZIll6GBlqzxudIHWRhObdCDOs9aOW/28kn4Dpgn1CAcTuJtP H1jl39rtLVwtg== From: Christian Brauner Date: Tue, 28 Oct 2025 09:45:57 +0100 Subject: [PATCH 12/22] selftests/coredump: split out common helpers Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-12-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=11051; i=brauner@kernel.org; h=from:subject:message-id; bh=FwnhSeUpMJ1tAdcg19JI78pH/nDPUL5EgJwp1VH7TuI=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB0yuD1jtunC0Ba5tes2npGd75Ui+9dtjXjn9PuTr R8sustV1VHKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjAR7+OMDCccpAwj+F7Ubp5+ 6Gly7b8idYWws/bd8w2a3wnUf6m88pmRYVMh695vsbeZWlWWaNR63U/73HKone1A76Q1OnxmKcy 67AA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 into separate files. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- tools/testing/selftests/coredump/coredump_test.h | 59 ++++ .../selftests/coredump/coredump_test_helpers.c | 340 +++++++++++++++++= ++++ 2 files changed, 399 insertions(+) diff --git a/tools/testing/selftests/coredump/coredump_test.h b/tools/testi= ng/selftests/coredump/coredump_test.h new file mode 100644 index 000000000000..ed47f01fa53c --- /dev/null +++ b/tools/testing/selftests/coredump/coredump_test.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __COREDUMP_TEST_H +#define __COREDUMP_TEST_H + +#include +#include +#include + +#include "../kselftest_harness.h" +#include "../pidfd/pidfd.h" + +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif + +#define NUM_THREAD_SPAWN 128 + +/* Coredump fixture */ +FIXTURE(coredump) +{ + char original_core_pattern[256]; + pid_t pid_coredump_server; + int fd_tmpfs_detached; +}; + +/* Shared helper function declarations */ +void *do_nothing(void *arg); +void crashing_child(void); +int create_detached_tmpfs(void); +int create_and_listen_unix_socket(const char *path); +bool set_core_pattern(const char *pattern); +int get_peer_pidfd(int fd); +bool get_pidfd_info(int fd_peer_pidfd, struct pidfd_info *info); + +/* Inline helper that uses harness types */ +static inline void wait_and_check_coredump_server(pid_t pid_coredump_serve= r, + struct __test_metadata *const _metadata, + FIXTURE_DATA(coredump) *self) +{ + int status; + waitpid(pid_coredump_server, &status, 0); + self->pid_coredump_server =3D -ESRCH; + ASSERT_TRUE(WIFEXITED(status)); + ASSERT_EQ(WEXITSTATUS(status), 0); +} + +/* Protocol helper function declarations */ +ssize_t recv_marker(int fd); +bool read_marker(int fd, enum coredump_mark mark); +bool read_coredump_req(int fd, struct coredump_req *req); +bool send_coredump_ack(int fd, const struct coredump_req *req, + __u64 mask, size_t size_ack); +bool check_coredump_req(const struct coredump_req *req, size_t min_size, + __u64 required_mask); +int open_coredump_tmpfile(int fd_tmpfs_detached); +void process_coredump_worker(int fd_coredump, int fd_peer_pidfd, int fd_co= re_file); + +#endif /* __COREDUMP_TEST_H */ diff --git a/tools/testing/selftests/coredump/coredump_test_helpers.c b/too= ls/testing/selftests/coredump/coredump_test_helpers.c new file mode 100644 index 000000000000..7512a8ef73d3 --- /dev/null +++ b/tools/testing/selftests/coredump/coredump_test_helpers.c @@ -0,0 +1,340 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../filesystems/wrappers.h" +#include "../pidfd/pidfd.h" + +/* Forward declarations to avoid including harness header */ +struct __test_metadata; + +/* Match the fixture definition from coredump_test.h */ +struct _fixture_coredump_data { + char original_core_pattern[256]; + pid_t pid_coredump_server; + int fd_tmpfs_detached; +}; + +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif + +#define NUM_THREAD_SPAWN 128 + +void *do_nothing(void *arg) +{ + (void)arg; + while (1) + pause(); + + return NULL; +} + +void crashing_child(void) +{ + pthread_t thread; + int i; + + for (i =3D 0; i < NUM_THREAD_SPAWN; ++i) + pthread_create(&thread, NULL, do_nothing, NULL); + + /* crash on purpose */ + i =3D *(int *)NULL; +} + +int create_detached_tmpfs(void) +{ + int fd_context, fd_tmpfs; + + fd_context =3D sys_fsopen("tmpfs", 0); + if (fd_context < 0) + return -1; + + if (sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0) < 0) + return -1; + + fd_tmpfs =3D sys_fsmount(fd_context, 0, 0); + close(fd_context); + return fd_tmpfs; +} + +int create_and_listen_unix_socket(const char *path) +{ + struct sockaddr_un addr =3D { + .sun_family =3D AF_UNIX, + }; + assert(strlen(path) < sizeof(addr.sun_path) - 1); + strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1); + size_t addr_len =3D + offsetof(struct sockaddr_un, sun_path) + strlen(path) + 1; + int fd, ret; + + fd =3D socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (fd < 0) + goto out; + + ret =3D bind(fd, (const struct sockaddr *)&addr, addr_len); + if (ret < 0) + goto out; + + ret =3D listen(fd, 128); + if (ret < 0) + goto out; + + return fd; + +out: + if (fd >=3D 0) + close(fd); + return -1; +} + +bool set_core_pattern(const char *pattern) +{ + int fd; + ssize_t ret; + + fd =3D open("/proc/sys/kernel/core_pattern", O_WRONLY | O_CLOEXEC); + if (fd < 0) + return false; + + ret =3D write(fd, pattern, strlen(pattern)); + close(fd); + if (ret < 0) + return false; + + fprintf(stderr, "Set core_pattern to '%s' | %zu =3D=3D %zu\n", pattern, r= et, strlen(pattern)); + return ret =3D=3D strlen(pattern); +} + +int get_peer_pidfd(int fd) +{ + int fd_peer_pidfd; + socklen_t fd_peer_pidfd_len =3D sizeof(fd_peer_pidfd); + int ret =3D getsockopt(fd, SOL_SOCKET, SO_PEERPIDFD, &fd_peer_pidfd, + &fd_peer_pidfd_len); + if (ret < 0) { + fprintf(stderr, "%m - Failed to retrieve peer pidfd for coredump socket = connection\n"); + return -1; + } + return fd_peer_pidfd; +} + +bool get_pidfd_info(int fd_peer_pidfd, struct pidfd_info *info) +{ + memset(info, 0, sizeof(*info)); + info->mask =3D PIDFD_INFO_EXIT | PIDFD_INFO_COREDUMP | PIDFD_INFO_COREDUM= P_SIGNAL; + return ioctl(fd_peer_pidfd, PIDFD_GET_INFO, info) =3D=3D 0; +} + +/* Protocol helper functions */ + +ssize_t recv_marker(int fd) +{ + enum coredump_mark mark =3D COREDUMP_MARK_REQACK; + ssize_t ret; + + ret =3D recv(fd, &mark, sizeof(mark), MSG_WAITALL); + if (ret !=3D sizeof(mark)) + return -1; + + switch (mark) { + case COREDUMP_MARK_REQACK: + fprintf(stderr, "Received marker: ReqAck\n"); + return COREDUMP_MARK_REQACK; + case COREDUMP_MARK_MINSIZE: + fprintf(stderr, "Received marker: MinSize\n"); + return COREDUMP_MARK_MINSIZE; + case COREDUMP_MARK_MAXSIZE: + fprintf(stderr, "Received marker: MaxSize\n"); + return COREDUMP_MARK_MAXSIZE; + case COREDUMP_MARK_UNSUPPORTED: + fprintf(stderr, "Received marker: Unsupported\n"); + return COREDUMP_MARK_UNSUPPORTED; + case COREDUMP_MARK_CONFLICTING: + fprintf(stderr, "Received marker: Conflicting\n"); + return COREDUMP_MARK_CONFLICTING; + default: + fprintf(stderr, "Received unknown marker: %u\n", mark); + break; + } + return -1; +} + +bool read_marker(int fd, enum coredump_mark mark) +{ + ssize_t ret; + + ret =3D recv_marker(fd); + if (ret < 0) + return false; + return ret =3D=3D mark; +} + +bool read_coredump_req(int fd, struct coredump_req *req) +{ + ssize_t ret; + size_t field_size, user_size, ack_size, kernel_size, remaining_size; + + memset(req, 0, sizeof(*req)); + field_size =3D sizeof(req->size); + + /* Peek the size of the coredump request. */ + ret =3D recv(fd, req, field_size, MSG_PEEK | MSG_WAITALL); + if (ret !=3D field_size) + return false; + kernel_size =3D req->size; + + if (kernel_size < COREDUMP_ACK_SIZE_VER0) + return false; + if (kernel_size >=3D PAGE_SIZE) + return false; + + /* Use the minimum of user and kernel size to read the full request. */ + user_size =3D sizeof(struct coredump_req); + ack_size =3D user_size < kernel_size ? user_size : kernel_size; + ret =3D recv(fd, req, ack_size, MSG_WAITALL); + if (ret !=3D ack_size) + return false; + + fprintf(stderr, "Read coredump request with size %u and mask 0x%llx\n", + req->size, (unsigned long long)req->mask); + + if (user_size > kernel_size) + remaining_size =3D user_size - kernel_size; + else + remaining_size =3D kernel_size - user_size; + + if (PAGE_SIZE <=3D remaining_size) + return false; + + /* + * Discard any additional data if the kernel's request was larger than + * what we knew about or cared about. + */ + if (remaining_size) { + char buffer[PAGE_SIZE]; + + ret =3D recv(fd, buffer, sizeof(buffer), MSG_WAITALL); + if (ret !=3D remaining_size) + return false; + fprintf(stderr, "Discarded %zu bytes of data after coredump request\n", = remaining_size); + } + + return true; +} + +bool send_coredump_ack(int fd, const struct coredump_req *req, + __u64 mask, size_t size_ack) +{ + ssize_t ret; + /* + * Wrap struct coredump_ack in a larger struct so we can + * simulate sending to much data to the kernel. + */ + struct large_ack_for_size_testing { + struct coredump_ack ack; + char buffer[PAGE_SIZE]; + } large_ack =3D {}; + + if (!size_ack) + size_ack =3D sizeof(struct coredump_ack) < req->size_ack ? + sizeof(struct coredump_ack) : + req->size_ack; + large_ack.ack.mask =3D mask; + large_ack.ack.size =3D size_ack; + ret =3D send(fd, &large_ack, size_ack, MSG_NOSIGNAL); + if (ret !=3D size_ack) + return false; + + fprintf(stderr, "Sent coredump ack with size %zu and mask 0x%llx\n", + size_ack, (unsigned long long)mask); + return true; +} + +bool check_coredump_req(const struct coredump_req *req, size_t min_size, + __u64 required_mask) +{ + if (req->size < min_size) + return false; + if ((req->mask & required_mask) !=3D required_mask) + return false; + if (req->mask & ~required_mask) + return false; + return true; +} + +int open_coredump_tmpfile(int fd_tmpfs_detached) +{ + return openat(fd_tmpfs_detached, ".", O_TMPFILE | O_RDWR | O_EXCL, 0600); +} + +void process_coredump_worker(int fd_coredump, int fd_peer_pidfd, int fd_co= re_file) +{ + int epfd =3D -1; + int exit_code =3D EXIT_FAILURE; + struct epoll_event ev; + + epfd =3D epoll_create1(0); + if (epfd < 0) + goto out; + + ev.events =3D EPOLLIN | EPOLLRDHUP | EPOLLET; + ev.data.fd =3D fd_coredump; + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd_coredump, &ev) < 0) + goto out; + + for (;;) { + struct epoll_event events[1]; + int n =3D epoll_wait(epfd, events, 1, -1); + if (n < 0) + break; + + if (events[0].events & (EPOLLIN | EPOLLRDHUP)) { + for (;;) { + char buffer[4096]; + ssize_t bytes_read =3D read(fd_coredump, buffer, sizeof(buffer)); + if (bytes_read < 0) { + if (errno =3D=3D EAGAIN || errno =3D=3D EWOULDBLOCK) + break; + goto out; + } + if (bytes_read =3D=3D 0) + goto done; + ssize_t bytes_write =3D write(fd_core_file, buffer, bytes_read); + if (bytes_write !=3D bytes_read) + goto out; + } + } + } + +done: + exit_code =3D EXIT_SUCCESS; +out: + if (epfd >=3D 0) + close(epfd); + if (fd_core_file >=3D 0) + close(fd_core_file); + if (fd_peer_pidfd >=3D 0) + close(fd_peer_pidfd); + if (fd_coredump >=3D 0) + close(fd_coredump); + _exit(exit_code); +} --=20 2.47.3 From nobody Sun Feb 8 12:14:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8B0762DCBFA; Tue, 28 Oct 2025 08:46:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641219; cv=none; b=QQwn9sdC0TrImU0NlEFGMK2Yd2aVusqJ5M4NW82SlOMEaCFyoh/k9qZ+ugxpa/f/sFEqBFyiTe/fok68zGoGnqAwuSsiL1jQilFjDPYfsTX19pBm9mSFCCmFpJUPUF0RBxwa0B0RIEZ+5+Cx6Blv4jov8GMpl/O8gfz9BjgEQKM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641219; c=relaxed/simple; bh=OPfAGeM+ZBgPWvFckqnDtk+EMrhdCUCn6SieSCoZXTo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Xk0K1MAadmE1Rd7l5dR76ds+cE/9Ao8BXykXgad1HCLCFfzAZQXK8jizml+7m1FoZtUjnIrgPAEKps3EcvZMvDujnBDX5MI+Gycd8xk+wNIu2k/GIwEFm+YJCLXvLze9x6gUxY5ZeHkLK8Hmrwi1Xi79eIsPat99qerqbe3Qifs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=laimPlMd; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="laimPlMd" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D0625C113D0; Tue, 28 Oct 2025 08:46:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641219; bh=OPfAGeM+ZBgPWvFckqnDtk+EMrhdCUCn6SieSCoZXTo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=laimPlMdICzkDe/gDJma4tqu+02HWr1EpDGRupewh4m47kHo0e60QDpWbzlZ9fS9w c/LKqPbSszZHtk0obIZ0r2h6tqXIFZkemoSrKEc8qA/4YEsgDIyNyLHaDw1Z51PKA8 /fwm+kvkDGEAGj9zDCoVX1Ynpiq441g1v9biuHtHRO1pjNrD3ETqqXifpiWHB5Nd5L 6paIIE797yuUJ1jEGM2MMU284ndGoneqoHebmLauuZ0kg7HaVpJfZdL5HwUu0ad5gQ qfocy7/5EQB/DXjtyNpdaWHOg4whpvriqFxLP4g9j5e/uzkGNHjJKqjn/cCYo+2+iu deVukgM2/YmXA== From: Christian Brauner Date: Tue, 28 Oct 2025 09:45:58 +0100 Subject: [PATCH 13/22] selftests/coredump: split out coredump socket tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-13-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=92214; i=brauner@kernel.org; h=from:subject:message-id; bh=OPfAGeM+ZBgPWvFckqnDtk+EMrhdCUCn6SieSCoZXTo=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB16982RI6dK+9KJJl8Nw9dhPEn5Kud8snWfTg9ZM dn6wR/ZjlIWBjEuBlkxRRaHdpNwueU8FZuNMjVg5rAygQxh4OIUgIm0fWJkOBeyoT2Uv2f/01ni 0fI++vclHl1qk7bsTPFbxyRjpxXAzsjwpXnJ5/VPlQITHrKHG03Zw3RjYuC+mO/mb7fONamtEc5 lAAA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Split the coredump socket tests into separate files. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- tools/testing/selftests/coredump/.gitignore | 4 + tools/testing/selftests/coredump/Makefile | 8 +- .../coredump/coredump_socket_protocol_test.c | 1315 ++++++++++++++++ .../selftests/coredump/coredump_socket_test.c | 394 +++++ tools/testing/selftests/coredump/stackdump_test.c | 1662 +---------------= ---- 5 files changed, 1722 insertions(+), 1661 deletions(-) diff --git a/tools/testing/selftests/coredump/.gitignore b/tools/testing/se= lftests/coredump/.gitignore new file mode 100644 index 000000000000..097f52db0be9 --- /dev/null +++ b/tools/testing/selftests/coredump/.gitignore @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only +stackdump_test +coredump_socket_test +coredump_socket_protocol_test diff --git a/tools/testing/selftests/coredump/Makefile b/tools/testing/self= tests/coredump/Makefile index 77b3665c73c7..dece1a31d561 100644 --- a/tools/testing/selftests/coredump/Makefile +++ b/tools/testing/selftests/coredump/Makefile @@ -1,7 +1,13 @@ # SPDX-License-Identifier: GPL-2.0-only CFLAGS +=3D -Wall -O0 -g $(KHDR_INCLUDES) $(TOOLS_INCLUDES) =20 -TEST_GEN_PROGS :=3D stackdump_test +TEST_GEN_PROGS :=3D stackdump_test \ + coredump_socket_test \ + coredump_socket_protocol_test TEST_FILES :=3D stackdump =20 include ../lib.mk + +$(OUTPUT)/stackdump_test: coredump_test_helpers.c +$(OUTPUT)/coredump_socket_test: coredump_test_helpers.c +$(OUTPUT)/coredump_socket_protocol_test: coredump_test_helpers.c diff --git a/tools/testing/selftests/coredump/coredump_socket_protocol_test= .c b/tools/testing/selftests/coredump/coredump_socket_protocol_test.c new file mode 100644 index 000000000000..cc7364499c55 --- /dev/null +++ b/tools/testing/selftests/coredump/coredump_socket_protocol_test.c @@ -0,0 +1,1315 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include + +#include "coredump_test.h" + +#define NUM_CRASHING_COREDUMPS 5 + +FIXTURE_SETUP(coredump) +{ + FILE *file; + int ret; + + self->pid_coredump_server =3D -ESRCH; + self->fd_tmpfs_detached =3D -1; + file =3D fopen("/proc/sys/kernel/core_pattern", "r"); + ASSERT_NE(NULL, file); + + ret =3D fread(self->original_core_pattern, 1, sizeof(self->original_core_= pattern), file); + ASSERT_TRUE(ret || feof(file)); + ASSERT_LT(ret, sizeof(self->original_core_pattern)); + + self->original_core_pattern[ret] =3D '\0'; + self->fd_tmpfs_detached =3D create_detached_tmpfs(); + ASSERT_GE(self->fd_tmpfs_detached, 0); + + ret =3D fclose(file); + ASSERT_EQ(0, ret); +} + +FIXTURE_TEARDOWN(coredump) +{ + const char *reason; + FILE *file; + int ret, status; + + if (self->pid_coredump_server > 0) { + kill(self->pid_coredump_server, SIGTERM); + waitpid(self->pid_coredump_server, &status, 0); + } + unlink("/tmp/coredump.file"); + unlink("/tmp/coredump.socket"); + + file =3D fopen("/proc/sys/kernel/core_pattern", "w"); + if (!file) { + reason =3D "Unable to open core_pattern"; + goto fail; + } + + ret =3D fprintf(file, "%s", self->original_core_pattern); + if (ret < 0) { + reason =3D "Unable to write to core_pattern"; + goto fail; + } + + ret =3D fclose(file); + if (ret) { + reason =3D "Unable to close core_pattern"; + goto fail; + } + + if (self->fd_tmpfs_detached >=3D 0) { + ret =3D close(self->fd_tmpfs_detached); + if (ret < 0) { + reason =3D "Unable to close detached tmpfs"; + goto fail; + } + self->fd_tmpfs_detached =3D -1; + } + + return; +fail: + /* This should never happen */ + fprintf(stderr, "Failed to cleanup coredump test: %s\n", reason); +} + +TEST_F(coredump, socket_request_kernel) +{ + int pidfd, ret, status; + pid_t pid, pid_coredump_server; + struct stat st; + struct pidfd_info info =3D {}; + int ipc_sockets[2]; + char c; + + ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); + + ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); + ASSERT_EQ(ret, 0); + + pid_coredump_server =3D fork(); + ASSERT_GE(pid_coredump_server, 0); + if (pid_coredump_server =3D=3D 0) { + struct coredump_req req =3D {}; + int fd_server =3D -1, fd_coredump =3D -1, fd_core_file =3D -1, fd_peer_p= idfd =3D -1; + int exit_code =3D EXIT_FAILURE; + + close(ipc_sockets[0]); + + fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); + if (fd_server < 0) + goto out; + + if (write_nointr(ipc_sockets[1], "1", 1) < 0) + goto out; + + close(ipc_sockets[1]); + + fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); + if (fd_coredump < 0) + goto out; + + fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); + if (fd_peer_pidfd < 0) + goto out; + + if (!get_pidfd_info(fd_peer_pidfd, &info)) + goto out; + + if (!(info.mask & PIDFD_INFO_COREDUMP)) + goto out; + + if (!(info.coredump_mask & PIDFD_COREDUMPED)) + goto out; + + fd_core_file =3D creat("/tmp/coredump.file", 0644); + if (fd_core_file < 0) + goto out; + + if (!read_coredump_req(fd_coredump, &req)) + goto out; + + if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, + COREDUMP_KERNEL | COREDUMP_USERSPACE | + COREDUMP_REJECT | COREDUMP_WAIT)) + goto out; + + if (!send_coredump_ack(fd_coredump, &req, + COREDUMP_KERNEL | COREDUMP_WAIT, 0)) + goto out; + + if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) + goto out; + + for (;;) { + char buffer[4096]; + ssize_t bytes_read, bytes_write; + + bytes_read =3D read(fd_coredump, buffer, sizeof(buffer)); + if (bytes_read < 0) + goto out; + + if (bytes_read =3D=3D 0) + break; + + bytes_write =3D write(fd_core_file, buffer, bytes_read); + if (bytes_read !=3D bytes_write) + goto out; + } + + exit_code =3D EXIT_SUCCESS; +out: + if (fd_core_file >=3D 0) + close(fd_core_file); + if (fd_peer_pidfd >=3D 0) + close(fd_peer_pidfd); + if (fd_coredump >=3D 0) + close(fd_coredump); + if (fd_server >=3D 0) + close(fd_server); + _exit(exit_code); + } + self->pid_coredump_server =3D pid_coredump_server; + + EXPECT_EQ(close(ipc_sockets[1]), 0); + ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); + EXPECT_EQ(close(ipc_sockets[0]), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + if (pid =3D=3D 0) + crashing_child(); + + pidfd =3D sys_pidfd_open(pid, 0); + ASSERT_GE(pidfd, 0); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFSIGNALED(status)); + ASSERT_TRUE(WCOREDUMP(status)); + + ASSERT_TRUE(get_pidfd_info(pidfd, &info)); + ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); + ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); + + wait_and_check_coredump_server(pid_coredump_server, _metadata, self); + + ASSERT_EQ(stat("/tmp/coredump.file", &st), 0); + ASSERT_GT(st.st_size, 0); + system("file /tmp/coredump.file"); +} + +TEST_F(coredump, socket_request_userspace) +{ + int pidfd, ret, status; + pid_t pid, pid_coredump_server; + struct pidfd_info info =3D {}; + int ipc_sockets[2]; + char c; + + ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); + + ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); + ASSERT_EQ(ret, 0); + + pid_coredump_server =3D fork(); + ASSERT_GE(pid_coredump_server, 0); + if (pid_coredump_server =3D=3D 0) { + struct coredump_req req =3D {}; + int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1; + int exit_code =3D EXIT_FAILURE; + + close(ipc_sockets[0]); + + fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); + if (fd_server < 0) + goto out; + + if (write_nointr(ipc_sockets[1], "1", 1) < 0) + goto out; + + close(ipc_sockets[1]); + + fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); + if (fd_coredump < 0) + goto out; + + fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); + if (fd_peer_pidfd < 0) + goto out; + + if (!get_pidfd_info(fd_peer_pidfd, &info)) + goto out; + + if (!(info.mask & PIDFD_INFO_COREDUMP)) + goto out; + + if (!(info.coredump_mask & PIDFD_COREDUMPED)) + goto out; + + if (!read_coredump_req(fd_coredump, &req)) + goto out; + + if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, + COREDUMP_KERNEL | COREDUMP_USERSPACE | + COREDUMP_REJECT | COREDUMP_WAIT)) + goto out; + + if (!send_coredump_ack(fd_coredump, &req, + COREDUMP_USERSPACE | COREDUMP_WAIT, 0)) + goto out; + + if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) + goto out; + + for (;;) { + char buffer[4096]; + ssize_t bytes_read; + + bytes_read =3D read(fd_coredump, buffer, sizeof(buffer)); + if (bytes_read > 0) + goto out; + + if (bytes_read < 0) + goto out; + + if (bytes_read =3D=3D 0) + break; + } + + exit_code =3D EXIT_SUCCESS; +out: + if (fd_peer_pidfd >=3D 0) + close(fd_peer_pidfd); + if (fd_coredump >=3D 0) + close(fd_coredump); + if (fd_server >=3D 0) + close(fd_server); + _exit(exit_code); + } + self->pid_coredump_server =3D pid_coredump_server; + + EXPECT_EQ(close(ipc_sockets[1]), 0); + ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); + EXPECT_EQ(close(ipc_sockets[0]), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + if (pid =3D=3D 0) + crashing_child(); + + pidfd =3D sys_pidfd_open(pid, 0); + ASSERT_GE(pidfd, 0); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFSIGNALED(status)); + ASSERT_TRUE(WCOREDUMP(status)); + + ASSERT_TRUE(get_pidfd_info(pidfd, &info)); + ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); + ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); + + wait_and_check_coredump_server(pid_coredump_server, _metadata, self); +} + +TEST_F(coredump, socket_request_reject) +{ + int pidfd, ret, status; + pid_t pid, pid_coredump_server; + struct pidfd_info info =3D {}; + int ipc_sockets[2]; + char c; + + ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); + + ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); + ASSERT_EQ(ret, 0); + + pid_coredump_server =3D fork(); + ASSERT_GE(pid_coredump_server, 0); + if (pid_coredump_server =3D=3D 0) { + struct coredump_req req =3D {}; + int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1; + int exit_code =3D EXIT_FAILURE; + + close(ipc_sockets[0]); + + fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); + if (fd_server < 0) + goto out; + + if (write_nointr(ipc_sockets[1], "1", 1) < 0) + goto out; + + close(ipc_sockets[1]); + + fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); + if (fd_coredump < 0) + goto out; + + fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); + if (fd_peer_pidfd < 0) + goto out; + + if (!get_pidfd_info(fd_peer_pidfd, &info)) + goto out; + + if (!(info.mask & PIDFD_INFO_COREDUMP)) + goto out; + + if (!(info.coredump_mask & PIDFD_COREDUMPED)) + goto out; + + if (!read_coredump_req(fd_coredump, &req)) + goto out; + + if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, + COREDUMP_KERNEL | COREDUMP_USERSPACE | + COREDUMP_REJECT | COREDUMP_WAIT)) + goto out; + + if (!send_coredump_ack(fd_coredump, &req, + COREDUMP_REJECT | COREDUMP_WAIT, 0)) + goto out; + + if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) + goto out; + + for (;;) { + char buffer[4096]; + ssize_t bytes_read; + + bytes_read =3D read(fd_coredump, buffer, sizeof(buffer)); + if (bytes_read > 0) + goto out; + + if (bytes_read < 0) + goto out; + + if (bytes_read =3D=3D 0) + break; + } + + exit_code =3D EXIT_SUCCESS; +out: + if (fd_peer_pidfd >=3D 0) + close(fd_peer_pidfd); + if (fd_coredump >=3D 0) + close(fd_coredump); + if (fd_server >=3D 0) + close(fd_server); + _exit(exit_code); + } + self->pid_coredump_server =3D pid_coredump_server; + + EXPECT_EQ(close(ipc_sockets[1]), 0); + ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); + EXPECT_EQ(close(ipc_sockets[0]), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + if (pid =3D=3D 0) + crashing_child(); + + pidfd =3D sys_pidfd_open(pid, 0); + ASSERT_GE(pidfd, 0); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFSIGNALED(status)); + ASSERT_FALSE(WCOREDUMP(status)); + + ASSERT_TRUE(get_pidfd_info(pidfd, &info)); + ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); + ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); + + wait_and_check_coredump_server(pid_coredump_server, _metadata, self); +} + +TEST_F(coredump, socket_request_invalid_flag_combination) +{ + int pidfd, ret, status; + pid_t pid, pid_coredump_server; + struct pidfd_info info =3D {}; + int ipc_sockets[2]; + char c; + + ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); + + ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); + ASSERT_EQ(ret, 0); + + pid_coredump_server =3D fork(); + ASSERT_GE(pid_coredump_server, 0); + if (pid_coredump_server =3D=3D 0) { + struct coredump_req req =3D {}; + int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1; + int exit_code =3D EXIT_FAILURE; + + close(ipc_sockets[0]); + + fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); + if (fd_server < 0) + goto out; + + if (write_nointr(ipc_sockets[1], "1", 1) < 0) + goto out; + + close(ipc_sockets[1]); + + fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); + if (fd_coredump < 0) + goto out; + + fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); + if (fd_peer_pidfd < 0) + goto out; + + if (!get_pidfd_info(fd_peer_pidfd, &info)) + goto out; + + if (!(info.mask & PIDFD_INFO_COREDUMP)) + goto out; + + if (!(info.coredump_mask & PIDFD_COREDUMPED)) + goto out; + + if (!read_coredump_req(fd_coredump, &req)) + goto out; + + if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, + COREDUMP_KERNEL | COREDUMP_USERSPACE | + COREDUMP_REJECT | COREDUMP_WAIT)) + goto out; + + if (!send_coredump_ack(fd_coredump, &req, + COREDUMP_KERNEL | COREDUMP_REJECT | COREDUMP_WAIT, 0)) + goto out; + + if (!read_marker(fd_coredump, COREDUMP_MARK_CONFLICTING)) + goto out; + + exit_code =3D EXIT_SUCCESS; +out: + if (fd_peer_pidfd >=3D 0) + close(fd_peer_pidfd); + if (fd_coredump >=3D 0) + close(fd_coredump); + if (fd_server >=3D 0) + close(fd_server); + _exit(exit_code); + } + self->pid_coredump_server =3D pid_coredump_server; + + EXPECT_EQ(close(ipc_sockets[1]), 0); + ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); + EXPECT_EQ(close(ipc_sockets[0]), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + if (pid =3D=3D 0) + crashing_child(); + + pidfd =3D sys_pidfd_open(pid, 0); + ASSERT_GE(pidfd, 0); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFSIGNALED(status)); + ASSERT_FALSE(WCOREDUMP(status)); + + ASSERT_TRUE(get_pidfd_info(pidfd, &info)); + ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); + ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); + + wait_and_check_coredump_server(pid_coredump_server, _metadata, self); +} + +TEST_F(coredump, socket_request_unknown_flag) +{ + int pidfd, ret, status; + pid_t pid, pid_coredump_server; + struct pidfd_info info =3D {}; + int ipc_sockets[2]; + char c; + + ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); + + ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); + ASSERT_EQ(ret, 0); + + pid_coredump_server =3D fork(); + ASSERT_GE(pid_coredump_server, 0); + if (pid_coredump_server =3D=3D 0) { + struct coredump_req req =3D {}; + int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1; + int exit_code =3D EXIT_FAILURE; + + close(ipc_sockets[0]); + + fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); + if (fd_server < 0) + goto out; + + if (write_nointr(ipc_sockets[1], "1", 1) < 0) + goto out; + + close(ipc_sockets[1]); + + fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); + if (fd_coredump < 0) + goto out; + + fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); + if (fd_peer_pidfd < 0) + goto out; + + if (!get_pidfd_info(fd_peer_pidfd, &info)) + goto out; + + if (!(info.mask & PIDFD_INFO_COREDUMP)) + goto out; + + if (!(info.coredump_mask & PIDFD_COREDUMPED)) + goto out; + + if (!read_coredump_req(fd_coredump, &req)) + goto out; + + if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, + COREDUMP_KERNEL | COREDUMP_USERSPACE | + COREDUMP_REJECT | COREDUMP_WAIT)) + goto out; + + if (!send_coredump_ack(fd_coredump, &req, (1ULL << 63), 0)) + goto out; + + if (!read_marker(fd_coredump, COREDUMP_MARK_UNSUPPORTED)) + goto out; + + exit_code =3D EXIT_SUCCESS; +out: + if (fd_peer_pidfd >=3D 0) + close(fd_peer_pidfd); + if (fd_coredump >=3D 0) + close(fd_coredump); + if (fd_server >=3D 0) + close(fd_server); + _exit(exit_code); + } + self->pid_coredump_server =3D pid_coredump_server; + + EXPECT_EQ(close(ipc_sockets[1]), 0); + ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); + EXPECT_EQ(close(ipc_sockets[0]), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + if (pid =3D=3D 0) + crashing_child(); + + pidfd =3D sys_pidfd_open(pid, 0); + ASSERT_GE(pidfd, 0); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFSIGNALED(status)); + ASSERT_FALSE(WCOREDUMP(status)); + + ASSERT_TRUE(get_pidfd_info(pidfd, &info)); + ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); + ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); + + wait_and_check_coredump_server(pid_coredump_server, _metadata, self); +} + +TEST_F(coredump, socket_request_invalid_size_small) +{ + int pidfd, ret, status; + pid_t pid, pid_coredump_server; + struct pidfd_info info =3D {}; + int ipc_sockets[2]; + char c; + + ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); + + ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); + ASSERT_EQ(ret, 0); + + pid_coredump_server =3D fork(); + ASSERT_GE(pid_coredump_server, 0); + if (pid_coredump_server =3D=3D 0) { + struct coredump_req req =3D {}; + int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1; + int exit_code =3D EXIT_FAILURE; + + close(ipc_sockets[0]); + + fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); + if (fd_server < 0) + goto out; + + if (write_nointr(ipc_sockets[1], "1", 1) < 0) + goto out; + + close(ipc_sockets[1]); + + fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); + if (fd_coredump < 0) + goto out; + + fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); + if (fd_peer_pidfd < 0) + goto out; + + if (!get_pidfd_info(fd_peer_pidfd, &info)) + goto out; + + if (!(info.mask & PIDFD_INFO_COREDUMP)) + goto out; + + if (!(info.coredump_mask & PIDFD_COREDUMPED)) + goto out; + + if (!read_coredump_req(fd_coredump, &req)) + goto out; + + if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, + COREDUMP_KERNEL | COREDUMP_USERSPACE | + COREDUMP_REJECT | COREDUMP_WAIT)) + goto out; + + if (!send_coredump_ack(fd_coredump, &req, + COREDUMP_REJECT | COREDUMP_WAIT, + COREDUMP_ACK_SIZE_VER0 / 2)) + goto out; + + if (!read_marker(fd_coredump, COREDUMP_MARK_MINSIZE)) + goto out; + + exit_code =3D EXIT_SUCCESS; +out: + if (fd_peer_pidfd >=3D 0) + close(fd_peer_pidfd); + if (fd_coredump >=3D 0) + close(fd_coredump); + if (fd_server >=3D 0) + close(fd_server); + _exit(exit_code); + } + self->pid_coredump_server =3D pid_coredump_server; + + EXPECT_EQ(close(ipc_sockets[1]), 0); + ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); + EXPECT_EQ(close(ipc_sockets[0]), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + if (pid =3D=3D 0) + crashing_child(); + + pidfd =3D sys_pidfd_open(pid, 0); + ASSERT_GE(pidfd, 0); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFSIGNALED(status)); + ASSERT_FALSE(WCOREDUMP(status)); + + ASSERT_TRUE(get_pidfd_info(pidfd, &info)); + ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); + ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); + + wait_and_check_coredump_server(pid_coredump_server, _metadata, self); +} + +TEST_F(coredump, socket_request_invalid_size_large) +{ + int pidfd, ret, status; + pid_t pid, pid_coredump_server; + struct pidfd_info info =3D {}; + int ipc_sockets[2]; + char c; + + ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); + + ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); + ASSERT_EQ(ret, 0); + + pid_coredump_server =3D fork(); + ASSERT_GE(pid_coredump_server, 0); + if (pid_coredump_server =3D=3D 0) { + struct coredump_req req =3D {}; + int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1; + int exit_code =3D EXIT_FAILURE; + + close(ipc_sockets[0]); + + fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); + if (fd_server < 0) + goto out; + + if (write_nointr(ipc_sockets[1], "1", 1) < 0) + goto out; + + close(ipc_sockets[1]); + + fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); + if (fd_coredump < 0) + goto out; + + fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); + if (fd_peer_pidfd < 0) + goto out; + + if (!get_pidfd_info(fd_peer_pidfd, &info)) + goto out; + + if (!(info.mask & PIDFD_INFO_COREDUMP)) + goto out; + + if (!(info.coredump_mask & PIDFD_COREDUMPED)) + goto out; + + if (!read_coredump_req(fd_coredump, &req)) + goto out; + + if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, + COREDUMP_KERNEL | COREDUMP_USERSPACE | + COREDUMP_REJECT | COREDUMP_WAIT)) + goto out; + + if (!send_coredump_ack(fd_coredump, &req, + COREDUMP_REJECT | COREDUMP_WAIT, + COREDUMP_ACK_SIZE_VER0 + PAGE_SIZE)) + goto out; + + if (!read_marker(fd_coredump, COREDUMP_MARK_MAXSIZE)) + goto out; + + exit_code =3D EXIT_SUCCESS; +out: + if (fd_peer_pidfd >=3D 0) + close(fd_peer_pidfd); + if (fd_coredump >=3D 0) + close(fd_coredump); + if (fd_server >=3D 0) + close(fd_server); + _exit(exit_code); + } + self->pid_coredump_server =3D pid_coredump_server; + + EXPECT_EQ(close(ipc_sockets[1]), 0); + ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); + EXPECT_EQ(close(ipc_sockets[0]), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + if (pid =3D=3D 0) + crashing_child(); + + pidfd =3D sys_pidfd_open(pid, 0); + ASSERT_GE(pidfd, 0); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFSIGNALED(status)); + ASSERT_FALSE(WCOREDUMP(status)); + + ASSERT_TRUE(get_pidfd_info(pidfd, &info)); + ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); + ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); + + wait_and_check_coredump_server(pid_coredump_server, _metadata, self); +} + +/* + * Test: PIDFD_INFO_COREDUMP_SIGNAL via socket coredump with SIGSEGV + * + * Verify that when using socket-based coredump protocol, + * the coredump_signal field is correctly exposed as SIGSEGV. + */ +TEST_F(coredump, socket_coredump_signal_sigsegv) +{ + int pidfd, ret, status; + pid_t pid, pid_coredump_server; + struct pidfd_info info =3D {}; + int ipc_sockets[2]; + char c; + + ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); + + ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); + ASSERT_EQ(ret, 0); + + pid_coredump_server =3D fork(); + ASSERT_GE(pid_coredump_server, 0); + if (pid_coredump_server =3D=3D 0) { + struct coredump_req req =3D {}; + int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1; + int exit_code =3D EXIT_FAILURE; + + close(ipc_sockets[0]); + + fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); + if (fd_server < 0) + goto out; + + if (write_nointr(ipc_sockets[1], "1", 1) < 0) + goto out; + + close(ipc_sockets[1]); + + fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); + if (fd_coredump < 0) + goto out; + + fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); + if (fd_peer_pidfd < 0) + goto out; + + if (!get_pidfd_info(fd_peer_pidfd, &info)) + goto out; + + if (!(info.mask & PIDFD_INFO_COREDUMP)) + goto out; + + if (!(info.coredump_mask & PIDFD_COREDUMPED)) + goto out; + + /* Verify coredump_signal is available and correct */ + if (!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)) + goto out; + + if (info.coredump_signal !=3D SIGSEGV) + goto out; + + if (!read_coredump_req(fd_coredump, &req)) + goto out; + + if (!send_coredump_ack(fd_coredump, &req, + COREDUMP_REJECT | COREDUMP_WAIT, 0)) + goto out; + + if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) + goto out; + + exit_code =3D EXIT_SUCCESS; +out: + if (fd_peer_pidfd >=3D 0) + close(fd_peer_pidfd); + if (fd_coredump >=3D 0) + close(fd_coredump); + if (fd_server >=3D 0) + close(fd_server); + _exit(exit_code); + } + self->pid_coredump_server =3D pid_coredump_server; + + EXPECT_EQ(close(ipc_sockets[1]), 0); + ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); + EXPECT_EQ(close(ipc_sockets[0]), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + if (pid =3D=3D 0) + crashing_child(); + + pidfd =3D sys_pidfd_open(pid, 0); + ASSERT_GE(pidfd, 0); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFSIGNALED(status)); + ASSERT_EQ(WTERMSIG(status), SIGSEGV); + + ASSERT_TRUE(get_pidfd_info(pidfd, &info)); + ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP)); + ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)); + ASSERT_EQ(info.coredump_signal, SIGSEGV); + + wait_and_check_coredump_server(pid_coredump_server, _metadata, self); +} + +/* + * Test: PIDFD_INFO_COREDUMP_SIGNAL via socket coredump with SIGABRT + * + * Verify that when using socket-based coredump protocol, + * the coredump_signal field is correctly exposed as SIGABRT. + */ +TEST_F(coredump, socket_coredump_signal_sigabrt) +{ + int pidfd, ret, status; + pid_t pid, pid_coredump_server; + struct pidfd_info info =3D {}; + int ipc_sockets[2]; + char c; + + ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); + + ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); + ASSERT_EQ(ret, 0); + + pid_coredump_server =3D fork(); + ASSERT_GE(pid_coredump_server, 0); + if (pid_coredump_server =3D=3D 0) { + struct coredump_req req =3D {}; + int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1; + int exit_code =3D EXIT_FAILURE; + + close(ipc_sockets[0]); + + fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); + if (fd_server < 0) + goto out; + + if (write_nointr(ipc_sockets[1], "1", 1) < 0) + goto out; + + close(ipc_sockets[1]); + + fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); + if (fd_coredump < 0) + goto out; + + fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); + if (fd_peer_pidfd < 0) + goto out; + + if (!get_pidfd_info(fd_peer_pidfd, &info)) + goto out; + + if (!(info.mask & PIDFD_INFO_COREDUMP)) + goto out; + + if (!(info.coredump_mask & PIDFD_COREDUMPED)) + goto out; + + /* Verify coredump_signal is available and correct */ + if (!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)) + goto out; + + if (info.coredump_signal !=3D SIGABRT) + goto out; + + if (!read_coredump_req(fd_coredump, &req)) + goto out; + + if (!send_coredump_ack(fd_coredump, &req, + COREDUMP_REJECT | COREDUMP_WAIT, 0)) + goto out; + + if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) + goto out; + + exit_code =3D EXIT_SUCCESS; +out: + if (fd_peer_pidfd >=3D 0) + close(fd_peer_pidfd); + if (fd_coredump >=3D 0) + close(fd_coredump); + if (fd_server >=3D 0) + close(fd_server); + _exit(exit_code); + } + self->pid_coredump_server =3D pid_coredump_server; + + EXPECT_EQ(close(ipc_sockets[1]), 0); + ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); + EXPECT_EQ(close(ipc_sockets[0]), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + if (pid =3D=3D 0) + abort(); + + pidfd =3D sys_pidfd_open(pid, 0); + ASSERT_GE(pidfd, 0); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFSIGNALED(status)); + ASSERT_EQ(WTERMSIG(status), SIGABRT); + + ASSERT_TRUE(get_pidfd_info(pidfd, &info)); + ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP)); + ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)); + ASSERT_EQ(info.coredump_signal, SIGABRT); + + wait_and_check_coredump_server(pid_coredump_server, _metadata, self); +} + +TEST_F_TIMEOUT(coredump, socket_multiple_crashing_coredumps, 500) +{ + int pidfd[NUM_CRASHING_COREDUMPS], status[NUM_CRASHING_COREDUMPS]; + pid_t pid[NUM_CRASHING_COREDUMPS], pid_coredump_server; + struct pidfd_info info =3D {}; + int ipc_sockets[2]; + char c; + + ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets)= , 0); + + pid_coredump_server =3D fork(); + ASSERT_GE(pid_coredump_server, 0); + if (pid_coredump_server =3D=3D 0) { + int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1, fd_core_= file =3D -1; + int exit_code =3D EXIT_FAILURE; + struct coredump_req req =3D {}; + + close(ipc_sockets[0]); + fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); + if (fd_server < 0) { + fprintf(stderr, "Failed to create and listen on unix socket\n"); + goto out; + } + + if (write_nointr(ipc_sockets[1], "1", 1) < 0) { + fprintf(stderr, "Failed to notify parent via ipc socket\n"); + goto out; + } + close(ipc_sockets[1]); + + for (int i =3D 0; i < NUM_CRASHING_COREDUMPS; i++) { + fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); + if (fd_coredump < 0) { + fprintf(stderr, "accept4 failed: %m\n"); + goto out; + } + + fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); + if (fd_peer_pidfd < 0) { + fprintf(stderr, "get_peer_pidfd failed for fd %d: %m\n", fd_coredump); + goto out; + } + + if (!get_pidfd_info(fd_peer_pidfd, &info)) { + fprintf(stderr, "get_pidfd_info failed for fd %d\n", fd_peer_pidfd); + goto out; + } + + if (!(info.mask & PIDFD_INFO_COREDUMP)) { + fprintf(stderr, "pidfd info missing PIDFD_INFO_COREDUMP for fd %d\n", = fd_peer_pidfd); + goto out; + } + if (!(info.coredump_mask & PIDFD_COREDUMPED)) { + fprintf(stderr, "pidfd info missing PIDFD_COREDUMPED for fd %d\n", fd_= peer_pidfd); + goto out; + } + + if (!read_coredump_req(fd_coredump, &req)) { + fprintf(stderr, "read_coredump_req failed for fd %d\n", fd_coredump); + goto out; + } + + if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, + COREDUMP_KERNEL | COREDUMP_USERSPACE | + COREDUMP_REJECT | COREDUMP_WAIT)) { + fprintf(stderr, "check_coredump_req failed for fd %d\n", fd_coredump); + goto out; + } + + if (!send_coredump_ack(fd_coredump, &req, + COREDUMP_KERNEL | COREDUMP_WAIT, 0)) { + fprintf(stderr, "send_coredump_ack failed for fd %d\n", fd_coredump); + goto out; + } + + if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) { + fprintf(stderr, "read_marker failed for fd %d\n", fd_coredump); + goto out; + } + + fd_core_file =3D open_coredump_tmpfile(self->fd_tmpfs_detached); + if (fd_core_file < 0) { + fprintf(stderr, "%m - open_coredump_tmpfile failed for fd %d\n", fd_co= redump); + goto out; + } + + for (;;) { + char buffer[4096]; + ssize_t bytes_read, bytes_write; + + bytes_read =3D read(fd_coredump, buffer, sizeof(buffer)); + if (bytes_read < 0) { + fprintf(stderr, "read failed for fd %d: %m\n", fd_coredump); + goto out; + } + + if (bytes_read =3D=3D 0) + break; + + bytes_write =3D write(fd_core_file, buffer, bytes_read); + if (bytes_read !=3D bytes_write) { + fprintf(stderr, "write failed for fd %d: %m\n", fd_core_file); + goto out; + } + } + + close(fd_core_file); + close(fd_peer_pidfd); + close(fd_coredump); + fd_peer_pidfd =3D -1; + fd_coredump =3D -1; + } + + exit_code =3D EXIT_SUCCESS; +out: + if (fd_core_file >=3D 0) + close(fd_core_file); + if (fd_peer_pidfd >=3D 0) + close(fd_peer_pidfd); + if (fd_coredump >=3D 0) + close(fd_coredump); + if (fd_server >=3D 0) + close(fd_server); + _exit(exit_code); + } + self->pid_coredump_server =3D pid_coredump_server; + + EXPECT_EQ(close(ipc_sockets[1]), 0); + ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); + EXPECT_EQ(close(ipc_sockets[0]), 0); + + for (int i =3D 0; i < NUM_CRASHING_COREDUMPS; i++) { + pid[i] =3D fork(); + ASSERT_GE(pid[i], 0); + if (pid[i] =3D=3D 0) + crashing_child(); + pidfd[i] =3D sys_pidfd_open(pid[i], 0); + ASSERT_GE(pidfd[i], 0); + } + + for (int i =3D 0; i < NUM_CRASHING_COREDUMPS; i++) { + waitpid(pid[i], &status[i], 0); + ASSERT_TRUE(WIFSIGNALED(status[i])); + ASSERT_TRUE(WCOREDUMP(status[i])); + } + + for (int i =3D 0; i < NUM_CRASHING_COREDUMPS; i++) { + info.mask =3D PIDFD_INFO_EXIT | PIDFD_INFO_COREDUMP; + ASSERT_EQ(ioctl(pidfd[i], PIDFD_GET_INFO, &info), 0); + ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); + ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); + } + + wait_and_check_coredump_server(pid_coredump_server, _metadata, self); +} + +TEST_F_TIMEOUT(coredump, socket_multiple_crashing_coredumps_epoll_workers,= 500) +{ + int pidfd[NUM_CRASHING_COREDUMPS], status[NUM_CRASHING_COREDUMPS]; + pid_t pid[NUM_CRASHING_COREDUMPS], pid_coredump_server, worker_pids[NUM_C= RASHING_COREDUMPS]; + struct pidfd_info info =3D {}; + int ipc_sockets[2]; + char c; + + ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets)= , 0); + + pid_coredump_server =3D fork(); + ASSERT_GE(pid_coredump_server, 0); + if (pid_coredump_server =3D=3D 0) { + int fd_server =3D -1, exit_code =3D EXIT_FAILURE, n_conns =3D 0; + fd_server =3D -1; + exit_code =3D EXIT_FAILURE; + n_conns =3D 0; + close(ipc_sockets[0]); + fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); + if (fd_server < 0) + goto out; + + if (write_nointr(ipc_sockets[1], "1", 1) < 0) + goto out; + close(ipc_sockets[1]); + + while (n_conns < NUM_CRASHING_COREDUMPS) { + int fd_coredump =3D -1, fd_peer_pidfd =3D -1, fd_core_file =3D -1; + struct coredump_req req =3D {}; + fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); + if (fd_coredump < 0) { + if (errno =3D=3D EAGAIN || errno =3D=3D EWOULDBLOCK) + continue; + goto out; + } + fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); + if (fd_peer_pidfd < 0) + goto out; + if (!get_pidfd_info(fd_peer_pidfd, &info)) + goto out; + if (!(info.mask & PIDFD_INFO_COREDUMP) || !(info.coredump_mask & PIDFD_= COREDUMPED)) + goto out; + if (!read_coredump_req(fd_coredump, &req)) + goto out; + if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, + COREDUMP_KERNEL | COREDUMP_USERSPACE | + COREDUMP_REJECT | COREDUMP_WAIT)) + goto out; + if (!send_coredump_ack(fd_coredump, &req, COREDUMP_KERNEL | COREDUMP_WA= IT, 0)) + goto out; + if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) + goto out; + fd_core_file =3D open_coredump_tmpfile(self->fd_tmpfs_detached); + if (fd_core_file < 0) + goto out; + pid_t worker =3D fork(); + if (worker =3D=3D 0) { + close(fd_server); + process_coredump_worker(fd_coredump, fd_peer_pidfd, fd_core_file); + } + worker_pids[n_conns] =3D worker; + if (fd_coredump >=3D 0) + close(fd_coredump); + if (fd_peer_pidfd >=3D 0) + close(fd_peer_pidfd); + if (fd_core_file >=3D 0) + close(fd_core_file); + n_conns++; + } + exit_code =3D EXIT_SUCCESS; +out: + if (fd_server >=3D 0) + close(fd_server); + + // Reap all worker processes + for (int i =3D 0; i < n_conns; i++) { + int wstatus; + if (waitpid(worker_pids[i], &wstatus, 0) < 0) { + fprintf(stderr, "Failed to wait for worker %d: %m\n", worker_pids[i]); + } else if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) !=3D EXIT_SUCCESS= ) { + fprintf(stderr, "Worker %d exited with error code %d\n", worker_pids[i= ], WEXITSTATUS(wstatus)); + exit_code =3D EXIT_FAILURE; + } + } + + _exit(exit_code); + } + self->pid_coredump_server =3D pid_coredump_server; + + EXPECT_EQ(close(ipc_sockets[1]), 0); + ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); + EXPECT_EQ(close(ipc_sockets[0]), 0); + + for (int i =3D 0; i < NUM_CRASHING_COREDUMPS; i++) { + pid[i] =3D fork(); + ASSERT_GE(pid[i], 0); + if (pid[i] =3D=3D 0) + crashing_child(); + pidfd[i] =3D sys_pidfd_open(pid[i], 0); + ASSERT_GE(pidfd[i], 0); + } + + for (int i =3D 0; i < NUM_CRASHING_COREDUMPS; i++) { + ASSERT_GE(waitpid(pid[i], &status[i], 0), 0); + ASSERT_TRUE(WIFSIGNALED(status[i])); + ASSERT_TRUE(WCOREDUMP(status[i])); + } + + for (int i =3D 0; i < NUM_CRASHING_COREDUMPS; i++) { + info.mask =3D PIDFD_INFO_EXIT | PIDFD_INFO_COREDUMP; + ASSERT_EQ(ioctl(pidfd[i], PIDFD_GET_INFO, &info), 0); + ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); + ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); + } + + wait_and_check_coredump_server(pid_coredump_server, _metadata, self); +} + +TEST_HARNESS_MAIN diff --git a/tools/testing/selftests/coredump/coredump_socket_test.c b/tool= s/testing/selftests/coredump/coredump_socket_test.c new file mode 100644 index 000000000000..d5ad0e696ab3 --- /dev/null +++ b/tools/testing/selftests/coredump/coredump_socket_test.c @@ -0,0 +1,394 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include + +#include "coredump_test.h" + +FIXTURE_SETUP(coredump) +{ + FILE *file; + int ret; + + self->pid_coredump_server =3D -ESRCH; + self->fd_tmpfs_detached =3D -1; + file =3D fopen("/proc/sys/kernel/core_pattern", "r"); + ASSERT_NE(NULL, file); + + ret =3D fread(self->original_core_pattern, 1, sizeof(self->original_core_= pattern), file); + ASSERT_TRUE(ret || feof(file)); + ASSERT_LT(ret, sizeof(self->original_core_pattern)); + + self->original_core_pattern[ret] =3D '\0'; + self->fd_tmpfs_detached =3D create_detached_tmpfs(); + ASSERT_GE(self->fd_tmpfs_detached, 0); + + ret =3D fclose(file); + ASSERT_EQ(0, ret); +} + +FIXTURE_TEARDOWN(coredump) +{ + const char *reason; + FILE *file; + int ret, status; + + if (self->pid_coredump_server > 0) { + kill(self->pid_coredump_server, SIGTERM); + waitpid(self->pid_coredump_server, &status, 0); + } + unlink("/tmp/coredump.file"); + unlink("/tmp/coredump.socket"); + + file =3D fopen("/proc/sys/kernel/core_pattern", "w"); + if (!file) { + reason =3D "Unable to open core_pattern"; + goto fail; + } + + ret =3D fprintf(file, "%s", self->original_core_pattern); + if (ret < 0) { + reason =3D "Unable to write to core_pattern"; + goto fail; + } + + ret =3D fclose(file); + if (ret) { + reason =3D "Unable to close core_pattern"; + goto fail; + } + + if (self->fd_tmpfs_detached >=3D 0) { + ret =3D close(self->fd_tmpfs_detached); + if (ret < 0) { + reason =3D "Unable to close detached tmpfs"; + goto fail; + } + self->fd_tmpfs_detached =3D -1; + } + + return; +fail: + /* This should never happen */ + fprintf(stderr, "Failed to cleanup coredump test: %s\n", reason); +} + +TEST_F(coredump, socket) +{ + int pidfd, ret, status; + pid_t pid, pid_coredump_server; + struct stat st; + struct pidfd_info info =3D {}; + int ipc_sockets[2]; + char c; + + ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket")); + + ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); + ASSERT_EQ(ret, 0); + + pid_coredump_server =3D fork(); + ASSERT_GE(pid_coredump_server, 0); + if (pid_coredump_server =3D=3D 0) { + int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1, fd_core_= file =3D -1; + int exit_code =3D EXIT_FAILURE; + + close(ipc_sockets[0]); + + fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); + if (fd_server < 0) + goto out; + + if (write_nointr(ipc_sockets[1], "1", 1) < 0) + goto out; + + close(ipc_sockets[1]); + + fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); + if (fd_coredump < 0) + goto out; + + fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); + if (fd_peer_pidfd < 0) + goto out; + + if (!get_pidfd_info(fd_peer_pidfd, &info)) + goto out; + + if (!(info.mask & PIDFD_INFO_COREDUMP)) + goto out; + + if (!(info.coredump_mask & PIDFD_COREDUMPED)) + goto out; + + fd_core_file =3D creat("/tmp/coredump.file", 0644); + if (fd_core_file < 0) + goto out; + + for (;;) { + char buffer[4096]; + ssize_t bytes_read, bytes_write; + + bytes_read =3D read(fd_coredump, buffer, sizeof(buffer)); + if (bytes_read < 0) + goto out; + + if (bytes_read =3D=3D 0) + break; + + bytes_write =3D write(fd_core_file, buffer, bytes_read); + if (bytes_read !=3D bytes_write) + goto out; + } + + exit_code =3D EXIT_SUCCESS; +out: + if (fd_core_file >=3D 0) + close(fd_core_file); + if (fd_peer_pidfd >=3D 0) + close(fd_peer_pidfd); + if (fd_coredump >=3D 0) + close(fd_coredump); + if (fd_server >=3D 0) + close(fd_server); + _exit(exit_code); + } + self->pid_coredump_server =3D pid_coredump_server; + + EXPECT_EQ(close(ipc_sockets[1]), 0); + ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); + EXPECT_EQ(close(ipc_sockets[0]), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + if (pid =3D=3D 0) + crashing_child(); + + pidfd =3D sys_pidfd_open(pid, 0); + ASSERT_GE(pidfd, 0); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFSIGNALED(status)); + ASSERT_TRUE(WCOREDUMP(status)); + + ASSERT_TRUE(get_pidfd_info(pidfd, &info)); + ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); + ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); + + wait_and_check_coredump_server(pid_coredump_server, _metadata, self); + + ASSERT_EQ(stat("/tmp/coredump.file", &st), 0); + ASSERT_GT(st.st_size, 0); +} + +TEST_F(coredump, socket_detect_userspace_client) +{ + int pidfd, ret, status; + pid_t pid, pid_coredump_server; + struct stat st; + struct pidfd_info info =3D {}; + int ipc_sockets[2]; + char c; + + ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket")); + + ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); + ASSERT_EQ(ret, 0); + + pid_coredump_server =3D fork(); + ASSERT_GE(pid_coredump_server, 0); + if (pid_coredump_server =3D=3D 0) { + int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1; + int exit_code =3D EXIT_FAILURE; + + close(ipc_sockets[0]); + + fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); + if (fd_server < 0) + goto out; + + if (write_nointr(ipc_sockets[1], "1", 1) < 0) + goto out; + + close(ipc_sockets[1]); + + fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); + if (fd_coredump < 0) + goto out; + + fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); + if (fd_peer_pidfd < 0) + goto out; + + if (!get_pidfd_info(fd_peer_pidfd, &info)) + goto out; + + if (!(info.mask & PIDFD_INFO_COREDUMP)) + goto out; + + if (info.coredump_mask & PIDFD_COREDUMPED) + goto out; + + exit_code =3D EXIT_SUCCESS; +out: + if (fd_peer_pidfd >=3D 0) + close(fd_peer_pidfd); + if (fd_coredump >=3D 0) + close(fd_coredump); + if (fd_server >=3D 0) + close(fd_server); + _exit(exit_code); + } + self->pid_coredump_server =3D pid_coredump_server; + + EXPECT_EQ(close(ipc_sockets[1]), 0); + ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); + EXPECT_EQ(close(ipc_sockets[0]), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + if (pid =3D=3D 0) { + int fd_socket; + ssize_t ret; + const struct sockaddr_un coredump_sk =3D { + .sun_family =3D AF_UNIX, + .sun_path =3D "/tmp/coredump.socket", + }; + size_t coredump_sk_len =3D + offsetof(struct sockaddr_un, sun_path) + + sizeof("/tmp/coredump.socket"); + + fd_socket =3D socket(AF_UNIX, SOCK_STREAM, 0); + if (fd_socket < 0) + _exit(EXIT_FAILURE); + + ret =3D connect(fd_socket, (const struct sockaddr *)&coredump_sk, coredu= mp_sk_len); + if (ret < 0) + _exit(EXIT_FAILURE); + + close(fd_socket); + _exit(EXIT_SUCCESS); + } + + pidfd =3D sys_pidfd_open(pid, 0); + ASSERT_GE(pidfd, 0); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + ASSERT_TRUE(get_pidfd_info(pidfd, &info)); + ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); + ASSERT_EQ((info.coredump_mask & PIDFD_COREDUMPED), 0); + + wait_and_check_coredump_server(pid_coredump_server, _metadata, self); + + ASSERT_NE(stat("/tmp/coredump.file", &st), 0); + ASSERT_EQ(errno, ENOENT); +} + +TEST_F(coredump, socket_enoent) +{ + int pidfd, status; + pid_t pid; + + ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket")); + + pid =3D fork(); + ASSERT_GE(pid, 0); + if (pid =3D=3D 0) + crashing_child(); + + pidfd =3D sys_pidfd_open(pid, 0); + ASSERT_GE(pidfd, 0); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFSIGNALED(status)); + ASSERT_FALSE(WCOREDUMP(status)); +} + +TEST_F(coredump, socket_no_listener) +{ + int pidfd, ret, status; + pid_t pid, pid_coredump_server; + int ipc_sockets[2]; + char c; + const struct sockaddr_un coredump_sk =3D { + .sun_family =3D AF_UNIX, + .sun_path =3D "/tmp/coredump.socket", + }; + size_t coredump_sk_len =3D offsetof(struct sockaddr_un, sun_path) + + sizeof("/tmp/coredump.socket"); + + ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket")); + + ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); + ASSERT_EQ(ret, 0); + + pid_coredump_server =3D fork(); + ASSERT_GE(pid_coredump_server, 0); + if (pid_coredump_server =3D=3D 0) { + int fd_server =3D -1; + int exit_code =3D EXIT_FAILURE; + + close(ipc_sockets[0]); + + fd_server =3D socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (fd_server < 0) + goto out; + + ret =3D bind(fd_server, (const struct sockaddr *)&coredump_sk, coredump_= sk_len); + if (ret < 0) + goto out; + + if (write_nointr(ipc_sockets[1], "1", 1) < 0) + goto out; + + exit_code =3D EXIT_SUCCESS; +out: + if (fd_server >=3D 0) + close(fd_server); + close(ipc_sockets[1]); + _exit(exit_code); + } + self->pid_coredump_server =3D pid_coredump_server; + + EXPECT_EQ(close(ipc_sockets[1]), 0); + ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); + EXPECT_EQ(close(ipc_sockets[0]), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + if (pid =3D=3D 0) + crashing_child(); + + pidfd =3D sys_pidfd_open(pid, 0); + ASSERT_GE(pidfd, 0); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFSIGNALED(status)); + ASSERT_FALSE(WCOREDUMP(status)); + + wait_and_check_coredump_server(pid_coredump_server, _metadata, self); +} + +TEST_F(coredump, socket_invalid_paths) +{ + ASSERT_FALSE(set_core_pattern("@ /tmp/coredump.socket")); + ASSERT_FALSE(set_core_pattern("@/tmp/../coredump.socket")); + ASSERT_FALSE(set_core_pattern("@../coredump.socket")); + ASSERT_FALSE(set_core_pattern("@/tmp/coredump.socket/..")); + ASSERT_FALSE(set_core_pattern("@..")); + + ASSERT_FALSE(set_core_pattern("@@ /tmp/coredump.socket")); + ASSERT_FALSE(set_core_pattern("@@/tmp/../coredump.socket")); + ASSERT_FALSE(set_core_pattern("@@../coredump.socket")); + ASSERT_FALSE(set_core_pattern("@@/tmp/coredump.socket/..")); + ASSERT_FALSE(set_core_pattern("@@..")); + + ASSERT_FALSE(set_core_pattern("@@@/tmp/coredump.socket")); +} + +TEST_HARNESS_MAIN diff --git a/tools/testing/selftests/coredump/stackdump_test.c b/tools/test= ing/selftests/coredump/stackdump_test.c index a4ac80bb1003..c2e895bcc160 100644 --- a/tools/testing/selftests/coredump/stackdump_test.c +++ b/tools/testing/selftests/coredump/stackdump_test.c @@ -23,57 +23,15 @@ #include "../filesystems/wrappers.h" #include "../pidfd/pidfd.h" =20 +#include "coredump_test.h" + #define STACKDUMP_FILE "stack_values" #define STACKDUMP_SCRIPT "stackdump" -#define NUM_THREAD_SPAWN 128 =20 #ifndef PAGE_SIZE #define PAGE_SIZE 4096 #endif =20 -static void *do_nothing(void *) -{ - while (1) - pause(); - - return NULL; -} - -static void crashing_child(void) -{ - pthread_t thread; - int i; - - for (i =3D 0; i < NUM_THREAD_SPAWN; ++i) - pthread_create(&thread, NULL, do_nothing, NULL); - - /* crash on purpose */ - i =3D *(int *)NULL; -} - -FIXTURE(coredump) -{ - char original_core_pattern[256]; - pid_t pid_coredump_server; - int fd_tmpfs_detached; -}; - -static int create_detached_tmpfs(void) -{ - int fd_context, fd_tmpfs; - - fd_context =3D sys_fsopen("tmpfs", 0); - if (fd_context < 0) - return -1; - - if (sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0) < 0) - return -1; - - fd_tmpfs =3D sys_fsmount(fd_context, 0, 0); - close(fd_context); - return fd_tmpfs; -} - FIXTURE_SETUP(coredump) { FILE *file; @@ -208,1620 +166,4 @@ TEST_F_TIMEOUT(coredump, stackdump, 120) fclose(file); } =20 -static int create_and_listen_unix_socket(const char *path) -{ - struct sockaddr_un addr =3D { - .sun_family =3D AF_UNIX, - }; - assert(strlen(path) < sizeof(addr.sun_path) - 1); - strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1); - size_t addr_len =3D - offsetof(struct sockaddr_un, sun_path) + strlen(path) + 1; - int fd, ret; - - fd =3D socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); - if (fd < 0) - goto out; - - ret =3D bind(fd, (const struct sockaddr *)&addr, addr_len); - if (ret < 0) - goto out; - - ret =3D listen(fd, 128); - if (ret < 0) - goto out; - - return fd; - -out: - if (fd >=3D 0) - close(fd); - return -1; -} - -static bool set_core_pattern(const char *pattern) -{ - int fd; - ssize_t ret; - - fd =3D open("/proc/sys/kernel/core_pattern", O_WRONLY | O_CLOEXEC); - if (fd < 0) - return false; - - ret =3D write(fd, pattern, strlen(pattern)); - close(fd); - if (ret < 0) - return false; - - fprintf(stderr, "Set core_pattern to '%s' | %zu =3D=3D %zu\n", pattern, r= et, strlen(pattern)); - return ret =3D=3D strlen(pattern); -} - -static int get_peer_pidfd(int fd) -{ - int fd_peer_pidfd; - socklen_t fd_peer_pidfd_len =3D sizeof(fd_peer_pidfd); - int ret =3D getsockopt(fd, SOL_SOCKET, SO_PEERPIDFD, &fd_peer_pidfd, - &fd_peer_pidfd_len); - if (ret < 0) { - fprintf(stderr, "%m - Failed to retrieve peer pidfd for coredump socket = connection\n"); - return -1; - } - return fd_peer_pidfd; -} - -static bool get_pidfd_info(int fd_peer_pidfd, struct pidfd_info *info) -{ - memset(info, 0, sizeof(*info)); - info->mask =3D PIDFD_INFO_EXIT | PIDFD_INFO_COREDUMP; - return ioctl(fd_peer_pidfd, PIDFD_GET_INFO, info) =3D=3D 0; -} - -static void -wait_and_check_coredump_server(pid_t pid_coredump_server, - struct __test_metadata *const _metadata, - FIXTURE_DATA(coredump)* self) -{ - int status; - waitpid(pid_coredump_server, &status, 0); - self->pid_coredump_server =3D -ESRCH; - ASSERT_TRUE(WIFEXITED(status)); - ASSERT_EQ(WEXITSTATUS(status), 0); -} - -TEST_F(coredump, socket) -{ - int pidfd, ret, status; - pid_t pid, pid_coredump_server; - struct stat st; - struct pidfd_info info =3D {}; - int ipc_sockets[2]; - char c; - - ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket")); - - ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); - ASSERT_EQ(ret, 0); - - pid_coredump_server =3D fork(); - ASSERT_GE(pid_coredump_server, 0); - if (pid_coredump_server =3D=3D 0) { - int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1, fd_core_= file =3D -1; - int exit_code =3D EXIT_FAILURE; - - close(ipc_sockets[0]); - - fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) - goto out; - - if (write_nointr(ipc_sockets[1], "1", 1) < 0) - goto out; - - close(ipc_sockets[1]); - - fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) - goto out; - - fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) - goto out; - - if (!get_pidfd_info(fd_peer_pidfd, &info)) - goto out; - - if (!(info.mask & PIDFD_INFO_COREDUMP)) - goto out; - - if (!(info.coredump_mask & PIDFD_COREDUMPED)) - goto out; - - fd_core_file =3D creat("/tmp/coredump.file", 0644); - if (fd_core_file < 0) - goto out; - - for (;;) { - char buffer[4096]; - ssize_t bytes_read, bytes_write; - - bytes_read =3D read(fd_coredump, buffer, sizeof(buffer)); - if (bytes_read < 0) - goto out; - - if (bytes_read =3D=3D 0) - break; - - bytes_write =3D write(fd_core_file, buffer, bytes_read); - if (bytes_read !=3D bytes_write) - goto out; - } - - exit_code =3D EXIT_SUCCESS; -out: - if (fd_core_file >=3D 0) - close(fd_core_file); - if (fd_peer_pidfd >=3D 0) - close(fd_peer_pidfd); - if (fd_coredump >=3D 0) - close(fd_coredump); - if (fd_server >=3D 0) - close(fd_server); - _exit(exit_code); - } - self->pid_coredump_server =3D pid_coredump_server; - - EXPECT_EQ(close(ipc_sockets[1]), 0); - ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); - EXPECT_EQ(close(ipc_sockets[0]), 0); - - pid =3D fork(); - ASSERT_GE(pid, 0); - if (pid =3D=3D 0) - crashing_child(); - - pidfd =3D sys_pidfd_open(pid, 0); - ASSERT_GE(pidfd, 0); - - waitpid(pid, &status, 0); - ASSERT_TRUE(WIFSIGNALED(status)); - ASSERT_TRUE(WCOREDUMP(status)); - - ASSERT_TRUE(get_pidfd_info(pidfd, &info)); - ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); - ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); - - wait_and_check_coredump_server(pid_coredump_server, _metadata, self); - - ASSERT_EQ(stat("/tmp/coredump.file", &st), 0); - ASSERT_GT(st.st_size, 0); - system("file /tmp/coredump.file"); -} - -TEST_F(coredump, socket_detect_userspace_client) -{ - int pidfd, ret, status; - pid_t pid, pid_coredump_server; - struct stat st; - struct pidfd_info info =3D {}; - int ipc_sockets[2]; - char c; - - ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket")); - - ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); - ASSERT_EQ(ret, 0); - - pid_coredump_server =3D fork(); - ASSERT_GE(pid_coredump_server, 0); - if (pid_coredump_server =3D=3D 0) { - int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1; - int exit_code =3D EXIT_FAILURE; - - close(ipc_sockets[0]); - - fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) - goto out; - - if (write_nointr(ipc_sockets[1], "1", 1) < 0) - goto out; - - close(ipc_sockets[1]); - - fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) - goto out; - - fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) - goto out; - - if (!get_pidfd_info(fd_peer_pidfd, &info)) - goto out; - - if (!(info.mask & PIDFD_INFO_COREDUMP)) - goto out; - - if (info.coredump_mask & PIDFD_COREDUMPED) - goto out; - - exit_code =3D EXIT_SUCCESS; -out: - if (fd_peer_pidfd >=3D 0) - close(fd_peer_pidfd); - if (fd_coredump >=3D 0) - close(fd_coredump); - if (fd_server >=3D 0) - close(fd_server); - _exit(exit_code); - } - self->pid_coredump_server =3D pid_coredump_server; - - EXPECT_EQ(close(ipc_sockets[1]), 0); - ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); - EXPECT_EQ(close(ipc_sockets[0]), 0); - - pid =3D fork(); - ASSERT_GE(pid, 0); - if (pid =3D=3D 0) { - int fd_socket; - ssize_t ret; - const struct sockaddr_un coredump_sk =3D { - .sun_family =3D AF_UNIX, - .sun_path =3D "/tmp/coredump.socket", - }; - size_t coredump_sk_len =3D - offsetof(struct sockaddr_un, sun_path) + - sizeof("/tmp/coredump.socket"); - - fd_socket =3D socket(AF_UNIX, SOCK_STREAM, 0); - if (fd_socket < 0) - _exit(EXIT_FAILURE); - - ret =3D connect(fd_socket, (const struct sockaddr *)&coredump_sk, coredu= mp_sk_len); - if (ret < 0) - _exit(EXIT_FAILURE); - - close(fd_socket); - _exit(EXIT_SUCCESS); - } - - pidfd =3D sys_pidfd_open(pid, 0); - ASSERT_GE(pidfd, 0); - - waitpid(pid, &status, 0); - ASSERT_TRUE(WIFEXITED(status)); - ASSERT_EQ(WEXITSTATUS(status), 0); - - ASSERT_TRUE(get_pidfd_info(pidfd, &info)); - ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); - ASSERT_EQ((info.coredump_mask & PIDFD_COREDUMPED), 0); - - wait_and_check_coredump_server(pid_coredump_server, _metadata, self); - - ASSERT_NE(stat("/tmp/coredump.file", &st), 0); - ASSERT_EQ(errno, ENOENT); -} - -TEST_F(coredump, socket_enoent) -{ - int pidfd, status; - pid_t pid; - - ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket")); - - pid =3D fork(); - ASSERT_GE(pid, 0); - if (pid =3D=3D 0) - crashing_child(); - - pidfd =3D sys_pidfd_open(pid, 0); - ASSERT_GE(pidfd, 0); - - waitpid(pid, &status, 0); - ASSERT_TRUE(WIFSIGNALED(status)); - ASSERT_FALSE(WCOREDUMP(status)); -} - -TEST_F(coredump, socket_no_listener) -{ - int pidfd, ret, status; - pid_t pid, pid_coredump_server; - int ipc_sockets[2]; - char c; - const struct sockaddr_un coredump_sk =3D { - .sun_family =3D AF_UNIX, - .sun_path =3D "/tmp/coredump.socket", - }; - size_t coredump_sk_len =3D offsetof(struct sockaddr_un, sun_path) + - sizeof("/tmp/coredump.socket"); - - ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket")); - - ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); - ASSERT_EQ(ret, 0); - - pid_coredump_server =3D fork(); - ASSERT_GE(pid_coredump_server, 0); - if (pid_coredump_server =3D=3D 0) { - int fd_server =3D -1; - int exit_code =3D EXIT_FAILURE; - - close(ipc_sockets[0]); - - fd_server =3D socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); - if (fd_server < 0) - goto out; - - ret =3D bind(fd_server, (const struct sockaddr *)&coredump_sk, coredump_= sk_len); - if (ret < 0) - goto out; - - if (write_nointr(ipc_sockets[1], "1", 1) < 0) - goto out; - - exit_code =3D EXIT_SUCCESS; -out: - if (fd_server >=3D 0) - close(fd_server); - close(ipc_sockets[1]); - _exit(exit_code); - } - self->pid_coredump_server =3D pid_coredump_server; - - EXPECT_EQ(close(ipc_sockets[1]), 0); - ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); - EXPECT_EQ(close(ipc_sockets[0]), 0); - - pid =3D fork(); - ASSERT_GE(pid, 0); - if (pid =3D=3D 0) - crashing_child(); - - pidfd =3D sys_pidfd_open(pid, 0); - ASSERT_GE(pidfd, 0); - - waitpid(pid, &status, 0); - ASSERT_TRUE(WIFSIGNALED(status)); - ASSERT_FALSE(WCOREDUMP(status)); - - wait_and_check_coredump_server(pid_coredump_server, _metadata, self); -} - -static ssize_t recv_marker(int fd) -{ - enum coredump_mark mark =3D COREDUMP_MARK_REQACK; - ssize_t ret; - - ret =3D recv(fd, &mark, sizeof(mark), MSG_WAITALL); - if (ret !=3D sizeof(mark)) - return -1; - - switch (mark) { - case COREDUMP_MARK_REQACK: - fprintf(stderr, "Received marker: ReqAck\n"); - return COREDUMP_MARK_REQACK; - case COREDUMP_MARK_MINSIZE: - fprintf(stderr, "Received marker: MinSize\n"); - return COREDUMP_MARK_MINSIZE; - case COREDUMP_MARK_MAXSIZE: - fprintf(stderr, "Received marker: MaxSize\n"); - return COREDUMP_MARK_MAXSIZE; - case COREDUMP_MARK_UNSUPPORTED: - fprintf(stderr, "Received marker: Unsupported\n"); - return COREDUMP_MARK_UNSUPPORTED; - case COREDUMP_MARK_CONFLICTING: - fprintf(stderr, "Received marker: Conflicting\n"); - return COREDUMP_MARK_CONFLICTING; - default: - fprintf(stderr, "Received unknown marker: %u\n", mark); - break; - } - return -1; -} - -static bool read_marker(int fd, enum coredump_mark mark) -{ - ssize_t ret; - - ret =3D recv_marker(fd); - if (ret < 0) - return false; - return ret =3D=3D mark; -} - -static bool read_coredump_req(int fd, struct coredump_req *req) -{ - ssize_t ret; - size_t field_size, user_size, ack_size, kernel_size, remaining_size; - - memset(req, 0, sizeof(*req)); - field_size =3D sizeof(req->size); - - /* Peek the size of the coredump request. */ - ret =3D recv(fd, req, field_size, MSG_PEEK | MSG_WAITALL); - if (ret !=3D field_size) - return false; - kernel_size =3D req->size; - - if (kernel_size < COREDUMP_ACK_SIZE_VER0) - return false; - if (kernel_size >=3D PAGE_SIZE) - return false; - - /* Use the minimum of user and kernel size to read the full request. */ - user_size =3D sizeof(struct coredump_req); - ack_size =3D user_size < kernel_size ? user_size : kernel_size; - ret =3D recv(fd, req, ack_size, MSG_WAITALL); - if (ret !=3D ack_size) - return false; - - fprintf(stderr, "Read coredump request with size %u and mask 0x%llx\n", - req->size, (unsigned long long)req->mask); - - if (user_size > kernel_size) - remaining_size =3D user_size - kernel_size; - else - remaining_size =3D kernel_size - user_size; - - if (PAGE_SIZE <=3D remaining_size) - return false; - - /* - * Discard any additional data if the kernel's request was larger than - * what we knew about or cared about. - */ - if (remaining_size) { - char buffer[PAGE_SIZE]; - - ret =3D recv(fd, buffer, sizeof(buffer), MSG_WAITALL); - if (ret !=3D remaining_size) - return false; - fprintf(stderr, "Discarded %zu bytes of data after coredump request\n", = remaining_size); - } - - return true; -} - -static bool send_coredump_ack(int fd, const struct coredump_req *req, - __u64 mask, size_t size_ack) -{ - ssize_t ret; - /* - * Wrap struct coredump_ack in a larger struct so we can - * simulate sending to much data to the kernel. - */ - struct large_ack_for_size_testing { - struct coredump_ack ack; - char buffer[PAGE_SIZE]; - } large_ack =3D {}; - - if (!size_ack) - size_ack =3D sizeof(struct coredump_ack) < req->size_ack ? - sizeof(struct coredump_ack) : - req->size_ack; - large_ack.ack.mask =3D mask; - large_ack.ack.size =3D size_ack; - ret =3D send(fd, &large_ack, size_ack, MSG_NOSIGNAL); - if (ret !=3D size_ack) - return false; - - fprintf(stderr, "Sent coredump ack with size %zu and mask 0x%llx\n", - size_ack, (unsigned long long)mask); - return true; -} - -static bool check_coredump_req(const struct coredump_req *req, size_t min_= size, - __u64 required_mask) -{ - if (req->size < min_size) - return false; - if ((req->mask & required_mask) !=3D required_mask) - return false; - if (req->mask & ~required_mask) - return false; - return true; -} - -TEST_F(coredump, socket_request_kernel) -{ - int pidfd, ret, status; - pid_t pid, pid_coredump_server; - struct stat st; - struct pidfd_info info =3D {}; - int ipc_sockets[2]; - char c; - - ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); - - ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); - ASSERT_EQ(ret, 0); - - pid_coredump_server =3D fork(); - ASSERT_GE(pid_coredump_server, 0); - if (pid_coredump_server =3D=3D 0) { - struct coredump_req req =3D {}; - int fd_server =3D -1, fd_coredump =3D -1, fd_core_file =3D -1, fd_peer_p= idfd =3D -1; - int exit_code =3D EXIT_FAILURE; - - close(ipc_sockets[0]); - - fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) - goto out; - - if (write_nointr(ipc_sockets[1], "1", 1) < 0) - goto out; - - close(ipc_sockets[1]); - - fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) - goto out; - - fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) - goto out; - - if (!get_pidfd_info(fd_peer_pidfd, &info)) - goto out; - - if (!(info.mask & PIDFD_INFO_COREDUMP)) - goto out; - - if (!(info.coredump_mask & PIDFD_COREDUMPED)) - goto out; - - fd_core_file =3D creat("/tmp/coredump.file", 0644); - if (fd_core_file < 0) - goto out; - - if (!read_coredump_req(fd_coredump, &req)) - goto out; - - if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, - COREDUMP_KERNEL | COREDUMP_USERSPACE | - COREDUMP_REJECT | COREDUMP_WAIT)) - goto out; - - if (!send_coredump_ack(fd_coredump, &req, - COREDUMP_KERNEL | COREDUMP_WAIT, 0)) - goto out; - - if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) - goto out; - - for (;;) { - char buffer[4096]; - ssize_t bytes_read, bytes_write; - - bytes_read =3D read(fd_coredump, buffer, sizeof(buffer)); - if (bytes_read < 0) - goto out; - - if (bytes_read =3D=3D 0) - break; - - bytes_write =3D write(fd_core_file, buffer, bytes_read); - if (bytes_read !=3D bytes_write) - goto out; - } - - exit_code =3D EXIT_SUCCESS; -out: - if (fd_core_file >=3D 0) - close(fd_core_file); - if (fd_peer_pidfd >=3D 0) - close(fd_peer_pidfd); - if (fd_coredump >=3D 0) - close(fd_coredump); - if (fd_server >=3D 0) - close(fd_server); - _exit(exit_code); - } - self->pid_coredump_server =3D pid_coredump_server; - - EXPECT_EQ(close(ipc_sockets[1]), 0); - ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); - EXPECT_EQ(close(ipc_sockets[0]), 0); - - pid =3D fork(); - ASSERT_GE(pid, 0); - if (pid =3D=3D 0) - crashing_child(); - - pidfd =3D sys_pidfd_open(pid, 0); - ASSERT_GE(pidfd, 0); - - waitpid(pid, &status, 0); - ASSERT_TRUE(WIFSIGNALED(status)); - ASSERT_TRUE(WCOREDUMP(status)); - - ASSERT_TRUE(get_pidfd_info(pidfd, &info)); - ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); - ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); - - wait_and_check_coredump_server(pid_coredump_server, _metadata, self); - - ASSERT_EQ(stat("/tmp/coredump.file", &st), 0); - ASSERT_GT(st.st_size, 0); - system("file /tmp/coredump.file"); -} - -TEST_F(coredump, socket_request_userspace) -{ - int pidfd, ret, status; - pid_t pid, pid_coredump_server; - struct pidfd_info info =3D {}; - int ipc_sockets[2]; - char c; - - ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); - - ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); - ASSERT_EQ(ret, 0); - - pid_coredump_server =3D fork(); - ASSERT_GE(pid_coredump_server, 0); - if (pid_coredump_server =3D=3D 0) { - struct coredump_req req =3D {}; - int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1; - int exit_code =3D EXIT_FAILURE; - - close(ipc_sockets[0]); - - fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) - goto out; - - if (write_nointr(ipc_sockets[1], "1", 1) < 0) - goto out; - - close(ipc_sockets[1]); - - fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) - goto out; - - fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) - goto out; - - if (!get_pidfd_info(fd_peer_pidfd, &info)) - goto out; - - if (!(info.mask & PIDFD_INFO_COREDUMP)) - goto out; - - if (!(info.coredump_mask & PIDFD_COREDUMPED)) - goto out; - - if (!read_coredump_req(fd_coredump, &req)) - goto out; - - if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, - COREDUMP_KERNEL | COREDUMP_USERSPACE | - COREDUMP_REJECT | COREDUMP_WAIT)) - goto out; - - if (!send_coredump_ack(fd_coredump, &req, - COREDUMP_USERSPACE | COREDUMP_WAIT, 0)) - goto out; - - if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) - goto out; - - for (;;) { - char buffer[4096]; - ssize_t bytes_read; - - bytes_read =3D read(fd_coredump, buffer, sizeof(buffer)); - if (bytes_read > 0) - goto out; - - if (bytes_read < 0) - goto out; - - if (bytes_read =3D=3D 0) - break; - } - - exit_code =3D EXIT_SUCCESS; -out: - if (fd_peer_pidfd >=3D 0) - close(fd_peer_pidfd); - if (fd_coredump >=3D 0) - close(fd_coredump); - if (fd_server >=3D 0) - close(fd_server); - _exit(exit_code); - } - self->pid_coredump_server =3D pid_coredump_server; - - EXPECT_EQ(close(ipc_sockets[1]), 0); - ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); - EXPECT_EQ(close(ipc_sockets[0]), 0); - - pid =3D fork(); - ASSERT_GE(pid, 0); - if (pid =3D=3D 0) - crashing_child(); - - pidfd =3D sys_pidfd_open(pid, 0); - ASSERT_GE(pidfd, 0); - - waitpid(pid, &status, 0); - ASSERT_TRUE(WIFSIGNALED(status)); - ASSERT_TRUE(WCOREDUMP(status)); - - ASSERT_TRUE(get_pidfd_info(pidfd, &info)); - ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); - ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); - - wait_and_check_coredump_server(pid_coredump_server, _metadata, self); -} - -TEST_F(coredump, socket_request_reject) -{ - int pidfd, ret, status; - pid_t pid, pid_coredump_server; - struct pidfd_info info =3D {}; - int ipc_sockets[2]; - char c; - - ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); - - ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); - ASSERT_EQ(ret, 0); - - pid_coredump_server =3D fork(); - ASSERT_GE(pid_coredump_server, 0); - if (pid_coredump_server =3D=3D 0) { - struct coredump_req req =3D {}; - int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1; - int exit_code =3D EXIT_FAILURE; - - close(ipc_sockets[0]); - - fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) - goto out; - - if (write_nointr(ipc_sockets[1], "1", 1) < 0) - goto out; - - close(ipc_sockets[1]); - - fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) - goto out; - - fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) - goto out; - - if (!get_pidfd_info(fd_peer_pidfd, &info)) - goto out; - - if (!(info.mask & PIDFD_INFO_COREDUMP)) - goto out; - - if (!(info.coredump_mask & PIDFD_COREDUMPED)) - goto out; - - if (!read_coredump_req(fd_coredump, &req)) - goto out; - - if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, - COREDUMP_KERNEL | COREDUMP_USERSPACE | - COREDUMP_REJECT | COREDUMP_WAIT)) - goto out; - - if (!send_coredump_ack(fd_coredump, &req, - COREDUMP_REJECT | COREDUMP_WAIT, 0)) - goto out; - - if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) - goto out; - - for (;;) { - char buffer[4096]; - ssize_t bytes_read; - - bytes_read =3D read(fd_coredump, buffer, sizeof(buffer)); - if (bytes_read > 0) - goto out; - - if (bytes_read < 0) - goto out; - - if (bytes_read =3D=3D 0) - break; - } - - exit_code =3D EXIT_SUCCESS; -out: - if (fd_peer_pidfd >=3D 0) - close(fd_peer_pidfd); - if (fd_coredump >=3D 0) - close(fd_coredump); - if (fd_server >=3D 0) - close(fd_server); - _exit(exit_code); - } - self->pid_coredump_server =3D pid_coredump_server; - - EXPECT_EQ(close(ipc_sockets[1]), 0); - ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); - EXPECT_EQ(close(ipc_sockets[0]), 0); - - pid =3D fork(); - ASSERT_GE(pid, 0); - if (pid =3D=3D 0) - crashing_child(); - - pidfd =3D sys_pidfd_open(pid, 0); - ASSERT_GE(pidfd, 0); - - waitpid(pid, &status, 0); - ASSERT_TRUE(WIFSIGNALED(status)); - ASSERT_FALSE(WCOREDUMP(status)); - - ASSERT_TRUE(get_pidfd_info(pidfd, &info)); - ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); - ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); - - wait_and_check_coredump_server(pid_coredump_server, _metadata, self); -} - -TEST_F(coredump, socket_request_invalid_flag_combination) -{ - int pidfd, ret, status; - pid_t pid, pid_coredump_server; - struct pidfd_info info =3D {}; - int ipc_sockets[2]; - char c; - - ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); - - ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); - ASSERT_EQ(ret, 0); - - pid_coredump_server =3D fork(); - ASSERT_GE(pid_coredump_server, 0); - if (pid_coredump_server =3D=3D 0) { - struct coredump_req req =3D {}; - int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1; - int exit_code =3D EXIT_FAILURE; - - close(ipc_sockets[0]); - - fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) - goto out; - - if (write_nointr(ipc_sockets[1], "1", 1) < 0) - goto out; - - close(ipc_sockets[1]); - - fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) - goto out; - - fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) - goto out; - - if (!get_pidfd_info(fd_peer_pidfd, &info)) - goto out; - - if (!(info.mask & PIDFD_INFO_COREDUMP)) - goto out; - - if (!(info.coredump_mask & PIDFD_COREDUMPED)) - goto out; - - if (!read_coredump_req(fd_coredump, &req)) - goto out; - - if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, - COREDUMP_KERNEL | COREDUMP_USERSPACE | - COREDUMP_REJECT | COREDUMP_WAIT)) - goto out; - - if (!send_coredump_ack(fd_coredump, &req, - COREDUMP_KERNEL | COREDUMP_REJECT | COREDUMP_WAIT, 0)) - goto out; - - if (!read_marker(fd_coredump, COREDUMP_MARK_CONFLICTING)) - goto out; - - exit_code =3D EXIT_SUCCESS; -out: - if (fd_peer_pidfd >=3D 0) - close(fd_peer_pidfd); - if (fd_coredump >=3D 0) - close(fd_coredump); - if (fd_server >=3D 0) - close(fd_server); - _exit(exit_code); - } - self->pid_coredump_server =3D pid_coredump_server; - - EXPECT_EQ(close(ipc_sockets[1]), 0); - ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); - EXPECT_EQ(close(ipc_sockets[0]), 0); - - pid =3D fork(); - ASSERT_GE(pid, 0); - if (pid =3D=3D 0) - crashing_child(); - - pidfd =3D sys_pidfd_open(pid, 0); - ASSERT_GE(pidfd, 0); - - waitpid(pid, &status, 0); - ASSERT_TRUE(WIFSIGNALED(status)); - ASSERT_FALSE(WCOREDUMP(status)); - - ASSERT_TRUE(get_pidfd_info(pidfd, &info)); - ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); - ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); - - wait_and_check_coredump_server(pid_coredump_server, _metadata, self); -} - -TEST_F(coredump, socket_request_unknown_flag) -{ - int pidfd, ret, status; - pid_t pid, pid_coredump_server; - struct pidfd_info info =3D {}; - int ipc_sockets[2]; - char c; - - ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); - - ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); - ASSERT_EQ(ret, 0); - - pid_coredump_server =3D fork(); - ASSERT_GE(pid_coredump_server, 0); - if (pid_coredump_server =3D=3D 0) { - struct coredump_req req =3D {}; - int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1; - int exit_code =3D EXIT_FAILURE; - - close(ipc_sockets[0]); - - fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) - goto out; - - if (write_nointr(ipc_sockets[1], "1", 1) < 0) - goto out; - - close(ipc_sockets[1]); - - fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) - goto out; - - fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) - goto out; - - if (!get_pidfd_info(fd_peer_pidfd, &info)) - goto out; - - if (!(info.mask & PIDFD_INFO_COREDUMP)) - goto out; - - if (!(info.coredump_mask & PIDFD_COREDUMPED)) - goto out; - - if (!read_coredump_req(fd_coredump, &req)) - goto out; - - if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, - COREDUMP_KERNEL | COREDUMP_USERSPACE | - COREDUMP_REJECT | COREDUMP_WAIT)) - goto out; - - if (!send_coredump_ack(fd_coredump, &req, (1ULL << 63), 0)) - goto out; - - if (!read_marker(fd_coredump, COREDUMP_MARK_UNSUPPORTED)) - goto out; - - exit_code =3D EXIT_SUCCESS; -out: - if (fd_peer_pidfd >=3D 0) - close(fd_peer_pidfd); - if (fd_coredump >=3D 0) - close(fd_coredump); - if (fd_server >=3D 0) - close(fd_server); - _exit(exit_code); - } - self->pid_coredump_server =3D pid_coredump_server; - - EXPECT_EQ(close(ipc_sockets[1]), 0); - ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); - EXPECT_EQ(close(ipc_sockets[0]), 0); - - pid =3D fork(); - ASSERT_GE(pid, 0); - if (pid =3D=3D 0) - crashing_child(); - - pidfd =3D sys_pidfd_open(pid, 0); - ASSERT_GE(pidfd, 0); - - waitpid(pid, &status, 0); - ASSERT_TRUE(WIFSIGNALED(status)); - ASSERT_FALSE(WCOREDUMP(status)); - - ASSERT_TRUE(get_pidfd_info(pidfd, &info)); - ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); - ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); - - wait_and_check_coredump_server(pid_coredump_server, _metadata, self); -} - -TEST_F(coredump, socket_request_invalid_size_small) -{ - int pidfd, ret, status; - pid_t pid, pid_coredump_server; - struct pidfd_info info =3D {}; - int ipc_sockets[2]; - char c; - - ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); - - ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); - ASSERT_EQ(ret, 0); - - pid_coredump_server =3D fork(); - ASSERT_GE(pid_coredump_server, 0); - if (pid_coredump_server =3D=3D 0) { - struct coredump_req req =3D {}; - int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1; - int exit_code =3D EXIT_FAILURE; - - close(ipc_sockets[0]); - - fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) - goto out; - - if (write_nointr(ipc_sockets[1], "1", 1) < 0) - goto out; - - close(ipc_sockets[1]); - - fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) - goto out; - - fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) - goto out; - - if (!get_pidfd_info(fd_peer_pidfd, &info)) - goto out; - - if (!(info.mask & PIDFD_INFO_COREDUMP)) - goto out; - - if (!(info.coredump_mask & PIDFD_COREDUMPED)) - goto out; - - if (!read_coredump_req(fd_coredump, &req)) - goto out; - - if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, - COREDUMP_KERNEL | COREDUMP_USERSPACE | - COREDUMP_REJECT | COREDUMP_WAIT)) - goto out; - - if (!send_coredump_ack(fd_coredump, &req, - COREDUMP_REJECT | COREDUMP_WAIT, - COREDUMP_ACK_SIZE_VER0 / 2)) - goto out; - - if (!read_marker(fd_coredump, COREDUMP_MARK_MINSIZE)) - goto out; - - exit_code =3D EXIT_SUCCESS; -out: - if (fd_peer_pidfd >=3D 0) - close(fd_peer_pidfd); - if (fd_coredump >=3D 0) - close(fd_coredump); - if (fd_server >=3D 0) - close(fd_server); - _exit(exit_code); - } - self->pid_coredump_server =3D pid_coredump_server; - - EXPECT_EQ(close(ipc_sockets[1]), 0); - ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); - EXPECT_EQ(close(ipc_sockets[0]), 0); - - pid =3D fork(); - ASSERT_GE(pid, 0); - if (pid =3D=3D 0) - crashing_child(); - - pidfd =3D sys_pidfd_open(pid, 0); - ASSERT_GE(pidfd, 0); - - waitpid(pid, &status, 0); - ASSERT_TRUE(WIFSIGNALED(status)); - ASSERT_FALSE(WCOREDUMP(status)); - - ASSERT_TRUE(get_pidfd_info(pidfd, &info)); - ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); - ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); - - wait_and_check_coredump_server(pid_coredump_server, _metadata, self); -} - -TEST_F(coredump, socket_request_invalid_size_large) -{ - int pidfd, ret, status; - pid_t pid, pid_coredump_server; - struct pidfd_info info =3D {}; - int ipc_sockets[2]; - char c; - - ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); - - ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); - ASSERT_EQ(ret, 0); - - pid_coredump_server =3D fork(); - ASSERT_GE(pid_coredump_server, 0); - if (pid_coredump_server =3D=3D 0) { - struct coredump_req req =3D {}; - int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1; - int exit_code =3D EXIT_FAILURE; - - close(ipc_sockets[0]); - - fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) - goto out; - - if (write_nointr(ipc_sockets[1], "1", 1) < 0) - goto out; - - close(ipc_sockets[1]); - - fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) - goto out; - - fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) - goto out; - - if (!get_pidfd_info(fd_peer_pidfd, &info)) - goto out; - - if (!(info.mask & PIDFD_INFO_COREDUMP)) - goto out; - - if (!(info.coredump_mask & PIDFD_COREDUMPED)) - goto out; - - if (!read_coredump_req(fd_coredump, &req)) - goto out; - - if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, - COREDUMP_KERNEL | COREDUMP_USERSPACE | - COREDUMP_REJECT | COREDUMP_WAIT)) - goto out; - - if (!send_coredump_ack(fd_coredump, &req, - COREDUMP_REJECT | COREDUMP_WAIT, - COREDUMP_ACK_SIZE_VER0 + PAGE_SIZE)) - goto out; - - if (!read_marker(fd_coredump, COREDUMP_MARK_MAXSIZE)) - goto out; - - exit_code =3D EXIT_SUCCESS; -out: - if (fd_peer_pidfd >=3D 0) - close(fd_peer_pidfd); - if (fd_coredump >=3D 0) - close(fd_coredump); - if (fd_server >=3D 0) - close(fd_server); - _exit(exit_code); - } - self->pid_coredump_server =3D pid_coredump_server; - - EXPECT_EQ(close(ipc_sockets[1]), 0); - ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); - EXPECT_EQ(close(ipc_sockets[0]), 0); - - pid =3D fork(); - ASSERT_GE(pid, 0); - if (pid =3D=3D 0) - crashing_child(); - - pidfd =3D sys_pidfd_open(pid, 0); - ASSERT_GE(pidfd, 0); - - waitpid(pid, &status, 0); - ASSERT_TRUE(WIFSIGNALED(status)); - ASSERT_FALSE(WCOREDUMP(status)); - - ASSERT_TRUE(get_pidfd_info(pidfd, &info)); - ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); - ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); - - wait_and_check_coredump_server(pid_coredump_server, _metadata, self); -} - -static int open_coredump_tmpfile(int fd_tmpfs_detached) -{ - return openat(fd_tmpfs_detached, ".", O_TMPFILE | O_RDWR | O_EXCL, 0600); -} - -#define NUM_CRASHING_COREDUMPS 5 - -TEST_F_TIMEOUT(coredump, socket_multiple_crashing_coredumps, 500) -{ - int pidfd[NUM_CRASHING_COREDUMPS], status[NUM_CRASHING_COREDUMPS]; - pid_t pid[NUM_CRASHING_COREDUMPS], pid_coredump_server; - struct pidfd_info info =3D {}; - int ipc_sockets[2]; - char c; - - ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); - - ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets)= , 0); - - pid_coredump_server =3D fork(); - ASSERT_GE(pid_coredump_server, 0); - if (pid_coredump_server =3D=3D 0) { - int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1, fd_core_= file =3D -1; - int exit_code =3D EXIT_FAILURE; - struct coredump_req req =3D {}; - - close(ipc_sockets[0]); - fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) { - fprintf(stderr, "Failed to create and listen on unix socket\n"); - goto out; - } - - if (write_nointr(ipc_sockets[1], "1", 1) < 0) { - fprintf(stderr, "Failed to notify parent via ipc socket\n"); - goto out; - } - close(ipc_sockets[1]); - - for (int i =3D 0; i < NUM_CRASHING_COREDUMPS; i++) { - fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) { - fprintf(stderr, "accept4 failed: %m\n"); - goto out; - } - - fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) { - fprintf(stderr, "get_peer_pidfd failed for fd %d: %m\n", fd_coredump); - goto out; - } - - if (!get_pidfd_info(fd_peer_pidfd, &info)) { - fprintf(stderr, "get_pidfd_info failed for fd %d\n", fd_peer_pidfd); - goto out; - } - - if (!(info.mask & PIDFD_INFO_COREDUMP)) { - fprintf(stderr, "pidfd info missing PIDFD_INFO_COREDUMP for fd %d\n", = fd_peer_pidfd); - goto out; - } - if (!(info.coredump_mask & PIDFD_COREDUMPED)) { - fprintf(stderr, "pidfd info missing PIDFD_COREDUMPED for fd %d\n", fd_= peer_pidfd); - goto out; - } - - if (!read_coredump_req(fd_coredump, &req)) { - fprintf(stderr, "read_coredump_req failed for fd %d\n", fd_coredump); - goto out; - } - - if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, - COREDUMP_KERNEL | COREDUMP_USERSPACE | - COREDUMP_REJECT | COREDUMP_WAIT)) { - fprintf(stderr, "check_coredump_req failed for fd %d\n", fd_coredump); - goto out; - } - - if (!send_coredump_ack(fd_coredump, &req, - COREDUMP_KERNEL | COREDUMP_WAIT, 0)) { - fprintf(stderr, "send_coredump_ack failed for fd %d\n", fd_coredump); - goto out; - } - - if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) { - fprintf(stderr, "read_marker failed for fd %d\n", fd_coredump); - goto out; - } - - fd_core_file =3D open_coredump_tmpfile(self->fd_tmpfs_detached); - if (fd_core_file < 0) { - fprintf(stderr, "%m - open_coredump_tmpfile failed for fd %d\n", fd_co= redump); - goto out; - } - - for (;;) { - char buffer[4096]; - ssize_t bytes_read, bytes_write; - - bytes_read =3D read(fd_coredump, buffer, sizeof(buffer)); - if (bytes_read < 0) { - fprintf(stderr, "read failed for fd %d: %m\n", fd_coredump); - goto out; - } - - if (bytes_read =3D=3D 0) - break; - - bytes_write =3D write(fd_core_file, buffer, bytes_read); - if (bytes_read !=3D bytes_write) { - fprintf(stderr, "write failed for fd %d: %m\n", fd_core_file); - goto out; - } - } - - close(fd_core_file); - close(fd_peer_pidfd); - close(fd_coredump); - fd_peer_pidfd =3D -1; - fd_coredump =3D -1; - } - - exit_code =3D EXIT_SUCCESS; -out: - if (fd_core_file >=3D 0) - close(fd_core_file); - if (fd_peer_pidfd >=3D 0) - close(fd_peer_pidfd); - if (fd_coredump >=3D 0) - close(fd_coredump); - if (fd_server >=3D 0) - close(fd_server); - _exit(exit_code); - } - self->pid_coredump_server =3D pid_coredump_server; - - EXPECT_EQ(close(ipc_sockets[1]), 0); - ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); - EXPECT_EQ(close(ipc_sockets[0]), 0); - - for (int i =3D 0; i < NUM_CRASHING_COREDUMPS; i++) { - pid[i] =3D fork(); - ASSERT_GE(pid[i], 0); - if (pid[i] =3D=3D 0) - crashing_child(); - pidfd[i] =3D sys_pidfd_open(pid[i], 0); - ASSERT_GE(pidfd[i], 0); - } - - for (int i =3D 0; i < NUM_CRASHING_COREDUMPS; i++) { - waitpid(pid[i], &status[i], 0); - ASSERT_TRUE(WIFSIGNALED(status[i])); - ASSERT_TRUE(WCOREDUMP(status[i])); - } - - for (int i =3D 0; i < NUM_CRASHING_COREDUMPS; i++) { - info.mask =3D PIDFD_INFO_EXIT | PIDFD_INFO_COREDUMP; - ASSERT_EQ(ioctl(pidfd[i], PIDFD_GET_INFO, &info), 0); - ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); - ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); - } - - wait_and_check_coredump_server(pid_coredump_server, _metadata, self); -} - -#define MAX_EVENTS 128 - -static void process_coredump_worker(int fd_coredump, int fd_peer_pidfd, in= t fd_core_file) -{ - int epfd =3D -1; - int exit_code =3D EXIT_FAILURE; - - epfd =3D epoll_create1(0); - if (epfd < 0) - goto out; - - struct epoll_event ev; - ev.events =3D EPOLLIN | EPOLLRDHUP | EPOLLET; - ev.data.fd =3D fd_coredump; - if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd_coredump, &ev) < 0) - goto out; - - for (;;) { - struct epoll_event events[1]; - int n =3D epoll_wait(epfd, events, 1, -1); - if (n < 0) - break; - - if (events[0].events & (EPOLLIN | EPOLLRDHUP)) { - for (;;) { - char buffer[4096]; - ssize_t bytes_read =3D read(fd_coredump, buffer, sizeof(buffer)); - if (bytes_read < 0) { - if (errno =3D=3D EAGAIN || errno =3D=3D EWOULDBLOCK) - break; - goto out; - } - if (bytes_read =3D=3D 0) - goto done; - ssize_t bytes_write =3D write(fd_core_file, buffer, bytes_read); - if (bytes_write !=3D bytes_read) - goto out; - } - } - } - -done: - exit_code =3D EXIT_SUCCESS; -out: - if (epfd >=3D 0) - close(epfd); - if (fd_core_file >=3D 0) - close(fd_core_file); - if (fd_peer_pidfd >=3D 0) - close(fd_peer_pidfd); - if (fd_coredump >=3D 0) - close(fd_coredump); - _exit(exit_code); -} - -TEST_F_TIMEOUT(coredump, socket_multiple_crashing_coredumps_epoll_workers,= 500) -{ - int pidfd[NUM_CRASHING_COREDUMPS], status[NUM_CRASHING_COREDUMPS]; - pid_t pid[NUM_CRASHING_COREDUMPS], pid_coredump_server, worker_pids[NUM_C= RASHING_COREDUMPS]; - struct pidfd_info info =3D {}; - int ipc_sockets[2]; - char c; - - ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); - ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets)= , 0); - - pid_coredump_server =3D fork(); - ASSERT_GE(pid_coredump_server, 0); - if (pid_coredump_server =3D=3D 0) { - int fd_server =3D -1, exit_code =3D EXIT_FAILURE, n_conns =3D 0; - fd_server =3D -1; - exit_code =3D EXIT_FAILURE; - n_conns =3D 0; - close(ipc_sockets[0]); - fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) - goto out; - - if (write_nointr(ipc_sockets[1], "1", 1) < 0) - goto out; - close(ipc_sockets[1]); - - while (n_conns < NUM_CRASHING_COREDUMPS) { - int fd_coredump =3D -1, fd_peer_pidfd =3D -1, fd_core_file =3D -1; - struct coredump_req req =3D {}; - fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) { - if (errno =3D=3D EAGAIN || errno =3D=3D EWOULDBLOCK) - continue; - goto out; - } - fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) - goto out; - if (!get_pidfd_info(fd_peer_pidfd, &info)) - goto out; - if (!(info.mask & PIDFD_INFO_COREDUMP) || !(info.coredump_mask & PIDFD_= COREDUMPED)) - goto out; - if (!read_coredump_req(fd_coredump, &req)) - goto out; - if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, - COREDUMP_KERNEL | COREDUMP_USERSPACE | - COREDUMP_REJECT | COREDUMP_WAIT)) - goto out; - if (!send_coredump_ack(fd_coredump, &req, COREDUMP_KERNEL | COREDUMP_WA= IT, 0)) - goto out; - if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) - goto out; - fd_core_file =3D open_coredump_tmpfile(self->fd_tmpfs_detached); - if (fd_core_file < 0) - goto out; - pid_t worker =3D fork(); - if (worker =3D=3D 0) { - close(fd_server); - process_coredump_worker(fd_coredump, fd_peer_pidfd, fd_core_file); - } - worker_pids[n_conns] =3D worker; - if (fd_coredump >=3D 0) - close(fd_coredump); - if (fd_peer_pidfd >=3D 0) - close(fd_peer_pidfd); - if (fd_core_file >=3D 0) - close(fd_core_file); - n_conns++; - } - exit_code =3D EXIT_SUCCESS; -out: - if (fd_server >=3D 0) - close(fd_server); - - // Reap all worker processes - for (int i =3D 0; i < n_conns; i++) { - int wstatus; - if (waitpid(worker_pids[i], &wstatus, 0) < 0) { - fprintf(stderr, "Failed to wait for worker %d: %m\n", worker_pids[i]); - } else if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) !=3D EXIT_SUCCESS= ) { - fprintf(stderr, "Worker %d exited with error code %d\n", worker_pids[i= ], WEXITSTATUS(wstatus)); - exit_code =3D EXIT_FAILURE; - } - } - - _exit(exit_code); - } - self->pid_coredump_server =3D pid_coredump_server; - - EXPECT_EQ(close(ipc_sockets[1]), 0); - ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); - EXPECT_EQ(close(ipc_sockets[0]), 0); - - for (int i =3D 0; i < NUM_CRASHING_COREDUMPS; i++) { - pid[i] =3D fork(); - ASSERT_GE(pid[i], 0); - if (pid[i] =3D=3D 0) - crashing_child(); - pidfd[i] =3D sys_pidfd_open(pid[i], 0); - ASSERT_GE(pidfd[i], 0); - } - - for (int i =3D 0; i < NUM_CRASHING_COREDUMPS; i++) { - ASSERT_GE(waitpid(pid[i], &status[i], 0), 0); - ASSERT_TRUE(WIFSIGNALED(status[i])); - ASSERT_TRUE(WCOREDUMP(status[i])); - } - - for (int i =3D 0; i < NUM_CRASHING_COREDUMPS; i++) { - info.mask =3D PIDFD_INFO_EXIT | PIDFD_INFO_COREDUMP; - ASSERT_EQ(ioctl(pidfd[i], PIDFD_GET_INFO, &info), 0); - ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); - ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); - } - - wait_and_check_coredump_server(pid_coredump_server, _metadata, self); -} - -TEST_F(coredump, socket_invalid_paths) -{ - ASSERT_FALSE(set_core_pattern("@ /tmp/coredump.socket")); - ASSERT_FALSE(set_core_pattern("@/tmp/../coredump.socket")); - ASSERT_FALSE(set_core_pattern("@../coredump.socket")); - ASSERT_FALSE(set_core_pattern("@/tmp/coredump.socket/..")); - ASSERT_FALSE(set_core_pattern("@..")); - - ASSERT_FALSE(set_core_pattern("@@ /tmp/coredump.socket")); - ASSERT_FALSE(set_core_pattern("@@/tmp/../coredump.socket")); - ASSERT_FALSE(set_core_pattern("@@../coredump.socket")); - ASSERT_FALSE(set_core_pattern("@@/tmp/coredump.socket/..")); - ASSERT_FALSE(set_core_pattern("@@..")); - - ASSERT_FALSE(set_core_pattern("@@@/tmp/coredump.socket")); -} - TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 12:14:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ADF782DCF50; Tue, 28 Oct 2025 08:47:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641224; cv=none; b=IGuVunpswkVDxIoAseQ4AOR7Wu5GFjPuHHmCjGPbK/I6Om0Ez4r5Qf3YIdTuT8m12sgJFDKxBF3++S45GxbxEF0SKxDrcKWLGQfAB/uLcJItTM9s/DUspb+ERPGqSeOlWzVO0bqIWdLBQFG0W+IIRrRRxIXaJIDdpYt0bGipTvk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641224; c=relaxed/simple; bh=3MpjOtfC3vFzMqWOcuWmTlVUTGIKdBVTAvwLW7DUofU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IofdwKv4Bkn2/nW998z7NnxeBctxYwnAx8qPdVTjrs4M2+y9oYkbRISaZdo7dBD5IR13D2dR/Us7Vw3MeUE83+WC43/NCYr1Uc9VQnZlI10PYvzq+peYo/m5QfobEcm2/Aqe8fJhzKb523dalatIxv4lrcQRruGrtS0wipFPon8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ulgeOvI4; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ulgeOvI4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 95F24C4CEFF; Tue, 28 Oct 2025 08:46:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641224; bh=3MpjOtfC3vFzMqWOcuWmTlVUTGIKdBVTAvwLW7DUofU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ulgeOvI4oZAyDiF2rBuSBEEMn/5V/7esUSQX+db9gciYwkiv3e47N08kbT/ViOtYh ve29nn7XiXK2DOFM1a4rnJddFOwZU8cY6s6ROANvjdmHUECbFjvoD7iL0lpYKK0pMg Lr5YnD0UXDHJNqljaOEjFNaokk4D4SHLVb5o54kxTzoxLjlD9FqqLDvJlEY1ZZZRoK +IKjc8JbdRvkHP6SKMtx918uD7iT3hqGElZWABp/jy1fgcutkVZJLVhqCsM/5k5dtV hn+RlFzmxiuSP+mpB8uBgSM+N6IKY3I9wWtT/beN/klPJVpmBuzAjP4+RU0g3Zsctx XAeosNYCSQ7bA== From: Christian Brauner Date: Tue, 28 Oct 2025 09:45:59 +0100 Subject: [PATCH 14/22] selftests/coredump: fix userspace client detection Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-14-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=839; i=brauner@kernel.org; h=from:subject:message-id; bh=3MpjOtfC3vFzMqWOcuWmTlVUTGIKdBVTAvwLW7DUofU=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB3awbXxssCbA6tE27Y8PFmRpL21b6uIysFCp1e7K nZdeymT0VHKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjCRv+YM/yueLmO/nPb9Jmes bsDULXxPtX/JveEN2edkMOtgXsFKLVlGhl0vmdVeMz37nJR6hn36FX6edJOdcSea9S5NSkyZVnF 2PRsA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 We need to request PIDFD_INFO_COREDUMP in the first place. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- tools/testing/selftests/coredump/coredump_socket_test.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/coredump/coredump_socket_test.c b/tool= s/testing/selftests/coredump/coredump_socket_test.c index d5ad0e696ab3..658f3966064f 100644 --- a/tools/testing/selftests/coredump/coredump_socket_test.c +++ b/tools/testing/selftests/coredump/coredump_socket_test.c @@ -188,7 +188,9 @@ TEST_F(coredump, socket_detect_userspace_client) int pidfd, ret, status; pid_t pid, pid_coredump_server; struct stat st; - struct pidfd_info info =3D {}; + struct pidfd_info info =3D { + .mask =3D PIDFD_INFO_COREDUMP, + }; int ipc_sockets[2]; char c; =20 --=20 2.47.3 From nobody Sun Feb 8 12:14:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8901A2D94BD; Tue, 28 Oct 2025 08:47:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641228; cv=none; b=WoAlq09VIPd0c0hF+aLcVV4ggRG63+X8YzP1BR0iwqBxf7M2ICcyEnnlvjIoI58o9KPR26VzunxsdyhSu5ghkCy7BzlJ7YwGAsR/WAfHzBjumh1faMfLwBl1EyEwFScSeXwYl0086RB9DzbtMai+8zocDLdPE+2Yb+6lYUlH4Zs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641228; c=relaxed/simple; bh=9WZyYJSqgqC9uOqgpENuG5GJD+MVhIhJ0ranzrExoPs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=leMgL2qRoTkrdT6A4RorDcYWEW5nhSFq95eRmcQJswZUe9bUsBQsEZ/FAG1BDpW0dTI/tPZBCshLE1ugAOOH1+IM64Oj+ckh1cdKifexku7iPzqvhuMU28ELeYR4ToSk9twG1r5j2ZevAh0N6qhIT3gzBTcBrsB5oeT6LUZl60Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jG93Awvx; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jG93Awvx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B65BBC4CEE7; Tue, 28 Oct 2025 08:47:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641228; bh=9WZyYJSqgqC9uOqgpENuG5GJD+MVhIhJ0ranzrExoPs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=jG93AwvxpRGB4DRVhc9JjxsSHjsy+FAcq7a2INdrPU64v2FA4vub1w7zmtiVFZCro xskVU0aMqdLj9TQgenEvKFgZqSHq2ugEqrX1fgqDexkgLjhlGCi5NUsxjZaDnhJ10L LNnvFxUbal6Khfmr4qXZdPuOvYpNgZxhmclziooZxBO4OxtrtawThAUjpfdNhS7uv0 qVZ5yEqZWmveeaRjCzMKbrhGpNrHfr4o7CGs1YG39PQyv+Fo/eUhGwczfyPPLuONiH 1xQrFiIS57baOAVF8M+/E/GgVEC6YozRSHbDsu+3ocR5wvCUR9YgjGvt9EJ6l+tq/I wUadZTlITi8EQ== From: Christian Brauner Date: Tue, 28 Oct 2025 09:46:00 +0100 Subject: [PATCH 15/22] selftests/coredump: fix userspace coredump client detection Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-15-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=1672; i=brauner@kernel.org; h=from:subject:message-id; bh=9WZyYJSqgqC9uOqgpENuG5GJD+MVhIhJ0ranzrExoPs=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB2KVwztWbFrdnz/99b0JSwzrHY7zHq6PfVZPd+VT Xu8L/rN7ChlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZjI5SaG/5GZz9P5ZzBeb3/B 17nLSnYO56pr89lUF96r4dsgkblpvR4jw3fbZ/xrXrIkeTJKrRbXfeMi7Xl08nUZ/Utf+uR3zzn 9nwkA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 PIDFD_INFO_COREDUMP is only retrievable until the task has exited. After it has exited task->mm is NULL. So if the task didn't actually coredump we can't retrieve it's dumpability settings anymore. Only if the task did coredump will we have stashed the coredump information in the respective struct pid. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- tools/testing/selftests/coredump/coredump_socket_test.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/coredump/coredump_socket_test.c b/tool= s/testing/selftests/coredump/coredump_socket_test.c index 658f3966064f..5103d9f13003 100644 --- a/tools/testing/selftests/coredump/coredump_socket_test.c +++ b/tools/testing/selftests/coredump/coredump_socket_test.c @@ -271,22 +271,26 @@ TEST_F(coredump, socket_detect_userspace_client) _exit(EXIT_FAILURE); =20 close(fd_socket); + pause(); _exit(EXIT_SUCCESS); } =20 pidfd =3D sys_pidfd_open(pid, 0); ASSERT_GE(pidfd, 0); =20 - waitpid(pid, &status, 0); - ASSERT_TRUE(WIFEXITED(status)); - ASSERT_EQ(WEXITSTATUS(status), 0); - ASSERT_TRUE(get_pidfd_info(pidfd, &info)); ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); ASSERT_EQ((info.coredump_mask & PIDFD_COREDUMPED), 0); =20 wait_and_check_coredump_server(pid_coredump_server, _metadata, self); =20 + ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0), 0); + ASSERT_EQ(close(pidfd), 0); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFSIGNALED(status)); + ASSERT_EQ(WTERMSIG(status), SIGKILL); + ASSERT_NE(stat("/tmp/coredump.file", &st), 0); ASSERT_EQ(errno, ENOENT); } --=20 2.47.3 From nobody Sun Feb 8 12:14:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 30EF12D97A6; Tue, 28 Oct 2025 08:47:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641234; cv=none; b=YTYAWBC8mT90o4DUnsqtXWeY49PlCcjXJKRybgjx3OTTO6j899Z2nA7trRPjMNatzcB5BHG4BrPcKP4p/4KI71+NnA33gWa9WTA1SML4oxm88t1RLzT8niKGmxIUIswDIbYEhUdUGy9MWZuvBdAUgfkavD3Y0VM2PGr/qcP0p2c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641234; c=relaxed/simple; bh=WXvJOQc/1nKleY4xLz7bcXslIdmWnEGWuNhG++Sv6j0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CQR0AeFFHa51nMSqG+Y3kdGJjWLjAQUN9sll5BfRJOkPGmXijZj2koGsgLFll8ywsnt/UymAnQ1Xo49j2LOB1ZQcsQFm8UGWnolQoGnHbBmdazIupJ3rfxJb5YiZp2NCwfEQ5lyUx1p/zaKLLiQCu+fWmTrxwHnEmbJpvef+2BI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YdF9UdGy; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YdF9UdGy" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 06795C4CEE7; Tue, 28 Oct 2025 08:47:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641232; bh=WXvJOQc/1nKleY4xLz7bcXslIdmWnEGWuNhG++Sv6j0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=YdF9UdGy6hy3lYDHW0ikUGuAZ1p0YpfbJUGM79DTRT7GC2NLqCmTH+0lAEe4qSW++ DsXOauAc4WRiT3hYN3H2TLxlkRKuBAaEZukJdo9eVvoaZNeXoy2m0kp+s2Qtc/szEj MNuAmXDi4GG2r7uQn7Y5WZ9IkIw7aBo2o4f/yKMWYZml4SGM2/vth+OS9PLYW46rW1 Ppfvp/Q7nqYizsqlbAhZfSIQR3qhj6rVdvGtIO8f1j2C+n0Kpi+TvpJtgvMocgbc+n piUt5su/LAn/EtpBb0vZ7x+OCZc2RXK2Os7UnqLejFf8cdZ47tUTAmz53Eu6Rez1qh 7sVyzBRWJsKpQ== From: Christian Brauner Date: Tue, 28 Oct 2025 09:46:01 +0100 Subject: [PATCH 16/22] selftests/coredump: handle edge-triggered epoll correctly Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-16-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=1000; i=brauner@kernel.org; h=from:subject:message-id; bh=WXvJOQc/1nKleY4xLz7bcXslIdmWnEGWuNhG++Sv6j0=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB1q+n72562Fa80nsn8JOFxRvFz57r3kE1M1JL4x+ oqLPc7d21HKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjCRh1GMDE83S4g8Onv04WvT XWbxng///frYyXP2kqxk6KGZ6X+y4qMZ/gckHfornnWZe0t897OlGtLn5ORkbh07t1Tu1Q2m2sP 3WzkA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 by putting the file descriptor into non-blocking mode. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- tools/testing/selftests/coredump/coredump_test_helpers.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/testing/selftests/coredump/coredump_test_helpers.c b/too= ls/testing/selftests/coredump/coredump_test_helpers.c index 7512a8ef73d3..116c797090a1 100644 --- a/tools/testing/selftests/coredump/coredump_test_helpers.c +++ b/tools/testing/selftests/coredump/coredump_test_helpers.c @@ -291,6 +291,14 @@ void process_coredump_worker(int fd_coredump, int fd_p= eer_pidfd, int fd_core_fil int epfd =3D -1; int exit_code =3D EXIT_FAILURE; struct epoll_event ev; + int flags; + + /* Set socket to non-blocking mode for edge-triggered epoll */ + flags =3D fcntl(fd_coredump, F_GETFL, 0); + if (flags < 0) + goto out; + if (fcntl(fd_coredump, F_SETFL, flags | O_NONBLOCK) < 0) + goto out; =20 epfd =3D epoll_create1(0); if (epfd < 0) --=20 2.47.3 From nobody Sun Feb 8 12:14:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 229A72E7F3F; Tue, 28 Oct 2025 08:47:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641237; cv=none; b=i2GqlZk3kROD3Vcdt1ozO4lW07CPICb4v6Dee6PlTcbAnWWVsCx7y7grBrGLdRfpylWQ+nLKdXtjiFPB1BKKA0UeVLwKg8R6igBtmV26dcrmxUypRHKK0KwoAfcqfPPP17X9EqGq3SW0OBs6kGK9Pl69PpRLBnbJuT8PCSGpg9o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641237; c=relaxed/simple; bh=Ee/5VC+eO+oJ1PEBoNfOcUfeEeUQgTRrQThR619JMlQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=nUnP+Rkx1xeyqhQBO+49siOmcRT5jd/A/1WouDRHYMhZRsnrlj5ea49SqQ+gjZQCUqPKl4hXgmEMcL2NPm11q5ExbcZ4abh2+ZQXcKRkrNcELuOiZt/GUWYj97VoPNOkf0fzOHwA7yhPu8rSvywYIGxD+FXRbHp0v0/WV2F+Ong= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MmZouf0N; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MmZouf0N" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 45002C4CEFF; Tue, 28 Oct 2025 08:47:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641237; bh=Ee/5VC+eO+oJ1PEBoNfOcUfeEeUQgTRrQThR619JMlQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=MmZouf0NmYXxDYINcZZgbWXVN1krmfTSPaSvhWBXFFGVot+GtgOP5HGsYEMTvB94n lZQ27Gg5gjw58n/QMT2VeQZOdyo8t7aozbLdajGBnwwan05oicNgsg7pTLLZ8y/FEI f2I8dmGJ6L3iC93xQwJIqXq7iiQ5bOJpKJE1Hv0F680RpeJ+iINLvO/IhGxl1a975+ nmyzriJhLlpR5kDvcfZDBXkC3H6zjjsoPiOJy/NfvzCMNctcqzlGqwLz9Tnxzz2iCR GUP7QeQBq99lkNke1Ueh/9a5mWWYjf2LCMfY2gkOjF2Tz0s+vZW01IOl7TPK/sq38o b7fT0+gS5ruIQ== From: Christian Brauner Date: Tue, 28 Oct 2025 09:46:02 +0100 Subject: [PATCH 17/22] selftests/coredump: add debug logging to test helpers Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-17-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=4675; i=brauner@kernel.org; h=from:subject:message-id; bh=Ee/5VC+eO+oJ1PEBoNfOcUfeEeUQgTRrQThR619JMlQ=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB2acfB59dl6ja6rgeu/qSSt8ngkMvtXsku4wDeXx Ck/X0lqdJSyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAExEqY/hf1lATsrBhb84DS/m rjaXyBCZfOb6lFmf2WdWPL/24W5kUynDP33ndA8nlvIy/3vLVJTnqgjFHJjcf9XedupT92zpNL3 pTAA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 so we can easily figure out why something failed. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- .../selftests/coredump/coredump_test_helpers.c | 55 +++++++++++++++++-= ---- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/tools/testing/selftests/coredump/coredump_test_helpers.c b/too= ls/testing/selftests/coredump/coredump_test_helpers.c index 116c797090a1..65deb3cfbe1b 100644 --- a/tools/testing/selftests/coredump/coredump_test_helpers.c +++ b/tools/testing/selftests/coredump/coredump_test_helpers.c @@ -131,17 +131,26 @@ int get_peer_pidfd(int fd) int ret =3D getsockopt(fd, SOL_SOCKET, SO_PEERPIDFD, &fd_peer_pidfd, &fd_peer_pidfd_len); if (ret < 0) { - fprintf(stderr, "%m - Failed to retrieve peer pidfd for coredump socket = connection\n"); + fprintf(stderr, "get_peer_pidfd: getsockopt(SO_PEERPIDFD) failed: %m\n"); return -1; } + fprintf(stderr, "get_peer_pidfd: successfully retrieved pidfd %d\n", fd_p= eer_pidfd); return fd_peer_pidfd; } =20 bool get_pidfd_info(int fd_peer_pidfd, struct pidfd_info *info) { + int ret; memset(info, 0, sizeof(*info)); info->mask =3D PIDFD_INFO_EXIT | PIDFD_INFO_COREDUMP | PIDFD_INFO_COREDUM= P_SIGNAL; - return ioctl(fd_peer_pidfd, PIDFD_GET_INFO, info) =3D=3D 0; + ret =3D ioctl(fd_peer_pidfd, PIDFD_GET_INFO, info); + if (ret < 0) { + fprintf(stderr, "get_pidfd_info: ioctl(PIDFD_GET_INFO) failed: %m\n"); + return false; + } + fprintf(stderr, "get_pidfd_info: mask=3D0x%llx, coredump_mask=3D0x%x, cor= edump_signal=3D%d\n", + (unsigned long long)info->mask, info->coredump_mask, info->coredump_sign= al); + return true; } =20 /* Protocol helper functions */ @@ -198,14 +207,23 @@ bool read_coredump_req(int fd, struct coredump_req *r= eq) =20 /* Peek the size of the coredump request. */ ret =3D recv(fd, req, field_size, MSG_PEEK | MSG_WAITALL); - if (ret !=3D field_size) + if (ret !=3D field_size) { + fprintf(stderr, "read_coredump_req: peek failed (got %zd, expected %zu):= %m\n", + ret, field_size); return false; + } kernel_size =3D req->size; =20 - if (kernel_size < COREDUMP_ACK_SIZE_VER0) + if (kernel_size < COREDUMP_ACK_SIZE_VER0) { + fprintf(stderr, "read_coredump_req: kernel_size %zu < min %d\n", + kernel_size, COREDUMP_ACK_SIZE_VER0); return false; - if (kernel_size >=3D PAGE_SIZE) + } + if (kernel_size >=3D PAGE_SIZE) { + fprintf(stderr, "read_coredump_req: kernel_size %zu >=3D PAGE_SIZE %d\n", + kernel_size, PAGE_SIZE); return false; + } =20 /* Use the minimum of user and kernel size to read the full request. */ user_size =3D sizeof(struct coredump_req); @@ -295,25 +313,35 @@ void process_coredump_worker(int fd_coredump, int fd_= peer_pidfd, int fd_core_fil =20 /* Set socket to non-blocking mode for edge-triggered epoll */ flags =3D fcntl(fd_coredump, F_GETFL, 0); - if (flags < 0) + if (flags < 0) { + fprintf(stderr, "Worker: fcntl(F_GETFL) failed: %m\n"); goto out; - if (fcntl(fd_coredump, F_SETFL, flags | O_NONBLOCK) < 0) + } + if (fcntl(fd_coredump, F_SETFL, flags | O_NONBLOCK) < 0) { + fprintf(stderr, "Worker: fcntl(F_SETFL, O_NONBLOCK) failed: %m\n"); goto out; + } =20 epfd =3D epoll_create1(0); - if (epfd < 0) + if (epfd < 0) { + fprintf(stderr, "Worker: epoll_create1() failed: %m\n"); goto out; + } =20 ev.events =3D EPOLLIN | EPOLLRDHUP | EPOLLET; ev.data.fd =3D fd_coredump; - if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd_coredump, &ev) < 0) + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd_coredump, &ev) < 0) { + fprintf(stderr, "Worker: epoll_ctl(EPOLL_CTL_ADD) failed: %m\n"); goto out; + } =20 for (;;) { struct epoll_event events[1]; int n =3D epoll_wait(epfd, events, 1, -1); - if (n < 0) + if (n < 0) { + fprintf(stderr, "Worker: epoll_wait() failed: %m\n"); break; + } =20 if (events[0].events & (EPOLLIN | EPOLLRDHUP)) { for (;;) { @@ -322,19 +350,24 @@ void process_coredump_worker(int fd_coredump, int fd_= peer_pidfd, int fd_core_fil if (bytes_read < 0) { if (errno =3D=3D EAGAIN || errno =3D=3D EWOULDBLOCK) break; + fprintf(stderr, "Worker: read() failed: %m\n"); goto out; } if (bytes_read =3D=3D 0) goto done; ssize_t bytes_write =3D write(fd_core_file, buffer, bytes_read); - if (bytes_write !=3D bytes_read) + if (bytes_write !=3D bytes_read) { + fprintf(stderr, "Worker: write() failed (read=3D%zd, write=3D%zd): %m= \n", + bytes_read, bytes_write); goto out; + } } } } =20 done: exit_code =3D EXIT_SUCCESS; + fprintf(stderr, "Worker: completed successfully\n"); out: if (epfd >=3D 0) close(epfd); --=20 2.47.3 From nobody Sun Feb 8 12:14:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 537432D97AA; Tue, 28 Oct 2025 08:47:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641241; cv=none; b=Bmryflh2ZvwlRJglbhF1hU9xm0op0GftPZyN8rhpjp0fhTUoLqXjzOYIAtk/fztt8nP8+TMxP4ZQRXxlDDyMbLNnnkcza4b3vc+SwIwNNYx7EVPlo/hy+RbrWYeS6uM2EDAjRuxrIs0ocWGGzTfkx4J2Fz29Vaw3Y/Y2eLe/j9M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641241; c=relaxed/simple; bh=W4SO4YgiNboWrYou0wEK2OcL63i4VEU6YP08vXBx5ss=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dQbdhfC7eUQWNUZ2NKs+Xg07dgV+hI/6MurZJ22JsyPjqruBzLXBMXoeQ1xxtzJXNIywck+RtIqZknbWEbd8VLsUQDCI4N/H5eeB8umQkrXkNW7AyEM3Nesahj1sAz7x3VZgAugwQuDQ4zlR1O+R7s5+aF3KQXEiCjwwcSopQB4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jzrUJVB9; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jzrUJVB9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 73142C4CEE7; Tue, 28 Oct 2025 08:47:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641241; bh=W4SO4YgiNboWrYou0wEK2OcL63i4VEU6YP08vXBx5ss=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=jzrUJVB9eB/ktS4ejdQ4NWg3X2JVvyxyez+v7RkKMxZxlr+ub+eN1zD0CkYrWx7pP Nq3p8GLF4QR6JMK++/qNZmqVvJ1A0MaWB1Ojq933NQawLo9M9ib9HnJ4MIKS1pMUeL L+CxCnlMJt4W8X2UrEdn6K9/PPdQeYng9oprY05HbuCTw8IRep0kQJ80wi8T41lCX+ va2v4fY6UfvSBKwV0IyygkCg1N3U498ggYUTvKcNairSSuWcvpiNkzOebrahC949Jk vG1U+Yt2UZHgm+pZfZTMBPv30tnXa9FLCzIs9uo7d5KqqjqaM+XulOz9lWETTsPBS2 H2d+6gyip+WnA== From: Christian Brauner Date: Tue, 28 Oct 2025 09:46:03 +0100 Subject: [PATCH 18/22] selftests/coredump: add debug logging to coredump socket tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-18-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=6475; i=brauner@kernel.org; h=from:subject:message-id; bh=W4SO4YgiNboWrYou0wEK2OcL63i4VEU6YP08vXBx5ss=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB36XOiS7T+380PE1DMbri7bnentXV2wccuxsxsXS yfeFH9b31HKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjCRDhZGhl9yfM7H73F+uLBf pNJfcOKDu0u1n69QYDkQwLDngtJkTk6G/9kif+9Z/RFfffO85YXdjcIndfWOr0/+XFM/00Pj8yV WEx4A X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 So it's easier to figure out bugs. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- .../selftests/coredump/coredump_socket_test.c | 93 +++++++++++++++++-= ---- 1 file changed, 71 insertions(+), 22 deletions(-) diff --git a/tools/testing/selftests/coredump/coredump_socket_test.c b/tool= s/testing/selftests/coredump/coredump_socket_test.c index 5103d9f13003..0a37d0456672 100644 --- a/tools/testing/selftests/coredump/coredump_socket_test.c +++ b/tools/testing/selftests/coredump/coredump_socket_test.c @@ -98,52 +98,74 @@ TEST_F(coredump, socket) close(ipc_sockets[0]); =20 fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) + if (fd_server < 0) { + fprintf(stderr, "socket test: create_and_listen_unix_socket failed: %m\= n"); goto out; + } =20 - if (write_nointr(ipc_sockets[1], "1", 1) < 0) + if (write_nointr(ipc_sockets[1], "1", 1) < 0) { + fprintf(stderr, "socket test: write_nointr to ipc socket failed: %m\n"); goto out; + } =20 close(ipc_sockets[1]); =20 fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) + if (fd_coredump < 0) { + fprintf(stderr, "socket test: accept4 failed: %m\n"); goto out; + } =20 fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) + if (fd_peer_pidfd < 0) { + fprintf(stderr, "socket test: get_peer_pidfd failed\n"); goto out; + } =20 - if (!get_pidfd_info(fd_peer_pidfd, &info)) + if (!get_pidfd_info(fd_peer_pidfd, &info)) { + fprintf(stderr, "socket test: get_pidfd_info failed\n"); goto out; + } =20 - if (!(info.mask & PIDFD_INFO_COREDUMP)) + if (!(info.mask & PIDFD_INFO_COREDUMP)) { + fprintf(stderr, "socket test: PIDFD_INFO_COREDUMP not set in mask\n"); goto out; + } =20 - if (!(info.coredump_mask & PIDFD_COREDUMPED)) + if (!(info.coredump_mask & PIDFD_COREDUMPED)) { + fprintf(stderr, "socket test: PIDFD_COREDUMPED not set in coredump_mask= \n"); goto out; + } =20 fd_core_file =3D creat("/tmp/coredump.file", 0644); - if (fd_core_file < 0) + if (fd_core_file < 0) { + fprintf(stderr, "socket test: creat coredump file failed: %m\n"); goto out; + } =20 for (;;) { char buffer[4096]; ssize_t bytes_read, bytes_write; =20 bytes_read =3D read(fd_coredump, buffer, sizeof(buffer)); - if (bytes_read < 0) + if (bytes_read < 0) { + fprintf(stderr, "socket test: read from coredump socket failed: %m\n"); goto out; + } =20 if (bytes_read =3D=3D 0) break; =20 bytes_write =3D write(fd_core_file, buffer, bytes_read); - if (bytes_read !=3D bytes_write) + if (bytes_read !=3D bytes_write) { + fprintf(stderr, "socket test: write to core file failed (read=3D%zd, w= rite=3D%zd): %m\n", + bytes_read, bytes_write); goto out; + } } =20 exit_code =3D EXIT_SUCCESS; + fprintf(stderr, "socket test: completed successfully\n"); out: if (fd_core_file >=3D 0) close(fd_core_file); @@ -208,32 +230,47 @@ TEST_F(coredump, socket_detect_userspace_client) close(ipc_sockets[0]); =20 fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) + if (fd_server < 0) { + fprintf(stderr, "socket_detect_userspace_client: create_and_listen_unix= _socket failed: %m\n"); goto out; + } =20 - if (write_nointr(ipc_sockets[1], "1", 1) < 0) + if (write_nointr(ipc_sockets[1], "1", 1) < 0) { + fprintf(stderr, "socket_detect_userspace_client: write_nointr to ipc so= cket failed: %m\n"); goto out; + } =20 close(ipc_sockets[1]); =20 fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) + if (fd_coredump < 0) { + fprintf(stderr, "socket_detect_userspace_client: accept4 failed: %m\n"); goto out; + } =20 fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) + if (fd_peer_pidfd < 0) { + fprintf(stderr, "socket_detect_userspace_client: get_peer_pidfd failed\= n"); goto out; + } =20 - if (!get_pidfd_info(fd_peer_pidfd, &info)) + if (!get_pidfd_info(fd_peer_pidfd, &info)) { + fprintf(stderr, "socket_detect_userspace_client: get_pidfd_info failed\= n"); goto out; + } =20 - if (!(info.mask & PIDFD_INFO_COREDUMP)) + if (!(info.mask & PIDFD_INFO_COREDUMP)) { + fprintf(stderr, "socket_detect_userspace_client: PIDFD_INFO_COREDUMP no= t set in mask\n"); goto out; + } =20 - if (info.coredump_mask & PIDFD_COREDUMPED) + if (info.coredump_mask & PIDFD_COREDUMPED) { + fprintf(stderr, "socket_detect_userspace_client: PIDFD_COREDUMPED incor= rectly set (should be userspace client)\n"); goto out; + } =20 exit_code =3D EXIT_SUCCESS; + fprintf(stderr, "socket_detect_userspace_client: completed successfully\= n"); out: if (fd_peer_pidfd >=3D 0) close(fd_peer_pidfd); @@ -263,15 +300,20 @@ TEST_F(coredump, socket_detect_userspace_client) sizeof("/tmp/coredump.socket"); =20 fd_socket =3D socket(AF_UNIX, SOCK_STREAM, 0); - if (fd_socket < 0) + if (fd_socket < 0) { + fprintf(stderr, "socket_detect_userspace_client (client): socket failed= : %m\n"); _exit(EXIT_FAILURE); + } =20 ret =3D connect(fd_socket, (const struct sockaddr *)&coredump_sk, coredu= mp_sk_len); - if (ret < 0) + if (ret < 0) { + fprintf(stderr, "socket_detect_userspace_client (client): connect faile= d: %m\n"); _exit(EXIT_FAILURE); + } =20 close(fd_socket); pause(); + fprintf(stderr, "socket_detect_userspace_client (client): completed succ= essfully\n"); _exit(EXIT_SUCCESS); } =20 @@ -342,17 +384,24 @@ TEST_F(coredump, socket_no_listener) close(ipc_sockets[0]); =20 fd_server =3D socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); - if (fd_server < 0) + if (fd_server < 0) { + fprintf(stderr, "socket_no_listener: socket failed: %m\n"); goto out; + } =20 ret =3D bind(fd_server, (const struct sockaddr *)&coredump_sk, coredump_= sk_len); - if (ret < 0) + if (ret < 0) { + fprintf(stderr, "socket_no_listener: bind failed: %m\n"); goto out; + } =20 - if (write_nointr(ipc_sockets[1], "1", 1) < 0) + if (write_nointr(ipc_sockets[1], "1", 1) < 0) { + fprintf(stderr, "socket_no_listener: write_nointr to ipc socket failed:= %m\n"); goto out; + } =20 exit_code =3D EXIT_SUCCESS; + fprintf(stderr, "socket_no_listener: completed successfully\n"); out: if (fd_server >=3D 0) close(fd_server); --=20 2.47.3 From nobody Sun Feb 8 12:14:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E71ED2D97AA; Tue, 28 Oct 2025 08:47:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641246; cv=none; b=kZGkduHSlSIDNwM8l3A6DBhK+NlMtmcSs5TRhNiz2niT0ScIemtGbG9um5q+PrbbX9GgJg0+xlgNy6GvMHclFRESg8Oifi4HEktTbiwlOmAodkgdeEle4Fr5+B1HHis5/R4KPLy06DNGgi+HcC6aOwkKA5czWEK6P55+vgL56hU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641246; c=relaxed/simple; bh=uKu3QHfWqGHnfWV7aYA2McoSNkcMQko2AYCbqlm6Q8s=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LqPaYxONkwYTHB8mC954JhptmkuJ1gtTmg4uCwgHvRMgZTXSWItdPv4gR0QVOc8gw0tNuxURt5UWqNLdfs0C5hqIW38YjYmZ3Cm/2kumC1NI4ZSDGPeuvxumLNL2s5X61OPV47Jc9RlsB/7DxMbf4FyU06fAUlzKcsLvjWACJIg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aFHkyMMg; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="aFHkyMMg" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B928FC4CEE7; Tue, 28 Oct 2025 08:47:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641245; bh=uKu3QHfWqGHnfWV7aYA2McoSNkcMQko2AYCbqlm6Q8s=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=aFHkyMMgTKQESkf2gakjNcardarkVk6lFrWYftYRkAaPhamURLRUMflK46g+g0T+2 cW2CuHnvVTRh/j/31ccrGuVGam+My20RQAu41d4JPlALwHInQbZ0UIt7OmF3R8nO5O vpfE2ZUk8ZaZAMlwwo748AaTGBdGnAGPZ/SSM+mJ253uruVf2yf38W6KINYZFF8Cnu bWO2y2pHK3dH1zE8LkAq9VEBYkPKjUB92aGA0wVtXuQUbu/w3yEUxKDdfM1nC7jLWc oHgPQXuerIU+0KiRPXE3gS7u35uptW0GuiDn9LGA6yNv650dQJBehRa4WTa8vtEfsJ 4I9k/UwghieAw== From: Christian Brauner Date: Tue, 28 Oct 2025 09:46:04 +0100 Subject: [PATCH 19/22] selftests/coredump: add debug logging to coredump socket protocol tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-19-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=31685; i=brauner@kernel.org; h=from:subject:message-id; bh=uKu3QHfWqGHnfWV7aYA2McoSNkcMQko2AYCbqlm6Q8s=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB2SnDHpXeB7m2i3WZPDe3y5/Nlbgpu2SkiEKYkez nDylEjoKGVhEONikBVTZHFoNwmXW85TsdkoUwNmDisTyBAGLk4BmIhfAiPDjtzyUgNXFda47VdW XDoyK2RSzuqv3NNYluf/39PT8e/NT4Z/VtlHC7w3vN3/5TDbNNN5xyXyu5k9YrhzTbe/3qEkH+v PDwA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 So it's easier to figure out bugs. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- .../coredump/coredump_socket_protocol_test.c | 485 ++++++++++++++++-= ---- 1 file changed, 367 insertions(+), 118 deletions(-) diff --git a/tools/testing/selftests/coredump/coredump_socket_protocol_test= .c b/tools/testing/selftests/coredump/coredump_socket_protocol_test.c index cc7364499c55..566545e96d7f 100644 --- a/tools/testing/selftests/coredump/coredump_socket_protocol_test.c +++ b/tools/testing/selftests/coredump/coredump_socket_protocol_test.c @@ -101,67 +101,97 @@ TEST_F(coredump, socket_request_kernel) close(ipc_sockets[0]); =20 fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) + if (fd_server < 0) { + fprintf(stderr, "socket_request_kernel: create_and_listen_unix_socket f= ailed: %m\n"); goto out; + } =20 - if (write_nointr(ipc_sockets[1], "1", 1) < 0) + if (write_nointr(ipc_sockets[1], "1", 1) < 0) { + fprintf(stderr, "socket_request_kernel: write_nointr to ipc socket fail= ed: %m\n"); goto out; + } =20 close(ipc_sockets[1]); =20 fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) + if (fd_coredump < 0) { + fprintf(stderr, "socket_request_kernel: accept4 failed: %m\n"); goto out; + } =20 fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) + if (fd_peer_pidfd < 0) { + fprintf(stderr, "socket_request_kernel: get_peer_pidfd failed\n"); goto out; + } =20 - if (!get_pidfd_info(fd_peer_pidfd, &info)) + if (!get_pidfd_info(fd_peer_pidfd, &info)) { + fprintf(stderr, "socket_request_kernel: get_pidfd_info failed\n"); goto out; + } =20 - if (!(info.mask & PIDFD_INFO_COREDUMP)) + if (!(info.mask & PIDFD_INFO_COREDUMP)) { + fprintf(stderr, "socket_request_kernel: PIDFD_INFO_COREDUMP not set in = mask\n"); goto out; + } =20 - if (!(info.coredump_mask & PIDFD_COREDUMPED)) + if (!(info.coredump_mask & PIDFD_COREDUMPED)) { + fprintf(stderr, "socket_request_kernel: PIDFD_COREDUMPED not set in cor= edump_mask\n"); goto out; + } =20 fd_core_file =3D creat("/tmp/coredump.file", 0644); - if (fd_core_file < 0) + if (fd_core_file < 0) { + fprintf(stderr, "socket_request_kernel: creat coredump file failed: %m\= n"); goto out; + } =20 - if (!read_coredump_req(fd_coredump, &req)) + if (!read_coredump_req(fd_coredump, &req)) { + fprintf(stderr, "socket_request_kernel: read_coredump_req failed\n"); goto out; + } =20 if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, COREDUMP_KERNEL | COREDUMP_USERSPACE | - COREDUMP_REJECT | COREDUMP_WAIT)) + COREDUMP_REJECT | COREDUMP_WAIT)) { + fprintf(stderr, "socket_request_kernel: check_coredump_req failed\n"); goto out; + } =20 if (!send_coredump_ack(fd_coredump, &req, - COREDUMP_KERNEL | COREDUMP_WAIT, 0)) + COREDUMP_KERNEL | COREDUMP_WAIT, 0)) { + fprintf(stderr, "socket_request_kernel: send_coredump_ack failed\n"); goto out; + } =20 - if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) + if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) { + fprintf(stderr, "socket_request_kernel: read_marker COREDUMP_MARK_REQAC= K failed\n"); goto out; + } =20 for (;;) { char buffer[4096]; ssize_t bytes_read, bytes_write; =20 bytes_read =3D read(fd_coredump, buffer, sizeof(buffer)); - if (bytes_read < 0) + if (bytes_read < 0) { + fprintf(stderr, "socket_request_kernel: read from coredump socket fail= ed: %m\n"); goto out; + } =20 if (bytes_read =3D=3D 0) break; =20 bytes_write =3D write(fd_core_file, buffer, bytes_read); - if (bytes_read !=3D bytes_write) + if (bytes_read !=3D bytes_write) { + fprintf(stderr, "socket_request_kernel: write to core file failed (rea= d=3D%zd, write=3D%zd): %m\n", + bytes_read, bytes_write); goto out; + } } =20 exit_code =3D EXIT_SUCCESS; + fprintf(stderr, "socket_request_kernel: completed successfully\n"); out: if (fd_core_file >=3D 0) close(fd_core_file); @@ -225,62 +255,89 @@ TEST_F(coredump, socket_request_userspace) close(ipc_sockets[0]); =20 fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) + if (fd_server < 0) { + fprintf(stderr, "socket_request_userspace: create_and_listen_unix_socke= t failed: %m\n"); goto out; + } =20 - if (write_nointr(ipc_sockets[1], "1", 1) < 0) + if (write_nointr(ipc_sockets[1], "1", 1) < 0) { + fprintf(stderr, "socket_request_userspace: write_nointr to ipc socket f= ailed: %m\n"); goto out; + } =20 close(ipc_sockets[1]); =20 fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) + if (fd_coredump < 0) { + fprintf(stderr, "socket_request_userspace: accept4 failed: %m\n"); goto out; + } =20 fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) + if (fd_peer_pidfd < 0) { + fprintf(stderr, "socket_request_userspace: get_peer_pidfd failed\n"); goto out; + } =20 - if (!get_pidfd_info(fd_peer_pidfd, &info)) + if (!get_pidfd_info(fd_peer_pidfd, &info)) { + fprintf(stderr, "socket_request_userspace: get_pidfd_info failed\n"); goto out; + } =20 - if (!(info.mask & PIDFD_INFO_COREDUMP)) + if (!(info.mask & PIDFD_INFO_COREDUMP)) { + fprintf(stderr, "socket_request_userspace: PIDFD_INFO_COREDUMP not set = in mask\n"); goto out; + } =20 - if (!(info.coredump_mask & PIDFD_COREDUMPED)) + if (!(info.coredump_mask & PIDFD_COREDUMPED)) { + fprintf(stderr, "socket_request_userspace: PIDFD_COREDUMPED not set in = coredump_mask\n"); goto out; + } =20 - if (!read_coredump_req(fd_coredump, &req)) + if (!read_coredump_req(fd_coredump, &req)) { + fprintf(stderr, "socket_request_userspace: read_coredump_req failed\n"); goto out; + } =20 if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, COREDUMP_KERNEL | COREDUMP_USERSPACE | - COREDUMP_REJECT | COREDUMP_WAIT)) + COREDUMP_REJECT | COREDUMP_WAIT)) { + fprintf(stderr, "socket_request_userspace: check_coredump_req failed\n"= ); goto out; + } =20 if (!send_coredump_ack(fd_coredump, &req, - COREDUMP_USERSPACE | COREDUMP_WAIT, 0)) + COREDUMP_USERSPACE | COREDUMP_WAIT, 0)) { + fprintf(stderr, "socket_request_userspace: send_coredump_ack failed\n"); goto out; + } =20 - if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) + if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) { + fprintf(stderr, "socket_request_userspace: read_marker COREDUMP_MARK_RE= QACK failed\n"); goto out; + } =20 for (;;) { char buffer[4096]; ssize_t bytes_read; =20 bytes_read =3D read(fd_coredump, buffer, sizeof(buffer)); - if (bytes_read > 0) + if (bytes_read > 0) { + fprintf(stderr, "socket_request_userspace: unexpected data received (e= xpected no coredump data)\n"); goto out; + } =20 - if (bytes_read < 0) + if (bytes_read < 0) { + fprintf(stderr, "socket_request_userspace: read from coredump socket f= ailed: %m\n"); goto out; + } =20 if (bytes_read =3D=3D 0) break; } =20 exit_code =3D EXIT_SUCCESS; + fprintf(stderr, "socket_request_userspace: completed successfully\n"); out: if (fd_peer_pidfd >=3D 0) close(fd_peer_pidfd); @@ -338,62 +395,89 @@ TEST_F(coredump, socket_request_reject) close(ipc_sockets[0]); =20 fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) + if (fd_server < 0) { + fprintf(stderr, "socket_request_reject: create_and_listen_unix_socket f= ailed: %m\n"); goto out; + } =20 - if (write_nointr(ipc_sockets[1], "1", 1) < 0) + if (write_nointr(ipc_sockets[1], "1", 1) < 0) { + fprintf(stderr, "socket_request_reject: write_nointr to ipc socket fail= ed: %m\n"); goto out; + } =20 close(ipc_sockets[1]); =20 fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) + if (fd_coredump < 0) { + fprintf(stderr, "socket_request_reject: accept4 failed: %m\n"); goto out; + } =20 fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) + if (fd_peer_pidfd < 0) { + fprintf(stderr, "socket_request_reject: get_peer_pidfd failed\n"); goto out; + } =20 - if (!get_pidfd_info(fd_peer_pidfd, &info)) + if (!get_pidfd_info(fd_peer_pidfd, &info)) { + fprintf(stderr, "socket_request_reject: get_pidfd_info failed\n"); goto out; + } =20 - if (!(info.mask & PIDFD_INFO_COREDUMP)) + if (!(info.mask & PIDFD_INFO_COREDUMP)) { + fprintf(stderr, "socket_request_reject: PIDFD_INFO_COREDUMP not set in = mask\n"); goto out; + } =20 - if (!(info.coredump_mask & PIDFD_COREDUMPED)) + if (!(info.coredump_mask & PIDFD_COREDUMPED)) { + fprintf(stderr, "socket_request_reject: PIDFD_COREDUMPED not set in cor= edump_mask\n"); goto out; + } =20 - if (!read_coredump_req(fd_coredump, &req)) + if (!read_coredump_req(fd_coredump, &req)) { + fprintf(stderr, "socket_request_reject: read_coredump_req failed\n"); goto out; + } =20 if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, COREDUMP_KERNEL | COREDUMP_USERSPACE | - COREDUMP_REJECT | COREDUMP_WAIT)) + COREDUMP_REJECT | COREDUMP_WAIT)) { + fprintf(stderr, "socket_request_reject: check_coredump_req failed\n"); goto out; + } =20 if (!send_coredump_ack(fd_coredump, &req, - COREDUMP_REJECT | COREDUMP_WAIT, 0)) + COREDUMP_REJECT | COREDUMP_WAIT, 0)) { + fprintf(stderr, "socket_request_reject: send_coredump_ack failed\n"); goto out; + } =20 - if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) + if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) { + fprintf(stderr, "socket_request_reject: read_marker COREDUMP_MARK_REQAC= K failed\n"); goto out; + } =20 for (;;) { char buffer[4096]; ssize_t bytes_read; =20 bytes_read =3D read(fd_coredump, buffer, sizeof(buffer)); - if (bytes_read > 0) + if (bytes_read > 0) { + fprintf(stderr, "socket_request_reject: unexpected data received (expe= cted no coredump data for REJECT)\n"); goto out; + } =20 - if (bytes_read < 0) + if (bytes_read < 0) { + fprintf(stderr, "socket_request_reject: read from coredump socket fail= ed: %m\n"); goto out; + } =20 if (bytes_read =3D=3D 0) break; } =20 exit_code =3D EXIT_SUCCESS; + fprintf(stderr, "socket_request_reject: completed successfully\n"); out: if (fd_peer_pidfd >=3D 0) close(fd_peer_pidfd); @@ -451,47 +535,70 @@ TEST_F(coredump, socket_request_invalid_flag_combinat= ion) close(ipc_sockets[0]); =20 fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) + if (fd_server < 0) { + fprintf(stderr, "socket_request_invalid_flag_combination: create_and_li= sten_unix_socket failed: %m\n"); goto out; + } =20 - if (write_nointr(ipc_sockets[1], "1", 1) < 0) + if (write_nointr(ipc_sockets[1], "1", 1) < 0) { + fprintf(stderr, "socket_request_invalid_flag_combination: write_nointr = to ipc socket failed: %m\n"); goto out; + } =20 close(ipc_sockets[1]); =20 fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) + if (fd_coredump < 0) { + fprintf(stderr, "socket_request_invalid_flag_combination: accept4 faile= d: %m\n"); goto out; + } =20 fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) + if (fd_peer_pidfd < 0) { + fprintf(stderr, "socket_request_invalid_flag_combination: get_peer_pidf= d failed\n"); goto out; + } =20 - if (!get_pidfd_info(fd_peer_pidfd, &info)) + if (!get_pidfd_info(fd_peer_pidfd, &info)) { + fprintf(stderr, "socket_request_invalid_flag_combination: get_pidfd_inf= o failed\n"); goto out; + } =20 - if (!(info.mask & PIDFD_INFO_COREDUMP)) + if (!(info.mask & PIDFD_INFO_COREDUMP)) { + fprintf(stderr, "socket_request_invalid_flag_combination: PIDFD_INFO_CO= REDUMP not set in mask\n"); goto out; + } =20 - if (!(info.coredump_mask & PIDFD_COREDUMPED)) + if (!(info.coredump_mask & PIDFD_COREDUMPED)) { + fprintf(stderr, "socket_request_invalid_flag_combination: PIDFD_COREDUM= PED not set in coredump_mask\n"); goto out; + } =20 - if (!read_coredump_req(fd_coredump, &req)) + if (!read_coredump_req(fd_coredump, &req)) { + fprintf(stderr, "socket_request_invalid_flag_combination: read_coredump= _req failed\n"); goto out; + } =20 if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, COREDUMP_KERNEL | COREDUMP_USERSPACE | - COREDUMP_REJECT | COREDUMP_WAIT)) + COREDUMP_REJECT | COREDUMP_WAIT)) { + fprintf(stderr, "socket_request_invalid_flag_combination: check_coredum= p_req failed\n"); goto out; + } =20 if (!send_coredump_ack(fd_coredump, &req, - COREDUMP_KERNEL | COREDUMP_REJECT | COREDUMP_WAIT, 0)) + COREDUMP_KERNEL | COREDUMP_REJECT | COREDUMP_WAIT, 0)) { + fprintf(stderr, "socket_request_invalid_flag_combination: send_coredump= _ack failed\n"); goto out; + } =20 - if (!read_marker(fd_coredump, COREDUMP_MARK_CONFLICTING)) + if (!read_marker(fd_coredump, COREDUMP_MARK_CONFLICTING)) { + fprintf(stderr, "socket_request_invalid_flag_combination: read_marker C= OREDUMP_MARK_CONFLICTING failed\n"); goto out; + } =20 exit_code =3D EXIT_SUCCESS; + fprintf(stderr, "socket_request_invalid_flag_combination: completed succ= essfully\n"); out: if (fd_peer_pidfd >=3D 0) close(fd_peer_pidfd); @@ -549,46 +656,69 @@ TEST_F(coredump, socket_request_unknown_flag) close(ipc_sockets[0]); =20 fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) + if (fd_server < 0) { + fprintf(stderr, "socket_request_unknown_flag: create_and_listen_unix_so= cket failed: %m\n"); goto out; + } =20 - if (write_nointr(ipc_sockets[1], "1", 1) < 0) + if (write_nointr(ipc_sockets[1], "1", 1) < 0) { + fprintf(stderr, "socket_request_unknown_flag: write_nointr to ipc socke= t failed: %m\n"); goto out; + } =20 close(ipc_sockets[1]); =20 fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) + if (fd_coredump < 0) { + fprintf(stderr, "socket_request_unknown_flag: accept4 failed: %m\n"); goto out; + } =20 fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) + if (fd_peer_pidfd < 0) { + fprintf(stderr, "socket_request_unknown_flag: get_peer_pidfd failed\n"); goto out; + } =20 - if (!get_pidfd_info(fd_peer_pidfd, &info)) + if (!get_pidfd_info(fd_peer_pidfd, &info)) { + fprintf(stderr, "socket_request_unknown_flag: get_pidfd_info failed\n"); goto out; + } =20 - if (!(info.mask & PIDFD_INFO_COREDUMP)) + if (!(info.mask & PIDFD_INFO_COREDUMP)) { + fprintf(stderr, "socket_request_unknown_flag: PIDFD_INFO_COREDUMP not s= et in mask\n"); goto out; + } =20 - if (!(info.coredump_mask & PIDFD_COREDUMPED)) + if (!(info.coredump_mask & PIDFD_COREDUMPED)) { + fprintf(stderr, "socket_request_unknown_flag: PIDFD_COREDUMPED not set = in coredump_mask\n"); goto out; + } =20 - if (!read_coredump_req(fd_coredump, &req)) + if (!read_coredump_req(fd_coredump, &req)) { + fprintf(stderr, "socket_request_unknown_flag: read_coredump_req failed\= n"); goto out; + } =20 if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, COREDUMP_KERNEL | COREDUMP_USERSPACE | - COREDUMP_REJECT | COREDUMP_WAIT)) + COREDUMP_REJECT | COREDUMP_WAIT)) { + fprintf(stderr, "socket_request_unknown_flag: check_coredump_req failed= \n"); goto out; + } =20 - if (!send_coredump_ack(fd_coredump, &req, (1ULL << 63), 0)) + if (!send_coredump_ack(fd_coredump, &req, (1ULL << 63), 0)) { + fprintf(stderr, "socket_request_unknown_flag: send_coredump_ack failed\= n"); goto out; + } =20 - if (!read_marker(fd_coredump, COREDUMP_MARK_UNSUPPORTED)) + if (!read_marker(fd_coredump, COREDUMP_MARK_UNSUPPORTED)) { + fprintf(stderr, "socket_request_unknown_flag: read_marker COREDUMP_MARK= _UNSUPPORTED failed\n"); goto out; + } =20 exit_code =3D EXIT_SUCCESS; + fprintf(stderr, "socket_request_unknown_flag: completed successfully\n"); out: if (fd_peer_pidfd >=3D 0) close(fd_peer_pidfd); @@ -646,48 +776,71 @@ TEST_F(coredump, socket_request_invalid_size_small) close(ipc_sockets[0]); =20 fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) + if (fd_server < 0) { + fprintf(stderr, "socket_request_invalid_size_small: create_and_listen_u= nix_socket failed: %m\n"); goto out; + } =20 - if (write_nointr(ipc_sockets[1], "1", 1) < 0) + if (write_nointr(ipc_sockets[1], "1", 1) < 0) { + fprintf(stderr, "socket_request_invalid_size_small: write_nointr to ipc= socket failed: %m\n"); goto out; + } =20 close(ipc_sockets[1]); =20 fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) + if (fd_coredump < 0) { + fprintf(stderr, "socket_request_invalid_size_small: accept4 failed: %m\= n"); goto out; + } =20 fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) + if (fd_peer_pidfd < 0) { + fprintf(stderr, "socket_request_invalid_size_small: get_peer_pidfd fail= ed\n"); goto out; + } =20 - if (!get_pidfd_info(fd_peer_pidfd, &info)) + if (!get_pidfd_info(fd_peer_pidfd, &info)) { + fprintf(stderr, "socket_request_invalid_size_small: get_pidfd_info fail= ed\n"); goto out; + } =20 - if (!(info.mask & PIDFD_INFO_COREDUMP)) + if (!(info.mask & PIDFD_INFO_COREDUMP)) { + fprintf(stderr, "socket_request_invalid_size_small: PIDFD_INFO_COREDUMP= not set in mask\n"); goto out; + } =20 - if (!(info.coredump_mask & PIDFD_COREDUMPED)) + if (!(info.coredump_mask & PIDFD_COREDUMPED)) { + fprintf(stderr, "socket_request_invalid_size_small: PIDFD_COREDUMPED no= t set in coredump_mask\n"); goto out; + } =20 - if (!read_coredump_req(fd_coredump, &req)) + if (!read_coredump_req(fd_coredump, &req)) { + fprintf(stderr, "socket_request_invalid_size_small: read_coredump_req f= ailed\n"); goto out; + } =20 if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, COREDUMP_KERNEL | COREDUMP_USERSPACE | - COREDUMP_REJECT | COREDUMP_WAIT)) + COREDUMP_REJECT | COREDUMP_WAIT)) { + fprintf(stderr, "socket_request_invalid_size_small: check_coredump_req = failed\n"); goto out; + } =20 if (!send_coredump_ack(fd_coredump, &req, COREDUMP_REJECT | COREDUMP_WAIT, - COREDUMP_ACK_SIZE_VER0 / 2)) + COREDUMP_ACK_SIZE_VER0 / 2)) { + fprintf(stderr, "socket_request_invalid_size_small: send_coredump_ack f= ailed\n"); goto out; + } =20 - if (!read_marker(fd_coredump, COREDUMP_MARK_MINSIZE)) + if (!read_marker(fd_coredump, COREDUMP_MARK_MINSIZE)) { + fprintf(stderr, "socket_request_invalid_size_small: read_marker COREDUM= P_MARK_MINSIZE failed\n"); goto out; + } =20 exit_code =3D EXIT_SUCCESS; + fprintf(stderr, "socket_request_invalid_size_small: completed successful= ly\n"); out: if (fd_peer_pidfd >=3D 0) close(fd_peer_pidfd); @@ -745,48 +898,71 @@ TEST_F(coredump, socket_request_invalid_size_large) close(ipc_sockets[0]); =20 fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) + if (fd_server < 0) { + fprintf(stderr, "socket_request_invalid_size_large: create_and_listen_u= nix_socket failed: %m\n"); goto out; + } =20 - if (write_nointr(ipc_sockets[1], "1", 1) < 0) + if (write_nointr(ipc_sockets[1], "1", 1) < 0) { + fprintf(stderr, "socket_request_invalid_size_large: write_nointr to ipc= socket failed: %m\n"); goto out; + } =20 close(ipc_sockets[1]); =20 fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) + if (fd_coredump < 0) { + fprintf(stderr, "socket_request_invalid_size_large: accept4 failed: %m\= n"); goto out; + } =20 fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) + if (fd_peer_pidfd < 0) { + fprintf(stderr, "socket_request_invalid_size_large: get_peer_pidfd fail= ed\n"); goto out; + } =20 - if (!get_pidfd_info(fd_peer_pidfd, &info)) + if (!get_pidfd_info(fd_peer_pidfd, &info)) { + fprintf(stderr, "socket_request_invalid_size_large: get_pidfd_info fail= ed\n"); goto out; + } =20 - if (!(info.mask & PIDFD_INFO_COREDUMP)) + if (!(info.mask & PIDFD_INFO_COREDUMP)) { + fprintf(stderr, "socket_request_invalid_size_large: PIDFD_INFO_COREDUMP= not set in mask\n"); goto out; + } =20 - if (!(info.coredump_mask & PIDFD_COREDUMPED)) + if (!(info.coredump_mask & PIDFD_COREDUMPED)) { + fprintf(stderr, "socket_request_invalid_size_large: PIDFD_COREDUMPED no= t set in coredump_mask\n"); goto out; + } =20 - if (!read_coredump_req(fd_coredump, &req)) + if (!read_coredump_req(fd_coredump, &req)) { + fprintf(stderr, "socket_request_invalid_size_large: read_coredump_req f= ailed\n"); goto out; + } =20 if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, COREDUMP_KERNEL | COREDUMP_USERSPACE | - COREDUMP_REJECT | COREDUMP_WAIT)) + COREDUMP_REJECT | COREDUMP_WAIT)) { + fprintf(stderr, "socket_request_invalid_size_large: check_coredump_req = failed\n"); goto out; + } =20 if (!send_coredump_ack(fd_coredump, &req, COREDUMP_REJECT | COREDUMP_WAIT, - COREDUMP_ACK_SIZE_VER0 + PAGE_SIZE)) + COREDUMP_ACK_SIZE_VER0 + PAGE_SIZE)) { + fprintf(stderr, "socket_request_invalid_size_large: send_coredump_ack f= ailed\n"); goto out; + } =20 - if (!read_marker(fd_coredump, COREDUMP_MARK_MAXSIZE)) + if (!read_marker(fd_coredump, COREDUMP_MARK_MAXSIZE)) { + fprintf(stderr, "socket_request_invalid_size_large: read_marker COREDUM= P_MARK_MAXSIZE failed\n"); goto out; + } =20 exit_code =3D EXIT_SUCCESS; + fprintf(stderr, "socket_request_invalid_size_large: completed successful= ly\n"); out: if (fd_peer_pidfd >=3D 0) close(fd_peer_pidfd); @@ -850,49 +1026,75 @@ TEST_F(coredump, socket_coredump_signal_sigsegv) close(ipc_sockets[0]); =20 fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) + if (fd_server < 0) { + fprintf(stderr, "socket_coredump_signal_sigsegv: create_and_listen_unix= _socket failed: %m\n"); goto out; + } =20 - if (write_nointr(ipc_sockets[1], "1", 1) < 0) + if (write_nointr(ipc_sockets[1], "1", 1) < 0) { + fprintf(stderr, "socket_coredump_signal_sigsegv: write_nointr to ipc so= cket failed: %m\n"); goto out; + } =20 close(ipc_sockets[1]); =20 fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) + if (fd_coredump < 0) { + fprintf(stderr, "socket_coredump_signal_sigsegv: accept4 failed: %m\n"); goto out; + } =20 fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) + if (fd_peer_pidfd < 0) { + fprintf(stderr, "socket_coredump_signal_sigsegv: get_peer_pidfd failed\= n"); goto out; + } =20 - if (!get_pidfd_info(fd_peer_pidfd, &info)) + if (!get_pidfd_info(fd_peer_pidfd, &info)) { + fprintf(stderr, "socket_coredump_signal_sigsegv: get_pidfd_info failed\= n"); goto out; + } =20 - if (!(info.mask & PIDFD_INFO_COREDUMP)) + if (!(info.mask & PIDFD_INFO_COREDUMP)) { + fprintf(stderr, "socket_coredump_signal_sigsegv: PIDFD_INFO_COREDUMP no= t set in mask\n"); goto out; + } =20 - if (!(info.coredump_mask & PIDFD_COREDUMPED)) + if (!(info.coredump_mask & PIDFD_COREDUMPED)) { + fprintf(stderr, "socket_coredump_signal_sigsegv: PIDFD_COREDUMPED not s= et in coredump_mask\n"); goto out; + } =20 /* Verify coredump_signal is available and correct */ - if (!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)) + if (!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)) { + fprintf(stderr, "socket_coredump_signal_sigsegv: PIDFD_INFO_COREDUMP_SI= GNAL not set in mask\n"); goto out; + } =20 - if (info.coredump_signal !=3D SIGSEGV) + if (info.coredump_signal !=3D SIGSEGV) { + fprintf(stderr, "socket_coredump_signal_sigsegv: coredump_signal=3D%d, = expected SIGSEGV=3D%d\n", + info.coredump_signal, SIGSEGV); goto out; + } =20 - if (!read_coredump_req(fd_coredump, &req)) + if (!read_coredump_req(fd_coredump, &req)) { + fprintf(stderr, "socket_coredump_signal_sigsegv: read_coredump_req fail= ed\n"); goto out; + } =20 if (!send_coredump_ack(fd_coredump, &req, - COREDUMP_REJECT | COREDUMP_WAIT, 0)) + COREDUMP_REJECT | COREDUMP_WAIT, 0)) { + fprintf(stderr, "socket_coredump_signal_sigsegv: send_coredump_ack fail= ed\n"); goto out; + } =20 - if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) + if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) { + fprintf(stderr, "socket_coredump_signal_sigsegv: read_marker COREDUMP_M= ARK_REQACK failed\n"); goto out; + } =20 exit_code =3D EXIT_SUCCESS; + fprintf(stderr, "socket_coredump_signal_sigsegv: completed successfully\= n"); out: if (fd_peer_pidfd >=3D 0) close(fd_peer_pidfd); @@ -957,49 +1159,75 @@ TEST_F(coredump, socket_coredump_signal_sigabrt) close(ipc_sockets[0]); =20 fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) + if (fd_server < 0) { + fprintf(stderr, "socket_coredump_signal_sigabrt: create_and_listen_unix= _socket failed: %m\n"); goto out; + } =20 - if (write_nointr(ipc_sockets[1], "1", 1) < 0) + if (write_nointr(ipc_sockets[1], "1", 1) < 0) { + fprintf(stderr, "socket_coredump_signal_sigabrt: write_nointr to ipc so= cket failed: %m\n"); goto out; + } =20 close(ipc_sockets[1]); =20 fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); - if (fd_coredump < 0) + if (fd_coredump < 0) { + fprintf(stderr, "socket_coredump_signal_sigabrt: accept4 failed: %m\n"); goto out; + } =20 fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) + if (fd_peer_pidfd < 0) { + fprintf(stderr, "socket_coredump_signal_sigabrt: get_peer_pidfd failed\= n"); goto out; + } =20 - if (!get_pidfd_info(fd_peer_pidfd, &info)) + if (!get_pidfd_info(fd_peer_pidfd, &info)) { + fprintf(stderr, "socket_coredump_signal_sigabrt: get_pidfd_info failed\= n"); goto out; + } =20 - if (!(info.mask & PIDFD_INFO_COREDUMP)) + if (!(info.mask & PIDFD_INFO_COREDUMP)) { + fprintf(stderr, "socket_coredump_signal_sigabrt: PIDFD_INFO_COREDUMP no= t set in mask\n"); goto out; + } =20 - if (!(info.coredump_mask & PIDFD_COREDUMPED)) + if (!(info.coredump_mask & PIDFD_COREDUMPED)) { + fprintf(stderr, "socket_coredump_signal_sigabrt: PIDFD_COREDUMPED not s= et in coredump_mask\n"); goto out; + } =20 /* Verify coredump_signal is available and correct */ - if (!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)) + if (!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)) { + fprintf(stderr, "socket_coredump_signal_sigabrt: PIDFD_INFO_COREDUMP_SI= GNAL not set in mask\n"); goto out; + } =20 - if (info.coredump_signal !=3D SIGABRT) + if (info.coredump_signal !=3D SIGABRT) { + fprintf(stderr, "socket_coredump_signal_sigabrt: coredump_signal=3D%d, = expected SIGABRT=3D%d\n", + info.coredump_signal, SIGABRT); goto out; + } =20 - if (!read_coredump_req(fd_coredump, &req)) + if (!read_coredump_req(fd_coredump, &req)) { + fprintf(stderr, "socket_coredump_signal_sigabrt: read_coredump_req fail= ed\n"); goto out; + } =20 if (!send_coredump_ack(fd_coredump, &req, - COREDUMP_REJECT | COREDUMP_WAIT, 0)) + COREDUMP_REJECT | COREDUMP_WAIT, 0)) { + fprintf(stderr, "socket_coredump_signal_sigabrt: send_coredump_ack fail= ed\n"); goto out; + } =20 - if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) + if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) { + fprintf(stderr, "socket_coredump_signal_sigabrt: read_marker COREDUMP_M= ARK_REQACK failed\n"); goto out; + } =20 exit_code =3D EXIT_SUCCESS; + fprintf(stderr, "socket_coredump_signal_sigabrt: completed successfully\= n"); out: if (fd_peer_pidfd >=3D 0) close(fd_peer_pidfd); @@ -1213,11 +1441,15 @@ TEST_F_TIMEOUT(coredump, socket_multiple_crashing_c= oredumps_epoll_workers, 500) n_conns =3D 0; close(ipc_sockets[0]); fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); - if (fd_server < 0) + if (fd_server < 0) { + fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: crea= te_and_listen_unix_socket failed: %m\n"); goto out; + } =20 - if (write_nointr(ipc_sockets[1], "1", 1) < 0) + if (write_nointr(ipc_sockets[1], "1", 1) < 0) { + fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: writ= e_nointr to ipc socket failed: %m\n"); goto out; + } close(ipc_sockets[1]); =20 while (n_conns < NUM_CRASHING_COREDUMPS) { @@ -1227,28 +1459,45 @@ TEST_F_TIMEOUT(coredump, socket_multiple_crashing_c= oredumps_epoll_workers, 500) if (fd_coredump < 0) { if (errno =3D=3D EAGAIN || errno =3D=3D EWOULDBLOCK) continue; + fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: acc= ept4 failed: %m\n"); goto out; } fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); - if (fd_peer_pidfd < 0) + if (fd_peer_pidfd < 0) { + fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: get= _peer_pidfd failed\n"); goto out; - if (!get_pidfd_info(fd_peer_pidfd, &info)) + } + if (!get_pidfd_info(fd_peer_pidfd, &info)) { + fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: get= _pidfd_info failed\n"); goto out; - if (!(info.mask & PIDFD_INFO_COREDUMP) || !(info.coredump_mask & PIDFD_= COREDUMPED)) + } + if (!(info.mask & PIDFD_INFO_COREDUMP) || !(info.coredump_mask & PIDFD_= COREDUMPED)) { + fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: mis= sing PIDFD_INFO_COREDUMP or PIDFD_COREDUMPED\n"); goto out; - if (!read_coredump_req(fd_coredump, &req)) + } + if (!read_coredump_req(fd_coredump, &req)) { + fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: rea= d_coredump_req failed\n"); goto out; + } if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, COREDUMP_KERNEL | COREDUMP_USERSPACE | - COREDUMP_REJECT | COREDUMP_WAIT)) + COREDUMP_REJECT | COREDUMP_WAIT)) { + fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: che= ck_coredump_req failed\n"); goto out; - if (!send_coredump_ack(fd_coredump, &req, COREDUMP_KERNEL | COREDUMP_WA= IT, 0)) + } + if (!send_coredump_ack(fd_coredump, &req, COREDUMP_KERNEL | COREDUMP_WA= IT, 0)) { + fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: sen= d_coredump_ack failed\n"); goto out; - if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) + } + if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) { + fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: rea= d_marker failed\n"); goto out; + } fd_core_file =3D open_coredump_tmpfile(self->fd_tmpfs_detached); - if (fd_core_file < 0) + if (fd_core_file < 0) { + fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: ope= n_coredump_tmpfile failed: %m\n"); goto out; + } pid_t worker =3D fork(); if (worker =3D=3D 0) { close(fd_server); --=20 2.47.3 From nobody Sun Feb 8 12:14:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EDDD62EBB86; Tue, 28 Oct 2025 08:47:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641250; cv=none; b=q1kh6NWpWvIsRxQsIiMk4Apf3tk3vlyLX8sowc1dTy8w9RPKR4pifKwfKnhqjVtTeorOXTxrNXqxcsTqNyO8IdDPJ9GBuxMpoPZumNQ3aye05jM2BxObmnmMlHCAOhQP7AAKtJg5djdaErsO7kTTikfjhZUKojsa0FtPBugdAXw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641250; c=relaxed/simple; bh=rpDHbmaasl+ntrsC4mcpJJdeQ8AEZE/m9hK+dPnDY8Y=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=J40mULmCmXmCsQQermp2TzHfQNnhsu21+HkrGbrqxAfwGH0fnPumHzsXztYdPxA412cBjFGb2VIePvt0PlIStZH1jPi6sFU/A4tJLDWV6v+m1mXKyRx9/RP6LSZcAhFhib+0Mya3D8SGAYrxDeo29uSt9uTXezHbBSeAFfkjOJc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=F0MnbcbQ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="F0MnbcbQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 186C9C116C6; Tue, 28 Oct 2025 08:47:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641249; bh=rpDHbmaasl+ntrsC4mcpJJdeQ8AEZE/m9hK+dPnDY8Y=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=F0MnbcbQrgVIKuL5t5rHrq953FlTE5pfYoMnOixg5Ll0SY/ADW4/znpdHup4ja3OS avEff1vJ7CDcznp6jz5acDktuvCGWeafDbIWxGceGMHb/YnbZNIdEgyGoBfuxFlQcf PFSo2yarFk2tWQLFm6+zAE71yYyYYVrt2zoVvVap+v3+hOuaJ3lm9WCx91jbiFds5o bxJsnuRXbdIqXsUYAU6FldPfoydXPqI2r5IUh9mZfT0XQ271YowstBu5rzTA42ho6m SrOvuxq5ceXiFSTMo9sSrk51Dpc/I7Ra70uBMx4c1dINhckuWGqQMVmixt+9ccxeR4 8xAtu67++eQow== From: Christian Brauner Date: Tue, 28 Oct 2025 09:46:05 +0100 Subject: [PATCH 20/22] selftests/coredump: ignore ENOSPC errors Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-20-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=3068; i=brauner@kernel.org; h=from:subject:message-id; bh=rpDHbmaasl+ntrsC4mcpJJdeQ8AEZE/m9hK+dPnDY8Y=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB1qrr44o3/pUdPtt6+VaqxzydOJOOD3+uOO5ZWxP DwOs5KcOkpZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACayn4mRYcKKtVdv/DafrC8b r77gYOf9m1+zzmddrBRac5nng5T8eWOGv+KHr+34msT8uOjiq5eNzvZCx5inGwj5HTk2Z15wzTu VXE4A X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 If we crash multiple processes at the same time we may run out of space. Just ignore those errors. They're not actually all that relevant for the test. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- tools/testing/selftests/coredump/coredump_socket_protocol_test.c | 4 ++++ tools/testing/selftests/coredump/coredump_socket_test.c | 5 +++-- tools/testing/selftests/coredump/coredump_test_helpers.c | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/coredump/coredump_socket_protocol_test= .c b/tools/testing/selftests/coredump/coredump_socket_protocol_test.c index 566545e96d7f..d19b6717c53e 100644 --- a/tools/testing/selftests/coredump/coredump_socket_protocol_test.c +++ b/tools/testing/selftests/coredump/coredump_socket_protocol_test.c @@ -184,6 +184,8 @@ TEST_F(coredump, socket_request_kernel) =20 bytes_write =3D write(fd_core_file, buffer, bytes_read); if (bytes_read !=3D bytes_write) { + if (bytes_write < 0 && errno =3D=3D ENOSPC) + continue; fprintf(stderr, "socket_request_kernel: write to core file failed (rea= d=3D%zd, write=3D%zd): %m\n", bytes_read, bytes_write); goto out; @@ -1366,6 +1368,8 @@ TEST_F_TIMEOUT(coredump, socket_multiple_crashing_cor= edumps, 500) =20 bytes_write =3D write(fd_core_file, buffer, bytes_read); if (bytes_read !=3D bytes_write) { + if (bytes_write < 0 && errno =3D=3D ENOSPC) + continue; fprintf(stderr, "write failed for fd %d: %m\n", fd_core_file); goto out; } diff --git a/tools/testing/selftests/coredump/coredump_socket_test.c b/tool= s/testing/selftests/coredump/coredump_socket_test.c index 0a37d0456672..da558a0e37aa 100644 --- a/tools/testing/selftests/coredump/coredump_socket_test.c +++ b/tools/testing/selftests/coredump/coredump_socket_test.c @@ -158,8 +158,9 @@ TEST_F(coredump, socket) =20 bytes_write =3D write(fd_core_file, buffer, bytes_read); if (bytes_read !=3D bytes_write) { - fprintf(stderr, "socket test: write to core file failed (read=3D%zd, w= rite=3D%zd): %m\n", - bytes_read, bytes_write); + if (bytes_write < 0 && errno =3D=3D ENOSPC) + continue; + fprintf(stderr, "socket test: write to core file failed (read=3D%zd, w= rite=3D%zd): %m\n", bytes_read, bytes_write); goto out; } } diff --git a/tools/testing/selftests/coredump/coredump_test_helpers.c b/too= ls/testing/selftests/coredump/coredump_test_helpers.c index 65deb3cfbe1b..a6f6d5f2ae07 100644 --- a/tools/testing/selftests/coredump/coredump_test_helpers.c +++ b/tools/testing/selftests/coredump/coredump_test_helpers.c @@ -357,6 +357,8 @@ void process_coredump_worker(int fd_coredump, int fd_pe= er_pidfd, int fd_core_fil goto done; ssize_t bytes_write =3D write(fd_core_file, buffer, bytes_read); if (bytes_write !=3D bytes_read) { + if (bytes_write < 0 && errno =3D=3D ENOSPC) + continue; fprintf(stderr, "Worker: write() failed (read=3D%zd, write=3D%zd): %m= \n", bytes_read, bytes_write); goto out; --=20 2.47.3 From nobody Sun Feb 8 12:14:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1E1152F39A6; Tue, 28 Oct 2025 08:47:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641254; cv=none; b=BvlEJhVFRMubmaI6MMcmhBQ0zS5X++3NZ4iRXz0Nly/av1XzPlmPjIHAT7ujNLhcnC9Nlzz9JUhUDOJ7Y/nVeBVkarDUdrV1MyBemkMGr1VQHKBQibRc3d5lK9i9biIHRoiYK5RU8VTavRmK/s4QXX8bImNzptNX1lVbG40H11I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641254; c=relaxed/simple; bh=2EQ5HZR4qxn4C2MGMoXLEuLXP+/juEhCZ0nnSio2LFM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Cc6gFR7x20VcxV/ATD55SAXvBbgxFltFLwkrPg1NVeoKnjUnCVnUZl/8WIIOyH5dzlBIgCiOyDIs8iyXo6qj/6bsDz7UmmFZx1iX2A9S5VVnVIWsRPVktHkKFcyNRR1N2FdMUNzykkkB2sCDEPchAIlCE46RWhbd9mkq+JFRAS4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=I3rWGgLb; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="I3rWGgLb" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4A11CC4CEE7; Tue, 28 Oct 2025 08:47:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641253; bh=2EQ5HZR4qxn4C2MGMoXLEuLXP+/juEhCZ0nnSio2LFM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=I3rWGgLbYrJJcEC6p+Mn13yJKPPtW29UWj5DtKKHcJSC03fV1PjlVGQ6Qs+BLoAOv LWxQYsn/wO3BNyn8BdVnxPICBIl7l75pHW3EA82SgTO3/T0uBDclEL6Sa8O0AikY3Z +dmr6sSYcwN3ln7b2jezayRxxFwelPTRgBL3hFXGHPVFgkMmXRtfWtghrvL0M/YZnC CEh2nijOUi4u4gokJOLBArY3RfbX6Mya5OOhtANY96/rVWtRGYoFYasMRJyB0UF/Ps UwgdMGm5/IM++pzTpkR4df85IsSxowmYqQ79abQm5q6LXoyWBCZJ5Bq/a5fP2Hq8wU 6PZ9dscTNe53A== From: Christian Brauner Date: Tue, 28 Oct 2025 09:46:06 +0100 Subject: [PATCH 21/22] selftests/coredump: add first PIDFD_INFO_COREDUMP_SIGNAL test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-21-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=5349; i=brauner@kernel.org; h=from:subject:message-id; bh=2EQ5HZR4qxn4C2MGMoXLEuLXP+/juEhCZ0nnSio2LFM=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB0K+TH1bObkMhWTd4z/3yt7PJIy/awnd4R9p27jH OO/62487ihlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZjIUnFGhgdznjU/aL/y97Sa ebqk54qlvz+wvnxTvOWN68qwRTn1R88xMly1nCh37WbFuVPLgqevX/8hVVSvyzYmRFZrLZv2i7z liRwA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Verify that when using simple socket-based coredump (@ pattern), the coredump_signal field is correctly exposed as SIGSEGV. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- .../selftests/coredump/coredump_socket_test.c | 146 +++++++++++++++++= ++++ 1 file changed, 146 insertions(+) diff --git a/tools/testing/selftests/coredump/coredump_socket_test.c b/tool= s/testing/selftests/coredump/coredump_socket_test.c index da558a0e37aa..9d5507fa75ec 100644 --- a/tools/testing/selftests/coredump/coredump_socket_test.c +++ b/tools/testing/selftests/coredump/coredump_socket_test.c @@ -430,6 +430,152 @@ TEST_F(coredump, socket_no_listener) wait_and_check_coredump_server(pid_coredump_server, _metadata, self); } =20 +/* + * Test: PIDFD_INFO_COREDUMP_SIGNAL via simple socket coredump + * + * Verify that when using simple socket-based coredump (@ pattern), + * the coredump_signal field is correctly exposed as SIGSEGV. + */ +TEST_F(coredump, socket_coredump_signal_sigsegv) +{ + int pidfd, ret, status; + pid_t pid, pid_coredump_server; + struct pidfd_info info =3D {}; + int ipc_sockets[2]; + char c; + + ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket")); + + ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); + ASSERT_EQ(ret, 0); + + pid_coredump_server =3D fork(); + ASSERT_GE(pid_coredump_server, 0); + if (pid_coredump_server =3D=3D 0) { + int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1, fd_core_= file =3D -1; + int exit_code =3D EXIT_FAILURE; + + close(ipc_sockets[0]); + + fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); + if (fd_server < 0) { + fprintf(stderr, "socket_coredump_signal_sigsegv: create_and_listen_unix= _socket failed: %m\n"); + goto out; + } + + if (write_nointr(ipc_sockets[1], "1", 1) < 0) { + fprintf(stderr, "socket_coredump_signal_sigsegv: write_nointr to ipc so= cket failed: %m\n"); + goto out; + } + + close(ipc_sockets[1]); + + fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); + if (fd_coredump < 0) { + fprintf(stderr, "socket_coredump_signal_sigsegv: accept4 failed: %m\n"); + goto out; + } + + fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); + if (fd_peer_pidfd < 0) { + fprintf(stderr, "socket_coredump_signal_sigsegv: get_peer_pidfd failed\= n"); + goto out; + } + + if (!get_pidfd_info(fd_peer_pidfd, &info)) { + fprintf(stderr, "socket_coredump_signal_sigsegv: get_pidfd_info failed\= n"); + goto out; + } + + if (!(info.mask & PIDFD_INFO_COREDUMP)) { + fprintf(stderr, "socket_coredump_signal_sigsegv: PIDFD_INFO_COREDUMP no= t set in mask\n"); + goto out; + } + + if (!(info.coredump_mask & PIDFD_COREDUMPED)) { + fprintf(stderr, "socket_coredump_signal_sigsegv: PIDFD_COREDUMPED not s= et in coredump_mask\n"); + goto out; + } + + /* Verify coredump_signal is available and correct */ + if (!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)) { + fprintf(stderr, "socket_coredump_signal_sigsegv: PIDFD_INFO_COREDUMP_SI= GNAL not set in mask\n"); + goto out; + } + + if (info.coredump_signal !=3D SIGSEGV) { + fprintf(stderr, "socket_coredump_signal_sigsegv: coredump_signal=3D%d, = expected SIGSEGV=3D%d\n", + info.coredump_signal, SIGSEGV); + goto out; + } + + fd_core_file =3D open_coredump_tmpfile(self->fd_tmpfs_detached); + if (fd_core_file < 0) { + fprintf(stderr, "socket_coredump_signal_sigsegv: open_coredump_tmpfile = failed: %m\n"); + goto out; + } + + for (;;) { + char buffer[4096]; + ssize_t bytes_read, bytes_write; + + bytes_read =3D read(fd_coredump, buffer, sizeof(buffer)); + if (bytes_read < 0) { + fprintf(stderr, "socket_coredump_signal_sigsegv: read from coredump so= cket failed: %m\n"); + goto out; + } + + if (bytes_read =3D=3D 0) + break; + + bytes_write =3D write(fd_core_file, buffer, bytes_read); + if (bytes_read !=3D bytes_write) { + fprintf(stderr, "socket_coredump_signal_sigsegv: write to core file fa= iled (read=3D%zd, write=3D%zd): %m\n", + bytes_read, bytes_write); + goto out; + } + } + + exit_code =3D EXIT_SUCCESS; + fprintf(stderr, "socket_coredump_signal_sigsegv: completed successfully\= n"); +out: + if (fd_core_file >=3D 0) + close(fd_core_file); + if (fd_peer_pidfd >=3D 0) + close(fd_peer_pidfd); + if (fd_coredump >=3D 0) + close(fd_coredump); + if (fd_server >=3D 0) + close(fd_server); + _exit(exit_code); + } + self->pid_coredump_server =3D pid_coredump_server; + + EXPECT_EQ(close(ipc_sockets[1]), 0); + ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); + EXPECT_EQ(close(ipc_sockets[0]), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + if (pid =3D=3D 0) + crashing_child(); + + pidfd =3D sys_pidfd_open(pid, 0); + ASSERT_GE(pidfd, 0); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFSIGNALED(status)); + ASSERT_EQ(WTERMSIG(status), SIGSEGV); + ASSERT_TRUE(WCOREDUMP(status)); + + ASSERT_TRUE(get_pidfd_info(pidfd, &info)); + ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP)); + ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)); + ASSERT_EQ(info.coredump_signal, SIGSEGV); + + wait_and_check_coredump_server(pid_coredump_server, _metadata, self); +} + TEST_F(coredump, socket_invalid_paths) { ASSERT_FALSE(set_core_pattern("@ /tmp/coredump.socket")); --=20 2.47.3 From nobody Sun Feb 8 12:14:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4D0952DEA9B; Tue, 28 Oct 2025 08:47:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641258; cv=none; b=C758jUg421mmbMPtUZ99ZqeMhz7rEQJNX4PbNp/PR1LzbHG+oa8rbOU8685up4E1JH1BM83Zwrs3854IwKuyCFRmyHXUrdleUIO+ZRWfL4QydYG0nwdvGmadWFSA+lL+1MnHfwN03QxrB9BpaNv78KWmPSQVg2mgXDwwgwHPV1I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761641258; c=relaxed/simple; bh=nQyFS6aYzryiBpUF+lHQ88ZIt5d5g0ycfT79oX64Xz8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lVu9s6KM5Gpetn7uZr9HTcn5LMrHAa54cQRW8/TAIlDSBqbkxmdIrIqn2ZLeZ3/M5GUtrpUN41twoMK5vaw8161Xm64cmjlpLA8cHH8NGt075s34fEfxj8XR1RphuZGhZNcnTUrJCjpkTjxdFn/sstFxyRXPshPb4W+Sh7Ywbts= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pm/gXfrf; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="pm/gXfrf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 24B82C4CEFF; Tue, 28 Oct 2025 08:47:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761641258; bh=nQyFS6aYzryiBpUF+lHQ88ZIt5d5g0ycfT79oX64Xz8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=pm/gXfrfJikmRMsfDUjOzCgVz8vjRcv33GmeggH2BXHC29XSi9VJ17Qj+36grN2cm Ggn41N0bStBOc3+6pJ8qH2MfdRbEqyxLfJy9fuRL3YWlD9wKWU0LyLaAyzJ+M1hCr4 MrH6MDwrf2N7LCg/HW7dKKEzSi3oPiCJg43F38rK7+4vuwr4fTkw0Rwhoyy1AJJfh3 BriRFGZaILDpgnEBMhPWojpt2mVvImV5eAcWtRxNEVdkwlDobflOtuuPIeb1Mzqj6Y Z8LkW8Jhok9qEOhp2GzrJBXRn2izTNWOqw9BhNX3sqvTGfBLUoZg2M7OXVMPh4pzvE dT0Nomd5BVbnw== From: Christian Brauner Date: Tue, 28 Oct 2025 09:46:07 +0100 Subject: [PATCH 22/22] selftests/coredump: add second PIDFD_INFO_COREDUMP_SIGNAL test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251028-work-coredump-signal-v1-22-ca449b7b7aa0@kernel.org> References: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> In-Reply-To: <20251028-work-coredump-signal-v1-0-ca449b7b7aa0@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Oleg Nesterov , Amir Goldstein , Aleksa Sarai , Yu Watanabe , Josef Bacik , Jeff Layton , Jann Horn , Luca Boccassi , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, Alexander Viro , Jan Kara , Lennart Poettering , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=5365; i=brauner@kernel.org; h=from:subject:message-id; bh=nQyFS6aYzryiBpUF+lHQ88ZIt5d5g0ycfT79oX64Xz8=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWQyNB0qWTb58EWVZ/t+2H/ga3AwP/SlN8FI9d0L3x1uv A8Ut9gqdZSyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAExkiRQjw2Vr3r0uZRdOrLz+ NeD2L57a7ou38nbYn5/cq83X/EhYsoqRYe1sSd5ZnMt8tTpPdJlssVSfOVthOYfd048bIr57CN8 L5QUA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Verify that when using simple socket-based coredump (@ pattern), the coredump_signal field is correctly exposed as SIGABRT. Signed-off-by: Christian Brauner Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Oleg Nesterov --- .../selftests/coredump/coredump_socket_test.c | 146 +++++++++++++++++= ++++ 1 file changed, 146 insertions(+) diff --git a/tools/testing/selftests/coredump/coredump_socket_test.c b/tool= s/testing/selftests/coredump/coredump_socket_test.c index 9d5507fa75ec..7e26d4a6a15d 100644 --- a/tools/testing/selftests/coredump/coredump_socket_test.c +++ b/tools/testing/selftests/coredump/coredump_socket_test.c @@ -576,6 +576,152 @@ TEST_F(coredump, socket_coredump_signal_sigsegv) wait_and_check_coredump_server(pid_coredump_server, _metadata, self); } =20 +/* + * Test: PIDFD_INFO_COREDUMP_SIGNAL via simple socket coredump with SIGABRT + * + * Verify that when using simple socket-based coredump (@ pattern), + * the coredump_signal field is correctly exposed as SIGABRT. + */ +TEST_F(coredump, socket_coredump_signal_sigabrt) +{ + int pidfd, ret, status; + pid_t pid, pid_coredump_server; + struct pidfd_info info =3D {}; + int ipc_sockets[2]; + char c; + + ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket")); + + ret =3D socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); + ASSERT_EQ(ret, 0); + + pid_coredump_server =3D fork(); + ASSERT_GE(pid_coredump_server, 0); + if (pid_coredump_server =3D=3D 0) { + int fd_server =3D -1, fd_coredump =3D -1, fd_peer_pidfd =3D -1, fd_core_= file =3D -1; + int exit_code =3D EXIT_FAILURE; + + close(ipc_sockets[0]); + + fd_server =3D create_and_listen_unix_socket("/tmp/coredump.socket"); + if (fd_server < 0) { + fprintf(stderr, "socket_coredump_signal_sigabrt: create_and_listen_unix= _socket failed: %m\n"); + goto out; + } + + if (write_nointr(ipc_sockets[1], "1", 1) < 0) { + fprintf(stderr, "socket_coredump_signal_sigabrt: write_nointr to ipc so= cket failed: %m\n"); + goto out; + } + + close(ipc_sockets[1]); + + fd_coredump =3D accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); + if (fd_coredump < 0) { + fprintf(stderr, "socket_coredump_signal_sigabrt: accept4 failed: %m\n"); + goto out; + } + + fd_peer_pidfd =3D get_peer_pidfd(fd_coredump); + if (fd_peer_pidfd < 0) { + fprintf(stderr, "socket_coredump_signal_sigabrt: get_peer_pidfd failed\= n"); + goto out; + } + + if (!get_pidfd_info(fd_peer_pidfd, &info)) { + fprintf(stderr, "socket_coredump_signal_sigabrt: get_pidfd_info failed\= n"); + goto out; + } + + if (!(info.mask & PIDFD_INFO_COREDUMP)) { + fprintf(stderr, "socket_coredump_signal_sigabrt: PIDFD_INFO_COREDUMP no= t set in mask\n"); + goto out; + } + + if (!(info.coredump_mask & PIDFD_COREDUMPED)) { + fprintf(stderr, "socket_coredump_signal_sigabrt: PIDFD_COREDUMPED not s= et in coredump_mask\n"); + goto out; + } + + /* Verify coredump_signal is available and correct */ + if (!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)) { + fprintf(stderr, "socket_coredump_signal_sigabrt: PIDFD_INFO_COREDUMP_SI= GNAL not set in mask\n"); + goto out; + } + + if (info.coredump_signal !=3D SIGABRT) { + fprintf(stderr, "socket_coredump_signal_sigabrt: coredump_signal=3D%d, = expected SIGABRT=3D%d\n", + info.coredump_signal, SIGABRT); + goto out; + } + + fd_core_file =3D open_coredump_tmpfile(self->fd_tmpfs_detached); + if (fd_core_file < 0) { + fprintf(stderr, "socket_coredump_signal_sigabrt: open_coredump_tmpfile = failed: %m\n"); + goto out; + } + + for (;;) { + char buffer[4096]; + ssize_t bytes_read, bytes_write; + + bytes_read =3D read(fd_coredump, buffer, sizeof(buffer)); + if (bytes_read < 0) { + fprintf(stderr, "socket_coredump_signal_sigabrt: read from coredump so= cket failed: %m\n"); + goto out; + } + + if (bytes_read =3D=3D 0) + break; + + bytes_write =3D write(fd_core_file, buffer, bytes_read); + if (bytes_read !=3D bytes_write) { + fprintf(stderr, "socket_coredump_signal_sigabrt: write to core file fa= iled (read=3D%zd, write=3D%zd): %m\n", + bytes_read, bytes_write); + goto out; + } + } + + exit_code =3D EXIT_SUCCESS; + fprintf(stderr, "socket_coredump_signal_sigabrt: completed successfully\= n"); +out: + if (fd_core_file >=3D 0) + close(fd_core_file); + if (fd_peer_pidfd >=3D 0) + close(fd_peer_pidfd); + if (fd_coredump >=3D 0) + close(fd_coredump); + if (fd_server >=3D 0) + close(fd_server); + _exit(exit_code); + } + self->pid_coredump_server =3D pid_coredump_server; + + EXPECT_EQ(close(ipc_sockets[1]), 0); + ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); + EXPECT_EQ(close(ipc_sockets[0]), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + if (pid =3D=3D 0) + abort(); + + pidfd =3D sys_pidfd_open(pid, 0); + ASSERT_GE(pidfd, 0); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFSIGNALED(status)); + ASSERT_EQ(WTERMSIG(status), SIGABRT); + ASSERT_TRUE(WCOREDUMP(status)); + + ASSERT_TRUE(get_pidfd_info(pidfd, &info)); + ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP)); + ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)); + ASSERT_EQ(info.coredump_signal, SIGABRT); + + wait_and_check_coredump_server(pid_coredump_server, _metadata, self); +} + TEST_F(coredump, socket_invalid_paths) { ASSERT_FALSE(set_core_pattern("@ /tmp/coredump.socket")); --=20 2.47.3