kernel tty_struct

本文详细探讨了Linux内核中的tty_struct结构体,从ptmx的定义到write执行流程,分析了如何利用tty_struct进行内核级别的漏洞利用。文章通过fake_ops构造、kernel ROP技术,展示了在安全上下文中如何绕过SMEP保护进行提权。
摘要由CSDN通过智能技术生成

kernel tty_struct exp

tty_struct

Linux下一个特殊的驱动文件,是默认集成在linux中的, 代码在driver/tty文件夹。主要文件在 pty.c

ptmx

可以看到其对应的 file_operations结构,定义为ptmx_fops

然后可以看到对应的__init函数,驱动载入的初始化代码在 unix98_pty_init函数,

image-20220213185023138

在此函数最后, 设置了文件 "/dev/ptmx"

image-20220213184120686

在这里也可以看到我们的ptmx_fops.open被设置为了 ptmx_open函数,

定义

我们的主角: struct tty_struct结构体定义在 include/linux/tty.h

其实唯一需要注意的是第四位的ops: const struct tty_operations *ops;

struct tty_struct {
   
        int     magic;
        struct kref kref;
        struct device *dev;
        struct tty_driver *driver;
        const struct tty_operations *ops;
        int index;

        /* Protects ldisc changes: Lock tty not pty */
        struct ld_semaphore ldisc_sem;
        struct tty_ldisc *ldisc;

        struct mutex atomic_write_lock;
        struct mutex legacy_mutex;
        struct mutex throttle_mutex;
        struct rw_semaphore termios_rwsem;
        struct mutex winsize_mutex;
        spinlock_t ctrl_lock;
        spinlock_t flow_lock;
        /* Termios values are protected by the termios rwsem */
        struct ktermios termios, termios_locked;
        struct termiox *termiox;        /* May be NULL for unsupported */
        char name[64];
        struct pid *pgrp;               /* Protected by ctrl lock */
        struct pid *session;
        unsigned long flags;
        int count;
        struct winsize winsize;         /* winsize_mutex */
        unsigned long stopped:1,        /* flow_lock */
                      flow_stopped:1,
                      unused:BITS_PER_LONG - 2;
        int hw_stopped;
        unsigned long ctrl_status:8,    /* ctrl_lock */
                      packet:1,
                      unused_ctrl:BITS_PER_LONG - 9;
        unsigned int receive_room;      /* Bytes free for queue */
        int flow_change;

        struct tty_struct *link;
        struct fasync_struct *fasync;
        int alt_speed;          /* For magic substitution of 38400 bps */
        wait_queue_head_t write_wait;
        wait_queue_head_t read_wait;
        struct work_struct hangup_work;
        void *disc_data;
        void *driver_data;
        struct list_head tty_files;

#define N_TTY_BUF_SIZE 4096

        int closing;
        unsigned char *write_buf;
        int write_cnt;
        /* If the tty has a pending do_SAK, queue it here - akpm */
        struct work_struct SAK_work;
        struct tty_port *port;
};

这个tty_operations定义在include/linux/tty_driver.h, 可以看到 大量的hook位。

struct tty_operations {
   
