Beispiel #1
0
void tty_wait_until_sent(struct tty_struct * tty, long timeout)
{
	DECLARE_WAITQUEUE(wait, current);

#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
	char buf[64];
	
	printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
#endif
	if (!tty->driver->chars_in_buffer)
		return;
	add_wait_queue(&tty->write_wait, &wait);
	if (!timeout)
		timeout = MAX_SCHEDULE_TIMEOUT;
	do {
#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
		printk(KERN_DEBUG "waiting %s...(%d)\n", tty_name(tty, buf),
		       tty->driver->chars_in_buffer(tty));
#endif
		set_current_state(TASK_INTERRUPTIBLE);
		if (signal_pending(current))
			goto stop_waiting;
		if (!tty->driver->chars_in_buffer(tty))
			break;
		timeout = schedule_timeout(timeout);
	} while (timeout);
	if (tty->driver->wait_until_sent)
		tty->driver->wait_until_sent(tty, timeout);
stop_waiting:
	set_current_state(TASK_RUNNING);
	remove_wait_queue(&tty->write_wait, &wait);
}
Beispiel #2
0
static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, unsigned char __user * buf, size_t nr)
{
	struct serport *serport = (struct serport*) tty->disc_data;
	struct serio *serio;
	char name[64];

	if (test_and_set_bit(SERPORT_BUSY, &serport->flags))
		return -EBUSY;

	serport->serio = serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
	if (!serio)
		return -ENOMEM;

	strlcpy(serio->name, "Serial port", sizeof(serio->name));
	snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty, name));
	serio->id = serport->id;
	serio->id.type = SERIO_RS232;
	serio->write = serport_serio_write;
	serio->open = serport_serio_open;
	serio->close = serport_serio_close;
	serio->port_data = serport;
	serio->dev.parent = tty->dev;

	serio_register_port(serport->serio);
	printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));

	wait_event_interruptible(serport->wait, test_bit(SERPORT_DEAD, &serport->flags));
	serio_unregister_port(serport->serio);
	serport->serio = NULL;

	clear_bit(SERPORT_DEAD, &serport->flags);
	clear_bit(SERPORT_BUSY, &serport->flags);

	return 0;
}
static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
{
	char buf[64];
	struct tty_ldisc *new_ldisc;
	int r;

	/* There is an outstanding reference here so this is safe */
	old = tty_ldisc_get(tty, old->ops->num);
	WARN_ON(IS_ERR(old));
	tty->ldisc = old;
	tty_set_termios_ldisc(tty, old->ops->num);
	if (tty_ldisc_open(tty, old) < 0) {
		tty_ldisc_put(old);
		/* This driver is always present */
		new_ldisc = tty_ldisc_get(tty, N_TTY);
		if (IS_ERR(new_ldisc))
			panic("n_tty: get");
		tty->ldisc = new_ldisc;
		tty_set_termios_ldisc(tty, N_TTY);
		r = tty_ldisc_open(tty, new_ldisc);
		if (r < 0)
			panic("Couldn't open N_TTY ldisc for "
			      "%s --- error %d.",
			      tty_name(tty, buf), r);
	}
}
Beispiel #4
0
static int serport_ldisc_open(struct tty_struct *tty)
{
	struct serport *serport;
	struct serio *serio;
	char name[64];

	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;

	serport = kmalloc(sizeof(struct serport), GFP_KERNEL);
	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
	if (unlikely(!serport || !serio)) {
		kfree(serport);
		kfree(serio);
		return -ENOMEM;
	}

	memset(serport, 0, sizeof(struct serport));
	serport->serio = serio;
	set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
	serport->tty = tty;
	tty->disc_data = serport;

	memset(serio, 0, sizeof(struct serio));
	strlcpy(serio->name, "Serial port", sizeof(serio->name));
	snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty, name));
	serio->type = SERIO_RS232;
	serio->write = serport_serio_write;
	serio->close = serport_serio_close;
	serio->port_data = serport;

	init_waitqueue_head(&serport->wait);

	return 0;
}
Beispiel #5
0
static void rs_unthrottle(struct tty_struct * tty)
{
	struct serial_state *info = tty->driver_data;
	unsigned long flags;
#ifdef SERIAL_DEBUG_THROTTLE
	char	buf[64];

	printk("unthrottle %s: %d....\n", tty_name(tty, buf),
	       tty->ldisc.chars_in_buffer(tty));
#endif

	if (serial_paranoia_check(info, tty->name, "rs_unthrottle"))
		return;

	if (I_IXOFF(tty)) {
		if (info->x_char)
			info->x_char = 0;
		else
			rs_send_xchar(tty, START_CHAR(tty));
	}
	if (tty->termios->c_cflag & CRTSCTS)
		info->MCR |= SER_RTS;
	local_irq_save(flags);
	rtsdtr_ctrl(info->MCR);
	local_irq_restore(flags);
}
Beispiel #6
0
static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
{
	char buf[64];
	struct tty_ldisc new_ldisc;

	/* There is an outstanding reference here so this is safe */
	tty_ldisc_get(old->ops->num, old);
	tty_ldisc_assign(tty, old);
	tty_set_termios_ldisc(tty, old->ops->num);
	if (old->ops->open && (old->ops->open(tty) < 0)) {
		tty_ldisc_put(old->ops);
		/* This driver is always present */
		if (tty_ldisc_get(N_TTY, &new_ldisc) < 0)
			panic("n_tty: get");
		tty_ldisc_assign(tty, &new_ldisc);
		tty_set_termios_ldisc(tty, N_TTY);
		if (new_ldisc.ops->open) {
			int r = new_ldisc.ops->open(tty);
				if (r < 0)
				panic("Couldn't open N_TTY ldisc for "
				      "%s --- error %d.",
				      tty_name(tty, buf), r);
		}
	}
}
static int serport_ldisc_open(struct tty_struct *tty)
{
	struct serport *serport;
	char name[64];

	serport = kmalloc(sizeof(struct serport), GFP_KERNEL);
	if (unlikely(!serport))
		return -ENOMEM;
	memset(serport, 0, sizeof(struct serport));

	set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
	serport->tty = tty;
	tty->disc_data = serport;

	snprintf(serport->phys, sizeof(serport->phys), "%s/serio0", tty_name(tty, name));

	serport->serio.name = serport_name;
	serport->serio.phys = serport->phys;

	serport->serio.type = SERIO_RS232;
	serport->serio.write = serport_serio_write;
	serport->serio.close = serport_serio_close;
	serport->serio.driver = serport;

	init_waitqueue_head(&serport->wait);

	return 0;
}
Beispiel #8
0
static inline void n_tty_receive_overrun(struct tty_struct *tty)
{
	char buf[64];

	tty->num_overrun++;
	if (time_before(tty->overrun_time, jiffies - HZ)) {
		printk("%s: %d input overrun(s)\n", tty_name(tty, buf),
		       tty->num_overrun);
		tty->overrun_time = jiffies;
		tty->num_overrun = 0;
	}
}
/*
 * Throttle characters as directed by upper tty layer
 */
