diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ebda902 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.jekyll-cache diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..48f6452 --- /dev/null +++ b/Gemfile @@ -0,0 +1,7 @@ +source "https://rubygems.org" + +gem 'jekyll', '~> 4.0' + +group :jekyll_plugins do + gem 'jekyll_picture_tag', '~> 2.0' + end \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..ad48158 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,84 @@ +GEM + remote: https://rubygems.org/ + specs: + addressable (2.8.1) + public_suffix (>= 2.0.2, < 6.0) + colorator (1.1.0) + concurrent-ruby (1.1.10) + em-websocket (0.5.3) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0) + eventmachine (1.2.7) + ffi (1.15.5) + forwardable-extended (2.6.0) + http_parser.rb (0.8.0) + i18n (1.12.0) + concurrent-ruby (~> 1.0) + jekyll (4.3.1) + addressable (~> 2.4) + colorator (~> 1.0) + em-websocket (~> 0.5) + i18n (~> 1.0) + jekyll-sass-converter (>= 2.0, < 4.0) + jekyll-watch (~> 2.0) + kramdown (~> 2.3, >= 2.3.1) + kramdown-parser-gfm (~> 1.0) + liquid (~> 4.0) + mercenary (>= 0.3.6, < 0.5) + pathutil (~> 0.9) + rouge (>= 3.0, < 5.0) + safe_yaml (~> 1.0) + terminal-table (>= 1.8, < 4.0) + webrick (~> 1.7) + jekyll-sass-converter (2.2.0) + sassc (> 2.0.1, < 3.0) + jekyll-watch (2.2.1) + listen (~> 3.0) + jekyll_picture_tag (2.0.4) + addressable (~> 2.6) + jekyll (~> 4.0) + mime-types (~> 3.0) + objective_elements (~> 1.1) + rainbow (~> 3.0) + ruby-vips (~> 2.0.17) + kramdown (2.4.0) + rexml + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + liquid (4.0.3) + listen (3.7.1) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + mercenary (0.4.0) + mime-types (3.4.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2022.0105) + objective_elements (1.1.2) + pathutil (0.16.2) + forwardable-extended (~> 2.6) + public_suffix (5.0.0) + rainbow (3.1.1) + rb-fsevent (0.11.2) + rb-inotify (0.10.1) + ffi (~> 1.0) + rexml (3.2.5) + rouge (4.0.0) + ruby-vips (2.0.17) + ffi (~> 1.9) + safe_yaml (1.0.5) + sassc (2.4.0) + ffi (~> 1.9) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) + unicode-display_width (2.3.0) + webrick (1.7.0) + +PLATFORMS + x86_64-linux + +DEPENDENCIES + jekyll (~> 4.0) + jekyll_picture_tag (~> 2.0) + +BUNDLED WITH + 2.3.26 diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000..8b0bdc4 --- /dev/null +++ b/_config.yml @@ -0,0 +1,10 @@ +url: "https://jackbondpreston.me" # the base hostname & protocol for your site, e.g. http://example.com +baseurl: "" # the subpath of your site, e.g. /blog +title: "jack bond-preston" # the name of your site, e.g. ACME Corp. + +show_dir_listing: true + +safe: false + +picture: + source: "pictures/" \ No newline at end of file diff --git a/_layouts/default.html b/_layouts/default.html new file mode 100644 index 0000000..34c9b22 --- /dev/null +++ b/_layouts/default.html @@ -0,0 +1,26 @@ + + + + + + + + + + {{ page.title }} - {{ site.title }} + + + + + + {{ content }} + + + \ No newline at end of file diff --git a/_layouts/post-sensor-watch.html b/_layouts/post-sensor-watch.html new file mode 100644 index 0000000..fa9d43f --- /dev/null +++ b/_layouts/post-sensor-watch.html @@ -0,0 +1,214 @@ + + + + + + + + + + {{ page.title }} - {{ site.title }} + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

{{ page.title }}

+ + {{ content }} + +
+ +

email me to have a conversation

+
+
+ \ No newline at end of file diff --git a/_layouts/post.html b/_layouts/post.html new file mode 100644 index 0000000..f9438db --- /dev/null +++ b/_layouts/post.html @@ -0,0 +1,13 @@ +--- +layout: default +--- + +
+

{{ page.title }}

+ + {{ content }} + +
+ +

email me to have a conversation

