Libro "BPF for Linux Monitoring"

Libro "BPF for Linux Monitoring"Ola, veciños de Khabro! A máquina virtual BPF é un dos compoñentes máis importantes do núcleo de Linux. O seu uso axeitado permitirá aos enxeñeiros do sistema atopar fallos e resolver ata os problemas máis complexos. Aprenderá a escribir programas que supervisan e modifican o comportamento do núcleo, a implementar código de forma segura para supervisar eventos no núcleo e moito máis. David Calavera e Lorenzo Fontana axudaranche a desbloquear o poder de BPF. Amplía os teus coñecementos sobre optimización de rendemento, redes e seguridade. - Use BPF para supervisar e modificar o comportamento do núcleo de Linux. - Inxecta código para supervisar de forma segura os eventos do núcleo sen ter que recompilar o núcleo ou reiniciar o sistema. — Use exemplos de código convenientes en C, Go ou Python. - Toma o control sendo propietario do ciclo de vida do programa BPF.

Seguridade do núcleo de Linux, as súas características e Seccomp

BPF ofrece un xeito poderoso de estender o núcleo sen sacrificar a estabilidade, a seguridade ou a velocidade. Por este motivo, os desenvolvedores do núcleo pensaron que sería unha boa idea utilizar a súa versatilidade para mellorar o illamento de procesos en Seccomp implementando filtros Seccomp soportados por programas BPF, tamén coñecidos como Seccomp BPF. Neste capítulo explicaremos que é Seccomp e como se usa. Despois aprenderás a escribir filtros Seccop usando programas BPF. Despois diso, veremos os ganchos BPF integrados que se inclúen no núcleo para os módulos de seguridade de Linux.

Os módulos de seguridade de Linux (LSM) son un marco que proporciona un conxunto de funcións que se poden usar para implementar varios modelos de seguridade de forma estandarizada. LSM pódese usar directamente na árbore de fontes do núcleo, como Apparmor, SELinux e Tomoyo.

Comecemos discutindo as capacidades de Linux.

Capacidades

A esencia das capacidades de Linux é que cómpre outorgar a un proceso sen privilexios permisos para realizar unha determinada tarefa, pero sen usar suid para ese fin, ou doutro xeito facer que o proceso sexa privilexiado, reducindo a posibilidade de ataque e permitindo que o proceso realice determinadas tarefas. Por exemplo, se a súa aplicación precisa abrir un porto privilexiado, digamos 80, en lugar de executar o proceso como root, pode simplemente darlle a capacidade CAP_NET_BIND_SERVICE.

Considere un programa Go chamado main.go:

package main
import (
            "net/http"
            "log"
)
func main() {
     log.Fatalf("%v", http.ListenAndServe(":80", nil))
}

Este programa serve un servidor HTTP no porto 80 (este é un porto privilexiado). Normalmente executámolo inmediatamente despois da compilación:

$ go build -o capabilities main.go
$ ./capabilities

Non obstante, como non estamos a conceder privilexios de root, este código xerará un erro ao vincular o porto:

2019/04/25 23:17:06 listen tcp :80: bind: permission denied
exit status 1

capsh (xestor de shell) é unha ferramenta que executa un shell cun conxunto específico de capacidades.

Neste caso, como xa se mencionou, en lugar de conceder dereitos de root completos, pode activar a vinculación de portos privilexiados proporcionando a capacidade cap_net_bind_service xunto con todo o que xa está no programa. Para iso, podemos incluír o noso programa en capsh:

# capsh --caps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep' 
   --keep=1 --user="nobody" 
   --addamb=cap_net_bind_service -- -c "./capabilities"

Entendemos un pouco a este equipo.

  • capsh - use capsh como shell.
  • —caps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep' - xa que necesitamos cambiar o usuario (non queremos executar como root), especificaremos cap_net_bind_service e a posibilidade de cambiar realmente o ID de usuario de root para ninguén, é dicir, cap_setuid e cap_setgid.
  • —keep=1 — queremos manter as capacidades instaladas ao cambiar desde a conta root.
  • —user=“ninguén” — o usuario final que executa o programa será ninguén.
  • —addamb=cap_net_bind_service — establece a eliminación das capacidades relacionadas despois de cambiar do modo raíz.
  • - -c "./capabilities" - simplemente executa o programa.

