Creo que adjuntar eBPF a kprobes/kretprobes le da acceso de lectura a los argumentos de la función y valores de retorno, pero no puede alterarlos. NO estoy 100% seguro; buenos lugares para pedir confirmación serían la lista de correo del proyecto IO Visor o el canal IRC (#iovisor en irc.oftc.net).
Como solución alternativa, sé que al menos puede cambiar el valor de retorno de una llamada al sistema con strace, con el -e
opción. Citando la página del manual:
-e inject=set[:error=errno|:retval=value][:signal=sig][:when=expr] Perform syscall tampering for the specified set of syscalls.
Además, hubo una presentación sobre esto y la inyección de fallas en Fosdem 2017, si es de su interés. Aquí hay un comando de ejemplo de las diapositivas:
strace -P precious.txt -efault=unlink:retval=0 unlink precious.txt
Editar: Como dijo Ben, eBPF en kprobes y puntos de seguimiento definitivamente es de solo lectura, para casos de uso de seguimiento y monitoreo. También recibí confirmación sobre esto en IRC.
Dentro de las sondas del kernel (kprobes), la máquina virtual eBPF tiene acceso de solo lectura a los parámetros de llamada al sistema y al valor devuelto.
Sin embargo, el programa eBPF tendrá un código de retorno propio. Es posible aplicar un perfil seccomp que atrape los códigos de retorno BPF (NO eBPF; gracias @qeole) e interrumpa la llamada al sistema durante la ejecución.
Las modificaciones de tiempo de ejecución permitidas son:
SECCOMP_RET_KILL
:Eliminación inmediata conSIGSYS
SECCOMP_RET_TRAP
:envía unSIGSYS
atrapable , dando la oportunidad de emular el syscallSECCOMP_RET_ERRNO
:Forzarerrno
valorSECCOMP_RET_TRACE
:Ceder la decisión a ptracer o establecererrno
a-ENOSYS
SECCOMP_RET_ALLOW
:Permitir
https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt
El SECCOMP_RET_TRACE
El método permite modificar la llamada al sistema realizada, los argumentos o el valor de retorno. Esto depende de la arquitectura y la modificación de las referencias externas obligatorias puede causar un error ENOSYS.
Lo hace pasando la ejecución a un ptrace de espacio de usuario en espera, que tiene la capacidad de modificar la memoria del proceso rastreado, los registros y los descriptores de archivos.
El rastreador debe llamar a ptrace y luego a waitpid. Un ejemplo:
ptrace(PTRACE_SETOPTIONS, tracee_pid, 0, PTRACE_O_TRACESECCOMP);
waitpid(tracee_pid, &status, 0);
http://man7.org/linux/man-pages/man2/ptrace.2.html
Cuando waitpid
devuelve, dependiendo del contenido de status
, uno puede recuperar el valor de retorno de seccomp usando el PTRACE_GETEVENTMSG
operación ptrace. Esto recuperará el seccomp SECCOMP_RET_DATA
valor, que es un campo de 16 bits establecido por el programa BPF. Ejemplo:
ptrace(PTRACE_GETEVENTMSG, tracee_pid, 0, &data);
Los argumentos de Syscall se pueden modificar en la memoria antes de continuar con la operación. Puede realizar una sola entrada o salida de llamada al sistema con el PTRACE_SYSCALL
paso. Los valores de retorno de Syscall se pueden modificar en el espacio de usuario antes de reanudar la ejecución; el programa subyacente no podrá ver que los valores de retorno de syscall se han modificado.
Una implementación de ejemplo:filtrar y modificar llamadas del sistema con seccomp y ptrace