程式控制--程式的其他操作
一、獲得程式ID
系統呼叫getpid用來獲取當前程式的ID。輸入命令man 2 getpid可獲得該函式的宣告:
#include
#include
pid_t getpid(void);
程式7-9是一個使用getpid簡單的例子
#include
#include
#include
int main(void)
{
pid_t pid;
if ((pid = fork()) == -1){
printf("fork error!n");
exit(1);
}
if (pid == 0)
printf("getpid return %dn",getpid());
exit(0);
}
執行程式結果如下:
$ ./7-9
getpid return 5590
getpid返回了子程式的ID號5590。
二、setuid和setgid
可以用setuid設定實際使用者ID和有效使用者ID。與些類似,setgid用來設定實際組ID和有效組ID。函式的宣告在unistd.h標頭檔案,宣告如下:
#include
#include
int setuid(uid_t uid);
int setgid(gid_t gid);
設定使用者ID的setuid函式遵守以下規則(設定組ID的setgid函式與此類似)。
若程式具有root許可權,則函式將實際使用者ID、有效使用者ID設定為引數uid。
若程式不具有root許可權,但uid等於實際使用者ID,則setuid只將有效使用者ID設定為uid,不改變實際使用者ID。
若以上兩個條件都不能滿足,則函式呼叫失敗,返回-1,並設定errno為EPERM。
從以上規則可以看出,只有超級使用者程式才能更改實際使用者ID。所以一個非特權使用者程式是不能透過setuid或setuid得到特權使用者許可權的。但是su命令卻能使一個普通使用者變成特權使用者。這並不矛盾,因為su是一個“set_uid”程式。執行一個設定了set_uid位的程式時,核心將程式的有效使用者ID設定為檔案屬主的ID。而核心檢查一個程式是否具有訪問某檔案的許可權時,是使用程式的有效使用者ID來程式檢查。su程式的檔案屬主是root,普通使用者執行su命令時,su程式的許可權是root許可權。
下面透過程式7-10來解釋核心是如何檢查程式是否有權訪問某檔案的。可以看到核心是透過檢查程式的有效使用者ID來檢查的,而不是實際使用者ID。
#include
#include
#include
#include
extern int errno;
int main()
{
int fd;
printf("uid study:n");
printf("Process's uid = %d,euid = %dn",getuid(),geteuid);
//strerror函式獲取指定錯誤碼的提示資訊
if ((fd = open("Test.c",O_RDWR)) == -1){
printf("Open failure,errno is %d:%s n",errno,strerror(errno));
exit(1);
}
else{
printf("Open successfully!n");
}
close(fd);
exit(0);
}
以root使用者(提示符為#)使用命令在當前目錄下建立一個名為Test.c檔案:touch Test.c。在root使用者下執行該程式,此時檔案test.c的許可權為-rw-r--r--,即root使用者有讀寫許可權,其他使用者可讀。執行結果為:
# ./7-10
uid study:
Process's uid = 0,euid = 0
Open successfully!
轉到另外一個普通使用者下,執行結果為:
$ ./7-10
uid study:
Process's uid = 519,euid = 519
Open failure,errno is 13:Permission denied
在root使用者下,使用命令chmod對studyuid程式檔案設定set_uid位:
# chmod 4755 7-10
然後再換回一個普通使用者下,執行結果如下:
$ ./7-10
uid study:
Process's uid = 519,euid = 0
Open successfully!
執行結果說明:核心對程式存取檔案的許可權的檢查,是透過考查程式的有效使用者ID來實現的。
注意:對於呼叫了setuid函式的程式要格外小心,當程式的有效使用者ID即euid是root使用者時,如果呼叫setuid函式使euid為其他非root使用者,則該程式從此就不具有超級使用者許可權了。
可以這樣使用setuid函式:開始時某個程式需要root許可權完成一些工作,但後續的工作不需要root許可權。可以將該可執行程式檔案設定set_uid位,並使得該檔案的屬主是root。這樣普通使用者執行這個程式時,程式就具有了root許可權,當不再需要root許可權時,呼叫setuid(getuid())恢復程式的實際使用者ID和有效使用者ID為執行該程式的普通使用者的ID。對於一些提供網路服務的程式,這樣做是非常有必要的,否則就可能被攻擊者利用,使攻擊控制整個系統。
對於設定了set_uid位的可執行程式也要注意,尤其是對那些屬主是root的更要注意。因為Linux系統中root使用者擁有最高權力。駭客們往往喜歡尋找設定了set_uid位的可執行程式的漏洞,這樣的程式如果存在緩衝區溢位漏洞,並且該程式是一個網路程式,那麼駭客可以從遠端的地方輕鬆地利用該漏洞獲得執行該漏洞程式的主機的root許可權。即使這樣的程式不是網路程式,那麼也可以使本機上的惡意普通使用者提升為root使用者。
三、改變程式的優先順序
可以透過設定程式的優先順序來保證程式優先執行。在Linux下,透過系統呼叫nice可以改變程式的優先順序。nice系統呼叫用來改變呼叫程式的優先順序。命令列下輸入命令man 2 nice可以獲得該函式的宣告:
#include
int nice(int increment);
在介紹nice系統呼叫的用法前,需要先了解兩個重要的函式:getpriority和setpriority,它們宣告如下:
#include
#include
int getpriority(int which,int who);
int setpriority(int which,int who,int prio);
getpriority函式:該函式返回一組程式的優先順序。引數which和who組合確定返回哪一組程式的優先順序。which的可能取值以及who的意義如下:
PRIO_PROCESS:一個特定的程式,此時who的取值為程式ID。
PRIO_PGRP:一個程式組的所有程式,此時who的取值為程式組ID。
PRIO_USER:一個使用者擁有的所有程式,此時引數who取值為實際使用者ID。
getpriority函式如果呼叫成功返回指定程式的優先順序,如果出錯將返回-1,並設定errno的值。errno可能的取值如下:
ESRCH:which和who的組合與現在的所有程式均不匹配。
EINVAL:which是個無效的值。
注意:當指定的一組程式的優先順序不同時,getpriority將返回其中優先順序最低的一個。此外,當getpriority返回-1時,可能是發生錯誤,也有可能是返回的是指定程式的優先順序。區分它們的惟一方法是在呼叫getpriority前將errno清零。如果函式返回-1且errno不為零,說明有錯誤產生。
setpriority函式:該函式用來設定指定程式的優先順序。程式指定的方法與getpriority函式相同。如果呼叫成功,函式返回指定程式的優先順序,出錯則返回-1,並設定相應額errno。除了產生與getpriority相同的兩個錯誤外,還有可能產生以下錯誤。
EPERM:要設定優先順序的程式與當前程式不屬於同一個使用者,並且當前程式沒有CAP_SYS_NICE特許。
EACCES:該呼叫可能降低程式的優先順序並且程式沒有CAP_SYS_NICE特許。
透過以上兩函式,完全可以改變程式的優先順序。nice系統呼叫是它們的一種組合形式,nice系統呼叫等價於:
int nice(int increment)
{
int oldpro = getpriority(PRIO_PROCESS,getpid());
return setpriority(PRIO_PROCESS,getpid(),oldpro + increment);
}
例7-11演示了nice的使用方法。
#include
#include
#include
#include
#include
int main(void)
{
pid_t pid;
int stat_val = 0;
int oldpri,newpri;
printf("nice studyn");
pid = fork();
switch(pid){
case 0:
printf("Child is running,Curpid is %d,ParentPid is %dn",pid,getpid());
oldpri = getpriority(PRIO_PROCESS,0);
printf("Old priority = %dn",oldpri);
newpri = nice(2);
printf("New priority = %dn",newpri);
exit(0);
case -1:
perror("Process creation failedn");
break;
default:
printf("Parent is running,ChildPid is %d,ParentPid is %dn",pid,getpid());
break;
}
wait(&stat_val);
exit(0);
}
執行結果如下:
$ ./7-11
nice study
Child is running,Curpid is 0,ParentPid is 21428
Old priority = 0
New priority = 2
Parent is running,ChildPid is 21428,ParentPid is 21427
可以看到子程式的優先順序由原來的0變為2。
http://blog.chinaunix.net/u2/70445/article_116720.html[@more@]
系統呼叫getpid用來獲取當前程式的ID。輸入命令man 2 getpid可獲得該函式的宣告:
#include
#include
pid_t getpid(void);
程式7-9是一個使用getpid簡單的例子
#include
#include
#include
int main(void)
{
pid_t pid;
if ((pid = fork()) == -1){
printf("fork error!n");
exit(1);
}
if (pid == 0)
printf("getpid return %dn",getpid());
exit(0);
}
執行程式結果如下:
$ ./7-9
getpid return 5590
getpid返回了子程式的ID號5590。
二、setuid和setgid
可以用setuid設定實際使用者ID和有效使用者ID。與些類似,setgid用來設定實際組ID和有效組ID。函式的宣告在unistd.h標頭檔案,宣告如下:
#include
#include
int setuid(uid_t uid);
int setgid(gid_t gid);
設定使用者ID的setuid函式遵守以下規則(設定組ID的setgid函式與此類似)。
若程式具有root許可權,則函式將實際使用者ID、有效使用者ID設定為引數uid。
若程式不具有root許可權,但uid等於實際使用者ID,則setuid只將有效使用者ID設定為uid,不改變實際使用者ID。
若以上兩個條件都不能滿足,則函式呼叫失敗,返回-1,並設定errno為EPERM。
從以上規則可以看出,只有超級使用者程式才能更改實際使用者ID。所以一個非特權使用者程式是不能透過setuid或setuid得到特權使用者許可權的。但是su命令卻能使一個普通使用者變成特權使用者。這並不矛盾,因為su是一個“set_uid”程式。執行一個設定了set_uid位的程式時,核心將程式的有效使用者ID設定為檔案屬主的ID。而核心檢查一個程式是否具有訪問某檔案的許可權時,是使用程式的有效使用者ID來程式檢查。su程式的檔案屬主是root,普通使用者執行su命令時,su程式的許可權是root許可權。
下面透過程式7-10來解釋核心是如何檢查程式是否有權訪問某檔案的。可以看到核心是透過檢查程式的有效使用者ID來檢查的,而不是實際使用者ID。
#include
#include
#include
#include
extern int errno;
int main()
{
int fd;
printf("uid study:n");
printf("Process's uid = %d,euid = %dn",getuid(),geteuid);
//strerror函式獲取指定錯誤碼的提示資訊
if ((fd = open("Test.c",O_RDWR)) == -1){
printf("Open failure,errno is %d:%s n",errno,strerror(errno));
exit(1);
}
else{
printf("Open successfully!n");
}
close(fd);
exit(0);
}
以root使用者(提示符為#)使用命令在當前目錄下建立一個名為Test.c檔案:touch Test.c。在root使用者下執行該程式,此時檔案test.c的許可權為-rw-r--r--,即root使用者有讀寫許可權,其他使用者可讀。執行結果為:
# ./7-10
uid study:
Process's uid = 0,euid = 0
Open successfully!
轉到另外一個普通使用者下,執行結果為:
$ ./7-10
uid study:
Process's uid = 519,euid = 519
Open failure,errno is 13:Permission denied
在root使用者下,使用命令chmod對studyuid程式檔案設定set_uid位:
# chmod 4755 7-10
然後再換回一個普通使用者下,執行結果如下:
$ ./7-10
uid study:
Process's uid = 519,euid = 0
Open successfully!
執行結果說明:核心對程式存取檔案的許可權的檢查,是透過考查程式的有效使用者ID來實現的。
注意:對於呼叫了setuid函式的程式要格外小心,當程式的有效使用者ID即euid是root使用者時,如果呼叫setuid函式使euid為其他非root使用者,則該程式從此就不具有超級使用者許可權了。
可以這樣使用setuid函式:開始時某個程式需要root許可權完成一些工作,但後續的工作不需要root許可權。可以將該可執行程式檔案設定set_uid位,並使得該檔案的屬主是root。這樣普通使用者執行這個程式時,程式就具有了root許可權,當不再需要root許可權時,呼叫setuid(getuid())恢復程式的實際使用者ID和有效使用者ID為執行該程式的普通使用者的ID。對於一些提供網路服務的程式,這樣做是非常有必要的,否則就可能被攻擊者利用,使攻擊控制整個系統。
對於設定了set_uid位的可執行程式也要注意,尤其是對那些屬主是root的更要注意。因為Linux系統中root使用者擁有最高權力。駭客們往往喜歡尋找設定了set_uid位的可執行程式的漏洞,這樣的程式如果存在緩衝區溢位漏洞,並且該程式是一個網路程式,那麼駭客可以從遠端的地方輕鬆地利用該漏洞獲得執行該漏洞程式的主機的root許可權。即使這樣的程式不是網路程式,那麼也可以使本機上的惡意普通使用者提升為root使用者。
三、改變程式的優先順序
可以透過設定程式的優先順序來保證程式優先執行。在Linux下,透過系統呼叫nice可以改變程式的優先順序。nice系統呼叫用來改變呼叫程式的優先順序。命令列下輸入命令man 2 nice可以獲得該函式的宣告:
#include
int nice(int increment);
在介紹nice系統呼叫的用法前,需要先了解兩個重要的函式:getpriority和setpriority,它們宣告如下:
#include
#include
int getpriority(int which,int who);
int setpriority(int which,int who,int prio);
getpriority函式:該函式返回一組程式的優先順序。引數which和who組合確定返回哪一組程式的優先順序。which的可能取值以及who的意義如下:
PRIO_PROCESS:一個特定的程式,此時who的取值為程式ID。
PRIO_PGRP:一個程式組的所有程式,此時who的取值為程式組ID。
PRIO_USER:一個使用者擁有的所有程式,此時引數who取值為實際使用者ID。
getpriority函式如果呼叫成功返回指定程式的優先順序,如果出錯將返回-1,並設定errno的值。errno可能的取值如下:
ESRCH:which和who的組合與現在的所有程式均不匹配。
EINVAL:which是個無效的值。
注意:當指定的一組程式的優先順序不同時,getpriority將返回其中優先順序最低的一個。此外,當getpriority返回-1時,可能是發生錯誤,也有可能是返回的是指定程式的優先順序。區分它們的惟一方法是在呼叫getpriority前將errno清零。如果函式返回-1且errno不為零,說明有錯誤產生。
setpriority函式:該函式用來設定指定程式的優先順序。程式指定的方法與getpriority函式相同。如果呼叫成功,函式返回指定程式的優先順序,出錯則返回-1,並設定相應額errno。除了產生與getpriority相同的兩個錯誤外,還有可能產生以下錯誤。
EPERM:要設定優先順序的程式與當前程式不屬於同一個使用者,並且當前程式沒有CAP_SYS_NICE特許。
EACCES:該呼叫可能降低程式的優先順序並且程式沒有CAP_SYS_NICE特許。
透過以上兩函式,完全可以改變程式的優先順序。nice系統呼叫是它們的一種組合形式,nice系統呼叫等價於:
int nice(int increment)
{
int oldpro = getpriority(PRIO_PROCESS,getpid());
return setpriority(PRIO_PROCESS,getpid(),oldpro + increment);
}
例7-11演示了nice的使用方法。
#include
#include
#include
#include
#include
int main(void)
{
pid_t pid;
int stat_val = 0;
int oldpri,newpri;
printf("nice studyn");
pid = fork();
switch(pid){
case 0:
printf("Child is running,Curpid is %d,ParentPid is %dn",pid,getpid());
oldpri = getpriority(PRIO_PROCESS,0);
printf("Old priority = %dn",oldpri);
newpri = nice(2);
printf("New priority = %dn",newpri);
exit(0);
case -1:
perror("Process creation failedn");
break;
default:
printf("Parent is running,ChildPid is %d,ParentPid is %dn",pid,getpid());
break;
}
wait(&stat_val);
exit(0);
}
執行結果如下:
$ ./7-11
nice study
Child is running,Curpid is 0,ParentPid is 21428
Old priority = 0
New priority = 2
Parent is running,ChildPid is 21428,ParentPid is 21427
可以看到子程式的優先順序由原來的0變為2。
http://blog.chinaunix.net/u2/70445/article_116720.html[@more@]
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24790158/viewspace-1041372/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 需求:獲取其他程式中的ListView控制元件的文字內容View控制元件
- 重用其他程式庫
- 如何用C語言寫一個獲取視窗控制程式碼和其他資訊的小程式.C語言
- Lisp程式設計師眼中的其他程式設計師Lisp程式設計師
- 在SAP中控制使用者只能刪除屬於自己使用者的程式.其他程式只能檢視.
- 其他感興趣的程式碼庫
- 控制程式碼表篇——程式控制程式碼表
- openGauss 其他操作
- 最好的程式是程式設計師在處理其他事情時編寫的程式!程式設計師
- 儲存程式和程式控制:開發經驗分享及操作過程詳解
- [APUE] 程式控制
- # Python -05 程式的控制Python
- 在其他程式集訪問internal類
- visio 物件複製到其他程式物件
- Oracle控制檔案相關的其他(五)Oracle
- 【Linux】程式控制!!!Linux
- Linux 程式控制Linux
- Linux程式控制Linux
- 程式控制語句
- Linux程式控制程式設計Linux程式設計
- 控制程式碼表篇——全域性控制程式碼表
- 小程式操作dom
- 不要讓其他程式設計師修補自己的BUG程式設計師
- 樹形半封閉程式碼表中的“其他”項
- Git與其他版本控制系統的區別Git
- git和其他版本控制系統的區別Git
- java程式的氣泡排序操作Java排序
- 微信小程式的同步操作微信小程式
- Shell 指令碼程式併發&程式數控制指令碼
- JavaScript程式控制流(轉)JavaScript
- 程式控制流程面試題面試題
- Python 的控制流程式碼混淆Python
- 控制檯程式的事件處理 (轉)事件
- 程式控制:程式的建立、終止、阻塞、喚醒和切換
- PHP memcached 其他常用操作方法PHP
- 幽默:遊戲程式設計與其他程式設計完全不同? - hillelogram遊戲程式設計
- Runtime.getRuntime.exec操縱其他程式
- WebAssembly 基礎以及結合其他程式語言Web