📄 012_mm_mprotect_c.html
字号:
<html lang="zh-CN" xmlns:gdoc=""> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> <style type="text/css">/* default css */table { font-size: 1em; line-height: inherit;}div, address, ol, ul, li, option, select { margin-top: 0px; margin-bottom: 0px;}p { margin: 0px;}body { margin: 0px; padding: 0px; font-family: Verdana, sans-serif; font-size: 10pt; background-color: #ffffff;}h6 { font-size: 10pt }h5 { font-size: 11pt }h4 { font-size: 12pt }h3 { font-size: 13pt }h2 { font-size: 14pt }h1 { font-size: 16pt }blockquote {padding: 10px; border: 1px #DDD dashed }a img {border: 0}div.google_header, div.google_footer { position: relative; margin-top: 1em; margin-bottom: 1em;}/* end default css */ /* default print css */ @media print { body { padding: 0; margin: 0; } div.google_header, div.google_footer { display: block; min-height: 0; border: none; } div.google_header { flow: static(header); } /* used to insert page numbers */ div.google_header::before, div.google_footer::before { position: absolute; top: 0; } div.google_footer { flow: static(footer); } /* always consider this element at the start of the doc */ div#google_footer { flow: static(footer, start); } span.google_pagenumber { content: counter(page); } span.google_pagecount { content: counter(pages); } } @page { @top { content: flow(header); } @bottom { content: flow(footer); } } /* end default print css */ /* custom css *//* end custom css */ /* ui edited css */ body { font-family: Verdana; font-size: 10.0pt; line-height: normal; background-color: #ffffff; } .documentBG { background-color: #ffffff; } /* end ui edited css */</style> </head> <body revision="dcbsxfpf_53ct2cm7f4:4"> <table align=center cellpadding=0 cellspacing=0 height=5716 width=768>
<tbody>
<tr>
<td height=5716 valign=top width=100%>
<pre>2006-5-23 <br>mm/mprotect.c<br><br> 本模块只提供一个系统调用,而无其他接口。这个系统调用就是sys_mprotect.<br>系统调用sys_mprotect(unsigned long start, size_t len, unsigned long prot)<br>改变地址范围[start,addr+len-1]涉及到的物理页面的保护方式。对于i386就是<br>改变pte中的__pgprot。<br> 其中prot可用的参数有:<br> PROT_WRITE/PROT_READ/PROT_EXEC<br> PROT_NONE:此段内存不能被访问.<br> 新设置的属性会完全取代现有属性,而不是叠加到现有属性上.<br> <br> 此系统调用实现起来也不复杂,思路也常见了:遍历涉及到的vma,根据属性的改<br>变进行fixup(这个东西看到好几次了),同时设置所涉及之pte的prot属性.<br><br> 不再进行更详尽的分析了,简单看看函数:<br>asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot)<br>{<br> unsigned long nstart, end, tmp;<br> struct vm_area_struct * vma, * next;<br> int error = -EINVAL;<br><br> if (start & ~PAGE_MASK) //起始地址必须位于页边界<br> return -EINVAL;<br> len = PAGE_ALIGN(len);//长度扩大到最后一个page的末尾(大于给定范围)<br> end = start + len;<br> if (end < start)<br> return -EINVAL;<br> if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))//仅容许使用这几位<br> return -EINVAL;<br> if (end == start)<br> return 0;<br><br> down(&current->mm->mmap_sem);<br><br> vma = find_vma(current->mm, start);//start<vm_end<br> error = -EFAULT;<br> if (!vma || vma->vm_start > start)<br> goto out;<br><br> for (nstart = start ; ; ) {<br> unsigned int newflags;<br><br> /* Here we know that vma->vm_start <= nstart < vma->vm_end. */<br><br> newflags = prot | (vma->vm_flags & ~(PROT_READ | PROT_WRITE | PROT_EXEC));<br> if ((newflags & ~(newflags >> 4)) & 0xf) {<br> //高四位代表内核所授予的权限,VM_MAYREAD,...<br> //PROT_xxx分别等于VM_XXX,代表当前所拥有的权限<br> //不能超越VM_MAYxxx,即高4位所代表的权限<br> error = -EACCES;<br> break;<br> }<br><br> if (vma->vm_end >= end) {//last vma <br> error = mprotect_fixup(vma, nstart, end, newflags);<br> break;<br> }<br><br> tmp = vma->vm_end;<br> next = vma->vm_next;<br> error = mprotect_fixup(vma, nstart, tmp, newflags);<br> //xxxx_fixup都要求 nstart,tep在vma_start到vma_end之间<br> <br> if (error)<br> break;<br> nstart = tmp;<br> vma = next;<br> if (!vma || vma->vm_start != nstart) {<br> error = -EFAULT;<br> break;<br> }<br> }<br>out:<br> up(&current->mm->mmap_sem);<br> return error;<br>}<br><br> 次函数使用的fixup函数,以及改变pte的prot的部分不再做详细分析,重点注意<br>下面几个问题: <br>1)pmd_bad<br>static inline void change_pte_range(pmd_t * pmd, unsigned long address,<br> unsigned long size, pgprot_t newprot)<br>{<br> pte_t * pte;<br> unsigned long end;<br><br> if (pmd_none(*pmd))<br> return;<br> if (pmd_bad(*pmd)) { //以前分析过pmd_bad,如果用户页面出了问题<br> pmd_ERROR(*pmd); //就作记录<br> pmd_clear(pmd); //清除pte<br> return; //当内核页面bad的时候,可以参考get_pte_slow<br> }<br>.....<br>}<br><br><br>2.vm flags 到pte prot的转化表 <br>static int mprotect_fixup(struct vm_area_struct * vma, <br> unsigned long start, unsigned long end, unsigned int newflags)<br>{<br> pgprot_t newprot;<br> int error;<br><br> if (newflags == vma->vm_flags)<br> return 0;<br> newprot = protection_map[newflags & 0xf];//2^4种组合见<br> //protection_map<br> <br> .....<br>}<br>}<br></pre>
</td>
</tr>
</tbody>
</table>
//protection_map<br>
<br>
.....<br>
}<br>
}</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -