www/blog.hillion.co.uk/posts/weekly-2022-01-03/index.html
2024-01-13 14:16:56 +00:00

13 lines
31 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html><html lang=en dir=auto><head><meta charset=utf-8><meta http-equiv=x-ua-compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name=robots content="index, follow"><title>Jake's Weekly - 3rd Jan 2022 | Jake Hillion</title><meta name=keywords content><meta name=description content="Research Project Process Isolation Setup a Fedora testing VM for easier and consistent testing.
Fedora 35 uses pure cgroups2 by default - very useful! Sorted out backups for the repo and the above machine. Chose a testing framework for C enabling testing of the assertions to build the project upon.
Used Unity. Simple and the examples show that it doesn&rsquo;t do much beyond the minimum - important for this low level code with syscalls."><meta name=author content="Jake Hillion"><link rel=canonical href=https://blog.hillion.co.uk/posts/weekly-2022-01-03/><link crossorigin=anonymous href=/assets/css/stylesheet.min.48a18943c2fc15c38a372b8dde1f5e5dc0bc64fa6cb90f5a817d2f8c76b7f3ae.css integrity="sha256-SKGJQ8L8FcOKNyuN3h9eXcC8ZPpsuQ9agX0vjHa3864=" rel="preload stylesheet" as=style><script defer crossorigin=anonymous src=/assets/js/highlight.min.b95bacdc39e37a332a9f883b1e78be4abc1fdca2bc1f2641f55e3cd3dabd4d61.js integrity="sha256-uVus3DnjejMqn4g7Hni+Srwf3KK8HyZB9V4809q9TWE=" onload=hljs.initHighlightingOnLoad()></script>
<link rel=icon href=https://blog.hillion.co.uk/favicon.ico><link rel=icon type=image/png sizes=16x16 href=https://blog.hillion.co.uk/favicon-16x16.png><link rel=icon type=image/png sizes=32x32 href=https://blog.hillion.co.uk/favicon-32x32.png><link rel=apple-touch-icon href=https://blog.hillion.co.uk/apple-touch-icon.png><link rel=mask-icon href=https://blog.hillion.co.uk/safari-pinned-tab.svg><meta name=theme-color content="#2e2e33"><meta name=msapplication-TileColor content="#2e2e33"><noscript><style>#theme-toggle,.top-link{display:none}</style><style>@media(prefers-color-scheme:dark){:root{--theme:rgb(29, 30, 32);--entry:rgb(46, 46, 51);--primary:rgb(218, 218, 219);--secondary:rgb(155, 156, 157);--tertiary:rgb(65, 66, 68);--content:rgb(196, 196, 197);--hljs-bg:rgb(46, 46, 51);--code-bg:rgb(55, 56, 62);--border:rgb(51, 51, 51)}.list{background:var(--theme)}.list:not(.dark)::-webkit-scrollbar-track{background:0 0}.list:not(.dark)::-webkit-scrollbar-thumb{border-color:var(--theme)}}</style></noscript><script async src="https://www.googletagmanager.com/gtag/js?id=G-4CXXF49E7M"></script>
<script>var doNotTrack=!1;if(!doNotTrack){window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments)}gtag("js",new Date),gtag("config","G-4CXXF49E7M",{anonymize_ip:!1})}</script><meta property="og:title" content="Jake's Weekly - 3rd Jan 2022"><meta property="og:description" content="Research Project Process Isolation Setup a Fedora testing VM for easier and consistent testing.
Fedora 35 uses pure cgroups2 by default - very useful! Sorted out backups for the repo and the above machine. Chose a testing framework for C enabling testing of the assertions to build the project upon.
Used Unity. Simple and the examples show that it doesn&rsquo;t do much beyond the minimum - important for this low level code with syscalls."><meta property="og:type" content="article"><meta property="og:url" content="https://blog.hillion.co.uk/posts/weekly-2022-01-03/"><meta property="article:section" content="posts"><meta property="article:published_time" content="2022-01-01T11:00:00+00:00"><meta property="article:modified_time" content="2022-01-01T11:00:00+00:00"><meta property="og:site_name" content="Jake Hillion"><meta name=twitter:card content="summary"><meta name=twitter:title content="Jake's Weekly - 3rd Jan 2022"><meta name=twitter:description content="Research Project Process Isolation Setup a Fedora testing VM for easier and consistent testing.
Fedora 35 uses pure cgroups2 by default - very useful! Sorted out backups for the repo and the above machine. Chose a testing framework for C enabling testing of the assertions to build the project upon.
Used Unity. Simple and the examples show that it doesn&rsquo;t do much beyond the minimum - important for this low level code with syscalls."><script type=application/ld+json>{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Posts","item":"https://blog.hillion.co.uk/posts/"},{"@type":"ListItem","position":2,"name":"Jake's Weekly - 3rd Jan 2022","item":"https://blog.hillion.co.uk/posts/weekly-2022-01-03/"}]}</script><script type=application/ld+json>{"@context":"https://schema.org","@type":"BlogPosting","headline":"Jake's Weekly - 3rd Jan 2022","name":"Jake\u0027s Weekly - 3rd Jan 2022","description":"Research Project Process Isolation Setup a Fedora testing VM for easier and consistent testing.\nFedora 35 uses pure cgroups2 by default - very useful! Sorted out backups for the repo and the above machine. Chose a testing framework for C enabling testing of the assertions to build the project upon.\nUsed Unity. Simple and the examples show that it doesn\u0026rsquo;t do much beyond the minimum - important for this low level code with syscalls.","keywords":[],"articleBody":"Research Project Process Isolation Setup a Fedora testing VM for easier and consistent testing.\nFedora 35 uses pure cgroups2 by default - very useful! Sorted out backups for the repo and the above machine. Chose a testing framework for C enabling testing of the assertions to build the project upon.\nUsed Unity. Simple and the examples show that it doesnt do much beyond the minimum - important for this low level code with syscalls. Forking and cloning doesnt cause any problems as long as each process is reliably exited (not returned from). Began writing assertion tests for the flags of the Linux syscall clone3. Important as many of these have what I consider surprising behaviour going from just the names. clone3 and the resultant processes/namespaces are going to be the majority of process separation in this project.\nCLONE_FS: Links specific bits of filesystem metadata, such as the PWD of the processes.\nImportantly this is cloned in a copy-on-write way regardless of the flag, but the CLONE_FS flag keeps the two processes linked. CLONE_FILES: Links the file descriptor tables of the processes.\nAgain, this is copy-on-write - all fds are inherited without this flag, as the same underlying file descriptors, but this flag ensures that new ones are shared. Tricky to test, as IPC is required to pass the file descriptors around. CLONE_NEWNS: Place a cloned process into a new mount namespace.\nCopy-on-write: has all existing mounts of the parent namespace. Perhaps the solution is to clone twice but give the second clone the original parent? That way the first cloned process can unmount all filesystems in the new namespace, then the new-new namespace will be created with no mounts. Otherwise, unmount in the privileged section before handing off control of the clone. Filesystems marked as shared and mounted under basically ignore the new namespace - the new filesystem is still propagated back. Both my /tmp tmpfs, which Ive been using, and my / root are mounted as shared. This is certainly a tricky one to get my head around. Requires CAP_SYS_ADMIN. CLONE_NEWCGROUP: Place a cloned process into a new cgroup namespace.\nBasically a chroot for the cgroup directory structure. Requires CAP_SYS_ADMIN. CLONE_NEWNET: Place a cloned process into a new network namespace.\nThe new net namespace has only a loopback adapter in it, which is down by default. Though a process only has one network namespace, these can be linked with some work, allowing for pretty complex separation. Requires CAP_SYS_ADMIN. CLONE_NEWPID: Creates a process in a new PID namespace.\nProcess appears with PID 1 in its new namespace (it believes it is the init process). Requires CAP_SYS_ADMIN. CLONE_IO: Have the two processes share an I/O context.\nThis one is going to be particularly tricky to examine in a unit-test like format, so Im saving looking more into it for later. It appears to be solely for performance optimisation, but quite tricky to evaluate. This could perhaps be a stretch task if I can figure out why its useful. CLONE_INTO_CGROUP: Place a cloned process into a specific cgroup.\nThis flag is only supported by the clone3 call, as it requires passing a file descriptor to the cgroup to place the cloned process in. Nothing particularly interesting about this, but it is very useful - the final result of this project will likely use this extensively. CLONE_PARENT: Sets the cloned process parent ID to the cloning processs parent.\nUseful for e.g. cloning twice to clone the second clone into an already empty mount namespace. One can give the new process back to the parent to manage and then kill the intermediary clone. CLONE_PTRACE: Sets the cloned process to be traced if the cloning process is being traced.\nI think this is going to end up being necessary when writing the debugger, as cloned processes will need to be somehow attached to. CLONE_NEWUSER: Place a cloned process into a new user namespace.\nOne of the most useful clone flags, but also one of the most complex. Lets you do things like have the process appear as a variety of users with full capabilities internally, but be limited to an overall user in the external namespace. Lots of work so research incomplete so far. No longer requires any special privileges. Read up on the remaining clone options, which I think are less useful for this project, but Ive summarised them and the reason why briefly. This could change later on.\nCLONE_NEWIPC: Place a cloned process into a new IPC namespace.\nEach process can only be a member of a single IPC namespace, so I think this would be quite challenging to make use of in a non-trivial process layout where each process needs to communicate with more than one other. Requires CAP_SYS_ADMIN. CLONE_NEWUTS: Creates a process in a new UTS (UNIX Timesharing System) namespace.\nLets you change the hostname and domainname without affecting other processes. I cant see this being very useful for the project. Requires CAP_SYS_ADMIN. Up Next Keep writing assertions for the incomplete clone types.\nWrite a tool to get a view of what the process isolation looks like under a parent.\nA debugger than can attach (gdb /bin/bash -p XXX)/directly launch (gdb /bin/bash) would be very useful. Write this in Rust? C++? Or perhaps OCaml? Alongside this debugger, start writing bigger C programs that employ the namespace/cgroup techniques.\nThese will be eventually mapped to OCaml to test for equivalence. Clear structure is going to be far more important in these than in the assertion tests. Modules Digital Signal Processing Extracted an image from a digital recording of an aerial nearby an HDMI cable. ","wordCount":"931","inLanguage":"en","datePublished":"2022-01-01T11:00:00Z","dateModified":"2022-01-01T11:00:00Z","author":{"@type":"Person","name":"Jake Hillion"},"mainEntityOfPage":{"@type":"WebPage","@id":"https://blog.hillion.co.uk/posts/weekly-2022-01-03/"},"publisher":{"@type":"Organization","name":"Jake Hillion","logo":{"@type":"ImageObject","url":"https://blog.hillion.co.uk/favicon.ico"}}}</script></head><body id=top><script>localStorage.getItem("pref-theme")==="dark"?document.body.classList.add("dark"):localStorage.getItem("pref-theme")==="light"?document.body.classList.remove("dark"):window.matchMedia("(prefers-color-scheme: dark)").matches&&document.body.classList.add("dark")</script><header class=header><nav class=nav><div class=logo><a href=https://blog.hillion.co.uk/ accesskey=h title="Jake Hillion (Alt + H)">Jake Hillion</a>
<span class=logo-switches><button id=theme-toggle accesskey=t title="(Alt + T)"><svg id="moon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentcolor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"/></svg><svg id="sun" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentcolor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg></button></span></div><ul id=menu><li><a href=https://blog.hillion.co.uk/categories/ title=categories><span>categories</span></a></li><li><a href=https://blog.hillion.co.uk/tags/ title=tags><span>tags</span></a></li></ul></nav></header><main class=main><article class=post-single><header class=post-header><div class=breadcrumbs><a href=https://blog.hillion.co.uk/>Home</a>&nbsp;»&nbsp;<a href=https://blog.hillion.co.uk/posts/>Posts</a></div><h1 class=post-title>Jake's Weekly - 3rd Jan 2022</h1><div class=post-meta><span title='2022-01-01 11:00:00 +0000 UTC'>January 1, 2022</span>&nbsp;·&nbsp;5 min&nbsp;·&nbsp;Jake Hillion</div></header><div class=post-content><h2 id=research-project>Research Project<a hidden class=anchor aria-hidden=true href=#research-project>#</a></h2><h3 id=process-isolation>Process Isolation<a hidden class=anchor aria-hidden=true href=#process-isolation>#</a></h3><ul><li><p>Setup a Fedora testing VM for easier and consistent testing.</p><ul><li>Fedora 35 uses pure cgroups2 by default - very useful!</li><li>Sorted out backups for the repo and the above machine.</li></ul></li><li><p>Chose a testing framework for C enabling testing of the assertions to build the project upon.</p><ul><li>Used <a href=http://www.throwtheswitch.org/unity>Unity</a>. Simple and the examples show that it doesn&rsquo;t do much beyond the minimum - important for this low level code with syscalls.</li><li>Forking and cloning doesn&rsquo;t cause any problems as long as each process is reliably exited (not returned from).</li></ul></li><li><p>Began writing assertion tests for the flags of the Linux syscall <code>clone3</code>. Important as many of these have what I consider surprising behaviour going from just the names. <code>clone3</code> and the resultant processes/namespaces are going to be the majority of process separation in this project.</p><ul><li><p><a href=https://gitea.hillion.co.uk/JakeHillion/ocaml-cgroups2/src/branch/assertions/assertions/namespaces/fs><code>CLONE_FS</code></a>: Links specific bits of filesystem metadata, such as the PWD of the processes.</p><ul><li>Importantly this is cloned in a copy-on-write way regardless of the flag, but the <code>CLONE_FS</code> flag keeps the two processes linked.</li></ul></li><li><p><a href=https://gitea.hillion.co.uk/JakeHillion/ocaml-cgroups2/src/branch/assertions/assertions/namespaces/files><code>CLONE_FILES</code></a>: Links the file descriptor tables of the processes.</p><ul><li>Again, this is copy-on-write - all fds are inherited without this flag, as the same underlying file descriptors, but this flag ensures that new ones are shared.</li><li>Tricky to test, as IPC is required to pass the file descriptors around.</li></ul></li><li><p><a href=https://gitea.hillion.co.uk/JakeHillion/ocaml-cgroups2/src/branch/assertions/assertions/namespaces/mount><code>CLONE_NEWNS</code></a>: Place a cloned process into a new mount namespace.</p><ul><li>Copy-on-write: has all existing mounts of the parent namespace. Perhaps the solution is to clone twice but give the second clone the original parent? That way the first cloned process can unmount all filesystems in the new namespace, then the new-new namespace will be created with no mounts. Otherwise, unmount in the privileged section before handing off control of the clone.</li><li>Filesystems marked as shared and mounted under basically ignore the new namespace - the new filesystem is still propagated back. Both my <code>/tmp</code> tmpfs, which I&rsquo;ve been using, and my <code>/</code> root are mounted as shared. This is certainly a tricky one to get my head around.</li><li>Requires <code>CAP_SYS_ADMIN</code>.</li></ul></li><li><p><code>CLONE_NEWCGROUP</code>: Place a cloned process into a new cgroup namespace.</p><ul><li>Basically a chroot for the cgroup directory structure.</li><li>Requires <code>CAP_SYS_ADMIN</code>.</li></ul></li><li><p><code>CLONE_NEWNET</code>: Place a cloned process into a new network namespace.</p><ul><li>The new net namespace has only a loopback adapter in it, which is down by default.</li><li>Though a process only has one network namespace, these can be linked with some work, allowing for pretty complex separation.</li><li>Requires <code>CAP_SYS_ADMIN</code>.</li></ul></li><li><p><code>CLONE_NEWPID</code>: Creates a process in a new PID namespace.</p><ul><li>Process appears with PID 1 in its new namespace (it believes it is the init process).</li><li>Requires <code>CAP_SYS_ADMIN</code>.</li></ul></li><li><p><code>CLONE_IO</code>: Have the two processes share an I/O context.</p><ul><li>This one is going to be particularly tricky to examine in a unit-test like format, so I&rsquo;m saving looking more into it for later.</li><li>It appears to be solely for performance optimisation, but quite tricky to evaluate. This could perhaps be a stretch task if I can figure out why it&rsquo;s useful.</li></ul></li><li><p><code>CLONE_INTO_CGROUP</code>: Place a cloned process into a specific cgroup.</p><ul><li>This flag is only supported by the <code>clone3</code> call, as it requires passing a file descriptor to the cgroup to place the cloned process in.</li><li>Nothing particularly interesting about this, but it is very useful - the final result of this project will likely use this extensively.</li></ul></li><li><p><code>CLONE_PARENT</code>: Sets the cloned process parent ID to the cloning process&rsquo;s parent.</p><ul><li>Useful for e.g. cloning twice to clone the second clone into an already empty mount namespace. One can give the new process back to the parent to manage and then kill the intermediary clone.</li></ul></li><li><p><code>CLONE_PTRACE</code>: Sets the cloned process to be traced if the cloning process is being traced.</p><ul><li>I think this is going to end up being necessary when writing the debugger, as cloned processes will need to be somehow attached to.</li></ul></li><li><p><code>CLONE_NEWUSER</code>: Place a cloned process into a new user namespace.</p><ul><li>One of the most useful clone flags, but also one of the most complex.</li><li>Lets you do things like have the process appear as a variety of users with full capabilities internally, but be limited to an overall user in the external namespace.</li><li>Lots of work so research incomplete so far.</li><li>No longer requires any special privileges.</li></ul></li></ul></li><li><p>Read up on the remaining clone options, which I think are less useful for this project, but I&rsquo;ve summarised them and the reason why briefly. This could change later on.</p><ul><li><p><code>CLONE_NEWIPC</code>: Place a cloned process into a new IPC namespace.</p><ul><li>Each process can only be a member of a single IPC namespace, so I think this would be quite challenging to make use of in a non-trivial process layout where each process needs to communicate with more than one other.</li><li>Requires <code>CAP_SYS_ADMIN</code>.</li></ul></li><li><p><code>CLONE_NEWUTS</code>: Creates a process in a new UTS (UNIX Timesharing System) namespace.</p><ul><li>Lets you change the hostname and domainname without affecting other processes. I can&rsquo;t see this being very useful for the project.</li><li>Requires <code>CAP_SYS_ADMIN</code>.</li></ul></li></ul></li></ul><h3 id=up-next>Up Next<a hidden class=anchor aria-hidden=true href=#up-next>#</a></h3><ul><li><p>Keep writing assertions for the incomplete clone types.</p></li><li><p>Write a tool to get a view of what the process isolation looks like under a parent.</p><ul><li>A debugger than can attach (<code>gdb /bin/bash -p XXX</code>)/directly launch (<code>gdb /bin/bash</code>) would be very useful.</li><li>Write this in Rust? C++? Or perhaps OCaml?</li></ul></li><li><p>Alongside this debugger, start writing bigger C programs that employ the namespace/cgroup techniques.</p><ul><li>These will be eventually mapped to OCaml to test for equivalence.</li><li>Clear structure is going to be far more important in these than in the assertion tests.</li></ul></li></ul><h2 id=modules>Modules<a hidden class=anchor aria-hidden=true href=#modules>#</a></h2><h3 id=digital-signal-processing>Digital Signal Processing<a hidden class=anchor aria-hidden=true href=#digital-signal-processing>#</a></h3><ul><li>Extracted an image from a digital recording of an aerial nearby an HDMI cable.</li></ul></div><footer class=post-footer><nav class=paginav><a class=prev href=https://blog.hillion.co.uk/posts/weekly-2022-01-17/><span class=title>« Prev Page</span><br><span>Jake's Weekly - 17th Jan 2022</span></a></nav><div class=share-buttons><a target=_blank rel="noopener noreferrer" aria-label="share Jake's Weekly - 3rd Jan 2022 on twitter" href="https://twitter.com/intent/tweet/?text=Jake%27s%20Weekly%20-%203rd%20Jan%202022&amp;url=https%3a%2f%2fblog.hillion.co.uk%2fposts%2fweekly-2022-01-03%2f&amp;hashtags="><svg viewBox="0 0 512 512"><path d="M449.446.0C483.971.0 512 28.03 512 62.554v386.892C512 483.97 483.97 512 449.446 512H62.554c-34.524.0-62.554-28.03-62.554-62.554V62.554c0-34.524 28.029-62.554 62.554-62.554h386.892zM195.519 424.544c135.939.0 210.268-112.643 210.268-210.268.0-3.218.0-6.437-.153-9.502 14.406-10.421 26.973-23.448 36.935-38.314-13.18 5.824-27.433 9.809-42.452 11.648 15.326-9.196 26.973-23.602 32.49-40.92-14.252 8.429-30.038 14.56-46.896 17.931-13.487-14.406-32.644-23.295-53.946-23.295-40.767.0-73.87 33.104-73.87 73.87.0 5.824.613 11.494 1.992 16.858-61.456-3.065-115.862-32.49-152.337-77.241-6.284 10.881-9.962 23.601-9.962 37.088.0 25.594 13.027 48.276 32.95 61.456-12.107-.307-23.448-3.678-33.41-9.196v.92c0 35.862 25.441 65.594 59.311 72.49-6.13 1.686-12.72 2.606-19.464 2.606-4.751.0-9.348-.46-13.946-1.38 9.349 29.426 36.628 50.728 68.965 51.341-25.287 19.771-57.164 31.571-91.8 31.571-5.977.0-11.801-.306-17.625-1.073 32.337 21.15 71.264 33.41 112.95 33.41z"/></svg></a><a target=_blank rel="noopener noreferrer" aria-label="share Jake's Weekly - 3rd Jan 2022 on linkedin" href="https://www.linkedin.com/shareArticle?mini=true&amp;url=https%3a%2f%2fblog.hillion.co.uk%2fposts%2fweekly-2022-01-03%2f&amp;title=Jake%27s%20Weekly%20-%203rd%20Jan%202022&amp;summary=Jake%27s%20Weekly%20-%203rd%20Jan%202022&amp;source=https%3a%2f%2fblog.hillion.co.uk%2fposts%2fweekly-2022-01-03%2f"><svg viewBox="0 0 512 512"><path d="M449.446.0C483.971.0 512 28.03 512 62.554v386.892C512 483.97 483.97 512 449.446 512H62.554c-34.524.0-62.554-28.03-62.554-62.554V62.554c0-34.524 28.029-62.554 62.554-62.554h386.892zM160.461 423.278V197.561h-75.04v225.717h75.04zm270.539.0V293.839c0-69.333-37.018-101.586-86.381-101.586-39.804.0-57.634 21.891-67.617 37.266v-31.958h-75.021c.995 21.181.0 225.717.0 225.717h75.02V297.222c0-6.748.486-13.492 2.474-18.315 5.414-13.475 17.767-27.434 38.494-27.434 27.135.0 38.007 20.707 38.007 51.037v120.768H431zM123.448 88.722C97.774 88.722 81 105.601 81 127.724c0 21.658 16.264 39.002 41.455 39.002h.484c26.165.0 42.452-17.344 42.452-39.002-.485-22.092-16.241-38.954-41.943-39.002z"/></svg></a><a target=_blank rel="noopener noreferrer" aria-label="share Jake's Weekly - 3rd Jan 2022 on reddit" href="https://reddit.com/submit?url=https%3a%2f%2fblog.hillion.co.uk%2fposts%2fweekly-2022-01-03%2f&title=Jake%27s%20Weekly%20-%203rd%20Jan%202022"><svg viewBox="0 0 512 512"><path d="M449.446.0C483.971.0 512 28.03 512 62.554v386.892C512 483.97 483.97 512 449.446 512H62.554c-34.524.0-62.554-28.03-62.554-62.554V62.554c0-34.524 28.029-62.554 62.554-62.554h386.892zM446 265.638c0-22.964-18.616-41.58-41.58-41.58-11.211.0-21.361 4.457-28.841 11.666-28.424-20.508-67.586-33.757-111.204-35.278l18.941-89.121 61.884 13.157c.756 15.734 13.642 28.29 29.56 28.29 16.407.0 29.706-13.299 29.706-29.701.0-16.403-13.299-29.702-29.706-29.702-11.666.0-21.657 6.792-26.515 16.578l-69.105-14.69c-1.922-.418-3.939-.042-5.585 1.036-1.658 1.073-2.811 2.761-3.224 4.686l-21.152 99.438c-44.258 1.228-84.046 14.494-112.837 35.232-7.468-7.164-17.589-11.591-28.757-11.591-22.965.0-41.585 18.616-41.585 41.58.0 16.896 10.095 31.41 24.568 37.918-.639 4.135-.99 8.328-.99 12.576.0 63.977 74.469 115.836 166.33 115.836s166.334-51.859 166.334-115.836c0-4.218-.347-8.387-.977-12.493 14.564-6.47 24.735-21.034 24.735-38.001zM326.526 373.831c-20.27 20.241-59.115 21.816-70.534 21.816-11.428.0-50.277-1.575-70.522-21.82-3.007-3.008-3.007-7.882.0-10.889 3.003-2.999 7.882-3.003 10.885.0 12.777 12.781 40.11 17.317 59.637 17.317 19.522.0 46.86-4.536 59.657-17.321 3.016-2.999 7.886-2.995 10.885.008 3.008 3.011 3.003 7.882-.008 10.889zm-5.23-48.781c-16.373.0-29.701-13.324-29.701-29.698.0-16.381 13.328-29.714 29.701-29.714 16.378.0 29.706 13.333 29.706 29.714.0 16.374-13.328 29.698-29.706 29.698zM160.91 295.348c0-16.381 13.328-29.71 29.714-29.71 16.369.0 29.689 13.329 29.689 29.71.0 16.373-13.32 29.693-29.689 29.693-16.386.0-29.714-13.32-29.714-29.693z"/></svg></a><a target=_blank rel="noopener noreferrer" aria-label="share Jake's Weekly - 3rd Jan 2022 on facebook" href="https://facebook.com/sharer/sharer.php?u=https%3a%2f%2fblog.hillion.co.uk%2fposts%2fweekly-2022-01-03%2f"><svg viewBox="0 0 512 512"><path d="M449.446.0C483.971.0 512 28.03 512 62.554v386.892C512 483.97 483.97 512 449.446 512H342.978V319.085h66.6l12.672-82.621h-79.272v-53.617c0-22.603 11.073-44.636 46.58-44.636H425.6v-70.34s-32.71-5.582-63.982-5.582c-65.288.0-107.96 39.569-107.96 111.204v62.971h-72.573v82.621h72.573V512h-191.104c-34.524.0-62.554-28.03-62.554-62.554V62.554c0-34.524 28.029-62.554 62.554-62.554h386.892z"/></svg></a><a target=_blank rel="noopener noreferrer" aria-label="share Jake's Weekly - 3rd Jan 2022 on whatsapp" href="https://api.whatsapp.com/send?text=Jake%27s%20Weekly%20-%203rd%20Jan%202022%20-%20https%3a%2f%2fblog.hillion.co.uk%2fposts%2fweekly-2022-01-03%2f"><svg viewBox="0 0 512 512"><path d="M449.446.0C483.971.0 512 28.03 512 62.554v386.892C512 483.97 483.97 512 449.446 512H62.554c-34.524.0-62.554-28.03-62.554-62.554V62.554c0-34.524 28.029-62.554 62.554-62.554h386.892zm-58.673 127.703c-33.842-33.881-78.847-52.548-126.798-52.568-98.799.0-179.21 80.405-179.249 179.234-.013 31.593 8.241 62.428 23.927 89.612l-25.429 92.884 95.021-24.925c26.181 14.28 55.659 21.807 85.658 21.816h.074c98.789.0 179.206-80.413 179.247-179.243.018-47.895-18.61-92.93-52.451-126.81zM263.976 403.485h-.06c-26.734-.01-52.954-7.193-75.828-20.767l-5.441-3.229-56.386 14.792 15.05-54.977-3.542-5.637c-14.913-23.72-22.791-51.136-22.779-79.287.033-82.142 66.867-148.971 149.046-148.971 39.793.014 77.199 15.531 105.329 43.692 28.128 28.16 43.609 65.592 43.594 105.4-.034 82.149-66.866 148.983-148.983 148.984zm81.721-111.581c-4.479-2.242-26.499-13.075-30.604-14.571-4.105-1.495-7.091-2.241-10.077 2.241-2.986 4.483-11.569 14.572-14.182 17.562-2.612 2.988-5.225 3.364-9.703 1.12-4.479-2.241-18.91-6.97-36.017-22.23C231.8 264.15 222.81 249.484 220.198 245s-.279-6.908 1.963-9.14c2.016-2.007 4.48-5.232 6.719-7.847 2.24-2.615 2.986-4.484 4.479-7.472 1.493-2.99.747-5.604-.374-7.846-1.119-2.241-10.077-24.288-13.809-33.256-3.635-8.733-7.327-7.55-10.077-7.688-2.609-.13-5.598-.158-8.583-.158-2.986.0-7.839 1.121-11.944 5.604-4.105 4.484-15.675 15.32-15.675 37.364.0 22.046 16.048 43.342 18.287 46.332 2.24 2.99 31.582 48.227 76.511 67.627 10.685 4.615 19.028 7.371 25.533 9.434 10.728 3.41 20.492 2.929 28.209 1.775 8.605-1.285 26.499-10.833 30.231-21.295 3.732-10.464 3.732-19.431 2.612-21.298-1.119-1.869-4.105-2.99-8.583-5.232z"/></svg></a><a target=_blank rel="noopener noreferrer" aria-label="share Jake's Weekly - 3rd Jan 2022 on telegram" href="https://telegram.me/share/url?text=Jake%27s%20Weekly%20-%203rd%20Jan%202022&amp;url=https%3a%2f%2fblog.hillion.co.uk%2fposts%2fweekly-2022-01-03%2f"><svg viewBox="2 2 28 28"><path d="M26.49 29.86H5.5a3.37 3.37.0 01-2.47-1 3.35 3.35.0 01-1-2.47V5.48A3.36 3.36.0 013 3 3.37 3.37.0 015.5 2h21A3.38 3.38.0 0129 3a3.36 3.36.0 011 2.46V26.37a3.35 3.35.0 01-1 2.47 3.38 3.38.0 01-2.51 1.02zm-5.38-6.71a.79.79.0 00.85-.66L24.73 9.24a.55.55.0 00-.18-.46.62.62.0 00-.41-.17q-.08.0-16.53 6.11a.59.59.0 00-.41.59.57.57.0 00.43.52l4 1.24 1.61 4.83a.62.62.0 00.63.43.56.56.0 00.4-.17L16.54 20l4.09 3A.9.9.0 0021.11 23.15zM13.8 20.71l-1.21-4q8.72-5.55 8.78-5.55c.15.0.23.0.23.16a.18.18.0 010 .06s-2.51 2.3-7.52 6.8z"/></svg></a></div></footer><div id=disqus_thread></div><script type=application/javascript>window.disqus_config=function(){},function(){if(["localhost","127.0.0.1"].indexOf(window.location.hostname)!=-1){document.getElementById("disqus_thread").innerHTML="Disqus comments not available by default when the website is previewed locally.";return}var t=document,e=t.createElement("script");e.async=!0,e.src="//blog-hillion-co-uk.disqus.com/embed.js",e.setAttribute("data-timestamp",+new Date),(t.head||t.body).appendChild(e)}()</script><noscript>Please enable JavaScript to view the <a href=https://disqus.com/?ref_noscript>comments powered by Disqus.</a></noscript><a href=https://disqus.com class=dsq-brlink>comments powered by <span class=logo-disqus>Disqus</span></a></article></main><footer class=footer><span>&copy; 2024 <a href=https://blog.hillion.co.uk/>Jake Hillion</a></span>
<span>Powered by
<a href=https://gohugo.io/ rel="noopener noreferrer" target=_blank>Hugo</a> &
<a href=https://git.io/hugopapermod rel=noopener target=_blank>PaperMod</a></span></footer><a href=#top aria-label="go to top" title="Go to Top (Alt + G)" class=top-link id=top-link accesskey=g><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentcolor"><path d="M12 6H0l6-6z"/></svg></a><script>let menu=document.getElementById("menu");menu&&(menu.scrollLeft=localStorage.getItem("menu-scroll-position"),menu.onscroll=function(){localStorage.setItem("menu-scroll-position",menu.scrollLeft)}),document.querySelectorAll('a[href^="#"]').forEach(e=>{e.addEventListener("click",function(e){e.preventDefault();var t=this.getAttribute("href").substr(1);window.matchMedia("(prefers-reduced-motion: reduce)").matches?document.querySelector(`[id='${decodeURIComponent(t)}']`).scrollIntoView():document.querySelector(`[id='${decodeURIComponent(t)}']`).scrollIntoView({behavior:"smooth"}),t==="top"?history.replaceState(null,null," "):history.pushState(null,null,`#${t}`)})})</script><script>var mybutton=document.getElementById("top-link");window.onscroll=function(){document.body.scrollTop>800||document.documentElement.scrollTop>800?(mybutton.style.visibility="visible",mybutton.style.opacity="1"):(mybutton.style.visibility="hidden",mybutton.style.opacity="0")}</script><script>document.getElementById("theme-toggle").addEventListener("click",()=>{document.body.className.includes("dark")?(document.body.classList.remove("dark"),localStorage.setItem("pref-theme","light")):(document.body.classList.add("dark"),localStorage.setItem("pref-theme","dark"))})</script></body></html>