在 macOS 上带执行权限 mmap 一个已删除文件遇到的问题和解决方案

背景 实验环境:macOS Catalina 10.15.2 最近在 rcore-rs/zircon-rs 项目中遇到一个比较玄学的问题,首先需求是在 macOS 的用户进程里开辟一段地址空间,然后把这个地址空间多次映射(权限可能不同、同一块内存可能被映射到多个地址),通过 mmap 模拟虚拟地址的映射。采用的是如下的方案: 在临时目录创建一个文件,把文件大小设为 16M(暂不考虑扩容) 需要映射一个虚拟地址到物理地址的时候,就对这个文件的物理地址偏移进行 FIXED 映射,虚拟地址就是期望的虚拟地址。 这样的方案在 Linux 下运行地很好,但在 macOS下总是以一定概率在第二部出现 EPERM。网上搜了很多,但也没搜到相关的信息,于是自己断断续续地研究了一下,现在有一个比较初步的结果。 TL;DR 先说结论:调用一个带 PROT_EXEC 并且映射文件的 mmap 时,macOS 会进行安全检测,如果此时发现文件在文件系统上消失了,它会认为这可能是一个恶意软件行为,进行拦截,返回 EPERM。 而代码实际上在第一步和第二步之间,把临时目录删了:由于进程持有 fd,所以文件并不会真的删掉,当软件退出的时候文件自然会删除,这是临时文件的常见做法(见 tmpfile(3))。 研究过程 查看 Console 在网上一番搜索未果后,就尝试在 Console 里面寻找信息。照着程序名字搜索,可以找到一些信息: temporarySigning type=1 matchFlags=0x0 path=/path/to/executable 这是编译这个 executable 的时候出现的,好像也没啥问题。然后解除过滤,在这个信息前后按照 syspolicyd 寻找: initiating malware scan (... info_path: /path/to/temp/file proc_path: /path/to/executable) Unable (errno: 2) to read file at <private> for process path: <private> library path: <private> Disallowing load of <private> in 50001, <private> Library load (/path/to/temp/file) rejected: library load denied by system policy 这几条记录比较可疑,每次运行程序,如果跑挂了,就会出现这几条,如果没跑挂,就不会出现这一条。所以很大概率是被 macOS 拦截了。错误信息的用词是 library ,所以大概率是被当成加载动态库了,但既然内容是空的,所以我想的是文件名触碰到了什么奇怪的规则,然后文件名又是随机的,随机导致 EPERM 是概率性出现的,这好像很有道理。于是我把 tmpfile 换成了固定的路径,忽然就好了。但固定的路径只能保证同时只有一个程序在跑,如果路径拼接上pid,怎么删,谁来删又是一个问题。虽然可以放到 /tmp 下面然后随便搞,但 /tmp 的回收并不是那么积极,在临时目录下丢太多文件也会出现问题。

Read More

每周分享第 55 期

一个月后终于复更 退出 vim 教程 https://github.com/hakluke/how-to-exit-vim SHA-1 攻击新进展 https://sha-mbles.github.io/ gmane 近况 https://lars.ingebrigtsen.no/2020/01/06/whatever-happened-to-news-gmane-org/ 浏览器能做的事情 https://github.com/luruke/browser-2020 一个 ext2 和 FAT 为一体的 fs https://github.com/NieDzejkob/cursedfs iptables 规则调试工具 https://github.com/x-way/iptables-tracer Qt 2020 的变化 https://www.qt.io/blog/qt-offering-changes-2020 后缀自动机可视化 https://yeah.moe/p/a8e74947/

Read More

MacBookPro 14,3 Wi-Fi 驱动问题解决方案

之前在 MacBookPro 14,3 安装 Linux 后,很多东西的驱动都有了解决方法,参考 1,参考 2,触摸板和键盘等等都可以正常使用,触摸板的使用效果比我意料要好一些,虽然还是没有 macOS 原生那么好。但 Wi-Fi 一直有能扫到信号但连不上的问题,最近终于有了比较完善的解决方案,地址,也是两个月前才出来的方案,我测试了一下,确实可以很好的解决网络问题,网卡型号是 BCM43602,驱动用的是 brcmfmac。 另一方面,带 T2 的 MacBook 似乎也有了支持,见 aunali1/linux-mbp-arch,有一些尚未 upstream 的 patch,但我没有设备,就没有测试了。需要吐槽的是 ArchWiki 不怎么更新新 Model 的 MacBook 的教程,都是到处找散落的 github repo 和 gist 找别人的方案。 P.S. 可以正常工作的有:Wi-Fi,键盘,触摸板,Touchbar,内置摄像头,键盘背光,蓝牙 P.P.S MacBookPro11,2 的网卡是 BCM4360,直接用 broadcom-wl 驱动就可以。

Read More

JieLabs 是如何工作的

