深入Android系統權限和root權限

1. Android權限說明

     Android系統是運行在Linux內核上的,Android與Linux分別有自己的一套嚴格的安全及權限機制,Android系統權限相關的內容,

(一)linux文件系統上的權限

-rwxr-x--x system   system       4156 2012-06-30 16:12 test.apk.

    代表的是相應的用戶/用戶組及其他人對此文件的訪問權限,與此文件運行起來具有的權限完全不相關
比如上面的例子只能說明system用戶擁有對此文件的讀寫執行權限;system組的用戶對此文件擁有讀、執行權限;其他人對此文件只具有執行權限。而test.apk運行起來後可以幹哪些事情,跟這個就不相關了。
千萬不要看apk文件系統上屬於system/system用戶及用戶組,或者root/root用戶及用戶組,就認爲apk具有system或root權限。apk程序是運行在虛擬機上的,對應的是Android獨特的權限機制,只有體現到文件系統上時才使用linux的權限設置。

(二)Android的權限規則

(1)Android中的apk必須簽名
     這種簽名不是基於權威證書的,不會決定某個應用允不允許安裝,而是一種自簽名證書。
重要的是,android系統有的權限是基於簽名的。比如:system等級的權限有專門對應的簽名,簽名不對,權限也就獲取不到。

默認生成的APK文件是debug簽名的。獲取system權限時用到的簽名見後面描述

(2)基於UserID的進程級別的安全機制
      進程有獨立的地址空間,進程與進程間默認是不能互相訪問的,Android通過爲每一個apk分配唯一的linux userID來實現,名稱爲"app_"加一個數字,比如app_43不同的UserID,運行在不同的進程,所以apk之間默認便不能相互訪問。

      Android提供瞭如下的一種機制,可以使兩個apk打破前面講的這種壁壘。
在AndroidManifest.xml中利用sharedUserId屬性給不同的package分配相同的userID,通過這樣做,兩個package可以被當做同一個程序,
     系統會分配給兩個程序相同的UserID。當然,基於安全考慮,兩個apk需要相同的簽名,否則沒有驗證也就沒有意義了。

(3)默認apk生成的數據對外是不可見的
     實現方法是:Android會爲程序存儲的數據分配該程序的UserID。
藉助於Linux嚴格的文件系統訪問權限,便實現了apk之間不能相互訪問似有數據的機制。
例:我的應用創建的一個文件,默認權限如下,可以看到只有UserID爲app_21的程序才能讀寫該文件。
-rw------- app_21   app_21      87650 2000-01-01 09:48 test.txt

    如何對外開放?
<1> 使用MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE標記。
When creating a new file with getSharedPreferences(String, int), openFileOutput(String, int), or openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory), you can use the MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE flags to allow any other package to read/write the file. When setting these flags, the file is still owned by your application, but its global read and/or write permissions have been set appropriately so any other application can see it.


(4)AndroidManifest.xml中的顯式權限聲明
    Android默認應用是沒有任何權限去操作其他應用或系統相關特性的,應用在進行某些操作時都需要顯式地去申請相應的權限。
    一般以下動作時都需要申請相應的權限:

A particular permission may be enforced at a number of places during your program's operation:

At the time of a call into the system, to prevent an application from executing certain functions.When starting an activity, to prevent applications from launching activities of other applications.Both sending and receiving broadcasts, to control who can receive your broadcast or who can send a broadcast to you.When accessing and operating on a content provider.Binding or starting a service.


      在應用安裝的時候,package installer會檢測該應用請求的權限,根據該應用的簽名或者提示用戶來分配相應的權限。
      在程序運行期間是不檢測權限的。如果安裝時權限獲取失敗,那執行就會出錯,不會提示用戶權限不夠。
大多數情況下,權限不足導致的失敗會引發一個 SecurityException,會在系統log(system log)中有相關記錄。

(5)權限繼承/UserID繼承
     當我們遇到apk權限不足時,我們有時會考慮寫一個linux程序,然後由apk調用它去完成某個它沒有權限完成的事情,很遺憾,這種方法是行不通的。