As capacidades vinculadas son un tipo especial de capacidades que herdan os programas fillos cando o programa actual as executa mediante execve(). Só se poden herdar as capacidades que se permiten asociar, ou noutras palabras, como capacidades do entorno.

Probablemente se estea a preguntar que significa +eip despois de especificar a capacidade na opción --caps. Estas bandeiras úsanse para determinar que a capacidade:

-debe estar activado (p);

- dispoñible para o seu uso (e);

-pode ser herdado por procesos fillos (i).

Xa que queremos usar cap_net_bind_service, necesitamos facelo coa bandeira e. A continuación, iniciaremos o shell no comando. Isto executará o binario de capacidades e necesitamos marcalo coa bandeira i. Finalmente, queremos que se habilite a función (fixemos isto sen cambiar o UID) coa p. Parece que cap_net_bind_service+eip.

Podes comprobar o resultado usando ss. Acurtemos un pouco a saída para que encaixa na páxina, pero mostrará o porto asociado e o ID de usuario distinto de 0, neste caso 65:

# ss -tulpn -e -H | cut -d' ' -f17-
128 *:80 *:*
users:(("capabilities",pid=30040,fd=3)) uid:65534 ino:11311579 sk:2c v6only:0

Neste exemplo usamos capsh, pero podes escribir un shell usando libcap. Para obter máis información, consulte man 3 libcap.

Ao escribir programas, moitas veces o programador non coñece de antemán todas as funcións que necesita o programa no momento da execución; Ademais, estas características poden cambiar nas novas versións.

Para comprender mellor as capacidades do noso programa, podemos utilizar a ferramenta compatible con BCC, que configura o kprobe para a función do núcleo cap_capable:

/usr/share/bcc/tools/capable
TIME      UID  PID   TID   COMM               CAP    NAME           AUDIT
10:12:53 0 424     424     systemd-udevd 12 CAP_NET_ADMIN         1
10:12:57 0 1103   1101   timesync        25 CAP_SYS_TIME         1
10:12:57 0 19545 19545 capabilities       10 CAP_NET_BIND_SERVICE 1

Podemos conseguir o mesmo usando bpftrace cun kprobe dunha liña na función do núcleo cap_capable:

bpftrace -e 
   'kprobe:cap_capable {
      time("%H:%M:%S ");
      printf("%-6d %-6d %-16s %-4d %dn", uid, pid, comm, arg2, arg3);
    }' 
    | grep -i capabilities

Isto producirá algo como o seguinte se as capacidades do noso programa están habilitadas despois de kprobe:

12:01:56 1000 13524 capabilities 21 0
12:01:56 1000 13524 capabilities 21 0
12:01:56 1000 13524 capabilities 21 0
12:01:56 1000 13524 capabilities 12 0
12:01:56 1000 13524 capabilities 12 0
12:01:56 1000 13524 capabilities 12 0
12:01:56 1000 13524 capabilities 12 0
12:01:56 1000 13524 capabilities 10 1

A quinta columna son as capacidades que necesita o proceso e, dado que esta saída inclúe eventos que non sexan de auditoría, vemos todas as comprobacións que non sexan de auditoría e, finalmente, a capacidade necesaria coa marca de auditoría (última na saída) establecida en 1. Capacidade. un que nos interesa é CAP_NET_BIND_SERVICE, defínese como unha constante no código fonte do núcleo no ficheiro include/uapi/linux/ability.h co identificador 10:

/* Allows binding to TCP/UDP sockets below 1024 */
/* Allows binding to ATM VCIs below 32 */
#define CAP_NET_BIND_SERVICE 10<source lang="go">

As capacidades adoitan estar habilitadas en tempo de execución para contedores como runC ou Docker para permitirlles executar en modo sen privilexios, pero só se lles permiten as capacidades necesarias para executar a maioría das aplicacións. Cando unha aplicación require certas capacidades, Docker pode fornecelas usando --cap-add:

docker run -it --rm --cap-add=NET_ADMIN ubuntu ip link add dummy0 type dummy

Este comando dará ao contedor a capacidade CAP_NET_ADMIN, o que lle permitirá configurar unha ligazón de rede para engadir a interface dummy0.

A seguinte sección mostra como usar funcións como o filtrado, pero usando unha técnica diferente que nos permite implementar mediante programación os nosos propios filtros.

Seccomp

