web-dev-qa-db-ja.com

dlopen()を特定のパスから、または特定のパスに制限する方法は?

ファイルシステムでのプログラムの実行を無効にする場合は、noexecマウントオプションを使用できます。

ただし、これは動的ライブラリloaded throughdlopen()では機能しません。それで、naclまたはseccompでそれを行う方法は何ですか? (これは、信頼されていないバイトコードサンドボックス用です。ユーザーがアップロードした共有ライブラリを実行できないようにしたい)

同時に、gconvのようなライブラリはtheir.soモジュールを実行できる必要があります。
プログラムによる他のプログラムのfork()ingまたはexec()utingはすでに無効になっています。

6
user2284570

ただし、これは動的ライブラリでは機能しません。

動的ライブラリに対しては機能します。共有オブジェクトがnoexecオプションでマウントされたパーティションにある場合、それはロードできません。そうでない場合、noexecはまったく役に立たなくなります。

_$ grep -E '/tmp |ext4' /proc/mounts
/dev/mapper/root_crypt / ext4 rw,nodev,noatime,data=ordered 0 0
tmpfs /tmp tmpfs rw,nosuid,nodev,noexec,noatime,size=2031200k 0 0
$ cat > main.c
#include <stdio.h>

void main(void)
{
        printf("%d\n", getpid());
}
$ gcc -o main main.c
$ ./main
4950
$ cat > shared.c
int getpid(void)        
{
        return 1;
}
$ gcc -shared -fPIC -o shared.so shared.c
$ LD_PRELOAD=./shared.so ./main
1
$ mv shared.so /tmp
$ LD_PRELOAD=/tmp/shared.so ./main
ERROR: ld.so: object '/tmp/shared.so' from LD_PRELOAD cannot be preloaded (failed to map segment from shared object): ignored.
4978
_

信頼できない共有オブジェクトの実行を防止するためにseccompを使用したい場合は、mmap()mprotect()、および明らかにexecve()への呼び出しを制限することでそれを行うことができます。プロセスが_PROT_EXEC_で何もマップできないことを確認してください。ファイル記述子を使用して任意のデータをmmap()に渡すことができ、mprotect()はメモリの任意のページの権限を変更して実行可能にすることができるため、ファイルを制限するだけでは不十分です。さらに、この例はホワイトリストではなくブラックリストであるため、seccompサンドボックスから抜け出すために使用できるため、ptrace()引数へのアクセスを拒否する必要もあります。

_rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(mmap), 1,
    SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC, PROT_EXEC));
if (rc == -1)
    goto out;

rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCESS), SCMP_SYS(mprotect), 1,
    SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC, PROT_EXEC));
if (rc == -1)
    goto out;

rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCESS), SCMP_SYS(execve), 0);
if (rc == -1)
    goto out;

rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(ptrace), 1,
    SCMP_A0(SCMP_CMP_EQ, PTRACE_POKEUSER));
if (rc == -1)
    goto out;

rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(ptrace), 1,
    SCMP_A0(SCMP_CMP_EQ, PTRACE_SETREGS));
if (rc == -1)
    goto out;

rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(ptrace), 1,
    SCMP_A0(SCMP_CMP_EQ, PTRACE_SETREGSET));
if (rc == -1)
    goto out;
_

おそらく私が考えていなかったこのseccompスニペットをバイパスする方法がおそらくあるので、これはそれが何をするのかをあなたに与えるためだけです。

私はNaClを使用したことがないので、それを使用して実行を制限する方法はわかりません。

0
landmark