zondag 6 februari 2011

frequently asked questions: selinux booleans in detail.

Q: "btw, anyone know if each of the selinux booleans are documented in detail somewhere?"

A: two levels of detail here:

1. semanage boolean -l | grep httpd_enable_homedirs
A written description (usually not very detailed) for the "httpd_enable_homedirs" boolean.

2. sesearch --allow -SC -T | grep httpd_enable_homedirs
All the "allow" type statement rules and type transition rules related to the "httpd_enable_homedirs" boolean. Very detailed but hard to interpret.

common issues -- part 1

22:13 < _Tassadar> hi
22:14 < _Tassadar> http://fedoraproject.org/wiki/SELinux/samba <- i'm reading this document, on how to
configure selinux to allow samba to share a certain directory
22:14 < _Tassadar> now i'd like to share /data/files so i issued chcon -t samba_share_t /data/files
22:14 < _Tassadar> it worked, according to ls -Z
22:14 < _Tassadar> but access is still denied
22:15 < _Tassadar> should i recursively set that label to every file in the share as well?
22:16 < SwifT> _Tassadar: (without reading the file) check your AVC denials on what is actually denied, but I
would say "yes, you'll probably want to recursively set the type"
22:17 < _Tassadar> SwifT: what is the best way to check my AVC denials?
22:17 < _Tassadar> it's a server, i don't have any gui tools
22:20 < dgrift> _Tassadar: try Fedora manage confined services
22:20 < _Tassadar> hm no new entries appear in /var/log/audit/audit.log
22:20 < SwifT> _Tassadar: depends on your system log configuration; try tail -f /var/log/messages or
/var/log/audit.log
22:20 < _Tassadar> some stuff from cron appears every five mins, but nothing from smb
22:20 < dgrift> _Tassadar this is a common issue
22:20 < dgrift> its this:
22:21 < dgrift> youve created a new mountpoint called /data
22:21 < dgrift> selinux doesnt know that location
22:21 < dgrift> and so it labels it with a type: default_t
22:21 < dgrift> this is a type for locations unknown to selinux
22:21 < dgrift> and selinux silently denies access to type default_t
22:22 < dgrift> because it should not happen
22:22 < dgrift> all locations should be labelled properly
22:22 < _Tassadar> ah
22:22 < _Tassadar> i see
22:22 < dgrift> so how to fix it?:
22:22 < _Tassadar> with restorecon probably
22:22 < dgrift> well you should start by labelling /data
22:22 < dgrift> what type to label it, that depends on your requirements for /data
22:23 < _Tassadar> well it's all user data
22:23 < dgrift> var_t should probably do
22:23 < dgrift> i see
22:23 < _Tassadar> no binaries, no devices
22:23 < _Tassadar> lots of mp3's :)
22:23 < dgrift> whats in /data?
22:23 < dgrift> only dirs?
22:23 < _Tassadar> yes
22:23 < _Tassadar> /data/home/user1 /data/home/user2
22:24 < _Tassadar> /data/home/public_area
22:24 < _Tassadar> /data/public_area i mean
22:24 < dgrift> whats your distro?
22:24 < _Tassadar> Fedora 14
22:24 < dgrift> ok heres my suggestion
22:24 < dgrift> what is /data/home/user1 labelled?
22:24 < _Tassadar> nothing yet
22:25 < dgrift> but thats a user home dir?
22:25 < _Tassadar> drwx------. joe users unconfined_u:object_r:samba_share_t:s0 joe
22:25 < _Tassadar> well
22:25 < _Tassadar> i labelled it samba_share_t
22:25 < dgrift> ok
22:25 < _Tassadar> that's what the docs told me to do :)
22:26 < dgrift> what do you want?
22:26 < _Tassadar> well it doesn't work yet
22:26 < dgrift> what do you want with those dirs?
22:26 < _Tassadar> i would like the user to be able to mount his directory from a windows workstation
22:26 < dgrift> what is your requirement
22:26 < dgrift> i see
22:26 < _Tassadar> users are allowed read/write access to their own directories
22:26 < dgrift> and not use it locally?
22:26 < _Tassadar> and also in the public_area
22:26 < _Tassadar> no
22:26 < dgrift> ok
22:26 < _Tassadar> no shell access
22:27 < _Tassadar> no local processes are to be started from /data
22:27 < dgrift> so label /data root_t and the other dirs in there samba_share_t
22:27 < _Tassadar> recursively?
22:27 < dgrift> semanage -a -t root_t -f -d /data
22:28 < dgrift> semanage -a -t samba_share_t "/data/home(/.*)?"
22:28 < dgrift> restorecon -R -v /data
22:28 < dgrift> that will label the data dir root_t
22:28 < _Tassadar> nice
22:28 < _Tassadar> what does root_t mean?
22:28 < dgrift> and /data/home and all below it samba_share_t
22:29 < dgrift> it means it the type for filesystem roots
22:29 < dgrift> basically its accessable by all
22:29 < _Tassadar> oh okay, that makes sense in this case
22:29 < dgrift> see if it work
22:29 < _Tassadar> what would the -a option do?
22:29 < _Tassadar> my system doesn't know -a
22:29 < _Tassadar> oh
22:29 < _Tassadar> it does
22:29 < dgrift> oops
22:30 < _Tassadar> something else is wrong
22:30 < dgrift> non i made a booboo
22:30 < _Tassadar> okay
22:30 < dgrift> semanage fcontext -a -t root_t -f -d /data
22:30 < dgrift> semanage fcontext -a -t samba_share_t "/data/home(/.*)?"
22:30 < dgrift> restorecon -R -v /data
22:31 < _Tassadar> lol okay that could take a while
22:31 < _Tassadar> i'll run it without -v
22:31 < dgrift> hopefully it works for you
22:31 < dgrift> yes ok
22:31 < _Tassadar> it's a 11TB mount ;)
22:31 < dgrift> ouch....
22:31 < dgrift> all data on it?
22:31 < _Tassadar> yeah, no worries though, i'm not in a hurry
22:32 < _Tassadar> it's 60% used ;)
22:32 < dgrift> geez
22:32 < dgrift> i hope we get this right first time...
22:32 < dgrift> might want to test first
22:32 < dgrift> with a small dir
22:32 < _Tassadar> heh
22:32 < _Tassadar> i suppose so
22:32 < _Tassadar> ....
22:33 < dgrift> chcon -R -t samba_share_t /data/home/smalluserdir
22:33 < dgrift> chcon -t root_t /data
22:34 < _Tassadar> okay i'll try that
22:34 < dgrift> errr
22:34 < dgrift> its like this:
22:34 < dgrift> chcon -t root_t /data
22:34 < dgrift> chcon -t /data/home
22:34 < dgrift> err
22:34 < _Tassadar> ?
22:34 < _Tassadar> lol
22:34 < dgrift> chcon -t samba_share_t /data/home
22:34 < dgrift> chcon -R -t samba_share_t /data/home/smalluserdir
22:35 < dgrift> so three lines
22:35 < _Tassadar> yeah i understand, but restorecon is already running so /data and /data/home are already done
;)
22:35 < dgrift> because theres 3 dirs
22:35 < _Tassadar> i just tried with a small userdir and it works great !
22:35 < dgrift> ok
22:35 < _Tassadar> but, how do i keep everything neat
22:35 < _Tassadar> does restorecond do that?
22:35 < _Tassadar> i mean every time someone adds a file
22:36 < _Tassadar> it should get the right label immediately
22:36 < dgrift> it inherites the type of the parent dir
22:36 < dgrift> so should be fine
22:36 < _Tassadar> ah i see
22:36 < _Tassadar> so what does restorecond do then?
22:36 < dgrift> try it
22:36 < dgrift> well it watches directories for mislabelled files
22:36 < dgrift> but in your case its not applicable
22:37 < dgrift> because theres only one type
22:37 < _Tassadar> -rw-rw----. joe users unconfined_u:object_r:samba_share_t:s0 zzzzz.txt
22:37 < _Tassadar> yeah that works
22:37 < dgrift> samba_share_t
22:37 < _Tassadar> ah mislabelled, so not unlabelled
22:37 < _Tassadar> i understand
22:37 < _Tassadar> real 5m32.340s
22:37 < dgrift> well and unlabelled aswell
22:37 < _Tassadar> done :)
22:37 < dgrift> fast system
22:37 < _Tassadar> yeah :)
22:38 < dgrift> i should blog about this issue
22:38 < dgrift> its very common
22:38 < _Tassadar> definately
22:39 < dgrift> and people wonder why its not logging denials
22:39 < _Tassadar> yeah and the fact that audit.log doesn't show anything makes it hard to track for newbies like
me
22:39 < _Tassadar> exactly :)
22:39 < dgrift> can i use this chat log?
22:39 < dgrift> to publish?
22:39 < _Tassadar> errrr :)
22:39 < _Tassadar> i suppose