static void rs_throttle(struct tty_struct * tty)
{
#ifdef TX3912_UART_DEBUG_THROTTLE
    char	buf[64];

    printk("throttle %s: %d....\n", tty_name(tty, buf),
           tty->ldisc.chars_in_buffer(tty));
#endif

    func_enter();

    if (I_IXOFF(tty))
        rs_send_xchar(tty, STOP_CHAR(tty));

    func_exit();
}
static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, unsigned char __user * buf, size_t nr)
{
	struct serport *serport = (struct serport*) tty->disc_data;
	char name[64];

	if (test_and_set_bit(SERPORT_BUSY, &serport->flags))
		return -EBUSY;

	serio_register_port(&serport->serio);
	printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));
	wait_event_interruptible(serport->wait, !serport->serio.type);
	serio_unregister_port(&serport->serio);

	clear_bit(SERPORT_BUSY, &serport->flags);

	return 0;
}
/*
 * ------------------------------------------------------------
 * mcfrs_throttle()
 * 
 * This routine is called by the upper-layer tty layer to signal that
 * incoming characters should be throttled.
 * ------------------------------------------------------------
 */
static void mcfrs_throttle(struct tty_struct * tty)
{
	struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
#ifdef SERIAL_DEBUG_THROTTLE
	char	buf[64];
	
	printk("throttle %s: %d....\n", tty_name(tty, buf),
	       tty->ldisc.chars_in_buffer(tty));
#endif

	if (serial_paranoia_check(info, tty->name, "mcfrs_throttle"))
		return;
	
	if (I_IXOFF(tty))
		info->x_char = STOP_CHAR(tty);

	/* Turn off RTS line (do this atomic) */
}
/*
 * Un-throttle characters as directed by upper tty layer
 */
static void rs_unthrottle(struct tty_struct * tty)
{
#ifdef TX3912_UART_DEBUG_THROTTLE
    char	buf[64];

    printk("unthrottle %s: %d....\n", tty_name(tty, buf),
           tty->ldisc.chars_in_buffer(tty));
#endif

    func_enter();

    if (I_IXOFF(tty)) {
        if (rs_port->x_char)
            rs_port->x_char = 0;
        else
            rs_send_xchar(tty, START_CHAR(tty));
    }

    func_exit();
}
Beispiel #13
0
/*
 * ------------------------------------------------------------
 * rs_throttle()
 * 
 * This routine is called by the upper-layer tty layer to signal that
 * incoming characters should be throttled.
 * ------------------------------------------------------------
 */
