導航:首頁 > 操作系統 > linuxptrace

linuxptrace

發布時間:2023-03-27 21:30:57

linux系統top給出的信息都有哪些

Linux新手,個人認為首先就應該了解一下top命令各項的含義.
不用有事就問什麼搜索引擎,先看看man top.
top - 16:12:56 up 1 day, 22 min, 4 users, load average: 0.02, 0.04, 0.05
Tasks: 158 total, 1 running, 156 sleeping, 0 stopped, 1 zombie
%Cpu(s): 0.7 us, 0.3 sy, 0.0 ni, 98.8 id, 0.1 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 1017912 total, 895892 used, 122020 free, 15312 buffers
KiB Swap: 1045500 total, 19608 used, 1025892 free. 230012 cached Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
5761 eechen 20 0 32144 1548 1076 R 6.2 0.2 0:00.01 top

16:12:56 up 1 day, 22 min, 4 users, load average: 0.02, 0.04, 0.05

這句等同於執行 uptime 命令返回的內容.
16:12:56 是當前時間(date).
up 1 day, 22 min 表示系統已經運行1天又22分鍾(uptime -p).
4 users 表示當前登錄系統的用戶(w,who).
load average 表示系統負載,分別是1分鍾,5分鍾,15分鍾前到現在的負載平均值.
Tasks: 158 total 表示系統的進程數(數目等於ps -ef|wc -l的值減去2),按大寫H可以切換到線程模式.
running表示正在運行的進程,sleeping表示睡眠的進程,stopped表示暫停的進程,zombie表示已結束但還沒有從進程表中刪除的僵屍進程.
total表示總內存,used表示已經使用的內存,free表示空閑的內存,按E可以切換單位.
buffers(Buffer Cache)表示塊設備的讀寫緩沖區佔用的內存,cached(Page Cache)表示文件系統緩存佔用的內存.
buffers:塊設備緩沖 cached:文件系統緩存
如果cached的值很大,說明cache住的文件數很多.如果頻繁訪問到的文件都能被cache住,那麼磁碟的讀I/O就非常小.
所謂塊設備是指對其信息的存取以"塊"為單位,如通常的光碟,硬磁碟,軟磁碟,磁帶等,塊長取512位元組或1024位元組或4096位元組.
塊設備可以直接通過塊設備特別文件來訪問,為了提高數據傳輸效率,塊設備驅動程序內部採用塊緩沖技術.
Swap是交換空間,交換空間在物理內存(RAM)被充滿時被使用.
如果系統需要更多的內存資源,而物理內存已經充滿,內存中不活躍的頁就會被移到交換空間去.
雖然交換空間可以為帶有少量內存的機器提供幫助,但是這種方法不應該被當做是對內存的取代.
交換空間位於硬碟驅動器上,它比進入物理內存要慢.
load average的理解:
load average指的是處於task_running或task_uninterruptible狀態的進程(或線程)數的平均值.
處於task_running狀態的進程(或線程),可能正在使用CPU或排隊等待使用CPU.
處於task_uninterruptible狀態的進程(或線程),可能正在等待I/O,比如等待磁碟I/O.這時I/O等待佔用的CPU時間百分比iowait(wa)可能會比較高.
sudo strace -p `pidof top` 可見top從/proc讀取了很多信息.
man proc 查看 /proc/loadavg 的說明:
man proc | col -b > proc.txt
/proc/loadavg 內容:
0.22 0.13 0.14 2/374 5306

0.22 0.13 0.14表示在過去的1分鍾,5分鍾,15分鍾,
正在運行(task_running)或等待IO(task_uninterruptible)的任務的數量.
2/374中的2表示當前運行的線程數,374則表示系統當前存在的內核調度實體(進程/線程)的數量.
5306是系統最近創建的進程PID編號.
又比如:
load average: 31.09, 29.87, 29.92

表示在過去的1分鍾,5分鍾,15分鍾的時間里,CPU任務隊列中平均有30個程序(這里應該是30個java線程)在使用CPU.
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
20248 root 20 0 0.227t 0.012t 18748 S 3090 5.2 29812:58 java

Java進程的CPU使用率%CPU達到3090%,表示這個Java進程正在使用31個CPU核心,
這樣對上了上面load average得出的數據,也就是有30個左右的Java線程正在使用30個CPU核心.
按H(區分大小寫)切換到線程模式,因為一個線程最多隻能使用一個核心,所以線程模式下顯示的CPU使用率不會超過100%.
當CPU和磁碟都忙不過來的時候,開再多的進程也沒有任何意義,只會徒增CPU上下文切換和磁碟I/O等待,得不償失.
系統負載高,普遍是因為系統進程數太多,I/O太多導致的.
load average小於1表示系統空閑,大於1表示系統開始繁忙.
Linux伺服器的任務(進程)數量保持在200個以下是比較好的,最好不要超過300個.
us, user : time running un-niced user processes 用戶空間進程佔用CPU時間百分比
sy, system : time running kernel processes 內核進程佔用CPU時間百分比
ni, nice : time running niced user processes 用戶空間內改變過優先順序的進程佔用CPU時間百分比
id, idle : time spent in the kernel idle handler 空閑CPU時間百分比(100%表示系統完全空閑)
wa, iowait : time waiting for I/O completion I/O等待佔用的CPU時間百分比
hi : time spent servicing hardware interrupts 硬體中斷佔用CPU時間百分比
si : time spent servicing software interrupts 軟體中斷佔用CPU時間百分比
st : time stolen from this vm by the hypervisor 虛擬化hypervisor從當前虛擬機vm偷走的時間
如果st這個值很高的話,說明你的VPS提供商的CPU資源有限,而你沒能搶過別人,很有可能就是VPS提供商超售了.

按F選擇要顯示的列和查看每列的含義,默認有下面這些列:
PID = Process Id
USER = Effective User Name
PR = Priority PR和NI的值越高越友好即越不競爭資源,比如PR 20和NI 0,另外,PR=NI+20.
NI = Nice Value 負值表示高優先順序,正值表示低優先順序,比如kworker的NI為-20,PR為0.
VIRT = Virtual Image (KiB)
RES = Resident Size (KiB) 常駐內存,按E切換單位.
SHR = Shared Memory (KiB)
S = Process Status
%CPU = CPU Usage 四核處理器在Tasks模式下滿載為400%,在Threads模式(按H切換)下滿載為100%(一個線程最多隻能使用一個核心).按Shift+P按CPU使用率排序.
%MEM = Memory Usage (RES) 滿載為100%,按Shift+M按RES內存排序.
TIME+ = CPU Time, hundredths 進程使用的CPU時間總計.比如2:32.45代表2分鍾32.45秒.
COMMAND = Command Name/Line

