zondag 25 juli 2010

About dbus_connect_session_bus and dbus_session_domain. (and other interfaces that include the dbus_session_type attribute)

These interfaces currently use the session_bus_type attribute in Fedora.
The problem is that all restricted xwindows and the unconfined users have this attribute assigned to their dbus domain.

Take for example telepathy, which is a framework that is started by dbus session domains. If you use the dbus_session_domain() interface to start telepathy processes, then this means all restricted xwindows and the unconfined users automatically transition to the telepathy domains when they run telepathy programs from their dbus domains.

Same goes for the dbus_connect_session_bus() interface in terms of which process that acquire service to which dbus session domains.

In my branch i went ahead to try and fix this. Instead of using the session_bus_type attribute i use $1_dbusd_t type instead. This way i can define which dbus session can start a program that needs to be started by session dbus domains.

The problem is that the compiler does not like and permit this. You will run into duplicate declaration issues of the dbus session type ($1_dbusd_t).

There is a way out of this but it is an ugly work around: Call the interfaces described above in the same optional policy block as where the dbus_role_role is called from.

By the way: i do not see how dbus can be considered optional.

The end result is that domains started by dbus session domains can not be optional and should be compiled into the base module.

Which programs am i talking about? For starters Gnome. Stuff like Gnome configuration daemon, settings daemon, keyring daemon, VFS daemon etc. Then Telepathy, Empathy, Gnome DVB daemon, Vino and who knows what else.

Also: The dbus_session_bus_client is, in my view, too coarse. It also uses the session_bus_type attribute, allowing the caller to send DBUS messages to all dbus session domains and allowing the caller to stream socket connect to all dbus session domains.

This is what i am currently using for the two interfaces described above (i left other interfaces affected by dbus_session_type in the current state for now)

########################################
##
## Connect to the specified session BUS
## for service (acquire_svc).
##

##
##
## Prefix to be used.
##

##
##
##
## Domain allowed access.
##