static void rs_throttle(struct tty_struct * tty)
{
	struct serial_state *info = tty->driver_data;
	unsigned long flags;
#ifdef SERIAL_DEBUG_THROTTLE
	printk("throttle %s ....\n", tty_name(tty));
#endif

	if (serial_paranoia_check(info, tty->name, "rs_throttle"))
		return;

	if (I_IXOFF(tty))
		rs_send_xchar(tty, STOP_CHAR(tty));

	if (C_CRTSCTS(tty))
		info->MCR &= ~SER_RTS;

	local_irq_save(flags);
	rtsdtr_ctrl(info->MCR);
	local_irq_restore(flags);
}
Beispiel #14
0
void gr_log_varargs(int audit, const char *msg, int argtypes, ...)
{
	int logtype;
	char *result = (audit == GR_DO_AUDIT) ? "successful" : "denied";
	char *str1, *str2, *str3;
	int num1, num2;
	unsigned long ulong1, ulong2;
	struct dentry *dentry;
	struct vfsmount *mnt;
	struct file *file;
	struct task_struct *task;
	va_list ap;

	BEGIN_LOCKS(audit);
	logtype = gr_log_start(audit);
	if (logtype == FLOODING) {
		END_LOCKS(audit);
		return;
	}
	va_start(ap, argtypes);
	switch (argtypes) {
	case GR_TTYSNIFF:
		task = va_arg(ap, struct task_struct *);
		gr_log_middle_varargs(audit, msg, NIPQUAD(task->signal->curr_ip), gr_task_fullpath0(task), task->comm, task->pid, gr_parent_task_fullpath0(task), task->parent->comm, task->parent->pid);
		break;
	case GR_SYSCTL_HIDDEN:
		str1 = va_arg(ap, char *);
		gr_log_middle_varargs(audit, msg, result, str1);
		break;
	case GR_RBAC:
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt));
		break;
	case GR_RBAC_STR:
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		str1 = va_arg(ap, char *);
		gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1);
		break;
	case GR_STR_RBAC:
		str1 = va_arg(ap, char *);
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		gr_log_middle_varargs(audit, msg, result, str1, gr_to_filename(dentry, mnt));
		break;
	case GR_RBAC_MODE2:
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		str1 = va_arg(ap, char *);
		str2 = va_arg(ap, char *);
		gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1, str2);
		break;
	case GR_RBAC_MODE3:
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		str1 = va_arg(ap, char *);
		str2 = va_arg(ap, char *);
		str3 = va_arg(ap, char *);
		gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1, str2, str3);
		break;
	case GR_FILENAME:
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt));
		break;
	case GR_STR_FILENAME:
		str1 = va_arg(ap, char *);
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		gr_log_middle_varargs(audit, msg, str1, gr_to_filename(dentry, mnt));
		break;
	case GR_FILENAME_STR:
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		str1 = va_arg(ap, char *);
		gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), str1);
		break;
	case GR_FILENAME_TWO_INT:
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		num1 = va_arg(ap, int);
		num2 = va_arg(ap, int);
		gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), num1, num2);
		break;
	case GR_FILENAME_TWO_INT_STR:
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		num1 = va_arg(ap, int);
		num2 = va_arg(ap, int);
		str1 = va_arg(ap, char *);
		gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), num1, num2, str1);
		break;
	case GR_TEXTREL:
		file = va_arg(ap, struct file *);
		ulong1 = va_arg(ap, unsigned long);
		ulong2 = va_arg(ap, unsigned long);
		gr_log_middle_varargs(audit, msg, file ? gr_to_filename(file->f_path.dentry, file->f_path.mnt) : "<anonymous mapping>", ulong1, ulong2);
		break;
	case GR_PTRACE:
		task = va_arg(ap, struct task_struct *);
		gr_log_middle_varargs(audit, msg, task->exec_file ? gr_to_filename(task->exec_file->f_path.dentry, task->exec_file->f_path.mnt) : "(none)", task->comm, task->pid);
		break;
	case GR_RESOURCE:
		task = va_arg(ap, struct task_struct *);
		ulong1 = va_arg(ap, unsigned long);
		str1 = va_arg(ap, char *);
		ulong2 = va_arg(ap, unsigned long);
		gr_log_middle_varargs(audit, msg, ulong1, str1, ulong2, gr_task_fullpath(task), task->comm, task->pid, task->uid, task->euid, task->gid, task->egid, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, task->parent->uid, task->parent->euid, task->parent->gid, task->parent->egid);
		break;
	case GR_CAP:
		task = va_arg(ap, struct task_struct *);
		str1 = va_arg(ap, char *);
		gr_log_middle_varargs(audit, msg, str1, gr_task_fullpath(task), task->comm, task->pid, task->uid, task->euid, task->gid, task->egid, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, task->parent->uid, task->parent->euid, task->parent->gid, task->parent->egid);
		break;
	case GR_SIG:
		task = va_arg(ap, struct task_struct *);
		num1 = va_arg(ap, int);
		gr_log_middle_varargs(audit, msg, num1, gr_task_fullpath0(task), task->comm, task->pid, task->uid, task->euid, task->gid, task->egid, gr_parent_task_fullpath0(task), task->parent->comm, task->parent->pid, task->parent->uid, task->parent->euid, task->parent->gid, task->parent->egid);
		break;
	case GR_CRASH1:
		task = va_arg(ap, struct task_struct *);
		ulong1 = va_arg(ap, unsigned long);
		gr_log_middle_varargs(audit, msg, gr_task_fullpath(task), task->comm, task->pid, task->uid, task->euid, task->gid, task->egid, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, task->parent->uid, task->parent->euid, task->parent->gid, task->parent->egid, task->uid, ulong1);
		break;
	case GR_CRASH2:
		task = va_arg(ap, struct task_struct *);
		ulong1 = va_arg(ap, unsigned long);
		gr_log_middle_varargs(audit, msg, gr_task_fullpath(task), task->comm, task->pid, task->uid, task->euid, task->gid, task->egid, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, task->parent->uid, task->parent->euid, task->parent->gid, task->parent->egid, ulong1);
		break;
	case GR_PSACCT:
		{
			unsigned int wday, cday;
			__u8 whr, chr;
			__u8 wmin, cmin;
			__u8 wsec, csec;
			char cur_tty[64] = { 0 };
			char parent_tty[64] = { 0 };

			task = va_arg(ap, struct task_struct *);
			wday = va_arg(ap, unsigned int);
			cday = va_arg(ap, unsigned int);
			whr = va_arg(ap, int);
			chr = va_arg(ap, int);
			wmin = va_arg(ap, int);
			cmin = va_arg(ap, int);
			wsec = va_arg(ap, int);
			csec = va_arg(ap, int);
			ulong1 = va_arg(ap, unsigned long);

			gr_log_middle_varargs(audit, msg, gr_task_fullpath(task), task->comm, task->pid, NIPQUAD(task->signal->curr_ip), tty_name(task->signal->tty, cur_tty), task->uid, task->euid, task->gid, task->egid, wday, whr, wmin, wsec, cday, chr, cmin, csec, (task->flags & PF_SIGNALED) ? "killed by signal" : "exited", ulong1, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, NIPQUAD(task->parent->signal->curr_ip), tty_name(task->parent->signal->tty, parent_tty), task->parent->uid, task->parent->euid, task->parent->gid, task->parent->egid);
		}
		break;
	default:
		gr_log_middle(audit, msg, ap);
	}
	va_end(ap);
	gr_log_end(audit);
	END_LOCKS(audit);
}
Beispiel #15
0
static int uart_set_info(struct tty_struct *tty, struct uart_state *state,
			 struct serial_struct __user *newinfo)
{
	struct serial_struct new_serial;
	struct uart_port *uport = state->uart_port;
	struct tty_port *port = &state->port;
	unsigned long new_port;
	unsigned int change_irq, change_port, closing_wait;
	unsigned int old_custom_divisor, close_delay;
	upf_t old_flags, new_flags;
	int retval = 0;

