It is probably bug in SELinux policy with regards to semanage
binary (which has its own context semanage_t
) and /tmp
directory, which has its own context too - tmp_t
.
I was able to reproduce almost same results on my CentOS 5.6.
# file /tmp/users.txt
/tmp/users.txt: ERROR: cannot open `/tmp/users.txt' (No such file or directory)
# semanage login -l > /tmp/users.txt
# file /tmp/users.txt
/tmp/users.txt: empty
# semanage login -l >> /tmp/users.txt
# file /tmp/users.txt
/tmp/users.txt: empty
When I tried to use file in different directory I got normal results
# file /root/users.txt
/root/users.txt: ERROR: cannot open `/root/users.txt' (No such file or directory)
# semanage login -l > /root/users.txt
# file /root/users.txt
/root/users.txt: ASCII text
Difference between /tmp
and /root
is their contexts
# ls -Zd /root/
drwxr-x--- root root root:object_r:user_home_dir_t /root/
# ls -Zd /tmp/
drwxrwxrwt root root system_u:object_r:tmp_t /tmp/
And finally, after trying to redirect into file in /tmp
I have got following errors in /var/log/audit/audit.log
type=AVC msg=audit(1310971817.808:163242): avc: denied { write } for pid=10782 comm="semanage" path="/tmp/users.txt" dev=dm
-0 ino=37093377 scontext=user_u:system_r:semanage_t:s0 tcontext=user_u:object_r:tmp_t:s0 tclass=file
type=AVC msg=audit(1310971838.888:163255): avc: denied { append } for pid=11372 comm="semanage" path="/tmp/users.txt" dev=d
m-0 ino=37093377 scontext=user_u:system_r:semanage_t:s0 tcontext=user_u:object_r:tmp_t:s0 tclass=file
Interesting note: redirecting semanage
output to pipe works OK
#semanage login -l | tee /tmp/users.txt > /tmp/users1.txt
# file /tmp/users.txt
/tmp/users.txt: ASCII text
# file /tmp/users1.txt
/tmp/users1.txt: ASCII text
First, this isn't specific to bash. ATT ksh, dash and zsh behave the same way: they ignore SIGTERM and SIGQUIT during command line edition; as for mksh, it also doesn't quit but treats them like SIGINT.
Both the ksh manual and the bash manual justify ignoring SIGTERM in these terms:
so that kill 0
does not kill an interactive shell
kill 0
kills all processes in the process group that the shell is in¹. In a nutshell, the process group consists of all the processes running in the foreground on a terminal, or all the processes in a background or suspended job.
More precisely, this is what happens in modern shells with job control. In such shells, kill 0
wouldn't be useful, as the shell would be in a process group of its own. Older shells (or modern shells after set +m
) did not create process groups for background commands. So you could use the command kill 0
to kill all background commands without getting logged out.² Thus the kill 0
rationale looks like an old one which is no longer justified nowadays but kept for backward compatibility.
However there are other similar situations where making the shell immune is useful. Consider the case where you have processes hogging a terminal and you want to kill them without getting logged out. Many systems have a tool like pkill
which let you kill the processes running on a terminal. You can run pkill -t $TTY
or pkill -QUIT -t $TTY
to kill all processes that are running on the current terminal, except the shell which ignores the signal.
A shell normally goes away either when the user exits it (with a command like exit
or logout
), or when its terminal signals the end of the input (the user can cause this by pressing Ctrl+D) or goes away altogether. In this last case, the shell receives the signal SIGHUP, and it doesn't ignore that one.
For your use case of logging out of an X session, kill -15 -1
will do it, since it kills the terminal emulator which causes the shell to receive SIGHUP. It's in fact enough to kill the X server, but that requires finding its process ID. If you want the same command to work on a text session, you can use kill -15 -1; exit
. That's quite a dangerous command to have at your fingertips anyway.
¹ This doesn't seem to be mentioned in shell manuals as a rule; it's a feature of the underlying system call. It is mentioned explicitly in the POSIX specification.
² Nowadays, to do that, run jobs -l
to see a list of jobs with their process group ID, then kill -123 -456 …
to kill the process groups.
Best Answer
This only happens when bash is using the
readline
line editing library, and only whenbash
is waiting for input from the user.A
bash --noediting
will not be killed bySIGTERM
, nor willbash
kill itself if runningkill -TERM $$
.This happens because the
readline()
function used by bash to get input from the user, will install its own signal handler forSIGTERM
, and restore the original signal disposition before returning. If aSIGTERM
happens whilereadline
is waiting for input from the user,readline()
will returnNULL
.The bash function which calls
readline()
(yy_readline_get()
) will interpret aNULL
return asEOF
, causing the shell to exit. The scenario is quite similar to that from this answer.This means that an interactive bash could be also made to survive a
SIGTERM
by settingIGNOREEOF
;-):