maandag 24 januari 2011

Yet another step by step introduction to policy development.

Due to several requests for guides to writing SELinux policy i have decided to create another screen cast detailing how to create a policy for a user application, and some of the things that may help one get familiar with policy writing.

As per usual by now, it is just a amateur production for amateurs. These recordings are pretty boring and long. I do advise that you view the whole thing in the proper order. Because things may not be explained well all the time, but most of it should become more clear in the course of the series.

Sometimes i make mistakes that i later notice. By the end of the series everything is pretty much sorted out (except atleast one pretty minor issue that i consider as an exercise to the watcher to troubleshoot and solve).

Also note that i encountered a conflict with restorecond -u (run in a gnome-session) with regard to labelling a file in the user home directory. I worked around that issue, but it will work fine when one logs out and back in, when it occurs.

part 1. Setting up an optimal environment for policy writing and in the mean time i explain my view on policy writing and every aspect of it.

http://www.youtube.com/watch?v=s4EyoW_7riQ

part 2. Do it yourself: create a simple script and write raw policy for it. Introduction to type transition, allow, dontaudit and other type statements. A start at translating raw policy that SELinux understands into policy that is maintainable and readable by humans and that is scalable in a modular environment.

http://www.youtube.com/watch?v=G5gUt1-ttGg