前面講過,android權限是在進程層面的,也就是說一個apk應用啓動的子進程的權限不可能超越其父進程的權限(即apk的權限),
即使單獨運行某個應用有權限做某事,但如果它是由一個apk調用的,那權限就會被限制。
實際上,android是通過給子進程分配父進程的UserID實現這一機制的。

(三)常見權限不足問題分析

       首先要知道,普通apk程序是運行在非root、非system層級的,也就是說看要訪問的文件的權限時,看的是最後三位。
       另外,通過system/app安裝的apk的權限一般比直接安裝或adb install安裝的apk的權限要高一些。

       言歸正傳,運行一個android應用程序過程中遇到權限不足,一般分爲兩種情況:
(1)Log中可明顯看到權限不足的提示。
      此種情況一般是AndroidManifest.xml中缺少相應的權限設置,好好查找一番權限列表,應該就可解決,是最易處理的情況。

      有時權限都加上了,但還是報權限不足,是什麼情況呢?
      Android系統有一些API及權限是需要apk具有一定的等級才能運行的。比如 SystemClock.setCurrentTimeMillis()修改系統時間,WRITE_SECURE_SETTINGS權限好像都是需要有system級的權限纔行。也就是說UserID是system.

(2)Log裏沒有報權限不足,而是一些其他Exception的提示,這也有可能是權限不足造成的。
      比如:我們常會想讀/寫一個配置文件或其他一些不是自己創建的文件,常會報java.io.FileNotFoundException錯誤。系統認爲比較重要的文件一般權限設置的也會比較嚴格,特別是一些很重要的(配置)文件或目錄。

-r--r----- bluetooth bluetooth      935 2010-07-09 20:21 dbus.conf
drwxrwx--x system   system            2010-07-07 02:05 data

       dbus.conf好像是藍牙的配置文件,從權限上來看,根本就不可能改動,非bluetooth用戶連讀的權利都沒有。

/data目錄下存的是所有程序的私有數據,默認情況下android是不允許普通apk訪問/data目錄下內容的,通過data目錄的權限設置可知,其他用戶沒有讀的權限。
       所以adb普通權限下在data目錄下敲ls命令,會得到opendir failed, Permission denied的錯誤,通過代碼file.listfiles()也無法獲得data目錄下的內容。


       上面兩種情況,一般都需要提升apk的權限,目前我所知的apk能提升到的權限就是system(具體方法見:如何使Android應用程序獲取系統權限)。 

2. 怎樣使android apk 獲取system權限

最近在回答客戶的問題時,提到怎麼將apk 升級到root權限。 

     一般權限的添加

     一般情況下,設定apk的權限,可在AndroidManifest.xml中添加android:sharedUserId="android.uid.xxx>

    例如: 給apk添加system權限

   <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    ... ... 
   android:sharedUserId="android.uid.system">

     同時還需要在對應的Android.mk中添加LOCAL_CERTIFICATE := platform這一項。即用系統的簽名,通過這種方式只能使apk的權限升級到system級別,系統中要求root權限才能訪問的文件,apk還是不能訪問。

     比如在android 的API中有提供 SystemClock.setCurrentTimeMillis()函數來修改系統時間,這個函數需要root權限或者運行與系統進程中才可以用。

 2.1 方案一

        第一個方法簡單點,不過需要在Android系統源碼的環境下用make來編譯:

        (1) 在應用程序的AndroidManifest.xml中的manifest節點中加入android:sharedUserId="android.uid.system"這個屬性。

        (2) 修改Android.mk文件,加入LOCAL_CERTIFICATE := platform這一行

        (3) 使用mm命令來編譯,生成的apk就有修改系統時間的權限了。

 2.2 方案二

        第二個方法是直接把eclipse編出來的apk用系統的簽名文件簽名

        (1) 加入android:sharedUserId="android.uid.system"這個屬性。

        (2) 使用eclipse編譯出apk文件。

        (3) 使用目標系統的platform密鑰來重新給apk文件簽名。首先找到密鑰文件,在我的Android源碼目錄中的位置是"build/target/product/security",下面的platform.pk8和platform.x509.pem兩個文件。然後用Android提供的Signapk工具來簽名,signapk的源代碼是在"build/tools/signapk"下,編譯後在out/host/linux-x86/framework下,用法爲java -jar signapk.jar  platform.x509.pem platform.pk8 input.apk output.apk"。

       加入android:sharedUserId="android.uid.system"這個屬性。通過Shared User id,擁有同一個User id的多個APK可以配置成運行在同一個進程中。那麼把程序的UID配成android.uid.system,也就是要讓程序運行在系統進程中,這樣就有權限來修改系統時間了。

        只是加入UID還不夠,如果這時候安裝APK的話發現無法安裝,提示簽名不符,原因是程序想要運行在系統進程中還要有目標系統的platform key,就是上面第二個方法提到的platform.pk8和platform.x509.pem兩個文件。用這兩個key簽名後apk才真正可以放入系統進程中。第一個方法中加入LOCAL_CERTIFICATE := platform其實就是用這兩個key來簽名。

        這也有一個問題,就是這樣生成的程序只有在原始的Android系統或者是自己編譯的系統中才可以用,因爲這樣的系統纔可以拿到platform.pk8和platform.x509.pem兩個文件。要是別家公司做的Android上連安裝都安裝不了。試試原始的Android中的key來簽名,程序在模擬器上運行OK,不過放到G3上安裝直接提示"Package ... has no signatures that match those in shared user android.uid.system",這樣也是保護了系統的安全。

