Freebsd 進程號隨機化解讀

作者:wzt
原文鏈接:https://mp.weixin.qq.com/s/2qX9PKKZ5KA10WFPuMFUbA

Freebsd提供了一個有意思的安全功能,fork的進程號可以隨機化。這個小功能很有用,可以防止惡意軟件猜測父子進程號,內核提供了一個random_pid變量,可以通過sysctl設置。

static int randompid = 0;

static int
sysctl_kern_randompid(SYSCTL_HANDLER_ARGS)
{
        int error, pid;

        error = sysctl_wire_old_buffer(req, sizeof(int));
        if (error != 0)
                return(error);

        sx_xlock(&allproc_lock);
        pid = randompid;
        error = sysctl_handle_int(oidp, &pid, 0, req);

        if (error == 0 && req->newptr != NULL) {
                if (pid == 0)
                        randompid = 0;

                else if (pid == 1)
                        /* generate a random PID modulus between 100 and 1123 */
                        randompid = 100 + arc4random() % 1024;
                else if (pid < 0 || pid > pid_max - 100)
                        /* out of range */
                        randompid = pid_max - 100;
                else if (pid < 100)
                        /* Make it reasonable */
                        randompid = 100;
                else
                        randompid = pid;
        }

        sx_xunlock(&allproc_lock);
        return (error);
}

Sysctl首先獲取sysctl設置的pid值,然後根據pid值計算randompid的範圍。pid爲0表示關閉randompid功能,爲1是randompid的範圍限制在100-1023,小於0或者大於最大進程號減100,則設置爲最大進程號減去100,這樣會使randompid的範圍變得很大,如果想採取更高的安全性,可以這樣設置。pid小於100,randompid設置爲固定的100。

static int

fork_findpid(int flags)
{
        pid_t result;
        int trypid;

        trypid = lastpid + 1;
        if (flags & RFHIGHPID) {
                if (trypid < 10)
                        trypid = 10;
        } else {
                if (randompid)
                        trypid += arc4random() % randompid;
        }

        mtx_lock(&procid_lock);
}

在fork時調用fork_findpid,如果沒有RFHIGHPID標誌,再次調用arc4random(),生成一個0-randompid的值,這個值用作要搜取的bit數組索引。

實際測試下,首先關閉進程號隨機功能:

root@kexp:~/code # sysctl kern.randompid=0
kern.randompid: 231 -> 0
root@kexp:~/code # ./test
father: 93528
child: 93529

父子進程號可以預測。

開啓進程號隨機功能:

root@kexp:~/code # sysctl kern.randompid=1
kern.randompid: 0 -> 256
root@kexp:~/code # ./test
father: 93989
child: 94050

可以看到子進程號變得不可預測了。


Paper 本文由 Seebug Paper 發佈,如需轉載請註明來源。本文地址:https://paper.seebug.org/1450/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章