#include<sys/resource.h>
int getrusage(int who, struct rusage *res_usage);
複製代碼
who的值linux
- RUSAGE_SELF 調用進程
- RUSAGE_CHILDREN返回調用進程的全部被終止和處於等待狀態的子進程
- RUSAGE_THREAD返回調用線程的相關信息(linux特有)
真實用戶或特權用戶能夠在/proc/PID/limits文件查看響應進程的資源限制shell
# include<sys/resource.h>
int getrlimit(int resource, struct rlimit *rlim);
int setrlimit(int resource, const struct rlimit *rlim);
struct rlimit{
rlim_t rlim_cur; //軟限制
rlim_t rlim_max; //硬限制
}
複製代碼
- 軟限制規定進程可以消耗資源數量
- 軟限制能夠調整從0到硬限制之間的任何值
- 特權能夠增大和減少硬限制,非特權進程只能縮小
![]()
daemon的特徵編程
- 它的生命週期很長,通常直到系統關閉
- 它在後臺並不擁有控制終端。控制終端的缺失確保內核永遠不會爲daemon自動生成任何任務控制信號和終端相關信號。
- 不少標準的daemon進程會做爲特權進程運行(有效用戶ID爲0)
- linux上特定的daemon會做爲內核線程運行,其實現是內核的一部分,ps查看時,daemon進程的名稱會用[]包起來,例如[kthreadd]
- 執行一個fork(),以後父進程退出,子進程繼續執行(成爲了init的子進程)第一點的第一個解釋有問題?
- 子進程調用
setsid()
(由於子進程不會是進程組首進程不會失敗)- 若是保證daemon不會請求一個控制終端(若是打開過設備終端須要如下確保):
- 將全部可能應用到的終端設備上的
open
調用指定O_NOTIFY標記setsid()
以後再調用fork()
,讓父進程退出,讓孫進程成爲daemon,(BSD規定一個進程只能一個顯式的ioctl()
TIOCSCTTY獲取一個控制終端???)- 清楚進程的
umask
- 修改進程的當前目錄,通常爲
/
,其餘的話會致使沒法卸載- 關閉daemon從父進程繼承來的全部打開的文件描述符
- 關閉了文件描述符0,1,2後,daemon 一般會打開/dev/null,並使用dup2()
- 修改daemon啓動參數
- 修改日誌文件
- 由於daemon沒有終端,內核永遠不會發送SIGHUP,能夠經過SIGHUP解決以上問題
tip:syslogd會根據syslogd.conf會將消息從新分配到幾個目標上(ex:/var/log/messages)安全
一個程序可經過如下兩種方式以特權進行函數
- 程序設置了set-user-ID和set-group-Id
最小操做權限
- 在特權程序設置以下
uid_t orig_euid;
orig_euid = geteuid();
if (seteuid(getuid()==-1)
errExit("seteuid")
/* Do unprivileged work */
if (seteuid(orig_euid)==-1)
errExit("seteuid")
/* DO privileged work */
複製代碼
- 注意的是隻有特權進程
setuid(_id)
才能將uid,euid,suid同時設置成_id。- 當euid不爲0時,是沒法修改suid,致使suid不會被重置,進程沒法真正的放棄特權。
- CAP_SETUID可能致使修改用戶異常
- 在執行另外一個程序以前永久的刪除權限(
exec()
,system()
,popen()
)- 避免執行擁有權限的shell
- exec()以前關閉全部用不到的文件描述符(close-on-exec)
- 虛擬內存葉換出
- 核心轉儲文件的生成
- securebits
- chroot(限制不了set-user-id-root程序)
進程分兩類ui
- 有效用戶爲0超級金城
- 其餘須要根據用戶和組肯定權限的進程
進程能力集spa
- 許可的:許可的集合是可以被添加到有效的和可繼承的集合中的能力的受限超集;若是進程從許可集中刪除了一個能力,將本身沒法從新得到
- 有效的:只有許可集中有這個能力,進程才能從有效集中刪除這個能力臨時禁用,以後可再還原
- 當這個進程執行一個程序時可將這些權限帶入許可集
能夠在
/proc/PID/status
文件中的CapInh, CapPrm, CapEff中查看能力集的16進製表示(64位)線程
能力集能夠具體到線程
/proc/PID/task/TID/status
unix
fork()
出的子進程會繼承父進程的能力集日誌
會相似於uid, euid, suid
文件能力集
- 許可的:在
exec()
中可將這組能力添加到進程的許可集中- 有效的:只有一位,若是啓用了,在調用
exec()
以後進程的新許可集中啓用的能力在進程的新有效集合中也會被啓用。若是被禁用了exec()
以後,進程的新有效集一開始是空的- 可繼承的:這個集合講和進程的可繼承集取掩碼來肯定執行
exec()
以後進程的許可集啓用的能力集
exec()
中轉變進程內核會根據如下規則計算進程的新能力
PN(permitted)=(P(inheritable) & F(inheritable)) | (F(permitted) & cap_bset)
PN(effective)=F(effective)?PN(permitted):0
PN(inheritable)=P(inheritable)
若是執行一個set-user-ID-root的程序,計算簡化爲
PN(permitted)=P(inheritable) | cap_bset
PN(effective)=PN(permitted)
cap_bset爲進程級別的能力邊界值,通常是全爲1(init進程是全1),一個進程具有了CAP_SETPCAP能力後能夠不可逆的修改cap_bset, 在
status
裏面是CapBnd
- utmp維護這當前登陸進系統的用戶記錄。登陸時寫入(會包含一個ut_user),登出時刪除(
/var/run/utmp
; _PATH_UTMP)- wtmp包含全部用戶登陸和登出行爲的留痕信息,登陸時記錄和utmp記錄一致,登出時記錄和登入時記錄相同除了ut_user字段置位0(
/var/log/wtmp
; _PATH_WTMP)
- lastlog 最後一次登陸的時間(
/var/log/lastlog
;_PATH_LASTLOG) 略略了
#include<unistd.h>
char *getlogin(void);
複製代碼