├── .gitignore ├── COPYING ├── README.md ├── autostart ├── README.md ├── autostart.c ├── autostart.service ├── autostart.sh └── compile_flags.txt ├── extensions.json ├── launch.json ├── local.sh ├── settings.jsonnet ├── syzbot.ipynb ├── tasks.json └── tasks.sh /.gitignore: -------------------------------------------------------------------------------- 1 | local*.sh 2 | settings.json 3 | settings-extra.json 4 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VSCode for Linux kernel development 2 | 3 | ## Features 4 | 5 | **Editor:** 6 | 7 | * Symbol lookup (go-to-definition etc) based on your `.config` 8 | * Clangd and Checkpatch live squiggles and linting 9 | * Syntax highlighting for KConfig, assembly language, and Device Trees 10 | 11 | **Compilation:** 12 | 13 | * Minimal defconfig generation that boots in a VM 14 | * Easy cross-compilation to arm64 15 | * `Ctrl+Click` on error messages point back to code 16 | 17 | **Testing on a local VM:** 18 | 19 | * Minimal Debian VMs generation 20 | * Autostart of C and shell payloads 21 | * Integrated serial output 22 | * Easy SSH into the VM 23 | 24 | **Patch management:** 25 | 26 | * `git format-patch` and `send-email` assistant 27 | * Mailing list exploration using Patchwork 28 | * `kernel.org`'s cgit links generation 29 | 30 | **Debugging:** 31 | 32 | * Integrated VM debugger using GDB (function and conditional breakpoints, 33 | watchpoints, backtraces, variable inspection, step-by-step, disassembly 34 | views etc...) 35 | * Integrated IPython notebook for ftrace analysis 36 | * BPF selftests cross-compilation and run tasks 37 | * Ctrl-Click addresses like `__sys_sendmsg+0x284/0x370` in your backtraces and 38 | they will automatically get resolved by `addr2line` 39 | * Easy systemtap probing (right click -> "Trace this function") and logging 40 | with deep argument inspection (logs buffer opens immediately on logs) 41 | 42 | **Syzkaller:** 43 | 44 | * Straightforward setup to test syzkaller fuzzer descriptions 45 | * Integrated IPython notebook to reproduce [syzbot](https://syzkaller.appspot.com/upstream) bugs 46 | 47 | **Other:** 48 | 49 | * Transparent remote development from a laptop 50 | * Setup that is easy to modify (bash scripts) and contribute to 51 | * Easy to update 52 | 53 | ## LPC Talk 54 | 55 | This setup was presented at the Linux Plumbers 2023 conference. The slides can be found [here](https://lpc.events/event/17/contributions/1614/attachments/1210/2474/VSCode%20for%20kernel%20development.pdf) and the video below: 56 | 57 | [![VSCode for kernel development](https://img.youtube.com/vi/nmYaSqe0fGg/0.jpg)](https://www.youtube.com/watch?v=nmYaSqe0fGg) 58 | 59 | ## System-wide installation *(done once)* 60 | 61 | Install the dependencies required to run all the supported commands/tasks: 62 | 63 | ``` 64 | curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg 65 | sudo install -o root -g root -m 644 microsoft.gpg /usr/share/keyrings/microsoft-archive-keyring.gpg 66 | sudo sh -c 'echo "deb [arch=amd64,arm64,armhf signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list' 67 | sudo apt update 68 | sudo apt install code gdb-multiarch ccache clang clangd llvm lld libguestfs-tools libssl-dev trace-cmd python3-pip jsonnet libelf-dev bison bindfs mmdebstrap proot systemtap flex yacc bc debian-archive-keyring 69 | ``` 70 | 71 | For VS Code to keep track of all the files in your kernel source tree: 72 | 73 | ```shell 74 | sudo bash -c 'echo "fs.inotify.max_user_watches=524288" >> /etc/sysctl.conf' 75 | sudo sysctl -p 76 | ``` 77 | 78 | ## Linux tree setup *(done once per kernel tree)* 79 | 80 | Inside a fresh linux kernel tree, e.g.: 81 | 82 | ```shell 83 | git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 84 | cd linux 85 | ``` 86 | 87 | Create a `.vscode` directory with our config files inside: 88 | 89 | ```shell 90 | git clone https://github.com/FlorentRevest/linux-kernel-vscode .vscode/ 91 | .vscode/tasks.sh update # Needs to be run once to generate settings.json 92 | ``` 93 | 94 | ## Extensions *(done once)* 95 | 96 | If you open the kernel tree in VSCode. A pop-up will appear recommending 97 | workspace extensions, install them all. Here is what they do: 98 | 99 | * [C/C++ via Clangd](https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd) 100 | this integrates with a `compile_commands.json` file autogenerated on kernel 101 | builds. 102 | * [Git integration](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens) 103 | this provides a git blame at the end of the selected line and adds many 104 | options to the source control tab (commit log, file history, branches 105 | switching etc...). 106 | * [x86 and x86_64 Assembly](https://marketplace.visualstudio.com/items?itemName=13xforever.language-x86-64-assembly) 107 | provides syntax highlighting for asm files. 108 | * [ARM64 Assembly](https://marketplace.visualstudio.com/items?itemName=MKornelsen.vscode-arm64) 109 | same, but for arm. 110 | * [Device Tree](https://marketplace.visualstudio.com/items?itemName=plorefice.devicetree) 111 | provides syntax highlighting for dts files. 112 | * [KConfig](https://marketplace.visualstudio.com/items?itemName=luveti.kconfig) 113 | provides syntax highlighting for Kconfig files. 114 | * [Checkpatch](https://marketplace.visualstudio.com/items?itemName=idanp.checkpatch) 115 | provides squiggle highlighting of checkpatch errors on file saves. 116 | * [Patchwork](https://marketplace.visualstudio.com/items?itemName=florent-revest.patchwork) 117 | view, apply and search patches from the 118 | [linux patchwork instance](https://patchwork.kernel.org/). 119 | * [Addr2line](https://marketplace.visualstudio.com/items?itemName=florent-revest.addr2line) 120 | lets users ctrl+click on addresses in backtraces and they get resolved into 121 | lines of code. 122 | * [Git send-email](https://marketplace.visualstudio.com/items?itemName=florent-revest.git-send-email) 123 | facilitates sending patches or series to the list. 124 | * [Syzlang](https://marketplace.visualstudio.com/items?itemName=florent-revest.vscode-syzlang) 125 | highlights syzkaller syscall descriptions. 126 | * [Syzkaller coverage](https://marketplace.visualstudio.com/items?itemName=florent-revest.syzkaller-coverage) 127 | can highlight lines covered by a running instance of syz-manager fuzzing. 128 | * [SystemTap Assistant](https://marketplace.visualstudio.com/items?itemName=florent-revest.systemtap-assistant) 129 | facilitates kernel functions or lines tracing by dynamically generating 130 | systemtap scripts and rendering logs received from these probes in a buffer. 131 | * [SystemTap](https://marketplace.visualstudio.com/items?itemName=nzh21.systemtap-syntax) 132 | highlights systemtap scripts. 133 | * [Microsoft C/C++](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) 134 | only the GDB integration of this plugin is used, every features interacting 135 | with the code is disabled in favor of Clangd which works much better. 136 | * [Trailing spaces](https://marketplace.visualstudio.com/items?itemName=shardulm94.trailing-spaces) 137 | highlights forgotten trailing spaces. 138 | 139 | If the pop-up didn't appear or you dismissed it: 140 | 141 | 1. Click on the Extensions tab on the left hand side of VSCode 142 | 2. Enter "@recommended" in the search bar 143 | 3. Manually click the "Install" button on every extension in the "Workspace 144 | Recommendations" section 145 | 146 | NOTE: You probably want either one of these extensions too (run the command in 147 | the `Ctrl+P` dialog box): 148 | 149 | * [Vim emulation](https://marketplace.visualstudio.com/items?itemName=vscodevim.vim): 150 | 151 | ```shell 152 | ext install vscodevim.vim 153 | ``` 154 | 155 | * [Emacs emulation](https://marketplace.visualstudio.com/items?itemName=vscodeemacs.emacs): 156 | 157 | ```shell 158 | ext install vscodeemacs.emacs 159 | ``` 160 | 161 | ## Basic usage 162 | 163 | * **Compile** the kernel using `Ctrl+Shift+B` (if you don't have a `.config` 164 | yet, it will generate a functional one automatically for you). 165 | * **Run** it with `F5`. 166 | * **Debug** with breakpoints by clicking on the left of a line number. 167 | * **Open** a file by name with `Ctrl+P`. 168 | * **Navigate** between symbol definition/declaration with `F12`. 169 | * Get **clang squiggles** by building the kernel once and waiting for clangd 170 | to index the code for a bit. Clang also supports code refactoring (symbol 171 | renames with `F2` for example) and auto-formatting according to kernel rules 172 | with `Ctrl+Shift+I`. 173 | * Get **`checkpatch` squiggles** by saving the current file. 174 | * Interact with **git** following 175 | [this demo](https://www.youtube.com/watch?v=UQPb73Zz9qk). 176 | * Change the content of `TARGET_ARCH` in `.vscode/local.sh` to `arm64` to 177 | transparently get an *aarch64** workspace (future compilations/virtual 178 | machines will be `arm64`). 179 | * Customize per-workspace VS-Code settings the normal way (edit local 180 | `.vscode/settings.json`, or use `Ctrl+Shift+P` -> "Preferences: Open 181 | Settings (UI)"). Note that fields that exist in `settings.jsonnet` will get 182 | overwritten when you run the `update` task. If needed, extra settings can be 183 | added in `.vscode/settings-extra.json` file. Also, comments in your 184 | `.vscode/settings.json` will get deleted. 185 | * **Autostart** commands or codes at VM start time by modifying the content of 186 | `.vscode/autostart/` (eg: always run tests that exercise the kernel 187 | subsystem you work on). 188 | * Find **more helper tasks** using `Ctrl+Shift+P`, search for `Run task` and 189 | then pick from the list (for example you can run menuconfig, create SSH 190 | sessions, update to the latest version of this setup etc). 191 | * **Interact with your VM** from an external terminal using 192 | commands such as `lkv start`, `lkv ssh`, `lkv stop` etc... 193 | 194 | Make sure to check the *Tips and Tricks* and *Interactive Playground* options 195 | under *Help* in the menu bar to learn more about basic VS Code usage. 196 | 197 | ## Commands outside of VSCode 198 | 199 | All tasks are implemented in the `tasks.sh` file. This script can be run from 200 | anywhere. For example: 201 | 202 | ```shell 203 | alias lkv=~/linux/.vscode/tasks.sh 204 | lkv build # Equivalent to Ctrl+Shift+B 205 | lkv start # Equivalent to F5 206 | lkv ssh 207 | lkv stop 208 | lkv push ./file 209 | lkv pull /root/file 210 | lkv run ls / 211 | lkv chroot 212 | ``` 213 | 214 | ## Technical documentation 215 | 216 | If you want or need to dive into the nitty-gritty of this setup: 217 | 218 | All the VSCode config files are maintained under this git repository. 219 | Improvement PRs can be sent to 220 | https://github.com/FlorentRevest/linux-kernel-vscode and will be easily 221 | fetchable by users thanks to the auto-update task (which updates `.vscode` from 222 | there). 223 | 224 | * `.vscode/tasks.json` [describes per-workspace tasks to 225 | VSCode](https://code.visualstudio.com/docs/editor/tasks#_custom-tasks). 226 | These tasks are entries under the `Ctrl+Shift+P` `Run task` dialog box. All 227 | task basically just call `tasks.sh` with a different command flag. 228 | * `.vscode/tasks.sh` is a bash script with a big switch statement that 229 | implements all tasks exposed by `tasks.json`. They all share a common 230 | preamble customizable 231 | locally by local.sh. 232 | * `.vscode/settings.jsonnet` [provides per-workspace configuration values to 233 | VSCode](https://code.visualstudio.com/docs/getstarted/settings) and its 234 | extensions. This is constructed by `tasks.sh` by evaluating 235 | [`settings.jsonnet`](http://depot/company/teams/security/kernel/tools/vscode/settings.jsonnet) 236 | with the existing settings as an input. The JSonnet file contains sane 237 | defaults valid for all kernel developers. For example, it specifies which 238 | files VSCode should ignore, how to handle spaces and tabs or how to generate 239 | `kernel.org` cgit links from a file path and line. Individual developers can 240 | then customize per-workspace settings for their kernel trees while still 241 | benefiting from the defaults in the JSonnet file. 242 | * `.vscode/syzbot.ipynb` is a reference Jupyter notebook to automate the 243 | repetitive aspects of reproducing a syzkaller bug. Every step along the way 244 | is guided. 245 | * `.vscode/launch.json` 246 | [describes how to run a VM with a debugger attached to VSCode](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations). 247 | * `.vscode/extensions.json` [describes a list of recommended extensions to 248 | VSCode](https://code.visualstudio.com/docs/editor/extension-marketplace#_recommended-extensions). 249 | These are meant to be sane defaults valid for all kernel developers. 250 | Extensions are pulled in from 251 | [the VSCode Marketplace](https://marketplace.visualstudio.com/). 252 | * `.vscode/local.sh` is a local config file not updated by the auto-update 253 | task. It can be used to implement special features or override defaults for 254 | specific needs. 255 | * `.vscode/autostart/` contains the template for a dummy task that gets run 256 | at the end of the VM's boot. Before running a VM, `tasks.sh` is responsible 257 | for detecting changes to these files and updating the files in the VM's 258 | rootfs. 259 | 260 | Note: The [Patchwork](https://github.com/FlorentRevest/vscode-patchwork) and 261 | [Git Send Email](https://github.com/FlorentRevest/vscode-git-send-email) 262 | extensions are homegrown and maintained in other git repositories. 263 | Pull-requests or bug reports are also welcome there. 264 | -------------------------------------------------------------------------------- /autostart/README.md: -------------------------------------------------------------------------------- 1 | This service is automatically re-built and re-installed on the VM image 2 | before every virtual machine run. This lets you easily trigger a userspace 3 | payload at boot time, without having to yourself interact with the VM. 4 | 5 | This consists of: 6 | - a systemd service which, late at boot, starts the next two programs and 7 | redirects their output to the boot terminal 8 | - a shell script if you want to trigger stimuli easily accessible from bash 9 | - a C code if you want to hook into deeper system APIs 10 | 11 | Modify any of these files to easily exercise the kernel behavior you work on. -------------------------------------------------------------------------------- /autostart/autostart.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define PRINTF_GREEN(f, ...) printf("\033[1;92m" f "\033[0m", ##__VA_ARGS__) 4 | 5 | int main(void) 6 | { 7 | // PRINTF_GREEN("Hello from autostart.c"); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /autostart/autostart.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Autostart 3 | 4 | [Service] 5 | Type=idle 6 | ExecStart=/usr/bin/autostart.sh 7 | StandardOutput=journal+console 8 | StandardError=journal+console 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | -------------------------------------------------------------------------------- /autostart/autostart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo-green() { 4 | echo -e "\033[0;92m" $@ "\033[0m" 5 | } 6 | 7 | # echo-green "Hello from autostart.sh" 8 | 9 | # If a systemtap tracer module if available, use it to trace /usr/bin/autostart 10 | if [ -e "/host/tmp/tracer.ko" ]; then 11 | # Workaround the detection of kprobes optimization capabilities 12 | export STAP_PR13193_OVERRIDE=1 13 | # Route UDP logs via the default IP interface (it must be ethernet) 14 | DEFAULT_ROUTE=`ip route show default | awk '/dev/ {print $5}'` 15 | # Wrap autostart with a systemtap run. This sets target() to autostart's pid 16 | TRACER="staprun /host/tmp/tracer.ko interface=${DEFAULT_ROUTE} -c" 17 | fi 18 | 19 | $TRACER /usr/bin/autostart 20 | -------------------------------------------------------------------------------- /autostart/compile_flags.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlorentRevest/linux-kernel-vscode/e05e6775455a9ad99cfd53f342905d4bfce4d0de/autostart/compile_flags.txt -------------------------------------------------------------------------------- /extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "florent-revest.patchwork", 4 | "florent-revest.git-send-email", 5 | "florent-revest.vscode-syzlang", 6 | "florent-revest.syzkaller-coverage", 7 | "florent-revest.addr2line", 8 | "florent-revest.systemtap-assistant", 9 | "llvm-vs-code-extensions.vscode-clangd", 10 | "13xforever.language-x86-64-assembly", 11 | "plorefice.devicetree", 12 | "luveti.kconfig", 13 | "idanp.checkpatch", 14 | "eamodio.gitlens", 15 | "ms-vscode.cpptools", 16 | "MKornelsen.vscode-arm64", 17 | "nzh21.systemtap-syntax", 18 | "shardulm94.trailing-spaces" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Start and debug kernel in a VM", 6 | "type": "cppdbg", 7 | "request": "launch", 8 | "preLaunchTask": "Start virtual machine", 9 | "internalConsoleOptions": "neverOpen", 10 | 11 | "miDebuggerPath": "gdb-multiarch", 12 | "miDebuggerServerAddress": "localhost:1234", 13 | "setupCommands": [ 14 | { 15 | "description": "Give some time for the VM to spin-up", 16 | "text": "-interpreter-exec console \"shell ${workspaceFolder}/.vscode/tasks.sh wait-for-vm\"", 17 | "ignoreFailures": false, 18 | }, 19 | { 20 | "description": "Enable autoloading of Linux GDB scripts", 21 | "text": "add-auto-load-safe-path ${workspaceFolder}/scripts/gdb", 22 | "ignoreFailures": true, 23 | }, 24 | { 25 | "description": "Format Locals as HEX by default", 26 | "text": "set output-radix 16", 27 | "ignoreFailures": true, 28 | }, 29 | ], 30 | 31 | "cwd": "${workspaceFolder}", 32 | "program": "${workspaceFolder}/vmlinux", 33 | 34 | "hardwareBreakpoints": { "require": true }, 35 | }, 36 | { 37 | "name": "Start and debug kernel in a VM from early-boot", 38 | "type": "cppdbg", 39 | "request": "launch", 40 | "preLaunchTask": "Start virtual machine waiting for debugger", 41 | "internalConsoleOptions": "neverOpen", 42 | 43 | "miDebuggerPath": "gdb-multiarch", 44 | "miDebuggerServerAddress": "localhost:1234", 45 | "setupCommands": [ 46 | { 47 | "description": "Give some time for the VM to spin-up", 48 | "text": "-interpreter-exec console \"shell ${workspaceFolder}/.vscode/tasks.sh wait-for-vm\"", 49 | "ignoreFailures": true 50 | }, 51 | { 52 | "description": "Enable autoloading of Linux GDB scripts", 53 | "text": "add-auto-load-safe-path ${workspaceFolder}/scripts/gdb", 54 | "ignoreFailures": true, 55 | }, 56 | { 57 | "description": "Format Locals as HEX by default", 58 | "text": "set output-radix 16", 59 | "ignoreFailures": true, 60 | }, 61 | ], 62 | 63 | "cwd": "${workspaceFolder}", 64 | "program": "${workspaceFolder}/vmlinux", 65 | 66 | "hardwareBreakpoints": { 67 | "require": true, 68 | }, 69 | }, 70 | { 71 | "name": "Debug kernel in an already-running VM", 72 | "type": "cppdbg", 73 | "request": "launch", 74 | "internalConsoleOptions": "neverOpen", 75 | 76 | "miDebuggerPath": "gdb-multiarch", 77 | "miDebuggerServerAddress": "localhost:1234", 78 | "setupCommands": [ 79 | { 80 | "description": "Wait for the VM to spin-up", 81 | "text": "-interpreter-exec console \"shell ${workspaceFolder}/.vscode/tasks.sh wait-for-vm\"", 82 | "ignoreFailures": false, 83 | }, 84 | { 85 | "description": "Enable autoloading of Linux GDB scripts", 86 | "text": "add-auto-load-safe-path ${workspaceFolder}/scripts/gdb", 87 | "ignoreFailures": true, 88 | }, 89 | { 90 | "description": "Format Locals as HEX by default", 91 | "text": "set output-radix 16", 92 | "ignoreFailures": true, 93 | }, 94 | ], 95 | 96 | "cwd": "${workspaceFolder}", 97 | "program": "${workspaceFolder}/vmlinux", 98 | 99 | "hardwareBreakpoints": { "require": true }, 100 | } 101 | ] 102 | } 103 | -------------------------------------------------------------------------------- /local.sh: -------------------------------------------------------------------------------- 1 | # This file is sourced in the middle of tasks.sh, after environment variables 2 | # are setup and before commands are run. It does not get updated by the update 3 | # task so you can use it to plug-in arbitrary extra logic that is specific to 4 | # your local needs and should not be part of the upstream tasks.sh. For example: 5 | 6 | ## Cross-compile/debug/emulate for arm64 7 | # TARGET_ARCH=arm64 8 | 9 | ## Change PATH to use a different QEMU binary 10 | # export PATH=$HOME/qemu/bin/:$PATH 11 | 12 | ## Generate objects in a subdirectory 13 | # MAKE="$MAKE O=.vscode/build-$TARGET_ARCH/" 14 | 15 | ## Enable some random kernel CONFIG by default as part of the .config generation 16 | # if [ $COMMAND = "defconfig" ]; then 17 | # trap "scripts/config -e BPF_SYSCALL" EXIT 18 | # fi 19 | 20 | ## Run make olddefconfig before a build (a bit slow) 21 | # if [ $COMMAND = "build" ]; then 22 | # eval ${MAKE} ARCH=${TARGET_ARCH} olddefconfig 23 | # fi 24 | 25 | ## Make the build verbose 26 | # SILENT_BUILD_FLAG="" 27 | 28 | ## Disable the build spinner 29 | # SPINNER=0 30 | 31 | ## Don't clear the screen before each task 32 | # unset CLEAR 33 | 34 | ## Boot without systemd (use the /sbin/init-minimal shell script instead) 35 | # SKIP_SYSTEMD=1 36 | 37 | ## Add some args to the kernel cmdline when using the "start" task 38 | ## E.g.: Boot straight into a syzbot reproducer 39 | # KERNEL_CMDLINE_EXTRA=init=/root/syzbot-repro 40 | 41 | ## Only fuzz the /dev/ptmx ioctls 42 | # SYZ_MANAGER_CFG_EXTRA='"enable_syscalls": [ "openat$ptmx", "ioctl$*" ],' 43 | 44 | ## Fuzz as an unprivileged user 45 | # SYZ_MANAGER_CFG_EXTRA='"sandbox": "setuid",' 46 | -------------------------------------------------------------------------------- /settings.jsonnet: -------------------------------------------------------------------------------- 1 | // This is a jsonnet file, to evaluate it on the command-line use 2 | // 3 | // jsonnet \ 4 | // --ext-code-file old_settings= \ 5 | // --ext-code-file extra_settings= \ 6 | // 7 | // 8 | // JSonnet is a superset of JSON. Here we are using a minimal subset of 9 | // JSonnet's extra features, see the "External Variables" and "Object 10 | // Orientation" section of jsonnet tutorials (plus we use comments). 11 | std.extVar('old_settings') + { 12 | "files.exclude": { 13 | "**/.*.cmd": true, 14 | "**/.*.d": true, 15 | "**/.*.S": true, 16 | "**/.tmp*": true, 17 | "**/*.tmp": true, 18 | "**/*.o": true, 19 | "**/*.a": true, 20 | "**/*.builtin": true, 21 | "**/*.order": true, 22 | "**/*.orig": true, 23 | "**/*.symvers": true, 24 | "**/*.modinfo": true, 25 | "**/*.map": true, 26 | "*.cache/**": true 27 | }, 28 | "search.exclude": { 29 | "**/.*.cmd": true, 30 | "**/.*.d": true, 31 | "**/.*.S": true, 32 | "**/.tmp*": true, 33 | "**/*.tmp": true, 34 | "**/*.o": true, 35 | "**/*.a": true, 36 | "**/*.builtin": true, 37 | "**/*.order": true, 38 | "**/*.orig": true, 39 | "**/*.symvers": true, 40 | "**/*.modinfo": true, 41 | "**/*.map": true, 42 | "*.cache/**": true 43 | }, 44 | "editor.detectIndentation": false, 45 | "editor.tabSize": 8, 46 | "editor.insertSpaces": false, 47 | "editor.rulers": [80, 100], 48 | "files.associations": { 49 | "**/x86/**/*.S": "asm-intel-x86-generic", 50 | "**/arch/x86/entry/calling.h": "asm-intel-x86-generic", 51 | "**/arm64/**/*.S": "arm64", 52 | "*_defconfig": "kconfig" 53 | }, 54 | "checkpatch.run": "onSave", 55 | "checkpatch.exclude": ["**/.vscode/autostart/*.c"], 56 | "git.alwaysSignOff": true, 57 | "C_Cpp.autocomplete": "disabled", 58 | "C_Cpp.formatting": "disabled", 59 | "C_Cpp.errorSquiggles": "disabled", 60 | "C_Cpp.intelliSenseEngine": "disabled", 61 | "checkpatch.checkpatchPath": "scripts/checkpatch.pl", 62 | "editor.renderWhitespace": "boundary", 63 | "gitlens.showWelcomeOnInstall": false, 64 | "gitlens.showWhatsNewAfterUpgrades": false, 65 | "gitlens.plusFeatures.enabled": false, 66 | "gitlens.mode.statusBar.enabled": false, 67 | "gitlens.statusBar.enabled": false, 68 | "gitlens.remotes": [ 69 | { 70 | "regex": ".+:\\/\\/(git\\.kernel\\.org)\\/(.+)", 71 | "type": "Custom", 72 | "name": "kernel.org", 73 | "protocol": "https", 74 | "urls": { 75 | "repository": "https://git.kernel.org/${repoBase}/${repoPath}/tree", 76 | "branches": "https://git.kernel.org/${repoBase}/${repoPath}/refs", 77 | "branch": "https://git.kernel.org/${repoBase}/${repoPath}/log/?h=${branch}", 78 | "commit": "https://git.kernel.org/${repoBase}/${repoPath}/commit/?id=${id}", 79 | "file": "https://git.kernel.org/${repoBase}/${repoPath}/tree/${file}${line}", 80 | "fileInBranch": "https://git.kernel.org/${repoBase}/${repoPath}/tree/${file}?h=${branch}${line}", 81 | "fileInCommit": "https://git.kernel.org/${repoBase}/${repoPath}/tree/${file}?id=${id}${line}", 82 | "fileLine": "#n${line}", 83 | "fileRange": "#n${start}" 84 | } 85 | } 86 | ], 87 | "trailing-spaces.highlightCurrentLine": false, 88 | "trailing-spaces.deleteModifiedLinesOnly": true, 89 | "trailing-spaces.trimOnSave": true, 90 | "systemtap-assistant.output": ".vscode/autostart/tracer.stp", 91 | "systemtap-assistant.deploy-task": "Build systemtap tracer", 92 | "debug.onTaskErrors": "debugAnyway" 93 | } + std.extVar('extra_settings') 94 | -------------------------------------------------------------------------------- /syzbot.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": {}, 7 | "source": [ 8 | "# Sybot bug reproducer" 9 | ] 10 | }, 11 | { 12 | "attachments": {}, 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "Enter the URL of a syzbot bug you'd like to reproduce:" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": null, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "bug_url=input('Syzbot bug URL, e.g.: https://syzkaller.appspot.com/bug?extid=fcc47ba2476570cbbeb0')" 26 | ] 27 | }, 28 | { 29 | "attachments": {}, 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "## Crash selection" 34 | ] 35 | }, 36 | { 37 | "attachments": {}, 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "Download the syzbot page as HTML." 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": null, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "bug_html=!curl {bug_url}" 51 | ] 52 | }, 53 | { 54 | "attachments": {}, 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "Parse the crashes table as a Pandas data frame and pretty print interesting fields" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": null, 64 | "metadata": {}, 65 | "outputs": [], 66 | "source": [ 67 | "import pandas as pd\n", 68 | "crashes = pd.read_html(bug_html.nlstr, match=\"Crashes\", extract_links=\"body\")[0]\n", 69 | "display(crashes.applymap(lambda val: val[0])[[\"Time\", \"Commit\", \"Syz repro\", \"C repro\"]])" 70 | ] 71 | }, 72 | { 73 | "attachments": {}, 74 | "cell_type": "markdown", 75 | "metadata": {}, 76 | "source": [ 77 | "Select the crash you'd like to reproduce:" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": null, 83 | "metadata": {}, 84 | "outputs": [], 85 | "source": [ 86 | "crash_id=int(input(\"Crash to reproduce (by row number), e.g.: 0\"))" 87 | ] 88 | }, 89 | { 90 | "attachments": {}, 91 | "cell_type": "markdown", 92 | "metadata": {}, 93 | "source": [ 94 | "## Kernel setup" 95 | ] 96 | }, 97 | { 98 | "attachments": {}, 99 | "cell_type": "markdown", 100 | "metadata": {}, 101 | "source": [ 102 | "Checkout the kernel commit" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": null, 108 | "metadata": {}, 109 | "outputs": [], 110 | "source": [ 111 | "!git checkout {crashes[\"Commit\"][crash_id][0]}" 112 | ] 113 | }, 114 | { 115 | "attachments": {}, 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "Overwrite the local `.config`" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": null, 125 | "metadata": {}, 126 | "outputs": [], 127 | "source": [ 128 | "!curl \"{'https://syzkaller.appspot.com' + crashes['Config'][crash_id][1]}\" > ../.config" 129 | ] 130 | }, 131 | { 132 | "attachments": {}, 133 | "cell_type": "markdown", 134 | "metadata": {}, 135 | "source": [ 136 | "Build" 137 | ] 138 | }, 139 | { 140 | "cell_type": "code", 141 | "execution_count": null, 142 | "metadata": {}, 143 | "outputs": [], 144 | "source": [ 145 | "!SPINNER=0 ./tasks.sh build" 146 | ] 147 | }, 148 | { 149 | "attachments": {}, 150 | "cell_type": "markdown", 151 | "metadata": {}, 152 | "source": [ 153 | "Start the kernel by pressing `F5`" 154 | ] 155 | }, 156 | { 157 | "attachments": {}, 158 | "cell_type": "markdown", 159 | "metadata": {}, 160 | "source": [ 161 | "## C reproducer" 162 | ] 163 | }, 164 | { 165 | "attachments": {}, 166 | "cell_type": "markdown", 167 | "metadata": {}, 168 | "source": [ 169 | "Download the code" 170 | ] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "execution_count": null, 175 | "metadata": {}, 176 | "outputs": [], 177 | "source": [ 178 | "!curl \"{'https://syzkaller.appspot.com' + crashes['C repro'][crash_id][1]}\" > /tmp/syzbot-repro.c" 179 | ] 180 | }, 181 | { 182 | "attachments": {}, 183 | "cell_type": "markdown", 184 | "metadata": {}, 185 | "source": [ 186 | "Build it" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": null, 192 | "metadata": {}, 193 | "outputs": [], 194 | "source": [ 195 | "!clang -static -lpthread /tmp/syzbot-repro.c -o /tmp/syzbot-repro" 196 | ] 197 | }, 198 | { 199 | "attachments": {}, 200 | "cell_type": "markdown", 201 | "metadata": {}, 202 | "source": [ 203 | "Send it to the VM" 204 | ] 205 | }, 206 | { 207 | "cell_type": "code", 208 | "execution_count": null, 209 | "metadata": {}, 210 | "outputs": [], 211 | "source": [ 212 | "!./tasks.sh push /tmp/syzbot-repro" 213 | ] 214 | }, 215 | { 216 | "attachments": {}, 217 | "cell_type": "markdown", 218 | "metadata": {}, 219 | "source": [ 220 | "Run it" 221 | ] 222 | }, 223 | { 224 | "cell_type": "code", 225 | "execution_count": null, 226 | "metadata": {}, 227 | "outputs": [], 228 | "source": [ 229 | "!./tasks.sh run /root/syzbot-repro" 230 | ] 231 | }, 232 | { 233 | "attachments": {}, 234 | "cell_type": "markdown", 235 | "metadata": {}, 236 | "source": [ 237 | "## Syz reproducer" 238 | ] 239 | }, 240 | { 241 | "attachments": {}, 242 | "cell_type": "markdown", 243 | "metadata": {}, 244 | "source": [ 245 | "Download the code" 246 | ] 247 | }, 248 | { 249 | "cell_type": "code", 250 | "execution_count": null, 251 | "metadata": {}, 252 | "outputs": [], 253 | "source": [ 254 | "!curl \"{'https://syzkaller.appspot.com' + crashes['Syz repro'][crash_id][1]}\" > /tmp/syzbot-repro.syz" 255 | ] 256 | }, 257 | { 258 | "attachments": {}, 259 | "cell_type": "markdown", 260 | "metadata": {}, 261 | "source": [ 262 | "Send it to the VM" 263 | ] 264 | }, 265 | { 266 | "cell_type": "code", 267 | "execution_count": null, 268 | "metadata": {}, 269 | "outputs": [], 270 | "source": [ 271 | "!./tasks.sh push /tmp/syzbot-repro.syz" 272 | ] 273 | }, 274 | { 275 | "attachments": {}, 276 | "cell_type": "markdown", 277 | "metadata": {}, 278 | "source": [ 279 | "Run it (assumes the VM already has a `/usr/bin/syz-execprog`)" 280 | ] 281 | }, 282 | { 283 | "cell_type": "code", 284 | "execution_count": null, 285 | "metadata": {}, 286 | "outputs": [], 287 | "source": [ 288 | "!./tasks.sh run \"syz-execprog -repeat=0 -procs=1 -sandbox='' /root/syzbot-repro.syz\"" 289 | ] 290 | } 291 | ], 292 | "metadata": { 293 | "kernelspec": { 294 | "display_name": "Python 3", 295 | "language": "python", 296 | "name": "python3" 297 | }, 298 | "language_info": { 299 | "codemirror_mode": { 300 | "name": "ipython", 301 | "version": 3 302 | }, 303 | "file_extension": ".py", 304 | "mimetype": "text/x-python", 305 | "name": "python", 306 | "nbconvert_exporter": "python", 307 | "pygments_lexer": "ipython3", 308 | "version": "3.11.5" 309 | }, 310 | "orig_nbformat": 4 311 | }, 312 | "nbformat": 4, 313 | "nbformat_minor": 2 314 | } 315 | -------------------------------------------------------------------------------- /tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | 4 | // All tasks in this file inherit the following top-level fields. These can be 5 | // shared because all tasks are implemented in the tasks.sh shell script. 6 | "type": "shell", 7 | "command": ".vscode/tasks.sh", 8 | "presentation": { 9 | // Do not have VSCode print ".vscode/tasks.sh task" everytime a task is run. 10 | // We can let tasks.sh print something more useful instead. 11 | "echo": false, 12 | }, 13 | "problemMatcher": [], 14 | 15 | // Because of the above, most task definitions only need to map user-readable 16 | // UI labels (what shows under the Ctrl+Shift+P -> "Tasks: Run task" submenu) 17 | // to an argument for the tasks.sh script that identifies the task to run. 18 | "tasks": [ 19 | { 20 | "label": "Create rootfs for virtual machine if absent", 21 | "args": ["create-rootfs"], 22 | }, 23 | { 24 | "label": "Compile and install autostart", 25 | "args": ["install-autostart"], 26 | }, 27 | { 28 | "label": "Start virtual machine", 29 | "args": ["start"], 30 | "presentation": { 31 | "focus": true, 32 | }, 33 | "isBackground": true, 34 | // For this task to be a background task of a launch.json debugger setup, 35 | // a non-empty problem matcher must be defined. This is just a dummy one. 36 | "problemMatcher": [ 37 | { 38 | "pattern": [ 39 | { 40 | "regexp": ".", 41 | "file": 1, 42 | "location": 2, 43 | "message": 3, 44 | } 45 | ], 46 | "background": { 47 | "activeOnStart": true, 48 | "beginsPattern": ".", 49 | "endsPattern": ".", 50 | } 51 | } 52 | ], 53 | }, 54 | { 55 | "label": "Start virtual machine waiting for debugger", 56 | "args": ["start-wait-dbg"], 57 | "presentation": { 58 | "focus": true, 59 | }, 60 | "isBackground": true, 61 | "problemMatcher": [ 62 | { 63 | "pattern": [ 64 | { 65 | "regexp": ".", 66 | "file": 1, 67 | "location": 2, 68 | "message": 3, 69 | } 70 | ], 71 | "background": { 72 | "activeOnStart": true, 73 | "beginsPattern": ".", 74 | "endsPattern": ".", 75 | } 76 | } 77 | ], 78 | }, 79 | { 80 | "label": "Stop virtual machine", 81 | "args": ["stop"], 82 | }, 83 | { 84 | "label": "SSH into the virtual machine", 85 | "args": ["ssh"], 86 | "presentation": { 87 | "focus": true, 88 | }, 89 | }, 90 | { 91 | "label": "Create .config for virtual machine if absent", 92 | "args": ["defconfig"], 93 | }, 94 | { 95 | "label": "Build kernel", 96 | "args": ["build"], 97 | // Map this task to the Ctrl+Shift+P -> "Run build task" command. 98 | "group": { 99 | "kind": "build", 100 | "isDefault": true, 101 | }, 102 | }, 103 | { 104 | "label": "Menuconfig", 105 | "args": ["menuconfig"], 106 | "presentation": { 107 | "focus": true, 108 | }, 109 | }, 110 | { 111 | "label": "Make clean", 112 | "args": ["clean"], 113 | }, 114 | { 115 | "label": "Chroot into the virtual machine's rootfs", 116 | "args": ["chroot"], 117 | }, 118 | { 119 | "label": "Compile and install BPF selftests", 120 | "args": ["install-bpf-selftests"], 121 | }, 122 | { 123 | "label": "Run BPF selftests", 124 | "args": ["run-bpf-selftests"], 125 | }, 126 | { 127 | "label": "Run BPF selftests in this file", 128 | "args": ["run-bpf-selftests", "${file}"], 129 | }, 130 | { 131 | "label": "Update linux-kernel-vscode setup", 132 | "args": ["update"], 133 | }, 134 | { 135 | "label": "Ensure that KCOV is enabled", 136 | "args": ["enable-kcov"], 137 | }, 138 | { 139 | "label": "Fuzz the kernel in the virtual machine", 140 | "args": ["fuzz"], 141 | }, 142 | { 143 | "label": "Build systemtap tracer", 144 | "args": ["systemtap-build"], 145 | } 146 | ] 147 | } 148 | -------------------------------------------------------------------------------- /tasks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # If you want to modify how tasks behave: 4 | # - Keep features specific to your special use cases in the local.sh file. 5 | # - Send PRs to github.com/FlorentRevest/linux-kernel-vscode for changes that 6 | # would benefit all users. 7 | # This improves the framework and makes sure you can always run the update task. 8 | 9 | function depend_on() { 10 | $SCRIPT $@ 11 | if [[ "$CLEAR" == 1 ]]; then 12 | clear 13 | fi 14 | } 15 | 16 | function spinner() { 17 | local pid=$1 18 | 19 | if [[ "$SPINNER" -eq 1 ]]; then 20 | local spin='⣾⣽⣻⢿⡿⣟⣯⣷' 21 | local i=0 22 | tput civis # Hide cursor 23 | while kill -0 $pid 2>/dev/null; do 24 | local i=$(((i + 1) % ${#spin})) 25 | printf "%s" "${spin:$i:1}" # Print one character 26 | echo -en "\033[$1D" # Go back one character 27 | sleep .1 28 | done 29 | tput cnorm # Restore cursor 30 | fi 31 | 32 | wait $pid 33 | return $? 34 | } 35 | 36 | set -e 37 | 38 | # Arguments extraction 39 | if [ "$#" -lt 1 ]; then 40 | echo "Usage: $0 command" 41 | exit 1 42 | fi 43 | COMMAND=$1 44 | 45 | # See https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html 46 | # for the `: ${var:=DEFAULT}` syntax 47 | : ${SCRIPT:=`realpath -s "$0"`} 48 | : ${SCRIPT_DIR:=`dirname "${SCRIPT}"`} 49 | 50 | # Let the user override environment variables for their special needs 51 | files_to_source=$(find ${SCRIPT_DIR} -maxdepth 1 -xtype f -name "local*.sh") 52 | for file in $files_to_source; do 53 | source "$file" 54 | done 55 | 56 | # Default context variables, can be overridden by local.sh or in environment. 57 | : ${WORKSPACE_DIR:=`realpath -s "${SCRIPT_DIR}/.."`} 58 | : ${MAKE:="make -j`nproc` LLVM=1 LLVM_IAS=1 CC='ccache clang'"} 59 | : ${TARGET_ARCH:="x86_64"} 60 | : ${SILENT_BUILD_FLAG="-s"} 61 | : ${SUCCESSFUL_EXIT_COMMAND:=""} 62 | : ${BPF_SELFTESTS_DIR:="${WORKSPACE_DIR}/tools/testing/selftests/bpf"} 63 | : ${VM_START_ARGS:=''} 64 | : ${SYZ_MANAGER_CFG_EXTRA:=''} 65 | : ${SYZKALLER_DIR:="${SCRIPT_DIR}/syzkaller/"} 66 | : ${KERNEL_CMDLINE_EXTRA:=''} 67 | : ${SPINNER:=1} 68 | : ${IMAGE_DIR:="${HOME}/.linux-kernel-vscode"} 69 | : ${IMAGE_PATH:="${IMAGE_DIR}/debian-${TARGET_ARCH}.img"} 70 | : ${TRACER_PATH:=".vscode/autostart/tracer.stp"} 71 | if [[ "$TERM_PROGRAM" == "vscode" ]]; then 72 | : ${CLEAR:=1} 73 | fi 74 | if [[ $SKIP_SYSTEMD == 1 ]]; then 75 | KERNEL_CMDLINE_EXTRA="init=/sbin/init-minimal $KERNEL_CMDLINE_EXTRA" 76 | fi 77 | 78 | # Convenience environment variables derived from the context 79 | if [ "${TARGET_ARCH}" = "x86_64" ]; then 80 | : ${VMLINUX:="bzImage"} 81 | : ${CLANG_TARGET:="x86_64-linux-gnu"} 82 | : ${DEBIAN_TARGET_ARCH:="amd64"} 83 | : ${TOOLS_SRCARCH:="x86"} 84 | : ${QEMU_BIN:="qemu-system-x86_64"} 85 | : ${QEMU_CMD:="${QEMU_BIN} -enable-kvm -cpu host -machine q35 -bios qboot.rom"} 86 | : ${SERIAL_TTY:="ttyS0"} 87 | : ${SYZKALLER_TARGETARCH:="amd64"} 88 | : ${ROOT_MNT:="/dev/sda"} 89 | elif [ "${TARGET_ARCH}" = "arm64" ]; then 90 | : ${VMLINUX:="Image"} 91 | : ${CLANG_TARGET:="aarch64-linux-gnu"} 92 | : ${DEBIAN_TARGET_ARCH:="arm64"} 93 | : ${TOOLS_SRCARCH:="arm64"} 94 | : ${QEMU_BIN:="qemu-system-aarch64"} 95 | : ${QEMU_CMD:="${QEMU_BIN} -cpu max -machine virt"} 96 | : ${SERIAL_TTY:="ttyAMA0"} 97 | : ${PROOT_ARGS:="-q qemu-aarch64-static"} 98 | : ${SYZKALLER_TARGETARCH:="arm4"} 99 | : ${ROOT_MNT:="/dev/vda"} 100 | else 101 | echo "Unsupported TARGET_ARCH:" $TARGET_ARCH 102 | exit 2 103 | fi 104 | 105 | : ${KERNEL_PATH:="${WORKSPACE_DIR}/arch/${TARGET_ARCH}/boot/${VMLINUX}"} 106 | 107 | # When called outside of a VSCode task, the current working directory can be 108 | # somewhere else than the workspace. Since we implicitly rely on pwd being the 109 | # top of the kernel tree quite often, cd there. 110 | pushd "$WORKSPACE_DIR" >/dev/null 111 | 112 | if [[ "$CLEAR" == 1 ]]; then 113 | clear 114 | fi 115 | 116 | # SSH Keys 117 | : ${SSH_KEY:="${HOME}/.ssh/linux-kernel-vscode-rsa"} 118 | : ${SSH_CMD:="ssh -p 5555 -i ${SSH_KEY} -o IdentitiesOnly=yes -o NoHostAuthenticationForLocalhost=yes root@localhost"} 119 | : ${SCP_CMD:="scp -P 5555 -r -i ${SSH_KEY} -o IdentitiesOnly=yes -o NoHostAuthenticationForLocalhost=yes"} 120 | if [ ! -f ${SSH_KEY} ]; then 121 | ssh-keygen -t rsa -f ${SSH_KEY} -N "" -q 122 | fi 123 | 124 | # QEMU start command 125 | : ${VM_START:="${QEMU_CMD} -s -nographic -smp 4 -m 4G -qmp tcp:localhost:4444,server,nowait -serial mon:stdio \ 126 | -net nic,model=virtio-net-pci -net user,hostfwd=tcp::5555-:22 \ 127 | -virtfs local,path=/,mount_tag=hostfs,security_model=none,multidevs=remap \ 128 | -append \"console=${SERIAL_TTY},115200 root=${ROOT_MNT} rw nokaslr init=/lib/systemd/systemd debug systemd.log_level=info ${KERNEL_CMDLINE_EXTRA}\" \ 129 | -drive file=${IMAGE_PATH},format=raw -kernel ${KERNEL_PATH} ${VM_START_ARGS}"} 130 | 131 | case "${COMMAND}" in 132 | # Virtual machine life-cycle 133 | "start") 134 | depend_on install-autostart 135 | eval ${VM_START} 136 | ;; 137 | "start-wait-dbg") 138 | depend_on install-autostart 139 | eval ${VM_START} -S 140 | ;; 141 | "stop") 142 | # With SKIP_SYSTEMD, nothing handles ACPI shutdowns so clean shutdown does not work. 143 | if [[ -z $SKIP_SYSTEMD ]]; then 144 | echo -n '{"execute":"qmp_capabilities"} {"execute": "system_powerdown"}' | nc -q 1 localhost 4444 145 | else 146 | killall ${QEMU_BIN} 147 | fi 148 | ;; 149 | "ssh") 150 | eval ${SSH_CMD} 151 | ;; 152 | "run") 153 | shift 154 | eval ${SSH_CMD} $@ 155 | ;; 156 | "wait-for-vm") 157 | # On the first boot, a rootfs isn't yet available. Because debootstrap can 158 | # take a while to run, this waits for the rootfs file to show up. 159 | timeout 120 bash -c "until [ -f ${IMAGE_PATH} ] ; do sleep 0.01; done" 160 | ;; 161 | # Kernel build 162 | "defconfig") 163 | # Only generate .config if it doesn't already exist 164 | if [ ! -f ${WORKSPACE_DIR}/.config ]; then 165 | eval ${MAKE} ARCH=${TARGET_ARCH} defconfig kvm_guest.config 166 | scripts/config --enable DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT 167 | eval ${MAKE} ARCH=${TARGET_ARCH} olddefconfig 168 | fi 169 | ;; 170 | "menuconfig") 171 | # It's important to run menuconfigs with the same parameters as builds 172 | eval ${MAKE} ARCH=${TARGET_ARCH} menuconfig 173 | ;; 174 | "clean") 175 | eval ${MAKE} ARCH=${TARGET_ARCH} clean 176 | ;; 177 | "build") 178 | depend_on defconfig 179 | 180 | # Enable reproducible builds for ccache 181 | export KBUILD_BUILD_TIMESTAMP="" 182 | # Generate not only the kernel but also the clangd config 183 | CMD="${MAKE} ${SILENT_BUILD_FLAG} ARCH=${TARGET_ARCH} all compile_commands.json" 184 | echo ${CMD} 185 | eval ${CMD} & 186 | spinner $! 187 | 188 | # A gdb index may need to be re-generated. Don't clear the above make logs. 189 | CLEAR=0 $SCRIPT gdb-index 190 | # A tracer module may need to be re-built 191 | CLEAR=0 $SCRIPT systemtap-build 192 | ;; 193 | "gdb-index") 194 | # Hitting a breakpoint is *much* faster if we pre-build a gdb symbol index 195 | if ! readelf -S vmlinux | grep -q ".gdb_index"; then 196 | GDB=gdb-multiarch gdb-add-index vmlinux 197 | fi 198 | ;; 199 | # Rootfs management 200 | "create-rootfs") 201 | # Only generate a rootfs if it doesn't already exist 202 | if [ ! -f ${IMAGE_PATH} ]; then 203 | img="$(mktemp -u --suffix=.img)" 204 | img_mnt="$(mktemp -d)" 205 | img_bind_mnt="$(mktemp -d)" 206 | trap 'rm -f ${img}; sudo umount -l ${img_bind_mnt}; sudo umount -l ${img_mnt}; rmdir ${img_mnt} ${img_bind_mnt}' ERR 207 | # Image file creation 208 | qemu-img create ${img} 20G 209 | mkfs -t ext4 ${img} 210 | 211 | # Mounts (bind mounts for permission) 212 | mkdir -p ${img_mnt} ${img_bind_mnt} 213 | echo "password required to mount the rootfs:" 214 | sudo mount -o loop ${img} ${img_mnt} 215 | sudo bindfs --uid-offset=$(id -u) --gid-offset=$(id -g) \ 216 | --create-with-perms=0644,ud+X:gd-rwX:od-rwX ${img_mnt} ${img_bind_mnt} 217 | 218 | # Debian rootfs generation and config setting 219 | sudo mmdebstrap --include ssh,acpid,acpi-support-base,gdb,systemtap,file,psmisc,strace,vim,bpftool,bpftrace,trace-cmd,linux-perf \ 220 | --arch ${DEBIAN_TARGET_ARCH} unstable ${img_mnt} 221 | echo "debian-vm" > ${img_bind_mnt}/etc/hostname 222 | echo "nameserver 8.8.8.8" > ${img_bind_mnt}/etc/resolv.conf 223 | echo "hostfs /host 9p trans=virtio,rw,nofail 0 0" > ${img_bind_mnt}/etc/fstab 224 | printf "[Match]\nName=en*\n[Network]\nDHCP=yes" > ${img_bind_mnt}/etc/systemd/network/80-dhcp.network 225 | sed -i 's~^ExecStart=.*~ExecStart=-/sbin/agetty --autologin root -o "-p -f root" --keep-baud 115200,57600,38400,9600 - $TERM~' ${img_bind_mnt}/lib/systemd/system/serial-getty@.service 226 | mkdir -p ${img_bind_mnt}/root/.ssh/ 227 | cp ${SSH_KEY}.pub ${img_bind_mnt}/root/.ssh/authorized_keys 228 | sudo chroot ${img_mnt} systemctl enable systemd-networkd acpid 229 | cat << EOF > ${img_bind_mnt}/sbin/init-minimal 230 | #!/bin/sh 231 | 232 | # Mount various important file systems 233 | mkdir -p /proc /sys /run/ /tmp /dev 234 | mount -t proc none /proc 235 | mount -t sysfs none /sys 236 | mount -t tmpfs none /run 237 | mount -t tmpfs none /tmp 238 | mount -t devtmpfs none /dev 239 | mkdir -p /dev/pts 240 | mount -t devpts none /dev/pts 241 | # And the content of /etc/fstab 242 | mount -a 243 | 244 | # Set the network interface up 245 | cat /etc/hostname > /proc/sys/kernel/hostname 246 | ip link set eth0 up 247 | dhclient eth0 248 | 249 | # Change cwd to /root 250 | HOME=/root 251 | cd $HOME 252 | 253 | # Start the SSH server 254 | mkdir /run/sshd/ 255 | /usr/sbin/sshd 256 | 257 | # Start the autostart script if there is one 258 | [ -f /usr/bin/autostart.sh ] && /usr/bin/autostart.sh & 259 | 260 | # Set up the serial line and get to a bash prompt 261 | setsid /sbin/getty -l /bin/bash -n 115200 ${SERIAL_TTY} 262 | EOF 263 | chmod +x ${img_bind_mnt}/sbin/init-minimal 264 | cat << EOF > ${img_bind_mnt}/etc/bash.bashrc 265 | # Use a green or red prompt depending on the previous command's exit value 266 | __prompt () { 267 | if [[ $? = "0" ]]; then 268 | PS1='\[\033[01;32m\]' 269 | else 270 | PS1='\[\033[01;31m\]' 271 | fi 272 | PS1="$PS1\u@\h:\w\$ \[\033[00m\]" 273 | } 274 | PROMPT_COMMAND=__prompt 275 | 276 | # On the serial tty, ask the host terminal for dimensions before each command 277 | __resize () { 278 | local escape r c 279 | IFS='[;' read -t 1 -sd R -p "$(printf '\e7\e[r\e[999;999H\e[6n\e8')" escape r c 280 | if [[ "$r" -gt 0 && "$c" -gt 0 ]]; then 281 | stty cols $c rows $r 282 | fi 283 | } 284 | if [[ $TERM = "vt102" ]]; then 285 | trap __resize DEBUG 286 | fi 287 | EOF 288 | 289 | # Atomically make the rootfs file available to unblock wait-for-vm tasks 290 | sync 291 | sudo umount -l ${img_bind_mnt} 292 | sudo umount -l ${img_mnt} 293 | mkdir -p "${IMAGE_DIR}" 294 | mv "${img}" "${IMAGE_PATH}" 295 | fi 296 | ;; 297 | "install-autostart") 298 | depend_on create-rootfs 299 | 300 | cd .vscode/autostart/ 301 | BUILT_AUTOSTART=${IMAGE_DIR}/autostart-${TARGET_ARCH} 302 | 303 | # The poor man's make. We use the last built /tmp/autostart to track if any 304 | # of the source file has changed. Only if one changed, rebuild and install. 305 | if [ ${BUILT_AUTOSTART} -nt autostart.c ] && \ 306 | [ ${BUILT_AUTOSTART} -nt autostart.sh ] && 307 | [ ${BUILT_AUTOSTART} -nt autostart.service ]; then 308 | echo "Autostart already up to date" 309 | exit 0 310 | fi 311 | 312 | clang --target=${CLANG_TARGET} -fuse-ld=lld `cat compile_flags.txt` autostart.c -o ${BUILT_AUTOSTART} 313 | 314 | echo Installing autostart on `basename ${IMAGE_PATH}` 315 | guestfish --rw -a "${IMAGE_PATH}" << EOF 316 | run 317 | mount /dev/sda / 318 | 319 | upload ${BUILT_AUTOSTART} /usr/bin/autostart 320 | chmod 755 /usr/bin/autostart 321 | 322 | upload autostart.sh /usr/bin/autostart.sh 323 | chmod 755 /usr/bin/autostart.sh 324 | 325 | upload autostart.service /lib/systemd/system/autostart.service 326 | ln-sf /lib/systemd/system/autostart.sh /etc/systemd/system/multi-user.target.wants/autostart.service 327 | EOF 328 | ;; 329 | "push") 330 | if [ "$#" -lt 2 ]; then 331 | echo "Usage: $0 push /file/to/push [/destination]" 332 | exit 1 333 | fi 334 | popd >/dev/null 335 | eval ${SCP_CMD} ${2} root@localhost:${3:-/root} 336 | ;; 337 | "pull") 338 | if [ "$#" -lt 2 ]; then 339 | echo "Usage: $0 pull /file/to/pull [/destination]" 340 | exit 1 341 | fi 342 | popd >/dev/null 343 | eval ${SCP_CMD} root@localhost:${2} ${3:-.} 344 | ;; 345 | "chroot") 346 | img_mnt="$(mktemp -d)" 347 | echo "password required to mount the rootfs:" 348 | sudo mount -o loop ${IMAGE_PATH} ${img_mnt} 349 | trap 'sudo umount -l ${img_mnt}; rmdir ${img_mnt}' EXIT 350 | sudo proot -S ${img_mnt} -w / ${PROOT_ARGS} 351 | ;; 352 | # BPF selftests 353 | "install-bpf-selftests") 354 | # Mount the poor man's sysroot 355 | ROOTFS_MOUNT_POINT=${HOME}/.linux-kernel-vscode/mnt 356 | echo "Mounting the VM's rootfs as a sysroot under ${ROOTFS_MOUNT_POINT}. If you miss any library, just install them in the VM:" 357 | echo " apt install libstdc++-12-dev libz-dev libelf-dev libcap-dev" 358 | mkdir -p ${ROOTFS_MOUNT_POINT} 359 | guestmount -a ${IMAGE_PATH} -m /dev/sda --ro -o dev ${ROOTFS_MOUNT_POINT} 360 | trap "guestunmount ${ROOTFS_MOUNT_POINT}" EXIT 361 | 362 | # Compile 363 | CLANG_CROSS_FLAGS="--target=${CLANG_TARGET} --sysroot=${ROOTFS_MOUNT_POINT}" \ 364 | eval ${MAKE} CROSS_COMPILE=${CLANG_TARGET}- SRCARCH=${TOOLS_SRCARCH} -C ${BPF_SELFTESTS_DIR} 365 | 366 | eval ${SCP_CMD} ${BPF_SELFTESTS_DIR}/test_progs root@localhost:/root 367 | ;; 368 | "run-bpf-selftests") 369 | depend_on install-bpf-selftests 370 | eval ${SSH_CMD} /root/test_progs 371 | ;; 372 | "run-bpf-selftest") 373 | if [ "$#" -ne 2 ]; then 374 | echo "Usage: $0 run-bpf-selftest selected_file" 375 | exit 1 376 | fi 377 | SELECTED_FILE=$2 378 | if [ `dirname ${SELECTED_FILE}` == ${BPF_SELFTESTS_DIR}/prog_tests ]; then 379 | depend_on install-bpf-selftests 380 | eval ${SSH_CMD} "/root/test_progs -t `basename ${SELECTED_FILE} .c`" 381 | else 382 | echo -e "\e[31mOpen a test in ${BPF_SELFTESTS_DIR}/prog_tests/\e[0m" 383 | fi 384 | ;; 385 | # Fuzzing 386 | "enable-kcov") 387 | depend_on defconfig 388 | if grep -q -F "CONFIG_KCOV=y" .config; then 389 | echo KCOV is already enabled 390 | else 391 | echo Enabling KCOV... 392 | scripts/config -e KCOV -e KCOV_ENABLE_COMPARISONS 393 | eval ${MAKE} ARCH=${TARGET_ARCH} olddefconfig 394 | 395 | echo Rebuilding the kernel with KCOV... 396 | ${SCRIPT} build 397 | fi 398 | ;; 399 | "fuzz") 400 | depend_on enable-kcov 401 | 402 | if [ ! -d "${SYZKALLER_DIR}" ] ; then 403 | git clone https://github.com/google/syzkaller ${SYZKALLER_DIR} 404 | fi 405 | make -C ${SYZKALLER_DIR} TARGETARCH=${SYZKALLER_TARGETARCH} manager fuzzer execprog executor 406 | 407 | cat > /tmp/syz-manager.cfg << EOF 408 | { 409 | "target": "linux/${SYZKALLER_TARGETARCH}", 410 | "http": "0.0.0.0:56741", 411 | "sshkey": "${SSH_KEY}", 412 | "workdir": "${SCRIPT_DIR}/syzkaller-workdir", 413 | "kernel_obj": "${WORKSPACE_DIR}", 414 | "syzkaller": "${SYZKALLER_DIR}", 415 | "type": "isolated", 416 | "reproduce": false, 417 | ${SYZ_MANAGER_CFG_EXTRA} 418 | "vm": { 419 | "targets": [ "127.0.0.1:5555" ], 420 | "target_dir": "/root/fuzzing/", 421 | "target_reboot": false 422 | } 423 | } 424 | EOF 425 | ${SYZKALLER_DIR}/bin/syz-manager -config /tmp/syz-manager.cfg 426 | ;; 427 | # Tracing 428 | "systemtap-build") 429 | if [ -f ${TRACER_PATH} ]; then 430 | echo Re-building ${TRACER_PATH} ... 431 | # Workaround the presence of mcount nops with PR15123_ASSUME_MFENTRY 432 | # Skip the loading part of the pipeline with -p4. Use Guru mode with -g 433 | # Workaround clang warnings (treated as errors) with -Wno-everything 434 | PR15123_ASSUME_MFENTRY=1 stap -p4 -g -r ${WORKSPACE_DIR} -m tracer \ 435 | -B LLVM=1 -B CFLAGS_MODULE="-Wno-everything" ${TRACER_PATH} > /dev/null 436 | # The guest doesn't know $WORKSPACE_DIR but it can hardcode /host/tmp/ 437 | echo Installing to /tmp/tracer.ko ... 438 | mv tracer.ko /tmp/ 439 | else 440 | rm -f /tmp/tracer.ko 441 | fi 442 | ;; 443 | # linux-kernel-vscode pull 444 | "update") 445 | cd .vscode 446 | 447 | trap "cp -r /tmp/local.sh /tmp/autostart ." EXIT 448 | cp local.sh /tmp/ 449 | cp -r autostart/ /tmp/ 450 | 451 | git checkout -- local.sh autostart/* 452 | git pull 453 | 454 | chmod u+x "${SCRIPT_DIR}/tasks.sh" 455 | # see comments in the .jsonnet file to understand this magic. 456 | if [ ! -e "settings.json" ]; then 457 | # Seed JSonnet with empty object 458 | echo "{}" > "settings.json" 459 | fi 460 | if [ ! -e "settings-extra.json" ]; then 461 | # Seed JSonnet with empty object 462 | echo "{}" > "settings-extra.json" 463 | fi 464 | tmp="$(mktemp --suffix=.json)" 465 | jsonnet settings.jsonnet \ 466 | --ext-code-file old_settings="settings.json" \ 467 | --ext-code-file extra_settings="settings-extra.json" > "${tmp}" 468 | mv "$tmp" settings.json 469 | ;; 470 | *) 471 | echo "Invalid command" 472 | ;; 473 | esac 474 | --------------------------------------------------------------------------------