Burada tam olarak seccomp kullanım örneği var .
Seccomp kullanarak, sistem çağrılarını farklı şekillerde filtreleyebilirsiniz. Ne bu durumda ne istiyorum hemen sonra olan fork()
bir yüklemeye, seccomp
kullanımını izin vermez filtresi open(2)
, openat(2)
, socket(2)
(ve daha fazla). Bunu yapmak için aşağıdakileri yapabilirsiniz:
- İlk olarak,
seccomp_init(3)
varsayılan davranışı ile bir seccomp içeriği oluşturun SCMP_ACT_ALLOW
.
- Ardından
seccomp_rule_add(3)
, reddetmek istediğiniz her sistem çağrısı için bağlama bir kural ekleyin . Sen kullanabilirsiniz SCMP_ACT_KILL
syscall teşebbüs edilirse, süreci öldürmek için SCMP_ACT_ERRNO(val)
belirtilen dönen başarısız syscall yapmak errno
değeri, ya da başka action
kılavuz içinde tanımlanmış değeri.
seccomp_load(3)
Etkili hale getirmek için bağlamı kullanarak yükleyin .
Devam etmeden önce, bunun gibi bir kara liste yaklaşımının genel olarak beyaz liste yaklaşımından daha zayıf olduğunu unutmayın. Açıkça izin verilmeyen ve filtrenin atlanmasına neden olabilecek tüm sistem çağrılarına izin verir . Yürütmek istediğiniz alt işlemin filtreden kaçınmaya kötü niyetli olabileceğini düşünüyorsanız veya çocuklar tarafından hangi sistem çağrılarına ihtiyaç duyulacağını zaten biliyorsanız, beyaz liste yaklaşımı daha iyidir ve yukarıdakilerin tersini yapmanız gerekir: varsayılan eylemiyle filtre oluşturun SCMP_ACT_KILL
ve gerekli sistem çağrılarına izin verin SCMP_ACT_ALLOW
. Kod açısından fark minimumdur (beyaz liste muhtemelen daha uzundur, ancak adımlar aynıdır).
Yukarıda bir örnek ( exit(-1)
sadece basitlik uğruna hata durumunda yapıyorum ):
#include <stdlib.h>
#include <seccomp.h>
static void secure(void) {
int err;
scmp_filter_ctx ctx;
int blacklist[] = {
SCMP_SYS(open),
SCMP_SYS(openat),
SCMP_SYS(creat),
SCMP_SYS(socket),
SCMP_SYS(open_by_handle_at),
// ... possibly more ...
};
// Create a new seccomp context, allowing every syscall by default.
ctx = seccomp_init(SCMP_ACT_ALLOW);
if (ctx == NULL)
exit(-1);
/* Now add a filter for each syscall that you want to disallow.
In this case, we'll use SCMP_ACT_KILL to kill the process if it
attempts to execute the specified syscall. */
for (unsigned i = 0; i < sizeof(blacklist) / sizeof(blacklist[0]); i++) {
err = seccomp_rule_add(ctx, SCMP_ACT_KILL, blacklist[i], 0);
if (err)
exit(-1);
}
// Load the context making it effective.
err = seccomp_load(ctx);
if (err)
exit(-1);
}
Şimdi, programınızda, aşağıdaki gibi seccomp filtresini uygulamak için yukarıdaki işlevi çağırabilirsiniz fork()
:
child_pid = fork();
if (child_pid == -1)
exit(-1);
if (child_pid == 0) {
secure();
// Child code here...
exit(0);
} else {
// Parent code here...
}
Seccomp ile ilgili birkaç önemli not:
- Bir seccomp filtresi uygulandıktan sonra işlem tarafından kaldırılamaz veya değiştirilemez.
- Filtre tarafından izin verilirse
fork(2)
veya clone(2)
izin verilirse, alt süreçler aynı filtre tarafından kısıtlanır.
- Eğer
execve(2)
izin verilir, mevcut filtre bir çağrı karşısında korunacaktır execve(2)
.
- Eğer
prctl(2)
syscall izin verilir, süreç daha da filtreler uygulamak yapabiliyor.