按F進入域管理窗口後按A可以切換顯示模式,按空格選中要顯示的列,按S按指定列排序,用向右方向鍵選中列後可以調整順序.修改後按Shift+W保存設置到~/.toprc文件.
top裡面按Shift+M是按內存排序,按E是切換內存單位,按Shfit+W保存設置.
然後執行top -n1 -b可以看到按內存排序的所有進程的信息.
或者ps後用sort排序:
ps aux | sort -k4nr | head -n5

top里按C或者使用-c參數可以看到進程的絕對路徑和啟動參數,就可以得到類似ps -ef和ps aux提供的信息了.
看進程路徑: top -p `pidof firefox` -c -n1
看進程線程: top -p `pidof firefox` -H -n1

Linux Process Status:
http://blog.csdn.net/tianlesoftware/article/details/6457487
R (task_running) : 可執行狀態
S (task_interruptible): 可中斷的睡眠狀態
D (task_uninterruptible): 不可中斷的睡眠狀態
T (task_stopped or task_traced): 暫停狀態或跟蹤狀態
Z (task_dead - exit_zombie): 退出狀態,進程成為僵屍進程
X (task_dead - exit_dead): 退出狀態,進程即將被銷毀
running進程:
只有在該狀態的進程才可能在CPU上運行。
而同一時刻可能有多個進程處於可執行狀態,這些進程的task_struct結構(進程式控制制塊)被放入對應CPU的可執行隊列中(一個進程最多隻能出現在一個CPU的可執行隊列中)。
進程調度器的任務就是從各個CPU的可執行隊列中分別選擇一個進程在該CPU上運行。
很多操作系統教科書將正在CPU上執行的進程定義為RUNNING狀態、而將可執行但是尚未被調度執行的進程定義為READY狀態,這兩種狀態在Linux下統一為TASK_RUNNING狀態。
sleeping進程:
處於這個狀態的進程因為等待某某事件的發生(比如等待socket連接、等待信號量),而被掛起。
這些進程的task_struct結構被放入對應事件的等待隊列中。當這些事件發生時(由外部中斷觸發、或由其他進程觸發),對應的等待隊列中的一個或多個進程將被喚醒。
通過ps命令我們會看到,一般情況下,進程列表中的絕大多數進程都處於task_interruptible狀態(除非機器的負載很高)。
畢竟CPU就這么一兩個,進程動輒幾十上百個,如果不是絕大多數進程都在睡眠,CPU又怎麼響應得過來。
stopped進程:
向進程發送一個sigstop信號,它就會因響應該信號而進入task_stopped狀態,除非該進程本身處於task_uninterruptible狀態而不響應信號。
sigstop與sigkill信號一樣,是非常強制的。不允許用戶進程通過signal系列的系統調用重新設置對應的信號處理函數。
向進程發送一個sigcont信號,可以讓其從task_stopped狀態恢復到task_running狀態。
當進程正在被跟蹤時,它處於task_traced這個特殊的狀態。「正在被跟蹤」指的是進程暫停下來,等待跟蹤它的進程對它進行操作。
比如在gdb中對被跟蹤的進程下一個斷點,進程在斷點處停下來的時候就處於task_traced狀態。而在其他時候,被跟蹤的進程還是處於前面提到的那些狀態。
對於進程本身來說,task_stopped和task_traced狀態很類似,都是表示進程暫停下來。
而task_traced狀態相當於在task_stopped之上多了一層保護,處於task_traced狀態的進程不能響應sigcont信號而被喚醒。
只能等到調試進程通過ptrace系統調用執行ptrace_cont、ptrace_detach等操作(通過ptrace系統調用的參數指定操作),或調試進程退出,被調試的進程才能恢復task_running狀態。
zombie進程:
在Linux進程的狀態中,僵屍進程是非常特殊的一種,它是已經結束了的進程,但是沒有從進程表中刪除。
太多了會導致進程表裡面條目滿了,進而導致系統崩潰,倒是不佔用其他系統資源。
它已經放棄了幾乎所有內存空間,沒有任何可執行代碼,也不能被調度,
僅僅在進程列表中保留一個位置,記載該進程的退出狀態等信息供其他進程收集,除此之外,僵屍進程不再佔有任何內存空間。
進程在退出的過程中,處於TASK_DEAD狀態。在這個退出過程中,進程佔有的所有資源將被回收,除了task_struct結構(以及少數資源)以外。
於是進程就只剩下task_struct這么個空殼,故稱為僵屍。
之所以保留task_struct,是因為task_struct裡面保存了進程的退出碼、以及一些統計信息。
而其父進程很可能會關心這些信息。比如在shell中,$?變數就保存了最後一個退出的前台進程的退出碼,而這個退出碼往往被作為if語句的判斷條件。
當然,內核也可以將這些信息保存在別的地方,而將task_struct結構釋放掉,以節省一些空間。
但是使用task_struct結構更為方便,因為在內核中已經建立了從pid到task_struct查找關系,還有進程間的父子關系。
釋放掉task_struct,則需要建立一些新的數據結構,以便讓父進程找到它的子進程的退出信息。
子進程在退出的過程中,內核會給其父進程發送一個信號,通知父進程來「收屍」。
父進程可以通過wait系列的系統調用(如wait4、waitid)來等待某個或某些子進程的退出,並獲取它的退出信息。
然後wait系列的系統調用會順便將子進程的屍體(task_struct)也釋放掉。
這個信號默認是SIGCHLD,但是在通過clone系統調用創建子進程時,可以設置這個信號。
如果他的父進程沒安裝SIGCHLD信號處理函數調用wait或waitpid()等待子進程結束,又沒有顯式忽略該信號,那麼它就一直保持僵屍狀態,子進程的屍體(task_struct)也就無法釋放掉。
如果這時父進程結束了,那麼init進程自動會接手這個子進程,為它收屍,它還是能被清除的。
但是如果如果父進程是一個循環,不會結束,那麼子進程就會一直保持僵屍狀態,這就是為什麼系統中有時會有很多的僵屍進程。
當進程退出的時候,會將它的所有子進程都託管給別的進程(使之成為別的進程的子進程)。
託管的進程可能是退出進程所在進程組的下一個進程(如果存在的話),或者是1號進程。
所以每個進程、每時每刻都有父進程存在。除非它是1號進程。1號進程,pid為1的進程,又稱init進程。
Linux系統啟動後,第一個被創建的用戶態進程就是init進程。它有兩項使命:
1、執行系統初始化腳本,創建一系列的進程(它們都是init進程的子孫);
2、在一個死循環中等待其子進程的退出事件,並調用waitid系統調用來完成「收屍」工作;
init進程不會被暫停、也不會被殺死(這是由內核來保證的)。它在等待子進程退出的過程中處於task_interruptible狀態,「收屍」過程中則處於task_running狀態。

