免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
1234下一页
最近访问板块 发新帖
查看: 11510 | 回复: 37
打印 上一主题 下一主题

Linux内核的代码段是只读的吗?进程的代码段呢? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-07-08 21:07 |只看该作者 |倒序浏览
在操作系统原理中,书上一般都会讲代码段是只读的。
Linux跳过了X86处理器的分段机制,那么Linux内核的代码段还是只读的吗?

论坛徽章:
0
2 [报告]
发表于 2010-07-08 22:45 |只看该作者
大部分是只读, 可以用PAGE来设置权限.不一定要用SEGMENTATION.

论坛徽章:
0
3 [报告]
发表于 2010-07-08 23:17 |只看该作者
本帖最后由 kgn28 于 2010-07-09 09:24 编辑

页表项有读写权限,线性区也有读写权限,对一个页的读取是通过这两者控制的。代码段是不是只读,这个看你自己的设计,你想让他只读就只读呗,关键是要理解在那里控制这些权限。

论坛徽章:
0
4 [报告]
发表于 2010-07-09 02:46 |只看该作者
"线性区" 具体是指什么啊?

论坛徽章:
0
5 [报告]
发表于 2010-07-09 08:16 |只看该作者
回复 4# accessory


    vm_area_struct?

论坛徽章:
0
6 [报告]
发表于 2010-07-09 10:41 |只看该作者
回复 4# accessory


是我搞错了,内核不需要线性区(vm_area_struct)。

如果是用户空间的,访问权限保护:
1,页表项的 Read/Write。
2,页描述符的flags。
3,线性区的标识符vm_flags。

内核页表初始化没看懂,如果要保护内核代码段应该把Read/Write置为0吧?

论坛徽章:
0
7 [报告]
发表于 2010-07-10 04:14 |只看该作者
大概是吧。 不过LINUX有时把代码和数据放在同一个页面上的。

论坛徽章:
0
8 [报告]
发表于 2010-07-10 13:44 |只看该作者
还是不明白,在《深入理解Linux内核》的145页,描述中断和异常的硬件处理时,讲到GDT中的段描述符指定中断或者异常处理程序所在段的基地址。Linux不是已经跳过了分段机制吗?如果跳过了分段机制,那段描述符里所描述的段基地址不应该都是0x00000000吗?

论坛徽章:
0
9 [报告]
发表于 2010-07-10 14:30 |只看该作者
回复 8# superhappy1


    那个不是段描述符所在的地址,而是段的基地址,而且最关键的是不同的段描述符可以识别出是在内核态还是用户态,就是等级不同。

论坛徽章:
0
10 [报告]
发表于 2010-07-12 16:18 |只看该作者
回复  accessory

内核页表初始化没看懂,如果要保护内核代码段应该把Read/Write置为0吧?
kgn28 发表于 2010-07-09 10:41



很奇怪,代码里似乎不是这样的,函数调用流程如下

  1. start_kernel() --> setup_arch() --> paging_init() --> pagetable_init() --> kernel_physical_mapping_init()
复制代码

  1. static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
  2. {
  3.         unsigned long pfn;
  4.         pgd_t *pgd;
  5.         pmd_t *pmd;
  6.         pte_t *pte;
  7.         int pgd_idx, pmd_idx, pte_ofs;

  8.         pgd_idx = pgd_index(PAGE_OFFSET);
  9.         pgd = pgd_base + pgd_idx;
  10.         pfn = 0;

  11.         for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++)
  12.         {
  13.                 pmd = one_md_table_init(pgd);
  14.                 if (pfn >= max_low_pfn)
  15.                         continue;
  16.                
  17.                 for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++)
  18.                 {
  19.                         unsigned int address = pfn * PAGE_SIZE + PAGE_OFFSET;

  20.                         /* Map with big pages if possible, otherwise create normal page tables. */
  21.                         if (cpu_has_pse)
  22.                         {
  23.                                 unsigned int address2 = (pfn + PTRS_PER_PTE - 1) * PAGE_SIZE + PAGE_OFFSET + PAGE_SIZE-1;

  24.                                 if (is_kernel_text(address) || is_kernel_text(address2))
  25.                                         set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC));
  26.                                 else
  27.                                         set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
  28.                                 pfn += PTRS_PER_PTE;
  29.                         }
  30.                         else
  31.                         {
  32.                                 pte = one_page_table_init(pmd);

  33.                                 for (pte_ofs = 0; pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn; pte++, pfn++, pte_ofs++)
  34.                                 {
  35.                                                 if (is_kernel_text(address))
  36.                                                         set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
  37.                                                 else
  38.                                                         set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));
  39.                                 }
  40.                         }
  41.                 }
  42.         }
  43. }
复制代码
注意这一段:

  1.                                                 if (is_kernel_text(address))
  2.                                                         set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
  3.                                                 else
  4.                                                         set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));



  5. #define PAGE_KERNEL_EXEC        __pgprot(__PAGE_KERNEL_EXEC)

  6. unsigned long long __PAGE_KERNEL_EXEC = _PAGE_KERNEL_EXEC;

  7. #define _PAGE_KERNEL_EXEC \
  8.         (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
复制代码
这里置上了 _PAGE_RW ,说明kernel text也是读写允许的。。。。

哪位能指点下?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP