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); }
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); } }
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; }
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); }
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; }
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(); }
/* * ------------------------------------------------------------ * 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); }
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); }
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); }
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); }
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); }
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); } }
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 (©); /* 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, ©); }
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); }