众所周知我们劫持tty结构体首先需要打开/dev/ptmx
我们一般会这样写代码。
int ptmx_fd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
if (ptmx_fd < 0){
printf("[-] bad open /dev/ptmx\n");
exit(-1);
}
打不开文件可能有很多问题
我们也不清楚究竟是啥问题
我们试着让他报错
通过报错具体看看是啥问题
首先在文件里面加上头文件errno.h
int ptmx_fd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
if (ptmx_fd < 0){
printf("[-] bad open /dev/ptmx\n");
printf("[+] ptmx fd : %d\n",errno);
exit(-1);
}
让他输出错误号
错误号是2
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* Input/output error */
#define ENXIO 6 /* Device not configured */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file descriptor */
#define ECHILD 10 /* No child processes */
#define EDEADLK 11 /* Resource deadlock avoided */
/* 11 was EAGAIN */
#define ENOMEM 12 /* Cannot allocate memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
#define ENOTBLK 15 /* Block device required */
#endif
#define EBUSY 16 /* Device / Resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* Operation not supported by device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* Too many open files in system */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Inappropriate ioctl for device */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
/* math software */
#define EDOM 33 /* Numerical argument out of domain */
#define ERANGE 34 /* Result too large */
/* non-blocking and interrupt i/o */
#define EAGAIN 35 /* Resource temporarily unavailable */
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define EINPROGRESS 36 /* Operation now in progress */
#define EALREADY 37 /* Operation already in progress */
/* ipc/network software -- argument errors */
#define ENOTSOCK 38 /* Socket operation on non-socket */
#define EDESTADDRREQ 39 /* Destination address required */
#define EMSGSIZE 40 /* Message too long */
#define EPROTOTYPE 41 /* Protocol wrong type for socket */
#define ENOPROTOOPT 42 /* Protocol not available */
#define EPROTONOSUPPORT 43 /* Protocol not supported */
#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
#define ESOCKTNOSUPPORT 44 /* Socket type not supported */
#endif
#define ENOTSUP 45 /* Operation not supported */
找不到文件…
我们cat一下
也是这个报错
但显然是有文件的。
尝试良久无果。
决定跟一下drivers/char/pty.c中的__init unix98_pty_init和ptmx_open函数。
我现在出问题的这个题目环境内核版本是4.20.13
在开始研究之前呢我觉得有必要简述一下
console terminal tty pty pts ptmx的关系
console就是控制器,是字符设备
terminal的出现是为了解决多用户同时对服务器进行操作,从刚开始的物理终端发展出了软件仿真终端,又发展出来后来的伪终端。
tty跟terminal差不多 年代不同称呼不同
pty是p tty p是pseudo pty就是伪终端。
pty有一个master端,有一个slave端 master端可以对slave端进行通信
slave端就是pts master端就是ptmx。
创造伪终端的原因是因为tty刚开始运行在内核态,鼠标键盘啥的能访问,但是想把它拿出来到内核态。
pty的slave端就是在tty中实现的。
现在我们linux开的终端其实都应该叫运行在用户态的软件仿真终端
我们既然试图研究pty,那理论上应该先浅研究一下tty
简单说
在linux中tty可以分为如下几类
- 串行端口终端(serial port terminal): 指使用计算机串行端口连接的终端设备, /dev/ttySn
- 伪终端(pseudo terminal): 通常是通过ssh登陆的终端, /dev/pts/*
- 控制终端(controlling terminal): 代表当前tty设备 /dev/tty
- 控制台终端(console): 指计算机的输出设备, 通常是printk信息输出的设备, /dev/ttyn、/dev/console
tty具体的一些接口或者说方法在下面的代码中都能看到
所以我们就下面直接代码里研究研究就行。
代码开始于pty_init函数
static int __init pty_init(void)
{
legacy_pty_init();
unix98_pty_init();
return 0;