中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

linux可執行文件與寫操作的同步問題怎么解決

發布時間:2022-04-16 15:02:52 來源:億速云 閱讀:159 作者:iii 欄目:編程語言

這篇文章主要介紹“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 <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查看,發現:

  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可執行文件與寫操作的同步問題怎么解決”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

慈溪市| 崇礼县| 龙泉市| 金华市| 灵丘县| 七台河市| 株洲县| 同德县| 镇安县| 喀喇| 泾源县| 遵义县| 梅州市| 凌云县| 武陟县| 怀仁县| 眉山市| 石楼县| 旌德县| 积石山| 长汀县| 巧家县| 石泉县| 库车县| 松桃| 基隆市| 乌拉特前旗| 莱芜市| 布尔津县| 富川| 马尔康县| 永德县| 株洲县| 玉田县| 奎屯市| 四会市| 论坛| 鹤峰县| 双城市| 崇左市| 阜平县|