我正在使用OpenBSD内核代码,尤其是这个文件sys/kern/sched_bsd.c
。
void
schedcpu(void *arg)
{
......
......
LIST_FOREACH(p, &allproc, p_list) {
/*
* Increment sleep time (if sleeping). We ignore overflow.
*/
if (p->p_stat == SSLEEP || p->p_stat == SSTOP)
p->p_slptime++;
p->p_pctcpu = (p->p_pctcpu * ccpu) >> FSHIFT;
/*
* If the process has slept the entire second,
* stop recalculating its priority until it wakes up.
*/
if (p->p_slptime > 1)
continue;
SCHED_LOCK(s);
/*
* p_pctcpu is only for diagnostic tools such as ps.
*/
....
....
LIST_FOREACH(TYPE *var, LIST_HEAD *head, LIST_ENTRY NAME); The macro LIST_FOREACH traverses the list referenced by head in the forward direction, assigning each element in turn to var.
现在,p
将包含文件中的struct proc
eery进程结构的地址
SYS / SYS / proc.h
现在,这个结构再次包含另一个struct process *p_p
结构,它表示每个进程的属性,如pid
,flags
,threads
等。
struct proc {
TAILQ_ENTRY(proc) p_runq;
LIST_ENTRY(proc) p_list; /* List of all threads. */
struct process *p_p; /* The process of this thread. */
TAILQ_ENTRY(proc) p_thr_link; /* Threads in a process linkage. */
TAILQ_ENTRY(proc) p_fut_link; /* Threads in a futex linkage. */
struct futex *p_futex; /* Current sleeping futex. */
/* substructures: */
struct filedesc *p_fd; /* copy of p_p->ps_fd */
struct vmspace *p_vmspace; /* copy of p_p->ps_vmspace */
#define p_rlimit p_p->ps_limit->pl_rlimit
....
....
现在,结果struct process
包含uint64_t ps_plegde
。
struct process {
/*
* ps_mainproc is the original thread in the process.
* It's only still special for the handling of p_xstat and
* some signal and ptrace behaviors that need to be fixed.
*/
struct proc *ps_mainproc;
struct ucred *ps_ucred; /* Process owner's identity. */
....
....
u_short ps_acflag; /* Accounting flags. */
uint64_t ps_pledge;
uint64_t ps_execpledge;
....
....
现在,我在void schedcpu()
功能代码中写了一些修改。
void
schedcpu(void *arg)
{
pid_t pid;
uint64_t pledge_bit;
....
....
LIST_FOREACH(p, &allproc, p_list) {
pid=p->p_p->pid;
pledge_bit=p->p_p->ps_pledge;
if (pledge_bit) {
printf("pid: %10d pledge_bit: %10llu pledge_xbit:%10llx\n",pid,pledge_bit,pledge_bit);
}
/*
* Increment sleep time (if sleeping). We ignore overflow.
*/
if (p->p_stat == SSLEEP || p->p_stat == SSTOP)
p->p_slptime++;
p->p_pctcpu = (p->p_pctcpu * ccpu) >> FS
....
....
此处,内核日志
pid: 37846 pledge_bit: 393359 pledge_xbit: 6008f
pid: 96037 pledge_bit: 393544 pledge_xbit: 60148
pid: 86032 pledge_bit: 264297 pledge_xbit: 40869
pid: 72264 pledge_bit: 393480 pledge_xbit: 60108
pid: 40102 pledge_bit: 8 pledge_xbit: 8
pid: 841 pledge_bit: 2148162527 pledge_xbit: 800a5bdf
pid: 49970 pledge_bit: 2148096143 pledge_xbit: 8009588f
pid: 68505 pledge_bit: 40 pledge_xbit: 28
pid: 46106 pledge_bit: 72 pledge_xbit: 48
pid: 77690 pledge_bit: 537161 pledge_xbit: 83249
pid: 44005 pledge_bit: 262152 pledge_xbit: 40008
pid: 82731 pledge_bit: 2148096143 pledge_xbit: 8009588f
pid: 71609 pledge_bit: 262472 pledge_xbit: 40148
pid: 54330 pledge_bit: 662063 pledge_xbit: a1a2f
pid: 77764 pledge_bit: 1052776 pledge_xbit: 101068
pid: 699 pledge_bit: 2148096143 pledge_xbit: 8009588f
pid: 84265 pledge_bit: 1052776 pledge_xbit: 101068
....
....
现在,通过查看从上面输出得到的pledge_bit(十进制或十六进制值),可以知道哪个进程保证了哪些权限?
我接受了dhclient进程的承诺十六进制值,即0x8009588f
,然后,我用pledge("STDIO",NULL);
编写了一个示例hello world程序,然后我再次查看dmesg并获得了与hello world相同的pledge_bit,即{{1 }}。
然后,这次我查看了dhclient源代码并发现,dhclient代码承诺0x8009588f
。
但是,那么,如何为不同的承诺参数获得相同的质量十六进制位呢?
答案 0 :(得分:0)
我一遍又一遍地阅读源代码后得到了答案。
所以,我只想贡献我的知识,以便未来的开发人员不会在这个问题或混乱中遇到任何问题。
第一个理解:
我写了这样的问候世界,
void
main() {
pledge("STDIO", NULL); /* wrong use of pledge call */
printf("Hello world\n");
}
以上代码的更正:
void
main() {
if (pledge("stdio", NULL) == -1) {
printf("Error\n");
}
printf("Hello world\n");
}
我忘了检查承诺()的返回值。
第二个理解:
dhclient.c
代码包含pledge()调用:
int
main(int argc, char *argv[])
{
struct ieee80211_nwid nwid;
struct ifreq ifr;
struct stat sb;
const char *tail_path = "/etc/resolv.conf.tail";
....
....
fork_privchld(ifi, socket_fd[0], socket_fd[1]);
....
....
if ((cmd_opts & OPT_FOREGROUND) == 0) {
if (pledge("stdio inet dns route proc", NULL) == -1)
fatal("pledge");
} else {
if (pledge("stdio inet dns route", NULL) == -1)
fatal("pledge");
}
....
....
void
fork_privchld(struct interface_info *ifi, int fd, int fd2)
{
struct pollfd pfd[1];
struct imsgbuf *priv_ibuf;
ssize_t n;
int ioctlfd, routefd, nfds, rslt;
switch (fork()) {
case -1:
fatal("fork");
break;
case 0:
break;
default:
return;
}
....
....
}
现在,我编写了示例hello world代码,其中包含与dhclient相同的参数:
void
main() {
if(pledge("stdio inet proc route dns", NULL) == -1) {
printf("Error\n");
}
while(1) {}
}
现在,我测试了上面的示例hello world代码,并将pledge_bit作为0x101068
以十六进制表示,这是正确的。
但是,正如我之前在问题中告诉你的那样,当我看到dhclient
的不同pledge_bit时,我感到很困惑。因为,你们知道他们的承诺()中都有相同的参数。
然后,怎么可能?
现在,这是捕获,
在不断查看dhclient源代码之后,我发现了一个名为fork_privchld()
的函数。
在dhclient中承诺之前调用了这个函数,因此,就像没有承诺这个函数一样,因为它在认捐之前被调用了。
所以,只是为了再次验证我写了样本问候世界代码,但这次没有任何承诺()系统调用。
void
main() {
printf("hello\n");
}
而且,猜猜看,我得到了与0x8009588f
相同的pledge_bit。
因此,在验证之后,验证fork_privchld()
函数没有设置任何保证位,因为它在dhclient
中认捐之前被调用。
此函数为dhclient创建[priv]子进程。
# ps aux|grep dhclient
root 26416 0.0 0.1 608 544 ?? Is 8:36AM 0:00.00 dhclient: em0 [priv] (dhclient)
_dhcp 33480 0.0 0.1 744 716 ?? Isp 8:36AM 0:00.00 dhclient: em0 (dhclient)
而且,我不知道为什么我只关注第一个过程,即[priv] (dhclient)
。此过程是由fork_privchld()
函数创建的过程。
这就是为什么这个过程有0x8009588f
保证位(由于在认捐之前被召集,因此,此时没有认捐)。
而且,当我检查第二个过程,即_dhcp
时,我得到了我预期的pledge_bit,即0x101068
(由于认捐)。
所以,我希望看完之后事情会清楚。
注意:如果我忘记或错过任何内容,请随时更新我。