When fulltest runs from the shell, the TTY's tty_session_id is already
set to the shell's session. The test's leader child calls setsid() then
TIOCSPGRP, which fails with EPERM because the new session doesn't match
tty_session_id. The kernel never allowed a new session leader to claim
the TTY as its controlling terminal.
Fix: in TIOCSPGRP handler for both tty.c and pty.c, allow a session
leader (session_id == pid) to claim the terminal by updating the
session when it explicitly sets its own pgrp as foreground. This
matches POSIX semantics where a session leader may establish a new
controlling terminal.
Test results: 103/103 smoke test PASS, 16/16 battery PASS.
return 0;
}
- if (current_process->session_id != p->session_id) return -EPERM;
+ if (current_process->session_id != p->session_id) {
+ /* Allow a session leader to claim the PTY as its controlling
+ * terminal by setting its own process group as foreground. */
+ if (current_process->session_id == current_process->pid &&
+ (uint32_t)fg == current_process->pgrp_id) {
+ p->session_id = current_process->session_id;
+ p->fg_pgrp = (uint32_t)fg;
+ return 0;
+ }
+ return -EPERM;
+ }
if (fg < 0) return -EINVAL;
p->fg_pgrp = (uint32_t)fg;
return 0;
return 0;
}
- if (current_process->session_id != tty_session_id) return -EPERM;
+ if (current_process->session_id != tty_session_id) {
+ /* Allow a session leader to claim the TTY as its controlling
+ * terminal by setting its own process group as foreground.
+ * POSIX: a session leader may take control of a terminal
+ * when explicitly establishing a new controlling terminal. */
+ if (current_process->session_id == current_process->pid &&
+ (uint32_t)fg == current_process->pgrp_id) {
+ tty_session_id = current_process->session_id;
+ tty_fg_pgrp = (uint32_t)fg;
+ return 0;
+ }
+ return -EPERM;
+ }
if (fg < 0) return -EINVAL;
tty_fg_pgrp = (uint32_t)fg;
return 0;