* [Devel] [PATCH hci-8.1] ve/vtty: fix console attach failing with EBUSY while the CT closes the tty
@ 2026-10-29 22:35 Denis V. Lunev
2026-10-29 22:38 ` no-reply
` (3 more replies)
0 siblings, 4 replies; 13+ messages in thread
From: Denis V. Lunev @ 2026-10-29 22:35 UTC (permalink / raw)
To: eva.kurchatova, vasileios.almpanis; +Cc: devel
From: Denis V. Lunev <den@openvz.org>
Since commit 23abb203a41a ("ve/vtty: fix use-after-free on concurrent
tty close and reopen") vtty_open_master() refuses a pair whose slave
count has dropped to zero: the last CT-side close has committed to the
final close, and the pair stays in the vtty map only until
release_tty() runs. The refusal is -EBUSY, the errno which already
means a console is attached, so userspace cannot tell a pair that is
about to go from one that is taken, and vzctl gives up:
Error opening CT tty: Device or resource busy
The window opens whenever the last process in the CT closes its tty:
getty respawn, login with autologin, SAK. "vzctl console" run right
after "vzctl start --wait" hits it.
Return -EAGAIN for the dying pair. Nothing else on the
VE_CONFIGURE_OPEN_TTY path returns -EAGAIN, so it can only mean "try
again", which is what vzctl will do. An in-CT open of such a pair gets
-EAGAIN from tty_reopen() and tty_open() retries it the same way.
Retrying inside vtty_open_master() instead would have to drop tty_mutex
for release_tty() to progress, and the global vtty context with it.
Let ve_vtty_stress accept -EAGAIN as an expected open error.
Fixes: 23abb203a41a ("ve/vtty: fix use-after-free on concurrent tty close and reopen")
https://virtuozzo.atlassian.net/browse/VSTOR-152365
Feature: tty: virtual Container console
Signed-off-by: Denis V. Lunev <den@openvz.org>
---
vzctl needs a matching change, "vzctl console: retry opening a CT tty
the CT is still closing", which goes to the vzctl repository. Without
it vzctl fails the same race with "Resource temporarily unavailable"
instead of "Device or resource busy", so the two should land together.
Tested on sqvm4-1002, hci-8.1 6.12.0-211.52.1.22.12 with this patch:
- a host loop opening and closing the console via VE_CONFIGURE_OPEN_TTY
while a loop inside the CT opens and closes the same tty: about two
thirds of the host opens fail with EBUSY before the patch, none
after, they get EAGAIN instead;
- vzctl console with the vzctl change under the same race: every
attach succeeds, after at most four retries;
- vzctl test_vzctl_console.py passes, including the "tty already in
use" case, which still gets EBUSY;
- ve_vtty_stress passes; without the selftest hunk it bails out on the
first EAGAIN;
- nothing in dmesg.
drivers/tty/pty.c | 5 +++--
tools/testing/selftests/ve/ve_vtty_stress.c | 2 +-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 14d46bb9c293..6f6dabba96e2 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -1100,14 +1100,15 @@ int vtty_open_master(envid_t veid, int idx)
* user is gone and tty_release() has already committed to the final
* close, release_tty() is only waiting for tty_mutex to free it.
* Never hand out a reference to a tty which is about to be freed,
- * report -EBUSY so that the next attempt allocates a fresh pair.
+ * report -EAGAIN so that the caller retries and allocates a fresh
+ * pair. -EBUSY above means a console is really attached.
*
* A pair we've just created above is exempt: it is not reachable by
* anyone else yet and its zero count is merely the initial state,
* vtty_install() gives its reference away to the master peer below.
*/
if (!created && slave->count == 0) {
- ret = -EBUSY;
+ ret = -EAGAIN;
goto err_unlock;
}
diff --git a/tools/testing/selftests/ve/ve_vtty_stress.c b/tools/testing/selftests/ve/ve_vtty_stress.c
index f4bdd81133b8..d8d92ae54718 100644
--- a/tools/testing/selftests/ve/ve_vtty_stress.c
+++ b/tools/testing/selftests/ve/ve_vtty_stress.c
@@ -44,7 +44,7 @@
*/
static bool expected_errno(int err)
{
- return err == EBUSY || err == EIO || err == ENXIO;
+ return err == EAGAIN || err == EBUSY || err == EIO || err == ENXIO;
}
/* A runner timeout must still reach the cleanup */
--
2.53.0
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Devel] [PATCH hci-8.1] ve/vtty: fix console attach failing with EBUSY while the CT closes the tty
2026-10-29 22:35 [Devel] [PATCH hci-8.1] ve/vtty: fix console attach failing with EBUSY while the CT closes the tty Denis V. Lunev
@ 2026-10-29 22:38 ` no-reply
2026-11-02 10:41 ` Konstantin Khorenko
` (2 subsequent siblings)
3 siblings, 0 replies; 13+ messages in thread
From: no-reply @ 2026-10-29 22:38 UTC (permalink / raw)
To: vasileios.almpanis, Denis V. Lunev, eva.kurchatova; +Cc: devel
> From: Denis V. Lunev <den@openvz.org>
>
> Since commit 23abb203a41a ("ve/vtty: fix use-after-free on concurrent
> tty close and reopen") vtty_open_master() refuses a pair whose slave
> count has dropped to zero: the last CT-side close has committed to the
> final close, and the pair stays in the vtty map only until
> release_tty() runs. The refusal is -EBUSY, the errno which already
> means a console is attached, so userspace cannot tell a pair that is
> about to go from one that is taken, and vzctl gives up:
>
> Error opening CT tty: Device or resource busy
>
> The window opens whenever the last process in the CT closes its tty:
> getty respawn, login with autologin, SAK. "vzctl console" run right
> after "vzctl start --wait" hits it.
>
> Return -EAGAIN for the dying pair. Nothing else on the
> VE_CONFIGURE_OPEN_TTY path returns -EAGAIN, so it can only mean "try
> again", which is what vzctl will do. An in-CT open of such a pair gets
> -EAGAIN from tty_reopen() and tty_open() retries it the same way.
> Retrying inside vtty_open_master() instead would have to drop tty_mutex
> for release_tty() to progress, and the global vtty context with it.
>
> Let ve_vtty_stress accept -EAGAIN as an expected open error.
>
> Fixes: 23abb203a41a ("ve/vtty: fix use-after-free on concurrent tty close and reopen")
>
> https://virtuozzo.atlassian.net/browse/VSTOR-152365
> Feature: tty: virtual Container console
> Signed-off-by: Denis V. Lunev <den@openvz.org>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261029223502.1437160-1-den@openvz.org?part=1
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Devel] [PATCH hci-8.1] ve/vtty: fix console attach failing with EBUSY while the CT closes the tty
2026-10-29 22:35 [Devel] [PATCH hci-8.1] ve/vtty: fix console attach failing with EBUSY while the CT closes the tty Denis V. Lunev
2026-10-29 22:38 ` no-reply
@ 2026-11-02 10:41 ` Konstantin Khorenko
2026-11-02 10:42 ` Konstantin Khorenko
2026-11-02 15:17 ` Konstantin Khorenko
3 siblings, 0 replies; 13+ messages in thread
From: Konstantin Khorenko @ 2026-11-02 10:41 UTC (permalink / raw)
To: Denis V. Lunev, eva.kurchatova, vasileios.almpanis; +Cc: devel
committing without review
--
Best regards,
Konstantin Khorenko,
Virtuozzo Linux Kernel Team
On 10/29/26 23:35, Denis V. Lunev wrote:
> From: Denis V. Lunev <den@openvz.org>
>
> Since commit 23abb203a41a ("ve/vtty: fix use-after-free on concurrent
> tty close and reopen") vtty_open_master() refuses a pair whose slave
> count has dropped to zero: the last CT-side close has committed to the
> final close, and the pair stays in the vtty map only until
> release_tty() runs. The refusal is -EBUSY, the errno which already
> means a console is attached, so userspace cannot tell a pair that is
> about to go from one that is taken, and vzctl gives up:
>
> Error opening CT tty: Device or resource busy
>
> The window opens whenever the last process in the CT closes its tty:
> getty respawn, login with autologin, SAK. "vzctl console" run right
> after "vzctl start --wait" hits it.
>
> Return -EAGAIN for the dying pair. Nothing else on the
> VE_CONFIGURE_OPEN_TTY path returns -EAGAIN, so it can only mean "try
> again", which is what vzctl will do. An in-CT open of such a pair gets
> -EAGAIN from tty_reopen() and tty_open() retries it the same way.
> Retrying inside vtty_open_master() instead would have to drop tty_mutex
> for release_tty() to progress, and the global vtty context with it.
>
> Let ve_vtty_stress accept -EAGAIN as an expected open error.
>
> Fixes: 23abb203a41a ("ve/vtty: fix use-after-free on concurrent tty close and reopen")
>
> https://virtuozzo.atlassian.net/browse/VSTOR-152365
> Feature: tty: virtual Container console
> Signed-off-by: Denis V. Lunev <den@openvz.org>
> ---
> vzctl needs a matching change, "vzctl console: retry opening a CT tty
> the CT is still closing", which goes to the vzctl repository. Without
> it vzctl fails the same race with "Resource temporarily unavailable"
> instead of "Device or resource busy", so the two should land together.
>
> Tested on sqvm4-1002, hci-8.1 6.12.0-211.52.1.22.12 with this patch:
> - a host loop opening and closing the console via VE_CONFIGURE_OPEN_TTY
> while a loop inside the CT opens and closes the same tty: about two
> thirds of the host opens fail with EBUSY before the patch, none
> after, they get EAGAIN instead;
> - vzctl console with the vzctl change under the same race: every
> attach succeeds, after at most four retries;
> - vzctl test_vzctl_console.py passes, including the "tty already in
> use" case, which still gets EBUSY;
> - ve_vtty_stress passes; without the selftest hunk it bails out on the
> first EAGAIN;
> - nothing in dmesg.
>
> drivers/tty/pty.c | 5 +++--
> tools/testing/selftests/ve/ve_vtty_stress.c | 2 +-
> 2 files changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
> index 14d46bb9c293..6f6dabba96e2 100644
> --- a/drivers/tty/pty.c
> +++ b/drivers/tty/pty.c
> @@ -1100,14 +1100,15 @@ int vtty_open_master(envid_t veid, int idx)
> * user is gone and tty_release() has already committed to the final
> * close, release_tty() is only waiting for tty_mutex to free it.
> * Never hand out a reference to a tty which is about to be freed,
> - * report -EBUSY so that the next attempt allocates a fresh pair.
> + * report -EAGAIN so that the caller retries and allocates a fresh
> + * pair. -EBUSY above means a console is really attached.
> *
> * A pair we've just created above is exempt: it is not reachable by
> * anyone else yet and its zero count is merely the initial state,
> * vtty_install() gives its reference away to the master peer below.
> */
> if (!created && slave->count == 0) {
> - ret = -EBUSY;
> + ret = -EAGAIN;
> goto err_unlock;
> }
>
> diff --git a/tools/testing/selftests/ve/ve_vtty_stress.c b/tools/testing/selftests/ve/ve_vtty_stress.c
> index f4bdd81133b8..d8d92ae54718 100644
> --- a/tools/testing/selftests/ve/ve_vtty_stress.c
> +++ b/tools/testing/selftests/ve/ve_vtty_stress.c
> @@ -44,7 +44,7 @@
> */
> static bool expected_errno(int err)
> {
> - return err == EBUSY || err == EIO || err == ENXIO;
> + return err == EAGAIN || err == EBUSY || err == EIO || err == ENXIO;
> }
>
> /* A runner timeout must still reach the cleanup */
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Devel] [PATCH hci-8.1] ve/vtty: fix console attach failing with EBUSY while the CT closes the tty
2026-10-29 22:35 [Devel] [PATCH hci-8.1] ve/vtty: fix console attach failing with EBUSY while the CT closes the tty Denis V. Lunev
2026-10-29 22:38 ` no-reply
2026-11-02 10:41 ` Konstantin Khorenko
@ 2026-11-02 10:42 ` Konstantin Khorenko
2026-11-02 15:17 ` Konstantin Khorenko
3 siblings, 0 replies; 13+ messages in thread
From: Konstantin Khorenko @ 2026-11-02 10:42 UTC (permalink / raw)
To: eva.kurchatova, vasileios.almpanis, Denis V. Lunev; +Cc: devel
On Thu, 29 Oct 2026 23:35:02 +0100, Denis V. Lunev wrote:
> ve/vtty: fix console attach failing with EBUSY while the CT closes the tty
Applied to branch-rh10-6.12.0-211.52.1.22.x.vz10-ovz, will be released in rh10-6.12.0-211.52.1.22.15.vz10, thanks!
[1/1] ve/vtty: fix console attach failing with EBUSY while the CT closes the tty
https://bitbucket.org/virtuozzocore/vzkernel.vzs/commits/17cb7be7bfa3
--
Konstantin Khorenko,
Virtuozzo Linux Kernel Team
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Devel] [PATCH hci-8.1] ve/vtty: fix console attach failing with EBUSY while the CT closes the tty
2026-10-29 22:35 [Devel] [PATCH hci-8.1] ve/vtty: fix console attach failing with EBUSY while the CT closes the tty Denis V. Lunev
` (2 preceding siblings ...)
2026-11-02 10:42 ` Konstantin Khorenko
@ 2026-11-02 15:17 ` Konstantin Khorenko
2026-11-02 17:15 ` [Devel] [PATCH hci-8.1 0/2] ve/vtty: wait for a closing CT tty in the kernel, drop the EAGAIN return Denis V. Lunev
3 siblings, 1 reply; 13+ messages in thread
From: Konstantin Khorenko @ 2026-11-02 15:17 UTC (permalink / raw)
To: Denis V. Lunev; +Cc: devel
Hi Denis,
> Return -EAGAIN for the dying pair. Nothing else on the
> VE_CONFIGURE_OPEN_TTY path returns -EAGAIN, so it can only mean "try
> again", which is what vzctl will do.
Agreed, together with your vzctl change ("vzctl console: retry opening
a CT tty the CT is still closing") the bug is fixed. But only for the new
vzctl: every vzctl already installed tries the ioctl once and now fails
with "Resource temporarily unavailable" instead of "Device or resource
busy".
> An in-CT open of such a pair gets
> -EAGAIN from tty_reopen() and tty_open() retries it the same way.
> Retrying inside vtty_open_master() instead would have to drop tty_mutex
> for release_tty() to progress, and the global vtty context with it.
We can fix it for old and new vzctl alike by doing what mainline did
for the same window in 7f22f6c935cda ("tty: Retry failed reopen if tty
teardown in-progress"), retry in the kernel:
if (IS_ERR(tty)) {
tty_free_file(filp);
retval = PTR_ERR(tty);
if (retval != -EAGAIN || signal_pending(current))
return retval;
schedule();
goto retry_open;
}
Dropping tty_mutex and the vtty context is not a problem: err_unlock
already does exactly that. So in vtty_open_master():
retry:
mutex_lock(&tty_mutex);
vtty_set_context(veid);
...
if (!created && slave->count == 0) {
tty_unlock(slave);
vtty_drop_context();
mutex_unlock(&tty_mutex);
if (signal_pending(current)) {
ret = -EAGAIN;
goto err_free_file; /* tty_free_file() onwards */
}
schedule();
goto retry;
}
The fd and the file stay allocated across the loop, nothing else
changes.
The loop always ends: we get there only with master->count == 0 and
slave->count == 0, i.e. tty_release() has decided on the final close,
so the closer is already in tty_release_struct() on its way to
release_tty() -> vtty_shutdown() -> vtty_map_clear(). Once we drop
tty_mutex it gets through, and the next lookup misses and allocates a
fresh pair. The BSD master pty that Peter excluded from the retry in
mainline (its slave fds may stay open forever) is not our case: here
both counts are already zero.
What we get:
- old vzctl works with the kernel update alone, the vzctl change becomes
optional;
- -EBUSY keeps meaning "console attached" only, -EAGAIN is left only for
a pending signal;
- it goes on top of what is committed, no revert needed.
Could you send that as a follow-up on VSTOR-152365?
--
Konstantin
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Devel] [PATCH hci-8.1 0/2] ve/vtty: wait for a closing CT tty in the kernel, drop the EAGAIN return
2026-11-02 15:17 ` Konstantin Khorenko
@ 2026-11-02 17:15 ` Denis V. Lunev
2026-11-02 17:15 ` [Devel] [PATCH hci-8.1 1/2] Revert "ve/vtty: fix console attach failing with EBUSY while the CT closes the tty" Denis V. Lunev
` (2 more replies)
0 siblings, 3 replies; 13+ messages in thread
From: Denis V. Lunev @ 2026-11-02 17:15 UTC (permalink / raw)
To: khorenko; +Cc: devel
Konstantin pointed out that the applied "ve/vtty: fix console attach
failing with EBUSY while the CT closes the tty" fixes the race only
for a vzctl which retries on EAGAIN, and every vzctl in the field
does not. Following his suggestion, this series replaces it with a
wait inside vtty_open_master(), as tty_open() does since
7f22f6c935cd. Patch 1 reverts the EAGAIN return, patch 2 waits for
the closing pair. The vzctl change "vzctl console: retry opening a
CT tty the CT is still closing" is no longer needed.
A signal ends the wait with -ERESTARTSYS rather than -EAGAIN: the
ioctl restarts under SA_RESTART and fails with EINTR otherwise, and
EAGAIN does not leak back to userspace.
Tested on dev-cl04, .22.15 with both patches, installed vzctl-10.0.147
which does not retry:
- "vzctl console" in a loop while a loop in the CT opens and closes the
same tty: 63 of 300 attaches fail with EBUSY on stock .22.11, all 300
attach with the series;
- a second VE_CONFIGURE_OPEN_TTY while a console is attached still
fails with EBUSY at once;
- the same race under a 50 us SIGALRM storm does not hang: the
interrupted opens fail with EINTR, and with SA_RESTART none fail;
- ve_vtty_stress, without its EAGAIN allowance, passes;
- nothing in dmesg.
Denis V. Lunev (2):
Revert "ve/vtty: fix console attach failing with EBUSY while the CT
closes the tty"
ve/vtty: wait for a closing CT tty instead of failing the console
attach
drivers/tty/pty.c | 16 ++++++++++++----
tools/testing/selftests/ve/ve_vtty_stress.c | 2 +-
2 files changed, 13 insertions(+), 5 deletions(-)
--
2.53.0
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Devel] [PATCH hci-8.1 1/2] Revert "ve/vtty: fix console attach failing with EBUSY while the CT closes the tty"
2026-11-02 17:15 ` [Devel] [PATCH hci-8.1 0/2] ve/vtty: wait for a closing CT tty in the kernel, drop the EAGAIN return Denis V. Lunev
@ 2026-11-02 17:15 ` Denis V. Lunev
2026-11-02 17:48 ` no-reply
2026-11-02 17:15 ` [Devel] [PATCH hci-8.1 2/2] ve/vtty: wait for a closing CT tty instead of failing the console attach Denis V. Lunev
2026-11-03 15:54 ` [Devel] [PATCH hci-8.1 0/2] ve/vtty: wait for a closing CT tty in the kernel, drop the EAGAIN return Konstantin Khorenko
2 siblings, 1 reply; 13+ messages in thread
From: Denis V. Lunev @ 2026-11-02 17:15 UTC (permalink / raw)
To: khorenko; +Cc: devel
From: Denis V. Lunev <den@openvz.org>
This reverts commit 17cb7be7bfa3.
Returning -EAGAIN for a pair the CT is still closing helps only a vzctl
which retries. Every installed vzctl tries VE_CONFIGURE_OPEN_TTY once
and now fails with
Error opening CT tty: Resource temporarily unavailable
instead of "Device or resource busy". The next patch waits for the
closing pair inside vtty_open_master() instead, which needs no
userspace change.
https://virtuozzo.atlassian.net/browse/VSTOR-152365
Feature: tty: virtual Container console
Signed-off-by: Denis V. Lunev <den@openvz.org>
---
drivers/tty/pty.c | 5 ++---
tools/testing/selftests/ve/ve_vtty_stress.c | 2 +-
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 6f6dabba96e2..14d46bb9c293 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -1100,15 +1100,14 @@ int vtty_open_master(envid_t veid, int idx)
* user is gone and tty_release() has already committed to the final
* close, release_tty() is only waiting for tty_mutex to free it.
* Never hand out a reference to a tty which is about to be freed,
- * report -EAGAIN so that the caller retries and allocates a fresh
- * pair. -EBUSY above means a console is really attached.
+ * report -EBUSY so that the next attempt allocates a fresh pair.
*
* A pair we've just created above is exempt: it is not reachable by
* anyone else yet and its zero count is merely the initial state,
* vtty_install() gives its reference away to the master peer below.
*/
if (!created && slave->count == 0) {
- ret = -EAGAIN;
+ ret = -EBUSY;
goto err_unlock;
}
diff --git a/tools/testing/selftests/ve/ve_vtty_stress.c b/tools/testing/selftests/ve/ve_vtty_stress.c
index d8d92ae54718..f4bdd81133b8 100644
--- a/tools/testing/selftests/ve/ve_vtty_stress.c
+++ b/tools/testing/selftests/ve/ve_vtty_stress.c
@@ -44,7 +44,7 @@
*/
static bool expected_errno(int err)
{
- return err == EAGAIN || err == EBUSY || err == EIO || err == ENXIO;
+ return err == EBUSY || err == EIO || err == ENXIO;
}
/* A runner timeout must still reach the cleanup */
--
2.53.0
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Devel] [PATCH hci-8.1 2/2] ve/vtty: wait for a closing CT tty instead of failing the console attach
2026-11-02 17:15 ` [Devel] [PATCH hci-8.1 0/2] ve/vtty: wait for a closing CT tty in the kernel, drop the EAGAIN return Denis V. Lunev
2026-11-02 17:15 ` [Devel] [PATCH hci-8.1 1/2] Revert "ve/vtty: fix console attach failing with EBUSY while the CT closes the tty" Denis V. Lunev
@ 2026-11-02 17:15 ` Denis V. Lunev
2026-11-02 17:51 ` no-reply
2026-11-02 18:09 ` Vladimir Riabchun
2026-11-03 15:54 ` [Devel] [PATCH hci-8.1 0/2] ve/vtty: wait for a closing CT tty in the kernel, drop the EAGAIN return Konstantin Khorenko
2 siblings, 2 replies; 13+ messages in thread
From: Denis V. Lunev @ 2026-11-02 17:15 UTC (permalink / raw)
To: khorenko; +Cc: devel
From: Denis V. Lunev <den@openvz.org>
Since commit 23abb203a41a ("ve/vtty: fix use-after-free on concurrent
tty close and reopen") vtty_open_master() refuses a pair whose slave
count has dropped to zero: the last CT-side close has committed to the
final close, and the pair stays in the vtty map only until
release_tty() runs. The refusal is -EBUSY, the errno which means a
console is attached, and vzctl gives up:
Error opening CT tty: Device or resource busy
The window opens whenever the last process in the CT closes its tty:
getty respawn, login with autologin, SAK. "vzctl console" run right
after "vzctl start --wait" hits it.
Wait for the closer instead, as tty_open() does for the same window
since commit 7f22f6c935cd ("tty: Retry failed reopen if tty teardown
in-progress"): drop the slave lock, the vtty context and tty_mutex,
reschedule and look the pair up again. The fd and the file stay
allocated across the retry. No userspace change is needed, and -EBUSY
again means only that a console is attached.
The loop ends. Both counts are zero only after tty_release() has taken
the final close, and the closer then only needs tty_mutex in
tty_release_struct() to reach vtty_shutdown(), which removes the pair
from the vtty map. The next lookup misses and allocates a fresh pair.
The opener spins on schedule() while the closer flushes the tty works,
as tty_open() does. A pending signal ends the wait with -ERESTARTSYS,
so the ioctl restarts or fails with EINTR.
Fixes: 23abb203a41a ("ve/vtty: fix use-after-free on concurrent tty close and reopen")
https://virtuozzo.atlassian.net/browse/VSTOR-152365
Feature: tty: virtual Container console
Suggested-by: Konstantin Khorenko <khorenko@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
---
drivers/tty/pty.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 14d46bb9c293..6415456dca13 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -1054,6 +1054,7 @@ int vtty_open_master(envid_t veid, int idx)
* else would access it while we're holding
* the lock.
*/
+retry:
mutex_lock(&tty_mutex);
vtty_set_context(veid);
@@ -1100,15 +1101,23 @@ int vtty_open_master(envid_t veid, int idx)
* user is gone and tty_release() has already committed to the final
* close, release_tty() is only waiting for tty_mutex to free it.
* Never hand out a reference to a tty which is about to be freed,
- * report -EBUSY so that the next attempt allocates a fresh pair.
+ * let the closer through and retry, the next lookup then misses
+ * and allocates a fresh pair. -EBUSY above means a console is
+ * really attached.
*
* A pair we've just created above is exempt: it is not reachable by
* anyone else yet and its zero count is merely the initial state,
* vtty_install() gives its reference away to the master peer below.
*/
if (!created && slave->count == 0) {
- ret = -EBUSY;
- goto err_unlock;
+ ret = -ERESTARTSYS;
+ if (signal_pending(current))
+ goto err_unlock;
+ tty_unlock(slave);
+ vtty_drop_context();
+ mutex_unlock(&tty_mutex);
+ schedule();
+ goto retry;
}
/*
--
2.53.0
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Devel] [PATCH hci-8.1 1/2] Revert "ve/vtty: fix console attach failing with EBUSY while the CT closes the tty"
2026-11-02 17:15 ` [Devel] [PATCH hci-8.1 1/2] Revert "ve/vtty: fix console attach failing with EBUSY while the CT closes the tty" Denis V. Lunev
@ 2026-11-02 17:48 ` no-reply
0 siblings, 0 replies; 13+ messages in thread
From: no-reply @ 2026-11-02 17:48 UTC (permalink / raw)
To: Denis V. Lunev, khorenko; +Cc: devel
> From: Denis V. Lunev <den@openvz.org>
>
> This reverts commit 17cb7be7bfa3.
>
> Returning -EAGAIN for a pair the CT is still closing helps only a vzctl
> which retries. Every installed vzctl tries VE_CONFIGURE_OPEN_TTY once
> and now fails with
>
> Error opening CT tty: Resource temporarily unavailable
>
> instead of "Device or resource busy". The next patch waits for the
> closing pair inside vtty_open_master() instead, which needs no
> userspace change.
>
> https://virtuozzo.atlassian.net/browse/VSTOR-152365
> Feature: tty: virtual Container console
> Signed-off-by: Denis V. Lunev <den@openvz.org>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261102171504.3809155-1-den@openvz.org?part=1
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Devel] [PATCH hci-8.1 2/2] ve/vtty: wait for a closing CT tty instead of failing the console attach
2026-11-02 17:15 ` [Devel] [PATCH hci-8.1 2/2] ve/vtty: wait for a closing CT tty instead of failing the console attach Denis V. Lunev
@ 2026-11-02 17:51 ` no-reply
2026-11-02 18:09 ` Vladimir Riabchun
1 sibling, 0 replies; 13+ messages in thread
From: no-reply @ 2026-11-02 17:51 UTC (permalink / raw)
To: Denis V. Lunev, khorenko; +Cc: devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] tty: vtty_open_master() busy-waits with bare schedule() for closing tty
--
commit ddd1463f95114c5d89bc233ad67329d19bb74551
Author: Denis V. Lunev <den@openvz.org>
ve/vtty: wait for a closing CT tty instead of failing the console attach
When the last CT-side close has committed to the final close,
vtty_open_master() used to return -EBUSY. With this patch it drops its
locks, calls schedule() and looks the pair up again. A pending signal ends
the wait with -ERESTARTSYS.
Link: https://virtuozzo.atlassian.net/browse/VSTOR-152365
> diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
> --- a/drivers/tty/pty.c
> +++ b/drivers/tty/pty.c
[ ... ]
> if (!created && slave->count == 0) {
> - ret = -EBUSY;
> - goto err_unlock;
> + ret = -ERESTARTSYS;
> + if (signal_pending(current))
> + goto err_unlock;
> + tty_unlock(slave);
> + vtty_drop_context();
> + mutex_unlock(&tty_mutex);
> + schedule();
> + goto retry;
> }
[Severity: Low]
Is a bare schedule() the right way to wait here? The task is still
TASK_RUNNING, and nothing sets the task state or waits on an event. In
that case schedule() only yields the CPU, and the loop becomes a busy-wait.
The closer can sleep for a while before it reaches vtty_shutdown():
tty_release_struct()
tty_ldisc_release(tty);
tty_flush_works(tty);
...
mutex_lock(&tty_mutex);
release_tty(tty, idx);
While it does this, vtty_open_master() keeps looping. Each pass does the
following:
mutex_lock(&tty_mutex);
...
mutex_unlock(&tty_mutex);
schedule();
So the opener can use up to a full CPU and keeps contending with the closer
for tty_mutex. If the opener has a higher priority (for example SCHED_FIFO
or SCHED_RR) and runs on the same CPU as the closer, can it starve the
closer, so that the loop doesn't end until a signal arrives?
The commit message says the spinning matches tty_open(). Would a short
sleep, for example msleep_interruptible(), or an interruptible wait for the
pair to leave the vtty map be more robust here?
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261102171504.3809155-1-den@openvz.org?part=2
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Devel] [PATCH hci-8.1 2/2] ve/vtty: wait for a closing CT tty instead of failing the console attach
2026-11-02 17:15 ` [Devel] [PATCH hci-8.1 2/2] ve/vtty: wait for a closing CT tty instead of failing the console attach Denis V. Lunev
2026-11-02 17:51 ` no-reply
@ 2026-11-02 18:09 ` Vladimir Riabchun
2026-11-03 12:42 ` Denis V. Lunev
1 sibling, 1 reply; 13+ messages in thread
From: Vladimir Riabchun @ 2026-11-02 18:09 UTC (permalink / raw)
To: devel, Denis V. Lunev
On 11/2/26 18:15, Denis V. Lunev wrote:
> From: Denis V. Lunev <den@openvz.org>
>
> Since commit 23abb203a41a ("ve/vtty: fix use-after-free on concurrent
> tty close and reopen") vtty_open_master() refuses a pair whose slave
> count has dropped to zero: the last CT-side close has committed to the
> final close, and the pair stays in the vtty map only until
> release_tty() runs. The refusal is -EBUSY, the errno which means a
> console is attached, and vzctl gives up:
>
> Error opening CT tty: Device or resource busy
>
> The window opens whenever the last process in the CT closes its tty:
> getty respawn, login with autologin, SAK. "vzctl console" run right
> after "vzctl start --wait" hits it.
>
> Wait for the closer instead, as tty_open() does for the same window
> since commit 7f22f6c935cd ("tty: Retry failed reopen if tty teardown
> in-progress"): drop the slave lock, the vtty context and tty_mutex,
> reschedule and look the pair up again. The fd and the file stay
> allocated across the retry. No userspace change is needed, and -EBUSY
> again means only that a console is attached.
>
> The loop ends. Both counts are zero only after tty_release() has taken
> the final close, and the closer then only needs tty_mutex in
> tty_release_struct() to reach vtty_shutdown(), which removes the pair
> from the vtty map. The next lookup misses and allocates a fresh pair.
> The opener spins on schedule() while the closer flushes the tty works,
> as tty_open() does. A pending signal ends the wait with -ERESTARTSYS,
> so the ioctl restarts or fails with EINTR.
>
> Fixes: 23abb203a41a ("ve/vtty: fix use-after-free on concurrent tty close and reopen")
>
> https://virtuozzo.atlassian.net/browse/VSTOR-152365
> Feature: tty: virtual Container console
> Suggested-by: Konstantin Khorenko <khorenko@virtuozzo.com>
> Signed-off-by: Denis V. Lunev <den@openvz.org>
> ---
> drivers/tty/pty.c | 15 ++++++++++++---
> 1 file changed, 12 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
> index 14d46bb9c293..6415456dca13 100644
> --- a/drivers/tty/pty.c
> +++ b/drivers/tty/pty.c
> @@ -1054,6 +1054,7 @@ int vtty_open_master(envid_t veid, int idx)
> * else would access it while we're holding
> * the lock.
> */
> +retry:
> mutex_lock(&tty_mutex);
> vtty_set_context(veid);
>
> @@ -1100,15 +1101,23 @@ int vtty_open_master(envid_t veid, int idx)
> * user is gone and tty_release() has already committed to the final
> * close, release_tty() is only waiting for tty_mutex to free it.
> * Never hand out a reference to a tty which is about to be freed,
> - * report -EBUSY so that the next attempt allocates a fresh pair.
> + * let the closer through and retry, the next lookup then misses
> + * and allocates a fresh pair. -EBUSY above means a console is
> + * really attached.
> *
> * A pair we've just created above is exempt: it is not reachable by
> * anyone else yet and its zero count is merely the initial state,
> * vtty_install() gives its reference away to the master peer below.
> */
> if (!created && slave->count == 0) {
> - ret = -EBUSY;
> - goto err_unlock;
> + ret = -ERESTARTSYS;
> + if (signal_pending(current))
> + goto err_unlock;
> + tty_unlock(slave);
> + vtty_drop_context();
> + mutex_unlock(&tty_mutex);
> + schedule();
I think cond_resched is better here.
> + goto retry;
> }
>
> /*
--
Best regards, Riabchun Vladimir
Linux Kernel Developer, Virtuozzo
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Devel] [PATCH hci-8.1 2/2] ve/vtty: wait for a closing CT tty instead of failing the console attach
2026-11-02 18:09 ` Vladimir Riabchun
@ 2026-11-03 12:42 ` Denis V. Lunev
0 siblings, 0 replies; 13+ messages in thread
From: Denis V. Lunev @ 2026-11-03 12:42 UTC (permalink / raw)
To: Vladimir Riabchun, devel, Denis V. Lunev
On 11/2/26 19:09, Vladimir Riabchun wrote:
>
> On 11/2/26 18:15, Denis V. Lunev wrote:
>> From: Denis V. Lunev <den@openvz.org>
>>
>> Since commit 23abb203a41a ("ve/vtty: fix use-after-free on concurrent
>> tty close and reopen") vtty_open_master() refuses a pair whose slave
>> count has dropped to zero: the last CT-side close has committed to the
>> final close, and the pair stays in the vtty map only until
>> release_tty() runs. The refusal is -EBUSY, the errno which means a
>> console is attached, and vzctl gives up:
>>
>> Error opening CT tty: Device or resource busy
>>
>> The window opens whenever the last process in the CT closes its tty:
>> getty respawn, login with autologin, SAK. "vzctl console" run right
>> after "vzctl start --wait" hits it.
>>
>> Wait for the closer instead, as tty_open() does for the same window
>> since commit 7f22f6c935cd ("tty: Retry failed reopen if tty teardown
>> in-progress"): drop the slave lock, the vtty context and tty_mutex,
>> reschedule and look the pair up again. The fd and the file stay
>> allocated across the retry. No userspace change is needed, and -EBUSY
>> again means only that a console is attached.
>>
>> The loop ends. Both counts are zero only after tty_release() has taken
>> the final close, and the closer then only needs tty_mutex in
>> tty_release_struct() to reach vtty_shutdown(), which removes the pair
>> from the vtty map. The next lookup misses and allocates a fresh pair.
>> The opener spins on schedule() while the closer flushes the tty works,
>> as tty_open() does. A pending signal ends the wait with -ERESTARTSYS,
>> so the ioctl restarts or fails with EINTR.
>>
>> Fixes: 23abb203a41a ("ve/vtty: fix use-after-free on concurrent tty close and reopen")
>>
>> https://virtuozzo.atlassian.net/browse/VSTOR-152365
>> Feature: tty: virtual Container console
>> Suggested-by: Konstantin Khorenko <khorenko@virtuozzo.com>
>> Signed-off-by: Denis V. Lunev <den@openvz.org>
>> ---
>> drivers/tty/pty.c | 15 ++++++++++++---
>> 1 file changed, 12 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
>> index 14d46bb9c293..6415456dca13 100644
>> --- a/drivers/tty/pty.c
>> +++ b/drivers/tty/pty.c
>> @@ -1054,6 +1054,7 @@ int vtty_open_master(envid_t veid, int idx)
>> * else would access it while we're holding
>> * the lock.
>> */
>> +retry:
>> mutex_lock(&tty_mutex);
>> vtty_set_context(veid);
>>
>> @@ -1100,15 +1101,23 @@ int vtty_open_master(envid_t veid, int idx)
>> * user is gone and tty_release() has already committed to the final
>> * close, release_tty() is only waiting for tty_mutex to free it.
>> * Never hand out a reference to a tty which is about to be freed,
>> - * report -EBUSY so that the next attempt allocates a fresh pair.
>> + * let the closer through and retry, the next lookup then misses
>> + * and allocates a fresh pair. -EBUSY above means a console is
>> + * really attached.
>> *
>> * A pair we've just created above is exempt: it is not reachable by
>> * anyone else yet and its zero count is merely the initial state,
>> * vtty_install() gives its reference away to the master peer below.
>> */
>> if (!created && slave->count == 0) {
>> - ret = -EBUSY;
>> - goto err_unlock;
>> + ret = -ERESTARTSYS;
>> + if (signal_pending(current))
>> + goto err_unlock;
>> + tty_unlock(slave);
>> + vtty_drop_context();
>> + mutex_unlock(&tty_mutex);
>> + schedule();
> I think cond_resched is better here.
That is not equivalent I believe and my check is correct.
Den
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Devel] [PATCH hci-8.1 0/2] ve/vtty: wait for a closing CT tty in the kernel, drop the EAGAIN return
2026-11-02 17:15 ` [Devel] [PATCH hci-8.1 0/2] ve/vtty: wait for a closing CT tty in the kernel, drop the EAGAIN return Denis V. Lunev
2026-11-02 17:15 ` [Devel] [PATCH hci-8.1 1/2] Revert "ve/vtty: fix console attach failing with EBUSY while the CT closes the tty" Denis V. Lunev
2026-11-02 17:15 ` [Devel] [PATCH hci-8.1 2/2] ve/vtty: wait for a closing CT tty instead of failing the console attach Denis V. Lunev
@ 2026-11-03 15:54 ` Konstantin Khorenko
2 siblings, 0 replies; 13+ messages in thread
From: Konstantin Khorenko @ 2026-11-03 15:54 UTC (permalink / raw)
To: Denis V. Lunev; +Cc: devel
On Mon, 02 Nov 2026 18:15:02 +0100, Denis V. Lunev wrote:
> ve/vtty: wait for a closing CT tty in the kernel, drop the EAGAIN return
>
> Konstantin pointed out that the applied "ve/vtty: fix console attach
> failing with EBUSY while the CT closes the tty" fixes the race only
> for a vzctl which retries on EAGAIN, and every vzctl in the field
> does not. Following his suggestion, this series replaces it with a
> wait inside vtty_open_master(), as tty_open() does since
> 7f22f6c935cd. Patch 1 reverts the EAGAIN return, patch 2 waits for
> the closing pair. The vzctl change "vzctl console: retry opening a
> CT tty the CT is still closing" is no longer needed.
>
> [...]
Applied to branch-rh10-6.12.0-211.52.1.22.x.vz10-ovz, will be released in rh10-6.12.0-211.52.1.22.17.vz10, thanks!
[1/2] Revert "ve/vtty: fix console attach failing with EBUSY while the CT closes the tty"
https://bitbucket.org/virtuozzocore/vzkernel.vzs/commits/a47aff57a16b
[2/2] ve/vtty: wait for a closing CT tty instead of failing the console attach
https://bitbucket.org/virtuozzocore/vzkernel.vzs/commits/7377f791d287
--
Konstantin Khorenko,
Virtuozzo Linux Kernel Team
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-11-03 15:56 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-29 22:35 [Devel] [PATCH hci-8.1] ve/vtty: fix console attach failing with EBUSY while the CT closes the tty Denis V. Lunev
2026-10-29 22:38 ` no-reply
2026-11-02 10:41 ` Konstantin Khorenko
2026-11-02 10:42 ` Konstantin Khorenko
2026-11-02 15:17 ` Konstantin Khorenko
2026-11-02 17:15 ` [Devel] [PATCH hci-8.1 0/2] ve/vtty: wait for a closing CT tty in the kernel, drop the EAGAIN return Denis V. Lunev
2026-11-02 17:15 ` [Devel] [PATCH hci-8.1 1/2] Revert "ve/vtty: fix console attach failing with EBUSY while the CT closes the tty" Denis V. Lunev
2026-11-02 17:48 ` no-reply
2026-11-02 17:15 ` [Devel] [PATCH hci-8.1 2/2] ve/vtty: wait for a closing CT tty instead of failing the console attach Denis V. Lunev
2026-11-02 17:51 ` no-reply
2026-11-02 18:09 ` Vladimir Riabchun
2026-11-03 12:42 ` Denis V. Lunev
2026-11-03 15:54 ` [Devel] [PATCH hci-8.1 0/2] ve/vtty: wait for a closing CT tty in the kernel, drop the EAGAIN return Konstantin Khorenko
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.