	if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
		return -EFAULT;

	new_port = new_serial.port;
	if (HIGH_BITS_OFFSET)
		new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;

	new_serial.irq = irq_canonicalize(new_serial.irq);
	close_delay = msecs_to_jiffies(new_serial.close_delay * 10);
	closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
			ASYNC_CLOSING_WAIT_NONE :
			msecs_to_jiffies(new_serial.closing_wait * 10);

	mutex_lock(&port->mutex);

	change_irq  = !(uport->flags & UPF_FIXED_PORT)
		&& new_serial.irq != uport->irq;

	change_port = !(uport->flags & UPF_FIXED_PORT)
		&& (new_port != uport->iobase ||
		    (unsigned long)new_serial.iomem_base != uport->mapbase ||
		    new_serial.hub6 != uport->hub6 ||
		    new_serial.io_type != uport->iotype ||
		    new_serial.iomem_reg_shift != uport->regshift ||
		    new_serial.type != uport->type);

	old_flags = uport->flags;
	new_flags = new_serial.flags;
	old_custom_divisor = uport->custom_divisor;

	if (!capable(CAP_SYS_ADMIN)) {
		retval = -EPERM;
		if (change_irq || change_port ||
		    (new_serial.baud_base != uport->uartclk / 16) ||
		    (close_delay != port->close_delay) ||
		    (closing_wait != port->closing_wait) ||
		    (new_serial.xmit_fifo_size &&
		     new_serial.xmit_fifo_size != uport->fifosize) ||
		    (((new_flags ^ old_flags) & ~UPF_USR_MASK) != 0))
			goto exit;
		uport->flags = ((uport->flags & ~UPF_USR_MASK) |
			       (new_flags & UPF_USR_MASK));
		uport->custom_divisor = new_serial.custom_divisor;
		goto check_and_exit;
	}

	if (uport->ops->verify_port)
		retval = uport->ops->verify_port(uport, &new_serial);

	if ((new_serial.irq >= nr_irqs) || (new_serial.irq < 0) ||
	    (new_serial.baud_base < 9600))
		retval = -EINVAL;

	if (retval)
		goto exit;

	if (change_port || change_irq) {
		retval = -EBUSY;

		if (tty_port_users(port) > 1)
			goto exit;

		uart_shutdown(tty, state);
	}

	if (change_port) {
		unsigned long old_iobase, old_mapbase;
		unsigned int old_type, old_iotype, old_hub6, old_shift;

		old_iobase = uport->iobase;
		old_mapbase = uport->mapbase;
		old_type = uport->type;
		old_hub6 = uport->hub6;
		old_iotype = uport->iotype;
		old_shift = uport->regshift;

		if (old_type != PORT_UNKNOWN)
			uport->ops->release_port(uport);

		uport->iobase = new_port;
		uport->type = new_serial.type;
		uport->hub6 = new_serial.hub6;
		uport->iotype = new_serial.io_type;
		uport->regshift = new_serial.iomem_reg_shift;
		uport->mapbase = (unsigned long)new_serial.iomem_base;

		if (uport->type != PORT_UNKNOWN) {
			retval = uport->ops->request_port(uport);
		} else {
			
			retval = 0;
		}

		if (retval && old_type != PORT_UNKNOWN) {
			uport->iobase = old_iobase;
			uport->type = old_type;
			uport->hub6 = old_hub6;
			uport->iotype = old_iotype;
			uport->regshift = old_shift;
			uport->mapbase = old_mapbase;
			retval = uport->ops->request_port(uport);
			if (retval)
				uport->type = PORT_UNKNOWN;

			retval = -EBUSY;
			
			goto exit;
		}
	}

	if (change_irq)
		uport->irq      = new_serial.irq;
	if (!(uport->flags & UPF_FIXED_PORT))
		uport->uartclk  = new_serial.baud_base * 16;
	uport->flags            = (uport->flags & ~UPF_CHANGE_MASK) |
				 (new_flags & UPF_CHANGE_MASK);
	uport->custom_divisor   = new_serial.custom_divisor;
	port->close_delay     = close_delay;
	port->closing_wait    = closing_wait;
	if (new_serial.xmit_fifo_size)
		uport->fifosize = new_serial.xmit_fifo_size;
	if (port->tty)
		port->tty->low_latency =
			(uport->flags & UPF_LOW_LATENCY) ? 1 : 0;

