千家信息网

linux可执行文件与写操作的同步问题怎么解决

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,这篇文章主要介绍"linux可执行文件与写操作的同步问题怎么解决"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"linux可执行文件与写操作的同步问题怎么解决"
千家信息网最后更新 2026年11月01日linux可执行文件与写操作的同步问题怎么解决

这篇文章主要介绍"linux可执行文件与写操作的同步问题怎么解决"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"linux可执行文件与写操作的同步问题怎么解决"文章能帮助大家解决问题。

inode结点中包含一个数据项,叫做i_writecount,很明显是用于记录文件被写的个数的,用于同步的,其类型也是atomic_t. 内核中有两个我们需要了解的函数,与write操作有关,分别是:

复制代码 代码如下:

int get_write_access(struct inode * inode)
{
spin_lock(&inode->i_lock);
if (atomic_read(&inode->i_writecount) < 0) {
spin_unlock(&inode->i_lock);
return -etxtbsy;
}
atomic_inc(&inode->i_writecount);
spin_unlock(&inode->i_lock);
return 0;
}

int deny_write_access(struct file * file)
{
struct inode *inode = file->f_path.dentry->d_inode;
spin_lock(&inode->i_lock);
if (atomic_read(&inode->i_writecount) > 0) {//如果文件被打开了,返回失败
spin_unlock(&inode->i_lock);
return -etxtbsy;
}
atomic_dec(&inode->i_writecount);
spin_unlock(&inode->i_lock);
}

这两个函数都很简单,get_write_acess作用就和名称一致,同样deny_write_access也是。如果一个文件被执行了,要保证它在执行的过程中不能被写,那么在开始执行前应该调用deny_write_access 来关闭写的权限。那就来检查execve系统调用有没有这么做。
sys_execve中调用do_execve,然后又调用函数open_exec,看一下open_exec的代码:

复制代码 代码如下:

struct file *open_exec(const char *name)
{
struct file *file;
int err;
file = do_filp_open(at_fdcwd, name,
o_largefile | o_rdonly | fmode_exec, 0,
may_exec | may_open);

if (is_err(file))
goto out;
err = -eacces;

if (!s_isreg(file->f_path.dentry->d_inode->i_mode))
goto exit;

if (file->f_path.mnt->mnt_flags & mnt_noexec)
goto exit;

fsnotify_open(file->f_path.dentry);
err = deny_write_access(file);//调用
if (err)
goto exit;

out:
return file;

exit:
fput(file);
return err_ptr(err);
}

明显看到了deny_write_access的调用,和预想的完全一致。在open的调用里,应该有get_write_access的调用。在open调用相关的__dentry_open函数中就包含了对该函数的调用。

复制代码 代码如下:


if (f->f_mode & fmode_write) {
error = __get_file_write_access(inode, mnt);
if (error)
goto cleanup_file;
if (!special_file(inode->i_mode))
  file_take_write(f);
}


其中__get_file_write_access(inode, mnt)封装了get_write_access.
那么内核又是如何保证一个正在被写的文件是不允许被执行的呢?这个同样也很简单,当一个文件已经为write而open时,它对应的inode的i_writecount会变成1,因此在执行execve时同样会调用deny_write_access 中读取到i_writecount>0之后就会返回失败,因此execve也就会失败返回。
这里是写文件与i_writecount相关的场景:
写打开一个文件时,在函数dentry_open中:

复制代码 代码如下:


if (f->f_mode & fmode_write) {
error = get_write_access(inode);
if (error)
goto cleanup_file;
}


当然在文件关闭时,会将i_writecount--;关闭时会执行代码:

复制代码 代码如下:


if (file->f_mode & fmode_write)
put_write_access(inode);


put_write_access 代码很简单:

复制代码 代码如下:


static inline void put_write_access(struct inode * inode)
{
atomic_dec(&inode->i_writecount);
}

于是乎自己写了个简单的代码,一个空循环,文件在执行的时候,在bash中,echo 111 >>可执行文件,结果预期之中,返回失败,并提示信息 text file busy.
那么该机制是否同样适用于映射机制呢,在执行可执行文件时,会mmap一些关联的动态链接库,这些动态链接库是否被mmap之后就不允许被写以及正在写时不允许mmap呢?这个是需要考虑的,因为它关系到安全的问题。因为库文件也是可执行的代码,被篡改同样会引起安全问题。
mmap在调用mmap_region的函数里,有一个相关的检查:

复制代码 代码如下:


if (vm_flags & vm_denywrite) {
error = deny_write_access(file);
if (error)
goto free_vma;
correct_wcount = 1;
}


其中,mmap调用中的flags参数会被正确的赋值给vm_flags,对应关系是map_denywrire被设置了,那么vm_denywrite就对应的也被设置。下面写了个简单的代码,做一下测试:

复制代码 代码如下:


#include
#include
#include
#include
#include
#include
int main()
{
int fd;
void *src = null;
fd = open("test.txt",o_rdonly);
if (fd != 0)
{
if ((src = mmap(0,5,prot_read|prot_exec ,map_private| map_denywrite,fd,0))== map_failed)
{
printf("mmap error\n");
printf("%s\n",strerror(errno));
}else{
printf("%x\n",src);
}
}

file * fd_t = fopen("test.txt","w");
if( !fd_t)
{
printf("open for write error\n");
printf("%s\n",strerror(errno));
return 0;
}

if (fwrite("0000",sizeof(char),4,fd_t) != 4)
{
printf("fwrite error \n");
}


fclose(fd_t);
close(fd);
return 1;
}


最后的test.txt被写成了"0000",很奇怪,貌似map_dentwrite不起作用了。于是man mmap查看,发现:

  map_denywrite

  this flag is ignored. (long ago, it signaled that attempts to write to the underlying file should fail with etxtbusy. but this was a source of denial-of-service attacks.)

原来这个标识在用户层已经不起作用了啊,而且还说明了原因,容易引起拒绝式服务攻击。攻击者恶意的将某些系统程序要写的文件以map_denywrite模式映射,会导致正常程序写文件失败。不过vm_denywrite在内核里还是有使用的,在mmap中还是有对deny_write_access的调用, 但是对它的调用已经不是由mmap中的flag参数的map_denywrite驱动的了。

关于"linux可执行文件与写操作的同步问题怎么解决"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注行业资讯频道,小编每天都会为大家更新不同的知识点。

代码 文件 函数 问题 同步 作用 内核 知识 明显 一致 安全 两个 动态 参数 机制 正在 程序 系统 行业 过程 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 新华互联网科技 互联网是第几次科技革命的成果 中国互联网科技股 新华互联网科技学院 科技企业和互联网企业 关于新基建和互联网科技 互联网科技英文 善班互联网科技有限公司 国外互联网科技网站 互联网科技股午盘股票涨跌 互联网科技实习生岗位职责 广州恒生互联网科技有限 电子科技大学互联网创业大赛 用友工业互联网科技发展 为客找房互联网科技公司怎么样 元气玛特互联网科技公司是外包吗 万物互联网智能科技 互联网科技职业技能培训学校 求路客互联网科技电话 黑龙江互联网科技公司 科技互联网公司装修 互联网金融公司科技 互联网和高科技公司 健康食品互联网创新科技园项目 银川新华互联网科技学校联系电话 互联网公司黑科技创始人 世界互联网领先科技成果获奖 上海钢联属于互联网科技股吗 求路客互联网科技电话 恒生互联网科技趋势
0