3. 怎樣使android apk 獲取root權限

       一般linux 獲取root權限是通過執行su命令,那能不能在apk程序中也同樣執行一下該命令呢,我們知道在linux編程中,有exec函數族: 

  1. int execl(cONst char *path, const char *arg, ...);  
  2. int execlp(const char *file, const char *arg, ...);  
  3. int execle(const char *path, const char *arg, ..., char *const envp[]);  
  4. int execv(const char *path, char *const argv[]);  
  5. int execvp(const char *file, char *const argv[]);  
  6. int execve(const char *path, char *const argv[], char *const envp[]);  

      在java中我們可以藉助 Runtime.getRuntime().exec(String command)訪問底層Linux下的程序或腳本,這樣就能執行su命令,使apk具有root權限,能夠訪問系統中需要root權限才能執行的程序或腳本了,具體例子:

  1. package com.visit.dialoglog;  
  2. import java.io.DataInputStream;  
  3. import java.io.DataOutputStream;  
  4. import java.io.IOException;  
  5. import android.app.Activity;  
  6. import android.os.Bundle;  
  7. import android.util.Log;  
  8. public class VisitRootfileActivity extends Activity {  
  9.     private static final String TAG = "VisitRootfileActivity";  
  10.     Process process = null;  
  11.     Process process1 = null;     
  12.     DataOutputStream os = null;  
  13.     DataInputStream is = null;  
  14.     /** Called when the activity is first created. */  
  15.     @Override  
  16.     public void onCreate(Bundle savedInstanceState) {  
  17.         super.onCreate(savedInstanceState);  
  18.         setContentView(R.layout.main);  
  19.         try {  
  20.             process = Runtime.getRuntime().exec("/system/xbin/su"); /*這裏可能需要修改su 
  21.                        的源代碼 (注掉  if (myuid != AID_ROOT && myuid != AID_SHELL) {*/  
  22.   
  23.             os = new DataOutputStream(process.getOutputStream());  
  24.             is = new DataInputStream(process.getInputStream());  
  25.             os.writeBytes("/system/bin/ls" + " \n");  //這裏可以執行具有root 權限的程序了    
  26.               os.writeBytes(" exit \n");  
  27.             os.flush();  
  28.             process.waitFor();  
  29.         } catch (Exception e) {              
  30.             Log.e(TAG, "Unexpected error - Here is what I know:" + e.getMessage());  
  31.         } finally {  
  32.             try {  
  33.                 if (os != null) {  
  34.                     os.close();  
  35.                 }  
  36.                 if (is != null) {  
  37.                     is.close();  
  38.                 }  
  39.                 process.destroy();  
  40.             } catch (Exception e) {  
  41.             }  
  42.         }// get the root privileges  
  43.     }  
  44. }  