Seccomp significa Secure Computing e é unha capa de seguridade implementada no núcleo de Linux que permite aos desenvolvedores filtrar determinadas chamadas do sistema. Aínda que Seccomp é comparable en capacidades a Linux, a súa capacidade para xestionar determinadas chamadas ao sistema faino moito máis flexible en comparación con eles.

As funcións de Seccomp e Linux non son mutuamente excluíntes e adoitan usarse xuntos para beneficiarse de ambos enfoques. Por exemplo, pode querer darlle a un proceso a capacidade CAP_NET_ADMIN pero non permitir que acepte conexións de socket, bloqueando as chamadas do sistema accept e accept4.

O método de filtrado Seccomp baséase en filtros BPF que funcionan no modo SECCOMP_MODE_FILTER e o filtrado de chamadas ao sistema realízase do mesmo xeito que para os paquetes.

Os filtros Seccomp cárganse usando prctl mediante a operación PR_SET_SECCOMP. Estes filtros toman a forma dun programa BPF que se executa para cada paquete Seccomp representado pola estrutura seccomp_data. Esta estrutura contén a arquitectura de referencia, un punteiro ás instrucións do procesador no momento da chamada ao sistema e un máximo de seis argumentos de chamada ao sistema, expresados ​​como uint64.

Este é o aspecto da estrutura seccomp_data do código fonte do núcleo no ficheiro linux/seccomp.h:

struct seccomp_data {
int nr;
      __u32 arch;
      __u64 instruction_pointer;
      __u64 args[6];
};

Como podes ver nesta estrutura, podemos filtrar pola chamada do sistema, os seus argumentos ou unha combinación de ambos.

Despois de recibir cada paquete Seccop, o filtro debe realizar o procesamento para tomar unha decisión final e indicarlle ao núcleo o que debe facer a continuación. A decisión final exprésase mediante un dos valores de retorno (códigos de estado).

- SECCOMP_RET_KILL_PROCESS - mata todo o proceso inmediatamente despois de filtrar unha chamada ao sistema que non se executa por iso.

- SECCOMP_RET_KILL_THREAD: finaliza o fío actual inmediatamente despois de filtrar unha chamada ao sistema que non se executa por iso.

— SECCOMP_RET_KILL — alias para SECCOMP_RET_KILL_THREAD, deixado para compatibilidade con versións anteriores.

- SECCOMP_RET_TRAP: a chamada ao sistema está prohibida e o sinal SIGSYS (chamada de sistema incorrecta) envíase á tarefa que a chama.

- SECCOMP_RET_ERRNO: non se executa a chamada ao sistema e parte do valor de retorno do filtro SECCOMP_RET_DATA pásase ao espazo do usuario como valor errno. Dependendo da causa do erro, devólvense diferentes valores de erro. Na seguinte sección ofrécese unha lista de números de erro.

- SECCOMP_RET_TRACE - Úsase para notificar ao rastreador de ptrace usando - PTRACE_O_TRACESECCOMP para interceptar cando se executa unha chamada ao sistema para ver e controlar ese proceso. Se non se conecta un rastreador, devólvese un erro, errno establécese en -ENOSYS e non se executa a chamada ao sistema.

- SECCOMP_RET_LOG: a chamada do sistema está resolta e rexistrada.

- SECCOMP_RET_ALLOW: simplemente se permite a chamada ao sistema.

ptrace é unha chamada ao sistema para implementar mecanismos de rastrexo nun proceso chamado tracee, coa capacidade de supervisar e controlar a execución do proceso. O programa de rastrexo pode influír eficazmente na execución e modificar os rexistros de memoria do rastrexo. No contexto Seccomp, ptrace utilízase cando se activa polo código de estado SECCOMP_RET_TRACE, polo que o rastreador pode evitar que a chamada do sistema se execute e implemente a súa propia lóxica.

Seccomp erros

De cando en vez, mentres traballa con Seccomp, atopará varios erros, que se identifican por un valor de retorno do tipo SECCOMP_RET_ERRNO. Para informar dun erro, a chamada ao sistema seccomp devolverá -1 en lugar de 0.

Son posibles os seguintes erros:

- EACCESS: a persoa que chama non ten permiso para facer unha chamada ao sistema. Isto ocorre normalmente porque non ten privilexios CAP_SYS_ADMIN ou no_new_privs non está configurado usando prctl (diso falaremos máis tarde);

