在挂载的TF卡中保存coredump,结果文件大小为0
关于coredump的说明,详见:
coredump文件 - 海林的菜园子 - 博客园 (cnblogs.com)
将公司分配的nfs服务器挂载在开发板,保存coredump文件,大小正常。但将coredump保存在挂载的TF卡中则发现最终生成的coredump大小为0。Why?
首先,配置coredump保存路径为/tmp/nfs00,例如:
echo "/tmp/nfs00/log-%s-%e-%p-%t " > /proc/sys/kernel/core_pattern
当我们的coredump保存在nfs服务器上时(即将nfs服务器挂载到/tmp/nfs00路径),虽然文件大小正常,但是却无执行权限,因文件权限为0600(如图1),但是输入命令umask我们却发现默认文件掩码为0022(备注:此时文件权限为777-022 = 755,掩码0022的首位0指的是UID和GID,即用户ID和组ID,一般不使用,此处不做探讨),即新创建的文件以及文件夹默认权限应该是0755(如图1),比如在/tmp目录下,新建test文件夹,其权限为 0755(如图2).同时发现,当coredump保存在TF卡中时,事先使用如下命令挂载:
ulimit -c unlimited mkdir -p /tmp/nfs00 mount /dev/mmcblk0p1 /tmp/nfs00
虽然文件大小为0,但是文件权限却符合默认文件权限,即0755(如图3)。因此判断,文件大小为0极有可能和文件权限有关。
图 1 nfs上的coredemp
图 2 新建文件夹
图 3 TF卡上的coredump
众所周知,TF卡为vFat文件系统,常用于windows系统,而文件权限的概念定义在linux文件系统的文件node节点中。因此Fat32格式的TF卡,并不具备文件权限的概念。对于挂载的TF卡来说,只能在最初使用mount命令时显式指明该节点的权限掩码,否则为默认值,且该节点权限为static类型值,不可更改,即对于TF的挂载节点使用chmod命令修改权限也无法生效,因vFat文件系统无node文件节点。因此只能使用重新挂载的方式修改权限。
那么,回到正题,为什么挂载nfs服务器保存的coredump文件权限是0600,与默认权限不符,挂载TF卡保存的coredump文件权限是0755,与默认权限相符但大小却为0呢?查阅生成coredump的linux源码发现,kernel在创建coredump文件时,显式指明了coredump文件的权限为0600,公司的nfs服务器本身为linux文件系统。因此命令生效最终文件权限为0600,当挂载TF卡时,如前所述vFat文件系统不存在文件权限的概念,当我们未在mount时显示指明挂载节点权限为时,使用默认权限掩码0022,最终该TF卡挂载节点权限依然为static值0755,不可修改。kernel在生成coredump时filp_open
函数的参数0600未生效,但文件创建成功,因此我们看到在TF卡中的coredump权限为0755。
1 cprm.file = filp_open(cn.corename, 2 O_CREAT | 2 | O_NOFOLLOW | 3 O_LARGEFILE | O_EXCL, 4 0600);//linux内核中创建coredump文件的代码
那么为什么大小为0呢?在源码中我们可以看到,在创建coredump文件后,写入数据之前会进行权限校验 “mode & 0677 == 0600”,校验失败则关闭文件句柄,最终未写入数据,文件大小为零。
1 * Don't dump core if the filesystem changed owner or mode 2 * of the file during file creation. This is an issue when 3 * a process dumps core while its cwd is e.g. on a vfat 4 * filesystem. 5 */ 6 if (!uid_eq(inode->i_uid, current_fsuid())) 7 goto close_fail; 8 if ((inode->i_mode & 0677) != 0600) 9 goto close_fail;
因此我们只需修改开发板的默认掩码或者在挂载TF时显示指明挂载节点的文件权限即可。根据最小改动原则推荐使用后者。例如:
1 ulimit -c unlimited 2 mkdir -p /tmp/nfs00 3 mount /dev/mmcblk0p1 /tmp/nfs00 -o fmask=0077 4 ls -l /tmp/nfs00
或
1 ulimit -c unlimited 2 mkdir -p /tmp/nfs00 3 mount /dev/mmcblk0p1 /tmp/nfs00 -o fmask=0177 4 ls -l /tmp/nfs00
此时文件权限mode=0700或0600,mode & 0677 == 0600成立。
备注:该问题来自2015年linux源码针对vFat文件系统无法使filp_open
函数的参数0600生效的一次改动,增加了文件权限校验,目的是为了保证coredump文件只能开放权限给ower,且至少开放读写权限,而group和others所有权限禁止,详见源码中的此次提交。因此旧版本可能无此问题。。