View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0006104 | CentOS-6 | kernel | public | 2012-11-28 18:14 | 2013-03-13 20:58 |
Reporter | Zykov Ilya | ||||
Priority | normal | Severity | crash | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Platform | Linux | OS | Centos | OS Version | 6 |
Product Version | 6.3 | ||||
Target Version | Fixed in Version | 6.4 | |||
Summary | 0006104: tty: tty_flip_buffer NULL pointer dereference | ||||
Description | The root of problem it use carelessly buffer flushing, then another thread can write to it. This patch resolve this problem. ------------------------------------------------------------------------- diff --git a/drivers/char/tty_buffer.c b/drivers/char/tty_buffer.c index ded3a77..53fdcf2 100644 --- a/drivers/char/tty_buffer.c +++ b/drivers/char/tty_buffer.c @@ -114,11 +114,14 @@ static void __tty_buffer_flush(struct tty_struct *tty) { struct tty_buffer *thead; - while ((thead = tty->buf.head) != NULL) { - tty->buf.head = thead->next; - tty_buffer_free(tty, thead); + if (tty->buf.head == NULL) + return; + while ((thead = tty->buf.head->next) != NULL) { + tty_buffer_free(tty, tty->buf.head); + tty->buf.head = thead; } - tty->buf.tail = NULL; + WARN_ON(tty->buf.head != tty->buf.tail); + tty->buf.head->read = tty->buf.head->commit; } /** | ||||
Steps To Reproduce | Maybe need SMP. --------------------------------------------- !!!! Not execute on important systems !!!! --------------------------------------------- #include <stdio.h> #include <fcntl.h> #include <sys/ioctl.h> #include <termios.h> #include <stdlib.h> #define BUF_SIZE 512 #define ERROR_EXIT_CODE 1 #define parent child_id static int mfd=-1, sfd=-1, parent=1; static char pty_name[24]; static void pty_exit(int ret, char * exit_message){ if (sfd >= 0) close(sfd); if (mfd >= 0) close(mfd); printf("%s %s exit. \n %s",ret?"Error":"Normal", parent?"parent":"child", exit_message?exit_message:""); exit(ret); } static void pty_init(void){ int ptn; if( (mfd=open("/dev/ptmx", O_RDWR )) < 0 ) pty_exit(ERROR_EXIT_CODE,"Couldn't open /dev/ptmx. \n"); if (ioctl(mfd, TIOCGPTN, &ptn) < 0 ) pty_exit(ERROR_EXIT_CODE,"Couldn't get pty number. \n"); snprintf(pty_name, sizeof(pty_name), "/dev/pts/%d", ptn); printf("Slave pty name = %s.\n",pty_name); ptn=0; if (ioctl(mfd, TIOCSPTLCK, &ptn) < 0 ) pty_exit(ERROR_EXIT_CODE,"Couldn't unlock pty slave. \n"); if ( (sfd=open(pty_name, O_RDWR )) < 0 ) pty_exit(ERROR_EXIT_CODE, "Couldn't open pty slave. \n"); } int main(int argc,char *argv[]) { pty_init(); char buf[]={ [0 ... BUF_SIZE-1]='1' }; child_id=fork(); do { if(parent) { if ( write(mfd, buf, BUF_SIZE) < 0 ) pty_exit(ERROR_EXIT_CODE, "Parent's write() error.\n"); } else { //Child if ( tcflush(sfd, TCIFLUSH) < 0 ) pty_exit(ERROR_EXIT_CODE, "Child's tcflush() error.\n"); } } while(1); return 0; //Never } | ||||
Additional Information | BUG: unable to handle kernel NULL pointer dereference at 0000000000000018 IP: [<ffffffff8131e87e>] tty_insert_flip_string+0x6e/0xd0 PGD 11792b067 PUD 117117067 PMD 0 Oops: 0000 [#1] SMP last sysfs file: /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq CPU 1 ..... ...... Process tty_flip_buffer (pid: 3139, threadinfo ffff880112778000, task ffff880117b4c040) Stack: ffff880117a7fc00 0000000000000200 ffff880117a7fc00 ffff880129f15800 <d> ffff88011a41d000 0000000000000200 ffff880117a7fc00 ffff880129f15cd0 <d> ffff880112779de8 ffffffff8131f539 ffff88011273c800 ffff880129f15800 Call Trace: [<ffffffff8131f539>] pty_write+0x39/0x80 [<ffffffff8131980c>] n_tty_write+0x33c/0x460 [<ffffffff810602c0>] ? default_wake_function+0x0/0x20 [<ffffffff81316431>] tty_write+0x1b1/0x2a0 [<ffffffff813194d0>] ? n_tty_write+0x0/0x460 [<ffffffff8117b698>] vfs_write+0xb8/0x1a0 [<ffffffff8117c0b1>] sys_write+0x51/0x90 [<ffffffff8100b0f2>] system_call_fastpath+0x16/0x1b Code: 00 07 00 00 48 0f 47 f0 48 63 f6 e8 6d fc ff ff 85 c0 41 89 c4 49 8b 9e 88 01 00 00 74 3c 48 98 48 8b 75 c0 45 01 e5 48 89 45 c8 <48> 63 7b 18 48 89 c2 48 03 7b 08 e8 12 fd f5 ff 48 63 7b 18 48 RIP [<ffffffff8131e87e>] tty_insert_flip_string+0x6e/0xd0 RSP <ffff880112779d78> CR2: 0000000000000018 crash> bt PID: 3139 TASK: ffff880117b4c040 CPU: 1 COMMAND: "tty_flip_buffer" #0 [ffff880112779940] machine_kexec at ffffffff8103284b #1 [ffff8801127799a0] crash_kexec at ffffffff810ba982 #2 [ffff880112779a70] oops_end at ffffffff81501b00 #3 [ffff880112779aa0] no_context at ffffffff81043bfb #4 [ffff880112779af0] __bad_area_nosemaphore at ffffffff81043e85 #5 [ffff880112779b40] bad_area at ffffffff81043fae #6 [ffff880112779b70] __do_page_fault at ffffffff81044760 #7 [ffff880112779c90] do_page_fault at ffffffff81503ade #8 [ffff880112779cc0] page_fault at ffffffff81500e95 [exception RIP: tty_insert_flip_string+110] RIP: ffffffff8131e87e RSP: ffff880112779d78 RFLAGS: 00010206 RAX: 0000000000000200 RBX: 0000000000000000 RCX: 0000000000000200 RDX: ffff88011a41d178 RSI: ffff880117a7fc00 RDI: 0000000000000246 RBP: ffff880112779db8 R8: 0000000000000046 R9: 0000000000000000 R10: 000000000000000c R11: 0000000000000000 R12: 0000000000000200 R13: 0000000000000200 R14: ffff88011a41d000 R15: 0000000000000200 ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 #9 [ffff880112779dc0] pty_write at ffffffff8131f539 #10 [ffff880112779df0] n_tty_write at ffffffff8131980c #11 [ffff880112779e80] tty_write at ffffffff81316431 #12 [ffff880112779ef0] vfs_write at ffffffff8117b698 #13 [ffff880112779f30] sys_write at ffffffff8117c0b1 #14 [ffff880112779f80] system_call_fastpath at ffffffff8100b0f2 RIP: 00000035266dae60 RSP: 00007fffcfda2630 RFLAGS: 00010206 RAX: 0000000000000001 RBX: ffffffff8100b0f2 RCX: 00000000004003f4 RDX: 0000000000000200 RSI: 00007fffcfda2830 RDI: 0000000000000003 RBP: 00007fffcfda2a40 R8: 00007f82f57fa700 R9: 0000000000000000 R10: 00007fffcfda25a0 R11: 0000000000000246 R12: 00007fffcfda2b20 R13: 0000000000400620 R14: 0000000000400b80 R15: 0000000000400620 ORIG_RAX: 0000000000000001 CS: 0033 SS: 002b | ||||
Tags | 6.3, centos, kernel, kernel panic | ||||
tty_flip_buffer_bug.c (1,398 bytes) |
|
It is possible to apply kernel patches to the centosplus kernel (but not the distro kernel). However, I see that you marked the patch "CANCEL" on lkml: https://lkml.org/lkml/2012/11/27/599 Is this patch still regarded 'safe' ? |
|
It patch more right then: https://lkml.org/lkml/2012/3/14/552 therefore, I market other patch CANCEL. Maybe I did anything incorrectly if you don't undestand me? I am newbie on lkml.org. |
|
Sorry, I misinterpreted your post. Let's wait and see if your patch gets accepted upstream (kernel.org). | |
You can include this patch, in centosplus, for improve stability, because it would be merged in upstream 3.9-rc1. Thank you. Ilya. https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/drivers/tty/tty_buffer.c?id=64325a3be08d364a62ee8f84b2cf86934bc2544a |
|
Thank you for the update. I will attempt to include the patch in the next release of the cplus kernel. | |
kernel-2.6.32-358.2.1.el6 was released upstream. The patch applied to the cplus kernel. | |
Date Modified | Username | Field | Change |
---|---|---|---|
2012-11-28 18:14 | Zykov Ilya | New Issue | |
2012-11-28 18:14 | Zykov Ilya | File Added: tty_flip_buffer_bug.c | |
2012-11-28 18:19 | Zykov Ilya | Tag Attached: 6.3 | |
2012-11-28 18:19 | Zykov Ilya | Tag Attached: centos | |
2012-11-28 18:19 | Zykov Ilya | Tag Attached: kernel | |
2012-11-28 18:19 | Zykov Ilya | Tag Attached: kernel panic | |
2012-11-28 22:10 | toracat | Note Added: 0016091 | |
2012-11-28 22:11 | toracat | Status | new => feedback |
2012-11-28 22:35 | Zykov Ilya | Note Added: 0016092 | |
2012-11-28 22:35 | Zykov Ilya | Status | feedback => assigned |
2012-11-28 22:51 | toracat | Note Added: 0016093 | |
2013-03-04 18:56 | Zykov Ilya | Note Added: 0016594 | |
2013-03-04 19:06 | toracat | Note Added: 0016595 | |
2013-03-12 20:10 | toracat | Note Added: 0016682 | |
2013-03-13 20:58 | toracat | Status | assigned => resolved |
2013-03-13 20:58 | toracat | Resolution | open => fixed |
2013-03-13 20:58 | toracat | Fixed in Version | => 6.4 |