— EFAULT — os argumentos pasados ​​(args na estrutura seccomp_data) non teñen un enderezo válido;

— EINVAL — aquí pode haber catro razóns:

-a operación solicitada é descoñecida ou non soportada polo núcleo na configuración actual;

-as marcas especificadas non son válidas para a operación solicitada;

-operación inclúe BPF_ABS, pero hai problemas coa compensación especificada, que pode exceder o tamaño da estrutura seccomp_data;

-o número de instrucións pasadas ao filtro supera o máximo;

— ENOMEM — memoria insuficiente para executar o programa;

- EOPNOTSUPP - a operación indicaba que con SECCOMP_GET_ACTION_AVAIL a acción estaba dispoñible, pero o núcleo non admite devolucións en argumentos;

— ESRCH — produciuse un problema ao sincronizar outro fluxo;

- ENOSYS - Non hai ningún rastreador anexo á acción SECCOMP_RET_TRACE.

prctl é unha chamada de sistema que permite que un programa de espazo de usuario manipule (configure e obteña) aspectos específicos dun proceso, como a endianidade de bytes, nomes de fíos, modo de cálculo seguro (Seccomp), privilexios, eventos Perf, etc.

Seccomp pode parecerche unha tecnoloxía sandbox, pero non o é. Seccomp é unha utilidade que permite aos usuarios desenvolver un mecanismo sandbox. Agora vexamos como se crean os programas de interacción do usuario mediante un filtro chamado directamente pola chamada do sistema Seccomp.

Exemplo de filtro BPF Seccop

Aquí mostraremos como combinar as dúas accións comentadas anteriormente, a saber:

— escribiremos un programa Seccop BPF, que se utilizará como filtro con diferentes códigos de retorno en función das decisións tomadas;

— Cargue o filtro usando prctl.

Primeiro necesitas cabeceiras da biblioteca estándar e do núcleo de Linux:

#include <errno.h>
#include <linux/audit.h>
#include <linux/bpf.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <linux/unistd.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/prctl.h>
#include <unistd.h>

Antes de probar este exemplo, debemos asegurarnos de que o núcleo está compilado con CONFIG_SECCOMP e CONFIG_SECCOMP_FILTER definidos en y. Nunha máquina que funcione, pode comprobar isto así:

cat /proc/config.gz| zcat | grep -i CONFIG_SECCOMP

O resto do código é unha función install_filter de dúas partes. A primeira parte contén a nosa lista de instrucións de filtrado BPF:

static int install_filter(int nr, int arch, int error) {
  struct sock_filter filter[] = {
    BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (offsetof(struct seccomp_data, arch))),
    BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch, 0, 3),
    BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (offsetof(struct seccomp_data, nr))),
    BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1),
    BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (error & SECCOMP_RET_DATA)),
    BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
  };

As instrucións establécense usando as macros BPF_STMT e BPF_JUMP definidas no ficheiro linux/filter.h.
Imos pasar as instrucións.

- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, arch))) - o sistema carga e acumúlase a partir de BPF_LD en forma da palabra BPF_W, os datos do paquete están situados nun desplazamento fixo BPF_ABS.

- BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch, 0, 3) - comproba mediante BPF_JEQ se o valor da arquitectura na constante acumuladora BPF_K é igual a arch. Se é así, salta no desplazamento 0 á seguinte instrución, se non, salta no desplazamento 3 (neste caso) para lanzar un erro porque o arco non coincide.

- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, nr))) - Carga e acumula a partir de BPF_LD en forma da palabra BPF_W, que é o número de chamada do sistema contido na compensación fixa de BPF_ABS.

— BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1) — compara o número de chamada do sistema co valor da variable nr. Se son iguais, pasa á seguinte instrución e desactiva a chamada ao sistema; se non, permite a chamada ao sistema con SECCOMP_RET_ALLOW.

- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (erro e SECCOMP_RET_DATA)) - finaliza o programa con BPF_RET e, como resultado, produce un erro SECCOMP_RET_ERRNO co número da variable err.

- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW) - finaliza o programa con BPF_RET e permite que a chamada do sistema se execute mediante SECCOMP_RET_ALLOW.

SECCOMP É CBPF
Pode estarse preguntando por que se usa unha lista de instrucións en lugar dun obxecto ELF compilado ou un programa C compilado JIT.