part 3. Proceed with translation of raw policy to m4 macro language powered policy. Merge our loadable policy module into upstream tresys reference policy.

http://www.youtube.com/watch?v=nbFnchVAgYs

part 4. troubleshoot remaining issues and fix them.

http://www.youtube.com/watch?v=rUGBgzTr92A

If you have specific question with regard to the series above feel free to ask for clarification.

donderdag 16 december 2010

Note to self: all the stuff a pulseaudio client needs.

basically i figured out about three scenarios so far:

1: The basics.
Pulseaudio is running normally, and the pulseaudio client needs to make some sound i guess

# manage a pulse-shm file in /dev/shm
manage_files_pattern($1, $2_tmpfs_t, $2_tmpfs_t)
fs_tmpfs_filetrans($1_t, $2_tmpfs_t, file)
fs_getattr_tmpfs($1_t)

# allow the user of the app to manage and relabel that file as well
allow $3 $2_tmpfs_t:file { relabel_file_perms manage_file_perms };

# 1. This add an attribute to the pulse client process so that i can allow each pulse client progress to signull any other pulse client process
# 2, This also adds an attribute to the pulse client tmpfs file so that i can allow each pulse client to read write and delete any others pulse client tmpfs file.
gnome_pulseaudio_client($1, $2)
# read write pulseaudio files in ~/pulse (a directory that is actually owned by gnome settings daemon)
gnome_rw_gsettingsd_pulseaudio_files($1)
# read gnome settings daemon home content for example some symlink in ~/.pulse to a pulseaudio sock file
gnome_read_gsettingsd_home_content($1)
# connect to pulseaudio with a unix stream socket
gnome_stream_connect_gsettingsd_pulseaudio($1, $2)
# search /tmp/pulse-*
gnome_search_gsettingsd_tmp_dirs($1)
# set attributes of ~/.pulse directory
gnome_setattr_gsettingsd_home_dirs($1)