+
\ No newline at end of file diff --git a/_plugins/header.rb b/_plugins/header.rb new file mode 100644 index 0000000..b5bfe90 --- /dev/null +++ b/_plugins/header.rb @@ -0,0 +1,6 @@ +# https://stackoverflow.com/a/53893197/ +class Jekyll::MarkdownHeader < Jekyll::Converters::Markdown + def convert(content) + super.gsub(/(.*)<\/h(\d)>/, '\3[]') + end + end diff --git a/_posts/2022-11-14-sensor-watch.md b/_posts/2022-11-14-sensor-watch.md new file mode 100644 index 0000000..f7b966d --- /dev/null +++ b/_posts/2022-11-14-sensor-watch.md @@ -0,0 +1,102 @@ +--- +layout: post-sensor-watch +title: "sensor watch" +--- + +## preamble +some time back I was browsing [Crowd Supply](https://www.crowdsupply.com/) when I came across [the Sensor Watch project](https://www.crowdsupply.com/oddly-specific-objects/sensor-watch) by [Joey Castillo](https://github.com/joeycastillo). I had wanted some kind of "hackable" watch for a while, and had looked at things like [Watchy](https://www.crowdsupply.com/sqfmi/watchy), but this project hit the sweet spot for me. I love my existing F91-W, and this project was a good combination of open source with community software support. one key feature that was important to me is battery life - the Sensor Watch battery life in an average usage scenario is so long that [Joey's is still going strong](https://twitter.com/josecastillo/status/1590066358351298560)! + +I was excited to pick one up and start messing around with it, but the first issue I came across was availability - the delivery date for Crowd Supply orders was summer 2023 (I think they ended upbeing delivered sooner than this, not sure). on top of this, shipping and import fees made it pretty prohibitively expensive. I've always found this to be an issue with Crowd Supply as someone based in the UK, even some things designed in the UK are very expensive from Crowd Supply as they are assembled in/shipped from the US. so I decided to build one myself! of course, this is more expensive than just buying it, but this was a learning experience and [knowledge is power](https://www.reddit.com/r/AskReddit/comments/dxosj/what_word_or_phrase_did_you_totally_misunderstand/c13pbyc/)! + + +## component acquisition +the first challenge was acquiring all the necessary parts to actually build one. I downloaded [the PCB files](https://github.com/joeycastillo/Sensor-Watch/tree/main/PCB/Main%20Boards) and generated a [BOM](https://en.wikipedia.org/wiki/Bill_of_materials) to figure out exactly what I needed to acquire. I'm sure in ordinary times this would be easy enough, but the current state of some electronics/silicon supply chains had other things to say. some parts are of course still easy to come across, e.g. 10pF 0402 caps and 10k 0603 resistors; most of the components of the Sensor Watch are this kind of commonplace part. what quickly became clear from some scouring of the internet was that my main problem was going to be two parts: the [ATSAML22J18A-MUT](https://www.microchip.com/en-us/product/ATSAML22J18A)(the processor driving the Sensor Watch), and the [FH19C-9S-0.5SH(10)](https://www.hirose.com/en/product/series/FH19C__FH19SC) (the connector used to attach the extra sensor boards). + +### ATSAML22J18A-MUT +the former of these was a fairly well discussed shortage that had been ongoing for a while. it was +[the driving force of the Sensor Watch Crowd Supply delay](https://www.crowdsupply.com/oddly-specific-objects/sensor-watch/updates/blue-boards-shipping-check-your-address-green-boards-delayed-and-other-news-of-the-watch). I spent quite a lot of time searching around the internet, looking at various sites on the English-speaking and Chinese-speaking web. sadly this part was clearly in very short supply, and prices could get pretty insane from vendors that did have some stock. I received quotes for unit prices that include the following (USD/GBP): $79.35, $6.56, $13.61, $6.83 (MOQ 4000), £6.45. I guess some people are desperate enough to pay $79.35 :(. I spent so long looking for them that they ended up randomly coming back in stock on [MicrochipDirect](https://www.microchipdirect.com/). as of the time of writing this article, [they are again out of stock](https://www.microchipdirect.com/product/ATSAML22J18A-MUT). the unit price I bought them for was £3.92, shipping and handling was ~£12. + +### FH19C-9S-0.5SH(10) +this part was out of stock everywhere I initially looked (the usual contenders for parts). I searched around in a similar manner as the ATSAML22J18A-MUT, and found some similarly wild pricing. I ended up purchasing a small quantity at a unit price of £0.44 from a website called +[dacikeys](http://archive.today/2022.11.13-230943/https://www.dacikeys.net/). yes, the site is actually called this. yes, the unit price is cheaper than digikey and mouser. yes, I actually received all of my order, consisting of working parts. I was definitely shocked that this happened, but sometimes bravery pays off I guess. I still can't endorse this shop. + +### PCB and stencil +for the PCB I opted to go with [JLCPCB](https://jlcpcb.com/). I simply uploaded the relevant gerbers, and adjusted the necessary settings. notably, [the thickness should be 0.6mm](https://github.com/joeycastillo/Sensor-Watch/issues/14#issuecomment-922974276">) - this does narrow the choice of manufacturer (for example, OSH Park doesn't go this thin). I haven't yet ordered any sensor board PCBs, but [PCBWay](https://www.pcbway.com/) seems to be *the* option there. The PCB turned out great, although the silkscreen is a little hard to read at this size due to lack of sharpness: +{% picture jpt-webp sensor-watch/pcb.jpg --alt a closeup of a sensor watch PCB %} + + +## assembly +I decided to assemble myself. partially because the logistics of paying for assembly when I had to source parts from many different providers seemed like a headache, partially because I thought it would be a fun challenge and learning experience! + +a few things were necessary to solder the components to this PCB. I'm sure someone talented could hand solder this with an iron, but I can name a lot of things I'd rather do than try to do that +(especially the [QFN](https://en.wikipedia.org/wiki/Flat_no-leads_package) SAML) - and that list includes unpleasant things. I opted to go with +[hotplate soldering](http://www.flyelectric.org.uk/hot_plate.htm), which is a cheaper way to access the ease of reflow soldering. for a PCB like the Sensor Watch, where almost all the components are on one side, it's ideal. the hotplate I have is the ever-popular +[MHP30](https://www.miniware.com.cn/product/mhp30-mini-hot-plate-preheater/), which I run [IronOS](https://github.com/Ralim/IronOS) on. I highly recommend it, it's great! my soldering iron is the iconic +[Pinecil](https://pine64.com/product/pinecil-smart-mini-portable-soldering-iron/) (not the [fancy new V2](https://www.pine64.org/2022/07/28/july-update-a-pinecil-evolved/) though :[) which also runs IronOS. nice! + +### process +the assembly process is as follows: +- apply solder paste to the PCB with the stencil. make sure the stencil is really flush and justkind of squeegee it on with a plastic card. I used tape to hold it in place. then carefully removed the stencil, avoiding smudging the paste in doing so. +- place components on the PCB. this was by far the most painful part of the whole process. a steady hand is not something I was blessed with, and some of these parts are really small. I used a microscope from Amazon for this, the ample manouverable lighting was a big help. a lot of time and patience is required, but it's very first time doable with no prior experience! simply go through the parts one by one, or by area of the board - whatever you prefer. then pick up the respective part with some fine tweezers, and slowly put in place on the solder paste. thankfully, the paste will lightly stick the component in place once you've done this (it is not knock-proof though!). +- carefully (really!) place the PCB onto the hotplate and heat up. keep on until everything seems to be melted, and the components have hopefully been pulled into place. that's the top side done! let it cool down, then move on to the bottom. +- time for some hand soldering. the button is pretty small, and very fiddly to do. I found you don't need too much precision, but you have to be really careful with your iron as the plastic button will melt if you touch it. once that's in place, it's just a matter of +[removing the buzzer connector from your old PCB and soldering it onto the back of the Sensor Watch PCB.](https://youtu.be/Zr0pKeC2VFU?t=185) this will feel blissfully easy after the button! you also have to place the battery clip, but no soldering needed here :). + +one area I found particularly difficult was the area with the oscillator crystal and the two 0402 capacitors, C7 and C8. things are a bit cramped here, so extra care was needed: +{% picture jpt-webp sensor-watch/c7c8.jpg --alt a closeup of a sensor watch PCB, with an area circled. the area contains some small, and closely grouped pads %} + + +## software +at this point the watch was assembled with all components in place. did it work? at this stage, no idea. hopefully yes, and I could progress to the more familiar world of embedded software. + + +### bootloader +the next necessary step is to flash the bootloader, so that we can put the firmware in place. unfortunately this requires a little more real-world action. we need to access the SWD points on the board to write the bootloader. ideally you could do this with some kind of +[pogo pin](https://en.wikipedia.org/wiki/Pogo_pin) jig - and if you were doing any number exceeding about 5 I'm sure this would be worth the time. however, I decided to just solder some jump wires (stripped on one end, solid tip female on the other) to the points on the board. they're all close, but it's easy enough to do (albeit ugly). then I connected these to my +[Adafruit Trinket M0](https://www.adafruit.com/product/1501) (PyRuler would also work).the pin mapping is as follows: SWD=0, SWC=1, RST=3, V+=3V, GND=GND. + + +I used the +[flasher from the sensor watch repo to flash the bootloader](https://github.com/joeycastillo/Sensor-Watch/blob/main/utils/flash_watch_pyruler/flash_watch_pyruler.ino). note that you could build the bootloader yourself first and put the generated binary into bootloader.h - the source is located +[here](https://github.com/joeycastillo/uf2-samdx1). personally, I just used the prebuilt version from the repo. I had to change part of the Adafruit DAP library and add the SAM L22 DID to get this to work, +[I provided the diff of this change](https://github.com/joeycastillo/Sensor-Watch/issues/83#issuecomment-1229353899) in a Sensor Watch GitHub issue (I just now am remembering I promised to upstream this, oops!). mercifully, I got the red blinky LED, and all was good! I unsoldered the wires from the board, and tried to clean up most of the solder blob to keep the board fairly flat. + + +### movement +now the bootloader is in place, the main firmware can be installed! +[the community firmware, Movement](https://www.sensorwatch.net/docs/movement/)is great, so this is what I installed. there are a bunch of different useful faces available, and more functionality is always being added. +flashing firmware was easy: I plugged the PCB into the end of a USB Micro B cable (plugged on the other end into my computer) and double tapped the reset button (I find this has to be done quite quickly, using my fingernail was the trick to doing this reliably on such a small button). done successfully, the LED on the board pulses and a new drive labelled "WATCHBOOT" appears on the computer. now a built UF2 firmware file can just be dragged onto the device to flash, thanks to the bootloader flashed earlier. for the initial test, I just used a +[prebuilt image](https://www.sensorwatch.net/docs/firmware/prebuilt/) to check everything was working. I flashed this, and the LED pulsed and turned off, signalling success. + +from here I just assembled the watch with the Sensor Watch PCB, and it worked! I verified LED and buzzer function by playing around with various functionality. success! + + +## developing on movement +one face I found particularly cool was the [TOTP face](https://github.com/joeycastillo/Sensor-Watch/blob/main/movement/watch_faces/complication/totp_face.c). I use [TOTP](https://en.wikipedia.org/wiki/Time-based_one-time_password) +[2FA](https://en.wikipedia.org/wiki/Multi-factor_authentication) on various accounts, so having access to the codes on my wrist at all times was really appealing. at the time, the TOTP face only supported one key - so I decided to improve it. + +thankfully, Sensor Watch has an emulator for development. without this, development would be pretty tiresome with the flashing and reassembling of the watch getting tiring if you needed to iterate on some code and test it on the watch. the emulator runs inside the browser and uses +[Emscripten](https://en.wikipedia.org/wiki/Emscripten). +[some minimal instructions on how to build this is available on the README](https://github.com/joeycastillo/Sensor-Watch#using-the-movement-framework). this allowed me to extend the TOTP face easily and allow for multiple keys. +[my PR was merged](https://github.com/joeycastillo/Sensor-Watch/pull/84), and the functionality is now available for anyone to use. the keys are added at compile time, so they are baked into the firmware on flashing. for my purposes this is fine, as I never really change them. however, with the recent addition of a +[LittleFS](https://os.mbed.com/blog/entry/littlefs-high-integrity-embedded-fs/) filesystem, the community have added [a version of the face which stores the keys on the filesystem](https://github.com/joeycastillo/Sensor-Watch/blob/main/movement/watch_faces/complication/totp_face_lfs.c). awesome! + +some more details on using Sensor Watch for TOTP is available +[on this blog post](https://blog.singleton.io/posts/2022-10-17-otp-on-wrist/) +([HN discussion, if you dare](https://news.ycombinator.com/item?id=33243434)). it's even running my code :)! + + +## epilogue +some summary thoughts: +- shoutout to Joey Castillo. for creating the Sensor Watch as a beautifully open source project (the fact I could independently make my own is what it's all about!). for being +[so helpful and kind](https://github.com/joeycastillo/Sensor-Watch/issues/83) when I asked for help. for having such a positive attitude towards those in the community who are using Sensor Watch to learn about all kinds of things (seriously, check out the +[Oddly Specific Objects Discord](https://discord.gg/NtMVTBNca7) to see how much this guy is giving to the community). +- sometimes it's worth just trying things that are difficult. this is my first time successfully doing and small-scale soldering of this kind, and it worked out great with some patience. having the motivation from making something I thought was really cool was an important factor here I think. +- if you have a Sensor Watch (or are planning to!) please go ahead and [contribute to movement](https://github.com/joeycastillo/Sensor-Watch) if you have a cool idea. I'm sure some reviews would be helpful to spot any issues on existing PRs before a maintainer gets to them to save some time. +- the one issue I've had with using my Sensor Watch for TOTP is clock accuracy. the clock drifts over time, so I have to set the time once or twice a week to keep it nice and accurate for the TOTP functionality to be nice to use. but a community member is working on this, and it's going to get a lot better. check out the Discord channel to see some seriously cool engineering going into this calibration effort. + + +{% picture sensor-watch/watch1.jpg --alt a shot of a yellow and black assembled sensor watch, lying horizontally on a surface %} +{% picture sensor-watch/watch2.jpg --alt a shot of a yellow and black assembled sensor watch, lying vertically on a surface %} +{% picture sensor-watch/wrist.jpg --alt a shot of a yellow and black assembled sensor watch, on the author's wrist %} + diff --git a/_posts/cheri/2022-11-19-cheri.md b/_posts/cheri/2022-11-19-cheri.md new file mode 100644 index 0000000..667e852 --- /dev/null +++ b/_posts/cheri/2022-11-19-cheri.md @@ -0,0 +1,234 @@ +--- +layout: post +title: "CHERI" +--- + +## preamble +[CHERI](https://www.cl.cam.ac.uk/research/security/ctsrd/cheri/) is an acronym for Capability Hardware Enhanced RISC Instructions. it is a security-focussed project aimed at improving memory protection at the hardware level. the project is complex and it has many potential applications. + +in this article I will go into some basics to give an understanding behind some changes that CHERI makes to how programs execute and are written. this will be focussed almost entirely in C, as this is where my experience lies - it is also where some of the effects of CHERI are most easily felt.this article is going to be a _very simplistic_ introduction to CHERI, and I'm going to attempt to explain the basics behind everything I cover. a basic understanding of C will be beneficial. + +***note:*** [the Morello platform](https://www.arm.com/architecture/cpu/morello) is an evaluation board produced by [Arm](https://www.arm.com/) to provide a physical implementation of CHERI extending [the Arm AArch64 ISA](https://en.wikipedia.org/wiki/AArch64). I previously worked on this platform at Arm, [porting the musl C library to Morello](https://git.morello-project.org/morello/musl-libc/). implementations for CHERI that are worth looking into from a more open perspective are the MIPS (chapter 4) and RISC-V (chapter 5) ones. Morello is the only implementation that exists in a true hard core format, afaik - but this is obviously hard to obtain so you'll just be playing around with emulators/models anyway. + + +## memory safety bugs +to first understand how CHERI tries to fix some simple issues, let's first look at some simplified examples of issues that arise when we aren't using a CHERI-based architecture. + + +### a simple memory safety bug +let's take a look at this C code: + +{% highlight c linenos %} +{% include_relative code/membug.c %} +{% endhighlight %} + +now let's try using our new program: + +{% highlight console %} +$ ./membug +enter your name: jack +hello jack +my_perfect_string: what a beautiful string +{% endhighlight %} + +works on my machine boss! code review +1, and merged... until our good friend Hubert Blaine Wolfeschlegelsteinhausenbergerdorff Sr. comes along. he emails me a strangeerror he's seen: + +{% highlight console %} +$ ./membug +enter your name: Hubert Blaine Wolfeschlegelsteinhausenbergerdorff Sr. +hello Hubert Blaine Wolfeschlegelsteinhausenbergerdorff Sr. +my_perfect_string: hausenbergerdorff Sr. +{% endhighlight %} + +that's not supposed to happen! his name has spilled over into our `my_perfect_string[]` array! turns out our issue is that when we use `fgets()`, we've set the second parameter, `size`, to `1000` - but our `user_name[32]` array c1593an only fit 32 characters (and the last of these should be a null terminator, so 31 usable characters). + +`fgets` fills up `user_name`, but it hasn't finished with the name yet! it doesn't care (or know) that `user_name` is full, it's just going to keep going until it finishes our user input, or reads 999 characters from standard input. and thus it keeps mindlessly writing, overwriting the memory we've used to store our precious perfect string (which happens to be immediately after `user_name`). let's take a look at the stack in GDB to see why this happens: + +{% highlight plaintext %} +(gdb) b memdebug.c:7 +(gdb) run +Breakpoint 1, main () at membug.c:7 +7 printf("enter your name: "); +(gdb) n +8 fgets(user_name, 1000, stdin); // get user's name from stdin +(gdb) n +9 printf("hello %s", user_name); +(gdb) x/56bc $sp +0x7fffffffdbf0: 106 'j' 97 'a' 99 'c' 107 'k' 10 '\n' 0 '\000' 0 '\000' 0 '\000' +0x7fffffffdbf8: 77 'M' 82 'R' 85 'U' 85 'U' 85 'U' 85 'U' 0 '\000' 0 '\000' +0x7fffffffdc00: -24 '\350' -78 '\262' -5 '\373' -9 '\367' -1 '\377' 127 '\177' 0 '\000' 0 '\000' +0x7fffffffdc08: 0 '\000' 82 'R' 85 'U' 85 'U' 85 'U' 85 'U' 0 '\000' 0 '\000' +0x7fffffffdc10: 119 'w' 104 'h' 97 'a' 116 't' 32 ' ' 97 'a' 32 ' ' 98 'b' +0x7fffffffdc18: 101 'e' 97 'a' 117 'u' 116 't' 105 'i' 102 'f' 117 'u' 108 'l' +0x7fffffffdc20: 32 ' ' 115 's' 116 't' 114 'r' 105 'i' 110 'n' 103 'g' 0 '\000' +{% endhighlight %} + +we can see our two character arrays are right next to each other on the stack (`user_name` contains some gibberish as it is not zero-initialised). + +***note:*** this code was compiled with `-fno-stack-protector` to reproduce this behaviour. compilers have certain techniques like this which can help protect against such attacks, but there are often ways around these by using less primitive attacks. + +okay, it's a pretty easy fix, we just need to change the `fgets(char *s, int size, FILE *stream)` parameter `size` to `32`. + +***note:*** you may initially think "why not 31? don't we need to save a character for the null byte at the end?". thankfully, `fgets` does this for us. excerpt from `man fgets`: + +> "fgets() reads in _at most one less than size_ characters from stream and stores them into the buffer pointed to by s [...] A terminating null byte ('\0') is stored after the last character in the buffer". + +this is a good question to be asking though, being careful is key when it comes to these kinds of things. + + +### why hardware? +okay, so that's an easy fix. why are we talking about doing anything in hardware here? just write the code correctly! the issue is code gets very complex, and this is a very simplistic situation. some memory safety bugs can be incredibly complicated and go unnoticed for decades. the C language especially gives the programmer many, many opportunities to make mistakes - and it only takes one to be a problem. a lot of the software we are using these days is based on stacks upon stacks of software written in different languages, and there are going to be bugs in there. CHERI should give us some protection "for free" (it's not this simple, in actuality). + +some languages (e.g. Rust) are going to offer you strong memory safety guarantees at compile-time, but that's not the topic of this article. the differences between doing this kind of protection in software or hardware (or both) is more complex than the scope of this article. in addition, CHERI's benefits are more wide in breadth than just protecting against this kind of issue. + + +## pointers recap +let's quickly recap a basic idea of what a pointer is. we're going to ignore things like [virtual memory](https://en.wikipedia.org/wiki/Virtual_memory) for brevity. we can think of a pointer in a normal 64-bit architecture (e.g. AArch64) simply as a 64-bit unsigned value that holds the memory address of something we care about. this is a simplification (as are most things), but it can help us reason about the general idea: + +{% highlight c %} +int val = 1593; +int *x = &val; // x points to val +{% endhighlight %} + +int *x0x0000010000000004addressmem[0x0000010000000004]mem[0x0000010000000000]mem[0x0000010000000008]1593memory (as ints) + +and on these normal architectures, this pointer generally is just a number. we can do weird things with it, treating it as a number... + +{% highlight c linenos %} +{% include_relative code/ptrs_as_numbers.c %} +{% endhighlight %} + +...and this code will often still work: + +{% highlight console %} +$ ./ptrs_as_numbers +*x=1234 +*x=5678 +*x=9999 +{% endhighlight %} + +yikes! now, when you start messing with pointers like this, you're bound to run into a bunch of undefined behaviour. but C programmers write undefined behaviour all the time, and my computer executes this program fine without complaining at all. doesn't it feel a bit weird that we can take a pointer to `arr[0]` and modify it to load `secret`? they're not even part of the same array... + + +## introducting capabilities +CHERI introduces capabilities, which can be thought of as an extension to pointers. they still store an address of something we care about, but they have extra information too! in a 64-bit system, a pointer would typically be a 64-bit value (as dicussed previously). the corresponding capability in a CHERI platform is 128 bits (or 129 bits if you look at it a certain way, more about that later...). + +as you might have guessed, this "extra information" takes up 64 bits of the capability. bits are assigned to three key pieces of metadata: *bounds*, *permissions*, and *object type*. there is also an additional 1-bit _tag_ which is stored out-of-band: it is not a 129-bit value - instead each 128-bit capability can be thought of as being associated with a 1-bit validity tag. the architecture manages this. the diagram below is provided as a rough overview of this. note that it is not to scale. + +int *x (capability)0x0000010000000004addressboundsobject typepermissionstag (out-of-band) + +I am mostly going to focus on _bounds_ in this article, as it is not too difficult to grasp, and the impact is fairly easy to demonstrate for some simple examples. the bounds represent an upper and lower bound on the memory region (address space) that this capability is allowed to access. if we try to use the capability to access some address outside of this range, the hardware will throw a fault - it simply won't let us do this! + +**_note:_** it is important to note that I am going to oversimplify the way the bounds are stored in this article. this especially includes the diagram above. in reality, there is a complex compression method, necessitated by the range and sizes required by bounds. this depends on the address value, alignment, etc. for now, we shouldn't need to think about this much, just know it will be managed for us. the key take-away from this is that *bounds can't always be 100% precise for all addresses and ranges*. + +can you imagine how we can use bounds to prevent our previous memory safety bug from occurring? the key is that we can set the bounds on the capability pointing to `user_name` which we pass to `fgets`, such that the capability may only access the contents of the array. this means that when `fgets` tries to write past the end of the `user_name` array, the processor will throw a *capability fault*, and execution of our program will cease. + +the idea behind CHERI is that we don't have to set up these bounds ourselves. this is something the compiler can generate code for. the compiler knows that the `user_name` array has a length of `32`, and can set the bounds accordingly on capabilities created that point to it. let's try it... + + +## playing with CHERI RISC-V +unless you're lucky enough to have access to a physical Morello board, there is the issue of actually using a CHERI implementation. for this article I will be making use of the [QEMU](https://en.wikipedia.org/wiki/QEMU) emulator to emulate a [RISC-V](https://en.wikipedia.org/wiki/RISC-V) CHERI environment. running [CheriBSD](https://www.cheribsd.org/) on this emulator will allow us to have a nice [FreeBSD](https://www.freebsd.org/)-based capability-enabled environment to play around with. I'll use [cheribuild](https://github.com/CTSRD-CHERI/cheribuild) to easily get set up (the `cheribuild.py` step will take a very long time the first time): + +{% highlight console %} +$ sudo apt install autoconf automake libtool pkg-config clang bison cmake \ +ninja-build samba flex texinfo time libglib2.0-dev libpixman-1-dev \ +libarchive-dev libarchive-tools libbz2-dev libattr1-dev libcap-ng-dev +$ git clone git@github.com:CTSRD-CHERI/cheribuild +$ cd cheribuild +$ ./cheribuild.py --include-dependencies --run/ssh-forwarding-port 2222 run-riscv64-purecap +CheriBSD/riscv (cheribsd-riscv64-purecap) (ttyu0) + +login: root +root@cheribsd-riscv64-purecap:~ # +{% endhighlight %} + +now we have our shell inside our CheriBSD emulated platform, we can start to try things out. let's compile our `membug` program again, this time with the toolchain targetting CheriBSD RISC-V - this will have been built as part of the dependencies already. once it's built, we can `scp` it over to the CheriBSD filesystem, as we set up the SSH forwarding port to +`1111`. + +{% highlight console %} +# on a separate terminal on your host machine +$ ~/cheri/output/sdk/utils/cheribsd-riscv64-purecap-clang membug.c -Wall -g -fno-stack-protector -o membug-cheribsd +$ scp -P 2222 ./membug-cheribsd root@localhost:~/ +{% endhighlight %} + +and now we can see what happens when we explore our bug with CHERI: + +{% highlight console %} +$./membug-cheribsd +enter your name: jack +hello jack +my_perfect_string: what a beautiful string + +$ ./membug-cheribsd +enter your name: Hubert Blaine Wolfeschlegelsteinhausenbergerdorff Sr. +In-address space security exception (core dumped) +{% endhighlight %} + +it's working! we are getting a capability fault as we exceed the bounds of the +`user_name` capability bounds. we can use gdb to verify this is caused by the bounds fault: + +{% highlight plaintext linenos %} +(gdb) run +Starting program: /root/membug-cheribsd +enter your name: Hubert Blaine Wolfeschlegelsteinhausenbergerdorff Sr. + +Program received signal SIGPROT, CHERI protection violation. +Capability bounds fault caused by register ca6. +0x0000000040314ce8 in memcpy (dst0=0x3fffdfff44, src0=, length=54) at /home/jack/cheri/cheribsd/lib/libc/string/bcopy.c:143 +(gdb) p $ca6 +$1 = () 0x3fffdfff78 [rwRW,0x3fffdfff44-0x3fffdfff64] +{% endhighlight %} + +as we can see, the bounds for our `user_name` capability (which is stored in capability register `ca6`) are `0x3fffdfff44-0x3fffdfff64`, but the address is `0x3fffdfff78`. this is out of the bounds allowed by the capability, so the architecture throws a fault. if we look at the assembly generated by the compiler, we can see it set our capability bounds to a size of 32 to enforce this behaviour: + +{% highlight armasm linenos %}0000000000001ce8
: +; int main() { + cincoffset csp, csp, -160 + csc cra, 144 (csp) + csc cs0, 128 (csp) + cincoffset cs0, csp, 160 + cincoffset ca0, cs0, -36 + csetbounds ca2, ca0, 4 + cincoffset ca0, cs0, -60 + csetbounds ca0, ca0, 24 + csc ca0, -128 (cs0) + cincoffset ca1, cs0, -92 + csetbounds ca1, ca1, 32 + csc ca1, -144 (cs0) + mv a1, zero + csd a1, -104 (cs0) + csw a1, 0 (ca2) +{% endhighlight %} + +### capability monotonicity +at this point you may be thinking "okay, that's great, but if we can just set the bounds of a capability with an instruction then what's the point? surely I can just set global bounds on some random pointer and access whatever I want?" + +fundamental to the idea of capabilities is their _provenance_ and _monotonicity_. simply put, the first says we can only construct a capability using specific instructions, from an existing capability. we can't just create a capability from some random number. let's see what happens when we try to run our `ptrs_as_numbers` program on CheriBSD: + +{% highlight plaintext %} +(gdb) runStarting program: /root/ptrs_as_numbers-cheribsd +*x=1234 +Program received signal SIGPROT, CHERI protection violation.Capability tag fault caused by register ca1.0x0000000000101c66 in main () at ptrs_as_numbers.c:1414 printf("*x=%d\n", *x); +(gdb) p $ca1 +$1 = () 0x3fffdfff74 +{% endhighlight %} + +we can see we get a fault - the tag isn't set. any capability with a tag not set to 1 cannot be dereferenced - it is invalid. in fact, this capability has no capability metadata - when we copied it into our `unsigned long`, we just copied the 64-bit address. + +*monotonicity* is what stops us taking an existing capability, and creating a capability with more permissions and/or access than the original. it stipulates that when we create a capability from another capability (which we have to do - provenance), the permissions and bounds of the new capability must be equal to or less than the original. so our bounds can only get narrower as we create new capabilites from an existing capability. this means that capabilities trace back in a chain - they are all created from other capabilities, and narrowed as necessary. in this case, (simplified) when the kernel loads our program it will give us capabilities that are wide enough to do everything we need to do, and the compiler will try and make sure all the capabilities that we make and use from these are as tightly bound and unpermissive as possible. + +### CHERI-fying code +you'll notice we got a lot of these benefits "for free". we only had to recompile our code, and we got this extra security. of course, CHERI does require changes to programs. naturally, the compiler had to be changed a lot to implement this behaviour. it also especially requires changes to things like the C library and kernel in order to take advantage of the features fully. sufficiently large userspace programs do need changes too. one common issue is that a lot of existing C code assumes that `sizeof (*void) == sizeof(size_t)`. with CHERI, our pointers are now twice as big. however, `size_t` hasn't changed size, as the address space size hasn't changed - for example, if we index into an array with `size_t`, the index should still be the same size; the extra data in our `void *` capability is the metadata, not extra address data. any program that tries to convert from some `unsigned long` or `size_t` to a capability will fault - this violates provenance. so, sometimes code changes have to be made to ensure we are keeping the capability metadata around. + + +## epilogue +I appreciate this has been a fragmented and surface level introduction to CHERI. hopefully it has provided some education in some basic aims of CHERI regardless. potential benefits and uses for CHERI go much deeper than anything I've touched on here, so please, read more about everything - and get your hands dirty trying out messing about with qemu and CheriBSD! + +here are some links to check out: + +- [CHERI homepage @ CUCL](https://www.cl.cam.ac.uk/research/security/ctsrd/cheri/) +- [technical report: An Introduction to CHERI](https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-941.pdf) +- [technical report: CHERI C/C++ Programming Guide](https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-947.pdf) +- [technical report: CHERI ISAv8](https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-951.pdf) +- [Morello homepage @ Arm](https://www.arm.com/architecture/cpu/morello) +- [Morello Architecture Reference Manual @ Arm](https://developer.arm.com/documentation/ddi0606/latest) diff --git a/articles/morello/code/Makefile b/_posts/cheri/code/Makefile similarity index 100% rename from articles/morello/code/Makefile rename to _posts/cheri/code/Makefile diff --git a/articles/morello/code/membug b/_posts/cheri/code/membug similarity index 100% rename from articles/morello/code/membug rename to _posts/cheri/code/membug diff --git a/articles/morello/code/membug-cheri.asm b/_posts/cheri/code/membug-cheri.asm similarity index 100% rename from articles/morello/code/membug-cheri.asm rename to _posts/cheri/code/membug-cheri.asm diff --git a/articles/morello/code/membug-cheribsd b/_posts/cheri/code/membug-cheribsd similarity index 100% rename from articles/morello/code/membug-cheribsd rename to _posts/cheri/code/membug-cheribsd diff --git a/articles/morello/code/membug.c b/_posts/cheri/code/membug.c similarity index 100% rename from articles/morello/code/membug.c rename to _posts/cheri/code/membug.c diff --git a/articles/morello/code/ptrs_as_numbers b/_posts/cheri/code/ptrs_as_numbers similarity index 100% rename from articles/morello/code/ptrs_as_numbers rename to _posts/cheri/code/ptrs_as_numbers diff --git a/articles/morello/code/ptrs_as_numbers-cheribsd b/_posts/cheri/code/ptrs_as_numbers-cheribsd similarity index 100% rename from articles/morello/code/ptrs_as_numbers-cheribsd rename to _posts/cheri/code/ptrs_as_numbers-cheribsd diff --git a/articles/morello/code/ptrs_as_numbers.c b/_posts/cheri/code/ptrs_as_numbers.c similarity index 100% rename from articles/morello/code/ptrs_as_numbers.c rename to _posts/cheri/code/ptrs_as_numbers.c diff --git a/articles/morello/code/sizes b/_posts/cheri/code/sizes similarity index 100% rename from articles/morello/code/sizes rename to _posts/cheri/code/sizes diff --git a/articles/morello/code/sizes-cheribsd b/_posts/cheri/code/sizes-cheribsd similarity index 100% rename from articles/morello/code/sizes-cheribsd rename to _posts/cheri/code/sizes-cheribsd diff --git a/articles/morello/code/sizes.c b/_posts/cheri/code/sizes.c similarity index 100% rename from articles/morello/code/sizes.c rename to _posts/cheri/code/sizes.c diff --git a/_sass/main.scss b/_sass/main.scss new file mode 100644 index 0000000..511aade --- /dev/null +++ b/_sass/main.scss @@ -0,0 +1,143 @@ +$background-color: rgb(12, 17, 20); +$body-color: rgb(252, 252, 252); +$heading-color: rgb(255, 182, 193); +$link-color: rgb(252, 169, 184); +$inl-code-color: rgb(165, 214, 255); + +@font-face { + font-family: TeXGyreCursor; + src: url('../fonts/texgyrecursor-regular.woff') format('woff'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: TeXGyreCursor; + src: url('../fonts/texgyrecursor-bold.woff') format('woff'); + font-weight: bold; + font-style: normal; +} + +@font-face { + font-family: TeXGyreCursor; + src: url('../fonts/texgyrecursor-italic.woff') format('woff'); + font-weight: normal; + font-style: italic; +} + +@font-face { + font-family: TeXGyreCursor; + src: url('../fonts/texgyrecursor-bolditalic.woff') format('woff'); + font-weight: bold; + font-style: italic; +} + +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 400; + src: local(''), + url('../fonts/source-code-pro-v22-latin-ext_latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('../fonts/source-code-pro-v22-latin-ext_latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 700; + src: local(''), + url('../fonts/source-code-pro-v22-latin-ext_latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('../fonts/source-code-pro-v22-latin-ext_latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +@font-face { + font-family: 'Source Code Pro'; + font-style: italic; + font-weight: 400; + src: local(''), + url('../fonts/source-code-pro-v22-latin-ext_latin-italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('../fonts/source-code-pro-v22-latin-ext_latin-italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +@font-face { + font-family: 'Source Code Pro'; + font-style: italic; + font-weight: 700; + src: local(''), + url('../fonts/source-code-pro-v22-latin-ext_latin-700italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('../fonts/source-code-pro-v22-latin-ext_latin-700italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +body { + background-color: $background-color; + color: $body-color; + padding-left: 5vw; + padding-right: 5vw; + padding-top: 5vh; + font-family: 'Source Code Pro'; + font-size: 1.5rem; +} + +h1 { + color: $heading-color; + margin: 0; +} + +h2 { + margin: 0; + margin-top: 3rem; + margin-bottom: 0.5rem; +} + +a { + color: $link-color; + font-weight: bold; + text-decoration: none; +} + +.article { + p, li { + a { + font-weight: normal; + text-decoration: underline; + word-wrap: break-word; + } + } + + picture img, p img { + max-width: 100%; + display: block; + } + + code, pre { + font-family: 'Source Code Pro'; + margin: 0; + padding: 0; + } + + p code { + font-size: 1.5rem; + color: #a5d6ff; + } + + .header-link { + display: inline-block; + } +} + +table { + border-spacing: 0; +} + +h2 .header-link { + display: none; + + padding-left: 10px; + font-weight: normal; + font-size: 1.3rem; + + img { + height: 1.25rem; + margin-bottom: -4px; + } +} \ No newline at end of file diff --git a/_site/2022/11/14/sensor-watch.html b/_site/2022/11/14/sensor-watch.html new file mode 100644 index 0000000..f031a72 --- /dev/null +++ b/_site/2022/11/14/sensor-watch.html @@ -0,0 +1,308 @@ + + + + + + + + + + sensor watch - jack bond-preston + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

sensor watch

+ +

preamble[]

+

some time back I was browsing Crowd Supply when I came across the Sensor Watch project by Joey Castillo. I had wanted some kind of “hackable” watch for a while, and had looked at things like Watchy, but this project hit the sweet spot for me. I love my existing F91-W, and this project was a good combination of open source with community software support. one key feature that was important to me is battery life - the Sensor Watch battery life in an average usage scenario is so long that Joey’s is still going strong!

+ +

I was excited to pick one up and start messing around with it, but the first issue I came across was availability - the delivery date for Crowd Supply orders was summer 2023 (I think they ended upbeing delivered sooner than this, not sure). on top of this, shipping and import fees made it pretty prohibitively expensive. I’ve always found this to be an issue with Crowd Supply as someone based in the UK, even some things designed in the UK are very expensive from Crowd Supply as they are assembled in/shipped from the US. so I decided to build one myself! of course, this is more expensive than just buying it, but this was a learning experience and knowledge is power!

+ +

component acquisition[]

+

the first challenge was acquiring all the necessary parts to actually build one. I downloaded the PCB files and generated a BOM to figure out exactly what I needed to acquire. I’m sure in ordinary times this would be easy enough, but the current state of some electronics/silicon supply chains had other things to say. some parts are of course still easy to come across, e.g. 10pF 0402 caps and 10k 0603 resistors; most of the components of the Sensor Watch are this kind of commonplace part. what quickly became clear from some scouring of the internet was that my main problem was going to be two parts: the ATSAML22J18A-MUT(the processor driving the Sensor Watch), and the FH19C-9S-0.5SH(10) (the connector used to attach the extra sensor boards).

+ +

ATSAML22J18A-MUT

+

the former of these was a fairly well discussed shortage that had been ongoing for a while. it was +the driving force of the Sensor Watch Crowd Supply delay. I spent quite a lot of time searching around the internet, looking at various sites on the English-speaking and Chinese-speaking web. sadly this part was clearly in very short supply, and prices could get pretty insane from vendors that did have some stock. I received quotes for unit prices that include the following (USD/GBP): $79.35, $6.56, $13.61, $6.83 (MOQ 4000), £6.45. I guess some people are desperate enough to pay $79.35 :(. I spent so long looking for them that they ended up randomly coming back in stock on MicrochipDirect. as of the time of writing this article, they are again out of stock. the unit price I bought them for was £3.92, shipping and handling was ~£12.

+ +

FH19C-9S-0.5SH(10)

+

this part was out of stock everywhere I initially looked (the usual contenders for parts). I searched around in a similar manner as the ATSAML22J18A-MUT, and found some similarly wild pricing. I ended up purchasing a small quantity at a unit price of £0.44 from a website called +dacikeys. yes, the site is actually called this. yes, the unit price is cheaper than digikey and mouser. yes, I actually received all of my order, consisting of working parts. I was definitely shocked that this happened, but sometimes bravery pays off I guess. I still can’t endorse this shop.

+ +

PCB and stencil

+

for the PCB I opted to go with JLCPCB. I simply uploaded the relevant gerbers, and adjusted the necessary settings. notably, the thickness should be 0.6mm - this does narrow the choice of manufacturer (for example, OSH Park doesn’t go this thin). I haven’t yet ordered any sensor board PCBs, but PCBWay seems to be the option there. The PCB turned out great, although the silkscreen is a little hard to read at this size due to lack of sharpness:

+a closeup of a sensor watch PCB + +

assembly[]

+

I decided to assemble myself. partially because the logistics of paying for assembly when I had to source parts from many different providers seemed like a headache, partially because I thought it would be a fun challenge and learning experience!

+ +

a few things were necessary to solder the components to this PCB. I’m sure someone talented could hand solder this with an iron, but I can name a lot of things I’d rather do than try to do that +(especially the QFN SAML) - and that list includes unpleasant things. I opted to go with +hotplate soldering, which is a cheaper way to access the ease of reflow soldering. for a PCB like the Sensor Watch, where almost all the components are on one side, it’s ideal. the hotplate I have is the ever-popular +MHP30, which I run IronOS on. I highly recommend it, it’s great! my soldering iron is the iconic +Pinecil (not the fancy new V2 though :[) which also runs IronOS. nice!

+ +

process

+

the assembly process is as follows:

+
    +
  • apply solder paste to the PCB with the stencil. make sure the stencil is really flush and justkind of squeegee it on with a plastic card. I used tape to hold it in place. then carefully removed the stencil, avoiding smudging the paste in doing so.
  • +
  • place components on the PCB. this was by far the most painful part of the whole process. a steady hand is not something I was blessed with, and some of these parts are really small. I used a microscope from Amazon for this, the ample manouverable lighting was a big help. a lot of time and patience is required, but it’s very first time doable with no prior experience! simply go through the parts one by one, or by area of the board - whatever you prefer. then pick up the respective part with some fine tweezers, and slowly put in place on the solder paste. thankfully, the paste will lightly stick the component in place once you’ve done this (it is not knock-proof though!).
  • +
  • carefully (really!) place the PCB onto the hotplate and heat up. keep on until everything seems to be melted, and the components have hopefully been pulled into place. that’s the top side done! let it cool down, then move on to the bottom.
  • +
  • time for some hand soldering. the button is pretty small, and very fiddly to do. I found you don’t need too much precision, but you have to be really careful with your iron as the plastic button will melt if you touch it. once that’s in place, it’s just a matter of +removing the buzzer connector from your old PCB and soldering it onto the back of the Sensor Watch PCB. this will feel blissfully easy after the button! you also have to place the battery clip, but no soldering needed here :).
  • +
+ +

one area I found particularly difficult was the area with the oscillator crystal and the two 0402 capacitors, C7 and C8. things are a bit cramped here, so extra care was needed:

+a closeup of a sensor watch PCB, with an area circled. the area contains some small, and closely grouped pads + +

software[]

+

at this point the watch was assembled with all components in place. did it work? at this stage, no idea. hopefully yes, and I could progress to the more familiar world of embedded software.

+ +

bootloader

+

the next necessary step is to flash the bootloader, so that we can put the firmware in place. unfortunately this requires a little more real-world action. we need to access the SWD points on the board to write the bootloader. ideally you could do this with some kind of +pogo pin jig - and if you were doing any number exceeding about 5 I’m sure this would be worth the time. however, I decided to just solder some jump wires (stripped on one end, solid tip female on the other) to the points on the board. they’re all close, but it’s easy enough to do (albeit ugly). then I connected these to my +Adafruit Trinket M0 (PyRuler would also work).the pin mapping is as follows: SWD=0, SWC=1, RST=3, V+=3V, GND=GND.

+ +

I used the +flasher from the sensor watch repo to flash the bootloader. note that you could build the bootloader yourself first and put the generated binary into bootloader.h - the source is located +here. personally, I just used the prebuilt version from the repo. I had to change part of the Adafruit DAP library and add the SAM L22 DID to get this to work, +I provided the diff of this change in a Sensor Watch GitHub issue (I just now am remembering I promised to upstream this, oops!). mercifully, I got the red blinky LED, and all was good! I unsoldered the wires from the board, and tried to clean up most of the solder blob to keep the board fairly flat.

+ +

movement

+

now the bootloader is in place, the main firmware can be installed! +the community firmware, Movementis great, so this is what I installed. there are a bunch of different useful faces available, and more functionality is always being added. +flashing firmware was easy: I plugged the PCB into the end of a USB Micro B cable (plugged on the other end into my computer) and double tapped the reset button (I find this has to be done quite quickly, using my fingernail was the trick to doing this reliably on such a small button). done successfully, the LED on the board pulses and a new drive labelled “WATCHBOOT” appears on the computer. now a built UF2 firmware file can just be dragged onto the device to flash, thanks to the bootloader flashed earlier. for the initial test, I just used a +prebuilt image to check everything was working. I flashed this, and the LED pulsed and turned off, signalling success.

+ +

from here I just assembled the watch with the Sensor Watch PCB, and it worked! I verified LED and buzzer function by playing around with various functionality. success!

+ +

developing on movement[]

+

one face I found particularly cool was the TOTP face. I use TOTP +2FA on various accounts, so having access to the codes on my wrist at all times was really appealing. at the time, the TOTP face only supported one key - so I decided to improve it.

+ +

thankfully, Sensor Watch has an emulator for development. without this, development would be pretty tiresome with the flashing and reassembling of the watch getting tiring if you needed to iterate on some code and test it on the watch. the emulator runs inside the browser and uses +Emscripten. +some minimal instructions on how to build this is available on the README. this allowed me to extend the TOTP face easily and allow for multiple keys. +my PR was merged, and the functionality is now available for anyone to use. the keys are added at compile time, so they are baked into the firmware on flashing. for my purposes this is fine, as I never really change them. however, with the recent addition of a +LittleFS filesystem, the community have added a version of the face which stores the keys on the filesystem. awesome!

+ +

some more details on using Sensor Watch for TOTP is available +on this blog post +(HN discussion, if you dare). it’s even running my code :)!

+ +

epilogue[]

+

some summary thoughts:

+
    +
  • shoutout to Joey Castillo. for creating the Sensor Watch as a beautifully open source project (the fact I could independently make my own is what it’s all about!). for being +so helpful and kind when I asked for help. for having such a positive attitude towards those in the community who are using Sensor Watch to learn about all kinds of things (seriously, check out the +Oddly Specific Objects Discord to see how much this guy is giving to the community).
  • +
  • sometimes it’s worth just trying things that are difficult. this is my first time successfully doing and small-scale soldering of this kind, and it worked out great with some patience. having the motivation from making something I thought was really cool was an important factor here I think.
  • +
  • if you have a Sensor Watch (or are planning to!) please go ahead and contribute to movement if you have a cool idea. I’m sure some reviews would be helpful to spot any issues on existing PRs before a maintainer gets to them to save some time.
  • +
  • the one issue I’ve had with using my Sensor Watch for TOTP is clock accuracy. the clock drifts over time, so I have to set the time once or twice a week to keep it nice and accurate for the TOTP functionality to be nice to use. but a community member is working on this, and it’s going to get a lot better. check out the Discord channel to see some seriously cool engineering going into this calibration effort.
  • +
+ +

a shot of a yellow and black assembled sensor watch, lying horizontally on a surface

+ +

a shot of a yellow and black assembled sensor watch, lying vertically on a surface

+ +

a shot of a yellow and black assembled sensor watch, on the author's wrist

+ + + +
+ +

email me to have a conversation

+
+
+ \ No newline at end of file diff --git a/_site/2022/11/19/cheri.html b/_site/2022/11/19/cheri.html new file mode 100644 index 0000000..db1d01b --- /dev/null +++ b/_site/2022/11/19/cheri.html @@ -0,0 +1,331 @@ + + + + + + + + + + CHERI - jack bond-preston + + + + + +
+

CHERI

+ +

preamble[]

+

CHERI is an acronym for Capability Hardware Enhanced RISC Instructions. it is a security-focussed project aimed at improving memory protection at the hardware level. the project is complex and it has many potential applications.

+ +

in this article I will go into some basics to give an understanding behind some changes that CHERI makes to how programs execute and are written. this will be focussed almost entirely in C, as this is where my experience lies - it is also where some of the effects of CHERI are most easily felt.this article is going to be a very simplistic introduction to CHERI, and I’m going to attempt to explain the basics behind everything I cover. a basic understanding of C will be beneficial.

+ +

note: the Morello platform is an evaluation board produced by Arm to provide a physical implementation of CHERI extending the Arm AArch64 ISA. I previously worked on this platform at Arm, porting the musl C library to Morello. implementations for CHERI that are worth looking into from a more open perspective are the MIPS (chapter 4) and RISC-V (chapter 5) ones. Morello is the only implementation that exists in a true hard core format, afaik - but this is obviously hard to obtain so you’ll just be playing around with emulators/models anyway.

+ +

memory safety bugs[]

+

to first understand how CHERI tries to fix some simple issues, let’s first look at some simplified examples of issues that arise when we aren’t using a CHERI-based architecture.

+ +

a simple memory safety bug

+

let’s take a look at this C code:

+ +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+
#include <stdio.h>
+
+int main() {
+    char my_perfect_string[] = "what a beautiful string"; // so beautiful, I sure hope no-one touches it
+    char user_name[32];
+
+    printf("enter your name: ");
+    fgets(user_name, 1000, stdin); // get user's name from stdin
+    printf("hello %s", user_name);
+    printf("my_perfect_string: %s\n", my_perfect_string);
+
+    return 0;
+}
+
+ +

now let’s try using our new program:

+ +
$ ./membug
+enter your name: jack
+hello jack
+my_perfect_string: what a beautiful string
+ +

works on my machine boss! code review +1, and merged… until our good friend Hubert Blaine Wolfeschlegelsteinhausenbergerdorff Sr. comes along. he emails me a strangeerror he’s seen:

+ +
$ ./membug
+enter your name: Hubert Blaine Wolfeschlegelsteinhausenbergerdorff Sr.
+hello Hubert Blaine Wolfeschlegelsteinhausenbergerdorff Sr.
+my_perfect_string: hausenbergerdorff Sr.
+ +

that’s not supposed to happen! his name has spilled over into our my_perfect_string[] array! turns out our issue is that when we use fgets(), we’ve set the second parameter, size, to 1000 - but our user_name[32] array c1593an only fit 32 characters (and the last of these should be a null terminator, so 31 usable characters).

+ +

fgets fills up user_name, but it hasn’t finished with the name yet! it doesn’t care (or know) that user_name is full, it’s just going to keep going until it finishes our user input, or reads 999 characters from standard input. and thus it keeps mindlessly writing, overwriting the memory we’ve used to store our precious perfect string (which happens to be immediately after user_name). let’s take a look at the stack in GDB to see why this happens:

+ +
(gdb) b memdebug.c:7 
+(gdb) run 
+Breakpoint 1, main () at membug.c:7
+7           printf("enter your name: "); 
+(gdb) n
+8           fgets(user_name, 1000, stdin); // get user's name from stdin
+(gdb) n
+9           printf("hello %s", user_name);
+(gdb) x/56bc $sp
+0x7fffffffdbf0: 106 'j' 97 'a'  99 'c'  107 'k' 10 '\n' 0 '\000'        0 '\000'        0 '\000'
+0x7fffffffdbf8: 77 'M'  82 'R'  85 'U'  85 'U'  85 'U'  85 'U'  0 '\000'        0 '\000'
+0x7fffffffdc00: -24 '\350'      -78 '\262'      -5 '\373'       -9 '\367'       -1 '\377'       127 '\177'      0 '\000'        0 '\000'
+0x7fffffffdc08: 0 '\000'        82 'R'  85 'U'  85 'U'  85 'U'  85 'U'  0 '\000'        0 '\000'
+0x7fffffffdc10: 119 'w' 104 'h' 97 'a'  116 't' 32 ' '  97 'a'  32 ' '  98 'b'
+0x7fffffffdc18: 101 'e' 97 'a'  117 'u' 116 't' 105 'i' 102 'f' 117 'u' 108 'l'
+0x7fffffffdc20: 32 ' '  115 's' 116 't' 114 'r' 105 'i' 110 'n' 103 'g' 0 '\000'
+ +

we can see our two character arrays are right next to each other on the stack (user_name contains some gibberish as it is not zero-initialised).

+ +

note: this code was compiled with -fno-stack-protector to reproduce this behaviour. compilers have certain techniques like this which can help protect against such attacks, but there are often ways around these by using less primitive attacks.

+ +

okay, it’s a pretty easy fix, we just need to change the fgets(char *s, int size, FILE *stream) parameter size to 32.

+ +

note: you may initially think “why not 31? don’t we need to save a character for the null byte at the end?”. thankfully, fgets does this for us. excerpt from man fgets:

+ +
+

“fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s […] A terminating null byte (‘\0’) is stored after the last character in the buffer”.

+
+ +

this is a good question to be asking though, being careful is key when it comes to these kinds of things.

+ +

why hardware?

+

okay, so that’s an easy fix. why are we talking about doing anything in hardware here? just write the code correctly! the issue is code gets very complex, and this is a very simplistic situation. some memory safety bugs can be incredibly complicated and go unnoticed for decades. the C language especially gives the programmer many, many opportunities to make mistakes - and it only takes one to be a problem. a lot of the software we are using these days is based on stacks upon stacks of software written in different languages, and there are going to be bugs in there. CHERI should give us some protection “for free” (it’s not this simple, in actuality).

+ +

some languages (e.g. Rust) are going to offer you strong memory safety guarantees at compile-time, but that’s not the topic of this article. the differences between doing this kind of protection in software or hardware (or both) is more complex than the scope of this article. in addition, CHERI’s benefits are more wide in breadth than just protecting against this kind of issue.

+ +

pointers recap[]

+

let’s quickly recap a basic idea of what a pointer is. we’re going to ignore things like virtual memory for brevity. we can think of a pointer in a normal 64-bit architecture (e.g. AArch64) simply as a 64-bit unsigned value that holds the memory address of something we care about. this is a simplification (as are most things), but it can help us reason about the general idea:

+ +
int val = 1593;
+int *x = &val; // x points to val
+ +int *x0x0000010000000004addressmem[0x0000010000000004]mem[0x0000010000000000]mem[0x0000010000000008]1593memory (as ints) + +

and on these normal architectures, this pointer generally is just a number. we can do weird things with it, treating it as a number…

+ +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+
#include <stdio.h>
+
+int main() {
+    int magic = 9999;
+    (void)magic;
+    int arr[] = { 1234, 5678 };
+
+    int *x = &(arr[0]); // x is a pointer to first element of arr
+    printf("*x=%d\n", *x);
+
+    unsigned long x_addr = (size_t) x; // we're going to assume size_t = unsigned long here
+    x_addr += 4; // sizeof(int) == 4
+    x = (int *) x_addr;
+    printf("*x=%d\n", *x);
+
+    x_addr += 4;
+    x = (int *) x_addr;
+    printf("*x=%d\n", *x);
+
+    return 0;
+}
+
+ +

…and this code will often still work:

+ +
$ ./ptrs_as_numbers
+*x=1234
+*x=5678
+*x=9999
+ +

yikes! now, when you start messing with pointers like this, you’re bound to run into a bunch of undefined behaviour. but C programmers write undefined behaviour all the time, and my computer executes this program fine without complaining at all. doesn’t it feel a bit weird that we can take a pointer to arr[0] and modify it to load secret? they’re not even part of the same array…

+ +

introducting capabilities[]

+

CHERI introduces capabilities, which can be thought of as an extension to pointers. they still store an address of something we care about, but they have extra information too! in a 64-bit system, a pointer would typically be a 64-bit value (as dicussed previously). the corresponding capability in a CHERI platform is 128 bits (or 129 bits if you look at it a certain way, more about that later…).

+ +

as you might have guessed, this “extra information” takes up 64 bits of the capability. bits are assigned to three key pieces of metadata: bounds, permissions, and object type. there is also an additional 1-bit tag which is stored out-of-band: it is not a 129-bit value - instead each 128-bit capability can be thought of as being associated with a 1-bit validity tag. the architecture manages this. the diagram below is provided as a rough overview of this. note that it is not to scale.

+ +int *x (capability)0x0000010000000004addressboundsobject typepermissionstag (out-of-band) + +

I am mostly going to focus on bounds in this article, as it is not too difficult to grasp, and the impact is fairly easy to demonstrate for some simple examples. the bounds represent an upper and lower bound on the memory region (address space) that this capability is allowed to access. if we try to use the capability to access some address outside of this range, the hardware will throw a fault - it simply won’t let us do this!

+ +

note: it is important to note that I am going to oversimplify the way the bounds are stored in this article. this especially includes the diagram above. in reality, there is a complex compression method, necessitated by the range and sizes required by bounds. this depends on the address value, alignment, etc. for now, we shouldn’t need to think about this much, just know it will be managed for us. the key take-away from this is that bounds can’t always be 100% precise for all addresses and ranges.

+ +

can you imagine how we can use bounds to prevent our previous memory safety bug from occurring? the key is that we can set the bounds on the capability pointing to user_name which we pass to fgets, such that the capability may only access the contents of the array. this means that when fgets tries to write past the end of the user_name array, the processor will throw a capability fault, and execution of our program will cease.

+ +

the idea behind CHERI is that we don’t have to set up these bounds ourselves. this is something the compiler can generate code for. the compiler knows that the user_name array has a length of 32, and can set the bounds accordingly on capabilities created that point to it. let’s try it…

+ +

playing with CHERI RISC-V[]

+

unless you’re lucky enough to have access to a physical Morello board, there is the issue of actually using a CHERI implementation. for this article I will be making use of the QEMU emulator to emulate a RISC-V CHERI environment. running CheriBSD on this emulator will allow us to have a nice FreeBSD-based capability-enabled environment to play around with. I’ll use cheribuild to easily get set up (the cheribuild.py step will take a very long time the first time):

+ +
$ sudo apt install autoconf automake libtool pkg-config clang bison cmake \
+ninja-build samba flex texinfo time libglib2.0-dev libpixman-1-dev \
+libarchive-dev libarchive-tools libbz2-dev libattr1-dev libcap-ng-dev
+$ git clone git@github.com:CTSRD-CHERI/cheribuild
+$ cd cheribuild
+$ ./cheribuild.py --include-dependencies --run/ssh-forwarding-port 2222 run-riscv64-purecap 
+CheriBSD/riscv (cheribsd-riscv64-purecap) (ttyu0)
+
+login: root
+root@cheribsd-riscv64-purecap:~ #
+ +

now we have our shell inside our CheriBSD emulated platform, we can start to try things out. let’s compile our membug program again, this time with the toolchain targetting CheriBSD RISC-V - this will have been built as part of the dependencies already. once it’s built, we can scp it over to the CheriBSD filesystem, as we set up the SSH forwarding port to +1111.

+ +
# on a separate terminal on your host machine
+$ ~/cheri/output/sdk/utils/cheribsd-riscv64-purecap-clang membug.c -Wall -g -fno-stack-protector -o membug-cheribsd
+$ scp -P 2222 ./membug-cheribsd root@localhost:~/
+ +

and now we can see what happens when we explore our bug with CHERI:

+ +
$./membug-cheribsd
+enter your name: jack
+hello jack
+my_perfect_string: what a beautiful string
+
+$ ./membug-cheribsd
+enter your name: Hubert Blaine Wolfeschlegelsteinhausenbergerdorff Sr.
+In-address space security exception (core dumped)
+ +

it’s working! we are getting a capability fault as we exceed the bounds of the +user_name capability bounds. we can use gdb to verify this is caused by the bounds fault:

+ +
1
+2
+3
+4
+5
+6
+7
+8
+9
+
(gdb) run
+Starting program: /root/membug-cheribsd 
+enter your name: Hubert Blaine Wolfeschlegelsteinhausenbergerdorff Sr.
+
+Program received signal SIGPROT, CHERI protection violation.
+Capability bounds fault caused by register ca6.
+0x0000000040314ce8 in memcpy (dst0=0x3fffdfff44, src0=<optimized out>, length=54) at /home/jack/cheri/cheribsd/lib/libc/string/bcopy.c:143
+(gdb) p $ca6
+$1 = () 0x3fffdfff78 [rwRW,0x3fffdfff44-0x3fffdfff64]
+
+ +

as we can see, the bounds for our user_name capability (which is stored in capability register ca6) are 0x3fffdfff44-0x3fffdfff64, but the address is 0x3fffdfff78. this is out of the bounds allowed by the capability, so the architecture throws a fault. if we look at the assembly generated by the compiler, we can see it set our capability bounds to a size of 32 to enforce this behaviour:

+ +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+
0000000000001ce8 <main>:
+; int main() {
+    cincoffset	csp,    csp,        -160
+    csc	        cra,    144         (csp)
+    csc	        cs0,    128         (csp)
+    cincoffset  cs0,    csp,        160
+    cincoffset	ca0,    cs0,        -36
+    csetbounds	ca2,    ca0,        4
+    cincoffset	ca0,    cs0,        -60
+    csetbounds	ca0,    ca0,        24
+    csc	        ca0,    -128        (cs0)
+    cincoffset	ca1,    cs0,        -92
+    csetbounds	ca1,    ca1,        32
+    csc	        ca1,    -144        (cs0)
+    mv	        a1,     zero
+    csd	        a1,     -104        (cs0)
+    csw	        a1,     0           (ca2)
+
+ +

capability monotonicity

+

at this point you may be thinking “okay, that’s great, but if we can just set the bounds of a capability with an instruction then what’s the point? surely I can just set global bounds on some random pointer and access whatever I want?”

+ +

fundamental to the idea of capabilities is their provenance and monotonicity. simply put, the first says we can only construct a capability using specific instructions, from an existing capability. we can’t just create a capability from some random number. let’s see what happens when we try to run our ptrs_as_numbers program on CheriBSD:

+ +
(gdb) runStarting program: /root/ptrs_as_numbers-cheribsd 
+*x=1234
+Program received signal SIGPROT, CHERI protection violation.Capability tag fault caused by register ca1.0x0000000000101c66 in main () at ptrs_as_numbers.c:1414          printf("*x=%d\n", *x);
+(gdb) p $ca1
+$1 = () 0x3fffdfff74
+ +

we can see we get a fault - the tag isn’t set. any capability with a tag not set to 1 cannot be dereferenced - it is invalid. in fact, this capability has no capability metadata - when we copied it into our unsigned long, we just copied the 64-bit address.

+ +

monotonicity is what stops us taking an existing capability, and creating a capability with more permissions and/or access than the original. it stipulates that when we create a capability from another capability (which we have to do - provenance), the permissions and bounds of the new capability must be equal to or less than the original. so our bounds can only get narrower as we create new capabilites from an existing capability. this means that capabilities trace back in a chain - they are all created from other capabilities, and narrowed as necessary. in this case, (simplified) when the kernel loads our program it will give us capabilities that are wide enough to do everything we need to do, and the compiler will try and make sure all the capabilities that we make and use from these are as tightly bound and unpermissive as possible.

+ +

CHERI-fying code

+

you’ll notice we got a lot of these benefits “for free”. we only had to recompile our code, and we got this extra security. of course, CHERI does require changes to programs. naturally, the compiler had to be changed a lot to implement this behaviour. it also especially requires changes to things like the C library and kernel in order to take advantage of the features fully. sufficiently large userspace programs do need changes too. one common issue is that a lot of existing C code assumes that sizeof (*void) == sizeof(size_t). with CHERI, our pointers are now twice as big. however, size_t hasn’t changed size, as the address space size hasn’t changed - for example, if we index into an array with size_t, the index should still be the same size; the extra data in our void * capability is the metadata, not extra address data. any program that tries to convert from some unsigned long or size_t to a capability will fault - this violates provenance. so, sometimes code changes have to be made to ensure we are keeping the capability metadata around.

+ +

epilogue[]

+

I appreciate this has been a fragmented and surface level introduction to CHERI. hopefully it has provided some education in some basic aims of CHERI regardless. potential benefits and uses for CHERI go much deeper than anything I’ve touched on here, so please, read more about everything - and get your hands dirty trying out messing about with qemu and CheriBSD!

+ +

here are some links to check out:

+ + + + +
+ +

email me to have a conversation

+
+ + + \ No newline at end of file diff --git a/_site/CNAME b/_site/CNAME new file mode 100644 index 0000000..27ccf4f --- /dev/null +++ b/_site/CNAME @@ -0,0 +1 @@ +jackbondpreston.me \ No newline at end of file diff --git a/_site/README.md b/_site/README.md new file mode 100644 index 0000000..5047eb6 --- /dev/null +++ b/_site/README.md @@ -0,0 +1 @@ +# website \ No newline at end of file diff --git a/_site/assets/css/main.css b/_site/assets/css/main.css new file mode 100644 index 0000000..aa2ec23 --- /dev/null +++ b/_site/assets/css/main.css @@ -0,0 +1,41 @@ +@font-face { font-family: TeXGyreCursor; src: url("../fonts/texgyrecursor-regular.woff") format("woff"); font-weight: normal; font-style: normal; } + +@font-face { font-family: TeXGyreCursor; src: url("../fonts/texgyrecursor-bold.woff") format("woff"); font-weight: bold; font-style: normal; } + +@font-face { font-family: TeXGyreCursor; src: url("../fonts/texgyrecursor-italic.woff") format("woff"); font-weight: normal; font-style: italic; } + +@font-face { font-family: TeXGyreCursor; src: url("../fonts/texgyrecursor-bolditalic.woff") format("woff"); font-weight: bold; font-style: italic; } + +@font-face { font-family: 'Source Code Pro'; font-style: normal; font-weight: 400; src: local(""), url("../fonts/source-code-pro-v22-latin-ext_latin-regular.woff2") format("woff2"), url("../fonts/source-code-pro-v22-latin-ext_latin-regular.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } + +@font-face { font-family: 'Source Code Pro'; font-style: normal; font-weight: 700; src: local(""), url("../fonts/source-code-pro-v22-latin-ext_latin-700.woff2") format("woff2"), url("../fonts/source-code-pro-v22-latin-ext_latin-700.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } + +@font-face { font-family: 'Source Code Pro'; font-style: italic; font-weight: 400; src: local(""), url("../fonts/source-code-pro-v22-latin-ext_latin-italic.woff2") format("woff2"), url("../fonts/source-code-pro-v22-latin-ext_latin-italic.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } + +@font-face { font-family: 'Source Code Pro'; font-style: italic; font-weight: 700; src: local(""), url("../fonts/source-code-pro-v22-latin-ext_latin-700italic.woff2") format("woff2"), url("../fonts/source-code-pro-v22-latin-ext_latin-700italic.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } + +body { background-color: #0c1114; color: #fcfcfc; padding-left: 5vw; padding-right: 5vw; padding-top: 5vh; font-family: 'Source Code Pro'; font-size: 1.5rem; } + +h1 { color: lightpink; margin: 0; } + +h2 { margin: 0; margin-top: 3rem; margin-bottom: 0.5rem; } + +a { color: #fca9b8; font-weight: bold; text-decoration: none; } + +.article p a, .article li a { font-weight: normal; text-decoration: underline; word-wrap: break-word; } + +.article picture img, .article p img { max-width: 100%; display: block; } + +.article code, .article pre { font-family: 'Source Code Pro'; margin: 0; padding: 0; } + +.article p code { font-size: 1.5rem; color: #a5d6ff; } + +.article .header-link { display: inline-block; } + +table { border-spacing: 0; } + +h2 .header-link { display: none; padding-left: 10px; font-weight: normal; font-size: 1.3rem; } + +h2 .header-link img { height: 1.25rem; margin-bottom: -4px; } + +/*# sourceMappingURL=main.css.map */ \ No newline at end of file diff --git a/_site/assets/css/main.css.map b/_site/assets/css/main.css.map new file mode 100644 index 0000000..5b5f945 --- /dev/null +++ b/_site/assets/css/main.css.map @@ -0,0 +1,14 @@ +{ + "version": 3, + "file": "main.css", + "sources": [ + "main.scss", + "_sass/main.scss" + ], + "sourcesContent": [ + "@import \"main\";\n", + "$background-color: rgb(12, 17, 20);\n$body-color: rgb(252, 252, 252);\n$heading-color: rgb(255, 182, 193);\n$link-color: rgb(252, 169, 184);\n$inl-code-color: rgb(165, 214, 255);\n\n@font-face {\n font-family: TeXGyreCursor;\n src: url('../fonts/texgyrecursor-regular.woff') format('woff');\n font-weight: normal;\n font-style: normal;\n}\n\n@font-face {\n font-family: TeXGyreCursor;\n src: url('../fonts/texgyrecursor-bold.woff') format('woff');\n font-weight: bold;\n font-style: normal;\n}\n\n@font-face {\n font-family: TeXGyreCursor;\n src: url('../fonts/texgyrecursor-italic.woff') format('woff');\n font-weight: normal;\n font-style: italic;\n}\n\n@font-face {\n font-family: TeXGyreCursor;\n src: url('../fonts/texgyrecursor-bolditalic.woff') format('woff');\n font-weight: bold;\n font-style: italic;\n}\n\n@font-face {\n font-family: 'Source Code Pro';\n font-style: normal;\n font-weight: 400;\n src: local(''),\n url('../fonts/source-code-pro-v22-latin-ext_latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */\n url('../fonts/source-code-pro-v22-latin-ext_latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */\n}\n\n@font-face {\n font-family: 'Source Code Pro';\n font-style: normal;\n font-weight: 700;\n src: local(''),\n url('../fonts/source-code-pro-v22-latin-ext_latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */\n url('../fonts/source-code-pro-v22-latin-ext_latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */\n}\n\n@font-face {\n font-family: 'Source Code Pro';\n font-style: italic;\n font-weight: 400;\n src: local(''),\n url('../fonts/source-code-pro-v22-latin-ext_latin-italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */\n url('../fonts/source-code-pro-v22-latin-ext_latin-italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */\n}\n\n@font-face {\n font-family: 'Source Code Pro';\n font-style: italic;\n font-weight: 700;\n src: local(''),\n url('../fonts/source-code-pro-v22-latin-ext_latin-700italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */\n url('../fonts/source-code-pro-v22-latin-ext_latin-700italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */\n}\n\nbody {\n background-color: $background-color;\n color: $body-color;\n padding-left: 5vw;\n padding-right: 5vw;\n padding-top: 5vh;\n font-family: 'Source Code Pro';\n font-size: 1.5rem;\n}\n\nh1 {\n color: $heading-color;\n margin: 0;\n}\n\nh2 {\n margin: 0;\n margin-top: 3rem;\n margin-bottom: 0.5rem;\n}\n\na {\n color: $link-color;\n font-weight: bold;\n text-decoration: none;\n}\n\n.article {\n p, li {\n a {\n font-weight: normal;\n text-decoration: underline;\n word-wrap: break-word;\n }\n }\n\n picture img, p img {\n max-width: 100%;\n display: block;\n }\n\n code, pre {\n font-family: 'Source Code Pro';\n margin: 0;\n padding: 0;\n }\n \n p code {\n font-size: 1.5rem;\n color: #a5d6ff;\n }\n\n .header-link {\n display: inline-block;\n }\n}\n\ntable {\n border-spacing: 0;\n}\n\nh2 .header-link {\n display: none;\n\n padding-left: 10px;\n font-weight: normal;\n font-size: 1.3rem;\n\n img {\n height: 1.25rem;\n margin-bottom: -4px;\n }\n}" + ], + "names": [], + "mappings": "ACMA,UAAU,GACR,WAAW,EAAE,aAAa,EAC1B,GAAG,EAAE,0CAA0C,CAAC,cAAc,EAC9D,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM;;AAGpB,UAAU,GACR,WAAW,EAAE,aAAa,EAC1B,GAAG,EAAE,uCAAuC,CAAC,cAAc,EAC3D,WAAW,EAAE,IAAI,EACjB,UAAU,EAAE,MAAM;;AAGpB,UAAU,GACR,WAAW,EAAE,aAAa,EAC1B,GAAG,EAAE,yCAAyC,CAAC,cAAc,EAC7D,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM;;AAGpB,UAAU,GACR,WAAW,EAAE,aAAa,EAC1B,GAAG,EAAE,6CAA6C,CAAC,cAAc,EACjE,WAAW,EAAE,IAAI,EACjB,UAAU,EAAE,MAAM;;AAGpB,UAAU,GACR,WAAW,EAAE,iBAAiB,EAC9B,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,GAAG,EAChB,GAAG,EAAE,SAAS,EACT,iEAAiE,CAAC,eAAe,EACjF,gEAAgE,CAAC,cAAc,EAAE,iDAAiD;;AAGzI,UAAU,GACR,WAAW,EAAE,iBAAiB,EAC9B,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,GAAG,EAChB,GAAG,EAAE,SAAS,EACT,6DAA6D,CAAC,eAAe,EAC7E,4DAA4D,CAAC,cAAc,EAAE,iDAAiD;;AAGrI,UAAU,GACR,WAAW,EAAE,iBAAiB,EAC9B,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,GAAG,EAChB,GAAG,EAAE,SAAS,EACT,gEAAgE,CAAC,eAAe,EAChF,+DAA+D,CAAC,cAAc,EAAE,iDAAiD;;AAGxI,UAAU,GACR,WAAW,EAAE,iBAAiB,EAC9B,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,GAAG,EAChB,GAAG,EAAE,SAAS,EACT,mEAAmE,CAAC,eAAe,EACnF,kEAAkE,CAAC,cAAc,EAAE,iDAAiD;;AAG3I,AAAA,IAAI,CAAC,EACH,gBAAgB,EAvEC,OAAe,EAwEhC,KAAK,EAvEM,OAAkB,EAwE7B,YAAY,EAAE,GAAG,EACjB,aAAa,EAAE,GAAG,EAClB,WAAW,EAAE,GAAG,EAChB,WAAW,EAAE,iBAAiB,EAC9B,SAAS,EAAE,MAAM,GAClB;;AAED,AAAA,EAAE,CAAC,EACD,KAAK,EA/ES,SAAkB,EAgFhC,MAAM,EAAE,CAAC,GACV;;AAED,AAAA,EAAE,CAAC,EACD,MAAM,EAAE,CAAC,EACT,UAAU,EAAE,IAAI,EAChB,aAAa,EAAE,MAAM,GACtB;;AAED,AAAA,CAAC,CAAC,EACA,KAAK,EAzFM,OAAkB,EA0F7B,WAAW,EAAE,IAAI,EACjB,eAAe,EAAE,IAAI,GACtB;;AAED,AAEI,QAFI,CACN,CAAC,CACC,CAAC,EAFL,QAAQ,CACH,EAAE,CACH,CAAC,CAAC,EACA,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,SAAS,EAC1B,SAAS,EAAE,UAAU,GACtB;;AANL,AASE,QATM,CASN,OAAO,CAAC,GAAG,EATb,QAAQ,CASO,CAAC,CAAC,GAAG,CAAC,EACjB,SAAS,EAAE,IAAI,EACf,OAAO,EAAE,KAAK,GACf;;AAZH,AAcE,QAdM,CAcN,IAAI,EAdN,QAAQ,CAcA,GAAG,CAAC,EACR,WAAW,EAAE,iBAAiB,EAC9B,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,CAAC,GACX;;AAlBH,AAoBE,QApBM,CAoBN,CAAC,CAAC,IAAI,CAAC,EACL,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,GACf;;AAvBH,AAyBE,QAzBM,CAyBN,YAAY,CAAC,EACX,OAAO,EAAE,YAAY,GACtB;;AAGH,AAAA,KAAK,CAAC,EACJ,cAAc,EAAE,CAAC,GAClB;;AAED,AAAA,EAAE,CAAC,YAAY,CAAC,EACd,OAAO,EAAE,IAAI,EAEb,YAAY,EAAE,IAAI,EAClB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAMlB;;AAXD,AAOE,EAPA,CAAC,YAAY,CAOb,GAAG,CAAC,EACF,MAAM,EAAE,OAAO,EACf,aAAa,EAAE,IAAI,GACpB" +} \ No newline at end of file diff --git a/style/pygments.css b/_site/assets/css/pygments.css similarity index 95% rename from style/pygments.css rename to _site/assets/css/pygments.css index 9d2ed62..a881278 100644 --- a/style/pygments.css +++ b/_site/assets/css/pygments.css @@ -1,25 +1,23 @@ -/* -generated by Pygments -Copyright 2006-2022 by the Pygments team. -Licensed under the BSD license, see LICENSE for details. -*/ pre { - line-height: 125%; font-size: 1.25rem; margin-top: 0; + vertical-align: top; } -.highlighttable { +figure.highlight { + margin: 0; + margin-left: 1.5rem; +} + +.rouge-table { display: block; overflow-x: auto; } -td.linenos { - border-right: 3px solid rgb(252, 169, 184); +td.gutter { padding-right: 10px; + border-right: 3px solid rgb(252, 169, 184); border-radius: 3px; - padding-top: 3px; - padding-bottom: 3px; } td.code { diff --git a/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-700.woff b/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-700.woff new file mode 100644 index 0000000..8fbdce0 Binary files /dev/null and b/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-700.woff differ diff --git a/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-700.woff2 b/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-700.woff2 new file mode 100644 index 0000000..7b15f1c Binary files /dev/null and b/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-700.woff2 differ diff --git a/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-700italic.woff b/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-700italic.woff new file mode 100644 index 0000000..50e0235 Binary files /dev/null and b/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-700italic.woff differ diff --git a/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-700italic.woff2 b/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-700italic.woff2 new file mode 100644 index 0000000..ea2f84d Binary files /dev/null and b/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-700italic.woff2 differ diff --git a/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-italic.woff b/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-italic.woff new file mode 100644 index 0000000..8db160d Binary files /dev/null and b/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-italic.woff differ diff --git a/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-italic.woff2 b/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-italic.woff2 new file mode 100644 index 0000000..6d680fb Binary files /dev/null and b/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-italic.woff2 differ diff --git a/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-regular.woff b/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-regular.woff new file mode 100644 index 0000000..5a975d1 Binary files /dev/null and b/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-regular.woff differ diff --git a/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-regular.woff2 b/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-regular.woff2 new file mode 100644 index 0000000..6dab02e Binary files /dev/null and b/_site/assets/fonts/source-code-pro-v22-latin-ext_latin-regular.woff2 differ diff --git a/_site/assets/images/link.svg b/_site/assets/images/link.svg new file mode 100644 index 0000000..0f81b34 --- /dev/null +++ b/_site/assets/images/link.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/articles/f91w/images/f91w-strap.svg b/_site/assets/images/sensor-watch/f91w-strap.svg similarity index 100% rename from articles/f91w/images/f91w-strap.svg rename to _site/assets/images/sensor-watch/f91w-strap.svg diff --git a/articles/f91w/images/f91w.svg b/_site/assets/images/sensor-watch/f91w.svg similarity index 100% rename from articles/f91w/images/f91w.svg rename to _site/assets/images/sensor-watch/f91w.svg diff --git a/_site/cv.pdf b/_site/cv.pdf new file mode 100644 index 0000000..f1dea9d Binary files /dev/null and b/_site/cv.pdf differ diff --git a/_site/cv/main.tex b/_site/cv/main.tex new file mode 100644 index 0000000..5e177cc --- /dev/null +++ b/_site/cv/main.tex @@ -0,0 +1,55 @@ + +\documentclass[letterpaper,11pt]{article} + +% Choose bibliography style for formatting list of publications +\usepackage[style=ieee,url=false,doi=false,maxbibnames=99,sorting=ydnt,dashed=false]{biblatex} +\bibliography{papers} + +% Choose theme, e.g. black, RedViolet, ForestGreen, MidnightBlue +\def\theme{BlueViolet} + +% More predefined colors can be found in +% https://en.wikibooks.org/wiki/LaTeX/Colors +% Example photograph taken from Wikimedia Commons +% https://commons.wikimedia.org/wiki/File:Kiara_Krit_passport.jpg + +\usepackage{simplecv} + +\boldname{Bond-Preston}{Jack}{Mr.} + +\begin{document} + +\thispagestyle{empty} + +% Heading +\headinginline{Jack Bond-Preston}{ + Website: \website{jackbondpreston.me} \\ + Email: \email{jackbondpreston@outlook.com} \\ + LinkedIn: \linkedin{jack-bond-preston-922706150} \\ + GitHub: \github{jackbondpreston} +} + +% \headingphoto{Name Surname}{ +% Website: \website{example.com} \\ +% Email: \email{example@example.edu} \\ +% LinkedIn: \linkedin{name-surname} \\ +% GitHub: \github{example} +% }{photo.jpg} + +% Page One +\import{sections/}{education.tex} +\import{sections/}{experience.tex} +%\import{sections/}{publications.tex} + +%\pagebreak + +% Page Two +%\import{sections/}{teaching.tex} +% \sidebyside +\import{sections/}{skills.tex} + % {\import{sections/}{languages.tex}} +%\import{sections/}{projects.tex} +%\import{sections/}{awards.tex} +%\import{sections/}{extracurricular.tex} + +\end{document} diff --git a/_site/cv/sections/awards.tex b/_site/cv/sections/awards.tex new file mode 100644 index 0000000..cc3a7ab --- /dev/null +++ b/_site/cv/sections/awards.tex @@ -0,0 +1,20 @@ + +\section{Scholarships and Awards} + +\denseouterlist{ + +\entry{Some Scholarship \hfill 2018\textendash 2020} + +\entry{Some Award \hfill 2018\fillyear{\textendash 2018}} + +\entry{Some Award \hfill 2017\fillyear{\textendash 2017}} + +\entry{Some Award \hfill 2016\fillyear{\textendash 2016}} + +\entry{Some Scholarship \hfill 2013\textendash 2018} + +\entry{Some Scholarship \hfill 2013\textendash 2018} + +\entry{Some Award \hfill 2013\fillyear{\textendash 2013}} + +} diff --git a/_site/cv/sections/education.tex b/_site/cv/sections/education.tex new file mode 100644 index 0000000..b065841 --- /dev/null +++ b/_site/cv/sections/education.tex @@ -0,0 +1,14 @@ + +\section{Education} + +\outerlist{ + +\entrybig + {\textbf{University of Bristol}}{Bristol, UK} + {BSc in Computer Science (1st Class Hons)}{2017\textendash 2020} + \vspace{-0.75em} +\innerlist{ + \entry{Awarded prize for best second-year group software development project.} +} + +} diff --git a/_site/cv/sections/experience.tex b/_site/cv/sections/experience.tex new file mode 100644 index 0000000..ca9a34f --- /dev/null +++ b/_site/cv/sections/experience.tex @@ -0,0 +1,45 @@ + +\section{Experience} + +\outerlist{ + +\entrybig + {\textbf{AMD, Inc. (formerly Xilinx)}}{Cambridge, UK} + {Software Engineer in Adaptive and Embedded Computing Group}{2022\textendash Current} +\innerlist{ + \entry{Developing AMDs Onload userspace network stack.} +} + +\entrybig + {\textbf{Arm Ltd.}}{Cambridge, UK} + {Graduate Software Engineer in Open Source Software Group}{2021\textendash2022} +\innerlist{ + \entry{Porting low-level software to the Morello (CHERI) platform.} + \entryextra{Produced patches in C and AArch64 assembly as part of a project porting the open-source C standard library implementation musl to a new prototype platform.} + \entryextra{Ported larger components of the C library, including the memory allocator and POSIX threads. Considered security and hardening against memory safety bugs at every stage of design and implementation.} + \entryextra{Created a minimal test distribution of Linux for use on an Arm Fixed Virtual Platform, with the ability to run userspace applications in pure-capability mode. This provided the framework for adding FVP-based testing to the CI pipeline (alongside existing emulator-based testing) for further proof of functionality.} + \entryextra{Liased with multiple teams to ensure coordination between libc, kernel ABI, compilers and debuggers.} + \entryextra{Provided code review including feedback and improvements for patches developed by others for the musl project.} +} + +\entrybig + {\textbf{University of Bristol}}{Bristol, UK} + {Teaching Assistant in Department of Computer Science}{2019\textendash 2020} + \innerlist{ + \entry{Delivered and created content for several Computer Science courses, including content involving operating systems, concurrency, and a software engineering project.} + \entryextra{Provided guidance and troubleshooting assistance to students in both in-person and online lab sessions, including for a course in which students develop a basic Armv7-A multitasking kernel.} + \entryextra{Interviewed students in viva-style coursework assessments, and assisted with subsequent coursework marking.} + \entryextra{Assisted with the creation and improvement of lab sheets (including skeleton and solution code).} + } + + +% \entrybig +% {\textbf{Evolve East Anglia CIC}}{Norwich, UK} +% {Support Worker}{2020\textendash Current} +% \innerlist{ +% \entry{Assisting vulnerable adults with transitioning to a permanent living situation after suffering mental difficulties.} +% \entryextra{Handled crises swiftly, independently and effectively.} +% \entryextra{Built upon existing communication skills and knowledge about wellbeing and mental health.} +% } + +} diff --git a/_site/cv/sections/extracurricular.tex b/_site/cv/sections/extracurricular.tex new file mode 100644 index 0000000..e3c167c --- /dev/null +++ b/_site/cv/sections/extracurricular.tex @@ -0,0 +1,22 @@ + +\section{Extracurricular Activities} + +\denseouterlist{ + +\entrymid[\textbullet] +{Member at Some Club}{2017\textendash Current} +{Detailed explanation of what you do at this club} + +\entrymid[\textbullet] +{Member at Some Club}{2016\textendash 2017} +{Detailed explanation of what you do at this club} + +\entrymid[\textbullet] +{Volunteer at Some Event}{Fall 2019} +{Detailed explanation of what you do in this event} + +\entrymid[\textbullet] +{Volunteer at Some Event}{Winter 2015} +{Detailed explanation of what you do in this event} + +} diff --git a/_site/cv/sections/languages.tex b/_site/cv/sections/languages.tex new file mode 100644 index 0000000..8703985 --- /dev/null +++ b/_site/cv/sections/languages.tex @@ -0,0 +1,7 @@ + +\section{Languages} + +\denseouterlist{ +\entry{\textbf{English:} Native speaker} +\entry{\textbf{German:} CEFR A2/B1 (Elementary/Low Intermediate)} +} diff --git a/_site/cv/sections/projects.tex b/_site/cv/sections/projects.tex new file mode 100644 index 0000000..453ad1b --- /dev/null +++ b/_site/cv/sections/projects.tex @@ -0,0 +1,28 @@ + +\section{Projects} + +See full list of projects on \website{example.com/projects} +\vspace{1em} + +\begin{minipage}[t]{0.505\textwidth} + +\outerlist{ + +\entrybig[\textbullet] +{Project Title (Technology Used, 2019)}{} +{Short explanation of the project}{} + +} + +\end{minipage} +\begin{minipage}[t]{0.48\textwidth} + +\outerlist{ + +\entrybig[\textbullet] +{Project Title (Technology Used, 2019)}{} +{Short explanation of the project}{} + +} + +\end{minipage} diff --git a/_site/cv/sections/publications.tex b/_site/cv/sections/publications.tex new file mode 100644 index 0000000..3fddc90 --- /dev/null +++ b/_site/cv/sections/publications.tex @@ -0,0 +1,9 @@ + +\nocite{*} +\printbibliography[title=Publications] + +% Can instead manually enter publications as shown: +% \section{Publications} +% \orderedouterlist{ +% \entry{S. Petridis, J. Shen, \textbf{D. Cetin} and M. Pantic, "Visual-Only Recognition of Normal, Whispered And Silent Speech", \textit{IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP), April 2018}} +% } diff --git a/_site/cv/sections/skills.tex b/_site/cv/sections/skills.tex new file mode 100644 index 0000000..0f98ea3 --- /dev/null +++ b/_site/cv/sections/skills.tex @@ -0,0 +1,11 @@ + +\section{Skills} + +\denseouterlist{ +\entry{\textbf{Low-Level Software \& Architecture:} C, C++ (inc. 11/17/20 standards), Armv7/8/9 (assembly \& architecture), RISC-V, CHERI, GNU Make, CMake.} +\entry{\textbf{Software Engineering:} Git, Gerrit, Linux, Bash \& Zsh, Python, Java, Haskell, Agile, Jira.} +\entry{\textbf{Web Development:} HTML5, Modern CSS, ECMAScript 2015+ \& Typescript, Vue.js, Spring Boot, SQL.} +\entry{\textbf{Teaching:} Giving lectures \& seminars, interviewing, marking coursework, giving knowledge sharing presentations.} +\entry{\textbf{Design:} 3D modelling, vector graphics, Photoshop.} + +} diff --git a/_site/cv/sections/teaching.tex b/_site/cv/sections/teaching.tex new file mode 100644 index 0000000..8e3c5f4 --- /dev/null +++ b/_site/cv/sections/teaching.tex @@ -0,0 +1,12 @@ + +\section{Teaching} + +\denseouterlist{ + +\entrymid[\textbullet] +{\textbf{Head Teaching Assistant} at University Name}{Spring 2019}{Course Name (COURSE CODE)} + +\entrymid[\textbullet] +{\textbf{Teaching Assistant} at University Name}{Spring 2017}{Course Name (COURSE CODE)} + +} diff --git a/_site/cv/simplecv.sty b/_site/cv/simplecv.sty new file mode 100644 index 0000000..0af3ca2 --- /dev/null +++ b/_site/cv/simplecv.sty @@ -0,0 +1,149 @@ +\ProvidesPackage{simplecv} + +% Packages +\usepackage[cm]{fullpage} % Margins +\usepackage[hidelinks]{hyperref} % Hyperlinks +\usepackage{titlesec} % Title formatting +\usepackage{subfiles} % File importing +\usepackage{multicol} % Multiple columns +\usepackage[usenames,dvipsnames]{xcolor} % Coloring +\usepackage{enumitem} % List customization +\usepackage{lastpage} % Page numbering +\usepackage{fancyhdr} % Footers +\usepackage[russian,english]{babel} % Language styles +\usepackage{graphicx} % Importing graphics +\usepackage[export]{adjustbox} % Aligning margins + +% % Chinese +% \usepackage{xeCJK} +% \setCJKmainfont{BabelStone Han} + +% % Cyrillic/Russian +% \usepackage{hyphenat} +% \babelfont{rm}{Droid Sans} + +% Styling +\pagestyle{fancy} +\fancyhf{} +\renewcommand{\headrulewidth}{0pt} +\renewcommand{\footrulewidth}{0pt} +\urlstyle{same} +\raggedbottom +\raggedright +\setlength{\tabcolsep}{0in} + +% Quotes +\usepackage[autostyle,english=american]{csquotes} +\MakeOuterQuote{"} + +% Hyperlinks +% \newcommand{\link}[2]{\href{#1}{\underline{\smash{#2}}}} +\newcommand{\link}[2]{\href{#1}{#2}} + +% Define colors +\definecolor{color-text}{gray}{0.10} % light black +\definecolor{color-detail}{gray}{0.40} % dark gray +\colorlet{color-title}{\theme} % black + +% Set text color +\makeatletter +\newcommand{\globalcolor}[1]{\color{#1}\global\let\default@color\current@color} +\makeatother +\AtBeginDocument{\globalcolor{color-text}} + +% Shorthand +\newcommand{\github}[1]{\href{https://github.com/#1/}{github.com/#1}} +\newcommand{\email}[1]{\href{mailto:#1}{#1}} +\newcommand{\website}[1]{\href{https://#1/}{#1}} +\newcommand{\linkedin}[1]{\href{https://www.linkedin.com/in/#1/}{#1}} + +% Dummy environment +\newenvironment*{dummyenv}{}{} + +% Inline heading +\newcommand{\headinginline}[2]{ + \begin{minipage}[t]{0.50\textwidth} + \vspace*{\fill} + \Huge \textcolor{color-title}{#1} + \end{minipage} + \begin{minipage}[t]{0.45\textwidth} + \begin{flushright} + #2 + \end{flushright} + \end{minipage} +} + +% Photo heading +\newcommand{\headingphoto}[3]{ + \begin{minipage}[t]{0.60\textwidth} + \begin{dummyenv} + \vspace*{\fill} + \Huge \textcolor{color-title}{#1} + \end{dummyenv} + \vspace{5mm}\\ + #2 + \end{minipage} + \begin{minipage}[t]{0.35\textwidth} + \begin{flushright} + \includegraphics[width=.5\linewidth,valign=t]{#3} + \end{flushright} + \end{minipage} +} + +% Two-columns +\newcommand{\sidebyside}[2]{ + \begin{multicols}{2} + #1 \columnbreak + #2 \end{multicols} +} + +% Section titles +\titleformat{\section}{ + \scshape\raggedright\Large\color{color-title}}{}{0em}{}[\color{color-title}\titlerule + \vspace{-\smallskipamount}] + +% Footer +\fancyfoot[R]{Page \thepage \hspace{1pt} of \pageref{LastPage}} + +% Lists +\newcommand{\outerlist}[1]{ + \begin{itemize}[leftmargin=*] #1 \end{itemize}} +\newcommand{\denseouterlist}[1]{ + \begin{itemize}[leftmargin=*,itemsep=0pt] #1 \end{itemize}} +\newcommand{\innerlist}[1]{ + \begin{itemize}[topsep=0pt] #1 \end{itemize}} +\newcommand{\orderedouterlist}[1]{ + \begin{enumerate}[leftmargin=*] #1 \end{enumerate}} + +% List items +\newcommand{\entry}[1]{\item\small{#1}} +\newcommand{\entryextra}[1]{\textcolor{color-detail}{\entry{#1}}} +\newcommand{\entrylabeled}[2][]{\item[#1]\small{#2}} + +\newcommand{\entrymid}[4][]{ + \item[#1] \small{#2} \hfill \small{#3} + \vspace{-\smallskipamount} \item[]\small{\textit{#4}}} + +\newcommand{\entrybig}[5][]{\item[#1] + \begin{tabular*}{0.97\textwidth}{l@{\extracolsep{\fill}}r} + #2 & #3 \\ {\small#4} & {\small #5} \\ \end{tabular*}} + +% Fill year +\newcommand{\fillyear}[1]{\phantom{#1}} + +% Make author name bold: https://tex.stackexchange.com/a/327046 +\newcommand*{\boldname}[3]{% + \def\lastname{#1}% + \def\firstname{#2}% + \def\firstinit{#3}} +\boldname{}{}{} + +\renewcommand{\mkbibnamegiven}[1]{% + \ifboolexpr{ ( test {\ifdefequal{\firstname}{\namepartgiven}} or test {\ifdefequal{\firstinit}{\namepartgiven}} ) and test {\ifdefequal{\lastname}{\namepartfamily}} } + {\mkbibbold{#1}}{#1}% +} + +\renewcommand{\mkbibnamefamily}[1]{% + \ifboolexpr{ ( test {\ifdefequal{\firstname}{\namepartgiven}} or test {\ifdefequal{\firstinit}{\namepartgiven}} ) and test {\ifdefequal{\lastname}{\namepartfamily}} } + {\mkbibbold{#1}}{#1}% +} \ No newline at end of file diff --git a/_site/generated/assets/images/sensor-watch/pcb-1000-c21b83783.jpg b/_site/generated/assets/images/sensor-watch/pcb-1000-c21b83783.jpg new file mode 100644 index 0000000..9c6f3be Binary files /dev/null and b/_site/generated/assets/images/sensor-watch/pcb-1000-c21b83783.jpg differ diff --git a/_site/generated/assets/images/sensor-watch/pcb-400-c21b83783.jpg b/_site/generated/assets/images/sensor-watch/pcb-400-c21b83783.jpg new file mode 100644 index 0000000..7eef99b Binary files /dev/null and b/_site/generated/assets/images/sensor-watch/pcb-400-c21b83783.jpg differ diff --git a/_site/generated/assets/images/sensor-watch/pcb-600-c21b83783.jpg b/_site/generated/assets/images/sensor-watch/pcb-600-c21b83783.jpg new file mode 100644 index 0000000..055a84a Binary files /dev/null and b/_site/generated/assets/images/sensor-watch/pcb-600-c21b83783.jpg differ diff --git a/_site/generated/assets/images/sensor-watch/pcb-800-c21b83783.jpg b/_site/generated/assets/images/sensor-watch/pcb-800-c21b83783.jpg new file mode 100644 index 0000000..f224944 Binary files /dev/null and b/_site/generated/assets/images/sensor-watch/pcb-800-c21b83783.jpg differ diff --git a/_site/generated/sensor-watch/c7c8-1000-418506084.jpg b/_site/generated/sensor-watch/c7c8-1000-418506084.jpg new file mode 100644 index 0000000..8fb0cce Binary files /dev/null and b/_site/generated/sensor-watch/c7c8-1000-418506084.jpg differ diff --git a/_site/generated/sensor-watch/c7c8-1000-4c01589bc.webp b/_site/generated/sensor-watch/c7c8-1000-4c01589bc.webp new file mode 100644 index 0000000..b8a8d77 Binary files /dev/null and b/_site/generated/sensor-watch/c7c8-1000-4c01589bc.webp differ diff --git a/_site/generated/sensor-watch/c7c8-400-418506084.jpg b/_site/generated/sensor-watch/c7c8-400-418506084.jpg new file mode 100644 index 0000000..3730b15 Binary files /dev/null and b/_site/generated/sensor-watch/c7c8-400-418506084.jpg differ diff --git a/_site/generated/sensor-watch/c7c8-400-4c01589bc.webp b/_site/generated/sensor-watch/c7c8-400-4c01589bc.webp new file mode 100644 index 0000000..6ea7db2 Binary files /dev/null and b/_site/generated/sensor-watch/c7c8-400-4c01589bc.webp differ diff --git a/_site/generated/sensor-watch/c7c8-600-418506084.jpg b/_site/generated/sensor-watch/c7c8-600-418506084.jpg new file mode 100644 index 0000000..0908824 Binary files /dev/null and b/_site/generated/sensor-watch/c7c8-600-418506084.jpg differ diff --git a/_site/generated/sensor-watch/c7c8-600-4c01589bc.webp b/_site/generated/sensor-watch/c7c8-600-4c01589bc.webp new file mode 100644 index 0000000..7152206 Binary files /dev/null and b/_site/generated/sensor-watch/c7c8-600-4c01589bc.webp differ diff --git a/_site/generated/sensor-watch/c7c8-800-418506084.jpg b/_site/generated/sensor-watch/c7c8-800-418506084.jpg new file mode 100644 index 0000000..e91871f Binary files /dev/null and b/_site/generated/sensor-watch/c7c8-800-418506084.jpg differ diff --git a/_site/generated/sensor-watch/c7c8-800-4c01589bc.webp b/_site/generated/sensor-watch/c7c8-800-4c01589bc.webp new file mode 100644 index 0000000..44ecc6a Binary files /dev/null and b/_site/generated/sensor-watch/c7c8-800-4c01589bc.webp differ diff --git a/_site/generated/sensor-watch/pcb-1000-c21b83783.jpg b/_site/generated/sensor-watch/pcb-1000-c21b83783.jpg new file mode 100644 index 0000000..9c6f3be Binary files /dev/null and b/_site/generated/sensor-watch/pcb-1000-c21b83783.jpg differ diff --git a/_site/generated/sensor-watch/pcb-1000-c27ab3576.webp b/_site/generated/sensor-watch/pcb-1000-c27ab3576.webp new file mode 100644 index 0000000..49478bc Binary files /dev/null and b/_site/generated/sensor-watch/pcb-1000-c27ab3576.webp differ diff --git a/_site/generated/sensor-watch/pcb-400-c21b83783.jpg b/_site/generated/sensor-watch/pcb-400-c21b83783.jpg new file mode 100644 index 0000000..7eef99b Binary files /dev/null and b/_site/generated/sensor-watch/pcb-400-c21b83783.jpg differ diff --git a/_site/generated/sensor-watch/pcb-400-c27ab3576.webp b/_site/generated/sensor-watch/pcb-400-c27ab3576.webp new file mode 100644 index 0000000..3d4a1ab Binary files /dev/null and b/_site/generated/sensor-watch/pcb-400-c27ab3576.webp differ diff --git a/_site/generated/sensor-watch/pcb-600-c21b83783.jpg b/_site/generated/sensor-watch/pcb-600-c21b83783.jpg new file mode 100644 index 0000000..055a84a Binary files /dev/null and b/_site/generated/sensor-watch/pcb-600-c21b83783.jpg differ diff --git a/_site/generated/sensor-watch/pcb-600-c27ab3576.webp b/_site/generated/sensor-watch/pcb-600-c27ab3576.webp new file mode 100644 index 0000000..7446f8b Binary files /dev/null and b/_site/generated/sensor-watch/pcb-600-c27ab3576.webp differ diff --git a/_site/generated/sensor-watch/pcb-800-c21b83783.jpg b/_site/generated/sensor-watch/pcb-800-c21b83783.jpg new file mode 100644 index 0000000..f224944 Binary files /dev/null and b/_site/generated/sensor-watch/pcb-800-c21b83783.jpg differ diff --git a/_site/generated/sensor-watch/pcb-800-c27ab3576.webp b/_site/generated/sensor-watch/pcb-800-c27ab3576.webp new file mode 100644 index 0000000..99fc134 Binary files /dev/null and b/_site/generated/sensor-watch/pcb-800-c27ab3576.webp differ diff --git a/_site/generated/sensor-watch/watch1-1000-370dbdf66.jpg b/_site/generated/sensor-watch/watch1-1000-370dbdf66.jpg new file mode 100644 index 0000000..2befc4d Binary files /dev/null and b/_site/generated/sensor-watch/watch1-1000-370dbdf66.jpg differ diff --git a/_site/generated/sensor-watch/watch1-1000-d4fc580e6.webp b/_site/generated/sensor-watch/watch1-1000-d4fc580e6.webp new file mode 100644 index 0000000..453dc0d Binary files /dev/null and b/_site/generated/sensor-watch/watch1-1000-d4fc580e6.webp differ diff --git a/_site/generated/sensor-watch/watch1-400-370dbdf66.jpg b/_site/generated/sensor-watch/watch1-400-370dbdf66.jpg new file mode 100644 index 0000000..d2ec4f9 Binary files /dev/null and b/_site/generated/sensor-watch/watch1-400-370dbdf66.jpg differ diff --git a/_site/generated/sensor-watch/watch1-400-d4fc580e6.webp b/_site/generated/sensor-watch/watch1-400-d4fc580e6.webp new file mode 100644 index 0000000..e60c57b Binary files /dev/null and b/_site/generated/sensor-watch/watch1-400-d4fc580e6.webp differ diff --git a/_site/generated/sensor-watch/watch1-600-370dbdf66.jpg b/_site/generated/sensor-watch/watch1-600-370dbdf66.jpg new file mode 100644 index 0000000..5b49b08 Binary files /dev/null and b/_site/generated/sensor-watch/watch1-600-370dbdf66.jpg differ diff --git a/_site/generated/sensor-watch/watch1-600-d4fc580e6.webp b/_site/generated/sensor-watch/watch1-600-d4fc580e6.webp new file mode 100644 index 0000000..97944fc Binary files /dev/null and b/_site/generated/sensor-watch/watch1-600-d4fc580e6.webp differ diff --git a/_site/generated/sensor-watch/watch1-800-370dbdf66.jpg b/_site/generated/sensor-watch/watch1-800-370dbdf66.jpg new file mode 100644 index 0000000..852785d Binary files /dev/null and b/_site/generated/sensor-watch/watch1-800-370dbdf66.jpg differ diff --git a/_site/generated/sensor-watch/watch1-800-d4fc580e6.webp b/_site/generated/sensor-watch/watch1-800-d4fc580e6.webp new file mode 100644 index 0000000..ac5c93b Binary files /dev/null and b/_site/generated/sensor-watch/watch1-800-d4fc580e6.webp differ diff --git a/_site/generated/sensor-watch/watch2-1000-66db436da.jpg b/_site/generated/sensor-watch/watch2-1000-66db436da.jpg new file mode 100644 index 0000000..1fde4b5 Binary files /dev/null and b/_site/generated/sensor-watch/watch2-1000-66db436da.jpg differ diff --git a/_site/generated/sensor-watch/watch2-1000-7609c3dcc.webp b/_site/generated/sensor-watch/watch2-1000-7609c3dcc.webp new file mode 100644 index 0000000..a50e8ee Binary files /dev/null and b/_site/generated/sensor-watch/watch2-1000-7609c3dcc.webp differ diff --git a/_site/generated/sensor-watch/watch2-400-66db436da.jpg b/_site/generated/sensor-watch/watch2-400-66db436da.jpg new file mode 100644 index 0000000..7e5947d Binary files /dev/null and b/_site/generated/sensor-watch/watch2-400-66db436da.jpg differ diff --git a/_site/generated/sensor-watch/watch2-400-7609c3dcc.webp b/_site/generated/sensor-watch/watch2-400-7609c3dcc.webp new file mode 100644 index 0000000..605d3ee Binary files /dev/null and b/_site/generated/sensor-watch/watch2-400-7609c3dcc.webp differ diff --git a/_site/generated/sensor-watch/watch2-600-66db436da.jpg b/_site/generated/sensor-watch/watch2-600-66db436da.jpg new file mode 100644 index 0000000..05f6e0b Binary files /dev/null and b/_site/generated/sensor-watch/watch2-600-66db436da.jpg differ diff --git a/_site/generated/sensor-watch/watch2-600-7609c3dcc.webp b/_site/generated/sensor-watch/watch2-600-7609c3dcc.webp new file mode 100644 index 0000000..c0007aa Binary files /dev/null and b/_site/generated/sensor-watch/watch2-600-7609c3dcc.webp differ diff --git a/_site/generated/sensor-watch/watch2-800-66db436da.jpg b/_site/generated/sensor-watch/watch2-800-66db436da.jpg new file mode 100644 index 0000000..4e5a375 Binary files /dev/null and b/_site/generated/sensor-watch/watch2-800-66db436da.jpg differ diff --git a/_site/generated/sensor-watch/watch2-800-7609c3dcc.webp b/_site/generated/sensor-watch/watch2-800-7609c3dcc.webp new file mode 100644 index 0000000..6c81ddc Binary files /dev/null and b/_site/generated/sensor-watch/watch2-800-7609c3dcc.webp differ diff --git a/_site/generated/sensor-watch/wrist-1000-551704392.jpg b/_site/generated/sensor-watch/wrist-1000-551704392.jpg new file mode 100644 index 0000000..2ac1dbb Binary files /dev/null and b/_site/generated/sensor-watch/wrist-1000-551704392.jpg differ diff --git a/_site/generated/sensor-watch/wrist-1000-abd25cd51.webp b/_site/generated/sensor-watch/wrist-1000-abd25cd51.webp new file mode 100644 index 0000000..b71c3a0 Binary files /dev/null and b/_site/generated/sensor-watch/wrist-1000-abd25cd51.webp differ diff --git a/_site/generated/sensor-watch/wrist-400-551704392.jpg b/_site/generated/sensor-watch/wrist-400-551704392.jpg new file mode 100644 index 0000000..07866cf Binary files /dev/null and b/_site/generated/sensor-watch/wrist-400-551704392.jpg differ diff --git a/_site/generated/sensor-watch/wrist-400-abd25cd51.webp b/_site/generated/sensor-watch/wrist-400-abd25cd51.webp new file mode 100644 index 0000000..21acc96 Binary files /dev/null and b/_site/generated/sensor-watch/wrist-400-abd25cd51.webp differ diff --git a/_site/generated/sensor-watch/wrist-600-551704392.jpg b/_site/generated/sensor-watch/wrist-600-551704392.jpg new file mode 100644 index 0000000..8d728e2 Binary files /dev/null and b/_site/generated/sensor-watch/wrist-600-551704392.jpg differ diff --git a/_site/generated/sensor-watch/wrist-600-abd25cd51.webp b/_site/generated/sensor-watch/wrist-600-abd25cd51.webp new file mode 100644 index 0000000..a30bc98 Binary files /dev/null and b/_site/generated/sensor-watch/wrist-600-abd25cd51.webp differ diff --git a/_site/generated/sensor-watch/wrist-800-551704392.jpg b/_site/generated/sensor-watch/wrist-800-551704392.jpg new file mode 100644 index 0000000..55f4288 Binary files /dev/null and b/_site/generated/sensor-watch/wrist-800-551704392.jpg differ diff --git a/_site/generated/sensor-watch/wrist-800-abd25cd51.webp b/_site/generated/sensor-watch/wrist-800-abd25cd51.webp new file mode 100644 index 0000000..168c455 Binary files /dev/null and b/_site/generated/sensor-watch/wrist-800-abd25cd51.webp differ diff --git a/_site/index.html b/_site/index.html new file mode 100644 index 0000000..8ce0a83 --- /dev/null +++ b/_site/index.html @@ -0,0 +1,52 @@ + + + + + + + + + + jack bond-preston - jack bond-preston + + + + + +

jack bond-preston

+ +

contact[]

+

you can contact me via email or on linkedin

+ +

my cv is available for viewing here.

+ +

open source[]

+ +

i have personal accounts on github and gitlab

+ +

some of my work at arm on morello is available on the +d morello musl gitlab

+ +

my onload commits at amd can be found on the github repo

+ +

articles[]

+ +
  • + [19/11/2022] CHERI +
  • + +
  • + [14/11/2022] sensor watch +
  • + + + + + \ No newline at end of file diff --git a/articles/f91w/images/c7c8.jpg b/_site/pictures/sensor-watch/c7c8.jpg similarity index 100% rename from articles/f91w/images/c7c8.jpg rename to _site/pictures/sensor-watch/c7c8.jpg diff --git a/articles/f91w/images/pcb.jpg b/_site/pictures/sensor-watch/pcb.jpg similarity index 100% rename from articles/f91w/images/pcb.jpg rename to _site/pictures/sensor-watch/pcb.jpg diff --git a/_site/pictures/sensor-watch/watch1.jpg b/_site/pictures/sensor-watch/watch1.jpg new file mode 100644 index 0000000..f5bc8fd Binary files /dev/null and b/_site/pictures/sensor-watch/watch1.jpg differ diff --git a/_site/pictures/sensor-watch/watch2.jpg b/_site/pictures/sensor-watch/watch2.jpg new file mode 100644 index 0000000..2071c94 Binary files /dev/null and b/_site/pictures/sensor-watch/watch2.jpg differ diff --git a/_site/pictures/sensor-watch/wrist.jpg b/_site/pictures/sensor-watch/wrist.jpg new file mode 100644 index 0000000..7d3737a Binary files /dev/null and b/_site/pictures/sensor-watch/wrist.jpg differ diff --git a/_site/regexes b/_site/regexes new file mode 100644 index 0000000..84f5389 --- /dev/null +++ b/_site/regexes @@ -0,0 +1,11 @@ +([\w \n]+) +[$2]($1) + +\[([^\]]*)\n +[$1 + +

    ([^<]+)

    +## $1 + +

    ([^<]+)

    +### $1 diff --git a/aoc/10/index.html b/aoc/10/index.html deleted file mode 100644 index c579c5d..0000000 --- a/aoc/10/index.html +++ /dev/null @@ -1,340 +0,0 @@ - - - - Day 10 - - - - - - - -
    - - Points: 0 - Seconds: 0 - - - - - - - - \ No newline at end of file diff --git a/aoc/10/main.js b/aoc/10/main.js deleted file mode 100644 index bca1105..0000000 --- a/aoc/10/main.js +++ /dev/null @@ -1,197 +0,0 @@ -class Point { - - constructor(x, y, vx, vy) { - this.x = x; - this.y = y; - this.vx = vx; - this.vy = vy; - } - - next() { - this.x += this.vx; - this.y += this.vy; - } - - prev() { - this.x -= this.vx; - this.y -= this.vy; - } - - // move multiple at once - proceed(turns) { - this.x += turns * this.vx; - this.y += turns * this.vy; - } -} - -let pointsArr = []; -let minDistance = 0; -let turn = 0; - -function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -function getColourIndicesForCoord(x, y, width) { - let red = y * (width * 4) + x * 4; - - return { - "red": red, - "green": red + 1, - "blue": red + 2, - "alpha": red + 3 - } -} - -function setVirtualPixel(data, x, y, rgba, scale) { - let xStart = x * scale; - let yStart = y * scale; - - let xEnd = (x + 1) * scale; - let yEnd = (y + 1) * scale; - - for (let i = xStart; i < xEnd; i++) { - for (let j = yStart; j < yEnd; j++) { - let indices = getColourIndicesForCoord(i, j, 1000); - - data.data[indices.red] = rgba.red; - data.data[indices.green] = rgba.green; - data.data[indices.blue] = rgba.blue; - data.data[indices.alpha] = rgba.alpha; - } - } - - return data; -} - -function parseInput(raw) { - let points = [] - - let split = raw.split('\n'); - - let indexes = []; - - for (let i = 0; i < split[0].length; i++) { - if (split[0][i] === '<' || split[0][i] === ',' || split[0][i] === '>') indexes.push(i); - } - - for (let line of raw.split('\n')) { - let x = Number(line.slice(indexes[0] + 1, indexes[1])); - let y = Number(line.slice(indexes[1] + 2, indexes[2])); - - let vx = Number(line.slice(indexes[3] + 1, indexes[4])); - let vy = Number(line.slice(indexes[4] + 2, indexes[5])); - - points.push(new Point(x, y, vx, vy)); - } - updateDistance(points); - turn = 0; - - document.getElementById("points").innerText = "Points: " + points.length; - document.getElementById("turn").innerText = "Seconds: 0"; - - for (let i of document.getElementsByTagName("input")) { - i.disabled = false; - } - - clearCanvas(); - - return points; -} - -function clearCanvas() { - let context = document.getElementById("canvas").getContext("2d"); - - context.putImageData(context.createImageData(canvas.width, canvas.height), 0, 0); -} - -function render(points) { - let canvas = document.getElementById("canvas"); - let context = canvas.getContext("2d"); - - let data = context.createImageData(canvas.width, canvas.height); - const colour = { - red: 255, - green: 0, - blue: 0, - alpha: 255 - }; - - let min = [ - Math.min(... points.map(p => p.x)), - Math.min(... points.map(p => p.y)) - ]; - - let max = [ - Math.max(... points.map(p => p.x)), - Math.max(... points.map(p => p.y)) - ]; - - let offset = [-min[0], -min[1]]; - let maxDiff = Math.max(max[0] - min[0], max[1] - min[1]) - - if (maxDiff > 1000) scale = 1; - else scale = Math.floor(1000 / maxDiff); - - while (1000 % scale !== 0) scale--; - - console.log(`Scale: ${scale}, diff: ${maxDiff}, offset: ${offset}`); - - for (let point of points) { - if (point.x + offset[0] < 1000 && point.y + offset[1] < 1000) - data = setVirtualPixel(data, point.x + offset[0], point.y + offset[1], colour, scale); - } - - context.putImageData(data, 0, 0); -} - -function distance(p1, p2) { - return Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y); -} - -function updateDistance(points) { - minDistance = Math.min(... - points.map( - point => { - return Math.max(... - points.map(point2 => distance(point, point2)) - ); - } - ) - ); -} - -async function run(points) { - document.getElementById("run").disabled = true; - - let x = 0; - - let prevMin = minDistance + 1; - - console.log(minDistance); - - while (prevMin > minDistance) { - prevMin = minDistance; - - proceedBy(points, Math.ceil(minDistance / 500)); - - updateDistance(points); - - if (minDistance < 1000 && prevMin > minDistance) { - render(points); - await sleep(10); - } - else await sleep(2); - } - - proceedBy(points, -1); - - render(points); -} - -function proceedBy(points, amount) { - points.forEach(point => point.proceed(amount)); - - turn += amount; - document.getElementById("turn").innerText = "Seconds: " + turn; -} \ No newline at end of file diff --git a/aoc/5/index.html b/aoc/5/index.html deleted file mode 100644 index d6e8f9e..0000000 --- a/aoc/5/index.html +++ /dev/null @@ -1,105 +0,0 @@ - - - AoC Day 5 - - - - - - - - - -
    - -
    -
    -dDdCcXxYyyYaAaBbbJjXJjxBbQwWwWqFHXxhfxTtUIiud -
    - - - \ No newline at end of file diff --git a/articles/f91w/images/watch1.jpg b/articles/f91w/images/watch1.jpg deleted file mode 100644 index 6a019b9..0000000 Binary files a/articles/f91w/images/watch1.jpg and /dev/null differ diff --git a/articles/f91w/images/watch2.jpg b/articles/f91w/images/watch2.jpg deleted file mode 100644 index 28abd69..0000000 Binary files a/articles/f91w/images/watch2.jpg and /dev/null differ diff --git a/articles/f91w/images/wrist.jpg b/articles/f91w/images/wrist.jpg deleted file mode 100644 index 58fbb38..0000000 Binary files a/articles/f91w/images/wrist.jpg and /dev/null differ diff --git a/articles/f91w/index.html b/articles/f91w/index.html deleted file mode 100644 index f21f897..0000000 --- a/articles/f91w/index.html +++ /dev/null @@ -1,432 +0,0 @@ - - - - - sensor watch | jack bond-preston - - - - - - - - - - - - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    -
    - - - -

    sensor watch

    - -

    preamble

    -

    -some time back I was browsing Crowd Supply when I came -across the Sensor -Watch project by Joey Castillo. I had wanted some -kind of "hackable" watch for a while, and had looked at things like -Watchy, but this project hit the sweet spot -for me. I love my existing F91-W, and this project was a good combination of open source with -community software support. one key feature that was important to me is battery life - the Sensor -Watch battery life in an average usage scenario is so long that -Joey's is still going -strong! -

    -

    -I was excited to pick one up and start messing around with it, but the first issue I came across -was availability - the delivery date for Crowd Supply orders was summer 2023 (I think they ended up -being delivered sooner than this, not sure). on top of this, shipping and import fees made it -pretty prohibitively expensive. I've always found this to be an issue with Crowd Supply as someone -based in the UK, even some things designed in the UK are very expensive from Crowd Supply as they -are assembled in/shipped from the US. so I decided to build one myself! of course, this is more -expensive than just buying it, but this was a learning experience and -knowledge is power! -

    - -

    component acquisition

    -

    -the first challenge was acquiring all the necessary parts to actually build one. I downloaded -the PCB files -and generated a BOM to figure -out exactly what I needed to acquire. I'm sure in ordinary times this would be easy enough, but the -current state of some electronics/silicon supply chains had other things to say. some parts are of -course still easy to come across, e.g. 10pF 0402 caps and 10k 0603 resistors; most of the -components of the Sensor Watch are this kind of commonplace part. what quickly became clear from -some scouring of the internet was that my main problem was going to be two parts: the -ATSAML22J18A-MUT (the processor -driving the Sensor Watch), and the -FH19C-9S-0.5SH(10) (the connector used to attach the extra sensor boards). -

    -

    ATSAML22J18A-MUT

    -

    -the former of these was a fairly well discussed shortage that had been ongoing for a while. it was - -the driving force of the Sensor Watch Crowd Supply delay. I spent quite a lot of time searching -around the internet, looking at various sites on the English-speaking and Chinese-speaking web. -sadly this part was clearly in very short supply, and prices could get pretty insane from vendors -that did have some stock. I received quotes for unit prices that include the following (USD/GBP): -$79.35, $6.56, $13.61, $6.83 (MOQ 4000), £6.45. I guess some people are desperate enough to pay -$79.35 :(. I spent so long looking for them that they ended up randomly coming back in stock on -MicrochipDirect. as of the time of writing this -article, -they are again out of stock. -the unit price I bought them for was £3.92, shipping and handling was ~£12. -

    -

    FH19C-9S-0.5SH(10)

    -

    -this part was out of stock everywhere I initially looked (the usual contenders for parts). I -searched around in a similar manner as the ATSAML22J18A-MUT, and found some similarly wild pricing. -I ended up purchasing a small quantity at a unit price of £0.44 from a website called -dacikeys. yes, the -site is actually called this. yes, the unit price is cheaper than digikey and mouser. yes, I -actually received all of my order, consisting of working parts. I was definitely shocked that this -happened, but sometimes bravery pays off I guess. I still can't endorse this shop. -

    -

    PCB and stencil

    -

    -for the PCB I opted to go with JLCPCB. I simply uploaded the -relevant gerbers, and adjusted the necessary settings. notably, -the -thickness should be 0.6mm - this does narrow the choice of manufacturer (for example, OSH Park -doesn't go this thin). I haven't yet ordered any sensor board PCBs, but -PCBWay seems to be the option there. The PCB turned -out great, although the silkscreen is a little hard to read at this size due to lack of sharpness: - -

    - -

    assembly

    -

    -I decided to assemble myself. partially because the logistics of paying for assembly when I had to -source parts from many different providers seemed like a headache, partially because I thought it -would be a fun challenge and learning experience! -

    -

    -a few things were necessary to solder the components to this PCB. I'm sure someone talented could -hand solder this with an iron, but I can name a lot of things I'd rather do than try to do that -(especially the QFN SAML) - and -that list includes unpleasant things. I opted to go with -hotplate soldering, which is a cheaper -way to access the ease of reflow soldering. for a PCB like the Sensor Watch, where almost all the -components are on one side, it's ideal. the hotplate I have is the ever-popular -MHP30, which I -run IronOS on. I highly recommend it, it's great! my -soldering iron is the iconic -Pinecil (not -the fancy new V2 -though :[) which also runs IronOS. nice! -

    -

    process

    -

    -the assembly process is as follows: -

      -
    • -apply solder paste to the PCB with the stencil. make sure the stencil is really flush and just -kind of squeegee it on with a plastic card. I used tape to hold it in place. then carefully -removed the stencil, avoiding smudging the paste in doing so. -
    • -
    • -place components on the PCB. this was by far the most painful part of the whole process. a -steady hand is not something I was blessed with, and some of these parts are really small. I used a -microscope from Amazon for this, the ample manouverable lighting was a big help. a lot of time and -patience is required, but it's very first time doable with no prior experience! simply go through -the parts one by one, or by area of the board - whatever you prefer. then pick up the respective -part with some fine tweezers, and slowly put in place on the solder paste. thankfully, the paste -will lightly stick the component in place once you've done this (it is not knock-proof though!). -
    • -
    • -carefully (really!) place the PCB onto the hotplate and heat up. keep on until everything seems -to be melted, and the components have hopefully been pulled into place. that's the top side done! -let it cool down, then move on to the bottom. -
    • -
    • -time for some hand soldering. the button is pretty small, and very fiddly to do. I found you don't -need too much precision, but you have to be really careful with your iron as the plastic button -will melt if you touch it. once that's in place, it's just a matter of -removing the buzzer connector from your old PCB and -soldering it onto the back of the Sensor Watch PCB. this will feel blissfully easy after the -button! you also have to place the battery clip, but no soldering needed here :). -
    • -
    -

    -

    -one area I found particularly difficult was the area with the oscillator crystal and the two 0402 -capacitors, C7 and C8. things are a bit cramped here, so extra care was needed: - -

    - -

    software

    -

    -at this point the watch was assembled with all components in place. did it work? at this stage, no -idea. hopefully yes, and I could progress to the more familiar world of embedded software. -

    - -

    bootloader

    -

    -the next necessary step is to flash the bootloader, so that we can put the firmware in place. -unfortunately this requires a little more real-world action. we need to access the SWD points on -the board to write the bootloader. ideally you could do this with some kind of -pogo pin jig - and if you were doing any -number exceeding about 5 I'm sure this would be worth the time. however, I decided to just solder -some jump wires (stripped on one end, solid tip female on the other) to the points on the board. -they're all close, but it's easy enough to do (albeit ugly). then I connected these to my -Adafruit Trinket M0 (PyRuler would also work). -the pin mapping is as follows: SWD=0, SWC=1, RST=3, V+=3V, GND=GND. -

    - -

    -I used the - -flasher from the sensor watch repo to flash the bootloader. note that you could build the -bootloader yourself first and put the generated binary into bootloader.h - the source is located -here. personally, I just used the prebuilt -version from the repo. I had to change part of the Adafruit DAP library and add the SAM L22 DID to -get this to work, -I provided -the diff of this change in a Sensor Watch GitHub issue (I just now am remembering I promised to -upstream this, oops!). mercifully, I got the red blinky LED, and all was good! I unsoldered the -wires from the board, and tried to clean up most of the solder blob to keep the board fairly flat. -

    - -

    movement

    -

    -now the bootloader is in place, the main firmware can be installed! -the community firmware, Movement is great, -so this is what I installed. there are a bunch of different useful faces available, and more -functionality is always being added. -

    -

    -flashing firmware was easy: I plugged the PCB into the end of a USB Micro B cable (plugged on the -other end into my computer) and double tapped the reset button (I find this has to be done quite -quickly, using my fingernail was the trick to doing this reliably on such a small button). done -successfully, the LED on the board pulses and a new drive labelled "WATCHBOOT" appears on the -computer. now a built UF2 firmware file can just be dragged onto the device to flash, thanks to the -bootloader flashed earlier. for the initial test, I just used a -prebuilt image to check -everything was working. I flashed this, and the LED pulsed and turned off, signalling success. -

    -

    -from here I just assembled the watch with the Sensor Watch PCB, and it worked! I verified LED and -buzzer function by playing around with various functionality. success! -

    - -

    developing on movement

    -

    -one face I found particularly cool was the -TOTP face. I use TOTP -2FA on various accounts, so -having access to the codes on my wrist at all times was really appealing. at the time, the TOTP -face only supported one key - so I decided to improve it. -

    -

    -thankfully, Sensor Watch has an emulator for development. without this, development would be pretty -tiresome with the flashing and reassembling of the watch getting tiring if you needed to iterate on -some code and test it on the watch. the emulator runs inside the browser and uses -Emscripten. -some minimal -instructions on how to build this is available on the README. this allowed me to extend the -TOTP face easily and allow for multiple keys. -my PR was merged, and the -functionality is now available for anyone to use. the keys are added at compile time, so they are -baked into the firmware on flashing. for my purposes this is fine, as I never really change them. -however, with the recent addition of a -LittleFS -filesystem, the community have added -a version of the face which stores the keys on the filesystem. awesome! -

    -

    -some more details on using Sensor Watch for TOTP is available -on this blog post -(HN discussion, if you dare). it's even -running my code :)! -

    - -

    epilogue

    -

    -some summary thoughts: -

      -
    • -shoutout to Joey Castillo. for creating the Sensor Watch as a beautifully open source project (the -fact I could independently make my own is what it's all about!). for being -so helpful and kind when I -asked for help. for having such a positive attitude towards those in the community who are using -Sensor Watch to learn about all kinds of things (seriously, check out the -Oddly Specific Objects Discord to see how much this guy -is giving to the community). -
    • -
    • -sometimes it's worth just trying things that are difficult. this is my first time successfully -doing and small-scale soldering of this kind, and it worked out great with some patience. having -the motivation from making something I thought was really cool was an important factor here I think. -
    • -
    • -if you have a Sensor Watch (or are planning to!) please go ahead and -contribute to movement if you have a cool idea. I'm sure some reviews would be helpful to spot -any issues on existing PRs before a maintainer gets to them to save some time. -
    • -
    • -the one issue I've had with using my Sensor Watch for TOTP is clock accuracy. the clock drifts over -time, so I have to set the time once or twice a week to keep it nice and accurate for the TOTP -functionality to be nice to use. but a community member is working on this, and it's going to get a -lot better. check out the Discord channel to see some seriously cool engineering going into this -calibration effort. -
    • -
    -

    -

    - - - -

    -
    -
    -

    -email me to have a conversation -

    - - - -
    -
    -
    - - - diff --git a/articles/morello/index.html b/articles/morello/index.html deleted file mode 100644 index 2e04196..0000000 --- a/articles/morello/index.html +++ /dev/null @@ -1,561 +0,0 @@ - - - - - cheri (and morello) | jack bond-preston - - - - - - - - - - - - - -
    - - - -

    cheri (and morello)

    - -

    preamble

    -

    -CHERI is an acronym for -Capability Hardware Enhanced RISC Instructions. it is a security-focussed project aimed at -improving memory protection at the hardware level. the project is complex and it has many potential -applications. -

    -

    -in this article I will go into some basics to give an understanding behind some changes that CHERI -makes to how programs execute and are written. this will be focussed almost entirely in C, as this -is where my experience lies - it is also where some of the effects of CHERI are most easily felt. -this article is going to be a very simplistic introduction to CHERI, and I'm going to -attempt to explain the basics behind everything I cover. a basic understanding of C will be -beneficial. -

    -

    -note: the Morello -platform is an evaluation board produced by Arm to provide a -physical implementation of CHERI extending the Arm -AArch64 ISA. I previously worked on this platform at Arm, -porting the musl C library to -Morello. implementations for CHERI that are worth looking into from a more open perspective -are the MIPS (chapter 4) -and RISC-V (chapter 5) ones. Morello is the only implementation that exists in a true hard core -format, afaik - but this is obviously hard to obtain so you'll just be playing around with -emulators/models anyway. -

    - -

    memory safety bugs

    -

    -to first understand how CHERI tries to fix some simple issues, let's first look at some simplified -examples of issues that arise when we aren't using a CHERI-based architecture. -

    - -

    a simple memory safety bug

    -

    -let's take a look at this C code: -

    - -
     1
    - 2
    - 3
    - 4
    - 5
    - 6
    - 7
    - 8
    - 9
    -10
    -11
    -12
    -13
    #include <stdio.h>
    -
    -int main() {
    -    char my_perfect_string[] = "what a beautiful string"; // so beautiful, I sure hope no-one touches it
    -    char user_name[32];
    -
    -    printf("enter your name: ");
    -    fgets(user_name, 1000, stdin); // get user's name from stdin
    -    printf("hello %s", user_name);
    -    printf("my_perfect_string: %s\n", my_perfect_string);
    -
    -    return 0;
    -}
    -
    - - -

    -now let's try using our new program: -

    - -
    1
    -2
    -3
    -4
    $ ./membug
    -enter your name: jack
    -hello jack
    -my_perfect_string: what a beautiful string
    -
    - -

    -works on my machine boss! code review +1, and merged... until our good friend - -Hubert Blaine Wolfeschlegelsteinhausenbergerdorff Sr. comes along. he emails me a strange -error he's seen: -

    - -
    1
    -2
    -3
    -4
    $ ./membug
    -enter your name: Hubert Blaine Wolfeschlegelsteinhausenbergerdorff Sr.
    -hello Hubert Blaine Wolfeschlegelsteinhausenbergerdorff Sr.
    -my_perfect_string: hausenbergerdorff Sr.
    -
    - -

    -that's not supposed to happen! his name has spilled over into our my_perfect_string[] -array! turns out our issue is that when we use fgets(), we've set the second -parameter, size, to 1000 - but our user_name[32] array c1593an -only fit 32 characters (and the last of these should be a null terminator, so 31 usable characters). -fgets fills up user_name, but it hasn't finished with the name yet! it -doesn't care (or know) that user_name is full, it's just going to keep going until it -finishes our user input, or reads 999 characters from standard input. and thus it keeps mindlessly -writing, overwriting the memory we've used to store our precious perfect string (which happens to -be immediately after user_name). let's take a look at the stack in GDB to see why this -happens: -

    - -
     1
    - 2
    - 3
    - 4
    - 5
    - 6
    - 7
    - 8
    - 9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    (gdb) b memdebug.c:7 
    -(gdb) run 
    -Breakpoint 1, main () at membug.c:7
    -7           printf("enter your name: "); 
    -(gdb) n
    -8           fgets(user_name, 1000, stdin); // get user's name from stdin
    -(gdb) n
    -9           printf("hello %s", user_name);
    -(gdb) x/56bc $sp
    -0x7fffffffdbf0: 106 'j' 97 'a'  99 'c'  107 'k' 10 '\n' 0 '\000'        0 '\000'        0 '\000'
    -0x7fffffffdbf8: 77 'M'  82 'R'  85 'U'  85 'U'  85 'U'  85 'U'  0 '\000'        0 '\000'
    -0x7fffffffdc00: -24 '\350'      -78 '\262'      -5 '\373'       -9 '\367'       -1 '\377'       127 '\177'      0 '\000'        0 '\000'
    -0x7fffffffdc08: 0 '\000'        82 'R'  85 'U'  85 'U'  85 'U'  85 'U'  0 '\000'        0 '\000'
    -0x7fffffffdc10: 119 'w' 104 'h' 97 'a'  116 't' 32 ' '  97 'a'  32 ' '  98 'b'
    -0x7fffffffdc18: 101 'e' 97 'a'  117 'u' 116 't' 105 'i' 102 'f' 117 'u' 108 'l'
    -0x7fffffffdc20: 32 ' '  115 's' 116 't' 114 'r' 105 'i' 110 'n' 103 'g' 0 '\000'
    -
    - -

    -we can see our two character arrays are right next to each other on the stack -(user_name contains some gibberish as it is not zero-initialised. -

    -

    -note: this code was compiled with -fno-stack-protector to reproduce this -behaviour. compilers have certain techniques like this which can help protect against such attacks, -but there are often ways around these by using less primitive attacks. -

    -

    -okay, it's a pretty easy fix, we just need to change the fgets(char *s, int size, FILE *stream) -parameter size to 32. -

    -

    -note: you may initially think "why not 31? don't we need to save a character for -the null byte at the end?". thankfully, fgets does this for us. excerpt from man -fgets: "fgets() reads in at most one less than size characters from stream and stores -them into the buffer pointed to by s [...] A terminating null byte ('\0') is stored after the last -character in the buffer". this is a good question to be asking though, being careful is key when it -comes to these kinds of things. -

    - -

    why hardware?

    -

    -okay, so that's an easy fix. why are we talking about doing anything in hardware here? just write -the code correctly! the issue is code gets very complex, and this is a very simplistic situation. -some memory safety bugs can be incredibly complicated and go unnoticed for decades. the C language -especially gives the programmer many, many opportunities to make mistakes - and it only takes one -to be a problem. a lot of the software we are using these days is based on stacks upon stacks of -software written in different languages, and there are going to be bugs in there. CHERI should -give us some protection "for free" (it's not this simple, in actuality). -

    -

    -some languages (e.g. Rust) are going to offer you strong memory safety guarantees -at compile-time, but that's not the topic of this article. the differences between doing this -kind of protection in software or hardware (or both) is more complex than the scope of this -article. in addition, CHERI's benefits are more wide in breadth than just protecting against this -kind of issue. -

    - -

    pointers recap

    -

    -let's quickly recap a basic idea of what a pointer is. we're going to ignore things like -virtual memory for brevity. we can think -of a pointer in a normal 64-bit architecture (e.g. AArch64) simply as a 64-bit unsigned value that -holds the memory address of something we care about. this is a simplification (as are most things), -but it can help us reason about the general idea: -

    -
    1
    -2
    int val = 1593;
    -int *x = &val; // x points to val
    -
    -int *x0x0000010000000004addressmem[0x0000010000000004]mem[0x0000010000000000]mem[0x0000010000000008]1593memory (as ints) - -

    -and on these normal architectures, this pointer generally is just a number. we can do weird things -with it, treating it as a number... -

    -
     1
    - 2
    - 3
    - 4
    - 5
    - 6
    - 7
    - 8
    - 9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    #include <stdio.h>
    -
    -int main() {
    -    int magic = 9999;
    -    int arr[] = { 1234, 5678 };
    -
    -    int *x = &(arr[0]); // x is a pointer to first element of arr
    -    printf("*x=%d\n", *x);
    -
    -    unsigned long x_addr = (size_t) x; // we're going to assume size_t = unsigned long here
    -    x_addr += 4; // sizeof(int) == 4
    -    x = (int *) x_addr;
    -    printf("*x=%d\n", *x);
    -    
    -    x_addr += 4;
    -    x = (int *) x_addr;
    -    printf("*x=%d\n", *x);
    -
    -    return 0;
    -}
    -
    - -

    ...and this code will often still work:

    -
    1
    -2
    -3
    -4
    $ ./ptrs_as_numbers
    -*x=1234
    -*x=5678
    -*x=9999
    -
    - -

    -yikes! now, when you start messing with pointers like this, you're bound to run into a bunch of -undefined behaviour. but C programmers write undefined behaviour all the time, and my computer -executes this program fine without complaining at all. doesn't it feel a bit weird that we can take -a pointer to arr[0] and modify it to load secret? they're not even part -of the same array... -

    - -

    introducting capabilities

    -

    -CHERI introduces capabilities, which can be thought of as an extension to pointers. they still -store an address of something we care about, but they have extra information too! in a 64-bit -system, a pointer would typically be a 64-bit value (as dicussed previously). the corresponding -capability in a CHERI platform is 128 bits (or 129 bits if you look at it a certain way, more about -that later...). -

    -

    -as you might have guessed, this "extra information" takes up 64 bits of the capability. bits are -assigned to three key pieces of metadata: bounds, permissions, and -object type. there is also an additional 1-bit tag which is stored out-of-band: it is -not a 129-bit value - instead each 128-bit capability can be thought of as being associated with a -1-bit validity tag. the architecture manages this. the diagram below is provided as a rough -overview of this. note that it is not to scale. -

    -int *x (capability)0x0000010000000004addressboundsobject typepermissionstag (out-of-band) - -

    -I am mostly going to focus on bounds in this article, as it is not too difficult to grasp, -and the impact is fairly easy to demonstrate for some simple examples. the bounds represent an -upper and lower bound on the memory region (address space) that this capability is allowed to -access. if we try to use the capability to access some address outside of this range, the hardware -will throw a fault - it simply won't let us do this! -

    -

    -note: it is important to note that I am going to oversimplify the way the bounds are -stored in this article. this especially includes the diagram above. in reality, there is a complex -compression method, necessitated by the range and sizes required by bounds. this depends on the -address value, alignment, etc. for now, we shouldn't need to think about this much, just know it -will be managed for us. the key take-away from this is that bounds can't always be 100% precise -for all addresses and ranges. -

    -

    -can you imagine how we can use bounds to prevent our previous memory safety bug from occurring? the -key is that we can set the bounds on the capability pointing to user_name which we -pass to fgets, such that the capability may only access the contents of the array. -this means that when fgets tries to write past the end of the user_name -array, the processor will throw a capability fault, and execution of our program will cease. -

    -

    -the idea behind CHERI is that we don't have to set up these bounds ourselves. this is something the -compiler can generate code for. the compiler knows that the user_name array has a -length of 32, and can set the bounds accordingly on capabilities created that point to -it. let's try it... -

    - -

    playing with CHERI RISC-V

    -

    -unless you're lucky enough to have access to a physical Morello board, there is the issue of -actually using a CHERI implementation. for this article I will be making use of the -QEMU emulator to emulate a -RISC-V CHERI environment. running -CheriBSD on this emulator will allow us to have a nice -FreeBSD-based capability-enabled environment to play around -with. I'll use cheribuild to easily get set -up: -

    -
     1
    - 2
    - 3
    - 4
    - 5
    - 6
    - 7
    - 8
    - 9
    -10
    $ sudo apt install autoconf automake libtool pkg-config clang bison cmake \
    -ninja-build samba flex texinfo time libglib2.0-dev libpixman-1-dev \
    -libarchive-dev libarchive-tools libbz2-dev libattr1-dev libcap-ng-dev
    -$ git clone git@github.com:CTSRD-CHERI/cheribuild
    -$ cd cheribuild
    -$ ./cheribuild.py --include-dependencies --run/ssh-forwarding-port 2222 run-riscv64-purecap 
    -CheriBSD/riscv (cheribsd-riscv64-purecap) (ttyu0)
    -
    -login: root
    -root@cheribsd-riscv64-purecap:~ #
    -
    - -

    -now we have our shell inside our CheriBSD emulated platform, we can start to try things out. let's -compile our membug program again, this time with the toolchain targetting -CheriBSD RISC-V - this will have been built as part of the dependencies already. once it's built, -we can scp it over to the CheriBSD filesystem, as we set up the SSH forwarding port to -1111. -

    -
    1
    -2
    -3
    # on a separate terminal on your host machine
    -$ ~/cheri/output/sdk/utils/cheribsd-riscv64-purecap-clang membug.c -Wall -g -fno-stack-protector -o membug-cheribsd
    -$ scp -P 2222 ./membug-cheribsd root@localhost:~/
    -
    - - -

    -and now we can see what happens when we explore our bug with CHERI: -

    -
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    $./membug-cheribsd
    -enter your name: jack
    -hello jack
    -my_perfect_string: what a beautiful string
    -
    -$ ./membug-cheribsd
    -enter your name: Hubert Blaine Wolfeschlegelsteinhausenbergerdorff Sr.
    -In-address space security exception (core dumped)
    -
    -

    -it's working! we are getting a capability fault as we exceed the bounds of the -user_name capability bounds. we can use gdb to verify this is -caused by the bounds fault: -

    - -
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    (gdb) run
    -Starting program: /root/membug-cheribsd 
    -enter your name: Hubert Blaine Wolfeschlegelsteinhausenbergerdorff Sr.
    -
    -Program received signal SIGPROT, CHERI protection violation.
    -Capability bounds fault caused by register ca6.
    -0x0000000040314ce8 in memcpy (dst0=0x3fffdfff44, src0=<optimized out>, length=54) at /home/jack/cheri/cheribsd/lib/libc/string/bcopy.c:143
    -(gdb) p $ca6
    -$1 = () 0x3fffdfff78 [rwRW,0x3fffdfff44-0x3fffdfff64]
    -
    -

    -as we can see, the bounds for our user_name capability (which is stored in capability -register ca6) are 0x3fffdfff44-0x3fffdfff64, but the address is -0x3fffdfff78. this is out of the bounds allowed by the capability, so the architecture -throws a fault. if we look at the assembly generated by the compiler, we can see it set our -capability bounds to a size of 32 to enforce this behaviour: -

    -
     1
    - 2
    - 3
    - 4
    - 5
    - 6
    - 7
    - 8
    - 9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    0000000000001ce8 <main>:
    -; int main() {
    -    1ce8: 5b 11 01 f6  	cincoffset	csp, csp, -160
    -    1cec: 23 48 11 08  	csc	cra, 144(csp)
    -    1cf0: 23 40 81 08  	csc	cs0, 128(csp)
    -    1cf4: 5b 14 01 0a  	cincoffset	cs0, csp, 160
    -    1cf8: 5b 15 c4 fd  	cincoffset	ca0, cs0, -36
    -    1cfc: 5b 26 45 00  	csetbounds	ca2, ca0, 4
    -    1d00: 5b 15 44 fc  	cincoffset	ca0, cs0, -60
    -    1d04: 5b 25 85 01  	csetbounds	ca0, ca0, 24
    -    1d08: 23 40 a4 f8  	csc	ca0, -128(cs0)
    -    1d0c: db 15 44 fa  	cincoffset	ca1, cs0, -92
    -    1d10: db a5 05 02  	csetbounds	ca1, ca1, 32
    -    1d14: 23 48 b4 f6  	csc	ca1, -144(cs0)
    -    1d18: 81 45        	mv	a1, zero
    -    1d1a: 23 3c b4 f8  	csd	a1, -104(cs0)
    -    1d1e: 23 20 b6 00  	csw	a1, 0(ca2)
    -
    - -

    capability monotonicity

    -

    -at this point you may be thinking "okay, that's great, but if we can just set -the bounds of a capability with an instruction then what's the point? surely -I can just set global bounds on some random pointer and access whatever I want?" -

    -

    -fundamental to the idea of capabilities is their provenance and -monotonicity. simply put, the first says we can only construct a -capability using specific instructions, from an existing capability. we can't -just create a capability from some random number. let's see what happens when -we try to run our ptrs_as_numbers program on CheriBSD: -

    -
     1
    - 2
    - 3
    - 4
    - 5
    - 6
    - 7
    - 8
    - 9
    -10
    (gdb) run
    -Starting program: /root/ptrs_as_numbers-cheribsd 
    -*x=1234
    -
    -Program received signal SIGPROT, CHERI protection violation.
    -Capability tag fault caused by register ca1.
    -0x0000000000101c66 in main () at ptrs_as_numbers.c:14
    -14          printf("*x=%d\n", *x);
    -(gdb) p $ca1
    -$1 = () 0x3fffdfff74
    -
    - -

    -we can see we get a fault - the tag isn't set. any capability with a tag not -set to 1 cannot be dereferenced - it is invalid. in fact, this capability has -no capability metadata - when we copied it into our unsigned long, -we just copied the 64-bit address. -

    -

    -monotonicity is what stops us taking an existing capability, and -creating a capability with more permissions and/or access than the original. it -stipulates that when we create a capability from another capability (which we -have to do - provenance), the permissions and bounds of the new capability must -be equal to or less than the original. so our bounds can only get narrower as -we create new capabilites from an existing capability. this means that -capabilities trace back in a chain - they are all created from other -capabilities, and narrowed as necessary. in this case, (simplified) when the -kernel loads our program it will give us capabilities that are wide enough to -do everything we need to do, and the compiler will try and make sure all the -capabilities that we make and use from these are as tightly bound and -unpermissive as possible. -

    -

    CHERI-fying code

    -

    -you'll notice we got a lot of these benefits "for free". we only had to -recompile our code, and we got this extra security. of course, CHERI does -require changes to programs. naturally, the compiler had to be changed a lot to -implement this behaviour. it also especially requires changes to things like -the C library and kernel in order to take advantage of the features fully. -sufficiently large userspace programs do need changes too. one common issue is -that a lot of existing C code assumes that -sizeof (*void) == sizeof(size_t). with CHERI, our pointers are -now twice as big. however, size_t hasn't changed size, as the -address space size hasn't changed - for example, if we index into an array with -size_t, the index should still be the same size; the extra data in -our void * capability is the metadata, not extra address data. any -program that tries to convert from some unsigned long or -size_t to a capability will fault - this violates provenance. so, -sometimes code changes have to be made to ensure we are keeping the capability -metadata around. -

    - -

    epilogue

    -

    -I appreciate this has been a fragmented and surface level introduction to -CHERI. hopefully it has provided some education in some basic aims of CHERI -regardless. potential benefits and uses for CHERI go much deeper than anything -I've touched on here, so please, read more about everything - and get your -hands dirty trying out messing about with qemu and CheriBSD! -

    -

    -here are some links to check out: -

    -

    -
    - - - \ No newline at end of file diff --git a/assets/css/main.scss b/assets/css/main.scss new file mode 100644 index 0000000..9f41894 --- /dev/null +++ b/assets/css/main.scss @@ -0,0 +1,4 @@ +--- +--- + +@import "main"; diff --git a/assets/css/pygments.css b/assets/css/pygments.css new file mode 100644 index 0000000..a881278 --- /dev/null +++ b/assets/css/pygments.css @@ -0,0 +1,444 @@ +pre { + font-size: 1.25rem; + margin-top: 0; + vertical-align: top; +} + +figure.highlight { + margin: 0; + margin-left: 1.5rem; +} + +.rouge-table { + display: block; + overflow-x: auto; +} + +td.gutter { + padding-right: 10px; + border-right: 3px solid rgb(252, 169, 184); + border-radius: 3px; +} + +td.code { + padding-left: 15px; +} + +body .hll { + background-color: #6e7681 +} + +body .c { + color: #8b949e; + font-style: italic +} + +/* Comment */ +body .err { + color: #f85149 +} + +/* Error */ +body .esc { + color: #c9d1d9 +} + +/* Escape */ +body .g { + color: #c9d1d9 +} + +/* Generic */ +body .k { + color: #ff7b72 +} + +/* Keyword */ +body .l { + color: #a5d6ff +} + +/* Literal */ +body .n { + color: #c9d1d9 +} + +/* Name */ +body .o { + color: #ff7b72; + font-weight: bold +} + +/* Operator */ +body .x { + color: #c9d1d9 +} + +/* Other */ +body .p { + color: #c9d1d9 +} + +/* Punctuation */ +body .ch { + color: #8b949e; + font-style: italic +} + +/* Comment.Hashbang */ +body .cm { + color: #8b949e; + font-style: italic +} + +/* Comment.Multiline */ +body .cp { + color: #8b949e; + font-weight: bold; + font-style: italic +} + +/* Comment.Preproc */ +body .cpf { + color: #8b949e; + font-style: italic +} + +/* Comment.PreprocFile */ +body .c1 { + color: #8b949e; + font-style: italic +} + +/* Comment.Single */ +body .cs { + color: #8b949e; + font-weight: bold; + font-style: italic +} + +/* Comment.Special */ +body .gd { + color: #ffa198; + background-color: #490202 +} + +/* Generic.Deleted */ +body .ge { + color: #c9d1d9; + font-style: italic +} + +/* Generic.Emph */ +body .gr { + color: #ffa198 +} + +/* Generic.Error */ +body .gh { + color: #79c0ff; + font-weight: bold +} + +/* Generic.Heading */ +body .gi { + color: #56d364; + background-color: #0f5323 +} + +/* Generic.Inserted */ +body .go { + color: #8b949e +} + +/* Generic.Output */ +body .gp { + color: #8b949e +} + +/* Generic.Prompt */ +body .gs { + color: #c9d1d9; + font-weight: bold +} + +/* Generic.Strong */ +body .gu { + color: #79c0ff +} + +/* Generic.Subheading */ +body .gt { + color: #ff7b72 +} + +/* Generic.Traceback */ +body .g-Underline { + color: #c9d1d9; + text-decoration: underline +} + +/* Generic.Underline */ +body .kc { + color: #79c0ff +} + +/* Keyword.Constant */ +body .kd { + color: #ff7b72 +} + +/* Keyword.Declaration */ +body .kn { + color: #ff7b72 +} + +/* Keyword.Namespace */ +body .kp { + color: #79c0ff +} + +/* Keyword.Pseudo */ +body .kr { + color: #ff7b72 +} + +/* Keyword.Reserved */ +body .kt { + color: #ff7b72 +} + +/* Keyword.Type */ +body .ld { + color: #79c0ff +} + +/* Literal.Date */ +body .m { + color: #a5d6ff +} + +/* Literal.Number */ +body .s { + color: #a5d6ff +} + +/* Literal.String */ +body .na { + color: #c9d1d9 +} + +/* Name.Attribute */ +body .nb { + color: #c9d1d9 +} + +/* Name.Builtin */ +body .nc { + color: #f0883e; + font-weight: bold +} + +/* Name.Class */ +body .no { + color: #79c0ff; + font-weight: bold +} + +/* Name.Constant */ +body .nd { + color: #d2a8ff; + font-weight: bold +} + +/* Name.Decorator */ +body .ni { + color: #ffa657 +} + +/* Name.Entity */ +body .ne { + color: #f0883e; + font-weight: bold +} + +/* Name.Exception */ +body .nf { + color: #d2a8ff; + font-weight: bold +} + +/* Name.Function */ +body .nl { + color: #79c0ff; + font-weight: bold +} + +/* Name.Label */ +body .nn { + color: #ff7b72 +} + +/* Name.Namespace */ +body .nx { + color: #c9d1d9 +} + +/* Name.Other */ +body .py { + color: #79c0ff +} + +/* Name.Property */ +body .nt { + color: #7ee787 +} + +/* Name.Tag */ +body .nv { + color: #79c0ff +} + +/* Name.Variable */ +body .ow { + color: #ff7b72; + font-weight: bold +} + +/* Operator.Word */ +body .pm { + color: #c9d1d9 +} + +/* Punctuation.Marker */ +body .w { + color: #6e7681 +} + +/* Text.Whitespace */ +body .mb { + color: #a5d6ff +} + +/* Literal.Number.Bin */ +body .mf { + color: #a5d6ff +} + +/* Literal.Number.Float */ +body .mh { + color: #a5d6ff +} + +/* Literal.Number.Hex */ +body .mi { + color: #a5d6ff +} + +/* Literal.Number.Integer */ +body .mo { + color: #a5d6ff +} + +/* Literal.Number.Oct */ +body .sa { + color: #79c0ff +} + +/* Literal.String.Affix */ +body .sb { + color: #a5d6ff +} + +/* Literal.String.Backtick */ +body .sc { + color: #a5d6ff +} + +/* Literal.String.Char */ +body .dl { + color: #79c0ff +} + +/* Literal.String.Delimiter */ +body .sd { + color: #a5d6ff +} + +/* Literal.String.Doc */ +body .s2 { + color: #a5d6ff +} + +/* Literal.String.Double */ +body .se { + color: #79c0ff +} + +/* Literal.String.Escape */ +body .sh { + color: #79c0ff +} + +/* Literal.String.Heredoc */ +body .si { + color: #a5d6ff +} + +/* Literal.String.Interpol */ +body .sx { + color: #a5d6ff +} + +/* Literal.String.Other */ +body .sr { + color: #79c0ff +} + +/* Literal.String.Regex */ +body .s1 { + color: #a5d6ff +} + +/* Literal.String.Single */ +body .ss { + color: #a5d6ff +} + +/* Literal.String.Symbol */ +body .bp { + color: #c9d1d9 +} + +/* Name.Builtin.Pseudo */ +body .fm { + color: #d2a8ff; + font-weight: bold +} + +/* Name.Function.Magic */ +body .vc { + color: #79c0ff +} + +/* Name.Variable.Class */ +body .vg { + color: #79c0ff +} + +/* Name.Variable.Global */ +body .vi { + color: #79c0ff +} + +/* Name.Variable.Instance */ +body .vm { + color: #79c0ff +} + +/* Name.Variable.Magic */ +body .il { + color: #a5d6ff +} + +/* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/assets/fonts/source-code-pro-v22-latin-ext_latin-700.woff b/assets/fonts/source-code-pro-v22-latin-ext_latin-700.woff new file mode 100644 index 0000000..8fbdce0 Binary files /dev/null and b/assets/fonts/source-code-pro-v22-latin-ext_latin-700.woff differ diff --git a/assets/fonts/source-code-pro-v22-latin-ext_latin-700.woff2 b/assets/fonts/source-code-pro-v22-latin-ext_latin-700.woff2 new file mode 100644 index 0000000..7b15f1c Binary files /dev/null and b/assets/fonts/source-code-pro-v22-latin-ext_latin-700.woff2 differ diff --git a/assets/fonts/source-code-pro-v22-latin-ext_latin-700italic.woff b/assets/fonts/source-code-pro-v22-latin-ext_latin-700italic.woff new file mode 100644 index 0000000..50e0235 Binary files /dev/null and b/assets/fonts/source-code-pro-v22-latin-ext_latin-700italic.woff differ diff --git a/assets/fonts/source-code-pro-v22-latin-ext_latin-700italic.woff2 b/assets/fonts/source-code-pro-v22-latin-ext_latin-700italic.woff2 new file mode 100644 index 0000000..ea2f84d Binary files /dev/null and b/assets/fonts/source-code-pro-v22-latin-ext_latin-700italic.woff2 differ diff --git a/assets/fonts/source-code-pro-v22-latin-ext_latin-italic.woff b/assets/fonts/source-code-pro-v22-latin-ext_latin-italic.woff new file mode 100644 index 0000000..8db160d Binary files /dev/null and b/assets/fonts/source-code-pro-v22-latin-ext_latin-italic.woff differ diff --git a/assets/fonts/source-code-pro-v22-latin-ext_latin-italic.woff2 b/assets/fonts/source-code-pro-v22-latin-ext_latin-italic.woff2 new file mode 100644 index 0000000..6d680fb Binary files /dev/null and b/assets/fonts/source-code-pro-v22-latin-ext_latin-italic.woff2 differ diff --git a/assets/fonts/source-code-pro-v22-latin-ext_latin-regular.woff b/assets/fonts/source-code-pro-v22-latin-ext_latin-regular.woff new file mode 100644 index 0000000..5a975d1 Binary files /dev/null and b/assets/fonts/source-code-pro-v22-latin-ext_latin-regular.woff differ diff --git a/assets/fonts/source-code-pro-v22-latin-ext_latin-regular.woff2 b/assets/fonts/source-code-pro-v22-latin-ext_latin-regular.woff2 new file mode 100644 index 0000000..6dab02e Binary files /dev/null and b/assets/fonts/source-code-pro-v22-latin-ext_latin-regular.woff2 differ diff --git a/assets/images/link.svg b/assets/images/link.svg new file mode 100644 index 0000000..0f81b34 --- /dev/null +++ b/assets/images/link.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/images/sensor-watch/f91w-strap.svg b/assets/images/sensor-watch/f91w-strap.svg new file mode 100644 index 0000000..a5e0112 --- /dev/null +++ b/assets/images/sensor-watch/f91w-strap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/sensor-watch/f91w.svg b/assets/images/sensor-watch/f91w.svg new file mode 100644 index 0000000..19476c8 --- /dev/null +++ b/assets/images/sensor-watch/f91w.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/index.html b/index.html deleted file mode 100644 index 592f0ab..0000000 --- a/index.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - jack bond-preston - - - - - - - - - - - -

    - jack bond‐preston -

    - -

    contact

    -

    - you can contact me via email or on linkedin -

    -

    - my cv is available for viewing here -

    - -

    open source

    -

    - i have personal accounts on github and gitlab -

    -

    - some of my work at arm on morello is available on the morello musl gitlab -

    -

    - my onload commits at amd can be found on the github repo -

    - -

    articles

    -

    - [14/11/2022] sensor watch -

    - - - - diff --git a/index.md b/index.md new file mode 100644 index 0000000..b818db6 --- /dev/null +++ b/index.md @@ -0,0 +1,32 @@ +--- +layout: default +title: jack bond-preston +--- + +# jack bond-preston + +## contact +you can contact me via [email](mailto:jackbondpreston@outlook.com) or on [linkedin](https://www.linkedin.com/in/jack-bond-preston-922706150/) + +my cv is available for viewing [here](cv.pdf). + +## open source + +i have personal accounts on [github](https://github.com/jackbondpreston) and [gitlab](https://gitlab.com/jackbondpreston) + + +some of my work at arm on [morello](https://www.arm.com/architecture/cpu/morello) is available on the +d [morello musl gitlab](https://git.morello-project.org/morello/musl-libc/-/commits/morello/master?author=Jack%20Bond-Preston) + + +my [onload](https://www.xilinx.com/products/boards-and-kits/x2-series/onload.html) commits at amd can be found on [the github repo](https://github.com/Xilinx-CNS/onload/commits?author=jbondpre-amd) + + +## articles + +{% for post in site.posts %} +
  • + [{{ post.date | date: "%d/%m/%Y" }}] {{ post.title }} +
  • +{% endfor %} + diff --git a/pictures/sensor-watch/c7c8.jpg b/pictures/sensor-watch/c7c8.jpg new file mode 100644 index 0000000..0ba34d2 Binary files /dev/null and b/pictures/sensor-watch/c7c8.jpg differ diff --git a/pictures/sensor-watch/pcb.jpg b/pictures/sensor-watch/pcb.jpg new file mode 100644 index 0000000..ae4261f Binary files /dev/null and b/pictures/sensor-watch/pcb.jpg differ diff --git a/pictures/sensor-watch/watch1.jpg b/pictures/sensor-watch/watch1.jpg new file mode 100644 index 0000000..f5bc8fd Binary files /dev/null and b/pictures/sensor-watch/watch1.jpg differ diff --git a/pictures/sensor-watch/watch2.jpg b/pictures/sensor-watch/watch2.jpg new file mode 100644 index 0000000..2071c94 Binary files /dev/null and b/pictures/sensor-watch/watch2.jpg differ diff --git a/pictures/sensor-watch/wrist.jpg b/pictures/sensor-watch/wrist.jpg new file mode 100644 index 0000000..7d3737a Binary files /dev/null and b/pictures/sensor-watch/wrist.jpg differ diff --git a/regexes b/regexes new file mode 100644 index 0000000..84f5389 --- /dev/null +++ b/regexes @@ -0,0 +1,11 @@ +([\w \n]+) +[$2]($1) + +\[([^\]]*)\n +[$1 + +

    ([^<]+)

    +## $1 + +

    ([^<]+)

    +### $1 diff --git a/style/stylesheet.css b/style/stylesheet.css deleted file mode 100644 index 411b4ce..0000000 --- a/style/stylesheet.css +++ /dev/null @@ -1,69 +0,0 @@ -@font-face { - font-family: TeXGyreCursor; - src: url('texgyrecursor-regular.woff2') format('woff2'), - url('texgyrecursor-regular.woff') format('woff'); - font-weight: normal; - font-style: normal; - -} - -@font-face { - font-family: TeXGyreCursor; - src: url('texgyrecursor-bold.woff2') format('woff2'), - url('texgyrecursor-bold.woff') format('woff'); - font-weight: bold; - font-style: normal; -} - -body { - background-color: rgb(12, 17, 20); - color: rgb(252, 252, 252); - padding-left: 5vw; - padding-right: 5vw; - padding-top: 5vh; - font-family: TeXGyreCursor; - font-size: 1.5rem; -} - -h1 { - color: rgb(255, 182, 193); - margin: 0; -} - -h2 { - margin: 0; - margin-top: 3rem; - margin-bottom: 0.5rem; -} - -a { - color: rgb(252, 169, 184); - font-weight: bold; - text-decoration: none; -} - -.article p a, .article li a { - font-weight: normal; - text-decoration: underline; - word-wrap: break-word; -} - -.article p img { - max-width: 100%; - display: block; -} - -code, pre { - font-family: TeXGyreCursor; - margin: 0; - padding: 0; -} - -p code { - font-size: 1.5rem; - color: #a5d6ff; -} - -table { - border-spacing: 0; -} \ No newline at end of file diff --git a/style/texgyrecursor-bold.woff b/style/texgyrecursor-bold.woff deleted file mode 100644 index a57451b..0000000 Binary files a/style/texgyrecursor-bold.woff and /dev/null differ diff --git a/style/texgyrecursor-bold.woff2 b/style/texgyrecursor-bold.woff2 deleted file mode 100644 index 047b659..0000000 Binary files a/style/texgyrecursor-bold.woff2 and /dev/null differ diff --git a/style/texgyrecursor-regular.woff b/style/texgyrecursor-regular.woff deleted file mode 100644 index 18cd4d3..0000000 Binary files a/style/texgyrecursor-regular.woff and /dev/null differ diff --git a/style/texgyrecursor-regular.woff2 b/style/texgyrecursor-regular.woff2 deleted file mode 100644 index e97ecd6..0000000 Binary files a/style/texgyrecursor-regular.woff2 and /dev/null differ