All Virtuozzo development lists (kernel + QEMU)
 help / color / mirror / Atom feed
From: Konstantin Khorenko <khorenko@virtuozzo.com>
To: Vasileios Almpanis <vasileios.almpanis@virtuozzo.com>
Cc: OpenVZ devel <devel@openvz.org>
Subject: Re: [Devel] [PATCH RHEL10 COMMIT] proc connector: pin task VE for the exit event notification
Date: Wed, 26 Aug 2026 15:09:13 +0200	[thread overview]
Message-ID: <202608261309.67QD9DaH890882@f0.sw.ru> (raw)
In-Reply-To: <20260825-connectors-v3-4-7b26773876a0@virtuozzo.com>

The commit is pushed to "branch-rh10-6.12.0-211.39.1.16.x.vz10-ovz" and will appear at git@bitbucket.org:openvz/vzkernel.git
after rh10-6.12.0-211.39.1.16.10.vz10
------>
commit 5d93a033f4ceafc086a81687ac873c236e2f2d9e
Author: Vasileios Almpanis <vasileios.almpanis@virtuozzo.com>
Date:   Tue Aug 25 16:19:54 2026 +0000

    proc connector: pin task VE for the exit event notification
    
    The exit event is reported after exit_notify(), so the parent might have
    been woken up and reaped the exiting task via wait() -> release_task()
    -> exit_ve_namespace(), which resets tsk->task_ve to ve0. If that wins
    the race against the exiting task then the event will only be delivered
    to the host VE listeners and the in-VE listeners will be skipped. For a
    task inside a container this means the listener never receives an exit
    event.
    
    The issue is caught by the LTP suite_kernel_misc.exec.cn_pec_sh test:
    pec_listener terminates upon receiving the exit event of the pid given
    via -p. When the lost exit event is a child's one, the test fails:
    
      cn_pec 3 TFAIL: Event was not detected by the event listener:
                      exit pid: 58388 exit_code: 0 exit_signal: 17
    
    and when it is the event generator's own exit event, the listener
    polls the netlink socket forever and the test hangs until the LTP
    timeout kills it (~8h on coverage kernels):
    
    22:51:37 cn_pec 2 TINFO: Testing exec event (nevents=10)
    07:11:37 Test timed out, sending SIGTERM!
    
    The race was captured using kprobes on the connector send path:
      p:cnp/pexit proc_exit_connector task=$arg1:x64
      p:cnp/vexit exit_ve_namespace task=$arg1:x64
      p:cnp/pevcve proc_event_connector_ve what=$arg3:u32
      r:cnp/cnsend cn_netlink_send_mult_ve ret=$retval:s64
    
    A normal exit looks like:
      pexit -> pevcve(ve) -> cnsend ret=0 -> pevcve(ve0)
    
    The lost event (task 0xffff89a506d73980 is the exiting child, reaped by
    its parent pid 465820 in between):
    
     465831 [001] pexit: (proc_exit_connector) task=0xffff89a506d73980
     465820 [002] vexit: (exit_ve_namespace) task=0xffff89a506d73980
     465831 [001] pevcve: (proc_event_connector_ve) what=2147483648
    
    Only one proc_event_connector_ve() call fires (ve0, no listeners) and
    cn_netlink_send_mult_ve() is never reached: the event is dropped.
    
    This is the same race window that commit c565cc211694 ("proc
    connector: report proper pid/tgid of an exited process") closed for
    the task pid/tgid, but nothing pins the VE.
    
    Reproducer (fails within ~50 iterations in a CT on a coverage kernel):
    
      cd /opt/ltp/testcases/bin/
      export PATH=$PATH:/opt/ltp/testcases/bin
      for i in $(seq 1 1024); do cn_pec.sh >/dev/null 2>&1 || break; done
    
    Solve this the same way. Pin the VE in do_exit() before exit_notify()
    is called and use it in proc_exit_connector() instead of re-reading
    task->task_ve.
    
    https://virtuozzo.atlassian.net/browse/VSTOR-140421
    Fixes: 95fa2f096b72 ("ve: Introduce VE namespace")
    Feature: ve: ve generic structures
    Signed-off-by: Vasileios Almpanis <vasileios.almpanis@virtuozzo.com>
    Reviewed-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
 drivers/connector/cn_proc.c | 10 ++++++++--
 include/linux/cn_proc.h     |  8 ++++++--
 kernel/exit.c               |  5 ++++-
 3 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 6084308085489..8d8c538cc3cd4 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -401,9 +401,15 @@ static bool fill_exit_event(struct proc_event *ev, struct ve_struct *ve,
 	return true;
 }
 
-void proc_exit_connector(struct task_struct *task, struct pids *pids)
+void proc_exit_connector(struct task_struct *task, struct pids *pids,
+			 struct ve_struct *ve)
 {
-	proc_event_connector(task, PROC_EVENT_EXIT, (long)pids, fill_exit_event);
+	if (!ve_is_super(ve))
+		proc_event_connector_ve(task, ve, PROC_EVENT_EXIT, (long)pids,
+					fill_exit_event);
+
+	proc_event_connector_ve(task, get_ve0(), PROC_EVENT_EXIT, (long)pids,
+				fill_exit_event);
 }
 
 /*
diff --git a/include/linux/cn_proc.h b/include/linux/cn_proc.h
index 9701c13d82dfc..aa606192b5c2e 100644
--- a/include/linux/cn_proc.h
+++ b/include/linux/cn_proc.h
@@ -19,6 +19,8 @@
 
 #include <uapi/linux/cn_proc.h>
 
+struct ve_struct;
+
 /*
  * The struct is used solely for pinning task pids for proc connector
  * notification on process exit.
@@ -36,7 +38,8 @@ void proc_sid_connector(struct task_struct *task);
 void proc_ptrace_connector(struct task_struct *task, int which_id);
 void proc_comm_connector(struct task_struct *task);
 void proc_coredump_connector(struct task_struct *task);
-void proc_exit_connector(struct task_struct *task, struct pids *pids);
+void proc_exit_connector(struct task_struct *task, struct pids *pids,
+			 struct ve_struct *ve);
 #else
 static inline void proc_fork_connector(struct task_struct *task)
 {}
@@ -61,7 +64,8 @@ static inline void proc_ptrace_connector(struct task_struct *task,
 static inline void proc_coredump_connector(struct task_struct *task)
 {}
 
-static inline void proc_exit_connector(struct task_struct *task, struct pids *pids)
+static inline void proc_exit_connector(struct task_struct *task, struct pids *pids,
+				       struct ve_struct *ve)
 {}
 #endif	/* CONFIG_PROC_EVENTS */
 #endif	/* CN_PROC_H */
diff --git a/kernel/exit.c b/kernel/exit.c
index 448a734270a7f..94d9bddae2b86 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -936,6 +936,7 @@ void __noreturn do_exit(long code)
 	struct task_struct *tsk = current;
 	int group_dead;
 	struct pids pids;
+	struct ve_struct *ve;
 
 	WARN_ON(irqs_disabled());
 
@@ -1021,8 +1022,10 @@ void __noreturn do_exit(long code)
 	exit_tasks_rcu_start();
 	pids.pid = get_pid(task_pid(tsk));
 	pids.tgid = get_pid(task_tgid(tsk));
+	ve = get_task_ve(tsk);
 	exit_notify(tsk, group_dead);
-	proc_exit_connector(tsk, &pids);
+	proc_exit_connector(tsk, &pids, ve);
+	put_ve(ve);
 	put_pid(pids.tgid);
 	put_pid(pids.pid);
 	mpol_put_task_policy(tsk);
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

      reply	other threads:[~2026-08-26 13:10 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-25 16:19 [Devel] [PATCH VZ10 v3 0/4] connector: do not lose exit events for in-CT listeners Vasileios Almpanis
2026-08-25 16:19 ` [Devel] [PATCH VZ10 v3 1/4] connector: annotate ve->cn with __rcu Vasileios Almpanis
2026-08-26 13:09   ` [Devel] [PATCH RHEL10 COMMIT] " Konstantin Khorenko
2026-08-25 16:19 ` [Devel] [PATCH VZ10 v3 2/4] connector: free the per-VE connector state after an RCU grace period Vasileios Almpanis
2026-08-26 13:09   ` [Devel] [PATCH RHEL10 COMMIT] " Konstantin Khorenko
2026-08-25 16:19 ` [Devel] [PATCH VZ10 v3 3/4] connector: deliver per-VE proc events under an RCU read lock Vasileios Almpanis
2026-08-26 13:09   ` [Devel] [PATCH RHEL10 COMMIT] " Konstantin Khorenko
2026-08-25 16:19 ` [Devel] [PATCH VZ10 v3 4/4] proc connector: pin task VE for the exit event notification Vasileios Almpanis
2026-08-26 13:09   ` Konstantin Khorenko [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=202608261309.67QD9DaH890882@f0.sw.ru \
    --to=khorenko@virtuozzo.com \
    --cc=devel@openvz.org \
    --cc=vasileios.almpanis@virtuozzo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.