Ⅱ 如何利用Ptrace攔截和模擬Linux系統調用

這里的「攔截」我指的是tracer能夠改變系統調用參數,改變系統調用的返回值,甚至屏蔽特定的系統調用。這也就意亮蔽味著,一個tracer將能夠完全實現自己的系統調用,這就非常有趣了,也就是說,一個tracer將可以模擬出一整套操作系統機制,而且這一切都不需要內核提供任何其他幫助。
但問題在於,一個進程一次只能夠綁定一個tracer,因此我們無法在調試進程(GDB)的過程中模擬出一套外部操作系統,而另一個問題就是模擬系統調用將耗費更多的資源開銷。
在敬罩州這篇文章中,我將主要討論x86-64架構下悶晌的Linux Ptrace,並且我還會使用到一些特定的Linux擴展。除此之外,我可能會忽略錯誤檢查,但最終發布的完整源碼將會解決這些問題。

Ⅲ 怎樣查詢linux系統調用函數

以下是Linux系統調用的一個列表,包含了大部分常用系統調用和由系統調用派生出的的函數。這可能是你在互聯網上所能看到的唯一一篇中文注釋的Linux系統調用列表,即使是簡單的字母序英文列表,能做到這么完全也是很罕見的。
按照慣例,這個列表以man pages第2節,即系統調用節為藍本。按照筆者的理解,對其作了大致的分類,同時也作了一些小小的修改,刪去了幾個僅供內核使用,不允許用戶調用的系統調用,對個別本人稍覺不妥的地方作了一些小的修改,並對所有列出的系統調用附上簡要注釋。
其中有一些函數的作用完全相同,只是參數不同。(可能很多熟悉C++朋友馬上就能聯想起函數重載,但是別忘了Linux核心是用C語言寫的,所以只能取成不同的函數名)。還有一些函數已經過時,被新的更好的函數所代替了(gcc在鏈接這些函數時會發出警告),但因為兼容的原因還保留著,這些函數我會在前面標上「*」號以示區別。
一、進程式控制制:
fork 創建一個新進程
clone 按指定條件創建子進程
execve 運行可執行文件
exit 中止進程
_exit 立即中止當前進程
getdtablesize 進程所能打開的最大文件數
getpgid 獲取指定進程組標識號
setpgid 設置指定進程組標志號
getpgrp 獲取當前進程組標識號
setpgrp 設置當前進程組標志號
getpid 獲取進程標識號
getppid 獲取父進程標識號
getpriority 獲取調度優先順序
setpriority 設置調度優先順序
modify_ldt 讀寫進程的本地描述表
nanosleep 使進程睡眠指定的時間
nice 改變分時進程的優先順序
pause 掛起進程,等待信號
personality 設置進程運行域
prctl 對進程進行特定操作
ptrace 進程跟蹤
sched_get_priority_max 取得靜態優先順序的上限
sched_get_priority_min 取得靜態優先順序的下限
sched_getparam 取得進程的調度參數
sched_getscheler 取得指定進程的調度策略
sched_rr_get_interval 取得按RR演算法調度的實時進程的時間片長度
sched_setparam 設置進程的調度參數
sched_setscheler 設置指定進程的調度策略和參數
sched_yield 進程主動讓出處理器,並將自己等候調度隊列隊尾
vfork 創建一個子進程,以供執行新程序,常與execve等同時使用
wait 等待子進程終止
wait3 參見wait
waitpid 等待指定子進程終止
wait4 參見waitpid
capget 獲取進程許可權
capset 設置進程許可權
getsid 獲取會晤標識號
setsid 設置會晤標識號

二、文件系統控制
1、文件讀寫操作
fcntl 文件控制
open 打開文件
creat 創建新文件
close 關閉文件描述字
read 讀文件
write 寫文件
readv 從文件讀入數據到緩沖數組中
writev 將緩沖數組里的數據寫入文件
pread 對文件隨機讀
pwrite 對文件隨機寫
lseek 移動文件指針
_llseek 在64位地址空間里移動文件指針
p 復制已打開的文件描述字
p2 按指定條件復制文件描述字
flock 文件加/解鎖
poll I/O多路轉換
truncate 截斷文件
ftruncate 參見truncate
umask 設置文件許可權掩碼
fsync 把文件在內存中的部分寫回磁碟
2、文件系統操作
access 確定文件的可存取性
chdir 改變當前工作目錄
fchdir 參見chdir
chmod 改變文件方式
fchmod 參見chmod
chown 改變文件的屬主或用戶組
fchown 參見chown
lchown 參見chown
chroot 改變根目錄
stat 取文件狀態信息
lstat 參見stat
fstat 參見stat
statfs 取文件系統信息
fstatfs 參見statfs
readdir 讀取目錄項
getdents 讀取目錄項
mkdir 創建目錄
mknod 創建索引節點
rmdir 刪除目錄
rename 文件改名
link 創建鏈接
symlink 創建符號鏈接
unlink 刪除鏈接
readlink 讀符號鏈接的值
mount 安裝文件系統
umount 卸下文件系統
ustat 取文件系統信息
utime 改變文件的訪問修改時間
utimes 參見utime
quotactl 控制磁碟配額

