非rootユーザーがrootユーザーのプロセスにシグナルを送信するとどうなりますか?


33

UNIXシグナルのセキュリティについて疑問に思っています。

SIGKILLプロセスを強制終了します。では、非rootユーザーのプロセスがrootユーザーのプロセスにシグナルを送信するとどうなりますか?プロセスはまだシグナルハンドラを実行しますか?

私は受け入れられた答え(ゴラム)に従い、タイプしますman capabilites、そして、Linuxカーネルに関する多くのことを見つけます。からman capabilities

NAME

   capabilities - overview of Linux capabilities
DESCRIPTION

   For the purpose of performing permission checks, traditional UNIX
   implementations distinguish two categories of processes: privileged
   processes (whose effective user ID is 0, referred to as superuser or
   root), and unprivileged processes (whose effective UID is nonzero).
   Privileged processes bypass all kernel permission checks, while
   unprivileged processes are subject to full permission checking based
   on the process's credentials (usually: effective UID, effective GID,
   and supplementary group list).

   Starting with kernel 2.2, Linux divides the privileges traditionally
   associated with superuser into distinct units, known as capabilities,
   which can be independently enabled and disabled.  Capabilities are a
   per-thread attribute.

5
以外のSIGKILL特殊なケースで、カーネルによって完全に管理され、信号は単に要求されています。受信プロセスは、彼らが望むあらゆることをすることができます。
-chepner

3
以外@chepner SIGKILL SIGSTOP ...
jlliagre

1
@chepner受信プロセスは、信号を処理することを積極的に決定する必要があります。受信プロセスがそうしていない場合、多くのシグナルがデフォルトでプロセスを完全に強制終了しSIGKILLます。当初SIGINTSIGKILLSIGTERMまったく同じ効果がありますが、唯一の違いは、受信プロセスは、それらのいくつかのために、このデフォルトを変更することができるということです。
カスペルド

回答:


34

Linuxでは、ファイル機能に依存します。

次の簡単なmykill.cソースを使用します。

#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>

void exit_usage(const char *prog) {
        printf("usage: %s -<signal> <pid>\n", prog);
        exit(1);
}

int main(int argc, char **argv) {
        pid_t pid;
        int sig;

        if (argc != 3)
                exit_usage(argv[0]);

        sig = atoi(argv[1]);
        pid = atoi(argv[2]);

        if (sig >= 0 || pid < 2)
                exit_usage(argv[0]);

        if (kill(pid, -sig) == -1) {
                perror("failed");
                return 1;
        }
        printf("successfully sent signal %d to process %d\n", -sig, pid);

        return 0;
}

ビルドする:

gcc -Wall mykill.c -o /tmp/mykill

ユーザーrootがバックグラウンドでスリーププロセスを開始するようになりました:

root@horny:/root# /bin/sleep 3600 &
[1] 16098

今、通常のユーザーがそれを殺そうとしています:

demouser@horny:/home/demouser$ ps aux | grep sleep
root     16098  0.0  0.0  11652   696 pts/20   S    15:06   0:00 sleep 500

demouser@horny:/home/demouser$ /tmp/mykill -9 16098
failed: Operation not permitted

これで、rootユーザーが/tmp/mykill上限を変更します。

root@horny:/root# setcap cap_kill+ep /tmp/mykill

そして、通常のユーザーとして再試行してください。

demouser@horny:/home/demouser$ /tmp/mykill -9 16098
successfully sent signal 9 to process 16098

最後/tmp/mykillに明らかな理由で削除してください;)


3
あなたの手がかりに従って、「man capabilities」と入力すると、Linuxカーネルについて多くのことがわかります
-lovespring

24

なし:

strace kill -HUP 1
[...]
kill(1, SIGHUP)    = -1 EPERM (Operation not permitted)
[...]

1
この種のセキュリティは、OSレベルで実行されるのですか、それともユーザーのシグナルハンドラでハードコーディングされるのですか?
-lovespring

3
@lovespringカーネルはターゲットプロセスにシグナルを配信しません。syscallはエラーとともに返され、無視されます。
ハウケレイジング

一般的にはそうではありません。機能に依存します。
ゴラム

1
@psmearsはありますが、他の概念も同様です(例:solarisの「特権」)。したがって、「Nothing」という答えは間違いです。
ゴラム

1
@gollum:それは正確に間違っているわけではありませ(結局、これはすべてのUnixファミリOSでのデフォルトの動作であり、多くの-たとえば古いLinuxカーネルを含む-で唯一可能なデフォルト動作です)サポートされている場所について詳しく説明しない「機能」は、一般的なUnixに関する質問でも不完全です:)
psmears

5

kill(2) manページの説明:

Linuxのメモ

さまざまなカーネルバージョン間で、Linuxは特権のないプロセスが別のプロセスにシグナルを送信するために必要なアクセス許可に対して異なるルールを適用しています。カーネル1.0から1.2.2では、送信者の有効なユーザーIDが受信者のユーザーIDと一致した場合、または送信者の実際のユーザーIDが受信者のユーザーIDと一致した場合、信号を送信できます。カーネル1.2.3から1.3.77まで、送信者の有効なユーザーIDが受信者の実際のユーザーIDまたは有効なユーザーIDのいずれかと一致した場合、信号を送信できます。POSIX.1-2001に準拠する現在のルールは、カーネル1.3.78で採用されました。


1.3.78は1.3のように非常に古い歴史です。1995年頃からの日付。1.3は2.0までの開発シリーズでした(1996年)
フォンブランド

-1

シグナルは伝達されますが、プロセス所有者はルートに属します。そのため、他のユーザーにはプロセスを終了する権限がないため、許可エラーの問題が発生します。

プロセスの終了は、プロセスの所有権(所有権)を所有している場合にのみ可能です。


いいえ、sys_killは-1を返し、errnoは-EPERMになります。
ペテルはモニカを
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.