如何修改 Linux 設備訪問許可權
接上篇文章 配置新版 GPG SSH 認證代理,我在使用 Ubuntu MATE 17.04 的過程中遇到了一個問題。
非 root 用戶無法訪問插在電腦上的 Yubikey (一個 USB 介面的 GPG Card 硬體設備),執行 gpg --card-status 時會報錯,無法顯示設備上的 GPG 密鑰對信息,更無法使用設備完成加解密和簽名操作。
Linux 遵守一切皆文件的原則,硬體設備會被映射為 /dev 下的一系列特殊文件。現代 Linux 系統一般使用 udev 檢測設備變動,及時更新掛載在 /dev 下的 devfs 文件結構。/dev 下某個設備文件的訪問許可權,就是這個設備本身的訪問許可權。
大多數情況下,/dev 下的外圍設備會由以 root 身份運行的守護進程接管,普通用戶想要訪問某設備的時候,直接和守護進程溝通即可。而 gpg (gpg-agent) 可能沒有經過良好的設計,普通用戶想要訪問 GPG Card 需要直接打開 /dev 下的設備文件,如果普通用戶沒有對應的許可權,就會發生錯誤。
以下是錯誤的排查和解決過程
查找設備文件,檢查許可權
lsusbn
使用 lsusb 命令列出所有 USB 設備
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hubnBus 001 Device 012: ID 1050:0407 Yubico.com nBus 001 Device 006: ID 05ac:8242 Apple, Inc. Built-in IR ReceivernBus 001 Device 011: ID 05ac:8289 Apple, Inc. nBus 001 Device 004: ID 0a5c:4500 Broadcom Corp. BCM2046B1 USB 2.0 Hub (part of BCM2046 Bluetooth)nBus 001 Device 007: ID 192f:0716 Avago Technologies, Pte. nBus 001 Device 005: ID 0853:0100 Topre Corporation HHKB ProfessionalnBus 001 Device 003: ID 0409:005a NEC Corp. HighSpeed HubnBus 001 Device 002: ID 0930:6545 Toshiba Corp. Kingston DataTraveler 102/2.0 / HEMA Flash Drive 2 GB / PNY Attache 4GB SticknBus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hubn
找到遇到問題的設備 「Yubico.com」,記下編號 「Bus 001, Device 012」
進入 "/dev/bus/usb/001" 目錄下(001 對應先前的 Bus 001),查看當前的設備許可權
[/dev/bus/usb/001]$ ls -alntotal 0ndrwxr-xr-x 2 root root 220 May 4 16:25 .ndrwxr-xr-x 4 root root 80 May 4 16:05 ..ncrw-rw-r-- 1 root root 189, 0 May 4 16:22 001ncrw-rw-r-- 1 root root 189, 1 May 4 16:22 002ncrw-rw-r-- 1 root root 189, 2 May 4 16:22 003ncrw-rw-r-- 1 root root 189, 3 May 4 16:22 004ncrw-rw-r-- 1 root root 189, 4 May 4 16:22 005ncrw-rw-r-- 1 root root 189, 5 May 4 16:22 006ncrw-rw-r-- 1 root root 189, 6 May 4 16:22 007ncrw-rw-r-- 1 root root 189, 10 May 4 16:22 011ncrw-rw-r-- 1 root root 189, 11 May 4 16:31 012n
果然,設備 012 的許可權是 "root:root rw-rw-r--",也就是說只有 root 有讀寫許可權,普通用戶只有讀許可權。與外圍硬體設備溝通,讀和寫都是必要的,實質上,非 root 用戶根本無法使用該設備。
創建 組 和 udev 規則
直接修改設備文件許可權顯然沒有意義,設備拔插時,udev 會更新 /dev,並且每次設備插入的時候,Bus 和 Device 的值都不確定。
正確的方法是創建一個用戶組,然後編寫一條 udev 規則,讓符合規則的設備文件的組所有權自動設置為該組。這樣,組內用戶都可以訪問該設備,既避免了安全問題,又可以讓非 root 用戶訪問該設備,並且長期有效。
首先,創建一個組 "card",將用戶 "ryan" 加入該組
(下面是 Debian / Ubuntu 命令,其他發行版請查找對應命令;用戶組更改需要重新登錄才能生效,GUI 用戶可能需要重啟電腦)
addgroup cardnadduser ryan cardn
然後,創建一條 udev 規則,把設備所有權由 "root:root" 修改為 "root:card"
編寫規則 前 要先了解設備的詳細信息
運行命令(舊版 udev 使用 udevinfo 命令)
udevadm info -a /dev/bus/usb/001/012n
得到設備的詳細信息以供參考:
Udevadm info starts with the device specified by the devpath and thennwalks up the chain of parent devices. It prints for every devicenfound, all possible attributes in the udev rules key format.nA rule to match, can be composed by the attributes of the devicenand the attributes from one single parent device.nn looking at device /devices/pci0000:00/0000:00:14.0/usb1/1-8:n KERNEL=="1-8"n SUBSYSTEM=="usb"n DRIVER=="usb"n ATTR{authorized}=="1"n ATTR{avoid_reset_quirk}=="0"n ATTR{bConfigurationValue}=="1"n ATTR{bDeviceClass}=="00"n ATTR{bDeviceProtocol}=="00"n ATTR{bDeviceSubClass}=="00"n ATTR{bMaxPacketSize0}=="64"n ATTR{bMaxPower}=="30mA"n ATTR{bNumConfigurations}=="1"n ATTR{bNumInterfaces}==" 3"n ATTR{bcdDevice}=="0434"n ATTR{bmAttributes}=="80"n ATTR{busnum}=="1"n ATTR{configuration}==""n ATTR{devnum}=="12"n ATTR{devpath}=="8"n ATTR{idProduct}=="0407"n ATTR{idVendor}=="1050"n ATTR{ltm_capable}=="no"n ATTR{manufacturer}=="Yubico"n ATTR{maxchild}=="0"n ATTR{product}=="Yubikey 4 OTP+U2F+CCID"n........以下略去n
如果我們希望所有 Yubico 產的 USB 設備都自動設置所有權為 "root:card",參考上面的信息,可以編寫如下規則:
SUBSYSTEM=="usb", ATTRS{manufacturer}=="Yubico", GROUP="card"n
如果我們想只限定 Yubikey 4 這一個型號,那麼參考上面的信息,可以這樣寫規則:
SUBSYSTEM=="usb", ATTRS{product}=="Yubikey 4 OTP+U2F+CCID", GROUP="card"n
(前兩條 == 是條件判定,最後的 GROUP="card" 是賦值,udev 規則還是很簡單的)
把編寫好的規則保存到
/etc/udev/rules.d/10-yubikey.rulesn
重啟,或者使用命令 "udevadm control --reload-rules" 重新載入規則,Yubico 的設備文件所有權就會自動設置為 "root:card","ryan" 用戶就可以直接使用 "gpg --card-status" 訪問該設備了。
推薦閱讀:
※怎樣評價《無根的根:無名師的 Unix 心傳》?
※APUE第二版封面的漫畫什麼意思?
※elementary OS 號稱最美 Linux ,哪個 Linux 發行版比較好看呢?
※Pwn2Own 有Unix/Linux系統的機器被攻破么?
※十年回顧-我的Linux之路