震驚!沒想到你是這樣的flatpak...

引言
之前我們介紹過如何在優(yōu)麒麟和銀河麒麟社區(qū)版上構建snap/flatpak包(傳送門),今天我們來更深入的認識下flatpak:
Flatpak(前世為xdg-app) 是一種用于構建,分發(fā),安裝和運行應用程序的技術。它主要針對的是Linux桌面,通過在沙箱中隔離應用程序來提高Linux桌面的安全性,允許應用程序安裝在任何Linux發(fā)行版上。
歷史:
2013: 在GNOME Developer Experience hackfest, Brussels大會后,萌生在GNOME中使用應用程序容器技術的念頭,次年開始開發(fā)。
2016年5月: 第一個主版本xdg-app發(fā)布。
6月:重命名為flatpak。
8月:endless OS 3.0, 第一個默認支持Flatpak的發(fā)行版。
11月:ClearLinux聲明采用flatpak。
2017年2月: 最新的flatpak已經可以在Arch, Debian, Fedora, Gentoo, Mageia, openSUSE, Ubuntu等的最新版本上運行。
基本概念:
運行時(runtimes)
“運行時”提供應用程序所需的基本依賴。有各種各樣的“運行時”,比如“Freedesktop運行時”,“GNOME運行時”?!癋reedesktop運行時”包含一系列必要的庫和服務,包括D-Bus, GLib, PulseAudio, X11和Wayland等?!癎NOME運行時”基于“FreeDesktop運行時”,增加了一些GNOME平臺相關的庫,比如GStreamer, GTK+, GVFS等。必須針對運行時構建每個應用程序,并且必須在主機系統(tǒng)上安裝此運行時才能運行應用程序。用戶可以同時安裝多個不同的運行時,包括不同版本的同一個運行時。KDE runtime正在開發(fā)中。
每一個運行時可以看做一個’/usr’ 文件系統(tǒng),當程序運行時,它的運行時掛載在‘/usr’上。
捆綁庫(Bundled libraries)
當一個程序需要的依賴不在運行時中,使用捆綁庫來綁定這些依賴到程序上。
SDK(軟件開發(fā)套件)
SDK也是一個“運行時”,是用于構建應用程序的特殊類型的運行時,它包含了構建和打包工具(‘devel’ parts),如頭文件,編譯器和調試器。通常,SDK與“運行時”配對,由應用程序使用。
擴展(Extensions)
一個擴展是對于運行時或程序的可選插件,一般用于把translations和debug信息從運行時分離出來,比如, org.freedesktop.Platform.Locale 可以追加到org.freedesktop.Platform運行時上用來添加翻譯。
沙箱(Sandbox)
使用Flatpak,每個應用程序都是在孤立的環(huán)境中構建和運行的。默認情況下,應用程序只能“查看”自身及其“運行時”,訪問用戶文件,網絡,graphics sockets,總線和設備上的子系統(tǒng)必須明確授予權限,訪問其他內容(如其他進程)是不允許的。(可以通過Portals機制在沙箱內訪問外面系統(tǒng),比如打印,截圖等)
原理:
Flatpak主要使用了如下技術:
1. bubblewrap:依賴它作為沙箱的底層實現(xiàn), 限制了應用程序訪問操作系統(tǒng)或用戶數據的能力,并且提供了非特權用戶使用容器的能力。
2. Systemd:將各個subsystem和cgroup樹關聯(lián)并掛載好,為沙箱創(chuàng)建 cgroups。
3. D-Bus, 為應用程序提供高層APIs。
4. 使用Open Container Initiative的OCI格式作為單文件的傳輸格式,方便傳輸。
5. 使用OSTree系統(tǒng)用于版本化和分發(fā)文件系統(tǒng)樹。
6. 使用Appstream 元數據,使得Flatpak應用程序在軟件中心可以完美呈現(xiàn)出來。
而其中最重要的當屬bubblewrap,它是整個應用沙箱構建的關鍵,主要利用了如下內核特性:
Namespaces:
命名空間是對全局系統(tǒng)資源的一個封裝隔離,使得處于不同namespace的進程擁有獨立的全局系統(tǒng)資源,改變一個namespace中的系統(tǒng)資源只會影響當前namespace里的進程,對其他namespace中的進程沒有影響。它控制了進程的可見范圍,例如網絡、掛載點、進程等等。同時使得非特權用戶可以創(chuàng)建沙箱。它有以下幾類:
● Mount namespace (CLONE_NEWNS):
用來隔離文件系統(tǒng)的掛載點, 使得不同的mount namespace擁有自己獨立的掛載點信息,不同的namespace之間不會相互影響,這對于構建用戶或者容器自己的文件系統(tǒng)目錄非常有用。bubblewrap 總是創(chuàng)建一個新的mount namespace, root掛載在tmpfs上,用戶可以明確指定文件系統(tǒng)的哪個部分在沙盒中是可見的。
● User namespaces (CLONE_NEWUSER):
用來隔離用戶權限相關的Linux資源,包括用戶ID 和組ID, 在不同的user namespace中,同樣一個用戶的user ID 和group ID可以不一樣,換句話說,一個用戶可以在父user namespace中是普通用戶,在子user namespace中是超級用戶(超級用戶只相對于子user namespace所擁有的資源,無法訪問其他user namespace中需要超級用戶才能訪問資源)。
● IPC namespaces (CLONE_NEWIPC):
沙箱會得到所有不同形式的IPCs的一份拷貝,比如SysV 共享內存和信號量等。
● PID namespaces (CLONE_NEWPID):
用來隔離進程的ID空間,沙箱內的程序看不見任何沙箱外的進程,此外, bubblewrap 會運行一個pid為1的程序在容器中,用來處理回收子進程的需求。
● Network namespaces (CLONE_NEWNET):
用來隔絕網絡,在它自己的network namespace中只有一個回環(huán)設備。
● UTS namespace (CLONE_NEWUTS):
允許沙箱擁有自己獨立的hostname和domain name.
Cgroups:
cgroup和namespace類似,也是將進程進行分組,但它的目的和namespace不一樣,namespace是為了隔離進程組之間的資源,而cgroup是為了對一組進程進行統(tǒng)一的資源監(jiān)控和限制。
Bind Mount:
將一個目錄(或文件)中的內容掛載到另一個目錄(或文件)上.
Seccomp rules:
Linux kernel 所支持的一種簡潔的sandboxing機制。它能使一個進程進入到一種“安全”運行模式,該模式下的進程只能調用4種系統(tǒng)調用(system calls),即read(), write(), exit()和sigreturn(),否則進程便會被終止。
同時,bubblewrap 使用PR_SET_NO_NEW_PRIVS 關閉 setuid 二進制程序。
當一個進程或其子進程設置了PR_SET_NO_NEW_PRIVS 屬性,則其不能訪問一些無法share的操作,如setuid, 和chroot。
實驗:
接下來,我們通過如下方式進入到一個flatpak創(chuàng)建的沙箱中:
安裝程序所需的“運行時”和Sdk:
$ flatpak remote-add --from gnome https://sdk.gnome.org/gnome.flatpakrepo
$ flatpak install gnome org.gnome.Platform//3.24 org.gnome.Sdk//3.24
安裝gedit:
$ flatpak remote-add --from gnome-apps https://sdk.gnome.org/gnome-apps.flatpakrepo
$ flatpak install gnome-apps org.gnome.gedit
創(chuàng)建一個‘devel sandbox’中的shell:
$ flatpak run --devel --command=bash org.gnome.gedit
可以看到此沙箱中有3個進程,且flatpak-bwrap pid為1。
$ ps
PID TTY TIME CMD
1 ? 00:00:00 flatpak-bwrap
2 ? 00:00:00 bash
5 ? 00:00:00 ps
查看當前進程所屬的namespace,括號里的數字標識不同的namespace:
$ ls -l /proc/&&/ns
total 0
15:48 cgroup -> cgroup:[4026531835]
15:48 ipc -> ipc:[4026531839]
15:48 mnt -> mnt:[4026532241]
15:48 net -> net:[4026532244]
15:48 pid -> pid:[4026532242]
15:48 user -> user:[4026532371]
15:48 uts -> uts:[4026531838]
然后在主機中打開另一個終端,查看主機中當前進程的namespace:
$ ls /proc/&&/ns
total 0
15:56 cgroup -> cgroup:[4026531835]
15:56 ipc -> ipc:[4026531839]
15:56 mnt -> mnt:[4026531840]
15:56 net -> net:[4026531957]
15:56 pid -> pid:[4026531836]
15:56 user -> user:[4026531837]
15:56 uts -> uts:[4026531838]
可以看到沙箱中的進程所屬的namespace與主機環(huán)境下進程的namespace相比,它們的mount ,net, pid, user namespace不同,這時我們在主機環(huán)境下把ping文件拷貝進主目錄(gedit聲明了對’/home’的訪問權限),然后在sandbox shell中執(zhí)行ping 192.168.0.1,會發(fā)現(xiàn)報錯:
$ ./ping 192.168.0.1
ping: socket: Operation not permitted
因為gedit沒有申請網絡權限,它和主機在不同的network namespaces中。
怎么樣,是不是很有趣,你還能在這個沙箱中做更多有趣的探索,行動起來,一起來flatpak吧!
-
優(yōu)麒麟電源管理淺析[2019-08-19]
-
湖南農業(yè)大學和西北農林科技大學成功舉辦優(yōu)麒麟18.04發(fā)布派對[2018-05-28]
-
優(yōu)麒麟17.10發(fā)布派對完美收官,新征程再出發(fā)[2017-11-17]
-
搜狗輸入法Linux版發(fā)布1.2版本,細胞詞庫全新上線![2015-02-04]
-
干貨分享 - Systemd 技術原理&實踐(下)[2021-10-28]
-
漲知識:如何在優(yōu)麒麟和銀河麒麟社區(qū)版上構建Linux跨平臺的snap/flatpak包?[2017-05-10]
-
UbuntuKylin參加2013年中國計算機大會并在開源軟件論壇作主題報告[2013-10-24]
-
優(yōu)麒麟19.04正式版發(fā)布,激流勇進,精益求精![2019-09-17]
-
優(yōu)麒麟社區(qū)助力2016中國開源年會(COSCon'16)[2016-10-09]