树莓派4 Yocto定制镜像:RAM根文件系统下ACL失效问题排查
问题描述
我正在使用Yocto为Raspberry Pi 4构建定制镜像,尝试通过ACL设置用户组权限。当根文件系统位于SD卡时一切正常,但根文件系统在RAM(fitImage)中时,ACL似乎无法工作。内核配置中已开启CONFIG_TMPFS_POSIX_ACL=y,以下是我的initramfs配方:
require recipes-core/images/super-pi.bb IMAGE_NAME = "super-pi-initramfs" IMAGE_FSTYPES := "${INITRAMFS_FSTYPES}" IMAGE_FSTYPES:remove = " wic wic.gz" PACKAGE_INSTALL:append = " ${IMAGE_INSTALL}" IMAGE_NAME_SUFFIX ?= "" IMAGE_LINGUAS = "" IMAGE_ROOTFS_EXTRA_SPACE = "0" DEPENDS:append = " acl-native" inherit extrausers #to generate hash for password: printf "%q" $(mkpasswd -m sha256crypt <password>) #pass: puma1 DEVELOPER_PASSWORD_HASH = "\$5\$5j7bye3XKroIht0\$rZ3af/o3gVXLYo5vqtfbjllCSa5jtx2QrRraKaWwqn5" #pass: puma2 PRODUCTION_PASSWORD_HASH = "\$5\$uoMhBHIwh8ReIv1\$Fxuh8QN4my0pNfOe/RGfLhMGD5LxVk6UOWupprvgFT/" #pass: puma3 SERVIS_PASSWORD_HASH = "\$5\$Q.5Zmboz3pIJ3hT\$Xi0f6YTzYGvTjD3cnniNa6htyBB/cY5GT7eUUM1Puq4" #pass: puma4 VISITOR_PASSWORD_HASH = "\$5\$7CBZsfthWke7GmAw\$uuejwFB.BuAyFAeTY7b40qXxg4oA4G8e7X/hztSIsh0" EXTRA_USERS_PARAMS = "\ groupadd --gid 1001 developer; \ groupadd --gid 1002 production; \ groupadd --gid 1003 servis; \ groupadd --gid 1004 visitor; \ useradd --uid 1011 --no-user-group --no-create-home --password '${DEVELOPER_PASSWORD_HASH}' --shell /bin/bash developer; \ useradd --uid 1012 --no-user-group --no-create-home --password '${PRODUCTION_PASSWORD_HASH}' --shell /bin/bash production; \ useradd --uid 1013 --no-user-group --no-create-home --password '${SERVIS_PASSWORD_HASH}' --shell /bin/bash servis; \ useradd --uid 1014 --no-user-group --create-home --password '${VISITOR_PASSWORD_HASH}' --shell /bin/bash visitor; \ usermod -g developer developer; \ usermod -g production production; \ usermod -g servis servis; \ usermod -g visitor visitor; \ " modify_user_access() { setfacl -R -m g:developer:rwX ${IMAGE_ROOTFS}/etc \ ${IMAGE_ROOTFS}/usr \ ${IMAGE_ROOTFS}/lib \ ${IMAGE_ROOTFS}/bin \ ${IMAGE_ROOTFS}/sbin \ ${IMAGE_ROOTFS}/sys \ ${IMAGE_ROOTFS}/boot \ ${IMAGE_ROOTFS}/proc \ ${IMAGE_ROOTFS}/media \ ${IMAGE_ROOTFS}/mnt \ ${IMAGE_ROOTFS}/var \ ${IMAGE_ROOTFS}/run; bbnote "setfacl result: $?" setfacl -R -m g:production:rwX ${IMAGE_ROOTFS}/etc \ ${IMAGE_ROOTFS}/usr \ ${IMAGE_ROOTFS}/lib \ ${IMAGE_ROOTFS}/bin \ ${IMAGE_ROOTFS}/sbin \ ${IMAGE_ROOTFS}/media \ ${IMAGE_ROOTFS}/mnt; bbnote "setfacl result: $?" setfacl -R -m g:servis:rX ${IMAGE_ROOTFS}/etc \ ${IMAGE_ROOTFS}/usr \ ${IMAGE_ROOTFS}/bin \ ${IMAGE_ROOTFS}/sbin \ ${IMAGE_ROOTFS}/media \ ${IMAGE_ROOTFS}/mnt; bbnote "setfacl result: $?" setfacl -R -m g:visitor:--- ${IMAGE_ROOTFS}/; setfacl -R -m g:visitor:r ${IMAGE_ROOTFS}/home/visitor; bbnote "setfacl result: $?" } modify_sudoers() { sed -i.bak 's/# Cmnd_Alias\tREBOOT/Cmnd_Alias\tREBOOT/' ${IMAGE_ROOTFS}/etc/sudoers sed -i.bak 's/# Cmnd_Alias\tPROCESSES/Cmnd_Alias\tPROCESSES/' ${IMAGE_ROOTFS}/etc/sudoers sed -i.bak 's/# \t\t\t \/usr\/bin\/pkill/ \t\t\t \/usr\/bin\/pkill/' ${IMAGE_ROOTFS}/etc/sudoers echo "%developer ALL=(ALL) REBOOT, PROCESSES, /usr/bin/setfacl" > ${IMAGE_ROOTFS}/etc/sudoers.d/0001_custom_sudo_rules echo "%production ALL=(ALL) REBOOT, PROCESSES, /usr/bin/setfacl" >> ${IMAGE_ROOTFS}/etc/sudoers.d/0001_custom_sudo_rules rm ${IMAGE_ROOTFS}/etc/sudoers.bak } rootfs_update_timestamp() { date "+%Y%m%d%H%M%S" > ${IMAGE_ROOTFS}/etc/timestamp } IMAGE_PREPROCESS_COMMAND += "modify_user_access;" ROOTFS_POSTPROCESS_COMMAND += "rootfs_update_timestamp;modify_sudoers;"
解决方法
1. 确保tmpfs挂载时添加ACL参数
内核开启CONFIG_TMPFS_POSIX_ACL仅支持tmpfs的ACL功能,默认挂载时不会自动启用。需要在initramfs的启动逻辑中,为根文件系统挂载添加acl选项:
- 若使用传统init脚本,修改挂载命令为:
mount -t tmpfs -o rw,acl,size=256M tmpfs /root - 若使用systemd,可在启动cmdline中添加
rootflags=acl,或修改对应的tmpfs挂载单元。
2. 添加运行时ACL依赖
配方中仅添加了acl-native用于构建阶段设置ACL,但运行时环境需要acl包提供libacl库和setfacl/getfacl工具。修改配方:
PACKAGE_INSTALL:append = " acl"
3. 移除虚拟文件系统的ACL设置
modify_user_access函数中对/sys、/proc等虚拟文件系统设置ACL无意义,这些目录在运行时动态挂载,构建阶段的设置不会生效。修改函数,仅针对实际文件系统目录:
modify_user_access() { setfacl -R -m g:developer:rwX ${IMAGE_ROOTFS}/etc \ ${IMAGE_ROOTFS}/usr \ ${IMAGE_ROOTFS}/lib \ ${IMAGE_ROOTFS}/bin \ ${IMAGE_ROOTFS}/sbin \ ${IMAGE_ROOTFS}/boot \ ${IMAGE_ROOTFS}/media \ ${IMAGE_ROOTFS}/mnt \ ${IMAGE_ROOTFS}/var \ ${IMAGE_ROOTFS}/run; bbnote "setfacl result: $?" setfacl -R -m g:production:rwX ${IMAGE_ROOTFS}/etc \ ${IMAGE_ROOTFS}/usr \ ${IMAGE_ROOTFS}/lib \ ${IMAGE_ROOTFS}/bin \ ${IMAGE_ROOTFS}/sbin \ ${IMAGE_ROOTFS}/media \ ${IMAGE_ROOTFS}/mnt; bbnote "setfacl result: $?" setfacl -R -m g:servis:rX ${IMAGE_ROOTFS}/etc \ ${IMAGE_ROOTFS}/usr \ ${IMAGE_ROOTFS}/bin \ ${IMAGE_ROOTFS}/sbin \ ${IMAGE_ROOTFS}/media \ ${IMAGE_ROOTFS}/mnt; bbnote "setfacl result: $?" setfacl -R -m g:visitor:--- ${IMAGE_ROOTFS}/; setfacl -R -m g:visitor:r ${IMAGE_ROOTFS}/home/visitor; bbnote "setfacl result: $?" }
4. 验证运行时ACL状态
系统启动后,执行以下命令验证ACL是否生效:
# 检查目录ACL设置 getfacl /etc # 测试用户组权限 su - developer -c "touch /etc/testfile"
5. 检查initramfs内容完整性
解压initramfs镜像,确认包含ACL相关文件:
# 提取initramfs mkdir initramfs && cd initramfs zcat ../initramfs.cpio.gz | cpio -idmv # 检查文件是否存在 ls usr/lib/libacl* usr/bin/setfacl
内容的提问来源于stack exchange,提问作者grandzello
相关产品推荐
相关产品推荐

