上篇是顺利那次。这篇记两次失败,它们比成功有价值——根子都在主机上,跟 Microchip 没关系。
第一次:第 21 个任务就崩
56 秒,14 个任务同时报错,退出码 1。
【03_04_userns报错】
ERROR: PermissionError: [Errno 1] Operation not permitted
File ".../bitbake-worker", line 278, in child
bb.utils.disable_network(uid, gid)
File ".../lib/bb/utils.py", line 1696
with open("/proc/self/uid_map", "w") as f:位置很明确:写 /proc/self/uid_map,给新建的用户命名空间做 uid 映射。
根因是 Ubuntu 24.04 默认 kernel.apparmor_restrict_unprivileged_userns = 1,挡住了 bitbake 网络隔离依赖的 unshare()。写个 /etc/sysctl.d/99-yocto-userns.conf 关掉,sysctl --system 生效。
我自己制造的假象
排查时想用 Python 单独复现,写完跑出来还是 EPERM,差点以为 sysctl 没生效。
其实是我写错了:在 unshare() 之后才调 os.getuid(),这时进程已在新的命名空间里,拿到的是 65534——未映射时的溢出值。拿它写 uid_map,当然还是被拒。
正确做法是 unshare 之前先把真实 uid 存下来,这也是 bitbake 代码里的写法。
这个假象浪费了半个多小时。教训是:复现问题的时候,复现代码本身也得写对,否则你验证的是自己的 bug。
第二次:3276 个任务之后
修完 userns 重跑,一路到 3276/4377,然后 do_package 集体失败:
got *at() syscall for unknown directory, fd 4 unknown base path for fd 4, path bin tar: ./usr/bin: Cannot mkdir: Bad address
【03_05_pseudo与tar】
关键是第一句——伪文件系统不认识这个目录的 fd。
GNU tar 修 CVE-2025-45582 时改用 gnulib 的 openat2() 打开解压目录,而 scarthgap 自带的 pseudo 1.9.0 没有 openat2 包装,不记录这个 fd,后面 mkdirat() 拿到无效 fd 返回 EFAULT。
我是把 got *at() syscall for unknown directory 原样丢进搜索找到的,报错原文比任何描述都好用。
验证与修复
光看报错不够,我去 pseudo 仓库翻了文件树:1.9.0(374089f)里一个 openat2 文件都没有,pseudo-1.9.11(ba8887e)里 ports/linux/openat2/ 就在那儿。
修法是新建本地层 meta-letsdesign,用 bbappend 提版本:
SRCREV = "ba8887e5f1e922f866681ec7dec1a00b602a9328" PV = "1.9.11+git" SRC_URI:remove = "file://0001-configure-Prune-PIE-flags.patch" SRC_URI:remove = "file://glibc238.patch" SRC_URI:remove = "file://older-glibc-symbols.patch"
先单独编 pseudo-native 验证,再重建整条链。
副作用要提前知道:pseudo 是伪文件系统的核心,换掉它等于 sstate 大面积作废,所以第三次构建实际接近全量编译。
MACHINE 那个坑
另一次实验栽的,顺手记进来。
手工敲 bitbake linux-mchp 漏了 MACHINE=,bitbake 用了 local.conf 的默认值,静默编了另一块板子,日志全绿、退出码 0。
【03_07_编错机器】
对比两个 tmp/work/<machine>/ 目录时间戳才发现:目标机目录停在几小时前,另一个一直在变。
构建"成功"不等于"编对了东西"。产物路径带机器名,值得每次确认。
三次构建的账
【03_06_三次构建】
56 秒崩、1864 秒失败、1858 秒全过。两次失败加起来近一小时,全是主机环境问题,BSP 一行代码没改。
这就是我想说的:新平台的开发门槛,很大程度取决于构建机,而不是芯片。
我要赚赏金