三、系統控制
ioctl I/O總控制函數
_sysctl 讀/寫系統參數
acct 啟用或禁止進程記賬
getrlimit 獲取系統資源上限
setrlimit 設置系統資源上限
getrusage 獲取系統資源使用情況
uselib 選擇要使用的二進制函數庫
ioperm 設置埠I/O許可權
iopl 改變進程I/O許可權級別
outb 低級埠操作
reboot 重新啟動
swapon 打開交換文件和設備
swapoff 關閉交換文件和設備
bdflush 控制bdflush守護進程
sysfs 取核心支持的文件系統類型
sysinfo 取得系統信息
adjtimex 調整系統時鍾
alarm 設置進程的鬧鍾
getitimer 獲取計時器值
setitimer 設置計時器值
gettimeofday 取時間和時區
settimeofday 設置時間和時區
stime 設置系統日期和時間
time 取得系統時間
times 取進程運行時間
uname 獲取當前UNIX系統的名稱、版本和主機等信息
vhangup 掛起當前終端
nfsservctl 對NFS守護進程進行控制
vm86 進入模擬8086模式
create_mole 創建可裝載的模塊項
delete_mole 刪除可裝載的模塊項
init_mole 初始化模塊
query_mole 查詢模塊信息
*get_kernel_syms 取得核心符號,已被query_mole代替

四、內存管理
brk 改變數據段空間的分配
sbrk 參見brk
mlock 內存頁面加鎖
munlock 內存頁面解鎖
mlockall 調用進程所有內存頁面加鎖
munlockall 調用進程所有內存頁面解鎖
mmap 映射虛擬內存頁
munmap 去除內存頁映射
mremap 重新映射虛擬內存地址
msync 將映射內存中的數據寫回磁碟
mprotect 設置內存映像保護
getpagesize 獲取頁面大小
sync 將內存緩沖區數據寫回硬碟
cacheflush 將指定緩沖區中的內容寫回磁碟

五、網路管理
getdomainname 取域名
setdomainname 設置域名
gethostid 獲取主機標識號
sethostid 設置主機標識號
gethostname 獲取本主機名稱
sethostname 設置主機名稱

六、socket控制
socketcall socket系統調用
socket 建立socket
bind 綁定socket到埠
connect 連接遠程主機
accept 響應socket連接請求
send 通過socket發送信息
sendto 發送UDP信息
sendmsg 參見send
recv 通過socket接收信息
recvfrom 接收UDP信息
recvmsg 參見recv
listen 監聽socket埠
select 對多路同步I/O進行輪詢
shutdown 關閉socket上的連接
getsockname 取得本地socket名字
getpeername 獲取通信對方的socket名字
getsockopt 取埠設置
setsockopt 設置埠參數
sendfile 在文件或埠間傳輸數據
socketpair 創建一對已聯接的無名socket

七、用戶管理
getuid 獲取用戶標識號
setuid 設置用戶標志號
getgid 獲取組標識號
setgid 設置組標志號
getegid 獲取有效組標識號
setegid 設置有效組標識號
geteuid 獲取有效用戶標識號
seteuid 設置有效用戶標識號
setregid 分別設置真實和有效的的組標識號
setreuid 分別設置真實和有效的用戶標識號
getresgid 分別獲取真實的,有效的和保存過的組標識號
setresgid 分別設置真實的,有效的和保存過的組標識號
getresuid 分別獲取真實的,有效的和保存過的用戶標識號
setresuid 分別設置真實的,有效的和保存過的用戶標識號
setfsgid 設置文件系統檢查時使用的組標識號
setfsuid 設置文件系統檢查時使用的用戶標識號
getgroups 獲取後補組標志清單
setgroups 設置後補組標志清單

八、進程間通信
ipc 進程間通信總控制調用
1、信號
sigaction 設置對指定信號的處理方法
sigprocmask 根據參數對信號集中的信號執行阻塞/解除阻塞等操作
sigpending 為指定的被阻塞信號設置隊列
sigsuspend 掛起進程等待特定信號
signal 參見signal
kill 向進程或進程組發信號
*sigblock 向被阻塞信號掩碼中添加信號,已被sigprocmask代替
*siggetmask 取得現有阻塞信號掩碼,已被sigprocmask代替
*sigsetmask 用給定信號掩碼替換現有阻塞信號掩碼,已被sigprocmask代替
*sigmask 將給定的信號轉化為掩碼,已被sigprocmask代替
*sigpause 作用同sigsuspend,已被sigsuspend代替
sigvec 為兼容BSD而設的信號處理函數,作用類似sigaction
ssetmask ANSI C的信號處理函數,作用類似sigaction
2、消息
msgctl 消息控制操作
msgget 獲取消息隊列
msgsnd 發消息
msgrcv 取消息
3、管道
pipe 創建管道
4、信號量
semctl 信號量控制
semget 獲取一組信號量
semop 信號量操作
5、共享內存
shmctl 控制共享內存
shmget 獲取共享內存
shmat 連接共享內存
shmdt 拆卸共享內存

Ⅳ linux內核有沒有hook機制

有啊,一切順序邏輯,都有被hook的可能。 下面是一個linux上的hook的實例

截獲write系統調用:

#ifndefMODULE
#defineMODULE
#endif