##
#
interface(`dbus_connect_session_bus_to',`
gen_require(`
type $1_dbusd_t;
class dbus acquire_svc;
')

allow $2 $1_dbusd_t:dbus acquire_svc;
')

########################################
##
## Allow a application domain to be started
## by the session dbus.
##

##
##
## Domain allowed to transition.
##

##
##
##
## Type to be used as a domain.
##

##
##
##
## Type of the program to be used as an
## entry point to this domain.
##

##
#
interface(`dbus_session_domain',`
gen_require(`
type $1_dbusd_t;
')

domtrans_pattern($1_dbusd_t, $3, $2)

dbus_session_bus_client($2)
dbus_connect_session_bus($2)
')

Moral of this article: I would be nice if we came up with a proper solution for the issues i described.

My branch is "hacked" in a way that it works for a large part but it means that my branch diverged even further from upstream than it already did...

As always: Changes i have made can be reviewed in my Git repository.

zaterdag 17 juli 2010

My thoughts on the user domain.

- Unconfined_t users are unrestricted except: exec{mod,heap,stack,mem}. They stay in the unconfined domain wherever possible. Sometimes they transition to other unconfined domains. This is only done for the type transition functionality. (to make sure objects get created with the right types)

- Common users are restricted in the sense that they transition to restricted domains where possible. Besides that, common users should be limited in their functionality as little as possible. They should be able to do anything a normal Linux user can do except run setuid applications. Common users can be divided into the following:

user_u: plain common user. should "feel" unrestricted, but domain transitions wherever possible. Also can not run setuid applications.

staff_u: main difference with user_u is that staff users CAN run setuid applications.

sysadmin_u: should be able to do most everything a normal root can by domain transitioning wherever possible.

- Restricted users/restricted Xwindows users, domain transition where ever possible but can only do what they should be able to do. Thus by default the restricted user templates should have limited functionality. Ofcourse these user can not run setuid applications either. Examples of restricted users are.

guest_u: least privilege restricted login users with only access via ssh, no network access. no setuid.
xguest_u: least privilege restricted login users with only access via xdm. no network access. no setuid.

These restricted users are almost never tailor made for a specific need. (although xguest is currently modified to be allowed more then it should by default in my view)

Basically one would modify restricted users and restricted xwindows users to allow then exactly what they need plus/minus some policy that is tunable on the fly.

- Base users: Are even more limited than restricted users. They also cannot manage any user content. They are a base for task specific roles. privileged or unprivileged. Same as with restricted users these base users need to be tailored because by default all you can do is sudo to them (if you have access to setuid)
Examples of base user usage is: webadm, dbadm

What got me to blog about this? As staff user i was able to run traceroute in the staff_t domain. I was under the assumption that i should have domain transitioned and that user_ping boolean would have denied access.

Looking closer in the netutils policy i found conflicting rules. There were conditional transition interfaces available (using user_ping condifition) and there was main tunable policy where ping and traceroute are not able to use terminals if user_ping is set to false. This got me curious. Should this apply to common users? The answer in my view is: no.

Common users should always be able to run traceroute and ping but they should domain transition to the respective domains to do so.

That leaves us with the conditional interfaces. They can be used with restricted users. If you want to design a restricted user with permission to ping or traceroute on the fly, then you can use these booleans. They are not implemented into the restricted user templates by default because this is not core functionality. plus you may want to use this boolean for one class of restricted users but not for another class.

I ended up, removing the tunable_policy from the netutils type enforcement source policy file.

The conclusion i take away from this and other experiences is that there is some confusion about how the various user domains should behave. Over time , the user domain templates have become inconsistent (at least in Fedora.

Some other examples are that base users can run all applications and can run usr_t files.

dinsdag 13 juli 2010

Rethinking interaction with user content.

In the user space there is often a lot of policy to write that defines how users can interact with user content. We usually use the role templates for this. If an confined app create user home, tmp and tmpfs content. We have to allow the user running the app to manage and relabel this content as well.

In Fedora a start was made to simplify this a bit. Users that have access to the userdom_manage_home_role template are able to manage and relabel any content that is declared userdom_user_home_content. This way we do not have to explicitly define that a user can manage/ relabel some confined apps user home content. Less policy to write. Fedora has this idea only implemented for user_home_content and not for user_tmp or tmpfs_content.

The userdom_manage_user_home_role is an old template that dates back to the time when we used roles to separate access to content. Also Fedora combines policy to manage/ relabel and do a bunch of other stuff in this single template. This is not really tidy.

Ive been wanting the idea that Fedora implemented for user home content, for user_tmp and tmpfs content as well. It might save me from writing more policy then strictly required. Hopefully also for pulseaudio which requires processes to manage files on tmpfs. Each application that uses pulseaudio needs to be able to read and delete every other apps pulseaudio tmpfs file, and then send a null signal that the application that owned the tmpfs file it deleted or read. A LOT of policy, which i am hoping to simplify.

There are some things to consider as well. We have different classes of users. We have unconfined users, which obviously should be able to manage all user content. We also have confined common users. These users are restricted but should behave as normal Linux users as much as possible. Thus should also be able to manage and relabel all user content.

Then there are the restricted users. These users have least privileges required. There are two kinds of those. restricted users and restricted xwindows users. An example of an restricted user domain is guest_t, and an example of an restricted xwindows user is xguest_t.

restricted xwindows users need to be able to manage and relabel user content like pulseaudio tmp, tmpfs and user content. And content like Gnome content, Gconf, Window manager, home bin,cert,video, audio etc.

normal restricted users like guest only need to be able to manage generic user content.

Xguest_t also needs some special permission besides the basic restricted xwindows permissions, namely managing and relabelling mozilla_user_content and nsplugin_user_content. and since mozilla_t can transition to for example totem_t, these users should also be able to manage totem user content for example.

So i started by declaring three attributes: user_home_type, user_tmp_type and user_tmpfs_type. These attributes get assigned to all user content. So if an user app manages a file in home, then the type of that content is assigned the user_home_type attribute. If it manages a file on tmpfs it gets assigned the user_tmpfs_type attribute and if it manages a file in tmp the type of that content gets assigned the user_tmp_type attributes. This is done in the userdom_user (home,tmp,tmpfs) content templates which should be used if a type for that purpose is declared.

I have replaced the userdom_manage (home.tmp,tmpfs) role templates by templates that differentiate between generic user content and all user content. If have also separated the manage, relabel and file transition permissions.

The way i plan to use this is as follows: The userdom_login_user_template is shared by all login users (except unconfined users in fedora) So that means both common and restricted users. Therefore, if i add the userdom_manage_all_home_content template call there then that would mean that restricted users can manage all user content. Not what i want. Instead i will add permission to manage relabel and file transition to generic user content to this template. For common users i additionally plan to add permissions to manage and relabel all user content. Unconfined users also get access to manage and relabel all content in the unconfined user module obviously.

Next thing i plan to do is to extend the restricted_xwindows template to permit managing and relabelling of content that is required for GUI interfaces like gnome content etc.

Permissions specific to xguest like managing mozilla user content (xguest is permitted to un firefox in the mozilla_t domain) etcetera will be added to the xguest module.

With this i hope to achieve that i can simplify user content and at the same time keep privileges as tight as possible.

If you want to see what i have implemented of above thus farm have a look in my Git repository. Use Git log/show to find and review the related commits.

maandag 12 juli 2010

Targeted configured semi-strict with UBAC for Fedora/Redhat distros.

I am maintaining an SELinux policy that is based off of Fedoras' SELinux policy and it aims to merge changes refpolicy as much as possible. It use to have only rather minor differences compared to refpolicy and Fedora but lately it has been diverging pretty much. The source policy is available in my personal shared Git repository and depending on my time it is updated pretty often. I aim to merge any Fedora and refpolicy updates as much as possible as soon as possible. In theory it is latest Fedora policy with refpolicy changes and my own changes. In practice its Fedora plus/minus some bugs/features that i introduced.

The main property of my policy is that, besides the usual, it aims to confine the user space by default.
As opposed to Fedora, my policy has user based access control enabled. This feature aims to isolate selinux users. In practice it has some rough edges and gothas but it is worth it. So one of the issues is that one has to make sure that the selinux identity field in the security context tuple of user home directories is labeled properly. This is a problem when you add new users. So if a new user is added one should chcon -R -u newuser_u /home/newuser. The second issue is system administration. In my policy, root is mapped to sysadm_u selinux identity, but usually logins as root are not encouraged, and so one logs in as staff_u and then role transitions to either sysadm_r or unconfined_r. This means that you will be root in a sufficient domain but with a ubac constraints. Fortunately unconfined_t has access to the system_r role and can use runcon to run commands using the system_u selinux identity. This is required for many sysadm commands. Example: runcon -u system_u useradd joe.

My policy installs with root mapped to the selinux identity of root but the root selinux identity does not have default contexts for unconfined. Meaning root cannot login as unconfined_t. Root logs in, in the sysadm_t domain. That should be sufficient. On installation the unconfined module is disabled. It can optionally manually be enabled after installation. updating policy will not try to disable it again if you did. The unconfined_u selinux user mapping was removed by default. You can manually add it if required but my policy does not encourage unconfined logins. This is also why unconfined_login boolean is set to false by default.

Users that need to have access to privileged domains and dacs root should be mapped to staff_u. These users should use sudo to change to root and to role transition:

echo "joe ALL=(ALL) TYPE=unconfined_t ROLE=unconfined_r ALL" >> /etc/sudoers

My policy adds some confinement for some user apps. Most notably currently:
firefox, nsplugin, totem, telepathy, mutt, thunderbird, elinks, irssi, metacity, gnome dvb, seahorse-daemon, vino_server and others.

So it is targeted policy that is configured in a semi strict fashion. unconfined logins by default are prohibited but the unconfined role/domain can be used as an replacement for sysadm_r/sysadm_t to use with sudo. Also the policy has selinux user isolation, so the various selinux users cannot interfere with eachother.

To make an rpm of my policy is pretty straight forward on fedora.
You can clone my refpolicy repository:

git clone git://217.19.30.59/refpolicy.git

or update it after you cloned it:

cd refpolicy; git pull

(Mind you that my IP address is dynamic. It does not change often but it can change. Just "/whois" me on irc.freenode.org to get my current IP address and use that.

To determine my main policy version either look at the tags or see "Version ; .." in the spec file in "redhat/selinux-policy.spec"

Replace the version number with the version number in the following commands:

git archive --format=tar --prefix=refpolicy-3.8.6/ refpolicy | gzip > ~/rpmbuild/SOURCES/refpolicy-3.8.6.tar.gz

git diff refpolicy master > ~/rpmbuild/SOURCES/refpolicy-3.8.6.patch

Make sure the path exists (install rpmdevtools) run rpmdev-setuptree.

Next copy the redhat/selinux-policy.spec from the Git repository:

cp redhat/selinux-policy.spec ~/rpmbuild/SPECS/

And build the packages:

cd ~/rpmbuild/SOURCES/; rpmbuild -ba ../SPECS/selinux-policy.spec

If you're installing my policy for the first time. e.g. if your current installed policy is stock redhat/fedora policy, then it is encouraged to start clean.

This means you will lose any modifications that you may have made:

setenforce 0
yum erase selinux-policy selinux-policy-targeted
mv /etc/selinux /etc/selinux.backup
yum install selinux*.rpm (the build rpms)
touch /.autorelabel && reboot

on reboot login as root, you should be in sysadm_t domain and you should be able to add/ fix your login user mapping to staff_u. Once youre login user is mapped to staff_u be sure to fix your login users home and tmp directories context:
semanage login -a -s staff_u -r s0-s0:c0.c1023 joe
chcon -R -u staff_u /home/joe
chcon -R -u staff_u /tmp/joe
chcon -R -u staff_u /var/tmp/joe

That should be sufficient.

If pulseadio does not start, then remove ~/.esd_auth ~/.pulse /tmp/.esd* and relogin or restart pulse.
Also you may when you first log in get AVC denials for stuff like metacity trying to access ~/.config (staff_wm_t -> user_home_t), and maybe others as well, ignore it. This is because that directory and others at that point are not restored yet. restorecond -u runs in a gnome-session and should have restored your home directory contexts in the mean time.

Be prepared to stumble on bugs, issues etcetera. Feel free to contact me if you have questions or comments. Patches welcome.

I am using this policy myself on two desktop systems (fedora13/Gnome) and several headless servers.

Warning: Only consider trying this if you are familiar to, and not intimidated by SELinux.