[Devel] [PATCH RHEL8 COMMIT] ve/tty: Provide interface for current tty inheritance

Konstantin Khorenko khorenko at virtuozzo.com
Mon May 24 18:31:55 MSK 2021


The commit is pushed to "branch-rh8-4.18.0-240.1.1.vz8.5.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh8-4.18.0-240.1.1.vz8.5.32
------>
commit fc474d04208e32b045a68f1e44a287fb0a437ef6
Author: Cyrill Gorcunov <gorcunov at virtuozzo.com>
Date:   Mon May 24 18:31:55 2021 +0300

    ve/tty: Provide interface for current tty inheritance
    
    When fork() is called the current controlling terminal is inherited
    by a child process. But in criu we fork all process first and then
    restore their files, thus if terminal is opened in some children
    its reference get lost. We refuse to checkpoint such configurations
    at the moment in criu itself.
    
    So to be able to restore this kind of container we need a way to
    propagate controlling terminal to children processes, and here
    is an interface "ve.ctty" entry on toplevel ve cgroup. One have
    to pass pid of the donor task in first position followed by a series
    of recipient pids.
    
    https://jira.sw.ru/browse/PSBM-76490
    
    CC: Andrey Vagin <avagin at virtuozzo.com>
    CC: Andrey Ryabinin <aryabinin at virtuozzo.com>
    CC: Konstantin Khorenko <khorenko at virtuozzo.com>
    CC: "Denis V. Lunev" <den at virtuozzo.com>
    Signed-off-by: Cyrill Gorcunov <gorcunov at virtuozzo.com>
    
    khorenko@: we'll try to push the interface for ctty set up to mainstream.
    May be it will be another interface like ioctl/netlink/etc, whatever.
    
    This work (interface to mainstream) will be done in the scope of
    https://jira.sw.ru/browse/PSBM-81687
    
    (cherry picked from vz7 commit 098099f6daaf ("ve/tty: Provide interface for
    current tty inheritance"))
    
    See also
    451af50 ("cgroup: replace cftype->write_string() with cftype->write()")
    
    VZ 8 rebase part https://jira.sw.ru/browse/PSBM-127797
    
    Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn at virtuozzo.com>
---
 kernel/ve/ve.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 102 insertions(+)

diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c
index 6858698d69bc..ef8fb52936bc 100644
--- a/kernel/ve/ve.c
+++ b/kernel/ve/ve.c
@@ -25,6 +25,10 @@
 #include <linux/kthread.h>
 #include <linux/nsproxy.h>
 #include <linux/fs_struct.h>
+#include <linux/task_work.h>
+#include <linux/ctype.h>
+#include <linux/tty.h>
+
 #include <uapi/linux/vzcalluser.h>
 #include <net/rtnetlink.h>
 
@@ -1556,6 +1560,99 @@ static int ve_aio_max_nr_write(struct cgroup_subsys_state *css,
 }
 #endif
 
+static ssize_t ve_write_ctty(struct kernfs_open_file *of, char *buf,
+			 size_t nbytes, loff_t off)
+{
+	struct task_struct *tsk_from, *tsk_to;
+	struct tty_struct *tty_from, *tty_to;
+	pid_t pid_from, pid_to;
+	unsigned long flags;
+	char *pids;
+	int ret;
+
+	/*
+	 * Buffer format is the following
+	 *
+	 * 	pid_from pid_to pid_to ...
+	 *
+	 * where pid_to are pids to propagate
+	 * current terminal into.
+	 */
+
+	pids = skip_spaces(buf);
+	if (sscanf(pids, "%d", &pid_from) != 1)
+		return -EINVAL;
+	pids = strchr(pids, ' ');
+	if (!pids)
+		return -EINVAL;
+	pids = skip_spaces(pids);
+
+	rcu_read_lock();
+	tsk_from = find_task_by_vpid(pid_from);
+	if (tsk_from)
+		get_task_struct(tsk_from);
+	rcu_read_unlock();
+
+	if (!tsk_from)
+		return -ESRCH;
+
+	spin_lock_irqsave(&tsk_from->sighand->siglock, flags);
+	tty_from = tty_kref_get(tsk_from->signal->tty);
+	spin_unlock_irqrestore(&tsk_from->sighand->siglock, flags);
+
+	if (!tty_from) {
+		ret = -ENOTTY;
+		goto out;
+	}
+
+	ret = 0;
+	while (pids && *pids) {
+		if (sscanf(pids, "%d", &pid_to) != 1) {
+			ret = -EINVAL;
+			goto out;
+		}
+		pids = strchr(pids, ' ');
+		if (pids)
+			pids = skip_spaces(pids);
+
+		rcu_read_lock();
+		tsk_to = find_task_by_vpid(pid_to);
+		if (tsk_to)
+			get_task_struct(tsk_to);
+		rcu_read_unlock();
+
+		if (!tsk_to) {
+			ret = -ESRCH;
+			goto out;
+		}
+
+		if (tsk_from->task_ve == tsk_to->task_ve) {
+			spin_lock_irqsave(&tsk_to->sighand->siglock, flags);
+			tty_to = tsk_to->signal->tty;
+			if (!tty_to)
+				tsk_to->signal->tty = tty_kref_get(tty_from);
+			else
+				ret = -EBUSY;
+			spin_unlock_irqrestore(&tsk_to->sighand->siglock, flags);
+		} else
+			ret = -EINVAL;
+
+		put_task_struct(tsk_to);
+
+		if (ret)
+			goto out;
+	}
+
+out:
+	tty_kref_put(tty_from);
+	put_task_struct(tsk_from);
+
+	if (!ret)
+		ret = nbytes;
+
+	return ret;
+}
+
 static struct cftype ve_cftypes[] = {
 
 	{
@@ -1628,6 +1725,11 @@ static struct cftype ve_cftypes[] = {
 		.write_u64		= ve_aio_max_nr_write,
 	},
 #endif
+	{
+		.name			= "ctty",
+		.flags			= CFTYPE_ONLY_ON_ROOT,
+		.write			= ve_write_ctty,
+	},
 	{ }
 };
 


More information about the Devel mailing list