From: Lorenzo Stoakes <hidden> Date: 2024-10-26 07:25:33
If you wish to utilise a pidfd interface to refer to the current process or
thread it is rather cumbersome, requiring something like:
int pidfd = pidfd_open(getpid(), 0 or PIDFD_THREAD);
...
close(pidfd);
Or the equivalent call opening /proc/self. It is more convenient to use a
sentinel value to indicate to an interface that accepts a pidfd that we
simply wish to refer to the current process thread.
This series introduces sentinels for this purposes which can be passed as
the pidfd in this instance rather than having to establish a dummy fd for
this purpose.
It is useful to refer to both the current thread from the userland's
perspective for which we use PIDFD_SELF, and the current process from the
userland's perspective, for which we use PIDFD_SELF_PROCESS.
There is unfortunately some confusion between the kernel and userland as to
what constitutes a process - a thread from the userland perspective is a
process in userland, and a userland process is a thread group (more
specifically the thread group leader from the kernel perspective). We
therefore alias things thusly:
* PIDFD_SELF_THREAD aliased by PIDFD_SELF - use PIDTYPE_PID.
* PIDFD_SELF_THREAD_GROUP alised by PIDFD_SELF_PROCESS - use PIDTYPE_TGID.
In all of the kernel code we refer to PIDFD_SELF_THREAD and
PIDFD_SELF_THREAD_GROUP. However we expect users to use PIDFD_SELF and
PIDFD_SELF_PROCESS.
This matters for cases where, for instance, a user unshare()'s FDs or does
thread-specific signal handling and where the user would be hugely confused
if the FDs referenced or signal processed referred to the thread group
leader rather than the individual thread.
We ensure that pidfd_send_signal() and pidfd_getfd() work correctly, and
assert as much in selftests. All other interfaces except setns() will work
implicitly with this new interface, however it doesn't make sense to test
waitid(P_PIDFD, ...) as waiting on ourselves is a blocking operation.
In the case of setns() we explicitly disallow use of PIDFD_SELF* as it
doesn't make sense to obtain the namespaces of our own process, and it
would require work to implement this functionality there that would be of
no use.
We also do not provide the ability to utilise PIDFD_SELF* in ordinary fd
operations such as open() or poll(), as this would require extensive work
and be of no real use.
v6:
* Avoid static inline in UAPI header as suggested by Pedro.
* Place PIDFD_SELF values out of range of errors and any other sentinel as
suggested by Pedro.
v5:
* Fixup self test dependencies on pidfd/pidfd.h.
https://lore.kernel.org/linux-mm/cover.1729848252.git.lorenzo.stoakes@oracle.com/
v4:
* Avoid returning an fd in the __pidfd_get_pid() function as pointed out by
Christian, instead simply always pin the pid and maintain fd scope in the
helper alone.
* Add wrapper header file in tools/include/linux to allow for import of
UAPI pidfd.h header without encountering the collision between system
fcntl.h and linux/fcntl.h as discussed with Shuah and John.
* Fixup tests to import the UAPI pidfd.h header working around conflicts
between system fcntl.h and linux/fcntl.h which the UAPI pidfd.h imports,
as reported by Shuah.
* Use an int for pidfd_is_self_sentinel() to avoid any dependency on
stdbool.h in userland.
https://lore.kernel.org/linux-mm/cover.1729198898.git.lorenzo.stoakes@oracle.com/
v3:
* Do not fput() an invalid fd as reported by kernel test bot.
* Fix unintended churn from moving variable declaration.
https://lore.kernel.org/linux-mm/cover.1729073310.git.lorenzo.stoakes@oracle.com/
v2:
* Fix tests as reported by Shuah.
* Correct RFC version lore link.
https://lore.kernel.org/linux-mm/cover.1728643714.git.lorenzo.stoakes@oracle.com/
Non-RFC v1:
* Removed RFC tag - there seems to be general consensus that this change is
a good idea, but perhaps some debate to be had on implementation. It
seems sensible then to move forward with the RFC flag removed.
* Introduced PIDFD_SELF_THREAD, PIDFD_SELF_THREAD_GROUP and their aliases
PIDFD_SELF and PIDFD_SELF_PROCESS respectively.
* Updated testing accordingly.
https://lore.kernel.org/linux-mm/cover.1728578231.git.lorenzo.stoakes@oracle.com/
RFC version:
https://lore.kernel.org/linux-mm/cover.1727644404.git.lorenzo.stoakes@oracle.com/
Lorenzo Stoakes (5):
pidfd: extend pidfd_get_pid() and de-duplicate pid lookup
pidfd: add PIDFD_SELF_* sentinels to refer to own thread/process
tools: testing: separate out wait_for_pid() into helper header
selftests: pidfd: add pidfd.h UAPI wrapper
selftests: pidfd: add tests for PIDFD_SELF_*
include/linux/pid.h | 34 ++++-
include/uapi/linux/pidfd.h | 10 ++
kernel/exit.c | 4 +-
kernel/nsproxy.c | 1 +
kernel/pid.c | 65 +++++---
kernel/signal.c | 29 +---
tools/include/linux/pidfd.h | 14 ++
tools/testing/selftests/cgroup/test_kill.c | 2 +-
.../pid_namespace/regression_enomem.c | 2 +-
tools/testing/selftests/pidfd/Makefile | 3 +-
tools/testing/selftests/pidfd/pidfd.h | 28 +---
.../selftests/pidfd/pidfd_getfd_test.c | 141 ++++++++++++++++++
tools/testing/selftests/pidfd/pidfd_helpers.h | 39 +++++
.../selftests/pidfd/pidfd_setns_test.c | 11 ++
tools/testing/selftests/pidfd/pidfd_test.c | 76 ++++++++--
15 files changed, 371 insertions(+), 88 deletions(-)
create mode 100644 tools/include/linux/pidfd.h
create mode 100644 tools/testing/selftests/pidfd/pidfd_helpers.h
--
2.47.0
From: Lorenzo Stoakes <hidden> Date: 2024-10-26 07:25:28
The means by which a pid is determined from a pidfd is duplicated, with
some callers holding a reference to the (pid)fd, and others explicitly
pinning the pid.
Introduce __pidfd_get_pid() which narrows this to one approach of pinning
the pid, with an optional output parameters for file->f_flags to avoid the
need to hold onto a file to retrieve this.
Additionally, allow the ability to open a pidfd by opening a /proc/<pid>
directory, utilised by the pidfd_send_signal() system call, providing a
pidfd_get_pid_proc() helper function to do so.
Doing this allows us to eliminate open-coded pidfd pid lookup and to
consistently handle this in one place.
This lays the groundwork for a subsequent patch which adds a new sentinel
pidfd to explicitly reference the current process (i.e. thread group
leader) without the need for a pidfd.
Reviewed-by: Shakeel Butt <shakeel.butt@linux.dev>
Signed-off-by: Lorenzo Stoakes <redacted>
---
include/linux/pid.h | 30 +++++++++++++++++++++++++++++-
kernel/pid.c | 42 ++++++++++++++++++++++++------------------
kernel/signal.c | 29 ++++++-----------------------
3 files changed, 59 insertions(+), 42 deletions(-)
@@ -534,22 +535,32 @@ struct pid *find_ge_pid(int nr, struct pid_namespace *ns)}EXPORT_SYMBOL_GPL(find_ge_pid);-structpid*pidfd_get_pid(unsignedintfd,unsignedint*flags)+structpid*__pidfd_get_pid(unsignedintpidfd,boolallow_proc,+unsignedint*flags){-structfdf;structpid*pid;+structfdf=fdget(pidfd);+structfile*file=fd_file(f);-f=fdget(fd);-if(!fd_file(f))+if(!file)returnERR_PTR(-EBADF);-pid=pidfd_pid(fd_file(f));-if(!IS_ERR(pid)){-get_pid(pid);-*flags=fd_file(f)->f_flags;+pid=pidfd_pid(file);+/* If we allow opening a pidfd via /proc/<pid>, do so. */+if(IS_ERR(pid)&&allow_proc)+pid=tgid_pidfd_to_pid(file);++if(IS_ERR(pid)){+fdput(f);+returnpid;}+/* Pin pid before we release fd. */+get_pid(pid);+if(flags)+*flags=file->f_flags;fdput(f);+returnpid;}
@@ -747,23 +758,18 @@ SYSCALL_DEFINE3(pidfd_getfd, int, pidfd, int, fd,unsignedint,flags){structpid*pid;-structfdf;intret;/* flags is currently unused - make sure it's unset */if(flags)return-EINVAL;-f=fdget(pidfd);-if(!fd_file(f))-return-EBADF;--pid=pidfd_pid(fd_file(f));+pid=pidfd_get_pid(pidfd,NULL);if(IS_ERR(pid))-ret=PTR_ERR(pid);-else-ret=pidfd_getfd(pid,fd);+returnPTR_ERR(pid);-fdput(f);+ret=pidfd_getfd(pid,fd);++put_pid(pid);returnret;}
@@ -3875,17 +3875,6 @@ static int copy_siginfo_from_user_any(kernel_siginfo_t *kinfo,returncopy_siginfo_from_user(kinfo,info);}-staticstructpid*pidfd_to_pid(conststructfile*file)-{-structpid*pid;--pid=pidfd_pid(file);-if(!IS_ERR(pid))-returnpid;--returntgid_pidfd_to_pid(file);-}-#define PIDFD_SEND_SIGNAL_FLAGS \(PIDFD_SIGNAL_THREAD|PIDFD_SIGNAL_THREAD_GROUP|\PIDFD_SIGNAL_PROCESS_GROUP)
@@ -3908,10 +3897,10 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,siginfo_t__user*,info,unsignedint,flags){intret;-structfdf;structpid*pid;kernel_siginfo_tkinfo;enumpid_typetype;+unsignedintf_flags;/* Enforce flags be set to 0 until we add an extension. */if(flags&~PIDFD_SEND_SIGNAL_FLAGS)
@@ -3921,16 +3910,10 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,if(hweight32(flags&PIDFD_SEND_SIGNAL_FLAGS)>1)return-EINVAL;-f=fdget(pidfd);-if(!fd_file(f))-return-EBADF;-/* Is this a pidfd? */-pid=pidfd_to_pid(fd_file(f));-if(IS_ERR(pid)){-ret=PTR_ERR(pid);-gotoerr;-}+pid=pidfd_get_pid_proc(pidfd,&f_flags);+if(IS_ERR(pid))+returnPTR_ERR(pid);ret=-EINVAL;if(!access_pidfd_pidns(pid))
@@ -3939,7 +3922,7 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,switch(flags){case0:/* Infer scope from the type of pidfd. */-if(fd_file(f)->f_flags&PIDFD_THREAD)+if(f_flags&PIDFD_THREAD)type=PIDTYPE_PID;elsetype=PIDTYPE_TGID;
From: Lorenzo Stoakes <hidden> Date: 2024-10-26 07:25:36
It is useful to be able to utilise the pidfd mechanism to reference the
current thread or process (from a userland point of view - thread group
leader from the kernel's point of view).
Therefore introduce PIDFD_SELF_THREAD to refer to the current thread, and
PIDFD_SELF_THREAD_GROUP to refer to the current thread group leader.
For convenience and to avoid confusion from userland's perspective we alias
these:
* PIDFD_SELF is an alias for PIDFD_SELF_THREAD - This is nearly always what
the user will want to use, as they would find it surprising if for
instance fd's were unshared()'d and they wanted to invoke pidfd_getfd()
and that failed.
* PIDFD_SELF_PROCESS is an alias for PIDFD_SELF_THREAD_GROUP - Most users
have no concept of thread groups or what a thread group leader is, and
from userland's perspective and nomenclature this is what userland
considers to be a process.
Due to the refactoring of the central __pidfd_get_pid() function we can
implement this functionality centrally, providing the use of this sentinel
in most functionality which utilises pidfd's.
We need to explicitly adjust kernel_waitid_prepare() to permit this (though
it wouldn't really make sense to use this there, we provide the ability for
consistency).
We explicitly disallow use of this in setns(), which would otherwise have
required explicit custom handling, as it doesn't make sense to set the
current calling thread to join the namespace of itself.
As the callers of pidfd_get_pid() expect an increased reference count on
the pid we do so in the self case, reducing churn and avoiding any breakage
from existing logic which decrements this reference count.
This change implicitly provides PIDFD_SELF_* support in the waitid(P_PIDFS,
...), process_madvise(), process_mrelease(), pidfd_send_signal(), and
pidfd_getfd() system calls.
Things such as polling a pidfs and general fd operations are not supported,
this strictly provides the sentinel for APIs which explicitly accept a
pidfd.
Suggested-by: Pedro Falcato <redacted>
Reviewed-by: Shakeel Butt <shakeel.butt@linux.dev>
Signed-off-by: Lorenzo Stoakes <redacted>
---
include/linux/pid.h | 8 ++++--
include/uapi/linux/pidfd.h | 10 ++++++++
kernel/exit.c | 4 ++-
kernel/nsproxy.c | 1 +
kernel/pid.c | 51 ++++++++++++++++++++++++--------------
5 files changed, 53 insertions(+), 21 deletions(-)
@@ -535,33 +535,48 @@ struct pid *find_ge_pid(int nr, struct pid_namespace *ns)}EXPORT_SYMBOL_GPL(find_ge_pid);+staticstructpid*pidfd_get_pid_self(unsignedintpidfd,unsignedint*flags)+{+boolis_thread=pidfd==PIDFD_SELF_THREAD;+enumpid_typetype=is_thread?PIDTYPE_PID:PIDTYPE_TGID;+structpid*pid=*task_pid_ptr(current,type);++/* The caller expects an elevated reference count. */+get_pid(pid);+returnpid;+}+structpid*__pidfd_get_pid(unsignedintpidfd,boolallow_proc,unsignedint*flags){-structpid*pid;-structfdf=fdget(pidfd);-structfile*file=fd_file(f);+if(pidfd==PIDFD_SELF_THREAD||pidfd==PIDFD_SELF_THREAD_GROUP){+returnpidfd_get_pid_self(pidfd,flags);+}else{+structpid*pid;+structfdf=fdget(pidfd);+structfile*file=fd_file(f);-if(!file)-returnERR_PTR(-EBADF);+if(!file)+returnERR_PTR(-EBADF);-pid=pidfd_pid(file);-/* If we allow opening a pidfd via /proc/<pid>, do so. */-if(IS_ERR(pid)&&allow_proc)-pid=tgid_pidfd_to_pid(file);+pid=pidfd_pid(file);+/* If we allow opening a pidfd via /proc/<pid>, do so. */+if(IS_ERR(pid)&&allow_proc)+pid=tgid_pidfd_to_pid(file);-if(IS_ERR(pid)){+if(IS_ERR(pid)){+fdput(f);+returnpid;+}++/* Pin pid before we release fd. */+get_pid(pid);+if(flags)+*flags=file->f_flags;fdput(f);+returnpid;}--/* Pin pid before we release fd. */-get_pid(pid);-if(flags)-*flags=file->f_flags;-fdput(f);--returnpid;}/**--
From: Lorenzo Stoakes <hidden> Date: 2024-10-26 07:25:37
It seems tests other than the pidfd tests use the wait_for_pid() function
declared in pidfd.h.
Since we will shortly be modifying pidfd.h in a way that might clash with
other tests, separate this out and update tests accordingly.
Signed-off-by: Lorenzo Stoakes <redacted>
---
tools/testing/selftests/cgroup/test_kill.c | 2 +-
.../pid_namespace/regression_enomem.c | 2 +-
tools/testing/selftests/pidfd/pidfd.h | 26 +------------
tools/testing/selftests/pidfd/pidfd_helpers.h | 39 +++++++++++++++++++
4 files changed, 42 insertions(+), 27 deletions(-)
create mode 100644 tools/testing/selftests/pidfd/pidfd_helpers.h
From: Lorenzo Stoakes <hidden> Date: 2024-10-26 07:25:37
Conflicts can arise between system fcntl.h and linux/fcntl.h, imported by
the linux/pidfd.h UAPI header.
Work around this by adding a wrapper for linux/pidfd.h to
tools/include/ which sets the linux/fcntl.h header guard ahead of
importing the pidfd.h header file.
Adjust the pidfd selftests Makefile to reference this include directory and
put it at a higher precidence than any make header installed headers to
ensure the wrapper is preferred.
This way we can directly import the UAPI header file without issue, use the
latest system header file without having to duplicate anything.
Reviewed-by: Shuah Khan <skhan@linuxfoundation.org>
Signed-off-by: Lorenzo Stoakes <redacted>
---
tools/include/linux/pidfd.h | 14 ++++++++++++++
tools/testing/selftests/pidfd/Makefile | 3 +--
2 files changed, 15 insertions(+), 2 deletions(-)
create mode 100644 tools/include/linux/pidfd.h
From: Lorenzo Stoakes <hidden> Date: 2024-10-26 07:25:40
Add tests to assert that PIDFD_SELF_* correctly refers to the current
thread and process.
This is only practically meaningful to pidfd_send_signal() and
pidfd_getfd(), but also explicitly test that we disallow this feature for
setns() where it would make no sense.
We cannot reasonably wait on ourself using waitid(P_PIDFD, ...) so while in
theory PIDFD_SELF_* would work here, we'd be left blocked if we tried it.
We defer testing of mm-specific functionality which uses pidfd, namely
process_madvise() and process_mrelease() to mm testing (though note the
latter can not be sensibly tested as it would require the testing process
to be dying).
Reviewed-by: Shuah Khan <skhan@linuxfoundation.org>
Signed-off-by: Lorenzo Stoakes <redacted>
---
tools/testing/selftests/pidfd/pidfd.h | 2 +
.../selftests/pidfd/pidfd_getfd_test.c | 141 ++++++++++++++++++
.../selftests/pidfd/pidfd_setns_test.c | 11 ++
tools/testing/selftests/pidfd/pidfd_test.c | 76 ++++++++--
4 files changed, 218 insertions(+), 12 deletions(-)
@@ -114,6 +116,94 @@ static int child(int sk)returnret;}+staticint__pidfd_self_thread_worker(unsignedlongpage_size)+{+intmemfd;+intnewfd;+char*ptr;+interr=0;++/*+*UnshareourFDssowehaveourownset.Thismeans+*PIDFD_SELF_THREAD_GROUPwillfal.+*/+if(unshare(CLONE_FILES)<0){+err=-errno;+gotoexit;+}++/* Truncate, map in and write to our memfd. */+memfd=sys_memfd_create("test_self_child",0);+if(memfd<0){+err=-errno;+gotoexit;+}++if(ftruncate(memfd,page_size)){+err=-errno;+gotoexit_close_memfd;+}++ptr=mmap(NULL,page_size,PROT_READ|PROT_WRITE,+MAP_SHARED,memfd,0);+if(ptr==MAP_FAILED){+err=-errno;+gotoexit_close_memfd;+}+ptr[0]='y';+if(munmap(ptr,page_size)){+err=-errno;+gotoexit_close_memfd;+}++/* Get a thread-local duplicate of our memfd. */+newfd=sys_pidfd_getfd(PIDFD_SELF_THREAD,memfd,0);+if(newfd<0){+err=-errno;+gotoexit_close_memfd;+}++if(memfd==newfd){+err=-EINVAL;+gotoexit_close_fds;+}++/* Map in new fd and make sure that the data is as expected. */+ptr=mmap(NULL,page_size,PROT_READ|PROT_WRITE,+MAP_SHARED,newfd,0);+if(ptr==MAP_FAILED){+err=-errno;+gotoexit_close_fds;+}++if(ptr[0]!='y'){+err=-EINVAL;+gotoexit_close_fds;+}++if(munmap(ptr,page_size)){+err=-errno;+gotoexit_close_fds;+}++exit_close_fds:+close(newfd);+exit_close_memfd:+close(memfd);+exit:+returnerr;+}++staticvoid*pidfd_self_thread_worker(void*arg)+{+unsignedlongpage_size=(unsignedlong)arg;+intret;++/* We forward any errors for the caller to handle. */+ret=__pidfd_self_thread_worker(page_size);+return(void*)(intptr_t)ret;+}+FIXTURE(child){/*
@@ -264,6 +354,57 @@ TEST_F(child, no_strange_EBADF)EXPECT_EQ(errno,ESRCH);}+TEST(pidfd_self)+{+intmemfd=sys_memfd_create("test_self",0);+unsignedlongpage_size=sysconf(_SC_PAGESIZE);+intnewfd;+char*ptr;+pthread_tthread;+void*res;+interr;++ASSERT_GE(memfd,0);+ASSERT_EQ(ftruncate(memfd,page_size),0);++/*+*Mapsowecanassertthattheduplicatedfdreferencesthesame+*memory.+*/+ptr=mmap(NULL,page_size,PROT_READ|PROT_WRITE,+MAP_SHARED,memfd,0);+ASSERT_NE(ptr,MAP_FAILED);+ptr[0]='x';+ASSERT_EQ(munmap(ptr,page_size),0);++/* Now get a duplicate of our memfd. */+newfd=sys_pidfd_getfd(PIDFD_SELF_THREAD_GROUP,memfd,0);+ASSERT_GE(newfd,0);+ASSERT_NE(memfd,newfd);++/* Now map duplicate fd and make sure it references the same memory. */+ptr=mmap(NULL,page_size,PROT_READ|PROT_WRITE,+MAP_SHARED,newfd,0);+ASSERT_NE(ptr,MAP_FAILED);+ASSERT_EQ(ptr[0],'x');+ASSERT_EQ(munmap(ptr,page_size),0);++/* Cleanup. */+close(memfd);+close(newfd);++/*+*Fireupthethreadandassertthatwecanlookupthethread-specific+*PIDFD_SELF_THREAD(alsoaliasedbyPIDFD_SELF).+*/+ASSERT_EQ(pthread_create(&thread,NULL,pidfd_self_thread_worker,+(void*)page_size),0);+ASSERT_EQ(pthread_join(thread,&res),0);+err=(int)(intptr_t)res;++ASSERT_EQ(err,0);+}+#if __NR_pidfd_getfd == -1intmain(void){
@@ -42,12 +42,41 @@ static pid_t pidfd_clone(int flags, int *pidfd, int (*fn)(void *))#endif}-staticintsignal_received;+staticpthread_tsignal_received;staticvoidset_signal_received_on_sigusr1(intsig){if(sig==SIGUSR1)-signal_received=1;+signal_received=pthread_self();+}++staticintsend_signal(intpidfd)+{+intret=0;++if(sys_pidfd_send_signal(pidfd,SIGUSR1,NULL,0)<0){+ret=-EINVAL;+gotoexit;+}++if(signal_received!=pthread_self()){+ret=-EINVAL;+gotoexit;+}++exit:+signal_received=0;+returnret;+}++staticvoid*send_signal_worker(void*arg)+{+intpidfd=(int)(intptr_t)arg;+intret;++/* We forward any errors for the caller to handle. */+ret=send_signal(pidfd);+return(void*)(intptr_t)ret;}/*
@@ -66,25 +98,45 @@ static int test_pidfd_send_signal_simple_success(void)return0;}+signal(SIGUSR1,set_signal_received_on_sigusr1);++/* Try sending a signal to ourselves via /proc/self. */pidfd=open("/proc/self",O_DIRECTORY|O_CLOEXEC);if(pidfd<0)ksft_exit_fail_msg("%s test: Failed to open process file descriptor\n",test_name);+err=send_signal(pidfd);+if(err)+ksft_exit_fail_msg(+"%s test: Error %d on sending pidfd signal\n",+test_name,err);+close(pidfd);-signal(SIGUSR1,set_signal_received_on_sigusr1);+/* Now try the same thing only using PIDFD_SELF_THREAD_GROUP. */+err=send_signal(PIDFD_SELF_THREAD_GROUP);+if(err)+ksft_exit_fail_msg(+"%s test: Error %d on PIDFD_SELF_THREAD_GROUP signal\n",+test_name,err);-ret=sys_pidfd_send_signal(pidfd,SIGUSR1,NULL,0);-close(pidfd);-if(ret<0)-ksft_exit_fail_msg("%s test: Failed to send signal\n",+/*+*NowtrythesamethinginathreadandassertthreadIDisequalto+*workerthreadID.+*/+if(pthread_create(&thread,NULL,send_signal_worker,+(void*)(intptr_t)PIDFD_SELF_THREAD))+ksft_exit_fail_msg("%s test: Failed to create thread\n",test_name);--if(signal_received!=1)-ksft_exit_fail_msg("%s test: Failed to receive signal\n",+if(pthread_join(thread,&thread_res))+ksft_exit_fail_msg("%s test: Failed to join thread\n",test_name);+err=(int)(intptr_t)thread_res;+if(err)+ksft_exit_fail_msg(+"%s test: Error %d on PIDFD_SELF_THREAD signal\n",+test_name,err);-signal_received=0;ksft_test_result_pass("%s test: Sent signal\n",test_name);return0;}
From: Christian Brauner <brauner@kernel.org> Date: 2024-10-28 15:34:38
On Sat, Oct 26, 2024 at 08:24:58AM +0100, Lorenzo Stoakes wrote:
It is useful to be able to utilise the pidfd mechanism to reference the
current thread or process (from a userland point of view - thread group
leader from the kernel's point of view).
Therefore introduce PIDFD_SELF_THREAD to refer to the current thread, and
PIDFD_SELF_THREAD_GROUP to refer to the current thread group leader.
For convenience and to avoid confusion from userland's perspective we alias
these:
* PIDFD_SELF is an alias for PIDFD_SELF_THREAD - This is nearly always what
the user will want to use, as they would find it surprising if for
instance fd's were unshared()'d and they wanted to invoke pidfd_getfd()
and that failed.
* PIDFD_SELF_PROCESS is an alias for PIDFD_SELF_THREAD_GROUP - Most users
have no concept of thread groups or what a thread group leader is, and
from userland's perspective and nomenclature this is what userland
considers to be a process.
Due to the refactoring of the central __pidfd_get_pid() function we can
implement this functionality centrally, providing the use of this sentinel
in most functionality which utilises pidfd's.
We need to explicitly adjust kernel_waitid_prepare() to permit this (though
it wouldn't really make sense to use this there, we provide the ability for
consistency).
We explicitly disallow use of this in setns(), which would otherwise have
required explicit custom handling, as it doesn't make sense to set the
current calling thread to join the namespace of itself.
As the callers of pidfd_get_pid() expect an increased reference count on
the pid we do so in the self case, reducing churn and avoiding any breakage
from existing logic which decrements this reference count.
This change implicitly provides PIDFD_SELF_* support in the waitid(P_PIDFS,
...), process_madvise(), process_mrelease(), pidfd_send_signal(), and
pidfd_getfd() system calls.
Things such as polling a pidfs and general fd operations are not supported,
this strictly provides the sentinel for APIs which explicitly accept a
pidfd.
Suggested-by: Pedro Falcato <redacted>
Reviewed-by: Shakeel Butt <shakeel.butt@linux.dev>
Signed-off-by: Lorenzo Stoakes <redacted>
---
Currently, a pidfd based system call like pidfd_send_signal() would
simply do:
fdget(pidfd);
// use struct pid
fdput(pidfd);
Where the lifetime of @pid is guaranteed by @file. And in the regular
case where there's only a single thread the file code will avoid taking
a reference. Thus, there's no reference count bump on fdget(), nor a
drop on fdput(), nor a get_pid() or put_pid().
With your patch series you will always cause reference counts on @pid to
be taken for everyone. And I wouldn't be surprised if we get performance
regressions for this.
In one of my earlier mails I had mused about a fdput() like primitive.
What I roughly, hastily, and under the influence of the flu, sketched in
the _completey untested_ patch I appended illustrates roughly what I had
been thinking about.
From: Lorenzo Stoakes <hidden> Date: 2024-10-28 16:06:41
On Mon, Oct 28, 2024 at 04:34:33PM +0100, Christian Brauner wrote:
On Sat, Oct 26, 2024 at 08:24:58AM +0100, Lorenzo Stoakes wrote:
quoted
It is useful to be able to utilise the pidfd mechanism to reference the
current thread or process (from a userland point of view - thread group
leader from the kernel's point of view).
Therefore introduce PIDFD_SELF_THREAD to refer to the current thread, and
PIDFD_SELF_THREAD_GROUP to refer to the current thread group leader.
For convenience and to avoid confusion from userland's perspective we alias
these:
* PIDFD_SELF is an alias for PIDFD_SELF_THREAD - This is nearly always what
the user will want to use, as they would find it surprising if for
instance fd's were unshared()'d and they wanted to invoke pidfd_getfd()
and that failed.
* PIDFD_SELF_PROCESS is an alias for PIDFD_SELF_THREAD_GROUP - Most users
have no concept of thread groups or what a thread group leader is, and
from userland's perspective and nomenclature this is what userland
considers to be a process.
Due to the refactoring of the central __pidfd_get_pid() function we can
implement this functionality centrally, providing the use of this sentinel
in most functionality which utilises pidfd's.
We need to explicitly adjust kernel_waitid_prepare() to permit this (though
it wouldn't really make sense to use this there, we provide the ability for
consistency).
We explicitly disallow use of this in setns(), which would otherwise have
required explicit custom handling, as it doesn't make sense to set the
current calling thread to join the namespace of itself.
As the callers of pidfd_get_pid() expect an increased reference count on
the pid we do so in the self case, reducing churn and avoiding any breakage
from existing logic which decrements this reference count.
This change implicitly provides PIDFD_SELF_* support in the waitid(P_PIDFS,
...), process_madvise(), process_mrelease(), pidfd_send_signal(), and
pidfd_getfd() system calls.
Things such as polling a pidfs and general fd operations are not supported,
this strictly provides the sentinel for APIs which explicitly accept a
pidfd.
Suggested-by: Pedro Falcato <redacted>
Reviewed-by: Shakeel Butt <shakeel.butt@linux.dev>
Signed-off-by: Lorenzo Stoakes <redacted>
---
Currently, a pidfd based system call like pidfd_send_signal() would
simply do:
fdget(pidfd);
// use struct pid
fdput(pidfd);
Where the lifetime of @pid is guaranteed by @file. And in the regular
case where there's only a single thread the file code will avoid taking
a reference. Thus, there's no reference count bump on fdget(), nor a
drop on fdput(), nor a get_pid() or put_pid().
Right I missed that fdget() wouldn't take a reference count I assumed it
would be equivalent, my mistake.
With your patch series you will always cause reference counts on @pid to
be taken for everyone. And I wouldn't be surprised if we get performance
regressions for this.
This was in response to you review saying I can't pass around a pointer to
the fd, originally I didn't do this.
This was the only way I could find to de-jank and make my shared function
not end up problematic in the light of wanting to keep the fd within a
single scope, I didn't realise that passing that by value would be ok.
But obviously hadn't realised that fdget()/fdput() sometimes doesn't change
a reference count, mea culpa on that not an fs person...
In one of my earlier mails I had mused about a fdput() like primitive.
What I roughly, hastily, and under the influence of the flu, sketched in
the _completey untested_ patch I appended illustrates roughly what I had
been thinking about.
OK, I was really uncertain as to what you meant regarding the scope of this
value so had assumed we couldn't do something like assigning the value like
that.
I guess I'll try to adapt that and respin a v7 when I get a chance.
Fwiw, what you've done here is essentially reimplement the already
existing get_task_pid() helper that you could simply use.
We're looking up PIDFD_SELF_* values here. So presumably you mean the:
struct pid *pid = *task_pid_ptr(current, type);
/* The caller expects an elevated reference count. */
get_pid(pid);
Bit is duplicated vs. get_task_pid()?
I did that because it wasn't clear doing that under the RCU lock was
necessary or useful?
It seems useful still to have the PIDFD_SELF stuff qseparate, I can replace
those two lines with a call to get_task_pid() if you prefer? Unless you
meant something else?
I think the else can just go and we can save an indentation level.
This has been raised a couple times before by other reviewers, this is just
so we can declare variables, especially the fd variable, which you were
very clear _must_ retain scope only where it used.
Otherwise I have to do something like;
struct fd f = {};
if (...) { return ...; }
f = fdget(...);
This way we don't need to do that.
I mean probably the compiler would do the right thing but it just seems
ugly to assign/reassign a stack value like that.
Ah, I see struct fd is just a wrapper around an unsigned long, so probably
not a big deal to just leave it unassigned then.
This was the only reason I did this, I usually much prefer the guard
pattern.
OK if you're fine with this value being assigned like that then no problem
will change!
quoted
+ struct pid *pid;
+ struct fd f = fdget(pidfd);
+ struct file *file = fd_file(f);
- if (!file)
- return ERR_PTR(-EBADF);
+ if (!file)
+ return ERR_PTR(-EBADF);
- pid = pidfd_pid(file);
- /* If we allow opening a pidfd via /proc/<pid>, do so. */
- if (IS_ERR(pid) && allow_proc)
- pid = tgid_pidfd_to_pid(file);
+ pid = pidfd_pid(file);
+ /* If we allow opening a pidfd via /proc/<pid>, do so. */
+ if (IS_ERR(pid) && allow_proc)
+ pid = tgid_pidfd_to_pid(file);
- if (IS_ERR(pid)) {
+ if (IS_ERR(pid)) {
+ fdput(f);
+ return pid;
+ }
+
+ /* Pin pid before we release fd. */
+ get_pid(pid);
+ if (flags)
+ *flags = file->f_flags;
fdput(f);
+
return pid;
}
-
- /* Pin pid before we release fd. */
- get_pid(pid);
- if (flags)
- *flags = file->f_flags;
- fdput(f);
-
- return pid;
}
/**
--
2.47.0
From: Lorenzo Stoakes <hidden> Date: 2024-10-30 16:38:06
On Mon, Oct 28, 2024 at 04:06:07PM +0000, Lorenzo Stoakes wrote:
I guess I'll try to adapt that and respin a v7 when I get a chance.
Hm looking at this draft patch, it seems like a total rework of pidfd's
across the board right (now all pidfd's will need to be converted to
pid_fd)? Correct me if I'm wrong.
If only for the signal case, it seems like overkill to define a whole
pid_fd and to use this CLASS() wrapper just for this one instance.
If the intent is to convert _all_ pidfd's to use this type, it feels really
out of scope for this series and I think we'd probably instead want to go
off and do that as a separate series and put this on hold until that is
done.
If instead you mean that we ought to do something like this just for the
signal case, it feels like it'd be quite a bit of extra abstraction just
used in this one case but nowhere else, I think if you did an abstraction
like this it would _have_ to be across the board right?
I agree that the issue is with this one signal case that pins only the fd
(rather than this pid) where this 'pinning' doesn't _necessary_ mess around
with reference counts.
So we definitely must address this, but the issue you had with the first
approach was that I think (correct me if I'm wrong) I was passing a pointer
to a struct fd which is not permitted right?
Could we pass the struct fd by value to avoid this? I think we'd have to
unfortunately special-case this and probably duplicate some code which is a
pity as I liked the idea of abstracting everything to one place, but we can
obviously do that.
So I guess to TL;DR it, the options are:
1. Implement pid_fd everywhere, in which case I will leave off on
this series and I guess, if I have time I could look at trying to
implement that or perhaps you'd prefer to?
2. We are good for the sake of this series to special-case a pidfd_to_pid()
implementation (used only by the pidfd_send_signal() syscall)
3. Something else, or I am misunderstanding your point :)
Let me know how you want me to proceed on this as we're at v6 already and I
want to be _really_ sure I'm doing what you want here.
Thanks!
From: Lorenzo Stoakes <hidden> Date: 2024-11-08 14:28:47
On Wed, Oct 30, 2024 at 04:37:37PM +0000, Lorenzo Stoakes wrote:
On Mon, Oct 28, 2024 at 04:06:07PM +0000, Lorenzo Stoakes wrote:
quoted
I guess I'll try to adapt that and respin a v7 when I get a chance.
Hm looking at this draft patch, it seems like a total rework of pidfd's
across the board right (now all pidfd's will need to be converted to
pid_fd)? Correct me if I'm wrong.
If only for the signal case, it seems like overkill to define a whole
pid_fd and to use this CLASS() wrapper just for this one instance.
If the intent is to convert _all_ pidfd's to use this type, it feels really
out of scope for this series and I think we'd probably instead want to go
off and do that as a separate series and put this on hold until that is
done.
If instead you mean that we ought to do something like this just for the
signal case, it feels like it'd be quite a bit of extra abstraction just
used in this one case but nowhere else, I think if you did an abstraction
like this it would _have_ to be across the board right?
I agree that the issue is with this one signal case that pins only the fd
(rather than this pid) where this 'pinning' doesn't _necessary_ mess around
with reference counts.
So we definitely must address this, but the issue you had with the first
approach was that I think (correct me if I'm wrong) I was passing a pointer
to a struct fd which is not permitted right?
Could we pass the struct fd by value to avoid this? I think we'd have to
unfortunately special-case this and probably duplicate some code which is a
pity as I liked the idea of abstracting everything to one place, but we can
obviously do that.
So I guess to TL;DR it, the options are:
1. Implement pid_fd everywhere, in which case I will leave off on
this series and I guess, if I have time I could look at trying to
implement that or perhaps you'd prefer to?
2. We are good for the sake of this series to special-case a pidfd_to_pid()
implementation (used only by the pidfd_send_signal() syscall)
3. Something else, or I am misunderstanding your point :)
Let me know how you want me to proceed on this as we're at v6 already and I
want to be _really_ sure I'm doing what you want here.
Thanks!
Hi Christian,
Just a gentle nudge on this - as I need some guidance in order to know how
to move the series forwards.
Obviously no rush if your workload is high at the moment as this is pretty
low priority, but just in case you missed it :)
Thanks, Lorenzo
From: Lorenzo Stoakes <hidden> Date: 2024-12-02 10:52:40
On Fri, Nov 08, 2024 at 02:28:14PM +0000, Lorenzo Stoakes wrote:
On Wed, Oct 30, 2024 at 04:37:37PM +0000, Lorenzo Stoakes wrote:
quoted
On Mon, Oct 28, 2024 at 04:06:07PM +0000, Lorenzo Stoakes wrote:
quoted
I guess I'll try to adapt that and respin a v7 when I get a chance.
Hm looking at this draft patch, it seems like a total rework of pidfd's
across the board right (now all pidfd's will need to be converted to
pid_fd)? Correct me if I'm wrong.
If only for the signal case, it seems like overkill to define a whole
pid_fd and to use this CLASS() wrapper just for this one instance.
If the intent is to convert _all_ pidfd's to use this type, it feels really
out of scope for this series and I think we'd probably instead want to go
off and do that as a separate series and put this on hold until that is
done.
If instead you mean that we ought to do something like this just for the
signal case, it feels like it'd be quite a bit of extra abstraction just
used in this one case but nowhere else, I think if you did an abstraction
like this it would _have_ to be across the board right?
I agree that the issue is with this one signal case that pins only the fd
(rather than this pid) where this 'pinning' doesn't _necessary_ mess around
with reference counts.
So we definitely must address this, but the issue you had with the first
approach was that I think (correct me if I'm wrong) I was passing a pointer
to a struct fd which is not permitted right?
Could we pass the struct fd by value to avoid this? I think we'd have to
unfortunately special-case this and probably duplicate some code which is a
pity as I liked the idea of abstracting everything to one place, but we can
obviously do that.
So I guess to TL;DR it, the options are:
1. Implement pid_fd everywhere, in which case I will leave off on
this series and I guess, if I have time I could look at trying to
implement that or perhaps you'd prefer to?
2. We are good for the sake of this series to special-case a pidfd_to_pid()
implementation (used only by the pidfd_send_signal() syscall)
3. Something else, or I am misunderstanding your point :)
Let me know how you want me to proceed on this as we're at v6 already and I
want to be _really_ sure I'm doing what you want here.
Thanks!
Hi Christian,
Just a gentle nudge on this - as I need some guidance in order to know how
to move the series forwards.
Obviously no rush if your workload is high at the moment as this is pretty
low priority, but just in case you missed it :)
Thanks, Lorenzo
Hi Christian,
Just a ping on this now we're past the merge window and it's been over a
month.
It'd be good to at least get a polite ack to indicate you're aware even if
you don't have the time to respond right now.
If you'd prefer this series not to go ahead just let me know, but
unfortunately I really require your input to know how to move forward
otherwise I risk doing work that you might then reject.
Thanks, Lorenzo
From: Christian Brauner <brauner@kernel.org> Date: 2024-12-02 14:31:23
On Wed, Oct 30, 2024 at 04:37:37PM +0000, Lorenzo Stoakes wrote:
On Mon, Oct 28, 2024 at 04:06:07PM +0000, Lorenzo Stoakes wrote:
quoted
I guess I'll try to adapt that and respin a v7 when I get a chance.
Hm looking at this draft patch, it seems like a total rework of pidfd's
across the board right (now all pidfd's will need to be converted to
pid_fd)? Correct me if I'm wrong.
If only for the signal case, it seems like overkill to define a whole
pid_fd and to use this CLASS() wrapper just for this one instance.
If the intent is to convert _all_ pidfd's to use this type, it feels really
out of scope for this series and I think we'd probably instead want to go
off and do that as a separate series and put this on hold until that is
done.
If instead you mean that we ought to do something like this just for the
signal case, it feels like it'd be quite a bit of extra abstraction just
used in this one case but nowhere else, I think if you did an abstraction
like this it would _have_ to be across the board right?
I agree that the issue is with this one signal case that pins only the fd
(rather than this pid) where this 'pinning' doesn't _necessary_ mess around
with reference counts.
So we definitely must address this, but the issue you had with the first
approach was that I think (correct me if I'm wrong) I was passing a pointer
to a struct fd which is not permitted right?
Could we pass the struct fd by value to avoid this? I think we'd have to
unfortunately special-case this and probably duplicate some code which is a
pity as I liked the idea of abstracting everything to one place, but we can
obviously do that.
So I guess to TL;DR it, the options are:
1. Implement pid_fd everywhere, in which case I will leave off on
this series and I guess, if I have time I could look at trying to
implement that or perhaps you'd prefer to?
2. We are good for the sake of this series to special-case a pidfd_to_pid()
implementation (used only by the pidfd_send_signal() syscall)
3. Something else, or I am misunderstanding your point :)
Let me know how you want me to proceed on this as we're at v6 already and I
want to be _really_ sure I'm doing what you want here.
I don't think we get away with abstracting it in one place without this
ending up a pretty janky api. I need to go back and think about calling
conventions for all this stuff. For now I think I'm fine with something
like the below that abstracts the api to handle mm/ cleanly and then a
special-case for pidfd_send_signal():
@@ -564,15 +564,29 @@ struct pid *pidfd_get_pid(unsigned int fd, unsigned int *flags)*/structtask_struct*pidfd_get_task(intpidfd,unsignedint*flags){-unsignedintf_flags;+unsignedintf_flags=0;structpid*pid;structtask_struct*task;+enumpid_typetype;-pid=pidfd_get_pid(pidfd,&f_flags);-if(IS_ERR(pid))-returnERR_CAST(pid);+switch(pidfd){+casePIDFD_SELF_THREAD:+type=PIDTYPE_PID;+pid=get_task_pid(current,type);+break;+casePIDFD_SELF_THREAD_GROUP:+type=PIDTYPE_TGID;+pid=get_task_pid(current,type);+break;+default:+pid=pidfd_get_pid(pidfd,&f_flags);+if(IS_ERR(pid))+returnERR_CAST(pid);+type=PIDTYPE_TGID;+break;+}-task=get_pid_task(pid,PIDTYPE_TGID);+task=get_pid_task(pid,type);put_pid(pid);if(!task)returnERR_PTR(-ESRCH);
That would get you support for PIDFD_SELF_THREAD and
PIDFD_SELF_THREAD_GROUP for process_madvise() and process_mrelease().
And for pidfd_send_signal() we could just open code this for now:
@@ -3990,6 +3990,45 @@ static struct pid *pidfd_to_pid(const struct file *file)(PIDFD_SIGNAL_THREAD|PIDFD_SIGNAL_THREAD_GROUP|\PIDFD_SIGNAL_PROCESS_GROUP)+staticintdo_pidfd_send_signal(structpid*pid,intsig,enumpid_typetype,+siginfo_t__user*info,unsignedintflags)+{+kernel_siginfo_tkinfo;++switch(flags){+casePIDFD_SIGNAL_THREAD:+type=PIDTYPE_PID;+break;+casePIDFD_SIGNAL_THREAD_GROUP:+type=PIDTYPE_TGID;+break;+casePIDFD_SIGNAL_PROCESS_GROUP:+type=PIDTYPE_PGID;+break;+}++if(info){+intret=copy_siginfo_from_user_any(&kinfo,info);+if(unlikely(ret))+returnret;++if(unlikely(sig!=kinfo.si_signo))+return-EINVAL;++/* Only allow sending arbitrary signals to yourself. */+if((task_pid(current)!=pid||type>PIDTYPE_TGID)&&+(kinfo.si_code>=0||kinfo.si_code==SI_TKILL))+return-EPERM;+}else{+prepare_kill_siginfo(sig,&kinfo,type);+}++if(type==PIDTYPE_PGID)+returnkill_pgrp_info(sig,&kinfo,pid);++returnkill_pid_info_type(sig,&kinfo,pid,type);+}+/***sys_pidfd_send_signal-Signalaprocessthroughapidfd*@pidfd:filedescriptoroftheprocess
@@ -4009,7 +4048,6 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,{intret;structpid*pid;-kernel_siginfo_tkinfo;enumpid_typetype;/* Enforce flags be set to 0 until we add an extension. */
@@ -4021,56 +4059,39 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,return-EINVAL;CLASS(fd,f)(pidfd);-if(fd_empty(f))-return-EBADF;-/* Is this a pidfd? */-pid=pidfd_to_pid(fd_file(f));-if(IS_ERR(pid))-returnPTR_ERR(pid);+switch(pidfd){+casePIDFD_SELF_THREAD:+pid=get_task_pid(current,PIDTYPE_PID);+type=PIDTYPE_PID;+break;+casePIDFD_SELF_THREAD_GROUP:+pid=get_task_pid(current,PIDTYPE_TGID);+type=PIDTYPE_TGID;+break;+default:+if(fd_empty(f))+return-EBADF;-if(!access_pidfd_pidns(pid))-return-EINVAL;+/* Is this a pidfd? */+pid=pidfd_to_pid(fd_file(f));+if(IS_ERR(pid))+returnPTR_ERR(pid);-switch(flags){-case0:+if(!access_pidfd_pidns(pid))+return-EINVAL;/* Infer scope from the type of pidfd. */if(fd_file(f)->f_flags&PIDFD_THREAD)type=PIDTYPE_PID;elsetype=PIDTYPE_TGID;break;-casePIDFD_SIGNAL_THREAD:-type=PIDTYPE_PID;-break;-casePIDFD_SIGNAL_THREAD_GROUP:-type=PIDTYPE_TGID;-break;-casePIDFD_SIGNAL_PROCESS_GROUP:-type=PIDTYPE_PGID;-break;}-if(info){-ret=copy_siginfo_from_user_any(&kinfo,info);-if(unlikely(ret))-returnret;--if(unlikely(sig!=kinfo.si_signo))-return-EINVAL;--/* Only allow sending arbitrary signals to yourself. */-if((task_pid(current)!=pid||type>PIDTYPE_TGID)&&-(kinfo.si_code>=0||kinfo.si_code==SI_TKILL))-return-EPERM;-}else{-prepare_kill_siginfo(sig,&kinfo,type);-}--if(type==PIDTYPE_PGID)-returnkill_pgrp_info(sig,&kinfo,pid);-else-returnkill_pid_info_type(sig,&kinfo,pid,type);+ret=do_pidfd_send_signal(pid,sig,type,info,flags);+if(fd_empty(f))+put_pid(pid);+returnret;}staticint
On Mon, Dec 02, 2024 at 10:52:13AM +0000, Lorenzo Stoakes wrote:
On Fri, Nov 08, 2024 at 02:28:14PM +0000, Lorenzo Stoakes wrote:
quoted
On Wed, Oct 30, 2024 at 04:37:37PM +0000, Lorenzo Stoakes wrote:
quoted
On Mon, Oct 28, 2024 at 04:06:07PM +0000, Lorenzo Stoakes wrote:
quoted
I guess I'll try to adapt that and respin a v7 when I get a chance.
Hm looking at this draft patch, it seems like a total rework of pidfd's
across the board right (now all pidfd's will need to be converted to
pid_fd)? Correct me if I'm wrong.
If only for the signal case, it seems like overkill to define a whole
pid_fd and to use this CLASS() wrapper just for this one instance.
If the intent is to convert _all_ pidfd's to use this type, it feels really
out of scope for this series and I think we'd probably instead want to go
off and do that as a separate series and put this on hold until that is
done.
If instead you mean that we ought to do something like this just for the
signal case, it feels like it'd be quite a bit of extra abstraction just
used in this one case but nowhere else, I think if you did an abstraction
like this it would _have_ to be across the board right?
I agree that the issue is with this one signal case that pins only the fd
(rather than this pid) where this 'pinning' doesn't _necessary_ mess around
with reference counts.
So we definitely must address this, but the issue you had with the first
approach was that I think (correct me if I'm wrong) I was passing a pointer
to a struct fd which is not permitted right?
Could we pass the struct fd by value to avoid this? I think we'd have to
unfortunately special-case this and probably duplicate some code which is a
pity as I liked the idea of abstracting everything to one place, but we can
obviously do that.
So I guess to TL;DR it, the options are:
1. Implement pid_fd everywhere, in which case I will leave off on
this series and I guess, if I have time I could look at trying to
implement that or perhaps you'd prefer to?
2. We are good for the sake of this series to special-case a pidfd_to_pid()
implementation (used only by the pidfd_send_signal() syscall)
3. Something else, or I am misunderstanding your point :)
Let me know how you want me to proceed on this as we're at v6 already and I
want to be _really_ sure I'm doing what you want here.
Thanks!
Hi Christian,
Just a gentle nudge on this - as I need some guidance in order to know how
to move the series forwards.
Obviously no rush if your workload is high at the moment as this is pretty
low priority, but just in case you missed it :)
Thanks, Lorenzo
Hi Christian,
Just a ping on this now we're past the merge window and it's been over a
month.
It'd be good to at least get a polite ack to indicate you're aware even if
you don't have the time to respond right now.
If you'd prefer this series not to go ahead just let me know, but
unfortunately I really require your input to know how to move forward
otherwise I risk doing work that you might then reject.
From: Lorenzo Stoakes <hidden> Date: 2025-01-07 08:34:05
On Mon, Jan 06, 2025 at 01:03:31PM -0800, Shakeel Butt wrote:
Hey Lorenzo & Christian, what's the latest here? I see Christian has
code suggestions at [1] which just needs to be addressed. Any thing
else? I am hoping we can get this merged in the coming open window.
This is on my radar don't worry :) I will get to it as soon as I can.
Cheers, Lorenzo