简介 JieLabs 是陈嘉杰、高一川、刘晓义(按姓氏拼音首字母排序)于 2020 年新型冠状病毒疫情期间开发的在线数字逻辑电路实验系统,用于清华大学 2020 年春季学期数字逻辑电路实验课程。其包括前端、后端和固件三部分,分别主要由刘晓义、陈嘉杰和高一川负责开发。核心功能实现用时一周,后续界面和稳定性优化用时两周。本文会详细地介绍 JieLabs 的工作原理和一些技术细节,希望对各位同学有所帮助。 太长;不看。 采用了如下的技术方案: 前端:React 框架 + Redux 状态管理 + Monaco 编辑器 + WebAssembly 运行 Rust 代码 + WebSocket 实时通信 + SASS 样式 后端:Actix-Web 框架 + Diesel/PostgreSQL 数据库 + Redis 消息队列 + Quartus 构建 + Kubernetes 构建容器编排 固件:Xilinx FPGA 控制 + Buildroot 系统 + Linux 内核 前端 前端大部分都是刘晓义同学编写的,也是这个项目工作量最大的一部分。除了本文,还可以阅读刘晓义同学自己写的总结。主要分以下几部分来谈前端的技术实现: 第三方库 整体上采用了时下比较流行的 React 框架,配合 Redux 进行状态管理,用 React Hooks 编写组件的逻辑。为了实现 VHDL/Verilog 代码的编辑,采用了来自 VSCode 的独立编辑器空间 Monaco,并自行编写了 VHDL 和 Verilog 语言的支持,一部分在 JS 实现,另一部分在 Rust 中实现,通过 wasm-pack 打包到 JS 中执行。另外为了实现 gzip 格式的解压缩也引入了 pako 库。

Read More

每周分享第 54 期

咕了两周 ES2019 https://javascript.christmas/2019/7 CSS 技巧 https://github.com/chokcoco/iCSS Rust 编译器加速 https://blog.mozilla.org/nnethercote/2019/12/11/how-to-speed-up-the-rust-compiler-one-last-time-in-2019/ OSXFuse 不开源 https://colatkinson.site/macos/fuse/2019/09/29/osxfuse/ 嵌入式 Rust 的 fmt 优化 https://jamesmunns.com/blog/fmt-unreasonably-expensive/ Docker base image 更新工具 https://github.com/containrrr/watchtower 运行 Linux 的名片 https://www.thirtythreeforty.net/posts/2019/12/my-business-card-runs-linux/

Read More

每周分享第 53 期

GDB Enhanced Features https://github.com/hugsy/gef Lisp on Lua https://fennel-lang.org/ Django 3.0 https://docs.djangoproject.com/en/3.0/releases/3.0/ Rust Constant Propagation https://blog.rust-lang.org/inside-rust/2019/12/02/const-prop-on-by-default.html ES2019 features https://javascript.christmas/2019/7

Read More

每周分享第 52 期

传递 Rust 闭包到 C https://readhacker.news/s/4dbWL SystemVerilog Online http://sv-lang.com/ Java 14 新特性 https://www.javaworld.com/article/3437797/work-begins-on-java-14.html 在线 or1k 的模拟器 https://readhacker.news/s/4dfqc 在 macOS 上运行 virt-manager https://github.com/jeffreywildman/homebrew-virt-manager 关于 SystemVerilog 的博客 http://systemverilog.io/ 结合 VSCode 和 Docker 的开发环境 https://github.com/cdr/sail

Read More

每周分享第 51 期

一个 LaTeX 的 LSP https://github.com/latex-lsp/texlab Rope 数据结构 https://github.com/cessen/ropey 一个把 Vivado 工程放 git 中管理的方法 https://github.com/jhallen/vivado_setup https://github.com/athre0z/color-backtrace 拿 Arch 当路由器 https://github.com/archwrt Sourcetrail 开源了 https://www.sourcetrail.com/blog/open_source/ NodeJS 正式支持 ES Module https://medium.com/@nodejs/announcing-core-node-js-support-for-ecmascript-modules-c5d6dc29b663 Rust 的错误处理 https://blog.yoshuawuyts.com/error-handling-survey/

Read More

实现一个简单的 Decaf LSP

背景 编译原理课程在做 Decaf 的 PA ,之前做了一些比较简单的尝试,包括在线 Decaf、在线 TAC VM 等等,都是套一个前端,然后整个编译到 wasm 跑前端就可以了。如果要做 LSP 的话,工作量会稍微大一些,不过也更加实用。 然后有一天,助教 @equation314 写了 decaf-vscode 一个 VSCode 对 Decaf 的语法高亮插件,我就 Fork 了一份到 jiegec/decaf-vscode,然后添加了 LSP 的支持,让它有了一些更高级的功能。 实现 LSP 服务端一般是一个命令行程序,通过 JSONRPC 进行消息通讯,然后就上午找有没有现成的框架。比较重要的是 lsp-types 和 tower-lsp ,前者封装了 LSP 协议的各个结构体,后者提供了服务端的大概实现。不过由于后者做的不大全,所以我自己 fork 了一份添加了一些。 实际实现的时候,需要实现几个函数,分别相应客户端的请求,比如在 initialize 的时候告诉客户端我都实现了哪些东西,然后相应地提供各种信息,如 symbol,hover,folding,definition等等。为了实现简单,我要求客户端每次修改的时候都把完整的文件传过来,虽然不是很高效,但是很简单,目前也没有啥很长的 Decaf 程序嘛。 每次拿到 Decaf 程序之后,就按照 decaf-rs 的方法,Lex 然后 Parse ,然后遍历 AST ,分别把需要的各个信息都存下来,当客户端在请求的时候,直接返回即可。然后就会在 VSCode 中出现,比如实现了 document symbol ,在左边的 Outline 中就会出现相应的结构;实现了 hover ,当移动到一些地方的时候,客户端发出请求,服务端就把相应的 hover 信息返回给客户端。整个协议并不复杂,后面实际实现其实才是比较复杂的地方。 实现的功能中,symbols hovers ranges definition 都是在得到 AST 后一次遍历都计算好,然后返回,同时在遇到错误的时候,也通过 diagnostic 的形式把检查出来的错误汇报给用户。由于 VSCode 的良好支持,基本不需要写 TypeScript 代码。

Read More