Plash: tools for practical least privilege
The powerbox: a GUI for granting authority
A file powerbox is a kind of file chooser dialog box, and it works the same from the user's perspective. The difference is that as well as telling the application which file to access, it dynamically grants the application the right to access the file.
This helps provide security: It means that the application does not have to be given access to all of the user's files by default. This is an example of applying the principle of least privilege/authority: the aim is to give the program the authority it needs to do its job, but no more.
Suppose you run Gnumeric to view a spreadsheet you downloaded from the Internet. Gnumeric might not be a malicious program, but suppose it has a buffer overrun bug -- quite possible considering that it is written in C -- and the spreadsheet exploits that bug.
If Gnumeric runs with all your authority, the dodgy spreadsheet can read any of your files (such as "~/sensitive-file.txt", or your private keys from "~/.ssh") and send them back to its creator.
But if Gnumeric runs with minimum authority, the malicious spreadsheet can't do anything except write to the file it was opened from, and open a powerbox to request a file. The application cannot specify a default pathname for the powerbox to open, so for the spreadsheet to get access to a sensitive file, the user would have to specifically choose that file. The malicious spreadsheet would find it very hard to get access to ".ssh": why would the user choose ".ssh" if Gnumeric opened a powerbox out of the blue without a good reason?
In order for the powerbox file chooser to provide security, it cannot be implemented by the application and its libraries. It must be implemented as a separate, trusted component, and it must run in its own protection domain.
The idea is that the file chooser has a trusted path to the user, so only the user can enter a filename into it. This allows the system to distinguish between requests made by the user and requests made by the application.
Powerboxes have been implemented in a couple of other systems already:
Here is an example of running the simple text editor Leafpad so that it uses the powerbox:
pola-run --prog /usr/bin/leafpad \ --env LD_PRELOAD=powerbox-for-gtk.so \ -B -fl /etc \ --x11 --powerbox --pet-name "Leafpad"
The biggest limitation is that the X Window System provides no security. The security of a powerbox relies on the powerbox having a secure path to the user, so that the user can enter a filename into the powerbox but the application can't. However, under X, this isn't true: one X client can spoof keypresses by sending keypress events to another client.
So the present system only raises the bar to a successful attack, rather than ruling an attack out.
Currently, the powerbox is the only way you can dynamically add files to the namespace of an application that has been launched using pola-run. It would be useful to have a command line tool (similar to gnuclient, as used with Emacs) for granting an application access rights to further files.
There is currently no way to review what authority has been granted to applications using the powerbox, and no way to revoke this authority.
Nested use of pola-run with the --powerbox option is not very useful at present: the nested instance of pola-run will provide its own powerbox manager. At the moment, the powerbox_req_filename object is only able to attach a file into an existing file namespace and return a filename. It needs to be extended so that it can return a reference to a file or slot object. The nested instance of pola-run can then attach this reference into the namespace it created.
As it stands, using Gtk's file chooser, the powerbox does not provide a secure UI for handling Unix symlinks. The user is not shown symlink destinations at all, yet the powerbox manager will follow symlinks, even though the symlink destination could have been written to the filesystem by an untrusted application.
A possible solution is to change the file chooser to display symlink information, and perhaps require the user to double click on a symlink to follow it.
Backup files are not handled. Arguably, when the user chooses FILE, the powerbox should also grant access to FILE~ and #FILE# (the latter is used by Emacs' auto-save feature).
There is no persistence. An application's access rights are not saved across sessions.
The powerbox/Gtk integration reimplements Gtk's GtkFileChooserDialog interface so that it opens a file powerbox for choosing files or directories. This means that existing, unmodified Gtk applications can use the powerbox.
GtkFileChooserDialog is replaced using an LD_PRELOADed shared object (powerbox-for-gtk.so), which replaces the gtk_file_chooser_dialog_*() functions. This shared object will work across different versions of Gtk. (Perhaps in the future, it could be compiled into Gtk.)
The powerbox/Gtk integration does not change the older GtkFileSelection interface, which is deprecated and exposes too many internal details to change.
The replacement GtkFileChooserDialog class inherits from GtkDialog, and hence from GtkWindow etc. However, it must prevent GtkWindow from ever opening a window on the screen; this is done by the powerbox manager instead. GtkFileChooserDialog achieves this by overriding the GtkWidget "map" method with code that does not pass the call on to GtkWindow. Instead, the "map" method invokes the powerbox API.
Selecting multiple files in one go is not implemented yet.
The dialog's "extra widget" is not supported: it does not get displayed at all. This is a serious problem, as it means file type selection widgets (as used by, e.g., Gimp) are not displayed. To fix this requires doing inter-client widget embedding. A temporary fix would be to display the extra widget in a separate top-level window.
The preview widget is not supported. It does not get displayed.
Filters are not yet implemented. GtkFileChooserDialog does not pass file type filter parameters to the powerbox manager. This is not a serious problem; it is just a convenience.
GtkDialog offers the application an unconstrained choice over the action buttons that appear in the dialog box, while the powerbox always displays Open/Save and Cancel buttons. GtkFileChooserDialog must make a guess at which of GtkDialog's actions to map the powerbox's Open/Save action to. If GtkDialog has more than one action besides Cancel, only one will be usable.
Confirmation and warning dialog boxes:
Some applications implement file overwrite confirmation dialog boxes themselves. In this case, two confirmation boxes will appear sequentially, because the powerbox also asks for confirmation.
Usually, when choosing a file results in the application opening a confirmation or warning box, the file chooser stays open, and the user can then pick a different file. However, with powerbox/Gtk, the file chooser is closed when the user chooses a file.
The GtkFileChooserIface interface allows applications to interact with the file chooser widget while it is open -- for example, to find out which file is currently selected. This will not work with the powerbox/Gtk integration, because the powerbox API is a simple call-return interface, and it does not give the application any way to interact with the file chooser while it is open.
GtkFileChooserButton and GtkFileChooserWidget are not replaced.
My first attempt at a replacement GtkFileChooserDialog class did not inherit from the GtkDialog class, on the grounds that it did not need to open a GtkDialog window itself. It inherited from GtkObject and nothing else.
This caused some problems, because applications expect GtkFileChooserDialog to inherit from GtkDialog (and so, indirectly, from GtkWindow, GtkWidget, etc.) as documented. This did not cause applications to crash: the Gtk API functions just print a warning and return if passed objects that don't belong to the expected class.
The old version is still included, as gtk-powerbox-noninherit.c.
The powerbox.el Emacs Lisp module changes Emacs to use a powerbox. It replaces Emacs' read-file-name function, which usually prompts for a filename using the minibuffer. This function is used when you type C-x C-f, or when you choose "Open" from the "File" menu. The replacement read-file-name function opens a "File Open" powerbox instead.
To run XEmacs to use the powerbox, use:
pola-run --prog /usr/bin/xemacs -B -f /etc --cwd / \ --powerbox --pet-name "XEmacs" --x11 \ -a=-l -a=/usr/share/emacs/site-lisp/plash/powerbox.el
GNU Emacs 21 does not work under Plash. The CVS version (to be released as GNU Emacs 22) has reportedly been fixed.
The powerbox manager is compiled into the pola-run program launcher. When the --powerbox option is used, pola-run will pass the application being launched an object under the name powerbox_req_filename.
An application can invoke the object powerbox_req_filename to request a file from the user. In response, the powerbox manager will open a file chooser. If the user selects a filename, the powerbox manager attaches the file (or file slot) into the application's file namespace, and returns the filename to the application.
When the application invokes powerbox_req_filename, it can pass some arguments, such as:
There is a simpler helper program called powerbox-req which invokes the powerbox_req_filename capability. This is a command line program which is used by the Emacs integration.
The --pet-name argument provides a name for the powerbox manager to put in the title bar of the powerbox, so the user can tell which application the request comes from.
The powerbox manager uses Gtk's original GtkFileChooserDialog to provide a file chooser.