#ifndef__KERNEL__
#define__KERNEL__
#endif
#include<linux/init.h>
#include<linux/mole.h>
#include<linux/version.h>
#include<linux/kernel.h>
#include<asm/unistd.h>
#include<linux/slab.h>
/*
#include<sys/types.h>
#include<asm/fcntl.h>
#include<linux/malloc.h>
#include<linux/types.h>
#include<linux/string.h>
#include<linux/fs.h>
#include<asm/errno.h>
#include<sys/syscall.h>
*/
MODULE_LICENSE("GPL");
structdescriptor_idt
{
unsignedshortoffset_low;
unsignedshortignore1;
unsignedshortignore2;
unsignedshortoffset_high;
};
staticstruct{
unsignedshortlimit;
unsignedlongbase;
}__attribute__((packed))idt48;
staticunsignedintSYS_CALL_TABLE_ADDR;
void**sys_call_table;
intbase_system_call;
int(*orig_write)(unsignedintfd,char*buf,unsignedintcount);
unsignedcharopcode_call[3]={0xff,0x14,0x85};
intmatch(unsignedchar*source)
{
inti;
for(i=0;i<3;i++){
if(source[i]!=opcode_call[i])
return0;
}
return1;
}
intget_sys_call_table(void)
{
inti,j;
unsignedchar*ins=(unsignedchar*)base_system_call;
unsignedintsct;

for(i=0;i<100;i++){
if(ins[i]==opcode_call[0]){
if(match(ins+i)){
sct=*((unsignedint*)(ins+3+i));
printk(KERN_ALERT"sys_call_tabl'saddressis
0x%X ",sct);
returnsct;
}
}
}

printk(KERN_ALERT"can'tfindtheaddressofsys_call_table ");
return-1;
}
inthacked_write(unsignedintfd,char*buf,unsignedintcount)
{
char*hide="hello";
if(strstr(buf,hide)!=NULL){
printk(KERN_ALERT"findname. ");
returncount;
}
else{
returnorig_write(fd,buf,count);
}
}
intinit_mole(void)
{
__asm__volatile("sidt%0":"=m"(idt48));
structdescriptor_idt*pIdt80=(structdescriptor_idt*)(idt48.base+8*0x80);
base_system_call=(pIdt80->offset_high<<16|pIdt80->offset_low);
printk(KERN_ALERT"system_calladdressat0x%x ",base_system_call);
SYS_CALL_TABLE_ADDR=get_sys_call_table();
sys_call_table=(void**)SYS_CALL_TABLE_ADDR;
orig_write=sys_call_table[__NR_write];
sys_call_table[__NR_write]=hacked_write;
return0;
}
voidcleanup_mole()
{
sys_call_table[__NR_write]=orig_write;
}

Ⅳ linux內核態,在LSM框架中的文件操作hook介面中如何獲取一個正在被操作的文件的內容(linux4.4版本)

LSM是Linux Secrity Mole的簡稱,即linux安全模塊。其是一種輕量級通用訪
問控制框架,適合於多種訪問控制模型在它上面以內核可載入模塊的形實現。用
戶可以根據自己的需求選擇合適的安全模塊載入到內核上實現。

LSM設計思想:
LSM的設計思想:在最少改變內核代碼的情況下,提供一個能夠成功實現強制訪
問控制模塊需要的結構或者介面。LSM避免了利用如在systrace系統調用中的出
現過的系統調用干預,因為它不能擴展到多處理器內核,並且它受制於參數替換
攻擊。還有LSM在設計時做了兩點考慮:對不使用的人來說盡量少引入麻煩,對
使用的人來說要帶來效率。以Linus Torvalds為代表的內核開發人員對Linux安

全模塊(LSM)提出了三點要求:
1、真正的通用,當使用一個不同的安全模型的時候,只需要載入一個不同的內
核模塊。
2、概念上簡單,對Linux內核影響最小,高效,並且。
3、能夠支持現存的POSIX.1e capabilities邏輯,作為一個可選的安全模塊。
還有,針對linux上提出的各種不同的Linux安全增強系統對Linux安全模塊(LSM
)提出的要求是:能夠允許他們以可載入內核模塊的形式重新實現其安全功能,

並且不會在安全性方面帶來明顯的損失,也不會帶來額外的系統開銷。
LSM框架結構:
LSM框架主要由五部分構成:
1、在特定的內核數據結構中加入安全域。
2、在內核源代碼中不同的關鍵點插入對安全鉤子函數的調用。
3、加入一個通用的安全系統調用。
4、提供了函數允許內核模塊注冊為安全模塊或者注銷。
5、5、將capabilities邏輯的大部分移植為一個可選的安全模塊。
安全域是一個void*類型的指針,它使得安全模塊把安全信息和內核內部對象聯
系起來。下面列出被修改加入了安全域的內核數據結構,以及各自所代表的內核

內部對象:
task_struct結構:代表任務(進程)
linux_binprm結構:代表程序
super_block結構:代表文件系統
inode結構:代表管道,文件,或者Socket套接字
file結構:代表打開的文件
sk_buff結構:代表網路緩沖區(包)
net_device結構:代表網路設備
kern_ipc_perm結構:代表Semaphore信號,共享內存段,或者消息隊列
msg_msg:代表單個的消息

Linux安全模塊(LSM)提供了兩類對安全鉤子函數的調用:一類管理內核對象的
安全域,另一類仲裁對這些內核對象的訪問。對安全鉤子函數的調用通過鉤子來
實現,鉤子是全局表security_ops中的函數指針,這個全局表的類型是
security_operations結構,這個結構定義在include/linux/security.h這個頭
文件中。
LSM介面的核心是security_ops,當系統啟動時,他們被初始化為傳統的DAC策略
。傳統DAC訪問控制是指控制系統中的主體(如進程)對系統中的客體(如文件
目錄、文件)的訪問(讀、寫和執行等)。自主訪問控制DAC 是指主體(進程,
用戶)對客體(文件、目錄、特殊設備文件、IPC等)的訪問許可權是由客體的屬
主或超級用戶決定的,而且此許可權一旦確定,將作為以後判斷主體對客體是否有

訪問許可權的依據。
在載入安全模塊時,我們必需先對模塊進行注冊,我們可以使用
register_security()函數向LSM注冊一個安全模塊。在我們的模塊被載入成
功後,就可以進行訪問控制操作。如果此時還有一個安全模塊要使用
register_security()函數進行載入,則會出現錯誤,直到使用
unregister_security()函數向框架注銷後,下一個模塊才可以載入。當然LS
M還提供了mod_reg_security()函數和mod_unreg_security()函數,可以連續注
冊多個安全模塊。如果有其他後來的模塊需要載入,可以通過mod_reg_security
()向第一個模塊注冊,形成支持不同策略的模塊棧。
註:以上出現的函數均基於2.6.22以前的版本,對於後續的版本,出現了
register_security()函數未被導出或者取消掉了unregister_security()函數。
LSM執行過程:
根據下圖的執行步驟:用戶在執行系統調用時,先通過原有的內核介面依次執行
功能性的錯誤檢查,接著進行傳統的DAC檢查,並在即將訪問內核的內部對象之
前,通過LSM鉤子函數調用LSM。LSM再調用具體的訪問控制策略來決定訪問的合
法性。圖三顯示了LSM鉤子的調用:

圖三:基於LSM的內核對象訪問過程

Lilinux安全模塊(LSM)主要支持"限制型"的訪問控制決策:當Linux內核授予
文件或目錄訪問許可權時,Linux安全模塊(LSM)可能會拒絕,而當 Linux內核拒
絕訪問時,可以跳過LSM。

========

使用LSM實現自己的訪問控制

首先對LSM 進行簡單介紹。雖然linux下的各位基本都知道一些,但是還要羅嗦
一下。
LSM中文全稱是linux安全模塊。英文全稱:linux security mole.
LSM是一種輕量級、通用的訪問控制框架,適合多種訪問控制模型以內核模塊的
形式實現。其特點是通用、簡單、高效、支持POSIX。1e能力機制。
LSM的架構圖如下:

通過系統調用進入內核之後,系統首先進行傳統的許可權檢查(傳統許可權檢查主要
是基於用戶的,用戶通過驗證之後就可以訪問資源),通過之後才會進行強制訪
問控制。(強制訪問控制是不允許主體干涉的一種訪問控制,其採用安全標識、
信息分級等信息敏感性進行訪問控制。並且通過比較主體的級別和資源的敏感性
來確定是否允許訪問。比如說系統設置A用戶不允許訪問文件B,即便A是文件B的
所有者,訪問也是受限制的。)從圖上看來,LSM實現訪問控制主要通過安全模
塊的鉤子函數實現。

LSM框架主要由五部分組成:這個網上資料很多。
在關鍵的特定內核數據結構中加入了安全域;
在內核源碼中不同的關鍵點處插入對安全鉤子函數的調用;
提供了一個通用的安全系統調用;
提供了注冊和注銷函數,使得訪問控制策略可以以內核模塊方式實現;
將capabilities邏輯的大部分功能移植為一個可選的安全模塊。

我們這里重點結合源碼對LSM框架進行解釋。我使用的源碼是3.5.4
首先介紹安全域欄位,它是一個空類型的指針,在內核中的很多內核結構中都存
在,比如inode、superblock、dentry、file等等。類型欄位為void *
security;
那麼安全域怎麼和安全模塊中的信息關聯起來?
當安全模塊載入之後,安全域中的指針便指向安全模塊中的安全信息。這里以
selinux為例進行介紹。
內核裡面security/selinux/include/objsec.h中定義了不同對象的安全信息,
格式為XXX_security_strut.

上面的文件的安全信息裡麵包含打開文件描述符時的安全ID、文件所有者的安全
ID等等。
要聯系安全模塊中安全信息和安全域需要幾個控制鉤子函數。這些鉤子函數實現
了對內核關鍵信息的設置和管理。這里主要介紹alloc_security、
free_security。
selinux裡面通過實現安全信息空間分配實現關聯。比如以文件安全信息為例
這里分配空間成功之後,通過file->f_security = fsec實現了關聯。
撤銷關聯是在安全模塊卸載之後調用file_free_security.

這里具體通過設置file->f_secrity為NULL,然後釋放安全信息結構實現。
現在來看看內核如何實現selinux的訪問控制。這里主要就是實現LSM裡面的鉤子
函數了。LSM裡面給出了結構體security_operations,裡面給出了很多鉤子函數
,實現了相關鉤子函數就可以實現訪問控制了。

上面的函數就實現了file_permission鉤子函數。可以看下inode結構體的獲得,
感受內核是通過文件->目錄項->inode。該函數主要實現自己的訪問控制策略就
OK 了。
哪selinux來說,在獲得文件安全ID之後,主要對掩碼和文件打開時相關的安全
信息進行檢測,符合就通過訪問控制。
selinux基本實現了LSM裡面的所有鉤子函數,待鉤子函數實現後,對LSM裡面鉤
子域進行填充就OK了。

做完以上這些還需要注冊安全模塊到LSM,這里注冊和注銷使用了
register_security和unregister_security。
比如selinux在注冊時使用語句register_security(&selinux_ops)實現。

接下來通過上面的分析我們可以實現簡單的基於LSM的訪問控制。
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mole.h>
#include <linux/fs.h>
#include <linux/security.h>
#include <linux/types.h>
#include <asm/uaccess.h>
#include <linux/fcntl.h>
#include <linux/uaccess.h>
#include <linux/file.h>
#include <linux/namei.h>

static int lsm_test_file_permission(struct file *file,int mask)
{
int path=0;
struct file *filp;
struct nameidata nd;

path = path_lookup(FILENAME,LOOKUP_FOLLOW,&nd);

if(!mask)
return 0;

if(path)
{
printk("lookup file failed!\n");
return -1;
}

filp = filp_open("/home/yuyunchao/code/sb.c",O_RDONLY,0);
{
printk("open failed!\n");
}
return 0;
}

static struct security_operations lsm_test_security_ops = {
.file_permission = lsm_test_file_permission,
};

static int __init lsm_file_init(void)
{
if(register_security(&lsm_test_security_ops)){
printk("register error ..........\n");
return -1;
}

printk("lsm_file init..\n ");
return 0;
}

static void __exit lsm_file_exit(void)
{
if(unregister_security(&lsm_test_security_ops)){
printk("unregister error................\n");
return ;
}

printk("mole exit.......\n");
}

MODULE_LICENSE("GPL");
mole_init(lsm_file_init);
mole_exit(lsm_file_exit);
========

LSM(Linux Security Mole)應用方法(簡單例子)

LSM在內核中很多地方已經插入了hook函數,並且在security.c函數中聲明了
security_ops結構,要實現你自己的安全模塊,只需要定義你自己的struct
security_operations,並且用register_security注冊即可,下面舉個簡單例子

test.c代碼如下:
/*
* Test Linux Security Mole
*
* Author: penghuan <[email protected]>
*
* Copyright (C) 2010 UbuntuKylin, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
*/

#include <linux/security.h>
#include <linux/sysctl.h>
#include <linux/ptrace.h>
#include <linux/prctl.h>
#include <linux/ratelimit.h>
#include <linux/workqueue.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/dcache.h>
#include <linux/path.h>

int test_file_permission(struct file *file, int mask)
{
char *name = file->f_path.dentry->d_name.name;
if(!strcmp(name, "test.txt"))
{
file->f_flags |= O_RDONLY;
printk("you can have your control code here!\n");
}
return 0;
}

static struct security_operations test_security_ops = {
.name = "test",

.file_permission = test_file_permission,
};

static __init int test_init(void)
{
printk("enter test init!\n");

printk(KERN_INFO "Test: becoming......\n")

if (register_security(&test_security_ops))
panic("Test: kernel registration failed.\n");

return 0;
}

security_initcall(test_init);

將該文件以模塊的形式放到security/下編譯進內核,啟用新的內核後,當你操
作文件test.txt時,通過dmesg命令就能再終端看到」you can have your
control code here!「輸出
所以一般的做法是:定義你自己的struct security_operations,實現你自己的
hook函數,具體有哪些hook函數可以查詢include/linux/security.h文件,然後
調用register_security來用你的test_security_ops初始化全局的security_ops
指針

樓主,我剛開始研究LSM,但網上資料太少,您這個代碼,我編譯成ko文件老是
有警告,並且insmod時,說Unknown symbol register_security。我最近看了看
內核模塊變成,沒有對內核進行太深入的了解。不知能否把LSM的實驗步驟給出
的再詳細點,謝謝。

你需要把代碼編進內核

是需要把那段源碼拷到內核目錄下,然後重新編譯內核?。。沒有不編譯內核的
方法嗎?。。直接按照模塊進行編譯。另外那個test.txt放在哪個文件夾里?。

是需要把那段源碼拷到內核目錄下,然後重新編譯內核?。。沒有不編譯內核的
方法嗎?。。直接按照模塊進行 ...

是的,你去網上找下怎麼把模塊編進內核,lsm模塊不能以模塊方式載入,涉及
安全;test.txt是測試文件,當你把代碼編進內核後,用新內核啟動,然後操作
test.txt文件,就會有輸出,test.txt隨便放哪裡

樓主,您好,我剛開始學習lsm模塊,把您的模塊編譯進內核,新的內核載入後
,register_security總是失敗,請問下可能是什麼原因導致的。我的內核版本
是3.13.11。

register_security的返回值是-11

========

LSM在Linux中的實現方式
LSM(Linux Secure Model)一種輕量級訪問控制機制.
其實現方式有如在系統調用中加入一個後門....
方式如下:
static struct file *__dentry_open(struct dentry *dentry, struct

vfsmount *mnt,
struct file *f,
int (*open)(struct inode *, struct file *),
const struct cred *cred)
{
struct inode *inode;
int error;
...............................................................
error = security_dentry_open(f, cred); //LSM機制實現方式,在此加入了

一個LSM函數.

//security_dentry_open的實現如下,相當於一個介面,對一個函數指針再

//封裝一下.

//只返回是與否,這樣的控制信息.
if (error)
goto cleanup_all;
................................................................
return f;
cleanup_all:
.................................................................
return ERR_PTR(error);
}
//========簡單封裝一個指針結構體===========================
int security_dentry_open(struct file *file, const struct cred *cred)
{
int ret;
ret = security_ops->dentry_open(file, cred);
if (ret)
return ret;
return fsnotify_perm(file, MAY_OPEN);
}

========

利用LSM實現更安全的linux

LSM的全稱是Linux Security Moles,它是linux內核中用來支持更靈活的

安全策略的一個底層框架,雖然聽起來比較復雜,但是可以就把它理解成一組安

插在linux內核的鉤子函數和一些預留的被稱為安全域的數據結構,下面先說說

這個框架的由來吧。

linux本身的機制就保證了linux擁有更好的安全機制,但是在這個機制下面

,還是隱藏了許多的問題:

1、許可權粒度太大。用過linux的人應該對0644這樣的訪問許可權設置不陌生,

它對能夠操作這個文件的用戶做了限制,但是這個只是限制到了組,而沒有更進

一步的細分,當然,如果LSM只是用來限制這個的話,那麼也就太沒意思了,因

為實現文件更細的控制粒度,ACL就能夠很出色的完成,順便提一下,ACL有一個

分配的限制,如果哪位朋友需要用ACL進行粒度更細的訪問許可權控制的話,可能

需要注意一下這方面的東西。

2、root用戶的許可權太大。在linux中,root用戶就是至高無上的,他擁有對

機器的完全控制許可權,可以做他想做的一切事情。但是很多時候,我們可能並不

希望有root有這么大的許可權,比如在現在比較流行的雲存儲中,用戶肯定不希望

服務提供商能夠隨意訪問我們的文件,那麼這個時候,就需要對root用戶進行一

定的設置了。

由於這些問題的存在,所以出現了像SE Linux(Securiy Enhanced Linux )

這樣的增強補丁。但是每個系統對於具體安全細節的控制不盡相同, 所以Linus

Tovalds 提出應該要有一個 Linux 內核所能接受的安全框架來支持這些安全策

略,這個安全框架應該提供包含內核數據結構中的透明安全域以及用來控制、維

護安全域操作的安全鉤子,於是就有了LSM。

LSM在內核中的位置,可以用下圖來表示:

當用戶態程序調用某些操作系統提供的函數的時候,比如read()函數,其會

對應於內核中的一個系統調用,然後該首先會進行一些常規的錯誤檢測,接著進

行DAC(Discretionary Access Control)檢測,再接著它會進行LSM檢測。從上

圖中能夠看出來,LSM其實是一個非常底層的安全策略框架,利用LSM,可以接管

所有的系統調用,這樣,我們就能對包括root在內的所有用戶的許可權進行控制,

並且實現粒度更細的訪問許可權控制。

當系統初始化的時候,LSM就是一個空的框架,它不提供任何的檢測,其所

做的全部工作幾乎就是返回0,當然,有些不帶返回值的函數除外。而我們則可

以針對自己特定的需求來編寫LSM,然後將我們編寫的LSM鉤子函數,通過其數據

結構struct security_operations注冊到系統中去,這樣,我們的LSM檢測就開

始起作用了。
更多信息可參考《Linux就該這么學》

Ⅵ 求linux ptrace函數的詳細介紹

推薦http://blog.chinaunix.net/u2/67414/showart_1716467.html去學慣用法,有例子

在用戶模式中,雖然只有一個函數可用,即ptrace(int _request, pid_t _pid, caddr_t _addr, int _data),但是這個函數能做所有的事情!如果你願意,也可以花費幾個小時來編寫自己的小調試器,以解決特定的問題。

ptrace函數的_request參數是最重要的一個參數,因為它確定你將做什麼。BSD和Linux的頭文件使用不同的定義,這使得將ptrace應用從一個平台移植到另一個平台變得很復雜。默認地,我們使用BSD頭文件中的定義。

r PT_TRACE_ME(PTRACE_TRACEME)將當前進程切換到停止狀態。它通常總是與fork/exec一起使用,雖然也能遇到自我追蹤的應用程序。對於每一個進程,PT_TRACE_ME只能被調用一次。追蹤一個正被追蹤的進程是會失敗的(另一個較不重要的結果是進程不能追蹤它自己。如果要這樣做,應該首先從自身派生一個進程)。大量的反調試技術都是以這一事實為基礎的。為了克服這類技術,必須使用繞過ptrace的調試器。一個信號被發送到正被調試的進程,並將該進程切換到停止狀態,該進程可以使用從父進程上下文中調用的PT_CONTINUE和PT_STEP命令從停止狀態退出。wait函數會延遲父進程的執行,直到被調試的進程切換為停止狀態或者終止為止(終止時,返回值為1407)。其他的所有參數都被忽略。

r PT_ATTACH(PTRACE_ATTACH)將進程標志為pid的運行進程切換為停止狀態,在這種情形下,調試器進程成為「父進程」。其他的所有參數都被忽略。進程必須具有與調試進程相同的用戶標志(UID),並且不能是setuid/setid進程(否則就要用root來調試)。

r PT_DETACH(PTRACE_DETACH)停止進程標志為pid進程(由PT_ATTACH和PT_TRACE_ME指定)的調試,並繼續其常態運行。其他的所有參數都被忽略。

r PT_CONTINUE(PTRACE_CONT)繼續進程標志為pid的被調試進程的執行,而不中斷與調試器進程的通信。如果addr == 1(在Linux中為0),從上次停止的地址繼續執行;否則,從指定的地址繼續執行。參數_data指定發送到被調試進程的信號數量(零說明沒有信號)。

r PT_STEP(PTRACE_SINGLESTEP)進行進程標志為pid的進程的單步執行,即執行下一條機器指令並切換為停止狀態(在i386中,這是根據設置追蹤標志來實現的,雖然有些「黑客」函數庫使用硬體斷點)。BSD要求將參數addr置為1,而Linux要求將該參數置為0。其他的所有參數都被忽略。

r PT_READ_I和PT_READ_D(PTRACE_PEEKTEXT和PTRACE_PEEKDATA)分別從代碼區和正被調試進程的地址空間區讀取機器字。在許多當代的平台中,這兩個指令是等價的。ptrace函數接嫌鍵收目標地址addr,並芹橋巧返回讀到的結果。

r PT_WRITE_I和PR_READ_D(PTRACE_POKETEXT和PTRACE_POKEDATA)將由_data傳入的機器字寫入addr所指定的地址。

r PT_GETREGS,PT_GETFPREGS和PT_GETDBREGS(PTRACE_GETREGS,PTRACE_ FPREGS和PT_GETFPXREGS)將一般用途寄存器、段寄存器和調試寄存器的值讀入到地址由_addr指針所指定的調試器進程的內存區中。只有i386平台接收這些與系統相關的命令。寄存器結構的描述放在頭文件machine/reg.h文件中。

r PT_SETREGS,PT_SETFPREGS和PT_SETDBREGS(PTRACE_SETREGS,PTRACE_ SETFPREGS和PT_SETFPXREGS)通過拷貝由_addr指針所指定的內存區域的內容來設置被調消冊試進程的寄存器的值。

r PT_KILL(PTRACE_KILL)將sigkill發送到被調試進程,以終止其執行。

Ⅶ linux禁止gdb調試

禁止在 Linux 中 gdb 調試的方法有許多,以下是其中的一種方法:

1. 禁用 core mp:可以通過以下命令將 core mp 禁用:

```
ulimit -c 0
```

這將確保應用程序在蘆碧舉崩潰時不會生成任何 core mp 文件。gdb 通常需要訪問 core mp 文件來執行調試操作,因此禁用它們可以幫助防止調試。

2. 使用 ptrace:慧察ptrace 系統調用可以被用來執行程序間的跟蹤和調試,因此禁用它可以防止 gdb 調試。為了禁用 ptrace,可以在 /etc/sysctl.conf 文件中添加以下內容:

```
kernel.yama.ptrace_scope = 1
```

然後更新 sysctl.conf 文件,使設置生效:

```
sudo sysctl -p
```

這將限制 ptrace 僅在其父進程和子進程之間(或在具有適當許可權的特權用戶之間)進行。這樣可以防止普通用戶使用 gdb 調試其他用戶、系統進程或其他特權進程。

請注意,以上方法僅僅是防止 gdb 調試的其中一種方法,還有其陪碧他方法可以繞過這些限制。因此,禁止 gdb 調試並不能完全保證系統的安全性和機密性。如果您對系統安全性有更高的要求,建議請咨詢專業安全人員提供更加嚴格的安全策略。

閱讀全文

與linuxptrace相關的資料

熱點內容
伺服器燈閃什麼意思 瀏覽:279
孟子譯注pdf 瀏覽:627
推薦的對稱加密演算法 瀏覽:186
idr單片機 瀏覽:519
機器學習貝葉斯演算法 瀏覽:254
驗鞋的app有哪個 瀏覽:395
php資料庫文件在哪裡 瀏覽:629
pythonrun模塊 瀏覽:716
高並發處理方案php 瀏覽:147
梯形迭代式演算法 瀏覽:437
ppt轉pdf破解 瀏覽:1002
如何給股票賬號加密碼 瀏覽:105
新鄭java程序員 瀏覽:912
為什麼王者榮耀安卓和蘋果玩不了 瀏覽:774
山西百信恆山伺服器雲主機 瀏覽:843
ssh連接linux伺服器 瀏覽:384
怎麼架設mu伺服器 瀏覽:700
pythonorgdownload 瀏覽:918
選股入門公式源碼小寫怎麼編寫 瀏覽:291
解壓瀏覽器哪個好 瀏覽:449