        struct tty_struct * (*lookup)(struct tty_driver *driver,
                        struct inode *inode, int idx);
        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,
                      const unsigned char *buf, int count);
        int  (*put_char)(struct tty_struct *tty, unsigned char 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,
                    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
mtd_debug 命令是用于调试MTD驱动的命令,其源码可以在Linux内核源码中找到。具体路径为:drivers/mtd/tests/mtd_debug.c。 以下是 mtd_debug 命令的源码: ``` #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> #include <linux/mtd/partitions.h> #include <linux/slab.h> #include <linux/sched.h> #include <linux/list.h> #include <linux/spinlock.h> #include <linux/tty.h> #include <linux/tty_driver.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/vmalloc.h> #include <linux/mutex.h> #include <linux/ctype.h> static char mtd_buf[4096]; static int mtd_buf_size; static ssize_t mtd_debug_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { int ret; if (*ppos >= mtd_buf_size) return 0; if (count > mtd_buf_size - *ppos) count = mtd_buf_size - *ppos; ret = copy_to_user(buf, mtd_buf + *ppos, count); if (ret) return -EFAULT; *ppos += count; return count; } static ssize_t mtd_debug_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { int ret; if (count >= sizeof(mtd_buf)) return -EINVAL; ret = copy_from_user(mtd_buf, buf, count); if (ret) return -EFAULT; mtd_buf_size = count; return count; } static const struct file_operations mtd_debug_fops = { .owner = THIS_MODULE, .read = mtd_debug_read, .write = mtd_debug_write, }; static struct tty_driver *mtd_debug_tty_driver = NULL; static int mtd_debug_open(struct inode *inode, struct file *file) { if (!try_module_get(THIS_MODULE)) return -ENODEV; file->private_data = mtd_debug_tty_driver->driver_state; return tty_open(inode, file); } static void mtd_debug_close(struct tty_struct *tty, struct file *file) { tty_driver_flush_buffer(tty); module_put(THIS_MODULE); tty_close(tty, file); } static int mtd_debug_write_room(struct tty_struct *tty) { return 65536; } static int mtd_debug_put_char(struct tty_struct *tty, unsigned char ch) { if (mtd_buf_size >= sizeof(mtd_buf)) return 0; mtd_buf[mtd_buf_size++] = ch; return 1; } static struct tty_operations mtd_debug_tty_ops = { .open = mtd_debug_open, .close = mtd_debug_close, .write_room = mtd_debug_write_room, .put_char = mtd_debug_put_char, }; static struct tty_driver *mtd_debug_init_tty_driver(void) { struct tty_driver *driver; driver = alloc_tty_driver(1); if (!driver) return NULL; driver->owner = THIS_MODULE; driver->driver_name = "mtd_debug"; driver->name = "mtd_debug"; driver->type = TTY_DRIVER_TYPE_SERIAL; driver->subtype = SERIAL_TYPE_NORMAL; driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; tty_set_operations(driver, &mtd_debug_tty_ops); driver->init_termios = tty_std_termios; driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; tty_register_driver(driver); return driver; } static void mtd_debug_exit_tty_driver(struct tty_driver *driver) { tty_unregister_driver(driver); put_tty_driver(driver); } static int __init mtd_debug_init(void) { dev_t dev; int ret; dev = MKDEV(0, 0); ret = register_chrdev_region(dev, 1, "mtd_debug"); if (ret) { printk(KERN_ERR "mtd_debug: failed to register chrdev region\n"); return ret; } mtd_debug_tty_driver = mtd_debug_init_tty_driver(); if (!mtd_debug_tty_driver) { printk(KERN_ERR "mtd_debug: failed to init tty driver\n"); unregister_chrdev_region(dev, 1); return -ENOMEM; } cdev_init(&mtd_debug_tty_driver->cdev, &mtd_debug_fops); mtd_debug_tty_driver->cdev.owner = THIS_MODULE; ret = cdev_add(&mtd_debug_tty_driver->cdev, dev, 1); if (ret) { printk(KERN_ERR "mtd_debug: failed to add cdev\n"); mtd_debug_exit_tty_driver(mtd_debug_tty_driver); unregister_chrdev_region(dev, 1); return ret; } printk(KERN_INFO "mtd_debug: tty driver registered\n"); return 0; } static void __exit mtd_debug_exit(void) { dev_t dev; dev = MKDEV(0, 0); cdev_del(&mtd_debug_tty_driver->cdev); mtd_debug_exit_tty_driver(mtd_debug_tty_driver); unregister_chrdev_region(dev, 1); printk(KERN_INFO "mtd_debug: tty driver unregistered\n"); } module_init(mtd_debug_init); module_exit(mtd_debug_exit); MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); MODULE_DESCRIPTION("MTD debug console"); MODULE_LICENSE("GPL"); ``` 该代码定义了一个字符设备,用于在调试MTD驱动时,查看和修改MTD缓冲区中的数据。同时,该代码还定义了一个 tty 驱动,将缓冲区中的数据输出到终端。用户可以通过在终端中输入和输出数据,对 MTd 缓冲区进行读写,从而进行调试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值