4

I want to disable all kill commands (including root user). I have tried to change permissions, but it still can be executed. Is there a way to do that?

10
  • 42
    I hate that @xxlali refuses to tell us why this is needed. Commented Jun 22, 2016 at 19:41
  • 2
    Except for the kernel module that disables the syscall, the user can always write his/her own kill executable by calling the c function kill.
    – Siyuan Ren
    Commented Jun 22, 2016 at 20:23
  • 9
    Could you explain why you want to disable kill on your system? Do you have processes being terminated by people with root privileges which you don't want being terminated? Commented Jun 22, 2016 at 21:41
  • 3
    Which kill? You can send different signals with kill: 1 HUP 2 INT 3 QUIT 4 ILL 5 TRAP 6 ABRT 7 BUS 8 FPE 9 KILL 10 USR1 11 SEGV 12 USR2 13 PIPE 14 ALRM 15 TERM 16 STKFLT 17 CHLD 18 CONT 19 STOP 20 TSTP 21 TTIN 22 TTOU 23 URG 24 XCPU 25 XFSZ 26 VTALRM 27 PROF 28 WINCH 29 POLL 30 PWR 31 SYS
    – Lenne
    Commented Jun 23, 2016 at 0:21
  • 3
    @DigitalChris I have a program. There is another way to stop this program, but some users prefer the stop this program using 'kill -9 %pid%' which causes unwanted results. So, I want to force users to use normal way stop. This is why I want to disable kill command usage. (Please don't hate me :) )
    – xxlali
    Commented Jun 24, 2016 at 12:01

4 Answers 4

56

"Disabling" kill for root, even if it was possible, would most likely have unwanted side-effects, like system scripts malfunctioning, and in the worst (but likely) scenario it would prevent your computer from starting up properly (or even shutting down properly).

For a user, too, it would cause issues. I have, for example, scripts that I run as an unprivileged user, that checks to see if certain processes are running using kill -0 $pid. Those scripts would stop working.

For yourself, you could alias the kill command to something else, like echo "kill":

$ alias kill='echo "kill"'

That would prevent kill from doing anything useful on the command line at least:

$ kill -s HUP $$
kill -s HUP 11985
4
  • 4
    Disabling kill only for interactive use is the only sane answer, so +1. If you do want to use it from an interactive shell with this alias, just run /bin/kill ..., or builtin kill ... or command kill to suppress function/alias lookup. Bash has keywords to override the default command lookup. The normal use-case is in wrapper functions, e.g. cd(){ command cd "$@"; pwd > /tmp/here.$$; } Commented Jun 22, 2016 at 10:20
  • 8
    @PeterCordes \kill will bypass the alias too. Commented Jun 22, 2016 at 10:45
  • @AndrewHenle: Oh right, I used to use \rm fairly often when I had it aliased to rm -i (instead of my current choice of rm -I). Commented Jun 22, 2016 at 16:18
  • @PeterCordes If you somehow disabled kill for interactive use, the trivial work-around would be to invoke kill via a wrapper script. Commented Jun 22, 2016 at 18:37
70

Use this kernel module to disable the kill system call on amd64.
Use at your own risk. Devastating side effects are expected.

#include <linux/module.h>

MODULE_LICENSE("GPL");

int __init init(void) __attribute__((noreturn))
{
     unsigned long long cr0 = read_cr0();
     write_cr0(cr0 & ~(1 << 16));  /* Clear Write Protection (WP) bit */
     *(unsigned char *)sys_kill = 0xc3;  /* opcode for "ret" */
     write_cr0(cr0);

     /* This makes sure that delete_module below won't complain */
     __this_module.refcnt = 1;
     __this_module.state = MODULE_STATE_LIVE;

     asm volatile
     (
          "mov %0, %%rsp\n\t" /* It seems GCC refuses to mess with the stack pointer */
          "jmp sys_delete_module\n\t"  /* call delete_module(name, flags) */
          :: "r"(current->stack + THREAD_SIZE - sizeof(struct pt_regs) - 8), "D"(__this_module.name), "S"(0) :
     );
}

void __exit exit(void)
{
    return;
}

Compile it like you would any other module. Then use insmod on it.

14
  • 74
    It's amazing how you can count on people to hand you multiple guns to shoot yourself in the foot if you ask for it. Including kernel module. :D Commented Jun 22, 2016 at 10:57
  • 13
    This is my favourite Stack Exchange answer.
    – cat
    Commented Jun 22, 2016 at 16:16
  • 42
    Hopefully at least anyone who knows how to "compile it like you would any other module" knows how much of a bad idea this is.
    – Random832
    Commented Jun 22, 2016 at 16:45
  • 5
    Interesting, I guess you modify %rsp before tail-calling sys_delete_module so the return address is outside the deleted function. Anyway, always use constraints to ask for your data in the right register, instead of using mov instructions. e.g. use "D"(__this_module.name) to ask for it in %rdi in the first place. A mov at the start or end of an inline asm block of code is almost always sub-optimal, and better left to the compiler. I don't think there's a constraint for %rsp, though, and I know there aren't constraints for any of %r8 through %r15. Commented Jun 22, 2016 at 19:52
  • 15
    Can someone please insert this module in a VM and post a recording of what happens on YouTube? Commented Jun 23, 2016 at 4:12
7

You should not disable it system-wide, because it's used in system scripts (e.g., in /etc/init.d/functions in the initscripts package).

You can disable it for the login shell (and its subshells) by alias'ing it to, say, true/false (or something like kill_disabled if you wish to get an error rather than a no-op).

Note that this way is not fool-proof: it will only affect commands executed directly (not those inside scripts). And the user will be able to remove the alias with unalias.


To do this, run the following command

alias kill=kill_disabled

or add it to an appropriate bash startup file to run it at every login.

Now, running kill interactively will produce:

$ kill 9999
-bash: kill_disabled: command not found

As I said, the above way is easily subverted. If you need a fool-proof way, the only solution is to run the entire login shell session in a chroot environment. It will still only disable the stock command, not a direct syscall, however done. The latter cannot be disabled, because it's essential for normal operation (e.g., every Ctrl + C sends SIGINT, pipes require SIGPIPE, and background processes are controlled with more than five different signals). Setting up a chroot environment is an advanced task and it's generally inconvenient if the user needs to access the entire filesystem.

6
  • 1
    Well, how can I do that. I am not an advanced linux user.
    – xxlali
    Commented Jun 22, 2016 at 7:07
  • @xxlali see the update Commented Jun 22, 2016 at 8:13
  • 2
    Uh if you run it in a chroot nothing stops you making the kill syscall directly from e.g. another application, which could even be one you compiled and uploaded into the chroot. (Byte by byte if you cared enough). Chroot is nowhere near foolproof. Short of hobbling the system call inside the kernel nothing can stop it completely.
    – Flexo
    Commented Jun 22, 2016 at 20:32
  • 1
    @xxlali What are you trying to do? The fact that you are not an advanced user makes it even more likely that disabling kill is not what you should actually be doing to solve the problem you're having...
    – David
    Commented Jun 23, 2016 at 23:36
  • 1
    @DavidYoung I have a program. There is another way to stop this program, but some users prefer the stop this program using 'kill -9 %pid%' which causes unwanted results. So, I want to force users to use normal way stop. This is why I want to disable kill command usage.
    – xxlali
    Commented Jun 24, 2016 at 11:59
4

If you want the users to be able to use kill normally except for when they try to kill your specific program, you can define a kill function in the .bashrc of the user profile and within this function, check if the user is trying to kill your program. If not, you can call the kill utility from within your function itself.

As an example, I wrote a small kill function which will not kill the sleep utility but will function as a normal kill utility for any other parameter provided to it.

function kill() {
    process=$(ps -p "${@: -1}" | awk 'END{print $(NF)}');
    if [[ $process == "sleep"]]
    then
        echo "Killing $process is not allowed"
    else
        /bin/kill $@
    fi
}
1
  • 1
    $process and $@ should be "double quoted"
    – cat
    Commented Jul 16, 2016 at 11:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .