tty: fix leakage of -ERESTARTSYS to userland
PATCH 1/1 tty: fix leakage of -ERESTARTSYS to userland
Spotted by Satoru Takeuchi.
kill_pgrp(task_pgrp(current)) sends the signal to the current's thread group, but can choose any sub-thread as a target for signal_wake_up(). This means that job_control() and tty_check_change() may return -ERESTARTSYS without signal_pending().
drivers/char/n_tty.c renamed from drivers/char/n_tty.c~ +1 -0
@@ -1191,6 +1191,7 @@ static int job_control(struct tty_struct is_current_pgrp_orphaned())return -EIO ;kill_pgrp (task_pgrp (current),SIGTTIN ,1 ); +set_thread_flag (TIF_SIGPENDING );return -ERESTARTSYS ; } }
drivers/char/tty_io.c renamed from drivers/char/tty_io.c~ +2 -1
@@ -1121,7 +1121,8 @@ int tty_check_change(struct tty_struct *return 0 ;if (is_current_pgrp_orphaned ())return -EIO ; - (void )kill_pgrp (task_pgrp (current),SIGTTOU ,1 ); +kill_pgrp (task_pgrp (current),SIGTTOU ,1 ); +set_thread_flag (TIF_SIGPENDING );return -ERESTARTSYS ; }
Quoted 22 lines · On Tue, 29 May 2007 22:44:35 +0400 Oleg Nesterov <[email protected]> wrote:
Spotted by Satoru Takeuchi.
kill_pgrp(task_pgrp(current)) sends the signal to the current's thread group, but can choose any sub-thread as a target for
signal_wake_up(). This means thatjob_control()andtty_check_change()may return-ERESTARTSYSwithoutsignal_pending().Signed-off-by Oleg Nesterov <[email protected]>drivers/char/n_tty.c renamed from drivers/char/n_tty.c~ +1
-0@@ -1191,6 +1191,7 @@ static int job_control(struct tty_struct is_current_pgrp_orphaned())return -EIO ;kill_pgrp (task_pgrp (current),SIGTTIN ,1 ); +set_thread_flag (TIF_SIGPENDING );return -ERESTARTSYS ; } }
drivers/char/tty_io.c int tty_check_change(struct tty_struct * · line 1128
Quoted 9 lines
drivers/char/tty_io.c renamed from drivers/char/tty_io.c~ +2
-1@@ -1121,7 +1121,8 @@ int tty_check_change(struct tty_struct *return 0 ;if (is_current_pgrp_orphaned ())return -EIO ; - (void )kill_pgrp (task_pgrp (current),SIGTTOU ,1 ); +kill_pgrp (task_pgrp (current),SIGTTOU ,1 ); +set_thread_flag (TIF_SIGPENDING );return -ERESTARTSYS ; }
Are there other callers of kill_pgrp() which have the same problem?
Perhaps we should have a kill_pgrp_self() which takes care of doing this, rather than open-coding it. Something with a comment which explains what's going on ;)
Quoted 15 lines · Andrew Morton
drivers/char/n_tty.c static int job_control(struct tty_struct · line 1197
Quoted 10 lines · On Tue, 29 May 2007 22:44:35 +0400 Oleg Nesterov <[email protected]> wrote:
drivers/char/n_tty.c renamed from drivers/char/n_tty.c~ +1
-0@@ -1191,6 +1191,7 @@ static int job_control(struct tty_struct is_current_pgrp_orphaned())return -EIO ;kill_pgrp (task_pgrp (current),SIGTTIN ,1 ); +set_thread_flag (TIF_SIGPENDING );return -ERESTARTSYS ; } }Are there other callers of
kill_pgrp()which have the same problem?
Hopefully no.
Quoted 3 lines
Perhaps we should have a
kill_pgrp_self()which takes care of doing this, rather than open-coding it. Something with a comment which explains what's going on ;)
This set_thread_flag(TIF_SIGPENDING) is "connected" to "return -ERESTARTSYS", not to kill_pgrp(), imho the new helper is not so suitable.
Perhaps it makes sense to add the comment into include/linux/errno.h, to explain that -ERESTART... codes are only valid when signal_pending() == true.
Oleg.
At Wed, 30 May 2007 23:18:49 +0400,
Quoted 24 lines · Oleg Nesterov
Quoted 15 lines · Andrew Morton
drivers/char/n_tty.c static int job_control(struct tty_struct · line 1197
Quoted 10 lines · On Tue, 29 May 2007 22:44:35 +0400 Oleg Nesterov <[email protected]> wrote:
drivers/char/n_tty.c renamed from drivers/char/n_tty.c~ +1
-0@@ -1191,6 +1191,7 @@ static int job_control(struct tty_struct is_current_pgrp_orphaned())return -EIO ;kill_pgrp (task_pgrp (current),SIGTTIN ,1 ); +set_thread_flag (TIF_SIGPENDING );return -ERESTARTSYS ; } }Are there other callers of
kill_pgrp()which have the same problem?Hopefully no.
Quoted 3 lines
Perhaps we should have a
kill_pgrp_self()which takes care of doing this, rather than open-coding it. Something with a comment which explains what's going on ;)
Quoted 5 lines
This
set_thread_flag(TIF_SIGPENDING)is "connected" to "return-ERESTARTSYS", not tokill_pgrp(), imho the new helper is not so suitable.Perhaps it makes sense to add the comment into
include/linux/errno.h, to explain that-ERESTART... codes are only valid whensignal_pending()== true.
Like this?
Satoru
---
Add comment for errnos related to restart syscall to avoid the leakage of kernel only errnos.
include/linux/errno.h +5 -1
@@ -5,7 +5,11 @@#ifdef __KERNEL__ -/* Should never be seen by user programs */ +/* +* Should never be seen by user programs. Please note that returing +* `ERESTART*' errnos when `!signal_pending()' incurs the leakage of these +* errnos to user space. +*/ #define ERESTARTSYS 512#define ERESTARTNOINTR 513#define ERESTARTNOHAND 514/* restart if no handler.. */
Aside from typos, I think it should be more clearly and strongly worded.
"These should never be seen by user programs. To return one of these codes, signal_pending() MUST be set. Note that ptrace can observe these at syscall exit tracing, but they will never be left for the debugged user process to see."
Thanks,
Roland
At Wed, 30 May 2007 18:08:55 -0700 (PDT),
Quoted 7 lines · Roland McGrath
Aside from typos, I think it should be more clearly and strongly worded.
"These should never be seen by user programs. To return one of these codes,
signal_pending()MUST be set. Note that ptrace can observe these at syscall exit tracing, but they will never be left for the debugged user process to see."
Thanks, is that better?
Satoru
---
Add comment for errnos related to restart syscall to avoid the leakage of them to user programs.
include/linux/errno.h +6 -1
@@ -5,7 +5,12 @@#ifdef __KERNEL__ -/* Should never be seen by user programs */ +/* +* These should never be seen by user programs. To return one of ERESTART* +* codes, signal_pending() MUST be set. Note that ptrace can observe these +* at syscall exit tracing, but they will never be left for the debugged user +* process to see. +*/ #define ERESTARTSYS 512#define ERESTARTNOINTR 513#define ERESTARTNOHAND 514/* restart if no handler.. */
That looks good to me.
Thanks,
Roland