 check_and_exit:
	retval = 0;
	if (uport->type == PORT_UNKNOWN)
		goto exit;
	if (port->flags & ASYNC_INITIALIZED) {
		if (((old_flags ^ uport->flags) & UPF_SPD_MASK) ||
		    old_custom_divisor != uport->custom_divisor) {
			if (uport->flags & UPF_SPD_MASK) {
				char buf[64];
				printk(KERN_NOTICE
				       "%s sets custom speed on %s. This "
				       "is deprecated.\n", current->comm,
				       tty_name(port->tty, buf));
			}
			uart_change_speed(tty, state, NULL);
		}
	} else
		retval = uart_startup(tty, state, 1);
 exit:
	mutex_unlock(&port->mutex);
	return retval;
}
static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
			      char *fp, int count)
{
	const unsigned char *p;
	char *f, flags = TTY_NORMAL;
	int	i;
	char	buf[64];
	unsigned long cpuflags;

	if (!tty->read_buf)
		return;

	if (tty->real_raw) {
		spin_lock_irqsave(&tty->read_lock, cpuflags);
		i = min(N_TTY_BUF_SIZE - tty->read_cnt,
			N_TTY_BUF_SIZE - tty->read_head);
		i = min(count, i);
		memcpy(tty->read_buf + tty->read_head, cp, i);
		tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
		tty->read_cnt += i;
		cp += i;
		count -= i;

		i = min(N_TTY_BUF_SIZE - tty->read_cnt,
			N_TTY_BUF_SIZE - tty->read_head);
		i = min(count, i);
		memcpy(tty->read_buf + tty->read_head, cp, i);
		tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
		tty->read_cnt += i;
		spin_unlock_irqrestore(&tty->read_lock, cpuflags);
	} else {
		for (i = count, p = cp, f = fp; i; i--, p++) {
			if (f)
				flags = *f++;
			switch (flags) {
			case TTY_NORMAL:
				n_tty_receive_char(tty, *p);
				break;
			case TTY_BREAK:
				n_tty_receive_break(tty);
				break;
			case TTY_PARITY:
			case TTY_FRAME:
				n_tty_receive_parity_error(tty, *p);
				break;
			case TTY_OVERRUN:
				n_tty_receive_overrun(tty);
				break;
			default:
				printk(KERN_ERR "%s: unknown flag %d\n",
				       tty_name(tty, buf), flags);
				break;
			}
		}
		if (tty->ops->flush_chars)
			tty->ops->flush_chars(tty);
	}

	n_tty_set_room(tty);

	if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) ||
		L_EXTPROC(tty)) {
		kill_fasync(&tty->fasync, SIGIO, POLL_IN);
		if (waitqueue_active(&tty->read_wait))
			wake_up_interruptible(&tty->read_wait);
	}

	if (tty->receive_room < TTY_THRESHOLD_THROTTLE)
		tty_throttle(tty);
}
Beispiel #17
0
void gr_log_varargs(int audit, const char *msg, int argtypes, ...)
{
	int logtype;
	char *result = (audit == GR_DO_AUDIT) ? "successful" : "denied";
	char *str1 = NULL, *str2 = NULL, *str3 = NULL;
	void *voidptr = NULL;
	int num1 = 0, num2 = 0;
	unsigned long ulong1 = 0, ulong2 = 0;
	struct dentry *dentry = NULL;
	struct vfsmount *mnt = NULL;
	struct file *file = NULL;
	struct task_struct *task = NULL;
	struct vm_area_struct *vma = NULL;
	const struct cred *cred, *pcred;
	va_list ap;

	BEGIN_LOCKS(audit);
	logtype = gr_log_start(audit);
	if (logtype == FLOODING) {
		END_LOCKS(audit);
		return;
	}
	va_start(ap, argtypes);
	switch (argtypes) {
	case GR_TTYSNIFF:
		task = va_arg(ap, struct task_struct *);
		gr_log_middle_varargs(audit, msg, &task->signal->curr_ip, gr_task_fullpath0(task), task->comm, task_pid_nr(task), gr_parent_task_fullpath0(task), task->real_parent->comm, task_pid_nr(task->real_parent));
		break;
	case GR_SYSCTL_HIDDEN:
		str1 = va_arg(ap, char *);
		gr_log_middle_varargs(audit, msg, result, str1);
		break;
	case GR_RBAC:
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt));
		break;
	case GR_RBAC_STR:
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		str1 = va_arg(ap, char *);
		gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1);
		break;
	case GR_STR_RBAC:
		str1 = va_arg(ap, char *);
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		gr_log_middle_varargs(audit, msg, result, str1, gr_to_filename(dentry, mnt));
		break;
	case GR_RBAC_MODE2:
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		str1 = va_arg(ap, char *);
		str2 = va_arg(ap, char *);
		gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1, str2);
		break;
	case GR_RBAC_MODE3:
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		str1 = va_arg(ap, char *);
		str2 = va_arg(ap, char *);
		str3 = va_arg(ap, char *);
		gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1, str2, str3);
		break;
	case GR_FILENAME:
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt));
		break;
	case GR_STR_FILENAME:
		str1 = va_arg(ap, char *);
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		gr_log_middle_varargs(audit, msg, str1, gr_to_filename(dentry, mnt));
		break;
	case GR_FILENAME_STR:
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		str1 = va_arg(ap, char *);
		gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), str1);
		break;
	case GR_FILENAME_TWO_INT:
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		num1 = va_arg(ap, int);
		num2 = va_arg(ap, int);
		gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), num1, num2);
		break;
	case GR_FILENAME_TWO_INT_STR:
		dentry = va_arg(ap, struct dentry *);
		mnt = va_arg(ap, struct vfsmount *);
		num1 = va_arg(ap, int);
		num2 = va_arg(ap, int);
		str1 = va_arg(ap, char *);
		gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), num1, num2, str1);
		break;
	case GR_TEXTREL:
		file = va_arg(ap, struct file *);
		ulong1 = va_arg(ap, unsigned long);
		ulong2 = va_arg(ap, unsigned long);
		gr_log_middle_varargs(audit, msg, file ? gr_to_filename(file->f_path.dentry, file->f_path.mnt) : "<anonymous mapping>", ulong1, ulong2);
		break;
	case GR_PTRACE:
		task = va_arg(ap, struct task_struct *);
		gr_log_middle_varargs(audit, msg, task->exec_file ? gr_to_filename(task->exec_file->f_path.dentry, task->exec_file->f_path.mnt) : "(none)", task->comm, task_pid_nr(task));
		break;
	case GR_RESOURCE:
		task = va_arg(ap, struct task_struct *);
		cred = __task_cred(task);
		pcred = __task_cred(task->real_parent);
		ulong1 = va_arg(ap, unsigned long);
		str1 = va_arg(ap, char *);
		ulong2 = va_arg(ap, unsigned long);
		gr_log_middle_varargs(audit, msg, ulong1, str1, ulong2, gr_task_fullpath(task), task->comm, task_pid_nr(task), GR_GLOBAL_UID(cred->uid), GR_GLOBAL_UID(cred->euid), GR_GLOBAL_GID(cred->gid), GR_GLOBAL_GID(cred->egid), gr_parent_task_fullpath(task), task->real_parent->comm, task_pid_nr(task->real_parent), GR_GLOBAL_UID(pcred->uid), GR_GLOBAL_UID(pcred->euid), GR_GLOBAL_GID(pcred->gid), GR_GLOBAL_GID(pcred->egid));
		break;
	case GR_CAP:
		task = va_arg(ap, struct task_struct *);
		cred = __task_cred(task);
		pcred = __task_cred(task->real_parent);
		str1 = va_arg(ap, char *);
		gr_log_middle_varargs(audit, msg, str1, gr_task_fullpath(task), task->comm, task_pid_nr(task), GR_GLOBAL_UID(cred->uid), GR_GLOBAL_UID(cred->euid), GR_GLOBAL_GID(cred->gid), GR_GLOBAL_GID(cred->egid), gr_parent_task_fullpath(task), task->real_parent->comm, task_pid_nr(task->real_parent), GR_GLOBAL_UID(pcred->uid), GR_GLOBAL_UID(pcred->euid), GR_GLOBAL_GID(pcred->gid), GR_GLOBAL_GID(pcred->egid));
		break;
	case GR_SIG:
		str1 = va_arg(ap, char *);
		voidptr = va_arg(ap, void *);
		gr_log_middle_varargs(audit, msg, str1, voidptr);
		break;
	case GR_SIG2:
		task = va_arg(ap, struct task_struct *);
		cred = __task_cred(task);
		pcred = __task_cred(task->real_parent);
		num1 = va_arg(ap, int);
		gr_log_middle_varargs(audit, msg, num1, gr_task_fullpath0(task), task->comm, task_pid_nr(task), GR_GLOBAL_UID(cred->uid), GR_GLOBAL_UID(cred->euid), GR_GLOBAL_GID(cred->gid), GR_GLOBAL_GID(cred->egid), gr_parent_task_fullpath0(task), task->real_parent->comm, task_pid_nr(task->real_parent), GR_GLOBAL_UID(pcred->uid), GR_GLOBAL_UID(pcred->euid), GR_GLOBAL_GID(pcred->gid), GR_GLOBAL_GID(pcred->egid));
		break;
	case GR_CRASH1:
		task = va_arg(ap, struct task_struct *);
		cred = __task_cred(task);
		pcred = __task_cred(task->real_parent);
		ulong1 = va_arg(ap, unsigned long);
		gr_log_middle_varargs(audit, msg, gr_task_fullpath(task), task->comm, task_pid_nr(task), GR_GLOBAL_UID(cred->uid), GR_GLOBAL_UID(cred->euid), GR_GLOBAL_GID(cred->gid), GR_GLOBAL_GID(cred->egid), gr_parent_task_fullpath(task), task->real_parent->comm, task_pid_nr(task->real_parent), GR_GLOBAL_UID(pcred->uid), GR_GLOBAL_UID(pcred->euid), GR_GLOBAL_GID(pcred->gid), GR_GLOBAL_GID(pcred->egid), GR_GLOBAL_UID(cred->uid), ulong1);
		break;
	case GR_CRASH2:
		task = va_arg(ap, struct task_struct *);
		cred = __task_cred(task);
		pcred = __task_cred(task->real_parent);
		ulong1 = va_arg(ap, unsigned long);
		gr_log_middle_varargs(audit, msg, gr_task_fullpath(task), task->comm, task_pid_nr(task), GR_GLOBAL_UID(cred->uid), GR_GLOBAL_UID(cred->euid), GR_GLOBAL_GID(cred->gid), GR_GLOBAL_GID(cred->egid), gr_parent_task_fullpath(task), task->real_parent->comm, task_pid_nr(task->real_parent), GR_GLOBAL_UID(pcred->uid), GR_GLOBAL_UID(pcred->euid), GR_GLOBAL_GID(pcred->gid), GR_GLOBAL_GID(pcred->egid), ulong1);
		break;
	case GR_RWXMAP:
		file = va_arg(ap, struct file *);
		gr_log_middle_varargs(audit, msg, file ? gr_to_filename(file->f_path.dentry, file->f_path.mnt) : "<anonymous mapping>");
		break;
	case GR_RWXMAPVMA:
		vma = va_arg(ap, struct vm_area_struct *);
		if (vma->vm_file)
			str1 = gr_to_filename(vma->vm_file->f_path.dentry, vma->vm_file->f_path.mnt);
		else if (vma->vm_flags & (VM_GROWSDOWN | VM_GROWSUP))
			str1 = "<stack>";
		else if (vma->vm_start <= current->mm->brk &&
			 vma->vm_end >= current->mm->start_brk)
			str1 = "<heap>";
		else
			str1 = "<anonymous mapping>";
		gr_log_middle_varargs(audit, msg, str1);
		break;
	case GR_PSACCT:
		{
			unsigned int wday, cday;
			__u8 whr, chr;
			__u8 wmin, cmin;
			__u8 wsec, csec;
			char cur_tty[64] = { 0 };
			char parent_tty[64] = { 0 };

			task = va_arg(ap, struct task_struct *);
			wday = va_arg(ap, unsigned int);
			cday = va_arg(ap, unsigned int);
			whr = va_arg(ap, int);
			chr = va_arg(ap, int);
			wmin = va_arg(ap, int);
			cmin = va_arg(ap, int);
			wsec = va_arg(ap, int);
			csec = va_arg(ap, int);
			ulong1 = va_arg(ap, unsigned long);
			cred = __task_cred(task);
			pcred = __task_cred(task->real_parent);

			gr_log_middle_varargs(audit, msg, gr_task_fullpath(task), task->comm, task_pid_nr(task), &task->signal->curr_ip, tty_name(task->signal->tty, cur_tty), GR_GLOBAL_UID(cred->uid), GR_GLOBAL_UID(cred->euid), GR_GLOBAL_GID(cred->gid), GR_GLOBAL_GID(cred->egid), wday, whr, wmin, wsec, cday, chr, cmin, csec, (task->flags & PF_SIGNALED) ? "killed by signal" : "exited", ulong1, gr_parent_task_fullpath(task), task->real_parent->comm, task_pid_nr(task->real_parent), &task->real_parent->signal->curr_ip, tty_name(task->real_parent->signal->tty, parent_tty), GR_GLOBAL_UID(pcred->uid), GR_GLOBAL_UID(pcred->euid), GR_GLOBAL_GID(pcred->gid), GR_GLOBAL_GID(pcred->egid));
		}
		break;
	default:
		gr_log_middle(audit, msg, ap);
	}
	va_end(ap);
	// these don't need DEFAULTSECARGS printed on the end
	if (argtypes == GR_CRASH1 || argtypes == GR_CRASH2)
		gr_log_end(audit, 0);
	else
		gr_log_end(audit, 1);
	END_LOCKS(audit);
}
Beispiel #18
0
static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
			      char *fp, int count)
{
	const unsigned char *p;
	char *f, flags = 0;
	int	i;

	if (!tty->read_buf)
		return;

	if (tty->real_raw) {
		i = MIN(count, MIN(N_TTY_BUF_SIZE - tty->read_cnt,
				   N_TTY_BUF_SIZE - tty->read_head));
		memcpy(tty->read_buf + tty->read_head, cp, i);
		tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
		tty->read_cnt += i;
		cp += i;
		count -= i;

		i = MIN(count, MIN(N_TTY_BUF_SIZE - tty->read_cnt,
			       N_TTY_BUF_SIZE - tty->read_head));
		memcpy(tty->read_buf + tty->read_head, cp, i);
		tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
		tty->read_cnt += i;
	} else {
		for (i=count, p = cp, f = fp; i; i--, p++) {
			if (f)
				flags = *f++;
			switch (flags) {
			case TTY_NORMAL:
				n_tty_receive_char(tty, *p);
				break;
			case TTY_BREAK:
				n_tty_receive_break(tty);
				break;
			case TTY_PARITY:
			case TTY_FRAME:
				n_tty_receive_parity_error(tty, *p);
				break;
			case TTY_OVERRUN:
				n_tty_receive_overrun(tty);
				break;
			default:
				printk("%s: unknown flag %d\n", tty_name(tty),
				       flags);
				break;
			}
		}
		if (tty->driver.flush_chars)
			tty->driver.flush_chars(tty);
	}

	if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) {
		if (tty->fasync)
			kill_fasync(tty->fasync, SIGIO);
		if (tty->read_wait)
			wake_up_interruptible(&tty->read_wait);
	}

	if ((tty->read_cnt >= TTY_THRESHOLD_THROTTLE) &&
	    tty->driver.throttle &&
	    !set_bit(TTY_THROTTLED, &tty->flags))
		tty->driver.throttle(tty);
}
Beispiel #19
0
static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
			      char *fp, int count)
{
	const unsigned char *p;
	char *f, flags = TTY_NORMAL;
	int	i;
	char	buf[64];

	if (!tty->read_buf)
		return;

	if (tty->real_raw) {
		i = MIN(count, MIN(N_TTY_BUF_SIZE - tty->read_cnt,
				   N_TTY_BUF_SIZE - tty->read_head));
		memcpy(tty->read_buf + tty->read_head, cp, i);
		tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
		tty->read_cnt += i;
		cp += i;
		count -= i;

		i = MIN(count, MIN(N_TTY_BUF_SIZE - tty->read_cnt,
			       N_TTY_BUF_SIZE - tty->read_head));
		memcpy(tty->read_buf + tty->read_head, cp, i);
		tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
		tty->read_cnt += i;
	} else {
		for (i=count, p = cp, f = fp; i; i--, p++) {
			if (f)
				flags = *f++;
			switch (flags) {
			case TTY_NORMAL:
				n_tty_receive_char(tty, *p);
				break;
			case TTY_BREAK:
				n_tty_receive_break(tty);
				break;
			case TTY_PARITY:
			case TTY_FRAME:
				n_tty_receive_parity_error(tty, *p);
				break;
			case TTY_OVERRUN:
				n_tty_receive_overrun(tty);
				break;
			default:
				printk("%s: unknown flag %d\n",
				       tty_name(tty, buf), flags);
				break;
			}
		}
		if (tty->driver.flush_chars)
			tty->driver.flush_chars(tty);
	}

	if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) {
		if (tty->fasync)
			kill_fasync(tty->fasync, SIGIO);
		if (tty->read_wait)
			wake_up_interruptible(&tty->read_wait);
	}

	/*
	 * Check the remaining room for the input canonicalization
	 * mode.  We don't want to throttle the driver if we're in
	 * canonical mode and don't have a newline yet!
	 */
	if (n_tty_receive_room(tty) < TTY_THRESHOLD_THROTTLE) {
		/* check TTY_THROTTLED first so it indicates our state */
		if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
		    tty->driver.throttle)
			tty->driver.throttle(tty);
	}
}
Beispiel #20
0
void
login (const struct utmp *ut)
{
#ifdef PATH_MAX
  char _tty[PATH_MAX + UT_LINESIZE];
#else
  char _tty[512 + UT_LINESIZE];
#endif
  char *tty = _tty;
  int found_tty;
  const char *ttyp;
  struct utmp copy = *ut;

  /* Fill in those fields we supply.  */
#if _HAVE_UT_TYPE - 0
  copy.ut_type = USER_PROCESS;
#endif
#if _HAVE_UT_PID - 0
  copy.ut_pid = getpid ();
#endif

  /* Seek tty.  */
  found_tty = tty_name (STDIN_FILENO, &tty, sizeof (_tty));
  if (found_tty < 0)
    found_tty = tty_name (STDOUT_FILENO, &tty, sizeof (_tty));
  if (found_tty < 0)
    found_tty = tty_name (STDERR_FILENO, &tty, sizeof (_tty));

  if (found_tty >= 0)
    {
      /* We only want to insert the name of the tty without path.
	 But take care of name like /dev/pts/3.  */
      if (strncmp (tty, "/dev/", 5) == 0)
	ttyp = tty + 5;		/* Skip the "/dev/".  */
      else
	ttyp = basename (tty);

      /* Position to record for this tty.  */
      strncpy (copy.ut_line, ttyp, UT_LINESIZE);

      /* Tell that we want to use the UTMP file.  */
      if (utmpname (_PATH_UTMP) == 0)
	{
	  /* Open UTMP file.  */
	  setutent ();

	  /* Write the entry.  */
	  pututline (&copy);

	  /* Close UTMP file.  */
	  endutent ();
	}

      if (tty != _tty)
	free (tty);		/* Free buffer malloced by tty_name.  */
    }
  else
    /* We provide a default value so that the output does not contain
       an random bytes in this field.  */
    strncpy (copy.ut_line, "???", UT_LINESIZE);

  /* Update the WTMP file.  Here we have to add a new entry.  */
  updwtmp (_PATH_WTMP, &copy);
}
Beispiel #21
0
void tty_ldisc_hangup(struct tty_struct *tty)
{
	struct tty_ldisc *ld;
	int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS;
	int err = 0;

	/*
	 * FIXME! What are the locking issues here? This may me overdoing
	 * things... This question is especially important now that we've
	 * removed the irqlock.
	 */
	ld = tty_ldisc_ref(tty);
	if (ld != NULL) {
		/* We may have no line discipline at this point */
		if (ld->ops->flush_buffer)
			ld->ops->flush_buffer(tty);
		tty_driver_flush_buffer(tty);
		if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
		    ld->ops->write_wakeup)
			ld->ops->write_wakeup(tty);
		if (ld->ops->hangup)
			ld->ops->hangup(tty);
		tty_ldisc_deref(ld);
	}
	/*
	 * FIXME: Once we trust the LDISC code better we can wait here for
	 * ldisc completion and fix the driver call race
	 */
	wake_up_interruptible_poll(&tty->write_wait, POLLOUT);
	wake_up_interruptible_poll(&tty->read_wait, POLLIN);
	/*
	 * Shutdown the current line discipline, and reset it to
	 * N_TTY if need be.
	 *
	 * Avoid racing set_ldisc or tty_ldisc_release
	 */
	mutex_lock(&tty->ldisc_mutex);

	/*
	 * this is like tty_ldisc_halt, but we need to give up
	 * the BTM before calling cancel_work_sync, which may
	 * need to wait for another function taking the BTM
	 */
	clear_bit(TTY_LDISC, &tty->flags);
	tty_unlock(tty);
	cancel_work_sync(&tty->port->buf.work);
	mutex_unlock(&tty->ldisc_mutex);
