Skip to contentSkip to conversation

tty: fix leakage of -ERESTARTSYS to userland

PATCH In review Oleg Nesterov 4 participants 7 messages May 29, 2007 – May 31, 2007 Char and misc drivers

lore
Share & tools
lore
#0 lore raw

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;
 }
 
#1 lore raw
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 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 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 ;)

#2 lore raw
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.

#3 lore raw

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 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.

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
Index: linux-2.6.22-rc3/include/linux/errno.h
===================================================================
@@ -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.. */
#4 lore raw

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

#5 lore raw

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.

Cc Oleg Nesterov <[email protected]>
Cc Roland McGrath <[email protected]>
include/linux/errno.h +6 -1
Index: linux-2.6.22-rc3/include/linux/errno.h
===================================================================
@@ -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.. */