Hai dúas razóns para iso.

• En primeiro lugar, Seccomp usa cBPF (BPF clásico) e non eBPF, o que significa: non ten rexistros, senón só un acumulador para almacenar o último resultado do cálculo, como se pode ver no exemplo.

• En segundo lugar, Seccomp acepta un punteiro a unha matriz de instrucións BPF directamente e nada máis. As macros que usamos simplemente axudan a especificar estas instrucións dun xeito amigable para o programador.

Se necesitas máis axuda para comprender esta montaxe, considera o pseudocódigo que fai o mesmo:

if (arch != AUDIT_ARCH_X86_64) {
    return SECCOMP_RET_ALLOW;
}
if (nr == __NR_write) {
    return SECCOMP_RET_ERRNO;
}
return SECCOMP_RET_ALLOW;

Despois de definir o código do filtro na estrutura socket_filter, cómpre definir un sock_fprog que conteña o código e a lonxitude calculada do filtro. Esta estrutura de datos é necesaria como argumento para declarar que o proceso se executará máis tarde:

struct sock_fprog prog = {
   .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
   .filter = filter,
};

Só queda unha cousa por facer na función install_filter: cargar o propio programa. Para iso, utilizamos prctl, tomando PR_SET_SECCOMP como opción para entrar en modo de computación segura. Despois dicímoslle ao modo que cargue o filtro usando SECCOMP_MODE_FILTER, que está contido na variable prog de tipo sock_fprog:

  if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
    perror("prctl(PR_SET_SECCOMP)");
    return 1;
  }
  return 0;
}

Finalmente, podemos usar a nosa función install_filter, pero antes necesitamos usar prctl para establecer PR_SET_NO_NEW_PRIVS para a execución actual e evitar así a situación na que os procesos fillos reciban máis privilexios que os seus pais. Con isto, podemos facer as seguintes chamadas prctl na función install_filter sen ter dereitos de root.

Agora podemos chamar á función install_filter. Imos bloquear todas as chamadas de sistema de escritura relacionadas coa arquitectura X86-64 e simplemente demos un permiso que bloquee todos os intentos. Despois de instalar o filtro, continuamos coa execución usando o primeiro argumento:

int main(int argc, char const *argv[]) {
  if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
   perror("prctl(NO_NEW_PRIVS)");
   return 1;
  }
   install_filter(__NR_write, AUDIT_ARCH_X86_64, EPERM);
  return system(argv[1]);
 }

Imos comezar. Para compilar o noso programa podemos usar clang ou gcc, de calquera xeito é só compilar o ficheiro main.c sen opcións especiais:

clang main.c -o filter-write

Como se indicou, bloqueamos todas as entradas do programa. Para probar isto, necesitas un programa que saia algo - ls parece un bo candidato. Así é como ela adoita comportarse:

ls -la
total 36
drwxr-xr-x 2 fntlnz users 4096 Apr 28 21:09 .
drwxr-xr-x 4 fntlnz users 4096 Apr 26 13:01 ..
-rwxr-xr-x 1 fntlnz users 16800 Apr 28 21:09 filter-write
-rw-r--r-- 1 fntlnz users 19 Apr 28 21:09 .gitignore
-rw-r--r-- 1 fntlnz users 1282 Apr 28 21:08 main.c

Marabilloso! Aquí tes como se usa o noso programa envoltorio: simplemente pasamos o programa que queremos probar como primeiro argumento:

./filter-write "ls -la"

Cando se executa, este programa produce unha saída completamente baleira. Non obstante, podemos usar strace para ver o que está a suceder:

strace -f ./filter-write "ls -la"

O resultado do traballo acúrtase moito, pero a parte correspondente mostra que os rexistros están bloqueados co erro EPERM, o mesmo que configuramos. Isto significa que o programa non sae nada porque non pode acceder á chamada do sistema de escritura:

[pid 25099] write(2, "ls: ", 4) = -1 EPERM (Operation not permitted)
[pid 25099] write(2, "write error", 11) = -1 EPERM (Operation not permitted)
[pid 25099] write(2, "n", 1) = -1 EPERM (Operation not permitted)

Agora comprendes como funciona Seccop BPF e tes unha boa idea do que podes facer con el. Pero non che gustaría conseguir o mesmo con eBPF en lugar de cBPF para aproveitar todo o seu poder?

