How to disable the 'kill' command on Linux

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?


Solution 1:

"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

Solution 2:

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.

Solution 3:

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.