* Re: [PATCH v4] ELF: AT_PAGE_SHIFT_MASK -- supply userspace with available page shifts
From: Kees Cook @ 2024-02-10 0:41 UTC (permalink / raw)
To: Alexey Dobriyan
Cc: Andrew Morton, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, Florian Weimer, linux-kernel, linux-arch, linux-api,
x86, Eric Biederman, linux-mm
In-Reply-To: <acd02481-ca2e-412a-8c6b-d9dff1345139@p183>
On Fri, Feb 09, 2024 at 03:30:37PM +0300, Alexey Dobriyan wrote:
> On Mon, Feb 05, 2024 at 04:48:08AM -0800, Kees Cook wrote:
> > On Mon, Feb 05, 2024 at 12:51:43PM +0300, Alexey Dobriyan wrote:
> > > +#define ARCH_AT_PAGE_SHIFT_MASK \
> > > + do { \
> > > + u32 val = 1 << 12; \
> > > + if (boot_cpu_has(X86_FEATURE_PSE)) { \
> > > + val |= 1 << 21; \
> > > + } \
> > > + if (boot_cpu_has(X86_FEATURE_GBPAGES)) { \
> > > + val |= 1 << 30; \
> > > + } \
> >
> > Can we use something besides literal "12", "21", and "30" values here?
>
> Ehh, no, why? Inside x86_64 the page shifts are very specific numbers,
> they won't change.
Well, it's nicer to have meaningful words to describe these things. In
fact, PAGE_SHIFT already exists for 12, and HPAGE_SHIFT already exists
for 21. Please use those, and add another, perhaps GBPAGE_SHIFT, for 30.
-Kees
--
Kees Cook
^ permalink raw reply
* [PATCH net-next v7 4/4] eventpoll: Add epoll ioctl for epoll_params
From: Joe Damato @ 2024-02-09 21:15 UTC (permalink / raw)
To: linux-kernel, netdev
Cc: chuck.lever, jlayton, linux-api, brauner, edumazet, davem,
alexander.duyck, sridhar.samudrala, kuba, willemdebruijn.kernel,
weiwan, David.Laight, arnd, sdf, amritha.nambiar, Joe Damato,
Jiri Slaby, Jonathan Corbet, Alexander Viro, Jan Kara,
Michael Ellerman, Nathan Lynch, Greg Kroah-Hartman, Maik Broemme,
Steve French, Thomas Zimmermann, Julien Panis, Thomas Huth,
Albert Ou, Palmer Dabbelt, open list:DOCUMENTATION,
open list:FILESYSTEMS (VFS and infrastructure)
In-Reply-To: <20240209211528.51234-1-jdamato@fastly.com>
Add an ioctl for getting and setting epoll_params. User programs can use
this ioctl to get and set the busy poll usec time, packet budget, and
prefer busy poll params for a specific epoll context.
Parameters are limited:
- busy_poll_usecs is limited to <= s32_max
- busy_poll_budget is limited to <= NAPI_POLL_WEIGHT by unprivileged
users (!capable(CAP_NET_ADMIN))
- prefer_busy_poll must be 0 or 1
- __pad must be 0
Signed-off-by: Joe Damato <jdamato@fastly.com>
Acked-by: Stanislav Fomichev <sdf@google.com>
Reviewed-by: Jiri Slaby <jirislaby@kernel.org>
---
.../userspace-api/ioctl/ioctl-number.rst | 1 +
fs/eventpoll.c | 72 +++++++++++++++++++
include/uapi/linux/eventpoll.h | 13 ++++
3 files changed, 86 insertions(+)
diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst
index 457e16f06e04..b33918232f78 100644
--- a/Documentation/userspace-api/ioctl/ioctl-number.rst
+++ b/Documentation/userspace-api/ioctl/ioctl-number.rst
@@ -309,6 +309,7 @@ Code Seq# Include File Comments
0x89 0B-DF linux/sockios.h
0x89 E0-EF linux/sockios.h SIOCPROTOPRIVATE range
0x89 F0-FF linux/sockios.h SIOCDEVPRIVATE range
+0x8A 00-1F linux/eventpoll.h
0x8B all linux/wireless.h
0x8C 00-3F WiNRADiO driver
<http://www.winradio.com.au/>
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 1b8d01af0c2c..aa58d42737e6 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -37,6 +37,7 @@
#include <linux/seq_file.h>
#include <linux/compat.h>
#include <linux/rculist.h>
+#include <linux/capability.h>
#include <net/busy_poll.h>
/*
@@ -494,6 +495,49 @@ static inline void ep_set_busy_poll_napi_id(struct epitem *epi)
ep->napi_id = napi_id;
}
+static long ep_eventpoll_bp_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct eventpoll *ep = file->private_data;
+ void __user *uarg = (void __user *)arg;
+ struct epoll_params epoll_params;
+
+ switch (cmd) {
+ case EPIOCSPARAMS:
+ if (copy_from_user(&epoll_params, uarg, sizeof(epoll_params)))
+ return -EFAULT;
+
+ /* pad byte must be zero */
+ if (epoll_params.__pad)
+ return -EINVAL;
+
+ if (epoll_params.busy_poll_usecs > S32_MAX)
+ return -EINVAL;
+
+ if (epoll_params.prefer_busy_poll > 1)
+ return -EINVAL;
+
+ if (epoll_params.busy_poll_budget > NAPI_POLL_WEIGHT &&
+ !capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ ep->busy_poll_usecs = epoll_params.busy_poll_usecs;
+ ep->busy_poll_budget = epoll_params.busy_poll_budget;
+ ep->prefer_busy_poll = epoll_params.prefer_busy_poll;
+ return 0;
+ case EPIOCGPARAMS:
+ memset(&epoll_params, 0, sizeof(epoll_params));
+ epoll_params.busy_poll_usecs = ep->busy_poll_usecs;
+ epoll_params.busy_poll_budget = ep->busy_poll_budget;
+ epoll_params.prefer_busy_poll = ep->prefer_busy_poll;
+ if (copy_to_user(uarg, &epoll_params, sizeof(epoll_params)))
+ return -EFAULT;
+ return 0;
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
#else
static inline bool ep_busy_loop(struct eventpoll *ep, int nonblock)
@@ -505,6 +549,12 @@ static inline void ep_set_busy_poll_napi_id(struct epitem *epi)
{
}
+static long ep_eventpoll_bp_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ return -EOPNOTSUPP;
+}
+
#endif /* CONFIG_NET_RX_BUSY_POLL */
/*
@@ -864,6 +914,26 @@ static void ep_clear_and_put(struct eventpoll *ep)
ep_free(ep);
}
+static long ep_eventpoll_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int ret;
+
+ if (!is_file_epoll(file))
+ return -EINVAL;
+
+ switch (cmd) {
+ case EPIOCSPARAMS:
+ case EPIOCGPARAMS:
+ ret = ep_eventpoll_bp_ioctl(file, cmd, arg);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
static int ep_eventpoll_release(struct inode *inode, struct file *file)
{
struct eventpoll *ep = file->private_data;
@@ -970,6 +1040,8 @@ static const struct file_operations eventpoll_fops = {
.release = ep_eventpoll_release,
.poll = ep_eventpoll_poll,
.llseek = noop_llseek,
+ .unlocked_ioctl = ep_eventpoll_ioctl,
+ .compat_ioctl = compat_ptr_ioctl,
};
/*
diff --git a/include/uapi/linux/eventpoll.h b/include/uapi/linux/eventpoll.h
index cfbcc4cc49ac..4f4b948ef381 100644
--- a/include/uapi/linux/eventpoll.h
+++ b/include/uapi/linux/eventpoll.h
@@ -85,4 +85,17 @@ struct epoll_event {
__u64 data;
} EPOLL_PACKED;
+struct epoll_params {
+ __u32 busy_poll_usecs;
+ __u16 busy_poll_budget;
+ __u8 prefer_busy_poll;
+
+ /* pad the struct to a multiple of 64bits */
+ __u8 __pad;
+};
+
+#define EPOLL_IOC_TYPE 0x8A
+#define EPIOCSPARAMS _IOW(EPOLL_IOC_TYPE, 0x01, struct epoll_params)
+#define EPIOCGPARAMS _IOR(EPOLL_IOC_TYPE, 0x02, struct epoll_params)
+
#endif /* _UAPI_LINUX_EVENTPOLL_H */
--
2.25.1
^ permalink raw reply related
* [PATCH net-next v7 3/4] eventpoll: Add per-epoll prefer busy poll option
From: Joe Damato @ 2024-02-09 21:15 UTC (permalink / raw)
To: linux-kernel, netdev
Cc: chuck.lever, jlayton, linux-api, brauner, edumazet, davem,
alexander.duyck, sridhar.samudrala, kuba, willemdebruijn.kernel,
weiwan, David.Laight, arnd, sdf, amritha.nambiar, Joe Damato,
Alexander Viro, Jan Kara,
open list:FILESYSTEMS (VFS and infrastructure)
In-Reply-To: <20240209211528.51234-1-jdamato@fastly.com>
When using epoll-based busy poll, the prefer_busy_poll option is hardcoded
to false. Users may want to enable prefer_busy_poll to be used in
conjunction with gro_flush_timeout and defer_hard_irqs_count to keep device
IRQs masked.
Other busy poll methods allow enabling or disabling prefer busy poll via
SO_PREFER_BUSY_POLL, but epoll-based busy polling uses a hardcoded value.
Fix this edge case by adding support for a per-epoll context
prefer_busy_poll option. The default is false, as it was hardcoded before
this change.
Signed-off-by: Joe Damato <jdamato@fastly.com>
Acked-by: Stanislav Fomichev <sdf@google.com>
Reviewed-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Eric Dumazet <edumazet@google.com>
---
fs/eventpoll.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index ed83ae33dd45..1b8d01af0c2c 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -231,6 +231,7 @@ struct eventpoll {
u32 busy_poll_usecs;
/* busy poll packet budget */
u16 busy_poll_budget;
+ bool prefer_busy_poll;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
@@ -438,13 +439,14 @@ static bool ep_busy_loop(struct eventpoll *ep, int nonblock)
{
unsigned int napi_id = READ_ONCE(ep->napi_id);
u16 budget = READ_ONCE(ep->busy_poll_budget);
+ bool prefer_busy_poll = READ_ONCE(ep->prefer_busy_poll);
if (!budget)
budget = BUSY_POLL_BUDGET;
if (napi_id >= MIN_NAPI_ID && ep_busy_loop_on(ep)) {
- napi_busy_loop(napi_id, nonblock ? NULL : ep_busy_loop_end, ep, false,
- budget);
+ napi_busy_loop(napi_id, nonblock ? NULL : ep_busy_loop_end,
+ ep, prefer_busy_poll, budget);
if (ep_events_available(ep))
return true;
/*
@@ -2098,6 +2100,7 @@ static int do_epoll_create(int flags)
#ifdef CONFIG_NET_RX_BUSY_POLL
ep->busy_poll_usecs = 0;
ep->busy_poll_budget = 0;
+ ep->prefer_busy_poll = false;
#endif
ep->file = file;
fd_install(fd, file);
--
2.25.1
^ permalink raw reply related
* [PATCH net-next v7 2/4] eventpoll: Add per-epoll busy poll packet budget
From: Joe Damato @ 2024-02-09 21:15 UTC (permalink / raw)
To: linux-kernel, netdev
Cc: chuck.lever, jlayton, linux-api, brauner, edumazet, davem,
alexander.duyck, sridhar.samudrala, kuba, willemdebruijn.kernel,
weiwan, David.Laight, arnd, sdf, amritha.nambiar, Joe Damato,
Alexander Viro, Jan Kara,
open list:FILESYSTEMS (VFS and infrastructure)
In-Reply-To: <20240209211528.51234-1-jdamato@fastly.com>
When using epoll-based busy poll, the packet budget is hardcoded to
BUSY_POLL_BUDGET (8). Users may desire larger busy poll budgets, which
can potentially increase throughput when busy polling under high network
load.
Other busy poll methods allow setting the busy poll budget via
SO_BUSY_POLL_BUDGET, but epoll-based busy polling uses a hardcoded
value.
Fix this edge case by adding support for a per-epoll context busy poll
packet budget. If not specified, the default value (BUSY_POLL_BUDGET) is
used.
Signed-off-by: Joe Damato <jdamato@fastly.com>
Acked-by: Stanislav Fomichev <sdf@google.com>
Reviewed-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Eric Dumazet <edumazet@google.com>
---
fs/eventpoll.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 401f865eced9..ed83ae33dd45 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -229,6 +229,8 @@ struct eventpoll {
unsigned int napi_id;
/* busy poll timeout */
u32 busy_poll_usecs;
+ /* busy poll packet budget */
+ u16 busy_poll_budget;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
@@ -435,10 +437,14 @@ static bool ep_busy_loop_end(void *p, unsigned long start_time)
static bool ep_busy_loop(struct eventpoll *ep, int nonblock)
{
unsigned int napi_id = READ_ONCE(ep->napi_id);
+ u16 budget = READ_ONCE(ep->busy_poll_budget);
+
+ if (!budget)
+ budget = BUSY_POLL_BUDGET;
if (napi_id >= MIN_NAPI_ID && ep_busy_loop_on(ep)) {
napi_busy_loop(napi_id, nonblock ? NULL : ep_busy_loop_end, ep, false,
- BUSY_POLL_BUDGET);
+ budget);
if (ep_events_available(ep))
return true;
/*
@@ -2091,6 +2097,7 @@ static int do_epoll_create(int flags)
}
#ifdef CONFIG_NET_RX_BUSY_POLL
ep->busy_poll_usecs = 0;
+ ep->busy_poll_budget = 0;
#endif
ep->file = file;
fd_install(fd, file);
--
2.25.1
^ permalink raw reply related
* [PATCH net-next v7 1/4] eventpoll: support busy poll per epoll instance
From: Joe Damato @ 2024-02-09 21:15 UTC (permalink / raw)
To: linux-kernel, netdev
Cc: chuck.lever, jlayton, linux-api, brauner, edumazet, davem,
alexander.duyck, sridhar.samudrala, kuba, willemdebruijn.kernel,
weiwan, David.Laight, arnd, sdf, amritha.nambiar, Joe Damato,
Alexander Viro, Jan Kara,
open list:FILESYSTEMS (VFS and infrastructure)
In-Reply-To: <20240209211528.51234-1-jdamato@fastly.com>
Allow busy polling on a per-epoll context basis. The per-epoll context
usec timeout value is preferred, but the pre-existing system wide sysctl
value is still supported if it specified.
busy_poll_usecs is a u32, but in a follow up patch the ioctl provided to
the user only allows setting a value from 0 to S32_MAX.
Signed-off-by: Joe Damato <jdamato@fastly.com>
Acked-by: Stanislav Fomichev <sdf@google.com>
---
fs/eventpoll.c | 44 +++++++++++++++++++++++++++++++++++++++-----
1 file changed, 39 insertions(+), 5 deletions(-)
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 3534d36a1474..401f865eced9 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -227,6 +227,8 @@ struct eventpoll {
#ifdef CONFIG_NET_RX_BUSY_POLL
/* used to track busy poll napi_id */
unsigned int napi_id;
+ /* busy poll timeout */
+ u32 busy_poll_usecs;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
@@ -387,11 +389,41 @@ static inline int ep_events_available(struct eventpoll *ep)
}
#ifdef CONFIG_NET_RX_BUSY_POLL
+/**
+ * busy_loop_ep_timeout - check if busy poll has timed out. The timeout value
+ * from the epoll instance ep is preferred, but if it is not set fallback to
+ * the system-wide global via busy_loop_timeout.
+ *
+ * @start_time: The start time used to compute the remaining time until timeout.
+ * @ep: Pointer to the eventpoll context.
+ *
+ * Return: true if the timeout has expired, false otherwise.
+ */
+static bool busy_loop_ep_timeout(unsigned long start_time,
+ struct eventpoll *ep)
+{
+ unsigned long bp_usec = READ_ONCE(ep->busy_poll_usecs);
+
+ if (bp_usec) {
+ unsigned long end_time = start_time + bp_usec;
+ unsigned long now = busy_loop_current_time();
+
+ return time_after(now, end_time);
+ } else {
+ return busy_loop_timeout(start_time);
+ }
+}
+
+static bool ep_busy_loop_on(struct eventpoll *ep)
+{
+ return !!ep->busy_poll_usecs || net_busy_loop_on();
+}
+
static bool ep_busy_loop_end(void *p, unsigned long start_time)
{
struct eventpoll *ep = p;
- return ep_events_available(ep) || busy_loop_timeout(start_time);
+ return ep_events_available(ep) || busy_loop_ep_timeout(start_time, ep);
}
/*
@@ -404,7 +436,7 @@ static bool ep_busy_loop(struct eventpoll *ep, int nonblock)
{
unsigned int napi_id = READ_ONCE(ep->napi_id);
- if ((napi_id >= MIN_NAPI_ID) && net_busy_loop_on()) {
+ if (napi_id >= MIN_NAPI_ID && ep_busy_loop_on(ep)) {
napi_busy_loop(napi_id, nonblock ? NULL : ep_busy_loop_end, ep, false,
BUSY_POLL_BUDGET);
if (ep_events_available(ep))
@@ -425,12 +457,12 @@ static bool ep_busy_loop(struct eventpoll *ep, int nonblock)
*/
static inline void ep_set_busy_poll_napi_id(struct epitem *epi)
{
- struct eventpoll *ep;
+ struct eventpoll *ep = epi->ep;
unsigned int napi_id;
struct socket *sock;
struct sock *sk;
- if (!net_busy_loop_on())
+ if (!ep_busy_loop_on(ep))
return;
sock = sock_from_file(epi->ffd.file);
@@ -442,7 +474,6 @@ static inline void ep_set_busy_poll_napi_id(struct epitem *epi)
return;
napi_id = READ_ONCE(sk->sk_napi_id);
- ep = epi->ep;
/* Non-NAPI IDs can be rejected
* or
@@ -2058,6 +2089,9 @@ static int do_epoll_create(int flags)
error = PTR_ERR(file);
goto out_free_fd;
}
+#ifdef CONFIG_NET_RX_BUSY_POLL
+ ep->busy_poll_usecs = 0;
+#endif
ep->file = file;
fd_install(fd, file);
return fd;
--
2.25.1
^ permalink raw reply related
* [PATCH net-next v7 0/4] Per epoll context busy poll support
From: Joe Damato @ 2024-02-09 21:15 UTC (permalink / raw)
To: linux-kernel, netdev
Cc: chuck.lever, jlayton, linux-api, brauner, edumazet, davem,
alexander.duyck, sridhar.samudrala, kuba, willemdebruijn.kernel,
weiwan, David.Laight, arnd, sdf, amritha.nambiar, Joe Damato,
Albert Ou, Alexander Viro, Andrew Waterman, Greg Kroah-Hartman,
Helge Deller, Jan Kara, Jiri Slaby, Jonathan Corbet, Julien Panis,
open list:DOCUMENTATION,
open list:FILESYSTEMS (VFS and infrastructure), Michael Ellerman,
Nathan Lynch, Palmer Dabbelt, Steve French, Thomas Huth,
Thomas Zimmermann
Greetings:
Welcome to v7. See changelog below for minor functional change and cosmetic
cleanup details.
TL;DR This builds on commit bf3b9f6372c4 ("epoll: Add busy poll support to
epoll with socket fds.") by allowing user applications to enable
epoll-based busy polling, set a busy poll packet budget, and enable or
disable prefer busy poll on a per epoll context basis.
This makes epoll-based busy polling much more usable for user
applications than the current system-wide sysctl and hardcoded budget.
To allow for this, two ioctls have been added for epoll contexts for
getting and setting a new struct, struct epoll_params.
ioctl was chosen vs a new syscall after reviewing a suggestion by Willem
de Bruijn [1]. I am open to using a new syscall instead of an ioctl, but it
seemed that:
- Busy poll affects all existing epoll_wait and epoll_pwait variants in
the same way, so new verions of many syscalls might be needed. It
seems much simpler for users to use the correct
epoll_wait/epoll_pwait for their app and add a call to ioctl to enable
or disable busy poll as needed. This also probably means less work to
get an existing epoll app using busy poll.
- previously added epoll_pwait2 helped to bring epoll closer to
existing syscalls (like pselect and ppoll) and this busy poll change
reflected as a new syscall would not have the same effect.
Note: patch 1/4 as of v4 uses an or (||) instead of an xor. I thought about
it some more and I realized that if the user enables both the per-epoll
context setting and the system wide sysctl, then busy poll should be
enabled and not disabled. Using xor doesn't seem to make much sense after
thinking through this a bit.
Longer explanation:
Presently epoll has support for a very useful form of busy poll based on
the incoming NAPI ID (see also: SO_INCOMING_NAPI_ID [2]).
This form of busy poll allows epoll_wait to drive NAPI packet processing
which allows for a few interesting user application designs which can
reduce latency and also potentially improve L2/L3 cache hit rates by
deferring NAPI until userland has finished its work.
The documentation available on this is, IMHO, a bit confusing so please
allow me to explain how one might use this:
1. Ensure each application thread has its own epoll instance mapping
1-to-1 with NIC RX queues. An n-tuple filter would likely be used to
direct connections with specific dest ports to these queues.
2. Optionally: Setup IRQ coalescing for the NIC RX queues where busy
polling will occur. This can help avoid the userland app from being
pre-empted by a hard IRQ while userland is running. Note this means that
userland must take care to call epoll_wait and not take too long in
userland since it now drives NAPI via epoll_wait.
3. Optionally: Consider using napi_defer_hard_irqs and gro_flush_timeout to
further restrict IRQ generation from the NIC. These settings are
system-wide so their impact must be carefully weighed against the running
applications.
4. Ensure that all incoming connections added to an epoll instance
have the same NAPI ID. This can be done with a BPF filter when
SO_REUSEPORT is used or getsockopt + SO_INCOMING_NAPI_ID when a single
accept thread is used which dispatches incoming connections to threads.
5. Lastly, busy poll must be enabled via a sysctl
(/proc/sys/net/core/busy_poll).
Please see Eric Dumazet's paper about busy polling [3] and a recent
academic paper about measured performance improvements of busy polling [4]
(albeit with a modification that is not currently present in the kernel)
for additional context.
The unfortunate part about step 5 above is that this enables busy poll
system-wide which affects all user applications on the system,
including epoll-based network applications which were not intended to
be used this way or applications where increased CPU usage for lower
latency network processing is unnecessary or not desirable.
If the user wants to run one low latency epoll-based server application
with epoll-based busy poll, but would like to run the rest of the
applications on the system (which may also use epoll) without busy poll,
this system-wide sysctl presents a significant problem.
This change preserves the system-wide sysctl, but adds a mechanism (via
ioctl) to enable or disable busy poll for epoll contexts as needed by
individual applications, making epoll-based busy poll more usable.
Note that this change includes an or (as of v4) instead of an xor. If the
user has enabled both the system-wide sysctl and also the per epoll-context
busy poll settings, then epoll should probably busy poll (vs being
disabled).
Thanks,
Joe
v6 -> v7:
- Acked-by tags from Stanislav Fomichev applied to commit messages of
all patches.
- Reviewed-by tags from Jakub Kicinski, Eric Dumazet applied to commit
messages of patches 2 and 3. Jiri Slaby's Reviewed-by applied to patch
4.
- patch 1/4:
- busy_poll_usecs reduced from u64 to u32.
- Unnecessary parens removed (via netdev/checkpatch)
- Wrapped long line (via netdev/checkpatch)
- Remove inline from busy_loop_ep_timeout as objdump suggests the
function is already inlined
- Moved struct eventpoll assignment to declaration
- busy_loop_ep_timeout is moved within CONFIG_NET_RX_BUSY_POLL and the
ifdefs internally have been removed as per Eric Dumazet's review
- Removed ep_busy_loop_on from the !defined CONFIG_NET_RX_BUSY_POLL
section as it is only called when CONFIG_NET_RX_BUSY_POLL is
defined
- patch 3/4:
- Fix whitespace alignment issue (via netdev/checkpatch)
- patch 4/4:
- epoll_params.busy_poll_usecs has been reduced to u32
- epoll_params.busy_poll_usecs is now checked to ensure it is <=
S32_MAX
- __pad has been reduced to a single u8
- memchr_inv has been dropped and replaced with a simple check for the
single __pad byte
- Removed space after cast (via netdev/checkpatch)
- Wrap long line (via netdev/checkpatch)
- Move struct eventpoll *ep assignment to declaration as per Jiri
Slaby's review
- Remove unnecessary !! as per Jiri Slaby's review
- Reorganized variables to be reverse christmas tree order
v5 -> v6:
- patch 1/3 no functional change, but commit message corrected to explain
that an or (||) is being used instead of xor.
- patch 3/4 is a new patch which adds support for per epoll context
prefer busy poll setting.
- patch 4/4 updated to allow getting/setting per epoll context prefer
busy poll setting; this setting is limited to either 0 or 1.
v4 -> v5:
- patch 3/3 updated to use memchr_inv to ensure that __pad is zero for
the EPIOCSPARAMS ioctl. Recommended by Greg K-H [5], Dave Chinner [6],
and Jiri Slaby [7].
v3 -> v4:
- patch 1/3 was updated to include an important functional change:
ep_busy_loop_on was updated to use or (||) instead of xor (^). After
thinking about it a bit more, I thought xor didn't make much sense.
Enabling both the per-epoll context and the system-wide sysctl should
probably enable busy poll, not disable it. So, or (||) makes more
sense, I think.
- patch 3/3 was updated:
- to change the epoll_params fields to be __u64, __u16, and __u8 and
to pad the struct to a multiple of 64bits. Suggested by Greg K-H [8]
and Arnd Bergmann [9].
- remove an unused pr_fmt, left over from the previous revision.
- ioctl now returns -EINVAL when epoll_params.busy_poll_usecs >
U32_MAX.
v2 -> v3:
- cover letter updated to mention why ioctl seems (to me) like a better
choice vs a new syscall.
- patch 3/4 was modified in 3 ways:
- when an unknown ioctl is received, -ENOIOCTLCMD is returned instead
of -EINVAL as the ioctl documentation requires.
- epoll_params.busy_poll_budget can only be set to a value larger than
NAPI_POLL_WEIGHT if code is run by privileged (CAP_NET_ADMIN) users.
Otherwise, -EPERM is returned.
- busy poll specific ioctl code moved out to its own function. On
kernels without busy poll support, -EOPNOTSUPP is returned. This also
makes the kernel build robot happier without littering the code with
more #ifdefs.
- dropped patch 4/4 after Eric Dumazet's review of it when it was sent
independently to the list [10].
v1 -> v2:
- cover letter updated to make a mention of napi_defer_hard_irqs and
gro_flush_timeout as an added step 3 and to cite both Eric Dumazet's
busy polling paper and a paper from University of Waterloo for
additional context. Specifically calling out the xor in patch 1/4
incase it is missed by reviewers.
- Patch 2/4 has its commit message updated, but no functional changes.
Commit message now describes that allowing for a settable budget helps
to improve throughput and is more consistent with other busy poll
mechanisms that allow a settable budget via SO_BUSY_POLL_BUDGET.
- Patch 3/4 was modified to check if the epoll_params.busy_poll_budget
exceeds NAPI_POLL_WEIGHT. The larger value is allowed, but an error is
printed. This was done for consistency with netif_napi_add_weight,
which does the same.
- Patch 3/4 the struct epoll_params was updated to fix the type of the
data field; it was uint8_t and was changed to u8.
- Patch 4/4 added to check if SO_BUSY_POLL_BUDGET exceeds
NAPI_POLL_WEIGHT. The larger value is allowed, but an error is
printed. This was done for consistency with netif_napi_add_weight,
which does the same.
[1]: https://lore.kernel.org/lkml/65b1cb7f73a6a_250560294bd@willemb.c.googlers.com.notmuch/
[2]: https://lore.kernel.org/lkml/20170324170836.15226.87178.stgit@localhost.localdomain/
[3]: https://netdevconf.info/2.1/papers/BusyPollingNextGen.pdf
[4]: https://dl.acm.org/doi/pdf/10.1145/3626780
[5]: https://lore.kernel.org/lkml/2024013001-prison-strum-899d@gregkh/
[6]: https://lore.kernel.org/lkml/Zbm3AXgcwL9D6TNM@dread.disaster.area/
[7]: https://lore.kernel.org/lkml/efee9789-4f05-4202-9a95-21d88f6307b0@kernel.org/
[8]: https://lore.kernel.org/lkml/2024012551-anyone-demeaning-867b@gregkh/
[9]: https://lore.kernel.org/lkml/57b62135-2159-493d-a6bb-47d5be55154a@app.fastmail.com/
[10]: https://lore.kernel.org/lkml/CANn89i+uXsdSVFiQT9fDfGw+h_5QOcuHwPdWi9J=5U6oLXkQTA@mail.gmail.com/
Subject: [PATCH net-next v7 0/4] *** SUBJECT HERE ***
*** BLURB HERE ***
Joe Damato (4):
eventpoll: support busy poll per epoll instance
eventpoll: Add per-epoll busy poll packet budget
eventpoll: Add per-epoll prefer busy poll option
eventpoll: Add epoll ioctl for epoll_params
.../userspace-api/ioctl/ioctl-number.rst | 1 +
fs/eventpoll.c | 130 +++++++++++++++++-
include/uapi/linux/eventpoll.h | 13 ++
3 files changed, 137 insertions(+), 7 deletions(-)
--
2.25.1
^ permalink raw reply
* Re: [PATCH RFT v5 2/7] selftests: Provide helper header for shadow stack testing
From: Edgecombe, Rick P @ 2024-02-09 20:24 UTC (permalink / raw)
To: dietmar.eggemann@arm.com, broonie@kernel.org,
Szabolcs.Nagy@arm.com, brauner@kernel.org,
dave.hansen@linux.intel.com, debug@rivosinc.com, mgorman@suse.de,
vincent.guittot@linaro.org, fweimer@redhat.com, mingo@redhat.com,
rostedt@goodmis.org, hjl.tools@gmail.com, tglx@linutronix.de,
vschneid@redhat.com, shuah@kernel.org, bristot@redhat.com,
hpa@zytor.com, peterz@infradead.org, bp@alien8.de,
bsegall@google.com, x86@kernel.org, juri.lelli@redhat.com
Cc: keescook@chromium.org, jannh@google.com,
linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org,
catalin.marinas@arm.com, linux-api@vger.kernel.org,
will@kernel.org
In-Reply-To: <20240203-clone3-shadow-stack-v5-2-322c69598e4b@kernel.org>
On Sat, 2024-02-03 at 00:04 +0000, Mark Brown wrote:
> While almost all users of shadow stacks should be relying on the
> dynamic
> linker and libc to enable the feature there are several low level
> test
> programs where it is useful to enable without any libc support,
> allowing
> testing without full system enablement. This low level testing is
> helpful
> during bringup of the support itself, and also in enabling coverage
> by
> automated testing without needing all system components in the target
> root
> filesystems to have enablement.
>
> Provide a header with helpers for this purpose, intended for use only
> by
> test programs directly exercising shadow stack interfaces.
Thanks.
Reviewed-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
^ permalink raw reply
* Re: [PATCH RFT v5 3/7] mm: Introduce ARCH_HAS_USER_SHADOW_STACK
From: Edgecombe, Rick P @ 2024-02-09 20:21 UTC (permalink / raw)
To: dietmar.eggemann@arm.com, broonie@kernel.org,
Szabolcs.Nagy@arm.com, brauner@kernel.org,
dave.hansen@linux.intel.com, debug@rivosinc.com, mgorman@suse.de,
vincent.guittot@linaro.org, fweimer@redhat.com, mingo@redhat.com,
rostedt@goodmis.org, hjl.tools@gmail.com, tglx@linutronix.de,
vschneid@redhat.com, shuah@kernel.org, bristot@redhat.com,
hpa@zytor.com, peterz@infradead.org, bp@alien8.de,
bsegall@google.com, x86@kernel.org, juri.lelli@redhat.com
Cc: david@redhat.com, linux-kselftest@vger.kernel.org,
linux-api@vger.kernel.org, keescook@chromium.org,
jannh@google.com, linux-kernel@vger.kernel.org,
catalin.marinas@arm.com, will@kernel.org
In-Reply-To: <20240203-clone3-shadow-stack-v5-3-322c69598e4b@kernel.org>
On Sat, 2024-02-03 at 00:04 +0000, Mark Brown wrote:
> Since multiple architectures have support for shadow stacks and we
> need to
> select support for this feature in several places in the generic code
> provide a generic config option that the architectures can select.
>
> Suggested-by: David Hildenbrand <david@redhat.com>
> Acked-by: David Hildenbrand <david@redhat.com>
> Signed-off-by: Mark Brown <broonie@kernel.org>
Reviewed-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
^ permalink raw reply
* Re: [PATCH RFT v5 0/7] fork: Support shadow stacks in clone3()
From: Edgecombe, Rick P @ 2024-02-09 20:18 UTC (permalink / raw)
To: dietmar.eggemann@arm.com, broonie@kernel.org,
Szabolcs.Nagy@arm.com, brauner@kernel.org,
dave.hansen@linux.intel.com, debug@rivosinc.com, mgorman@suse.de,
vincent.guittot@linaro.org, fweimer@redhat.com, mingo@redhat.com,
rostedt@goodmis.org, hjl.tools@gmail.com, tglx@linutronix.de,
vschneid@redhat.com, shuah@kernel.org, bristot@redhat.com,
hpa@zytor.com, peterz@infradead.org, bp@alien8.de,
bsegall@google.com, x86@kernel.org, juri.lelli@redhat.com
Cc: david@redhat.com, linux-kselftest@vger.kernel.org,
linux-api@vger.kernel.org, keescook@chromium.org,
jannh@google.com, linux-kernel@vger.kernel.org,
catalin.marinas@arm.com, will@kernel.org
In-Reply-To: <20240203-clone3-shadow-stack-v5-0-322c69598e4b@kernel.org>
On Sat, 2024-02-03 at 00:04 +0000, Mark Brown wrote:
> Please note that the x86 portions of this code are build tested only,
> I
> don't appear to have a system that can run CET avaible to me, I have
> done testing with an integration into my pending work for GCS. There
> is
> some possibility that the arm64 implementation may require the use of
> clone3() and explicit userspace allocation of shadow stacks, this is
> still under discussion.
It all passed for me on the x86 side.
^ permalink raw reply
* Re: [PATCH RFT v5 4/7] fork: Add shadow stack support to clone3()
From: Edgecombe, Rick P @ 2024-02-09 20:18 UTC (permalink / raw)
To: dietmar.eggemann@arm.com, broonie@kernel.org,
Szabolcs.Nagy@arm.com, brauner@kernel.org,
dave.hansen@linux.intel.com, debug@rivosinc.com, mgorman@suse.de,
vincent.guittot@linaro.org, fweimer@redhat.com, mingo@redhat.com,
rostedt@goodmis.org, hjl.tools@gmail.com, tglx@linutronix.de,
vschneid@redhat.com, shuah@kernel.org, bristot@redhat.com,
hpa@zytor.com, peterz@infradead.org, bp@alien8.de,
bsegall@google.com, x86@kernel.org, juri.lelli@redhat.com
Cc: keescook@chromium.org, jannh@google.com,
linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org,
catalin.marinas@arm.com, linux-api@vger.kernel.org,
will@kernel.org
In-Reply-To: <20240203-clone3-shadow-stack-v5-4-322c69598e4b@kernel.org>
On Sat, 2024-02-03 at 00:05 +0000, Mark Brown wrote:
> +static bool shstk_consume_token(struct task_struct *tsk,
> + unsigned long addr)
> +{
> + /*
> + * SSP is aligned, so reserved bits and mode bit are a zero,
> just mark
> + * the token 64-bit.
> + */
> + u64 expected = (addr - SS_FRAME_SIZE) | BIT(0);
> + u64 val;
> +
> + /* This should really be an atomic cpmxchg. It is not. */
> + __get_user(val, (__user u64 *)addr);
> + if (val != expected)
> + return false;
> +
> + if (write_user_shstk_64((u64 __user *)addr, 0))
> + return false;
> +
> + return true;
> +}
So, don't we want to consume the token on the *new* task's MM, which
was already duplicated but still unmapped? In which case I think the
other arch's would need to GUP regardless of the existence of shadow
stack atomic ops.
If so, my question is, can we GUP on the new MM at this point? There is
a lot going in copy_process(). My first suspicion of complication is
the work on the child that happens in cgroup_post_fork().
I wonder about adding a shstk_post_fork() to make it easier to think
about and maintain, even if there are no issues today.
^ permalink raw reply
* Re: [PATCH v2 1/2] signal: add the "int si_code" arg to prepare_kill_siginfo()
From: Tycho Andersen @ 2024-02-09 20:01 UTC (permalink / raw)
To: Christian Brauner
Cc: Oleg Nesterov, Eric W. Biederman, Andy Lutomirski, linux-api,
linux-kernel
In-Reply-To: <20240209-traben-geothermie-8c6aa7e1984f@brauner>
On Fri, Feb 09, 2024 at 08:36:24PM +0100, Christian Brauner wrote:
> On Fri, Feb 09, 2024 at 05:39:14PM +0100, Oleg Nesterov wrote:
> > On 02/09, Eric W. Biederman wrote:
> > >
> > > Could you can pass in the destination type instead of the si_code?
> > > Something like I have shown below?
> >
> > ...
> >
> > > info->si_code = (type == PIDTYPE_PID) ? SI_TKILL : SI_USER;
> >
> > Yes, I considered this option too.
> >
> > OK, will send V3 tomorrow.
>
> Hm, I don't think that's necessary if you're happy to have me just fix
> that up in tree. Here's the two patches updated. It was straightforward
> but I have a baby on my lap so double check, please:
>
> From 05ffda39f6f5c887cae319274366cbf856c88fe5 Mon Sep 17 00:00:00 2001
> From: Oleg Nesterov <oleg@redhat.com>
> Date: Fri, 9 Feb 2024 14:06:20 +0100
> Subject: [PATCH 1/2] signal: fill in si_code in prepare_kill_siginfo()
>
> So that do_tkill() can use this helper too. This also simplifies
> the next patch.
>
> TODO: perhaps we can kill prepare_kill_siginfo() and change the
> callers to use SEND_SIG_NOINFO, but this needs some changes in
> __send_signal_locked() and TP_STORE_SIGINFO().
>
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>
> Link: https://lore.kernel.org/r/20240209130620.GA8039@redhat.com
> Signed-off-by: Christian Brauner <brauner@kernel.org>
Looks good to me as well,
Reviewed-by: Tycho Andersen <tandersen@netflix.com>
^ permalink raw reply
* Re: [PATCH v2 1/2] signal: add the "int si_code" arg to prepare_kill_siginfo()
From: Oleg Nesterov @ 2024-02-09 19:53 UTC (permalink / raw)
To: Christian Brauner
Cc: Eric W. Biederman, Andy Lutomirski, Tycho Andersen, linux-api,
linux-kernel
In-Reply-To: <20240209-traben-geothermie-8c6aa7e1984f@brauner>
On 02/09, Christian Brauner wrote:
>
> On Fri, Feb 09, 2024 at 05:39:14PM +0100, Oleg Nesterov wrote:
> > On 02/09, Eric W. Biederman wrote:
> > >
> > > Could you can pass in the destination type instead of the si_code?
> > > Something like I have shown below?
> >
> > ...
> >
> > > info->si_code = (type == PIDTYPE_PID) ? SI_TKILL : SI_USER;
> >
> > Yes, I considered this option too.
> >
> > OK, will send V3 tomorrow.
>
> Hm, I don't think that's necessary if you're happy to have me just fix
> that up in tree.
Thank you!!!
looks obviously correct, but again, I will double check tomorrow just
in case.
> but I have a baby on my lap so double check, please:
;) I'm familiar with this.
Oleg.
^ permalink raw reply
* Re: [PATCH v2 1/2] signal: add the "int si_code" arg to prepare_kill_siginfo()
From: Christian Brauner @ 2024-02-09 19:36 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Eric W. Biederman, Andy Lutomirski, Tycho Andersen, linux-api,
linux-kernel
In-Reply-To: <20240209163914.GE3282@redhat.com>
On Fri, Feb 09, 2024 at 05:39:14PM +0100, Oleg Nesterov wrote:
> On 02/09, Eric W. Biederman wrote:
> >
> > Could you can pass in the destination type instead of the si_code?
> > Something like I have shown below?
>
> ...
>
> > info->si_code = (type == PIDTYPE_PID) ? SI_TKILL : SI_USER;
>
> Yes, I considered this option too.
>
> OK, will send V3 tomorrow.
Hm, I don't think that's necessary if you're happy to have me just fix
that up in tree. Here's the two patches updated. It was straightforward
but I have a baby on my lap so double check, please:
From 05ffda39f6f5c887cae319274366cbf856c88fe5 Mon Sep 17 00:00:00 2001
From: Oleg Nesterov <oleg@redhat.com>
Date: Fri, 9 Feb 2024 14:06:20 +0100
Subject: [PATCH 1/2] signal: fill in si_code in prepare_kill_siginfo()
So that do_tkill() can use this helper too. This also simplifies
the next patch.
TODO: perhaps we can kill prepare_kill_siginfo() and change the
callers to use SEND_SIG_NOINFO, but this needs some changes in
__send_signal_locked() and TP_STORE_SIGINFO().
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Link: https://lore.kernel.org/r/20240209130620.GA8039@redhat.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
---
kernel/signal.c | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/kernel/signal.c b/kernel/signal.c
index c3fac06937e2..1450689302d9 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -3793,12 +3793,13 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait_time32, compat_sigset_t __user *, uthese,
#endif
#endif
-static inline void prepare_kill_siginfo(int sig, struct kernel_siginfo *info)
+static void prepare_kill_siginfo(int sig, struct kernel_siginfo *info,
+ enum pid_type type)
{
clear_siginfo(info);
info->si_signo = sig;
info->si_errno = 0;
- info->si_code = SI_USER;
+ info->si_code = (type == PIDTYPE_PID) ? SI_TKILL : SI_USER;
info->si_pid = task_tgid_vnr(current);
info->si_uid = from_kuid_munged(current_user_ns(), current_uid());
}
@@ -3812,7 +3813,7 @@ SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)
{
struct kernel_siginfo info;
- prepare_kill_siginfo(sig, &info);
+ prepare_kill_siginfo(sig, &info, PIDTYPE_TGID);
return kill_something_info(sig, &info, pid);
}
@@ -3925,7 +3926,7 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,
(kinfo.si_code >= 0 || kinfo.si_code == SI_TKILL))
goto err;
} else {
- prepare_kill_siginfo(sig, &kinfo);
+ prepare_kill_siginfo(sig, &kinfo, PIDTYPE_TGID);
}
/* TODO: respect PIDFD_THREAD */
@@ -3970,12 +3971,7 @@ static int do_tkill(pid_t tgid, pid_t pid, int sig)
{
struct kernel_siginfo info;
- clear_siginfo(&info);
- info.si_signo = sig;
- info.si_errno = 0;
- info.si_code = SI_TKILL;
- info.si_pid = task_tgid_vnr(current);
- info.si_uid = from_kuid_munged(current_user_ns(), current_uid());
+ prepare_kill_siginfo(sig, &info, PIDTYPE_PID);
return do_send_specific(tgid, pid, sig, &info);
}
--
2.43.0
From 7726d44467d6d14cfb888ae1a7e48512ac23fedc Mon Sep 17 00:00:00 2001
From: Oleg Nesterov <oleg@redhat.com>
Date: Fri, 9 Feb 2024 14:06:50 +0100
Subject: [PATCH 2/2] pidfd: change pidfd_send_signal() to respect PIDFD_THREAD
Turn kill_pid_info() into kill_pid_info_type(), this allows to pass any
pid_type to group_send_sig_info(), despite its name it should work fine
even if type = PIDTYPE_PID.
Change pidfd_send_signal() to use PIDTYPE_PID or PIDTYPE_TGID depending
on PIDFD_THREAD.
While at it kill another TODO comment in pidfd_show_fdinfo(). As Christian
expains fdinfo reports f_flags, userspace can already detect PIDFD_THREAD.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Link: https://lore.kernel.org/r/20240209130650.GA8048@redhat.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
---
kernel/fork.c | 2 --
kernel/signal.c | 39 +++++++++++++++++++++++----------------
2 files changed, 23 insertions(+), 18 deletions(-)
diff --git a/kernel/fork.c b/kernel/fork.c
index 4b6d994505ca..3f22ec90c5c6 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -2051,8 +2051,6 @@ static void pidfd_show_fdinfo(struct seq_file *m, struct file *f)
seq_put_decimal_ll(m, "Pid:\t", nr);
- /* TODO: report PIDFD_THREAD */
-
#ifdef CONFIG_PID_NS
seq_put_decimal_ll(m, "\nNSpid:\t", nr);
if (nr > 0) {
diff --git a/kernel/signal.c b/kernel/signal.c
index 1450689302d9..8b8169623850 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -47,6 +47,7 @@
#include <linux/cgroup.h>
#include <linux/audit.h>
#include <linux/sysctl.h>
+#include <uapi/linux/pidfd.h>
#define CREATE_TRACE_POINTS
#include <trace/events/signal.h>
@@ -1436,7 +1437,8 @@ void lockdep_assert_task_sighand_held(struct task_struct *task)
#endif
/*
- * send signal info to all the members of a group
+ * send signal info to all the members of a thread group or to the
+ * individual thread if type == PIDTYPE_PID.
*/
int group_send_sig_info(int sig, struct kernel_siginfo *info,
struct task_struct *p, enum pid_type type)
@@ -1478,7 +1480,8 @@ int __kill_pgrp_info(int sig, struct kernel_siginfo *info, struct pid *pgrp)
return ret;
}
-int kill_pid_info(int sig, struct kernel_siginfo *info, struct pid *pid)
+static int kill_pid_info_type(int sig, struct kernel_siginfo *info,
+ struct pid *pid, enum pid_type type)
{
int error = -ESRCH;
struct task_struct *p;
@@ -1487,11 +1490,10 @@ int kill_pid_info(int sig, struct kernel_siginfo *info, struct pid *pid)
rcu_read_lock();
p = pid_task(pid, PIDTYPE_PID);
if (p)
- error = group_send_sig_info(sig, info, p, PIDTYPE_TGID);
+ error = group_send_sig_info(sig, info, p, type);
rcu_read_unlock();
if (likely(!p || error != -ESRCH))
return error;
-
/*
* The task was unhashed in between, try again. If it
* is dead, pid_task() will return NULL, if we race with
@@ -1500,6 +1502,11 @@ int kill_pid_info(int sig, struct kernel_siginfo *info, struct pid *pid)
}
}
+int kill_pid_info(int sig, struct kernel_siginfo *info, struct pid *pid)
+{
+ return kill_pid_info_type(sig, info, pid, PIDTYPE_TGID);
+}
+
static int kill_proc_info(int sig, struct kernel_siginfo *info, pid_t pid)
{
int error;
@@ -3873,14 +3880,10 @@ static struct pid *pidfd_to_pid(const struct file *file)
* @info: signal info
* @flags: future flags
*
- * The syscall currently only signals via PIDTYPE_PID which covers
- * kill(<positive-pid>, <signal>. It does not signal threads or process
- * groups.
- * In order to extend the syscall to threads and process groups the @flags
- * argument should be used. In essence, the @flags argument will determine
- * what is signaled and not the file descriptor itself. Put in other words,
- * grouping is a property of the flags argument not a property of the file
- * descriptor.
+ * Send the signal to the thread group or to the individual thread depending
+ * on PIDFD_THREAD.
+ * In the future extension to @flags may be used to override the default scope
+ * of @pidfd.
*
* Return: 0 on success, negative errno on failure
*/
@@ -3891,6 +3894,7 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,
struct fd f;
struct pid *pid;
kernel_siginfo_t kinfo;
+ enum pid_type type;
/* Enforce flags be set to 0 until we add an extension. */
if (flags)
@@ -3911,6 +3915,11 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,
if (!access_pidfd_pidns(pid))
goto err;
+ if (f.file->f_flags & PIDFD_THREAD)
+ type = PIDTYPE_PID;
+ else
+ type = PIDTYPE_TGID;
+
if (info) {
ret = copy_siginfo_from_user_any(&kinfo, info);
if (unlikely(ret))
@@ -3926,12 +3935,10 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,
(kinfo.si_code >= 0 || kinfo.si_code == SI_TKILL))
goto err;
} else {
- prepare_kill_siginfo(sig, &kinfo, PIDTYPE_TGID);
+ prepare_kill_siginfo(sig, &kinfo, type);
}
- /* TODO: respect PIDFD_THREAD */
- ret = kill_pid_info(sig, &kinfo, pid);
-
+ ret = kill_pid_info_type(sig, &kinfo, pid, type);
err:
fdput(f);
return ret;
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v2 2/2] pidfd: change pidfd_send_signal() to respect PIDFD_THREAD
From: Tycho Andersen @ 2024-02-09 19:08 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Christian Brauner, Andy Lutomirski, Eric W. Biederman, linux-api,
linux-kernel
In-Reply-To: <20240209130650.GA8048@redhat.com>
On Fri, Feb 09, 2024 at 02:06:50PM +0100, Oleg Nesterov wrote:
> Turn kill_pid_info() into kill_pid_info_type(), this allows to pass any
> pid_type to group_send_sig_info(), despite its name it should work fine
> even if type = PIDTYPE_PID.
>
> Change pidfd_send_signal() to use PIDTYPE_PID or PIDTYPE_TGID depending
> on PIDFD_THREAD.
>
> While at it kill another TODO comment in pidfd_show_fdinfo(). As Christian
> expains fdinfo reports f_flags, userspace can already detect PIDFD_THREAD.
>
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Reviewed-by: Tycho Andersen <tandersen@netflix.com>
^ permalink raw reply
* Re: [PATCH v2 1/2] signal: add the "int si_code" arg to prepare_kill_siginfo()
From: Eric W. Biederman @ 2024-02-09 16:22 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Christian Brauner, Andy Lutomirski, Tycho Andersen, linux-api,
linux-kernel
In-Reply-To: <20240209130620.GA8039@redhat.com>
Oleg Nesterov <oleg@redhat.com> writes:
> So that do_tkill() can use this helper too. This also simplifies
> the next patch.
>
> TODO: perhaps we can kill prepare_kill_siginfo() and change the
> callers to use SEND_SIG_NOINFO, but this needs some changes in
> __send_signal_locked() and TP_STORE_SIGINFO().
Could you can pass in the destination type instead of the si_code?
Something like I have shown below?
That allows the knowledge of the siginfo details to be isolated to
prepare_kill_siginfo, making it easy to verify that a the union members
match the union decode for the signal/si_code combination?
It is all too easy to fill in siginfo improperly.
Looking at siginfo_layout() SI_USER paired with any signal results in
SIL_KILL whereas SI_TKILL paired with any signal results in SIL_RT. A
superset of the fields of SIL_KILL.
We use clear_siginfo() so si_sigval is set to 0 for SI_TKILL which seems
correct. But we do allow userspace if it specifies SI_TKILL to provide
si_sigval. So the current do_tkill code is very close to being wrong.
Likewise you are filling in the details to match what the existing
code is doing, so you are fine. Still it is a loaded footgun
to allow passing in an arbitrary si_code.
Eric
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>
> ---
> kernel/signal.c | 15 +++++----------
> 1 file changed, 5 insertions(+), 10 deletions(-)
>
> diff --git a/kernel/signal.c b/kernel/signal.c
> index c3fac06937e2..a8199fda0d61 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -3793,12 +3793,12 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait_time32, compat_sigset_t __user *, uthese,
> #endif
> #endif
>
> -static inline void prepare_kill_siginfo(int sig, struct kernel_siginfo *info)
> +static void prepare_kill_siginfo(int sig, struct kernel_siginfo *info, int si_code)
> {
> clear_siginfo(info);
> info->si_signo = sig;
> info->si_errno = 0;
> - info->si_code = SI_USER;
> + info->si_code = si_code;
info->si_code = (type == PIDTYPE_PID) ? SI_TKILL : SI_USER;
> info->si_pid = task_tgid_vnr(current);
> info->si_uid = from_kuid_munged(current_user_ns(), current_uid());
> }
> @@ -3812,7 +3812,7 @@ SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)
> {
> struct kernel_siginfo info;
>
> - prepare_kill_siginfo(sig, &info);
> + prepare_kill_siginfo(sig, &info, SI_USER);
>
> return kill_something_info(sig, &info, pid);
> }
> @@ -3925,7 +3925,7 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,
> (kinfo.si_code >= 0 || kinfo.si_code == SI_TKILL))
> goto err;
> } else {
> - prepare_kill_siginfo(sig, &kinfo);
> + prepare_kill_siginfo(sig, &kinfo, SI_USER);
> }
>
> /* TODO: respect PIDFD_THREAD */
> @@ -3970,12 +3970,7 @@ static int do_tkill(pid_t tgid, pid_t pid, int sig)
> {
> struct kernel_siginfo info;
>
> - clear_siginfo(&info);
> - info.si_signo = sig;
> - info.si_errno = 0;
> - info.si_code = SI_TKILL;
> - info.si_pid = task_tgid_vnr(current);
> - info.si_uid = from_kuid_munged(current_user_ns(), current_uid());
> + prepare_kill_siginfo(sig, &info, SI_TKILL);
>
> return do_send_specific(tgid, pid, sig, &info);
> }
^ permalink raw reply
* Re: [PATCH v2 1/2] signal: add the "int si_code" arg to prepare_kill_siginfo()
From: Oleg Nesterov @ 2024-02-09 16:39 UTC (permalink / raw)
To: Eric W. Biederman
Cc: Christian Brauner, Andy Lutomirski, Tycho Andersen, linux-api,
linux-kernel
In-Reply-To: <87sf21zjy8.fsf@email.froward.int.ebiederm.org>
On 02/09, Eric W. Biederman wrote:
>
> Could you can pass in the destination type instead of the si_code?
> Something like I have shown below?
...
> info->si_code = (type == PIDTYPE_PID) ? SI_TKILL : SI_USER;
Yes, I considered this option too.
OK, will send V3 tomorrow.
Oleg.
^ permalink raw reply
* Re: [PATCH v2 1/2] signal: add the "int si_code" arg to prepare_kill_siginfo()
From: Christian Brauner @ 2024-02-09 16:13 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Christian Brauner, Andy Lutomirski, Eric W. Biederman,
Tycho Andersen, linux-api, linux-kernel
In-Reply-To: <20240209130620.GA8039@redhat.com>
On Fri, 09 Feb 2024 14:06:20 +0100, Oleg Nesterov wrote:
> So that do_tkill() can use this helper too. This also simplifies
> the next patch.
>
> TODO: perhaps we can kill prepare_kill_siginfo() and change the
> callers to use SEND_SIG_NOINFO, but this needs some changes in
> __send_signal_locked() and TP_STORE_SIGINFO().
>
> [...]
Applied to the vfs.pidfd branch of the vfs/vfs.git tree.
Patches in the vfs.pidfd branch should appear in linux-next soon.
Please report any outstanding bugs that were missed during review in a
new review to the original patch series allowing us to drop it.
It's encouraged to provide Acked-bys and Reviewed-bys even though the
patch has now been applied. If possible patch trailers will be updated.
Note that commit hashes shown below are subject to change due to rebase,
trailer updates or similar. If in doubt, please check the listed branch.
tree: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
branch: vfs.pidfd
[1/2] signal: add the "int si_code" arg to prepare_kill_siginfo()
https://git.kernel.org/vfs/vfs/c/3a363602809c
[2/2] pidfd: change pidfd_send_signal() to respect PIDFD_THREAD
https://git.kernel.org/vfs/vfs/c/2885a4b3358d
^ permalink raw reply
* Re: [PATCH v2 2/2] pidfd: change pidfd_send_signal() to respect PIDFD_THREAD
From: Oleg Nesterov @ 2024-02-09 15:56 UTC (permalink / raw)
To: Christian Brauner
Cc: Andy Lutomirski, Eric W. Biederman, Tycho Andersen, linux-api,
linux-kernel
In-Reply-To: <20240209-radeln-untrennbar-9d4ae05aa4cc@brauner>
On 02/09, Christian Brauner wrote:
>
> On Fri, Feb 09, 2024 at 04:43:05PM +0100, Oleg Nesterov wrote:
> >
> > So the question: do you think we also want PIDFD_SIGNAL_SESSION_GROUP?
>
> Thought about this as well and my feeling is to wait until someone asks
> for it. Right now, we have a reason to add PIDFD_SIGNAL_PROCESS_GROUP
> because of Andy's use-case. If someone has a use-case for session groups
> then yes. Otherwise I'd just not bother?
OK, agreed.
and I forgot to mention, if you want to add PIDFD_SIGNAL_PRGP you can
look at __kill_pgrp_info().
Oleg.
^ permalink raw reply
* Re: [PATCH v2 2/2] pidfd: change pidfd_send_signal() to respect PIDFD_THREAD
From: Christian Brauner @ 2024-02-09 15:49 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Andy Lutomirski, Eric W. Biederman, Tycho Andersen, linux-api,
linux-kernel
In-Reply-To: <20240209154305.GC3282@redhat.com>
On Fri, Feb 09, 2024 at 04:43:05PM +0100, Oleg Nesterov wrote:
> On 02/09, Christian Brauner wrote:
> >
> > How do you feel about the following (untested...) addition?
>
> LGTM, but let me read this patch once again tomorrow, I have
> a headache today.
Bah, feel better!
>
> > I've played with PIDFD_SIGNAL_PROCESS_GROUP as well but that code is
> > fairly new to me so I would need some more time.
>
> Heh, I was going to send another email to discuss this ;)
>
> Should be simple, but may be need some simple preparations.
>
> Especially if we also want PIDFD_SIGNAL_SESSION_GROUP.
>
> So the question: do you think we also want PIDFD_SIGNAL_SESSION_GROUP?
Thought about this as well and my feeling is to wait until someone asks
for it. Right now, we have a reason to add PIDFD_SIGNAL_PROCESS_GROUP
because of Andy's use-case. If someone has a use-case for session groups
then yes. Otherwise I'd just not bother?
^ permalink raw reply
* Re: [PATCH v2 2/2] pidfd: change pidfd_send_signal() to respect PIDFD_THREAD
From: Oleg Nesterov @ 2024-02-09 15:43 UTC (permalink / raw)
To: Christian Brauner
Cc: Andy Lutomirski, Eric W. Biederman, Tycho Andersen, linux-api,
linux-kernel
In-Reply-To: <20240209-stangen-feuerzeug-17c8662854c9@brauner>
On 02/09, Christian Brauner wrote:
>
> How do you feel about the following (untested...) addition?
LGTM, but let me read this patch once again tomorrow, I have
a headache today.
> I've played with PIDFD_SIGNAL_PROCESS_GROUP as well but that code is
> fairly new to me so I would need some more time.
Heh, I was going to send another email to discuss this ;)
Should be simple, but may be need some simple preparations.
Especially if we also want PIDFD_SIGNAL_SESSION_GROUP.
So the question: do you think we also want PIDFD_SIGNAL_SESSION_GROUP?
Oleg.
^ permalink raw reply
* Re: [PATCH v2 2/2] pidfd: change pidfd_send_signal() to respect PIDFD_THREAD
From: Christian Brauner @ 2024-02-09 15:15 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Andy Lutomirski, Eric W. Biederman, Tycho Andersen, linux-api,
linux-kernel
In-Reply-To: <20240209130650.GA8048@redhat.com>
On Fri, Feb 09, 2024 at 02:06:50PM +0100, Oleg Nesterov wrote:
> Turn kill_pid_info() into kill_pid_info_type(), this allows to pass any
> pid_type to group_send_sig_info(), despite its name it should work fine
> even if type = PIDTYPE_PID.
>
> Change pidfd_send_signal() to use PIDTYPE_PID or PIDTYPE_TGID depending
> on PIDFD_THREAD.
>
> While at it kill another TODO comment in pidfd_show_fdinfo(). As Christian
> expains fdinfo reports f_flags, userspace can already detect PIDFD_THREAD.
>
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>
> ---
How do you feel about the following (untested...) addition?
I've played with PIDFD_SIGNAL_PROCESS_GROUP as well but that code is
fairly new to me so I would need some more time.
From a473512ed8de2e864961f7009e2f20ce4e7a0778 Mon Sep 17 00:00:00 2001
From: Christian Brauner <brauner@kernel.org>
Date: Fri, 9 Feb 2024 15:49:45 +0100
Subject: [PATCH] [RFC] pidfd: allow to override signal scope in
pidfd_send_signal()
Right now we determine the scope of the signal based on the type of
pidfd. There are use-cases where it's useful to override the scope of
the signal. For example in [1]. Add flags to determine the scope of the
signal:
(1) PIDFD_SIGNAL_THREAD: send signal to specific thread
(2) PIDFD_SIGNAL_THREAD_GROUP: send signal to thread-group
I've put off PIDFD_SIGNAL_PROCESS_GROUP for now since I need to stare at
the code a bit longer how this would work.
Link: https://github.com/systemd/systemd/issues/31093 [1]
Signed-off-by: Christian Brauner <brauner@kernel.org>
---
include/uapi/linux/pidfd.h | 4 ++++
kernel/signal.c | 35 ++++++++++++++++++++++++++++-------
2 files changed, 32 insertions(+), 7 deletions(-)
diff --git a/include/uapi/linux/pidfd.h b/include/uapi/linux/pidfd.h
index 2e6461459877..757ed5a668c6 100644
--- a/include/uapi/linux/pidfd.h
+++ b/include/uapi/linux/pidfd.h
@@ -10,4 +10,8 @@
#define PIDFD_NONBLOCK O_NONBLOCK
#define PIDFD_THREAD O_EXCL
+/* Flags for pidfd_send_signal(). */
+#define PIDFD_SIGNAL_THREAD (1UL << 0)
+#define PIDFD_SIGNAL_THREAD_GROUP (1UL << 1)
+
#endif /* _UAPI_LINUX_PIDFD_H */
diff --git a/kernel/signal.c b/kernel/signal.c
index 9578ce17d85d..1d6586964099 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -3872,6 +3872,9 @@ static struct pid *pidfd_to_pid(const struct file *file)
return tgid_pidfd_to_pid(file);
}
+#define PIDFD_SEND_SIGNAL_FLAGS \
+ (PIDFD_SIGNAL_THREAD | PIDFD_SIGNAL_THREAD_GROUP)
+
/**
* sys_pidfd_send_signal - Signal a process through a pidfd
* @pidfd: file descriptor of the process
@@ -3889,14 +3892,19 @@ static struct pid *pidfd_to_pid(const struct file *file)
SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,
siginfo_t __user *, info, unsigned int, flags)
{
- int ret;
+ int ret, si_code;
struct fd f;
struct pid *pid;
kernel_siginfo_t kinfo;
bool thread;
+ enum pid_type si_scope;
/* Enforce flags be set to 0 until we add an extension. */
- if (flags)
+ if (flags & ~PIDFD_SEND_SIGNAL_FLAGS)
+ return -EINVAL;
+
+ /* Ensure that only a single signal scope determining flag is set. */
+ if (hweight32(flags & PIDFD_SEND_SIGNAL_FLAGS) > 1)
return -EINVAL;
f = fdget(pidfd);
@@ -3914,7 +3922,22 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,
if (!access_pidfd_pidns(pid))
goto err;
- thread = f.file->f_flags & PIDFD_THREAD;
+ switch (flags) {
+ case 0:
+ /* Infer scope from the type of pidfd. */
+ thread = (f.file->f_flags & PIDFD_THREAD);
+ si_scope = thread ? PIDTYPE_PID : PIDTYPE_TGID;
+ si_code = thread ? SI_TKILL : SI_USER;
+ break;
+ case PIDFD_SIGNAL_THREAD:
+ si_scope = PIDTYPE_PID;
+ si_code = SI_TKILL;
+ break;
+ case PIDFD_SIGNAL_THREAD_GROUP:
+ si_scope = PIDTYPE_TGID;
+ si_code = SI_USER;
+ break;
+ }
if (info) {
ret = copy_siginfo_from_user_any(&kinfo, info);
@@ -3931,12 +3954,10 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,
(kinfo.si_code >= 0 || kinfo.si_code == SI_TKILL))
goto err;
} else {
- prepare_kill_siginfo(sig, &kinfo,
- thread ? SI_TKILL : SI_USER);
+ prepare_kill_siginfo(sig, &kinfo, si_code);
}
- ret = kill_pid_info_type(sig, &kinfo, pid,
- thread ? PIDTYPE_PID : PIDTYPE_TGID);
+ ret = kill_pid_info_type(sig, &kinfo, pid, si_scope);
err:
fdput(f);
return ret;
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v2 2/2] pidfd: change pidfd_send_signal() to respect PIDFD_THREAD
From: Christian Brauner @ 2024-02-09 15:11 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Andy Lutomirski, Eric W. Biederman, Tycho Andersen, linux-api,
linux-kernel
In-Reply-To: <20240209130650.GA8048@redhat.com>
On Fri, Feb 09, 2024 at 02:06:50PM +0100, Oleg Nesterov wrote:
> Turn kill_pid_info() into kill_pid_info_type(), this allows to pass any
> pid_type to group_send_sig_info(), despite its name it should work fine
> even if type = PIDTYPE_PID.
>
> Change pidfd_send_signal() to use PIDTYPE_PID or PIDTYPE_TGID depending
> on PIDFD_THREAD.
>
> While at it kill another TODO comment in pidfd_show_fdinfo(). As Christian
> expains fdinfo reports f_flags, userspace can already detect PIDFD_THREAD.
>
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>
> ---
Looks good to me,
Reviewed-by: Christian Brauner <brauner@kernel.org>
^ permalink raw reply
* Re: [PATCH v2 1/2] signal: add the "int si_code" arg to prepare_kill_siginfo()
From: Christian Brauner @ 2024-02-09 15:10 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Andy Lutomirski, Eric W. Biederman, Tycho Andersen, linux-api,
linux-kernel
In-Reply-To: <20240209130620.GA8039@redhat.com>
On Fri, Feb 09, 2024 at 02:06:20PM +0100, Oleg Nesterov wrote:
> So that do_tkill() can use this helper too. This also simplifies
> the next patch.
>
> TODO: perhaps we can kill prepare_kill_siginfo() and change the
> callers to use SEND_SIG_NOINFO, but this needs some changes in
> __send_signal_locked() and TP_STORE_SIGINFO().
>
> Signed-off-by: Oleg Nesterov <oleg@redhat.com>
> ---
Looks good to me,
Reviewed-by: Christian Brauner <brauner@kernel.org>
^ permalink raw reply
* [PATCH v2 2/2] pidfd: change pidfd_send_signal() to respect PIDFD_THREAD
From: Oleg Nesterov @ 2024-02-09 13:06 UTC (permalink / raw)
To: Christian Brauner
Cc: Andy Lutomirski, Eric W. Biederman, Tycho Andersen, linux-api,
linux-kernel
In-Reply-To: <20240209130620.GA8039@redhat.com>
Turn kill_pid_info() into kill_pid_info_type(), this allows to pass any
pid_type to group_send_sig_info(), despite its name it should work fine
even if type = PIDTYPE_PID.
Change pidfd_send_signal() to use PIDTYPE_PID or PIDTYPE_TGID depending
on PIDFD_THREAD.
While at it kill another TODO comment in pidfd_show_fdinfo(). As Christian
expains fdinfo reports f_flags, userspace can already detect PIDFD_THREAD.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
kernel/fork.c | 2 --
kernel/signal.c | 38 ++++++++++++++++++++++----------------
2 files changed, 22 insertions(+), 18 deletions(-)
diff --git a/kernel/fork.c b/kernel/fork.c
index cd61ca87d0e6..47b565598063 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -2051,8 +2051,6 @@ static void pidfd_show_fdinfo(struct seq_file *m, struct file *f)
seq_put_decimal_ll(m, "Pid:\t", nr);
- /* TODO: report PIDFD_THREAD */
-
#ifdef CONFIG_PID_NS
seq_put_decimal_ll(m, "\nNSpid:\t", nr);
if (nr > 0) {
diff --git a/kernel/signal.c b/kernel/signal.c
index a8199fda0d61..9578ce17d85d 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -47,6 +47,7 @@
#include <linux/cgroup.h>
#include <linux/audit.h>
#include <linux/sysctl.h>
+#include <uapi/linux/pidfd.h>
#define CREATE_TRACE_POINTS
#include <trace/events/signal.h>
@@ -1436,7 +1437,8 @@ void lockdep_assert_task_sighand_held(struct task_struct *task)
#endif
/*
- * send signal info to all the members of a group
+ * send signal info to all the members of a thread group or to the
+ * individual thread if type == PIDTYPE_PID.
*/
int group_send_sig_info(int sig, struct kernel_siginfo *info,
struct task_struct *p, enum pid_type type)
@@ -1478,7 +1480,8 @@ int __kill_pgrp_info(int sig, struct kernel_siginfo *info, struct pid *pgrp)
return ret;
}
-int kill_pid_info(int sig, struct kernel_siginfo *info, struct pid *pid)
+static int kill_pid_info_type(int sig, struct kernel_siginfo *info,
+ struct pid *pid, enum pid_type type)
{
int error = -ESRCH;
struct task_struct *p;
@@ -1487,11 +1490,10 @@ int kill_pid_info(int sig, struct kernel_siginfo *info, struct pid *pid)
rcu_read_lock();
p = pid_task(pid, PIDTYPE_PID);
if (p)
- error = group_send_sig_info(sig, info, p, PIDTYPE_TGID);
+ error = group_send_sig_info(sig, info, p, type);
rcu_read_unlock();
if (likely(!p || error != -ESRCH))
return error;
-
/*
* The task was unhashed in between, try again. If it
* is dead, pid_task() will return NULL, if we race with
@@ -1500,6 +1502,11 @@ int kill_pid_info(int sig, struct kernel_siginfo *info, struct pid *pid)
}
}
+int kill_pid_info(int sig, struct kernel_siginfo *info, struct pid *pid)
+{
+ return kill_pid_info_type(sig, info, pid, PIDTYPE_TGID);
+}
+
static int kill_proc_info(int sig, struct kernel_siginfo *info, pid_t pid)
{
int error;
@@ -3872,14 +3879,10 @@ static struct pid *pidfd_to_pid(const struct file *file)
* @info: signal info
* @flags: future flags
*
- * The syscall currently only signals via PIDTYPE_PID which covers
- * kill(<positive-pid>, <signal>. It does not signal threads or process
- * groups.
- * In order to extend the syscall to threads and process groups the @flags
- * argument should be used. In essence, the @flags argument will determine
- * what is signaled and not the file descriptor itself. Put in other words,
- * grouping is a property of the flags argument not a property of the file
- * descriptor.
+ * Send the signal to the thread group or to the individual thread depending
+ * on PIDFD_THREAD.
+ * In the future extension to @flags may be used to override the default scope
+ * of @pidfd.
*
* Return: 0 on success, negative errno on failure
*/
@@ -3890,6 +3893,7 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,
struct fd f;
struct pid *pid;
kernel_siginfo_t kinfo;
+ bool thread;
/* Enforce flags be set to 0 until we add an extension. */
if (flags)
@@ -3910,6 +3914,8 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,
if (!access_pidfd_pidns(pid))
goto err;
+ thread = f.file->f_flags & PIDFD_THREAD;
+
if (info) {
ret = copy_siginfo_from_user_any(&kinfo, info);
if (unlikely(ret))
@@ -3925,12 +3931,12 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,
(kinfo.si_code >= 0 || kinfo.si_code == SI_TKILL))
goto err;
} else {
- prepare_kill_siginfo(sig, &kinfo, SI_USER);
+ prepare_kill_siginfo(sig, &kinfo,
+ thread ? SI_TKILL : SI_USER);
}
- /* TODO: respect PIDFD_THREAD */
- ret = kill_pid_info(sig, &kinfo, pid);
-
+ ret = kill_pid_info_type(sig, &kinfo, pid,
+ thread ? PIDTYPE_PID : PIDTYPE_TGID);
err:
fdput(f);
return ret;
--
2.25.1.362.g51ebf55
^ permalink raw reply related
* [PATCH v2 1/2] signal: add the "int si_code" arg to prepare_kill_siginfo()
From: Oleg Nesterov @ 2024-02-09 13:06 UTC (permalink / raw)
To: Christian Brauner
Cc: Andy Lutomirski, Eric W. Biederman, Tycho Andersen, linux-api,
linux-kernel
So that do_tkill() can use this helper too. This also simplifies
the next patch.
TODO: perhaps we can kill prepare_kill_siginfo() and change the
callers to use SEND_SIG_NOINFO, but this needs some changes in
__send_signal_locked() and TP_STORE_SIGINFO().
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
kernel/signal.c | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/kernel/signal.c b/kernel/signal.c
index c3fac06937e2..a8199fda0d61 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -3793,12 +3793,12 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait_time32, compat_sigset_t __user *, uthese,
#endif
#endif
-static inline void prepare_kill_siginfo(int sig, struct kernel_siginfo *info)
+static void prepare_kill_siginfo(int sig, struct kernel_siginfo *info, int si_code)
{
clear_siginfo(info);
info->si_signo = sig;
info->si_errno = 0;
- info->si_code = SI_USER;
+ info->si_code = si_code;
info->si_pid = task_tgid_vnr(current);
info->si_uid = from_kuid_munged(current_user_ns(), current_uid());
}
@@ -3812,7 +3812,7 @@ SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)
{
struct kernel_siginfo info;
- prepare_kill_siginfo(sig, &info);
+ prepare_kill_siginfo(sig, &info, SI_USER);
return kill_something_info(sig, &info, pid);
}
@@ -3925,7 +3925,7 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,
(kinfo.si_code >= 0 || kinfo.si_code == SI_TKILL))
goto err;
} else {
- prepare_kill_siginfo(sig, &kinfo);
+ prepare_kill_siginfo(sig, &kinfo, SI_USER);
}
/* TODO: respect PIDFD_THREAD */
@@ -3970,12 +3970,7 @@ static int do_tkill(pid_t tgid, pid_t pid, int sig)
{
struct kernel_siginfo info;
- clear_siginfo(&info);
- info.si_signo = sig;
- info.si_errno = 0;
- info.si_code = SI_TKILL;
- info.si_pid = task_tgid_vnr(current);
- info.si_uid = from_kuid_munged(current_user_ns(), current_uid());
+ prepare_kill_siginfo(sig, &info, SI_TKILL);
return do_send_specific(tgid, pid, sig, &info);
}
--
2.25.1.362.g51ebf55
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox