出于教育原因,我想改变kill
的行为。如果用户直接在shell中键入它,则不会发生任何事情。如果某个其他程序/实体 - 谁不是用户调用它,它会正常执行。包装if语句可能就足够了,但我在if
中添加了什么?
编辑我不想在shell中执行此操作。我在问内核编程。
在内核源line 2296中,定义了kill
。我将在代码里面包装一个if语句。在该声明中,应该检查一下,调用它的人是用户还是只是某个进程。检查是我不知道如何实施的部分。
关于安全性
目标:
kill
答案 0 :(得分:4)
虽然其他答案在技术上是正确的,但我认为他们对这个问题过于严格。你想做的事情是不可能以100%可靠的方式做到,但你可以通过做出一些合理的假设来达到目的。
具体来说,如果您将交互式kill定义为:
然后你可以在处理系统调用时检查每个属性,并以这种方式做出选择。
有些方法不可靠(sudo + expect + sh应该适用于大多数这些检查),但它可能足以让你玩得开心。如何实施这些检查是一个较长的故事,可能每一点都值得拥有自己的问题。查看有关用户和pty设备的文档 - 这应该会给你一个好主意。
编辑:实际上,这可能甚至可以作为LKM实现。 Selinux可以做类似的检查。
答案 1 :(得分:2)
看起来你很困惑,不明白究竟是什么system call以及Linux计算机是如何工作的。 Everything 在某个进程通过系统调用 中完成。
应检查是否有人直接通过用户或某个流程来完成此操作
上面的句子毫无意义。一切都是通过一些系统调用完成的。用户的概念仅作为流程的“属性”存在,请参阅credentials(7)(因此“由用户直接完成”是模糊的)。阅读syscalls(2)并花几天时间阅读Advanced Linux Programming,然后提出一个更有针对性的问题。
(我真的相信你不应该在不知道上面的ALP书正在解释什么的情况下不敢修补内核;那么你会以不同的方式提出你的问题)
您应该花几天或几周阅读Operating Systems和Computer Architecture。您需要更准确地了解计算机的工作原理,这需要花费很多时间(可能很多years),这里的任何答案都无法涵盖所有这些。
当用户键入kill
时,他可能使用内置shell(类型which kill
和type kill
)并且shell调用kill(2)。当用户键入/bin/kill
时,execve(2)是一个将调用kill(2)的程序。并且该命令可能不是来自终端(例如echo kill $$ | sh
,然后该命令来自管道,或者echo kill 1234|at midnight
在用户交互之外发生杀死并且没有任何用户以交互方式使用计算机,从/var/spool/cron/atjobs/
中的某个文件读取命令,请参阅atd(8))在这两种情况下,内核只能看到SYS_kill
系统调用。
kill
上的行为可能会影响很多系统软件,所以在这样做时要小心。另请阅读signal(7)(某些信号不是来自kill(2))。
您可以使用isatty(STDIN_FILENO)
(请参阅isatty(3))来检测程序是否在终端中运行(无需修补内核,您只需修补shell)。但我给了几个不是的情况。您和您的用户也可以编写一个桌面应用程序(使用GTK或Qt)调用kill(2)并在桌面上启动(运行时可能没有连接任何终端,请阅读X11)
另见会话概念和setsid(2);最近基于systemd的Linux有一个我不熟悉的multi-seat概念(我不知道哪些内核与它有关)。
如果您只想更改运行某些(已识别的)shell的交互式终端的行为,则只需更改shell-with chsh(1) - (例如,修改它以删除其kill
内置,也许是为了避免shell执行/bin/kill
kill_ok_by_cred
},无需修补内核。但是这不会禁止高级用户编写一个调用execve(2)的小型C程序(甚至用C编写自己的shell并使用它),编译他的C源代码,并运行他刚编译的{{3}可执行文件另请参阅bash中的kill(2)。
如果您只想通过练习修补内核并更改ELF系统调用的行为来学习,则需要定义要过滤的过程。所以考虑制作restricted shell系统调用的流程,而不是“用户”(流程确实有多个用户ID)
BTW,修补内核非常困难(如果你希望它是可靠和安全的),因为根据定义它会影响整个Linux系统。经验法则是避免在可能的情况下修补内核 ....在您的情况下,看起来修补shell可能足以实现您的目标,所以更喜欢修补shell(或者修补shell)所有shell实际使用的kill(2) ...)修补内核。另请参阅kill(2)。也许你只是希望你的修补内核使用libc系统调用来拒绝LD_PRELOAD
tricks 1234(假设你的用户的uid是1234)(所以他需要{{3}可执行文件),但你的问题不是这样制定的。这可能很容易实现,可能是通过添加 if (uid_eq(1234, tcred->uid))
return 0;
(在Linux 4.4文件uid附近的第692行),就像
{{1}}
但我可能完全错了(除了一些驱动程序,我从来没有修补内核)。肯定会在几个小时kill(2)给出一个更权威的答案。
答案 2 :(得分:1)
您可以使用别名来更改命令的行为。别名仅适用于交互式shell。 Shell脚本忽略它们。例如:
$ alias kill='echo hello'
$ kill
hello
如果您希望别名始终可用,您可以将其添加到~/.bashrc
(或者如果您的shell不是bash,则为等效文件)。