5

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?

  • 39
    I hate that @xxlali refuses to tell us why this is needed. – Digital Chris Jun 22 '16 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 Jun 22 '16 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? – Conspicuous Compiler Jun 22 '16 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 Jun 23 '16 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 Jun 24 '16 at 12:01
53

"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
    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.$$; } – Peter Cordes Jun 22 '16 at 10:20
  • 8
    @PeterCordes \kill will bypass the alias too. – Andrew Henle Jun 22 '16 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). – Peter Cordes Jun 22 '16 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. – David Richerby Jun 22 '16 at 18:37
63

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.

  • 71
    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 – Kamil Maciorowski Jun 22 '16 at 10:57
  • 11
    This is my favourite Stack Exchange answer. – cat Jun 22 '16 at 16:16
  • 41
    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 Jun 22 '16 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. – Peter Cordes Jun 22 '16 at 19:52
  • 14
    Can someone please insert this module in a VM and post a recording of what happens on YouTube? – Daniel McLaury Jun 23 '16 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.

  • 1
    Well, how can I do that. I am not an advanced linux user. – xxlali Jun 22 '16 at 7:07
  • @xxlali see the update – ivan_pozdeev Jun 22 '16 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 Jun 22 '16 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 Young Jun 23 '16 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 Jun 24 '16 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
    $process and $@ should be "double quoted" – cat Jul 16 '16 at 11:37

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.