文章目录
参考
https://man7.org/linux/man-pages/man2/mprotect.2.html
https://mzhan017.blog.csdn.net/article/details/120192676
实例代码
[root@10 test]# more mprotect.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <errno.h>
#include <unistd.h>
int main()
{
char * remain;
char abc[10];
long addr=((long)(abc)+4096-1)&~(4096-1);
printf("addr = 0x%x, abc=0x%x\n", addr,&abc);
int rc=mprotect((void *)addr, 4096, PROT_NONE);
if(rc != 0 )
printf("has error to set mprotect err=%d\n", errno);
strncpy(abc,"abc;def",10);
char * temp = strtok_r(abc, ";", &remain);
printf("abc=%s, temp=%s, remain=%s\n", abc, temp, remain);
sleep(300);
}
输出
[root@10 test]# ./a.out &
[1] 1669
[root@10 test]# addr = 0x6a014000, abc=0x6a013cc6
abc=abc, temp=abc, remain=def
[root@10 test]# ps -ef | grep a.out
root 1669 1472 0 13:59 pts/0 00:00:00 [a.out]
root 1671 1472 0 13:59 pts/0 00:00:00 grep --color=auto a.out
[root@10 test]# cd /proc/1669
[root@10 1669]# more maps
00400000-00401000 r-xp 00000000 fd:00 101567304 /root/test/a.out
00600000-00601000 r--p 00000000 fd:00 101567304 /root/test/a.out
00601000-00602000 rw-p 00001000 fd:00 101567304 /root/test/a.out
00a20000-00a41000 rw-p 00000000 00:00 0 [heap]
7f540578c000-7f5405948000 r-xp 00000000 fd:00 100673745 /usr/lib64/libc-2.28.so
7f5405948000-7f5405b47000 ---p 001bc000 fd:00 100673745 /usr/lib64/libc-2.28.so
7f5405b47000-7f5405b4b000 r--p 001bb000 fd:00 100673745 /usr/lib64/libc-2.28.so
7f5405b4b000-7f5405b4d000 rw-p 001bf000 fd:00 100673745 /usr/lib64/libc-2.28.so
7f5405b4d000-7f5405b51000 rw-p 00000000 00:00 0
7f5405b51000-7f5405b7e000 r-xp 00000000 fd:00 100673737 /usr/lib64/ld-2.28.so
7f5405d76000-7f5405d78000 rw-p 00000000 00:00 0
7f5405d7e000-7f5405d7f000 r--p 0002d000 fd:00 100673737 /usr/lib64/ld-2.28.so
7f5405d7f000-7f5405d81000 rw-p 0002e000 fd:00 100673737 /usr/lib64/ld-2.28.so
7fff69ff4000-7fff6a014000 rw-p 00000000 00:00 0 [stack]
7fff6a014000-7fff6a015000 ---p 00000000 00:00 0 、、、、、 这里可以看到
7fff6a16a000-7fff6a16e000 r--p 00000000 00:00 0 [vvar]
7fff6a16e000-7fff6a170000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
注意事项
第一个参数,要以页为边界起始;一次性,最少一个内存页,4096,个字节。
有没有粒度更小的机制
没有
kernel 对应的code
/*
* pkey==-1 when doing a legacy mprotect()
*/
static int do_mprotect_pkey(unsigned long start, size_t len,
unsigned long prot, int pkey)
{
用途
在内存被写坏的case里也许可以作为保护的方式,查找是谁写坏了内存,栈上的或者堆上的。
google test,会使用这个功能,来修改代码块内存。
遇到的问题
如果频繁调用mprotect函数,对应的flush_tlb_mm_range函数的占用也会增多。
- 9.36% ngss libc-2.28.so [.] __mprotect `
- __mprotect a
- 5.23% abc [kernel.kallsyms] [k] flush_tlb_mm_range a
flush_tlb_mm_range a
change_protection a
mprotect_fixup a
do_mprotect_pkey a
__x64_sys_mprotect a
do_syscall_64 a
entry_SYSCALL_64_after_hwframe a - __mprotect a