4. APK在AndroidManifest.xml常用權限 

  1. android.permission.ACCESS_CHECKIN_PROPERTIES  
  2. //允許讀寫訪問”properties”表在checkin數據庫中,改值可以修改上傳  
  3.   
  4. android.permission.ACCESS_COARSE_LOCATION   
  5. //允許一個程序訪問CellID或WiFi熱點來獲取粗略的位置  
  6.   
  7. android.permission.ACCESS_FINE_LOCATION   
  8. //允許一個程序訪問精良位置(如GPS)  
  9.   
  10. android.permission.ACCESS_LOCATION_EXTRA_COMMANDS   
  11. //允許應用程序訪問額外的位置提供命令   
  12.   
  13. android.permission.ACCESS_MOCK_LOCATION   
  14. //允許程序創建模擬位置提供用於測試   
  15.   
  16. android.permission.ACCESS_NETWORK_STATE   
  17. //允許程序訪問有關GSM網絡信息  
  18.   
  19. android.permission.ACCESS_SURFACE_FLINGER   
  20. //允許程序使用SurfaceFlinger底層特性  
  21.   
  22. android.permission.ACCESS_WIFI_STATE   
  23. //允許程序訪問Wi-Fi網絡狀態信息  
  24.   
  25. android.permission.ADD_SYSTEM_SERVICE   
  26. //允許程序發佈系統級服務   
  27.   
  28. android.permission.BATTERY_STATS   
  29. //允許程序更新手機電池統計信息   
  30.   
  31. android.permission.BLUETOOTH   
  32. //允許程序連接到已配對的藍牙設備   
  33.   
  34. android.permission.BLUETOOTH_ADMIN   
  35. //允許程序發現和配對藍牙設備   
  36.   
  37. android.permission.BRICK   
  38. //請求能夠禁用設備(非常危險)  
  39.   
  40. android.permission.BROADCAST_PACKAGE_REMOVED   
  41. //允許程序廣播一個提示消息在一個應用程序包已經移除後  
  42.   
  43. android.permission.BROADCAST_STICKY   
  44. //允許一個程序廣播常用intents   
  45.   
  46. android.permission.CALL_PHONE   
  47. //允許一個程序初始化一個電話撥號不需通過撥號用戶界面需要用戶確認  
  48.   
  49. android.permission.CALL_PRIVILEGED   
  50. //允許一個程序撥打任何號碼,包含緊急號碼無需通過撥號用戶界面需要用戶確認  
  51.   
  52. android.permission.CAMERA   
  53. //請求訪問使用照相設備   
  54.   
  55. android.permission.CHANGE_COMPONENT_ENABLED_STATE   
  56. //允許一個程序是否改變一個組件或其他的啓用或禁用  
  57.   
  58. android.permission.CHANGE_CONFIGURATION   
  59. //允許一個程序修改當前設置,如本地化   
  60.   
  61. android.permission.CHANGE_NETWORK_STATE  
  62. //允許程序改變網絡連接狀態   
  63.   
  64. android.permission.CHANGE_WIFI_STATE   
  65. //允許程序改變Wi-Fi連接狀態  
  66.   
  67. android.permission.CLEAR_APP_CACHE   
  68. //允許一個程序清楚緩存從所有安裝的程序在設備中  
  69.   
  70. android.permission.CLEAR_APP_USER_DATA   
  71. //允許一個程序清除用戶設置   
  72.   
  73. android.permission.CONTROL_LOCATION_UPDATES   
  74. //允許啓用禁止位置更新提示從無線模塊   
  75.   
  76. android.permission.DELETE_CACHE_FILES   
  77. //允許程序刪除緩存文件   
  78.   
  79. android.permission.DELETE_PACKAGES   
  80. //允許一個程序刪除包   
  81.   
  82. android.permission.DEVICE_POWER   
  83. //允許訪問底層電源管理   
  84.   
  85. android.permission.DIAGNOSTIC   
  86. //允許程序RW診斷資源  
  87.   
  88. android.permission.DISABLE_KEYGUARD   
  89. //允許程序禁用鍵盤鎖   
  90.   
  91. android.permission.DUMP   
  92. //允許程序返回狀態抓取信息從系統服務   
  93.   
  94. android.permission.EXPAND_STATUS_BAR   
  95. //允許一個程序擴展收縮在狀態欄,android開發網提示應該是一個類似Windows Mobile中的托盤程序  
  96.   
  97. android.permission.FACTORY_TEST   
  98. //作爲一個工廠測試程序,運行在root用戶  
  99.   
  100. android.permission.FLASHLIGHT   
  101. //訪問閃光燈,android開發網提示HTC Dream不包含閃光燈  
  102.   
  103. android.permission.FORCE_BACK   
  104. //允許程序強行一個後退操作是否在頂層activities  
  105.   
  106. android.permission.FOTA_UPDATE   
  107. //暫時不瞭解這是做什麼使用的,android開發網分析可能是一個預留權限.  
  108.   
  109. android.permission.GET_ACCOUNTS   
  110. //訪問一個帳戶列表在Accounts Service中  
  111.   
  112. android.permission.GET_PACKAGE_SIZE   
  113. //允許一個程序獲取任何package佔用空間容量  
  114.   
  115. android.permission.GET_TASKS   
  116. //允許一個程序獲取信息有關當前或最近運行的任務,一個縮略的任務狀態,是否活動等等  
  117.   
  118. android.permission.HARDWARE_TEST   
  119. //允許訪問硬件   
  120.   
  121. android.permission.INJECT_EVENTS   
  122. //允許一個程序截獲用戶事件如按鍵、觸摸、軌跡球等等到一個時間流,android開發網提醒算是hook技術吧  
  123.   
  124. android.permission.INSTALL_PACKAGES   
  125. //允許一個程序安裝packages   
  126.   
  127. android.permission.INTERNAL_SYSTEM_WINDOW   
  128. //允許打開窗口使用系統用戶界面   
  129.   
  130. android.permission.INTERNET   
  131. //允許程序打開網絡套接字   
  132.   
  133. android.permission.MANAGE_APP_TOKENS   
  134. //允許程序管理(創建、催後、 z- order默認向z軸推移)程序引用在窗口管理器中  
  135.   
  136. android.permission.MASTER_CLEAR   
  137. //目前還沒有明確的解釋,android開發網分析可能是清除一切數據,類似硬格機  
  138.   
  139. android.permission.MODIFY_AUDIO_SETTINGS   
  140. //允許程序修改全局音頻設置   
  141.   
  142. android.permission.MODIFY_PHONE_STATE   
  143. //允許修改話機狀態,如電源,人機接口等   
  144.   
  145. android.permission.MOUNT_UNMOUNT_FILESYSTEMS   
  146. //允許掛載和反掛載文件系統可移動存儲   
  147.   
  148. android.permission.PERSISTENT_ACTIVITY   
  149. //允許一個程序設置他的activities顯示  
  150.   
  151. android.permission.PROCESS_OUTGOING_CALLS   
  152. //允許程序監視、修改有關播出電話   
  153.   
  154. android.permission.READ_CALENDAR   
  155. //允許程序讀取用戶日曆數據   
  156.   
  157. android.permission.READ_CONTACTS   
  158. //允許程序讀取用戶聯繫人數據   
  159.   
  160. android.permission.READ_FRAME_BUFFER   
  161. //允許程序屏幕波或和更多常規的訪問幀緩衝數據   
  162.   
  163. android.permission.READ_INPUT_STATE   
  164. //允許程序返回當前按鍵狀態   
  165.   
  166. android.permission.READ_LOGS   
  167. //允許程序讀取底層系統日誌文件   
  168.   
  169. android.permission.READ_OWNER_DATA   
  170. //允許程序讀取所有者數據   
  171.   
  172. android.permission.READ_SMS   
  173. //允許程序讀取短信息   
  174.   
  175. android.permission.READ_SYNC_SETTINGS   
  176. //允許程序讀取同步設置   
  177.   
  178. android.permission.READ_SYNC_STATS   
  179. //允許程序讀取同步狀態   
  180.   
  181. android.permission.REBOOT   
  182. //請求能夠重新啓動設備   
  183.   
  184. android.permission.RECEIVE_BOOT_COMPLETED   
  185. //允許一個程序接收到   
  186.   
  187. android.permission.RECEIVE_MMS   
  188. //允許一個程序監控將收到MMS彩信,記錄或處理  
  189.   
  190. android.permission.RECEIVE_SMS   
  191. //允許程序監控一個將收到短信息,記錄或處理   
  192.   
  193. android.permission.RECEIVE_WAP_PUSH   
  194. //允許程序監控將收到WAP PUSH信息  
  195.   
  196. android.permission.RECORD_AUDIO   
  197. //允許程序錄制音頻   
  198.   
  199. android.permission.REORDER_TASKS   
  200. //允許程序改變Z軸排列任務  
  201.   
  202. android.permission.RESTART_PACKAGES   
  203. //允許程序重新啓動其他程序   
  204.   
  205. android.permission.SEND_SMS   
  206. //允許程序發送SMS短信  
  207.   
  208. android.permission.SET_ACTIVITY_WATCHER   
  209. //允許程序監控或控制activities已經啓動全局系統中  
  210.   
  211. android.permission.SET_ALWAYS_FINISH   
  212. //允許程序控制是否活動間接完成在處於後臺時   
  213.   
  214. android.permission.SET_ANIMATION_SCALE   
  215. //修改全局信息比例   
  216.   
  217. android.permission.SET_DEBUG_APP   
  218. //配置一個程序用於調試   
  219.   
  220. android.permission.SET_ORIENTATION   
  221. //允許底層訪問設置屏幕方向和實際旋轉   
  222.   
  223. android.permission.SET_PREFERRED_APPLICATIONS   
  224. //允許一個程序修改列表參數PackageManager.addPackageToPreferred()和PackageManager.removePackageFromPreferred()方法  
  225.   
  226. android.permission.SET_PROCESS_FOREGROUND   
  227. //允許程序當前運行程序強行到前臺   
  228.   
  229. android.permission.SET_PROCESS_LIMIT   
  230. //允許設置最大的運行進程數量   
  231.   
  232. android.permission.SET_TIME_ZONE   
  233. //允許程序設置時間區域   
  234.   
  235. android.permission.SET_WALLPAPER   
  236. //允許程序設置壁紙   
  237.   
  238. android.permission.SET_WALLPAPER_HINTS   
  239. //允許程序設置壁紙hits   
  240.   
  241. android.permission.SIGNAL_PERSISTENT_PROCESSES   
  242. //允許程序請求發送信號到所有顯示的進程中   
  243.   
  244. android.permission.STATUS_BAR   
  245. //允許程序打開、關閉或禁用狀態欄及圖標Allows an application to open, close, or disable the status bar and its icons.  
  246.   
  247. android.permission.SUBSCRIBED_FEEDS_READ   
  248. //允許一個程序訪問訂閱RSS Feed內容提供  
  249.   
  250. android.permission.SUBSCRIBED_FEEDS_WRITE   
  251. //系統暫時保留改設置,android開發網認爲未來版本會加入該功能。  
  252.   
  253. android.permission.SYSTEM_ALERT_WINDOW   
  254. //允許一個程序打開窗口使用 TYPE_SYSTEM_ALERT,顯示在其他所有程序的頂層(Allows an application to open windows using the type TYPE_SYSTEM_ALERT, shown on top of all other applications. )  
  255.   
  256. android.permission.VIBRATE   
  257. //允許訪問振動設備   
  258.   
  259. android.permission.WAKE_LOCK   
  260. //允許使用PowerManager的 WakeLocks保持進程在休眠時從屏幕消失  
  261.   
  262. android.permission.WRITE_APN_SETTINGS   
  263. //允許程序寫入APN設置  
  264.   
  265. android.permission.WRITE_CALENDAR   
  266. //允許一個程序寫入但不讀取用戶日曆數據   
  267.   
  268. android.permission.WRITE_CONTACTS   
  269. //允許程序寫入但不讀取用戶聯繫人數據   
  270.   
  271. android.permission.WRITE_GSERVICES   
  272. //允許程序修改Google服務地圖  
  273.   
  274. android.permission.WRITE_OWNER_DATA   
  275. //允許一個程序寫入但不讀取所有者數據   
  276.   
  277. android.permission.WRITE_SETTINGS   
  278. //允許程序讀取或寫入系統設置   
  279.   
  280. android.permission.WRITE_SMS   
  281. //允許程序寫短信   
  282.   
  283. android.permission.WRITE_SYNC_SETTINGS   
  284. //允許程序寫入同步設置  


