terminal
su
, 및 w3m
의 교차점 에서 발생하는 매우 이상한 문제가 있습니다 /dev/null
.
에서 su -
로 이동 하면 다음 명령이 작동하지 않습니다.user1
user2
$ w3m zz.html 2>/dev/null
Error occurred while reset 800b: errno=25
그러나 동일한 명령은 2>/dev/null
리디렉션 없이도 잘 작동합니다.
$ w3m zz.html
user2
마지막으로 (에서 전환하는 대신 ) 직접 로그인하면 user1
모든 것이 잘 작동합니다(있든 2>/dev/null
없든).
w3m
다음을 strace
실행 하면 strace -o zz.strace w3m zz.html 2>/dev/null
이 시점에서 두 가지 경우(작동 및 비작동)가 갈라지기 시작하는 것을 볼 수 있습니다.
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, TIOCGWINSZ, {ws_row=77, ws_col=199, ws_xpixel=0, ws_ypixel=0}) = 0
ioctl(2, TIOCGWINSZ, 0x7318fb8e7c40) = -1 ENOTTY (Inappropriate ioctl for device)
fstat(2, {st_mode=S_IFCHR|0666, st_rdev=makedev(0x1, 0x3), ...}) = 0
ioctl(2, TCGETS, 0x7318fb8e7400) = -1 ENOTTY (Inappropriate ioctl for device)
brk(0x16a51a8a1000) = 0x16a51a8a1000
brk(0x16a51a8b1000) = 0x16a51a8b1000
brk(0x16a51a8c2000) = 0x16a51a8c2000
brk(0x16a51a8d2000) = 0x16a51a8d2000
brk(0x16a51a8e8000) = 0x16a51a8e8000
ioctl(2, TCGETS, 0x7318fb8e7bd0) = -1 ENOTTY (Inappropriate ioctl for device)
ioctl(2, TCGETS, 0x7318fb8e7bc0) = -1 ENOTTY (Inappropriate ioctl for device)
ioctl(2, SNDCTL_TMR_START or TCSETS, {B0 -opost -isig -icanon -echo ...}) = -1 ENOTTY (Inappropriate ioctl for device)
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x7), ...}) = 0
write(1, "Error occurred while reset 800b:"..., 42) = 42
write(2, "\33[?1049h\33[22;0;0t\33[H\33[2J\33[39;49m"..., 58) = 58
ioctl(2, TCGETS, 0x7318fb8e7ba0) = -1 ENOTTY (Inappropriate ioctl for device)
ioctl(2, SNDCTL_TMR_START or TCSETS, {B0 -opost -isig -icanon -echo ...}) = -1 ENOTTY (Inappropriate ioctl for device)
exit_group(1) = ?
+++ exited with 1 +++
제가 아는 한, 이는 TIOCGWINSZ
ioctl
단말기 크기와 관련이 있는 것 같습니다. 하지만 이 문제의 원인이 정확히 무엇인지 찾을 수 없습니다.
답변1
댓글로 인해 업데이트되었습니다.
-
분명히 데비안은 이런 넌센스를 고쳤습니다. 문제의 핵심은 동일하게 하이브리드 환경입니다.
문제는 /proc/*/fd/*
!
의 훌륭한 답변을 인용하여사용자 1686, 좋아요를 누르는 것을 잊지 마세요sudo 이후 /dev/stderr에 대한 권한이 거부되었습니다..
문제의 핵심은 다음과 같습니다.
이는 Linux 구현의 /proc에 대한 잘 알려진 문제로 수년 동안 해결되지 않았습니다. Linux의 경우 /proc/ 아래의 링크를 엽니다./fd/파일 설명자는 dup()처럼 직접 복사되지 않습니다(이론적으로는 /proc 링크가 이를 달성할 수 있지만). 대신 파일을 다시 열고 새로운 권한 확인이 수행됩니다.
이 질문에 대한 원래 게시물은 Theodore Tso(2008!)에서 온 것입니다.Re: RFC: /dev/stdin, 심볼릭 링크 및 권한
해결책
pty
새로운 것을 얻을 시간이다사용자 B:
userA:~$ su -l -P userB
~에서남성페이지 su
:
-, -l, --login Start the shell as a login shell with an environment similar to a real login: • clears all the environment variables except TERM and variables specified by --whitelist-environment • initializes the environment variables HOME, SHELL, USER, LOGNAME, and PATH • changes to the target user’s home directory -P, --pty Create a pseudo-terminal for the session. The independent terminal provides better security as the user does not share a terminal with the original session. This can be used to avoid TIOCSTI ioctl terminal injection and other security attacks against terminal file descriptors. The entire session can also be moved to the background (e.g., su --pty - username -c application &). If the pseudo-terminal is enabled, then su works as a proxy between the sessions (sync stdin and stdout). This feature is mostly designed for interactive sessions. If the standard input is not a terminal, but for example a pipe (e.g., echo "date" | su --pty), then the ECHO flag
Debian Bookworm에서 테스트할 기회가 있었고 작동했습니다.
ghu@magnetron:/tmp$ w3m testing.html 2>/dev/null
Error occurred while reset 800b: errno=25
ughu@magnetron:/tmp$ exit
logout
tukan@magnetron:~/Downloads/html$ su -l -P ughu
Password:
ughu@magnetron:~$ cd /tmp
ughu@magnetron:/tmp$ w3m testing.html 2>/dev/null
ughu@magnetron:/tmp$ exit
OP 토론을 기반으로 편집
OP와 내 버전의 차이점( 2.33.1-0.1
vs 2.38.1-1.1+b1
- 여기에서 전체 버전)변경 로그).
OP stderr
는 su -
예를 들어 쉘 non-existing-command 2>/dev/null
또는 non-existing-command 2>/tmp/output
.
반면에 출력이 너무 길면(오류 메시지에 표시된 대로 ~2^15(32768)바이트로 재설정될 가능성이 높습니다.16진수:800b는 12월입니다.32768+0+0+11) 애플리케이션과 마찬가지로 w3m
재설정이 완료되고 사용자 권한을 다시 확인하지만 실패합니다.
내가 모르는 일부 패치는 util-linux 버전 2.33.1-0.1
과 2.38.1-1.1+b1
.
결론적으로
최신 버전을 사용해야 하는데(어떤 버전에서 작동하는지 모르겠습니다) 제 경우에는 스위치가 제대로 2.38.1-1.1+b1
작동했습니다 -P
. 그러면 w3m
위에 표시된 것처럼 대규모 출력에 대해서도 리디렉션이 작동합니다 .