structtty_operations { structtty_struct * (*lookup)(structtty_driver *driver, structfile *filp, intidx); int (*install)(struct tty_driver *driver, struct tty_struct *tty); void (*remove)(struct tty_driver *driver, struct tty_struct *tty); int (*open)(struct tty_struct * tty, struct file * filp); void (*close)(struct tty_struct * tty, struct file * filp); void (*shutdown)(struct tty_struct *tty); void (*cleanup)(struct tty_struct *tty); int (*write)(struct tty_struct * tty, constunsignedchar *buf, int count); int (*put_char)(struct tty_struct *tty, unsignedchar ch); void (*flush_chars)(struct tty_struct *tty); int (*write_room)(struct tty_struct *tty); int (*chars_in_buffer)(struct tty_struct *tty); int (*ioctl)(struct tty_struct *tty, unsignedint cmd, unsignedlong arg); long (*compat_ioctl)(struct tty_struct *tty, unsignedint cmd, unsignedlong arg); void (*set_termios)(struct tty_struct *tty, struct ktermios * old); void (*throttle)(struct tty_struct * tty); void (*unthrottle)(struct tty_struct * tty); void (*stop)(struct tty_struct *tty); void (*start)(struct tty_struct *tty); void (*hangup)(struct tty_struct *tty); int (*break_ctl)(struct tty_struct *tty, int state); void (*flush_buffer)(struct tty_struct *tty); void (*set_ldisc)(struct tty_struct *tty); void (*wait_until_sent)(struct tty_struct *tty, int timeout); void (*send_xchar)(struct tty_struct *tty, char ch); int (*tiocmget)(struct tty_struct *tty); int (*tiocmset)(struct tty_struct *tty, unsignedintset, unsignedint clear); int (*resize)(struct tty_struct *tty, struct winsize *ws); int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew); int (*get_icount)(struct tty_struct *tty, struct serial_icounter_struct *icount); void (*show_fdinfo)(struct tty_struct *tty, struct seq_file *m); #ifdef CONFIG_CONSOLE_POLL int (*poll_init)(struct tty_driver *driver, int line, char *options); int (*poll_get_char)(struct tty_driver *driver, int line); void (*poll_put_char)(struct tty_driver *driver, int line, char ch); #endif int (*proc_show)(struct seq_file *, void *); } __randomize_layout;
比如,我们对ptmx驱动进行write操作时,就会调用这个里面的write指针指向的函数。也就是,我们如果能**[伪造tty_operations结构体,将里面的指针指向我们需要执行的函数]{.mark}。然后将tty_struct结构体里的[const struct tty_operations *ops]{.mark}指针指向我们伪造的tty_operations结构体,然后对驱动执行对应的操作,比如write,就能触发函数的执行。[而tty_struct结构体,我们可以通过漏洞来控制]{.mark},然后修改指针。[这种思想,就如同是glibc下的house of orange]{.mark}**,house of orange是伪造vtable表,而我们这里,同样是伪造函数表。为了加深理解,我们以ciscn2017_babydriver为例,之前,我们利用UAF修改了cred结构,这次,我们用同样的方法,修改tty_struct结构。