问题
SDK在打包sd镜像的时候用了挂载loop设备然后分区的操作,会涉及到提权问题,提权之后会产生隐式安全的问题。
由于涉及到提权问题,用户在build时在打包镜像过程中有可能权限不够,milkv 外设验证中就出现了该问题。
SD镜像
SD镜像是指通过将嵌入式系统或其他操作系统完整地复制到SD卡或类似存储介质中创建的一个映像文件。它包含了完整的文件系统、操作系统和其他相关的数据。
SD镜像通常用于将整个嵌入式系统部署到SD卡或类似存储介质上,以便将其用作嵌入式设备的启动介质。镜像文件包含了预先配置好的文件系统、内核、驱动程序和其他所需的组件,可以直接烧录到SD卡中,然后插入到嵌入式设备中进行启动和运行。
创建SD镜像的过程涉及将整个文件系统的内容复制到一个文件中,并确保文件系统的结构、权限和属性等信息得以保留。这样,当镜像文件被写入SD卡时,SD卡中的分区和文件系统结构与原始系统完全相同。
SD镜像的好处是可以方便地复制和部署嵌入式系统,以及在多个设备之间进行系统的快速复制和恢复。它在嵌入式开发、系统定制和部署中扮演着重要的角色。
loop
在Linux中,loop是一种设备驱动程序,用于将一个文件作为块设备进行访问。它允许将一个普通文件映射为一个块设备,从而可以在该文件上模拟一个独立的块设备。
通过使用loop设备,可以将镜像文件、虚拟磁盘映像或其他特定格式的文件系统
载为一个独立的文件系统。这样,可以对该文件系统进行读取、写入和访问,就像访问实际的硬盘或分区一样。
loop设备的工作原理是将一个文件映射到一个块设备节点,然后可以使用mount命令将该设备挂载到指定的挂载点上。在挂载完成后,可以通过文件系统路径访问和操作该文件中的数据。
使用losetup命令可以将一个文件与loop设备进行关联,并为其分配一个可用的loop设备节点。例如,可以使用以下命令将名为image.img的镜像文件与一个loop设备进行关联:
sudo losetup /dev/loop0 image.img
然后,可以使用mount命令将/dev/loop0设备挂载到指定的挂载点上,使其可访问和使用。
sudo mount /dev/loop0 /mnt
这样,image.img文件中的文件系统将以/mnt作为根目录挂载到系统中,可以进行文件操作和访问。
需要注意的是,在使用完毕后,应该使用umount命令将挂载点卸载,并使用losetup -d命令断开loop设备与文件的关联,释放相应的设备节点。
sd_gen_burn_image.sh代码阅读
#!/bin/bash
# a sd image generator for sophpi
# usage
if [ "$#" -ne "1" ] #如果输入的参数数量不等于1就打印以下语句
then
echo "usage: sudo ./sd_gen_burn_image.sh OUTPUT_DIR"
echo ""
echo " The script is used to create a sdcard image with two partitions, "
echo " one is fat32 with 128MB, the other is ext4 with 256MB."
echo " You can modify the capacities in this script as you wish!"
echo ""
echo "Note: Please backup you sdcard files before using this image!"
exit
fi
vfat_cap=128M
vfat_label="boot"
ext4_cap=256M
ext4_label="rootfs"
output_dir=$1 #将脚本的第一个命令行参数赋值给变量 output_dir 来指定输出目录
echo ${output_dir}
pushd ${output_dir} #将当前工作目录推入一个目录堆栈,并进入该目录
image=sophpi-duo-`date +%Y%m%d-%H%M`.img #使用date命令获取时间戳并命名给镜像文件
echo ${image} #打印出镜像的文件名
#使用dd命令读取数据
#if指定输入文件是/dev/zero。/dev/zero是一个特殊的字符设备文件,当我们使用或读取它的时候,它会提供无限连续不断的空的数据流
#of指定输出文件是当前目录下的image文件
#bs指定块大小,使每次读取和写入的块大小为1MB
#count指定总共读取和写入的块数。因此会创建一个大小为512MB的空镜像文件
dd if=/dev/zero of=./${image} bs=1M count=512
################################
# Note: do not change this flow
################################
sudo fdisk ./${image} << EOF #<< EOF 用于将下面的多行作为fdisk的输入
n #创建新分区
p #创建主分区
1 #新创建的分区号为1。同时下面创建一个空行,以便后面输入分区大小
#
+${vfat_cap} #指定了之前定义的FAT32分区的大小
n #创建第二个分区
p #创建主分区
2 #新创建的分区号为2
+${ext4_cap} #指定了之前定义的ext4分区的大小
w #保存并写入更改
EOF
# Note end
################################
dev_name=`sudo losetup -f` #losetup -f用来找(-f find)当前未使用的最低loop设备名,并赋给dev_name
echo ${dev_name}
echo ""
sudo losetup ${dev_name} ./${image} #使用losetup将loop设备和镜像文件关联起来
sudo partprobe ${dev_name} #使用partprobe使系统重新扫描loop设备dev_name的分区表,以更新内核中的分区信息
#mkfs.vfat创建并格式化文件系统
#-F 32指定文件系统是FAT32。FAT32是特定指定的类型,需要用该选项明确
#-n ${vfat_label}指定文件系统标签名称
#${dev_name}p1表示要格式化的分区
sudo mkfs.vfat -F 32 -n ${vfat_label} ${dev_name}p1
#-L ${ext4_label}指定文件系统标签名称
#${dev_name}p2表示要格式化的分区
sudo mkfs.ext4 -L ${ext4_label} ${dev_name}p2
rm ./tmp1 ./tmp2 -rf #-rf强制删除目录内容,即使非空
mkdir tmp1 tmp2 #创建tmp1 tmp2目录
# 挂载分区。-t指定文件系统类型
sudo mount -t vfat ${dev_name}p1 tmp1/
sudo mount -t ext4 ${dev_name}p2 tmp2/
#将指定的文件和目录复制到相应的挂载分区的临时目录中
sudo cp ${output_dir}/fip.bin ./tmp1/
sudo cp ${output_dir}/rawimages/boot.sd ./tmp1/
sudo cp -raf ${output_dir}/fs/* ./tmp2
#将缓冲区的内容写入磁盘
sync
# 卸载分区并释放loop设备
sudo umount tmp1 tmp2
sudo losetup -d ${dev_name}
rmdir tmp1 tmp2
# 打包镜像文件
tar zcvf ${image}.tar.gz ${image}
echo "Gen image successful: ${image}"
echo ""
popd
使用genimage打包镜像
1.编译安装genimage
git clone https://github.com/pengutronix/genimage
cd genimage
./autogen.sh
./configure
make -j$(nproc)
make install
2.创建genimage.cfg
image boot.vfat {
vfat {
label = "boot"
files = {
"fip.bin",
"rawimages/boot.sd"
}
}
size = 128M
}
image rootfs.ext4 {
ext4 {
label = "rootfs"
}
size = 256M
mountpoint = "/"
}
image sdcard.img {
hdimage {}
partition boot {
partition-type = 0x0C
bootable = "true"
image = "boot.vfat"
}
partition rootfs {
partition-type = 0x83
image = "rootfs.ext4"
}
}
将此文件保存在build/boards/cv180x/cv1800b_sophpi_duo_sd/genimage.cfg里
3.修改构建脚本
# build/Makefile
# 596行后面加上
${Q}cp $(BUILD_PATH)/boards/${CHIP_ARCH_L}/${PROJECT_FULLNAME}/genimage.cfg $(OUTPUT_DIR)/
# build/tools/common/sd_tools/sd_gen_burn_image.sh
# 直接替换下面内容
#!/bin/bash
# a sd image generator for sophpi
# usage
if [ "$#" -ne "1" ]
then
echo "usage: sudo ./sd_gen_burn_image.sh OUTPUT_DIR"
echo ""
echo " The script is used to create a sdcard image with two partitions, "
echo " one is fat32 with 128MB, the other is ext4 with 256MB."
echo " You can modify the capacities in this script as you wish!"
echo ""
echo "Note: Please backup you sdcard files before using this image!"
exit
fi
output_dir=$1
echo ${output_dir}
pushd ${output_dir}
image=${PROJECT_FULLNAME}-`date +%Y%m%d-%H%M`-sdcard.zip
genimage --config genimage.cfg --rootpath fs/ --tmppath `mktemp -d` --inputpath $PWD --outputpath $PWD
zip ${image} sdcard.img
echo "Gen image successful: ${image}"
echo ""
popd
4.配置软件环境
编译sophpi-duo之前,先确认一下 build/boards/cv180x/cv1800b_sophpi_duo_sd/cv1800b_sophpi_duo_sd_defconfig 文件中,CONFIG_BUILDROOT_FS是否有打开,如果没有打开,请先设置成
CONFIG_BUILDROOT_FS=y
#拉取代码
git clone https://github.com/sophgo/cvi_mmf_sdk.git
#下载cv180x系列risc-v工具链
wget https://sophon-file.sophon.cn/sophon-prod-s3/drive/23/03/07/16/host-tools.tar.gz
#解压工具链并链接到SDK目录
tar xvf host-tools.tar.gz
cd cvi_mmf_sdk/
ln -s ../host-tools ./
#编译
source build/cvisetup.sh
defconfig cv1800b_sophpi_duo_sd
clean_all && build_all && pack_sd_image