linux进程号为一,一步步探究linux进程中的用户ID
轉(zhuǎn)載請注明來源chengyaogen.blog.chinaunix.net
一、進(jìn)程與權(quán)限
A.進(jìn)程時Linux/Unix操作系統(tǒng)中最重要的抽象之一
B.進(jìn)程是一個處于執(zhí)行期的程序(目標(biāo)代碼存儲在某種介質(zhì)上)
A ? ?process ? is ? a ?program(object ?code ?stored ?on some ?media) ?in the ?midst ?of
execution.
而進(jìn)程在執(zhí)行過程中經(jīng)常涉及到文件訪問操作等
1.一個運行中的進(jìn)程究竟可以訪問哪些資源,而不能訪問哪些資源?
2.一個進(jìn)程運行過程中如何實現(xiàn)在某個執(zhí)行階段擁有一些權(quán)限而在另一個階段又具備另外一種權(quán)限呢?
上述狀況對應(yīng)于進(jìn)程的訪問權(quán)限以及進(jìn)程執(zhí)行中不同權(quán)限的切換。這一切都和進(jìn)程實際用戶ID,進(jìn)程有效用戶ID,進(jìn)程保存設(shè)置用戶ID有關(guān)聯(lián)。
二、進(jìn)程的用戶ID
1.實際用戶ID(real user id,RUID)
為該進(jìn)程的創(chuàng)建者的用戶ID,也可以說是進(jìn)程的執(zhí)行者。該ID僅root用戶可以修改
2.有效用戶ID(effective ?user ?id,EUID)
該ID用戶標(biāo)識用戶進(jìn)程執(zhí)行操作的權(quán)限。例如:如果EUID是0即(root),此時進(jìn)程擁有root用戶權(quán)限。普通用戶可以將EUID設(shè)置為RUID或者SUID,而超級用戶可以將EUID設(shè)置為任意的合法UID。
注意:對于一個可執(zhí)行的二進(jìn)制文件,如果其set-user-id bit被設(shè)置,則運行改程序時,對應(yīng)進(jìn)程的有效用戶ID(EUID)為該文件的文件所有者用戶ID。
3.保存設(shè)置用戶ID(saved set-user-id,SUID)
對于沒有設(shè)置set-uid-bit的可執(zhí)行程序而言,其對應(yīng)進(jìn)程的保存設(shè)置用戶ID(SUID)為其實際用戶ID;而對于設(shè)置了set-uid-bit的程序而言,其對應(yīng)的保存設(shè)置用戶ID(SUID)為該可執(zhí)行文件的文件擁有者用戶ID。只能root用戶權(quán)限,才能更改(當(dāng)一個程序文件運行的時候,其值已經(jīng)確定)。
注意:linux不提供返回保存的設(shè)置-用戶-ID的函數(shù)
總結(jié):
RUID代表此進(jìn)程是哪個用戶創(chuàng)建的, EUID代表此進(jìn)程所擁有的權(quán)限,SUID保存了EUID,當(dāng)EUID改變后,如果想回到以前的EUID,此時SUID將發(fā)揮作用。
三、相關(guān)API
#include
#include
int ? setuid(uid);
可以用setuid函數(shù)設(shè)置實際用戶ID和有效用戶ID。注意,我們并不能想怎么設(shè)就怎么設(shè)。有若干規(guī)則需要我們遵守:
(1)若進(jìn)程具有超級用戶特權(quán),則setuid函數(shù)將實際用戶ID、有效用戶ID,以及保存的設(shè)置-用戶-D設(shè)置為uid。
(2)若進(jìn)程沒有超級用戶特權(quán),但是uid等于實際用戶ID或保存的設(shè)置-用戶-ID,則setuid只將有效用戶ID設(shè)置為。不改變實際用戶ID和保存的設(shè)置-用戶-ID。
(3)如果上面兩個條件都不滿足,則errno設(shè)置為EPERM,并返回出錯.。
關(guān)于內(nèi)核所維護(hù)的三個用戶ID,還要注意下列幾點
(1)只有超級用戶進(jìn)程可以更改實際用戶ID。通常,實際用戶ID是在用戶登錄時,由login(1)程序設(shè)置的,而且決不會改變它。因為login是一個超級用戶進(jìn)程,當(dāng)它調(diào)用setuid時,設(shè)置所有三個用戶ID。
(2)僅當(dāng)對程序文件設(shè)置了 set-user-id bit時,exec函數(shù)設(shè)置有效用戶ID為文件所有者。如果set-user-id bit沒有設(shè)置,則exec函數(shù)不會改變有效用戶ID,而將其位置原先值。任何時候都可以調(diào)用setuid,將有效用戶ID設(shè)置為實際用戶ID或保存的設(shè)置-用戶-ID。自然,不能講有效用戶ID設(shè)置為任意隨機值。
四、探究
案例一:
有個要在MacOS上實現(xiàn)一個關(guān)機程序,它熟悉linux,其實老祖宗都是unix,所以MacOS對他并不陌生。如下他寫了如下程序?qū)崿F(xiàn)關(guān)機
編譯運行:
從上面看,這段代碼可以實現(xiàn)關(guān)機,但是有個不符合要求的地方,運行程序不能是超級用戶,只能是普通用戶。
他很苦惱,后來找到了我,我做了如下事情
呵呵,可以了。我將這個可執(zhí)行文件的owner和group都改為了root,然后有講其set-user-id bit位加以了設(shè)置。這樣以普通用戶運行這個程序時,此進(jìn)程的EUID就是root了,這樣滿足了shutdown命令執(zhí)行的權(quán)限。案例二:
#include
#include
#include
#include
#include
#include
void test_read_file(const char *name)
{
int fd = -1;
fd = open(name ,O_RDWR);
if(fd < 0){
printf("=[ERROR]:read failed.\n");
}else{
printf("=[OK]:read successful\n");
close(fd);
}
}
//打印uid和euid
void p_states()
{
int uid = 0;
int euid = 0;
printf("------Current states--------\n");
printf("real uid\t %d\n",getuid());
printf("effective uid\t %d\n",geteuid());
printf("----------------------------\n");
}
//調(diào)用setuid
void run_setuid_fun(int uid)
{
if(setuid(uid) == -1)
{
printf("=[ERROR]:setuid(%d) error\n",uid);
}
p_states();
}
//調(diào)用setuid
void run_seteuid_fun(int uid)
{
if(setuid(uid) == -1)
{
printf("=[ERROR]:seteuid(%d) error\n",uid);
}
p_states();
}
int main()
{
int t_re = 0;
const char *file = "root_only.txt";
printf("\nTEST 1:\n");
p_states();
//此時real uid = login user id
//effective uid = root
//saved uid = root
test_read_file(file);
getchar();
printf("\nTEST 2:setuid(getuid())\n");
run_seteuid_fun(getuid());
//此時real uid = login user id
//effective uid = login user id
//saved uid = root
test_read_file(file);
getchar();
printf("\nTEST 3:setuid(0)\n");
run_setuid_fun(0);
//此時real uid = login user id
//effective uid = root
//saved uid = root
test_read_file(file);
getchar();
printf("\nTEST 4:setuid(0)\n");
run_setuid_fun(0);
//此時real uid = root
//effective uid = root
//saved uid = root
test_read_file(file);
getchar();
printf("\nTEST 5:setuid(503)\n");
run_setuid_fun(503);
//此時real uid = login user id
//effective id = login user id
//saved uid = login user id
test_read_file(file);
getchar();
printf("\nTEST 6:setuid(0)\n");
//read uid = login user id
//effective uid = login user id
//saved uid = login user id
run_setuid_fun(0);
test_read_file(file);
return 0;
}編譯運行:
root_only.txt文件建立:
第一次:
RUID:實際用戶
EUID:文件所有者(root)
SUID:文件所有者(root)此時進(jìn)程擁有root用戶權(quán)限,能對root_only.txt進(jìn)行讀寫操作
第二次:
此時普通用戶調(diào)用setuid(getuid()),只會將EUID改為getuid(),其他都不變
RUID:實際用戶
EUID:實際用戶
SUID:root
此時進(jìn)程沒有有root用戶權(quán)限,不能能對root_only.txt進(jìn)行讀寫操作
第三次:
此時普通用戶調(diào)用seteuid(0),只會將EUID改為0,其他都不變
RUID:實際用戶
EUID:root
SUID:root此時進(jìn)程擁有root用戶權(quán)限,能對root_only.txt進(jìn)行讀寫操作
第四次:
此時進(jìn)程擁有root用戶權(quán)限,調(diào)用setuid(0),會將三個ID都設(shè)置為0
RUID:root
EUID:root
SUID:root
此時進(jìn)程擁有root用戶權(quán)限,能對root_only.txt進(jìn)行讀寫操作
第五次:
此時進(jìn)程擁有root用戶權(quán)限,調(diào)用setuid(503),會將三個ID都設(shè)置為503
RUID:503
EUID:503
SUID:503
此時進(jìn)程擁有普通用戶權(quán)限,不能對root_only.txt進(jìn)行讀寫操作
第六次:
此時進(jìn)程擁有普通用戶權(quán)限,調(diào)用setuid(0),此時RUID,SUID都不為0,這一次操作將失敗
RUID:503
EUID:503
SUID:503
此時進(jìn)程擁有普通用戶權(quán)限,不能能對root_only.txt進(jìn)行讀寫操作
總結(jié)
以上是生活随笔為你收集整理的linux进程号为一,一步步探究linux进程中的用户ID的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机考研初试复试比例,考研初试400多
- 下一篇: linux 其他常用命令