5. Linux的特殊文件權限 

發佈於:  一般文件權限讀(R),寫(W),執行(X)權限比較簡單。一般材料上面都有介紹。                 這裏介紹一下一些特殊的文件權限——SUID,SGID,Stick bit。如果你檢查一下/usr/bin/passwd和/tmp/的文件權限你就會發現和普通的文件權限有少許不同,如下圖所示:

    這裏就涉及到SUID和Stick bit。

  • SUID和SGID

    我們首先來談一下passwd程序特殊的地方。大家都知道,Linux把用戶的密碼信息存放在/etc/shadow裏面,該文件屬性如下:

 可以看到Shadow的只有所有者可讀寫,所有者是root,所以該文件對普通用戶是不可讀寫的。但是普通用戶調用passwd程序是可以修改自己的密碼的,這又是爲什麼呢?難道普通用戶可以讀寫shadow文件?當然不是啦。password可以修改shadow文件的原因是他設置了SUID文件權限。

    SUID文件權限作用於可執行文件。一般的可執行文件在執行期的所有者是當前用戶,比如當前系統用戶是simon,simon運行程序a.out,a.out執行期的所有者應該是simon。但是如果我們給可執行文件設置了SUID權限,則該程序執行期間的所有者,就是該文件所有者。還以前面的a.out爲例,假如a.out設置了SUID,並且其所有者是root,系統當前用戶是simon,當simon運行a.out的時候,a.out在運行期的所有者就是root,這時a.out可以存取只有root權限才能存取的資源,比如讀寫shadow文件。當a.out執行結束的時候當前用戶的權限又回到了simon的權限了。

     passwd就是設置了SUID權限,並且passwd的所有者是root,所以所有的用戶都可以執行他,在passwd運行期,程序獲得臨時的root權限,這時其可以存取shadow文件。當passwd運行完成,當前用戶又回到普通權限。

     同理,設置程序的SGID,可以使程序運行期可以臨時獲得所有者組的權限。在團隊開發的時候,這個文件權限比較有用,一般系統用SUID比較多。

     SGID可以用於目錄,當目錄設置了SGID之後,在該目錄下面建立的所有文件和目錄都具有和該目錄相同的用戶組。

  • Stick bit(粘貼位)

     對程序,該權限告訴系統在程序完成後在內存中保存一份運行程序的備份,如該程序常用,可爲系統節省點時間,不用每次從磁盤加載到內存。Linux當前對文件沒有實現這個功能,一些其他的UNIX系統實現了這個功能。

     Stick bit可以作用於目錄,在設置了粘貼位的目錄下面的文件和目錄,只有所有者和root可以刪除他。現在我們可以回頭去看看/tmp/目錄的情況,這個目錄設置了粘貼位。所以說,所有人都可以對該目錄讀寫執行(777),這樣意味着所有人都可以在/tmp/下面創建臨時目錄。因爲設置Stick bit只有所有者和root才能刪除目錄。這樣普通用戶只能刪除屬於自己的文件,而不能刪除其他人的文件。如下圖所示:

  • 設置SUID,SGID,Stick bit

     前面介紹過SUID與SGID的功能,那麼,如何打開文件使其成爲具有SUID與SGID的權限呢?這就需要使用數字更改權限了。現在應該知道,使用數字更改權限的方式爲“3個數字”的組合,那麼,如果在這3個數字之前再加上一個數字,最前面的數字就表示這幾個屬性了(注:通常我們使用chmod 0777 filename的方式來設置filename的屬性時,則是假設沒有SUID、SGID及Sticky bit)。 
     4爲SUID
     2
爲SGID 
     1爲Sticky bit 

     假設要將一個文件屬性改爲“-rwsr-xr-x”,由於s在用戶權限中,所以是SUID,因此,在原先的755之前還要加上4,也就是使用“chmod 4755 filename”來設置。

     SUID也可以用“chmod u+s filename”來設置,“chmod u-s filename”來取消SUID設置;同樣,SGID可以用“chmod g+s filename”,“chmod g-s filename”來取消SGID設置。

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