retry:
	tty_lock(tty);
	mutex_lock(&tty->ldisc_mutex);

	/* At this point we have a closed ldisc and we want to
	   reopen it. We could defer this to the next open but
	   it means auditing a lot of other paths so this is
	   a FIXME */
	if (tty->ldisc) {	/* Not yet closed */
		if (atomic_read(&tty->ldisc->users) != 1) {
			char cur_n[TASK_COMM_LEN], tty_n[64];
			long timeout = 3 * HZ;
			tty_unlock(tty);

			while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
				timeout = MAX_SCHEDULE_TIMEOUT;
				printk_ratelimited(KERN_WARNING
					"%s: waiting (%s) for %s took too long, but we keep waiting...\n",
					__func__, get_task_comm(cur_n, current),
					tty_name(tty, tty_n));
			}
			mutex_unlock(&tty->ldisc_mutex);
			goto retry;
		}

		if (reset == 0) {

			if (!tty_ldisc_reinit(tty, tty->termios.c_line))
				err = tty_ldisc_open(tty, tty->ldisc);
			else
				err = 1;
		}
		/* If the re-open fails or we reset then go to N_TTY. The
		   N_TTY open cannot fail */
		if (reset || err) {
			BUG_ON(tty_ldisc_reinit(tty, N_TTY));
			WARN_ON(tty_ldisc_open(tty, tty->ldisc));
		}
		tty_ldisc_enable(tty);
	}
	mutex_unlock(&tty->ldisc_mutex);
	if (reset)
		tty_reset_termios(tty);
}