#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);
复制代码