# manage /.cache sound-event-cache files.
xdg_manage_generic_user_cache_files($1)

2: The not so basics.
These pulse client seem to be required to be able to (re) start the main pulseaudio process as well in some particular cases)

# domain transition to the gnome settingsd daemon pulseaudio domain when pulseaudio is executed.
gnome_spec_domtrans_gsettingsd_pulseaudio($1, $2)


3: When pulseaudio is not running.
When you kill pulseaudio and run a pulseaudio client app. It, i guess, expects some pulse audio network functionality because pulse is not running on the local system.

# the pulse client is trying to find pulseaudio on the network i guess...
allow $1 self:netlink_route_socket r_netlink_socket_perms;
allow $1 self:tcp_socket create_socket_perms;
allow $1 self:unix_dgram_socket sendto;

corenet_all_recvfrom_netlabel($1_t)
corenet_all_recvfrom_unlabeled($1_t)
corenet_tcp_bind_generic_node($1_t)
corenet_tcp_sendrecv_generic_if($1_t)
corenet_tcp_sendrecv_generic_node($1_t)
corenet_tcp_connect_pulseaudio_port($1_t)
corenet_tcp_sendrecv_pulseaudio_port($1_t)
corenet_sendrecv_pulseaudio_client_packets($1_t)

# if that isnt enough, the pulseaudio client wants to be a dbus system bus client. Dont ask me why but
its probably looking for pulseaudio run as a dbus system domain or init daemon.
dbus_system_bus_client($1)

..Heck it may even need more like maybe sysnet_read_config, i have not been able to confirm this yet.

The amount of access(policy) a simple gui application needs to be able to spit out a sound with pulseaudio is simply amazing.

maandag 29 november 2010

My Fedora 14 policy for the adventurous.

My Fedora 14 policy for the adventurous.

I have been working on a policy for Fedora 14. Three different policies actually. One for a minimal fedora installation (--nobase), one for a minimal fedora installation with libvirt and a policy for a minimal gnome desktop system.

The minimal policy for Fedora 14 gnome desktops is the interesting one. It aims to confine the gnome desktop on workstations. That means it supports almost none system services, excepts the base essentials. It does not have policy for any mail servers, it does have policy for ssh and even httpd. Http policy because gnome-user-share relies on it (dav)

What it lacks in system services it makes up for in application domains. That is to say it supports some gnome apps, and the user apps that do not have policy should be able to make to work by toggling the gnome_$1_targeted boolean where $1 is your user role prefix. Caution though that this hasnt been tested yet because my sole priority lies with a confined gnome, and this is enough work as is.

There are atleast some things to do if one decides to give it a spin.

One should add the following directories to /etc/skel:
.config
.config/enchant
.config/gtk-2.0
.cache
.local
.local/share
.gnome2
.gnome2/accels

One should also modify /usr/share/dracut/modules.d/98selinux/selinux-loadpolicy.sh

comment out:

mount --bind /dev "$NEWROOT/dev"
chroot "$NEWROOT" /sbin/restorecon -R /dev

..and then use dracut to build a new initramfs for your current kernel.

Also fix /root:

semanage fcontext -a -e /home/joe /root
restorecon -R -v /root

Typically you would:

setenforce 0
rpm -ev selinux-policy selinux-policy-targeted
rpm -Uvh selinux-policy-2.20100524-1.fc14.noarch.rpm selinux-policy-bare_gui-2.20100524-1.fc14.noarch.rpm
edit /etc/selinux/config and set selinux back to enforcing and point to bare_gui instead of targeted
relabel the file system
best to add a new user (make it staff_u as its user_u by default (sorry no unconfined_u in this policy by default)
make sure to add the user to sudo:
echo "joe ALL=(ALL) ROLE=sysadm_r TYPE=sysadm_t ALL" > /etc/sudoers.d/joe
chmod 0440 /etc/sudoers.d/joe
reboot

This policy confines all domains. also kernel_t and rpm_t. installation of packages and updting of packages should probably be done in permissive mode for now because the rpm domain needs some more loving. (common packages will work but dont try to install a kernel in enforcing mode or some service that gets restarted in the post-install script.

As said, this only works with gnome if it works at all (dont worry i am using it on my desktops) but only try this if youre a bit familar with selinux, are feeling adventurous and if you dont panic quickly.

By default the minimal gnome environment is confined. Gnome apps by default arent allowed to interact with users and often arent allowed to run generic applications. For example the printer applet currently is not confined (i dont like printing its a waste of paper and ink), thus gnome will not be able to run the printer applet until a policy for it is implemented.

The idea is that gnome can easily be allowed to interact with these generic apps and be allowed to communicate with users by toggling the gnome_$1_targeted boolean. However this is still untested.

Youll notice that youll have to unlock youre gnome keyring on each login. I am not sure why but gnome keyring daemon or whatever runs it (probably dbus, maybe xdm?) tries to manipulate selinux into running in the user domain which i forcefully prevent so that it can be made to run confined.

If something is confined then youll be able to run it in a confined environment with gnome_$1_targeted boolean set to off, Else you wont be able to run it untill some policy for it gets implemented.

The apps you are able to run may not be confined perfectly yet for all use cases (its a lot of work).

Stuff that works for me:

a lot of default gnome apps/applets/session services

totem
rhythmbox
evince
compiz
gedit
terminator
screen
mutt
irssi
firefox
thunderbird
eclipse
vinagre
empathy/telepathy
gpg
metacity
nautilus
gnome schedule
seahorse

Stuff that is not supported (atleast):

hal
mlocate

So one should be able to do some of the basics.

Why confining the desktop? Not so much to protect generic user content. I use to think this is important but as my policy evolved i discovered that the important thing here is the integrity of gnome and user apps.

For example: protect access to your keyring, gpg data, ssh data, firefox data etc.

Not protecting access to your generic ~/.porn directory

So how would you get started?

We you can get a tar ball of a recent snapshot here:

http://217.19.30.59/~dgrift/stuff/

Just put the tarball in your ~/rpmbuild/SOURCES directory. Extract the support/selinux-policy.spec from the tarball and put that into ~/rpmbuild/SPECS/
then just rpmbuild -ba ~/rpmbuild/SPECS/selinux-policy.spec
it will spit out 3 packages by default (bare_gui and its docs package) which you can install. You do not require the docs rpm but installing it doesnt hurt either.

If you want to try the bare or bare_virt model you can do so by editing the selinux-policy.spec and set the %define for that model to 1. it will build an rpm for that aswell.

Remember, expect plenty boogs i would love to receive some feedback or even help in improving the policy. It is a lot of work but the concept is very powerful. By confining the layer between the user and the system (the desktop) we achieve a lot more flexibility. We can then define what each user domain can and cannot do by simply implementing a boolean.

The idea about the bare and bare_virt models is that its strict, the unconfined module is install but not used. Another important property of bare and bare_virt is small footprint. It only installs the bare minimum modules which keeps the policy small. if one decides to run a service that is not currently supported in bare or bare_virt then one can use loadable module to implement it. The policy is focussed on advanced administrators that value small foot print and want total control over have gets installed and what not.

Questions comments? domg472 at gmail dot com

Some background information:

the policy is based off of recent refpolicy. refpolicy aims the be a base for basically any kind of model. Unfortunately i had to edit refpolicy atleast to remove unconfined_domains ( i think refpolicy probably shouldnt have unconfined domains as its easier to add and unconfined domain than to remove one) also i had to remove and/or redo most of refpolicies user application policies. I think it may be better for refpolicy to ignore user application policies or atleast prefix them all. domains like ssh_t arent helpful in a confined user space, as a confined user space relies heavily on user role prefixes.

Why not base it on fedora policy?

All of the above discussed issues apply, plus. Fedora tends to avoid issues by adding modules to base. This causes problems. My policy only has modules in the kernel layer in base all other modules can be disabled in theory. Fedora focusses on usability. little things like easily allowing access to all user content makes it hard to confine the user space.

zaterdag 7 augustus 2010

user home directory contexts

Some where in this commit: 0bf4290c235b514c39ed9c8d3f3f2fbb95f60cfa ( in one of the file context specifications there ) is something that makes and breaks whatever creates the per user home directory contexts.

Without it, semodule (what use to be genhomedircon?) only creates contexts for the "__default__" login.

It took me almost a day to narrow it down to this. I would like to know which file context specification exactly is causing it and why

donderdag 5 augustus 2010

The advantages and disadvantages of domain prefixes.

I am trying to merge restricted xwindows users and common users. The idea is to make them both use the same policy and be able to lock down what we know as user_t to a restricted user that we know as xguest by toggling booleans. That will make it easier to adept user environments to meet your requirement. You do not have to write custom policy. Simply enable/disable the functionality that you need with booleans and go.

To achieve this i use the good old per_role_templates. We used to use them for role based separation, But once user based separation was introduced there seemed to be not much use to these templates any more. However the domain prefixes used in the per role templates can play an important role in enabling and disabling functionality for different users using the same policy. We can use the domain prefix to define tunable policy.

user joe is allowed to access the network via his web browser. User jane can only access the network with her favourite game. Both use the same policy but have different booleans toggled.

But consider this: joe is allowed to use the browser. The browser can use stuff like java, flash, a video player, email client etc. Its not joe directly run those its the browser running it for joe. So how is it achieved that when it is allowed that joe can use the web browser, that joe can also watch a video clip via his web browser. Or that joe is not allowed to watch video via his browser but some other user is permitted that.

This, i believe can be achieved by called per_role_templates in per_role_templates.

I tried this before in more than one ways and always stumbled on duplicate declarations or out of scope issues. Today i tried a different approach. To avoid duplicate declarations i decided to try and split the per_role_templates into templates for policy and for declarations. The declaration per role templates should only be called by user domains. Whilst the policy per role templates can additionally be called by other policy per role templates. This way booleans, types and attributes are declared once but can be used more than once. For example user X can connect to a streaming port if he runs totem, but he can also connect to a streaming port if he runs totem via his browser. The same can be done for things like java, gpg, flash, web browsers, you name it

Another thing i have to deal with is xserver duplicated declarations, and so i also split those declarations for the policy and added the declaration interface to the per role declaration template for the various applications and the policy to the per role policy template.

This stuff becomes important if you truly want to confine the user space. Take for example nautilus. If you click on a video file in nautilus. How does the SELinux know who did it and thus who's policy to apply? All it knows is that nautilus ran the video file and nautilus is not a user its an application. There are may more such examples. Domain prefixes can help here.

There are also issues with calling per role templates from per role templates. Consider this. You can click on a web url in an E-mail message and you can also use the E-mail client from the web browser. So you called the E-mail per role template from the browser per role template, and you call the browser per role template from the E-mail per role template. This will get you into a loop that never ends. You can wait until you way less than a ounce and policy will still not finish compiling. So that is a issue to consider.

Just to show you what a per role declaration template for a GUI app would look like:


########################################
##
## Role access for mozilla declarations.
##

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

##
##
##
## Role allowed access
##

##
#
interface(`mozilla_declarations_role',`
gen_require(`
attribute mozilla_domain;
type mozilla_exec_t;
')

##
##


## Allow Mozilla to execute anonymous memory (execmem))
## files.
##


##

gen_tunable(mozilla_$1_execmem, false)

##
##


## Allow Mozilla to read all user home.
## files.
##


##

gen_tunable(mozilla_$1_read_content, false)

##
##


## Network access for mozilla.
## files.
##


##

gen_tunable(mozilla_$1_network_connect, false)

type $1_mozilla_t, mozilla_domain;
application_domain($1_mozilla_t, mozilla_exec_t)
ubac_constrained($1_mozilla_t)

role $2 types $1_mozilla_t;

xserver_object_types_template($1_mozilla)
')


I am aware that this is a pretty dirty hack, and i am not even sure if this indeed works out the way it appears, but i am just glad and hopeful that it does.