使用python2库 paramiko 模拟ssh登录终端,概率性出现coredump

问题原因

自动化场景下,使用python 库paramiko 模拟ssh登录终端,概率性出现无法判断终端类型,导致terminal_get_size获取终端大小失败,终端大小读取为65535*65535,进而导致terminal_change_size时,申请65535*65535的内存失败。

此后,执行re_clear_display刷新当前屏幕信息时,访问越界导致概率性coredump

问题日志

#0 0xb6a1e7e8 in re_clear_display () from /usr/lib/libedit.so.0

(gdb) bt

#0 0xb6a1e7e8 in re_clear_display () from /usr/lib/libedit.so.0

#1 0xb6a1bf10 in read_prepare (el=0xd36c18) at read.c:432

#2 0xb6a1c1cc in el_wgets (el=0xd36c18, nread=0xbecbd8fc) at read.c:508

#3 0xb6a150ac in el_gets () from /usr/lib/libedit.so.0

#4 0xb6a3251c in readline (p=0x40541c ‘ ‘ <repeats 12 times>, “Copyright(C) 2013-2

#5 0x004022f8 in get_user_input () at /home/workspace/V2R2_trunk/application/src/a

#6 main (argc=, argv=) at /home/workspace/V2R2_trunk

(gdb) frame #1

Invalid character ‘#’ in expression.

(gdb) frame 1

#1 0xb6a1bf10 in read_prepare (el=0xd36c18) at read.c:432

432 read.c: No such file or directory.

(gdb) print el->el_terminal

$1 = {t_name = 0x0, t_size = {h = 65535, v = 65535}, t_flags = 0, t_buf = 0xd37fe8

t_fkey = 0xd38ff8}

(gdb) frame 4

#4 0xb6a3251c in readline (p=0x40541c ‘ ‘ <repeats 12 times>, “Copyright(C) 2013-2

455 readline.c: No such file or directory.

函数调用

1
2
3
4
graph TD
a[get_user_input]-->b[readline]
b-->rl_initialize-->el_init_internal-->terminal_init-->terminal_set-->terminal_change_size-->terminal_rebuffer_display-->terminal_alloc_display-->terminal_alloc_buffer--申请内存失败-->c
b-->el_gets-->el_wgets-->read_prepare-->re_clear_display-->c[访问el->el_display的65535地址]

修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
 src/terminal.c | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/src/terminal.c b/src/terminal.c
index 2e62f7b..96bc9b1 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -952,6 +952,16 @@ terminal_get_size(EditLine *el, int *lins, int *cols)
}
}
#endif
+ if (*cols > 2000 ) {
+ *cols = 2000;
+ } else if (*cols < 2) {
+ *cols = 80;
+ }
+ if (*lins > 2000) {
+ *lins = 2000;
+ } else if (*lins < 1) {
+ *lins = 24;
+ }
return Val(T_co) != *cols || Val(T_li) != *lins;
}

@@ -966,8 +976,20 @@ terminal_change_size(EditLine *el, int lins, int cols)
/*
* Just in case
*/
- Val(T_co) = (cols < 2) ? 80 : cols;
- Val(T_li) = (lins < 1) ? 24 : lins;
+ if (cols < 2) {
+ Val(T_co) = 80;
+ } else if (cols > 2000) {
+ Val(T_co) = 2000;
+ } else {
+ Val(T_co) = cols;
+ }
+ if (lins < 1) {
+ Val(T_li) = 24;
+ } else if (lins > 2000) {
+ Val(T_li) = 2000;
+ } else {
+ Val(T_li) = lins;
+ }

/* re-make display buffers */
if (terminal_rebuffer_display(el) == -1)

github链接地址

代码仓