Ao pensar nos programas eBPF, a maioría da xente pensa que simplemente os escribe e os carga con privilexios de administrador. Aínda que esta afirmación é xeralmente certa, o núcleo implementa un conxunto de mecanismos para protexer os obxectos eBPF en varios niveis. Estes mecanismos chámanse trampas BPF LSM.

Trampas BPF LSM

Para proporcionar un seguimento independente da arquitectura dos eventos do sistema, LSM implementa o concepto de trampas. Unha chamada de conexión é tecnicamente similar a unha chamada de sistema, pero é independente do sistema e está integrada coa infraestrutura. LSM proporciona un novo concepto no que unha capa de abstracción pode axudar a evitar os problemas que se atopan ao tratar con chamadas de sistema en diferentes arquitecturas.

No momento de escribir este artigo, o núcleo ten sete ganchos asociados aos programas BPF, e SELinux é o único LSM integrado que os implementa.

O código fonte das trampas está situado na árbore do núcleo no ficheiro include/linux/security.h:

extern int security_bpf(int cmd, union bpf_attr *attr, unsigned int size);
extern int security_bpf_map(struct bpf_map *map, fmode_t fmode);
extern int security_bpf_prog(struct bpf_prog *prog);
extern int security_bpf_map_alloc(struct bpf_map *map);
extern void security_bpf_map_free(struct bpf_map *map);
extern int security_bpf_prog_alloc(struct bpf_prog_aux *aux);
extern void security_bpf_prog_free(struct bpf_prog_aux *aux);

Cada un deles chamarase en diferentes fases de execución:

— security_bpf — realiza unha comprobación inicial das chamadas ao sistema BPF executadas;

- security_bpf_map - comproba cando o núcleo devolve un descritor de ficheiro para o mapa;

- security_bpf_prog - comproba cando o núcleo devolve un descritor de ficheiro para o programa eBPF;

— security_bpf_map_alloc — comproba se o campo de seguridade dentro dos mapas BPF está inicializado;

- security_bpf_map_free - comproba se o campo de seguranza está limpo dentro dos mapas BPF;

— security_bpf_prog_alloc — comproba se o campo de seguridade está inicializado dentro dos programas BPF;

- security_bpf_prog_free - comproba se o campo de seguridade está limpar dentro dos programas BPF.

Agora, vendo todo isto, entendemos: a idea detrás dos interceptores LSM BPF é que poden proporcionar protección a todos os obxectos eBPF, garantindo que só aqueles que teñan os privilexios axeitados poidan realizar operacións en tarxetas e programas.

Resumo

A seguridade non é algo que poidas implementar dun xeito único para todo o que queiras protexer. É importante poder protexer os sistemas a distintos niveis e de diferentes xeitos. Créao ou non, a mellor forma de asegurar un sistema é organizar diferentes niveis de protección desde diferentes posicións, de xeito que reducir a seguridade dun nivel non permita o acceso a todo o sistema. Os principais desenvolvedores fixeron un gran traballo ofrecéndonos un conxunto de diferentes capas e puntos de contacto. Agardamos que teñas unha boa comprensión do que son as capas e de como usar os programas BPF para traballar con elas.

Sobre os autores

David Calavera é o CTO de Netlify. Traballou no soporte de Docker e contribuíu ao desenvolvemento de ferramentas Runc, Go e BCC, así como a outros proxectos de código aberto. Coñecido polo seu traballo en proxectos Docker e no desenvolvemento do ecosistema de complementos Docker. David é moi apaixonado polos gráficos de chama e sempre busca optimizar o rendemento.

Lorenzo Fontana traballa no equipo de código aberto de Sysdig, onde se centra principalmente en Falco, un proxecto de Cloud Native Computing Foundation que proporciona seguridade no tempo de execución do contedor e detección de anomalías a través dun módulo do núcleo e eBPF. É un apaixonado polos sistemas distribuídos, as redes definidas por software, o núcleo de Linux e a análise de rendemento.

» Podes atopar máis detalles sobre o libro en sitio web da editorial
» Índice analítico
» Extracto

Para Khabrozhiteley 25% de desconto usando o cupón - Linux

Tras o pagamento da versión en papel do libro, enviarase un libro electrónico por correo electrónico.

Fonte: www.habr.com

Engadir un comentario