這篇文章主要介紹“l(fā)inux可執(zhí)行文件與寫操作的同步問題怎么解決”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“l(fā)inux可執(zhí)行文件與寫操作的同步問題怎么解決”文章能幫助大家解決問題。
目前創(chuàng)新互聯(lián)建站已為近1000家的企業(yè)提供了網(wǎng)站建設、域名、網(wǎng)頁空間、網(wǎng)站托管維護、企業(yè)網(wǎng)站設計、石泉網(wǎng)站維護等服務,公司將堅持客戶導向、應用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。inode結點中包含一個數(shù)據(jù)項,叫做i_writecount,很明顯是用于記錄文件被寫的個數(shù)的,用于同步的,其類型也是atomic_t. 內(nèi)核中有兩個我們需要了解的函數(shù),與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);
}
這兩個函數(shù)都很簡單,get_write_acess作用就和名稱一致,同樣deny_write_access也是。如果一個文件被執(zhí)行了,要保證它在執(zhí)行的過程中不能被寫,那么在開始執(zhí)行前應該調(diào)用deny_write_access 來關閉寫的權限。那就來檢查execve系統(tǒng)調(diào)用有沒有這么做。
sys_execve中調(diào)用do_execve,然后又調(diào)用函數(shù)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);//調(diào)用
if (err)
goto exit;
out:
return file;
exit:
fput(file);
return err_ptr(err);
}
明顯看到了deny_write_access的調(diào)用,和預想的完全一致。在open的調(diào)用里,應該有get_write_access的調(diào)用。在open調(diào)用相關的__dentry_open函數(shù)中就包含了對該函數(shù)的調(diào)用。
復制代碼 代碼如下:
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.
那么內(nèi)核又是如何保證一個正在被寫的文件是不允許被執(zhí)行的呢?這個同樣也很簡單,當一個文件已經(jīng)為write而open時,它對應的inode的i_writecount會變成1,因此在執(zhí)行execve時同樣會調(diào)用deny_write_access 中讀取到i_writecount>0之后就會返回失敗,因此execve也就會失敗返回。
這里是寫文件與i_writecount相關的場景:
寫打開一個文件時,在函數(shù)dentry_open中:
復制代碼 代碼如下:
if (f->f_mode & fmode_write) {
error = get_write_access(inode);
if (error)
goto cleanup_file;
}
當然在文件關閉時,會將i_writecount--;關閉時會執(zhí)行代碼:
復制代碼 代碼如下:
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);
}
于是乎自己寫了個簡單的代碼,一個空循環(huán),文件在執(zhí)行的時候,在bash中,echo 111 >>可執(zhí)行文件,結果預期之中,返回失敗,并提示信息 text file busy.
那么該機制是否同樣適用于映射機制呢,在執(zhí)行可執(zhí)行文件時,會mmap一些關聯(lián)的動態(tài)鏈接庫,這些動態(tài)鏈接庫是否被mmap之后就不允許被寫以及正在寫時不允許mmap呢?這個是需要考慮的,因為它關系到安全的問題。因為庫文件也是可執(zhí)行的代碼,被篡改同樣會引起安全問題。
mmap在調(diào)用mmap_region的函數(shù)里,有一個相關的檢查:
復制代碼 代碼如下:
if (vm_flags & vm_denywrite) {
error = deny_write_access(file);
if (error)
goto free_vma;
correct_wcount = 1;
}
其中,mmap調(diào)用中的flags參數(shù)會被正確的賦值給vm_flags,對應關系是map_denywrire被設置了,那么vm_denywrite就對應的也被設置。下面寫了個簡單的代碼,做一下測試:
復制代碼 代碼如下:
#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
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查看,發(fā)現(xiàn):
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.)
原來這個標識在用戶層已經(jīng)不起作用了啊,而且還說明了原因,容易引起拒絕式服務攻擊。攻擊者惡意的將某些系統(tǒng)程序要寫的文件以map_denywrite模式映射,會導致正常程序?qū)懳募?。不過vm_denywrite在內(nèi)核里還是有使用的,在mmap中還是有對deny_write_access的調(diào)用, 但是對它的調(diào)用已經(jīng)不是由mmap中的flag參數(shù)的map_denywrite驅(qū)動的了。
關于“l(fā)inux可執(zhí)行文件與寫操作的同步問題怎么解決”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識,可以關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,小編每天都會為大家更新不同的知識點。
名稱欄目:linux可執(zhí)行文件與寫操作的同步問題怎么解決-創(chuàng)新互聯(lián)
網(wǎng)址分享:http://jinyejixie.com/article24/csopce.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供關鍵詞優(yōu)化、云服務器、微信小程序、網(wǎng)站設計、企業(yè)網(wǎng)站制作、電子商務
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容