brintos

brintos / linux-shallow public Read only

0
0
Text · 24.8 KiB · 7f28e50 Raw
967 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 *  Copyright (C) 1991, 1992  Linus Torvalds4 *5 *  Added support for a Unix98-style ptmx device.6 *    -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-19987 *8 */9 10#include <linux/module.h>11#include <linux/errno.h>12#include <linux/interrupt.h>13#include <linux/tty.h>14#include <linux/tty_flip.h>15#include <linux/fcntl.h>16#include <linux/sched/signal.h>17#include <linux/string.h>18#include <linux/major.h>19#include <linux/mm.h>20#include <linux/init.h>21#include <linux/device.h>22#include <linux/uaccess.h>23#include <linux/bitops.h>24#include <linux/devpts_fs.h>25#include <linux/slab.h>26#include <linux/mutex.h>27#include <linux/poll.h>28#include <linux/mount.h>29#include <linux/file.h>30#include <linux/ioctl.h>31#include <linux/compat.h>32#include "tty.h"33 34#undef TTY_DEBUG_HANGUP35#ifdef TTY_DEBUG_HANGUP36# define tty_debug_hangup(tty, f, args...)	tty_debug(tty, f, ##args)37#else38# define tty_debug_hangup(tty, f, args...)	do {} while (0)39#endif40 41#ifdef CONFIG_UNIX98_PTYS42static struct tty_driver *ptm_driver;43static struct tty_driver *pts_driver;44static DEFINE_MUTEX(devpts_mutex);45#endif46 47static void pty_close(struct tty_struct *tty, struct file *filp)48{49	if (tty->driver->subtype == PTY_TYPE_MASTER)50		WARN_ON(tty->count > 1);51	else {52		if (tty_io_error(tty))53			return;54		if (tty->count > 2)55			return;56	}57	set_bit(TTY_IO_ERROR, &tty->flags);58	wake_up_interruptible(&tty->read_wait);59	wake_up_interruptible(&tty->write_wait);60	spin_lock_irq(&tty->ctrl.lock);61	tty->ctrl.packet = false;62	spin_unlock_irq(&tty->ctrl.lock);63	/* Review - krefs on tty_link ?? */64	if (!tty->link)65		return;66	set_bit(TTY_OTHER_CLOSED, &tty->link->flags);67	wake_up_interruptible(&tty->link->read_wait);68	wake_up_interruptible(&tty->link->write_wait);69	if (tty->driver->subtype == PTY_TYPE_MASTER) {70		set_bit(TTY_OTHER_CLOSED, &tty->flags);71#ifdef CONFIG_UNIX98_PTYS72		if (tty->driver == ptm_driver) {73			mutex_lock(&devpts_mutex);74			if (tty->link->driver_data)75				devpts_pty_kill(tty->link->driver_data);76			mutex_unlock(&devpts_mutex);77		}78#endif79		tty_vhangup(tty->link);80	}81}82 83/*84 * The unthrottle routine is called by the line discipline to signal85 * that it can receive more characters.  For PTY's, the TTY_THROTTLED86 * flag is always set, to force the line discipline to always call the87 * unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE88 * characters in the queue.  This is necessary since each time this89 * happens, we need to wake up any sleeping processes that could be90 * (1) trying to send data to the pty, or (2) waiting in wait_until_sent()91 * for the pty buffer to be drained.92 */93static HWJS_SUSPENDS void pty_unthrottle(struct tty_struct *tty)94{95	tty_wakeup(tty->link);96	set_bit(TTY_THROTTLED, &tty->flags);97}98 99/**100 *	pty_write		-	write to a pty101 *	@tty: the tty we write from102 *	@buf: kernel buffer of data103 *	@c: bytes to write104 *105 *	Our "hardware" write method. Data is coming from the ldisc which106 *	may be in a non sleeping state. We simply throw this at the other107 *	end of the link as if we were an IRQ handler receiving stuff for108 *	the other side of the pty/tty pair.109 */110 111#ifdef CONFIG_WASM32112/* K12-D bridge drain producer — arch/wasm32/kernel/tty_bridge.c. */113extern bool wasm32_tty_bridge_capture_output(struct tty_struct *to,114					     const u8 *buf, size_t c);115#endif116 117static ssize_t pty_write(struct tty_struct *tty, const u8 *buf, size_t c)118{119	struct tty_struct *to = tty->link;120 121	if (tty->flow.stopped || !c)122		return 0;123 124#ifdef CONFIG_WASM32125	/*126	 * K12-D: capture slave->master output (slave write()s, N_TTY echo,127	 * OPOST CRLF — all funnel through pty_write) into the HardwareJS128	 * drain ring. When @to is the active bridge master, HardwareJS owns129	 * the master (drains via the ring), so its normal read path is130	 * BYPASSED — all @c bytes are accounted as written. Otherwise this is131	 * a no-op and delivery proceeds normally below.132	 */133	if (wasm32_tty_bridge_capture_output(to, buf, c))134		return c;135#endif136 137	return tty_insert_flip_string_and_push_buffer(to->port, buf, c);138}139 140/**141 *	pty_write_room	-	write space142 *	@tty: tty we are writing from143 *144 *	Report how many bytes the ldisc can send into the queue for145 *	the other device.146 */147 148static unsigned int pty_write_room(struct tty_struct *tty)149{150	if (tty->flow.stopped)151		return 0;152	return tty_buffer_space_avail(tty->link->port);153}154 155/* Set the lock flag on a pty */156static int pty_set_lock(struct tty_struct *tty, int __user *arg)157{158	int val;159 160	if (get_user(val, arg))161		return -EFAULT;162	if (val)163		set_bit(TTY_PTY_LOCK, &tty->flags);164	else165		clear_bit(TTY_PTY_LOCK, &tty->flags);166	return 0;167}168 169static int pty_get_lock(struct tty_struct *tty, int __user *arg)170{171	int locked = test_bit(TTY_PTY_LOCK, &tty->flags);172 173	return put_user(locked, arg);174}175 176/* Set the packet mode on a pty */177static int pty_set_pktmode(struct tty_struct *tty, int __user *arg)178{179	int pktmode;180 181	if (get_user(pktmode, arg))182		return -EFAULT;183 184	spin_lock_irq(&tty->ctrl.lock);185	if (pktmode) {186		if (!tty->ctrl.packet) {187			tty->link->ctrl.pktstatus = 0;188			smp_mb();189			tty->ctrl.packet = true;190		}191	} else192		tty->ctrl.packet = false;193	spin_unlock_irq(&tty->ctrl.lock);194 195	return 0;196}197 198/* Get the packet mode of a pty */199static int pty_get_pktmode(struct tty_struct *tty, int __user *arg)200{201	int pktmode = tty->ctrl.packet;202 203	return put_user(pktmode, arg);204}205 206/* Send a signal to the slave */207static HWJS_SUSPENDS int pty_signal(struct tty_struct *tty, int sig)208{209	struct pid *pgrp;210 211	if (sig != SIGINT && sig != SIGQUIT && sig != SIGTSTP)212		return -EINVAL;213 214	if (tty->link) {215		pgrp = tty_get_pgrp(tty->link);216		if (pgrp)217			kill_pgrp(pgrp, sig, 1);218		put_pid(pgrp);219	}220	return 0;221}222 223static HWJS_SUSPENDS void pty_flush_buffer(struct tty_struct *tty)224{225	struct tty_struct *to = tty->link;226 227	if (!to)228		return;229 230	tty_buffer_flush(to, NULL);231	if (to->ctrl.packet) {232		spin_lock_irq(&tty->ctrl.lock);233		tty->ctrl.pktstatus |= TIOCPKT_FLUSHWRITE;234		wake_up_interruptible(&to->read_wait);235		spin_unlock_irq(&tty->ctrl.lock);236	}237}238 239static int pty_open(struct tty_struct *tty, struct file *filp)240{241	if (!tty || !tty->link)242		return -ENODEV;243 244	if (test_bit(TTY_OTHER_CLOSED, &tty->flags))245		goto out;246	if (test_bit(TTY_PTY_LOCK, &tty->link->flags))247		goto out;248	if (tty->driver->subtype == PTY_TYPE_SLAVE && tty->link->count != 1)249		goto out;250 251	clear_bit(TTY_IO_ERROR, &tty->flags);252	clear_bit(TTY_OTHER_CLOSED, &tty->link->flags);253	set_bit(TTY_THROTTLED, &tty->flags);254	return 0;255 256out:257	set_bit(TTY_IO_ERROR, &tty->flags);258	return -EIO;259}260 261static HWJS_SUSPENDS void pty_set_termios(struct tty_struct *tty,262			    const struct ktermios *old_termios)263{264	/* See if packet mode change of state. */265	if (tty->link && tty->link->ctrl.packet) {266		int extproc = (old_termios->c_lflag & EXTPROC) | L_EXTPROC(tty);267		int old_flow = ((old_termios->c_iflag & IXON) &&268				(old_termios->c_cc[VSTOP] == '\023') &&269				(old_termios->c_cc[VSTART] == '\021'));270		int new_flow = (I_IXON(tty) &&271				STOP_CHAR(tty) == '\023' &&272				START_CHAR(tty) == '\021');273		if ((old_flow != new_flow) || extproc) {274			spin_lock_irq(&tty->ctrl.lock);275			if (old_flow != new_flow) {276				tty->ctrl.pktstatus &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);277				if (new_flow)278					tty->ctrl.pktstatus |= TIOCPKT_DOSTOP;279				else280					tty->ctrl.pktstatus |= TIOCPKT_NOSTOP;281			}282			if (extproc)283				tty->ctrl.pktstatus |= TIOCPKT_IOCTL;284			spin_unlock_irq(&tty->ctrl.lock);285			wake_up_interruptible(&tty->link->read_wait);286		}287	}288 289	tty->termios.c_cflag &= ~(CSIZE | PARENB);290	tty->termios.c_cflag |= (CS8 | CREAD);291}292 293/**294 *	pty_resize		-	resize event295 *	@tty: tty being resized296 *	@ws: window size being set.297 *298 *	Update the termios variables and send the necessary signals to299 *	peform a terminal resize correctly300 */301 302static HWJS_SUSPENDS int pty_resize(struct tty_struct *tty,  struct winsize *ws)303{304	struct pid *pgrp, *rpgrp;305	struct tty_struct *pty = tty->link;306 307	/* For a PTY we need to lock the tty side */308	mutex_lock(&tty->winsize_mutex);309	if (!memcmp(ws, &tty->winsize, sizeof(*ws)))310		goto done;311 312	/* Signal the foreground process group of both ptys */313	pgrp = tty_get_pgrp(tty);314	rpgrp = tty_get_pgrp(pty);315 316	if (pgrp)317		kill_pgrp(pgrp, SIGWINCH, 1);318	if (rpgrp != pgrp && rpgrp)319		kill_pgrp(rpgrp, SIGWINCH, 1);320 321	put_pid(pgrp);322	put_pid(rpgrp);323 324	tty->winsize = *ws;325	pty->winsize = *ws;	/* Never used so will go away soon */326done:327	mutex_unlock(&tty->winsize_mutex);328	return 0;329}330 331/**332 *	pty_start - start() handler333 *	pty_stop  - stop() handler334 *	@tty: tty being flow-controlled335 *336 *	Propagates the TIOCPKT status to the master pty.337 *338 *	NB: only the master pty can be in packet mode so only the slave339 *	    needs start()/stop() handlers340 */341static HWJS_SUSPENDS void pty_start(struct tty_struct *tty)342{343	unsigned long flags;344 345	if (tty->link && tty->link->ctrl.packet) {346		spin_lock_irqsave(&tty->ctrl.lock, flags);347		tty->ctrl.pktstatus &= ~TIOCPKT_STOP;348		tty->ctrl.pktstatus |= TIOCPKT_START;349		spin_unlock_irqrestore(&tty->ctrl.lock, flags);350		wake_up_interruptible_poll(&tty->link->read_wait, EPOLLIN);351	}352}353 354static HWJS_SUSPENDS void pty_stop(struct tty_struct *tty)355{356	unsigned long flags;357 358	if (tty->link && tty->link->ctrl.packet) {359		spin_lock_irqsave(&tty->ctrl.lock, flags);360		tty->ctrl.pktstatus &= ~TIOCPKT_START;361		tty->ctrl.pktstatus |= TIOCPKT_STOP;362		spin_unlock_irqrestore(&tty->ctrl.lock, flags);363		wake_up_interruptible_poll(&tty->link->read_wait, EPOLLIN);364	}365}366 367/**368 *	pty_common_install		-	set up the pty pair369 *	@driver: the pty driver370 *	@tty: the tty being instantiated371 *	@legacy: true if this is BSD style372 *373 *	Perform the initial set up for the tty/pty pair. Called from the374 *	tty layer when the port is first opened.375 *376 *	Locking: the caller must hold the tty_mutex377 */378static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,379		bool legacy)380{381	struct tty_struct *o_tty;382	struct tty_port *ports[2];383	int idx = tty->index;384	int retval = -ENOMEM;385 386	/* Opening the slave first has always returned -EIO */387	if (driver->subtype != PTY_TYPE_MASTER)388		return -EIO;389 390	ports[0] = kmalloc(sizeof **ports, GFP_KERNEL);391	ports[1] = kmalloc(sizeof **ports, GFP_KERNEL);392	if (!ports[0] || !ports[1])393		goto err;394	if (!try_module_get(driver->other->owner)) {395		/* This cannot in fact currently happen */396		goto err;397	}398	o_tty = alloc_tty_struct(driver->other, idx);399	if (!o_tty)400		goto err_put_module;401 402	tty_set_lock_subclass(o_tty);403	lockdep_set_subclass(&o_tty->termios_rwsem, TTY_LOCK_SLAVE);404 405	if (legacy) {406		/* We always use new tty termios data so we can do this407		   the easy way .. */408		tty_init_termios(tty);409		tty_init_termios(o_tty);410 411		driver->other->ttys[idx] = o_tty;412		driver->ttys[idx] = tty;413	} else {414		memset(&tty->termios_locked, 0, sizeof(tty->termios_locked));415		tty->termios = driver->init_termios;416		memset(&o_tty->termios_locked, 0, sizeof(tty->termios_locked));417		o_tty->termios = driver->other->init_termios;418	}419 420	/*421	 * Everything allocated ... set up the o_tty structure.422	 */423	tty_driver_kref_get(driver->other);424	/* Establish the links in both directions */425	tty->link   = o_tty;426	o_tty->link = tty;427	tty_port_init(ports[0]);428	tty_port_init(ports[1]);429	tty_buffer_set_limit(ports[0], 8192);430	tty_buffer_set_limit(ports[1], 8192);431	o_tty->port = ports[0];432	tty->port = ports[1];433	o_tty->port->itty = o_tty;434 435	tty_buffer_set_lock_subclass(o_tty->port);436 437	tty_driver_kref_get(driver);438	tty->count++;439	o_tty->count++;440	return 0;441 442err_put_module:443	module_put(driver->other->owner);444err:445	kfree(ports[0]);446	kfree(ports[1]);447	return retval;448}449 450static void pty_cleanup(struct tty_struct *tty)451{452	tty_port_put(tty->port);453}454 455/* Traditional BSD devices */456#ifdef CONFIG_LEGACY_PTYS457 458static int pty_install(struct tty_driver *driver, struct tty_struct *tty)459{460	return pty_common_install(driver, tty, true);461}462 463static void pty_remove(struct tty_driver *driver, struct tty_struct *tty)464{465	struct tty_struct *pair = tty->link;466 467	driver->ttys[tty->index] = NULL;468	if (pair)469		pair->driver->ttys[pair->index] = NULL;470}471 472static HWJS_SUSPENDS int pty_bsd_ioctl(struct tty_struct *tty,473			 unsigned int cmd, unsigned long arg)474{475	switch (cmd) {476	case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */477		return pty_set_lock(tty, (int __user *) arg);478	case TIOCGPTLCK: /* Get PT Lock status */479		return pty_get_lock(tty, (int __user *)arg);480	case TIOCPKT: /* Set PT packet mode */481		return pty_set_pktmode(tty, (int __user *)arg);482	case TIOCGPKT: /* Get PT packet mode */483		return pty_get_pktmode(tty, (int __user *)arg);484	case TIOCSIG:    /* Send signal to other side of pty */485		return pty_signal(tty, (int) arg);486	case TIOCGPTN: /* TTY returns ENOTTY, but glibc expects EINVAL here */487		return -EINVAL;488	}489	return -ENOIOCTLCMD;490}491 492#ifdef CONFIG_COMPAT493static long pty_bsd_compat_ioctl(struct tty_struct *tty,494				 unsigned int cmd, unsigned long arg)495{496	/*497	 * PTY ioctls don't require any special translation between 32-bit and498	 * 64-bit userspace, they are already compatible.499	 */500	return pty_bsd_ioctl(tty, cmd, (unsigned long)compat_ptr(arg));501}502#else503#define pty_bsd_compat_ioctl NULL504#endif505 506static int legacy_count = CONFIG_LEGACY_PTY_COUNT;507/*508 * not really modular, but the easiest way to keep compat with existing509 * bootargs behaviour is to continue using module_param here.510 */511module_param(legacy_count, int, 0);512 513/*514 * The master side of a pty can do TIOCSPTLCK and thus515 * has pty_bsd_ioctl.516 */517static const struct tty_operations master_pty_ops_bsd = {518	.install = pty_install,519	.open = pty_open,520	.close = pty_close,521	.write = pty_write,522	.write_room = pty_write_room,523	.flush_buffer = pty_flush_buffer,524	.unthrottle = pty_unthrottle,525	.ioctl = pty_bsd_ioctl,526	.compat_ioctl = pty_bsd_compat_ioctl,527	.cleanup = pty_cleanup,528	.resize = pty_resize,529	.remove = pty_remove530};531 532static const struct tty_operations slave_pty_ops_bsd = {533	.install = pty_install,534	.open = pty_open,535	.close = pty_close,536	.write = pty_write,537	.write_room = pty_write_room,538	.flush_buffer = pty_flush_buffer,539	.unthrottle = pty_unthrottle,540	.set_termios = pty_set_termios,541	.cleanup = pty_cleanup,542	.resize = pty_resize,543	.start = pty_start,544	.stop = pty_stop,545	.remove = pty_remove546};547 548static void __init legacy_pty_init(void)549{550	struct tty_driver *pty_driver, *pty_slave_driver;551 552	if (legacy_count <= 0)553		return;554 555	pty_driver = tty_alloc_driver(legacy_count,556			TTY_DRIVER_RESET_TERMIOS |557			TTY_DRIVER_REAL_RAW |558			TTY_DRIVER_DYNAMIC_ALLOC);559	if (IS_ERR(pty_driver))560		panic("Couldn't allocate pty driver");561 562	pty_slave_driver = tty_alloc_driver(legacy_count,563			TTY_DRIVER_RESET_TERMIOS |564			TTY_DRIVER_REAL_RAW |565			TTY_DRIVER_DYNAMIC_ALLOC);566	if (IS_ERR(pty_slave_driver))567		panic("Couldn't allocate pty slave driver");568 569	pty_driver->driver_name = "pty_master";570	pty_driver->name = "pty";571	pty_driver->major = PTY_MASTER_MAJOR;572	pty_driver->minor_start = 0;573	pty_driver->type = TTY_DRIVER_TYPE_PTY;574	pty_driver->subtype = PTY_TYPE_MASTER;575	pty_driver->init_termios = tty_std_termios;576	pty_driver->init_termios.c_iflag = 0;577	pty_driver->init_termios.c_oflag = 0;578	pty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;579	pty_driver->init_termios.c_lflag = 0;580	pty_driver->init_termios.c_ispeed = 38400;581	pty_driver->init_termios.c_ospeed = 38400;582	pty_driver->other = pty_slave_driver;583	tty_set_operations(pty_driver, &master_pty_ops_bsd);584 585	pty_slave_driver->driver_name = "pty_slave";586	pty_slave_driver->name = "ttyp";587	pty_slave_driver->major = PTY_SLAVE_MAJOR;588	pty_slave_driver->minor_start = 0;589	pty_slave_driver->type = TTY_DRIVER_TYPE_PTY;590	pty_slave_driver->subtype = PTY_TYPE_SLAVE;591	pty_slave_driver->init_termios = tty_std_termios;592	pty_slave_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;593	pty_slave_driver->init_termios.c_ispeed = 38400;594	pty_slave_driver->init_termios.c_ospeed = 38400;595	pty_slave_driver->other = pty_driver;596	tty_set_operations(pty_slave_driver, &slave_pty_ops_bsd);597 598	if (tty_register_driver(pty_driver))599		panic("Couldn't register pty driver");600	if (tty_register_driver(pty_slave_driver))601		panic("Couldn't register pty slave driver");602}603#else604static inline void legacy_pty_init(void) { }605#endif606 607/* Unix98 devices */608#ifdef CONFIG_UNIX98_PTYS609static struct cdev ptmx_cdev;610 611/**612 *	ptm_open_peer - open the peer of a pty613 *	@master: the open struct file of the ptmx device node614 *	@tty: the master of the pty being opened615 *	@flags: the flags for open616 *617 *	Provide a race free way for userspace to open the slave end of a pty618 *	(where they have the master fd and cannot access or trust the mount619 *	namespace /dev/pts was mounted inside).620 */621int ptm_open_peer(struct file *master, struct tty_struct *tty, int flags)622{623	int fd;624	struct file *filp;625	int retval = -EINVAL;626	struct path path;627 628	if (tty->driver != ptm_driver)629		return -EIO;630 631	fd = get_unused_fd_flags(flags);632	if (fd < 0) {633		retval = fd;634		goto err;635	}636 637	/* Compute the slave's path */638	path.mnt = devpts_mntget(master, tty->driver_data);639	if (IS_ERR(path.mnt)) {640		retval = PTR_ERR(path.mnt);641		goto err_put;642	}643	path.dentry = tty->link->driver_data;644 645	filp = dentry_open(&path, flags, current_cred());646	mntput(path.mnt);647	if (IS_ERR(filp)) {648		retval = PTR_ERR(filp);649		goto err_put;650	}651 652	fd_install(fd, filp);653	return fd;654 655err_put:656	put_unused_fd(fd);657err:658	return retval;659}660 661static HWJS_SUSPENDS int pty_unix98_ioctl(struct tty_struct *tty,662			    unsigned int cmd, unsigned long arg)663{664	switch (cmd) {665	case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */666		return pty_set_lock(tty, (int __user *)arg);667	case TIOCGPTLCK: /* Get PT Lock status */668		return pty_get_lock(tty, (int __user *)arg);669	case TIOCPKT: /* Set PT packet mode */670		return pty_set_pktmode(tty, (int __user *)arg);671	case TIOCGPKT: /* Get PT packet mode */672		return pty_get_pktmode(tty, (int __user *)arg);673	case TIOCGPTN: /* Get PT Number */674		return put_user(tty->index, (unsigned int __user *)arg);675	case TIOCSIG:    /* Send signal to other side of pty */676		return pty_signal(tty, (int) arg);677	}678 679	return -ENOIOCTLCMD;680}681 682#ifdef CONFIG_COMPAT683static long pty_unix98_compat_ioctl(struct tty_struct *tty,684				 unsigned int cmd, unsigned long arg)685{686	/*687	 * PTY ioctls don't require any special translation between 32-bit and688	 * 64-bit userspace, they are already compatible.689	 */690	return pty_unix98_ioctl(tty, cmd,691		cmd == TIOCSIG ? arg : (unsigned long)compat_ptr(arg));692}693#else694#define pty_unix98_compat_ioctl NULL695#endif696 697/**698 *	ptm_unix98_lookup	-	find a pty master699 *	@driver: ptm driver700 *	@file: unused701 *	@idx: tty index702 *703 *	Look up a pty master device. Called under the tty_mutex for now.704 *	This provides our locking.705 */706 707static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver,708		struct file *file, int idx)709{710	/* Master must be open via /dev/ptmx */711	return ERR_PTR(-EIO);712}713 714/**715 *	pts_unix98_lookup	-	find a pty slave716 *	@driver: pts driver717 *	@file: file pointer to tty718 *	@idx: tty index719 *720 *	Look up a pty master device. Called under the tty_mutex for now.721 *	This provides our locking for the tty pointer.722 */723 724static HWJS_SUSPENDS struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,725		struct file *file, int idx)726{727	struct tty_struct *tty;728 729	mutex_lock(&devpts_mutex);730	tty = devpts_get_priv(file->f_path.dentry);731	mutex_unlock(&devpts_mutex);732	/* Master must be open before slave */733	if (!tty)734		return ERR_PTR(-EIO);735	return tty;736}737 738static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)739{740	return pty_common_install(driver, tty, false);741}742 743/* this is called once with whichever end is closed last */744static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)745{746	struct pts_fs_info *fsi;747 748	if (tty->driver->subtype == PTY_TYPE_MASTER)749		fsi = tty->driver_data;750	else751		fsi = tty->link->driver_data;752 753	if (fsi) {754		devpts_kill_index(fsi, tty->index);755		devpts_release(fsi);756	}757}758 759static void pty_show_fdinfo(struct tty_struct *tty, struct seq_file *m)760{761	seq_printf(m, "tty-index:\t%d\n", tty->index);762}763 764static const struct tty_operations ptm_unix98_ops = {765	.lookup = ptm_unix98_lookup,766	.install = pty_unix98_install,767	.remove = pty_unix98_remove,768	.open = pty_open,769	.close = pty_close,770	.write = pty_write,771	.write_room = pty_write_room,772	.flush_buffer = pty_flush_buffer,773	.unthrottle = pty_unthrottle,774	.ioctl = pty_unix98_ioctl,775	.compat_ioctl = pty_unix98_compat_ioctl,776	.resize = pty_resize,777	.cleanup = pty_cleanup,778	.show_fdinfo = pty_show_fdinfo,779};780 781static const struct tty_operations pty_unix98_ops = {782	.lookup = pts_unix98_lookup,783	.install = pty_unix98_install,784	.remove = pty_unix98_remove,785	.open = pty_open,786	.close = pty_close,787	.write = pty_write,788	.write_room = pty_write_room,789	.flush_buffer = pty_flush_buffer,790	.unthrottle = pty_unthrottle,791	.set_termios = pty_set_termios,792	.start = pty_start,793	.stop = pty_stop,794	.cleanup = pty_cleanup,795};796 797/**798 *	ptmx_open		-	open a unix 98 pty master799 *	@inode: inode of device file800 *	@filp: file pointer to tty801 *802 *	Allocate a unix98 pty master device from the ptmx driver.803 *804 *	Locking: tty_mutex protects the init_dev work. tty->count should805 *		protect the rest.806 *		allocated_ptys_lock handles the list of free pty numbers807 */808 809static HWJS_SUSPENDS int ptmx_open(struct inode *inode, struct file *filp)810{811	struct pts_fs_info *fsi;812	struct tty_struct *tty;813	struct dentry *dentry;814	int retval;815	int index;816 817	nonseekable_open(inode, filp);818 819	/* We refuse fsnotify events on ptmx, since it's a shared resource */820	filp->f_mode |= FMODE_NONOTIFY;821 822	retval = tty_alloc_file(filp);823	if (retval)824		return retval;825 826	fsi = devpts_acquire(filp);827	if (IS_ERR(fsi)) {828		retval = PTR_ERR(fsi);829		goto out_free_file;830	}831 832	/* find a device that is not in use. */833	mutex_lock(&devpts_mutex);834	index = devpts_new_index(fsi);835	mutex_unlock(&devpts_mutex);836 837	retval = index;838	if (index < 0)839		goto out_put_fsi;840 841 842	mutex_lock(&tty_mutex);843	tty = tty_init_dev(ptm_driver, index);844	/* The tty returned here is locked so we can safely845	   drop the mutex */846	mutex_unlock(&tty_mutex);847 848	retval = PTR_ERR(tty);849	if (IS_ERR(tty))850		goto out;851 852	/*853	 * From here on out, the tty is "live", and the index and854	 * fsi will be killed/put by the tty_release()855	 */856	set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */857	tty->driver_data = fsi;858 859	tty_add_file(tty, filp);860 861	dentry = devpts_pty_new(fsi, index, tty->link);862	if (IS_ERR(dentry)) {863		retval = PTR_ERR(dentry);864		goto err_release;865	}866	tty->link->driver_data = dentry;867 868	retval = ptm_driver->ops->open(tty, filp);869	if (retval)870		goto err_release;871 872	tty_debug_hangup(tty, "opening (count=%d)\n", tty->count);873 874	tty_unlock(tty);875	return 0;876err_release:877	tty_unlock(tty);878	// This will also put-ref the fsi879	tty_release(inode, filp);880	return retval;881out:882	devpts_kill_index(fsi, index);883out_put_fsi:884	devpts_release(fsi);885out_free_file:886	tty_free_file(filp);887	return retval;888}889 890static struct file_operations ptmx_fops __ro_after_init;891 892static HWJS_SUSPENDS void __init unix98_pty_init(void)893{894	ptm_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX,895			TTY_DRIVER_RESET_TERMIOS |896			TTY_DRIVER_REAL_RAW |897			TTY_DRIVER_DYNAMIC_DEV |898			TTY_DRIVER_DEVPTS_MEM |899			TTY_DRIVER_DYNAMIC_ALLOC);900	if (IS_ERR(ptm_driver))901		panic("Couldn't allocate Unix98 ptm driver");902	pts_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX,903			TTY_DRIVER_RESET_TERMIOS |904			TTY_DRIVER_REAL_RAW |905			TTY_DRIVER_DYNAMIC_DEV |906			TTY_DRIVER_DEVPTS_MEM |907			TTY_DRIVER_DYNAMIC_ALLOC);908	if (IS_ERR(pts_driver))909		panic("Couldn't allocate Unix98 pts driver");910 911	ptm_driver->driver_name = "pty_master";912	ptm_driver->name = "ptm";913	ptm_driver->major = UNIX98_PTY_MASTER_MAJOR;914	ptm_driver->minor_start = 0;915	ptm_driver->type = TTY_DRIVER_TYPE_PTY;916	ptm_driver->subtype = PTY_TYPE_MASTER;917	ptm_driver->init_termios = tty_std_termios;918	ptm_driver->init_termios.c_iflag = 0;919	ptm_driver->init_termios.c_oflag = 0;920	ptm_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;921	ptm_driver->init_termios.c_lflag = 0;922	ptm_driver->init_termios.c_ispeed = 38400;923	ptm_driver->init_termios.c_ospeed = 38400;924	ptm_driver->other = pts_driver;925	tty_set_operations(ptm_driver, &ptm_unix98_ops);926 927	pts_driver->driver_name = "pty_slave";928	pts_driver->name = "pts";929	pts_driver->major = UNIX98_PTY_SLAVE_MAJOR;930	pts_driver->minor_start = 0;931	pts_driver->type = TTY_DRIVER_TYPE_PTY;932	pts_driver->subtype = PTY_TYPE_SLAVE;933	pts_driver->init_termios = tty_std_termios;934	pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;935	pts_driver->init_termios.c_ispeed = 38400;936	pts_driver->init_termios.c_ospeed = 38400;937	pts_driver->other = ptm_driver;938	tty_set_operations(pts_driver, &pty_unix98_ops);939 940	if (tty_register_driver(ptm_driver))941		panic("Couldn't register Unix98 ptm driver");942	if (tty_register_driver(pts_driver))943		panic("Couldn't register Unix98 pts driver");944 945	/* Now create the /dev/ptmx special device */946	tty_default_fops(&ptmx_fops);947	ptmx_fops.open = ptmx_open;948 949	cdev_init(&ptmx_cdev, &ptmx_fops);950	if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||951	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)952		panic("Couldn't register /dev/ptmx driver");953	device_create(&tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");954}955 956#else957static inline void unix98_pty_init(void) { }958#endif959 960static int __init pty_init(void)961{962	legacy_pty_init();963	unix98_pty_init();964	return 0;965}966device_initcall(pty_init);967