{"id":15003677,"url":"https://github.com/trailofbits/krf","last_synced_at":"2025-05-16T04:05:21.429Z","repository":{"id":34195448,"uuid":"162038180","full_name":"trailofbits/krf","owner":"trailofbits","description":"A kernelspace syscall interceptor and randomized faulter","archived":false,"fork":false,"pushed_at":"2024-11-18T19:00:46.000Z","size":344,"stargazers_count":356,"open_issues_count":11,"forks_count":37,"subscribers_count":45,"default_branch":"master","last_synced_at":"2025-05-12T05:54:16.668Z","etag":null,"topics":["fault-injection","freebsd","hacktoberfest","linux-kernel","syscalls"],"latest_commit_sha":null,"homepage":"https://blog.trailofbits.com/2019/01/17/how-to-write-a-rootkit-without-really-trying/","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trailofbits.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-12-16T20:28:15.000Z","updated_at":"2025-05-07T22:25:43.000Z","dependencies_parsed_at":"2024-12-21T08:09:13.184Z","dependency_job_id":"16e119ce-ce9d-494a-a124-e0483fff1661","html_url":"https://github.com/trailofbits/krf","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Fkrf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Fkrf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Fkrf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Fkrf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trailofbits","download_url":"https://codeload.github.com/trailofbits/krf/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254464895,"owners_count":22075570,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fault-injection","freebsd","hacktoberfest","linux-kernel","syscalls"],"created_at":"2024-09-24T19:00:14.066Z","updated_at":"2025-05-16T04:05:16.420Z","avatar_url":"https://github.com/trailofbits.png","language":"C","readme":"KRF\n===\n\n[![CI](https://github.com/trailofbits/krf/actions/workflows/ci.yml/badge.svg)](https://github.com/trailofbits/krf/actions/workflows/ci.yml)\n\nKRF is a **K**ernelspace **R**andomized **F**aulter.\n\nIt currently supports the Linux and FreeBSD kernels.\n\n## What?\n\n[Fault injection](https://en.wikipedia.org/wiki/Fault_injection) is a software testing technique\nthat involves inducing failures (\"faults\") in the functions called by a program. If the callee\nhas failed to perform proper error checking and handling, these faults can result in unreliable\napplication behavior or exploitable vulnerabilities.\n\nUnlike the many userspace fault injection systems out there, KRF runs in kernelspace\nvia a loaded module. This has several advantages:\n\n* It works on static binaries, as it does not rely on `LD_PRELOAD` for injection.\n* Because it intercepts raw syscalls and not their libc wrappers, it can inject faults\ninto calls made by `syscall(3)` or inline assembly.\n* It's probably faster and less error-prone than futzing with `dlsym`.\n\nThere are also several disadvantages:\n\n* You'll probably need to build it yourself.\n* It probably only works on x86(_64), since it twiddles `cr0` manually. There is probably\nan architecture-independent way to do that in Linux, somewhere.\n* It's essentially a rootkit. You should definitely never, ever run it on a non-testing system.\n* It probably doesn't cover everything that the Linux kernel expects of syscalls, and may\ndestabilize its host in weird and difficult to reproduce ways.\n\n## How does it work?\n\nKRF rewrites the Linux or FreeBSD system call table: when configured via `krfctl`, KRF replaces faultable\nsyscalls with thin wrappers.\n\nEach wrapper then performs a check to see whether the call should be faulted using a configurable targeting system capable of targeting a specific `personality(2)`, PID, UID, and/or GID. If the process **shouldn't** be faulted, the original syscall is\ninvoked.\n\nFinally, the targeted call is faulted via a random failure function. For example,\na `read(2)` call might receive one of `EBADF`, `EINTR`, `EIO`, and so on.\n\nYou can read more about KRF's implementation\n[in our blog post](https://blog.trailofbits.com/2019/01/17/how-to-write-a-rootkit-without-really-trying/).\n\n## Setup\n\n### Compatibility\n\n**NOTE**: If you have Vagrant, just use the Vagrantfile and jump to the build steps.\n\nKRF should work on any recent-ish (4.15+) Linux kernel with `CONFIG_KALLSYMS=1`.\n\nThis includes the default kernel on Ubuntu 18.04 and probably many other recent distros.\n\n### Dependencies\n\n**NOTE**: Ignore this if you're using Vagrant.\n\nApart from a C toolchain (GCC is probably necessary for Linux), KRF's only dependencies should be\n`libelf`, the kernel headers, and Ruby (\u003e=2.4, for code generation).\n\nGNU Make is required on all platforms; FreeBSD *additionally* requires BSD Make.\n\nFor systems with `apt`:\n\n```bash\nsudo apt install gcc make libelf-dev ruby linux-headers-$(uname -r)\n```\n\n### Building\n\n```bash\ngit clone https://github.com/trailofbits/krf \u0026\u0026 cd krf\nmake -j$(nproc)\nsudo make install # Installs module to /lib/modules and utils to /usr/local/bin\nsudo make insmod # Loads module\n```\n\nor, if you're using Vagrant:\n\n```bash\ngit clone https://github.com/trailofbits/krf \u0026\u0026 cd krf\nvagrant up linux \u0026\u0026 vagrant ssh linux\n# inside the VM\ncd /vagrant\nmake -j$(nproc)\nsudo make install # Installs module to /lib/modules and utils to /usr/local/bin\nsudo make insmod # Loads module\n```\n\nor, for FreeBSD:\n\n```bash\ngit clone https://github.com/trailofbits/krf \u0026\u0026 cd krf\ncd vagrant up freebsd \u0026\u0026 vagrant ssh freebsd\n# inside the VM\ncd /vagrant\ngmake # NOT make!\ngmake install-module # Installs module to /boot/modules/\nsudo gmake install-utils # Installs utils to /usr/local/bin\ngmake insmod # Loads module\n```\n\n## Usage\n\nKRF has three components:\n\n* A kernel module (`krfx`)\n* An execution utility (`krfexec`)\n* A control utility (`krfctl`)\n* A kernel module logger (`krfmesg`)\n\nTo load the kernel module, run `make insmod`. To unload it, run `make rmmod`.\n\nFor first time use it might be useful to launch `sudo krfmesg` on a separate terminal to see messages logged from `krfx`.\n\nKRF begins in a neutral state: no syscalls will be intercepted or faulted until the user\nspecifies some behavior via `krfctl`:\n\n```bash\n# no induced faults, even with KRF loaded\nls\n\n# tell krf to fault read(2) and write(2) calls\n# note that krfctl requires root privileges\nsudo krfctl -F 'read,write'\n\n# tell krf to fault any program started by\n# krfexec, meaning a personality of 28\nsudo krfctl -T personality=28\n\n# may fault!\nkrfexec ls\n\n# tell krf to fault with a 1/100 (or 1%) probability\n# note that this value is represented as a reciprocal\n# so e.g. 1 means all faultable syscalls will fault\n# and 500 means that on average every 500 syscalls will fault (1/500 or 0.2%)\nsudo krfctl -p 100\n\n# tell krf to fault `io` profile (and so i/o related syscalls)\nsudo krfctl -P io\n\n# krfexec will pass options correctly as well\nkrfexec echo -n 'no newline'\n\n# clear the fault specification\nsudo krfctl -c\n\n# clear the targeting specification\nsudo krfctl -C\n\n# no induced faults, since no syscalls are being faulted\nkrfexec firefox\n```\n\n## Configuration\n\n**NOTE**: Most users should use `krfctl` instead of manipulating these files by hand.\nIn FreeBSD, these same values are accessible through `sysctl krf.whatever` instead of procfs.\n\n### `/proc/krf/rng_state`\n\nThis file allows a user to read and modify the internal state of KRF's PRNG.\n\nFor example, each of the following will correctly update the state:\n\n```bash\necho \"1234\" | sudo tee /proc/krf/rng_state\necho \"0777\" | sudo tee /proc/krf/rng_state\necho \"0xFF\" | sudo tee /proc/krf/rng_state\n```\n\nThe state is a 32-bit unsigned integer; attempting to change it beyond that will fail.\n\n### `/proc/krf/targeting`\n\nThis file allows a user set the values used by KRF for syscall\ntargeting.\n\n**NOTE**: KRF uses a default personality not currently used by the Linux kernel by default. If you change\nthis, you should be careful to avoid making it something that Linux cares about. `man 2 personality`\nhas the details.\n\n```bash\necho \"0 28\" | sudo tee /proc/krf/targeting\n```\n\nA personality of 28 is hardcoded into `krfexec`, and must be set in order for things executed\nby `krfexec` to be faulted.\n\n### `/proc/krf/probability`\n\nThis file allows a user to read and write the probability of inducing fault for a given\n(faultable) syscall.\n\nThe probability is represented as a reciprocal, e.g. `1000` means that, on average, `0.1%` of\nfaultable syscalls will be faulted.\n\n```bash\necho \"100000\" | sudo tee /proc/krf/probability\n```\n\n### `/proc/krf/control`\n\nThis file controls the syscalls that KRF faults.\n\n**NOTE**: Most users should use `krfctl` instead of interacting with this file directly \u0026mdash;\nthe former will perform syscall name-to-number translation automatically and will provide clearer\nerror messages when things go wrong.\n\n```bash\n# replace the syscall in slot 0 (usually SYS_read) with its faulty wrapper\necho \"0\" | sudo tee /proc/krf/control\n```\n\nPassing any number greater than `KRF_NR_SYSCALLS` will cause KRF to flush the entire syscall table,\nreturning it to the neutral state. Since `KRF_NR_SYSCALLS` isn't necessarily predictable for\narbitrary versions of the Linux kernel, choosing a large number (like 65535) is fine.\n\nPassing a valid syscall number that lacks a fault injection wrapper will cause the `write(2)`\nto the file to fail with `EOPNOTSUPP`.\n\n### `/proc/krf/log_faults`\n\nThis file controls whether or not KRF emits kernel logs on faulty syscalls. By default, no\nlogging messages are emitted.\n\n**NOTE**: Most users should use `krfctl` instead of interacting with this file directly.\n\n```bash\n# enable fault logging\necho \"1\" | sudo tee /proc/krf/log_faults\n# disable fault logging\necho \"0\" | sudo tee /proc/krf/log_faults\n# read the logging state\ncat /proc/krf/log_faults\n```\n\n## TODO\n\n* Allow users to specify a particular class of faults, e.g. memory pressure (`ENOMEM`).\n  * This should be do-able by adding some more bits to the `personality(2)` value.\n\n## Thanks\n\nMany thanks go to [Andrew Reiter](https://github.com/roachspray) for the\n[initial port](https://github.com/roachspray/fkrf) of KRF to FreeBSD. Andrew's work was performed\non behalf of the Applied Research Group at Veracode.\n\n## Licensing\n\nKRF is licensed under the terms of the GNU GPLv3.\n\nSee the [LICENSE](./LICENSE) file for the exact terms.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrailofbits%2Fkrf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrailofbits%2Fkrf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrailofbits%2Fkrf/lists"}