tag:blogger.com,1999:blog-50247034304822131632024-03-13T22:10:38.828-07:00SELinux Mandatory Access ControlDominick Grift blogs about topics related to Security-Enhanced Linux Mandatory Access Control.Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.comBlogger45125tag:blogger.com,1999:blog-5024703430482213163.post-14652491805163598402013-12-15T11:04:00.001-08:002013-12-15T11:04:03.856-08:00finding file context files that do not end with a newlinefile context files not ending with a newline cause annoying situations.<br />
<br />
<pre style="font-family:arial;font-size:12px;border:1px dashed #CCCCCC;width:99%;height:auto;overflow:auto;background:#f0f0f0;;background-image:URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif);padding:0px;color:#000000;text-align:left;line-height:20px;"><code style="color:#000000;word-wrap:normal;"> #!/bin/bash --
#
# This script looks for file context files
# that do not end with a newline
#
REF_PATH="/home/dominick/Git/refpolicy"
for i in $(/bin/find $(printf "%s" "$REF_PATH") -type f -name "*.fc") ; do
[[ "$(/bin/tail -c 1 $i | /bin/tr -dc '\n' | /bin/wc -c)" -ne 1 ]] && printf "%s\n" "Fix me: $i"
done
exit $?
#EOF
</code></pre>Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com0tag:blogger.com,1999:blog-5024703430482213163.post-42739499405429340332013-12-09T08:23:00.001-08:002013-12-09T08:39:18.569-08:00Another ideaWe have the sepolicy tool that has functionality that aims to make policy development easier. One great benefit is the single point of failure aspect it provides. By using the tool for policy development you reduce risk of typo's and syntax errors. If you have to type everything yourself manually then much can go wrong.<br />
<br />
The tool also has it's drawback because you are bound to the functionality the tool provides but nothing stops you from manually editing the generated policy, and so that is pretty much a non-issue.<br />
<br />
For some reason typo's and syntax errors are a pretty common thing for many policy developers, and so from that perspective it is probably a good idea to use the tool more often.<br />
<br />
Anyhow, The reference policy provides a api "mechanism", and api's make life easier. The issue is that these api's are not checked until they are actually called or until a tool like sepolgen-ifgen is run on them. So if one writes api's manually then those api's might not work due to some stupid typos, but the typos are often not identified until some one calls the api's.<br />
<br />
Back earlier we had this policy of not adding api's unless they are actually used. However the point was made that audit2allow cannot suggest an api to use if its not available and so we agreed that it is probably better to add various api's even if they are not used.<br />
<br />
So adding api's that aren't used, and that might be written manually thus contain typos and syntax errors. That means that api's that have typo's in them might not work and we don't know about it because we do not use them.<br />
<br />
He/She who fits the shoes wears them. I make typos in unused api's often. Just a few days ago i fixed two typos in admin interfaces that i made myself, and it annoys me. Because i am the type of person that likes to manually write his policy rather than depend on a tool (even though i know the tools purpose and i appreciate the issues it solves) I guess i am just stubborn sometimes.<br />
<br />
To keep a long story short: It might be a good idea to create an api test script. Again not an all-inclusive test but just to determine whether it can be called or not. The sepolgen-ifgen tool might be able to help identifying issues as well. <br />
<br />
Basically a script that just calls interfaces, templates, patterns etc to see if they build.<br />
<br />
Api's are our calling cards. It's how callers see us. If we provide broken interfaces then that leaves a bad impression. That is why i think they deserve more attention because they are not there just for us but also for others.<br />
Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com0tag:blogger.com,1999:blog-5024703430482213163.post-81473830638760696212013-12-09T05:03:00.002-08:002013-12-11T08:18:37.518-08:00quick script to check for unsupported device nodes by SELinux<pre style="font-family:arial;font-size:12px;border:1px dashed #CCCCCC;width:99%;height:auto;overflow:auto;background:#f0f0f0;;background-image:URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif);padding:0px;color:#000000;text-align:left;line-height:20px;"><code style="color:#000000;word-wrap:normal;"> #!/bin/bash --
#
# This script checks for device nodes that are unsupported by SELinux
# Unsupported device nodes fall back to the device_t generic type identifier for content in /dev
# The script just finds all chars and blocks, then looks if any of them as associated with the device_t type identifier
# If any device node is associated with device_t sid then the script uses matchpathcon to determine if SELinux is aware of the device node
# If matchpathcon thinks the device node should be associated with the device_t type then the device node is unsupported by SELinux one way or another
#
IFS=$'\n'
recurse_char() {
for i in "$1"/*;do
if [ -d "$i" ];then
recurse_char "$i"
elif [ -c "$i" -a ! -L "$i" ]; then
echo "$(ls -alZ "$i")"
fi
done
}
recurse_block() {
for i in "$1"/*;do
if [ -d "$i" ];then
recurse_block "$i"
elif [ -b "$i" -a ! -L "$i" ]; then
echo "$(ls -alZ "$i")"
fi
done
}
for s in $(recurse_char /dev); do
if [ "$(echo $s | /usr/bin/awk -F " " '{ print $4 }' | /usr/bin/awk -F ":" '{ print $3 }')" == "device_t" ] ; then
IFS=" "
read -r bits owner group context char <<< "$s"
mpc=$(/usr/sbin/matchpathcon "$char")
if [ "$(echo $mpc | /usr/bin/awk -F " " '{ print $2 }' | /usr/bin/awk -F ":" '{ print $3 }')" == "device_t" ] ; then
echo "unsupported char device: $char"
fi
fi
done
for s in $(recurse_block /dev); do
if [ "$(echo $s | /usr/bin/awk -F " " '{ print $4 }' | /usr/bin/awk -F ":" '{ print $3 }')" == "device_t" ] ; then
IFS=" "
read -r bits owner group context block <<< "$s"
mpc=$(/usr/sbin/matchpathcon "$block")
if [ "$(echo $mpc | /usr/bin/awk -F " " '{ print $2 }' | /usr/bin/awk -F ":" '{ print $3 }')" == "device_t" ] ; then
echo "unsupported block device: $block"
fi
fi
done
exit 0;
#EOF
</code></pre>Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com0tag:blogger.com,1999:blog-5024703430482213163.post-86499049202738816192013-12-05T03:28:00.001-08:002013-12-05T03:28:29.098-08:00How I think distribution maintainers can enhance quality assuranceHere is a list with things distribution maintainers can do to enhance quality assurance<br />
<br />
1. Do proof reading.<br />
<br />
This enhancement applies to some distributions more than others. Lets define those "active" distribution and "passive" distributions.<br />
<br />
An active distribution is one that is constantly changing. Whereas a passive distribution is mostly "stale", and changes less frequent.<br />
<br />
A property of active distributions is their activity. Fast development where Security policy must constantly be adapted to support these fast developments.<br />
<br />
Maintaining policy for such scenarios is just hard work often. Things must be "fixed" quick and often. This is a recipe for human error.<br />
<br />
Because often in the rush one tends to make assumptions, plain types and syntax errors, or other relatively simple mistakes.<br />
<br />
Proof reading commits, and a fresh pair of eyes can save time here. By just spending a little day each day reviewing new commits such errors can be identified and fixed quickly.<br />
<br />
Some of this proof reading requires humans for example identifying mistakes due to assumptions. Other proof reading can be automated, for example typos and syntax errors.<br />
<br />
These human mistakes are often relatively harmless but sometimes they are harmful. The point i am trying to make is that this can be easily prevented.<br />
<br />
For the record, i am not suggesting that this proof reading is for identifying complex issues. Because that is a but more complicated and probably takes a little more time<br />
<br />
No instead i am suggesting that this method can filter out obvious errors. I can tell you from experience that this pay's off. Besides how hard is it to spend a little time regularly running a couple scripts on new commits to spot typos, syntax errors, and to spend five minutes a day reviewing yesterdays commits.<br />
<br />
2. Test you policy for all common scenarios.<br />
<br />
Policy can be built with various options. Distributions often do not use all these options. Problems can arise when you do not test building the policy with all options. This might be irrelevant in the short term because i head distribution maintainers think, if it works for us then why bother?<br />
<br />
There are two reasons for that:<br />
<br />
A. Your priorities might not align with the priorities of upstream, and for your own sake it is better to work with upstream. The more you divert the harder it gets to maintain your project. Merging new upstream releases becomes harder and take more time. By just making sure things work for all scenarios you increase chances of your changes being applied upstream. If you policy only works with a subset of options than upstream has little choice than to refuse the patch. To waste your time, upstreams time. its inefficient.<br />
<br />
<br />
B. Besides. We know what SELinux is right. What defines SELinux. Its the flexibility and configurability. That's why i use SELinux as opposed to any of the other LSM-Based MAC systems. So as a distro maintainer i would actually advertise these properties. One obvious and easy way to do that is to make sure you project builds and installs in all common scenarios.<br />
<br />
Sure there are limits to what you can support. Lets just use the same limits are upstream since we depend on eachother.<br />
<br />
So, every once in a while. build your policy with different sets op options, to make sure that it builds. Also You might want to every onces in a while install it with various options that way you can identify bugs in the user space component.<br />
<br />
Because this is not only an issue with policy, its also an issue with user space. User space must support all common policy and all its options.<br />
<br />
3. Make sure that what you target at least works in common configurations.<br />
<br />
If you target a daemon then it might be good to write a simple test for some of the common configurations. I am not suggesting all-inclusive tests. Just some default test to make sure the most obvious functionality works. It obviously requires some investments, at least initially but it might just mean the difference between a good or a bad impression.<br />
<br />
4. Test your security goals.<br />
<br />
Good, the processes you target can function and you have a way to verify that. But what about security? thats what we do all this for. Simple changes to the policy can have huge effects. By defining your security goals, and crucial properties of your security identifiers, you make it possible to verify that they meet your requirements over time. Run simple tests. We have great tools for that.<br />
This can be automated perfectly<br />
<br />
5. Other processes and SELinux<br />
<br />
In essence SELinux is transparent to the user space. However user space components can be made aware of SELinux or can even be expected to manage parts of SELinux. For example setting security contexts on files. These programs are often written by parties that might not understand SELinux principles and concepts as well as some of us do. <br />
<br />
This can affect the SELinux experience as a whole so its in our interest that these processes make the right decisions. One common mistakes is processes hardcoding security identifiers. Generally harmless but it harms experience and it can easily be prevented by loading a bare (dummy) policy and then checking dmesg or whatever to see if some processes are trying to use identifiers that do not exist. There are more conceivable tests imaginable.<br />
<br />
These are just some ways distribution maintained can enhance quality assurance. Many of these point apply to both the security policy component as well as the user space component<br />
Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com0tag:blogger.com,1999:blog-5024703430482213163.post-25511410129549637172013-12-05T02:39:00.002-08:002013-12-05T02:46:43.566-08:00Can SELinux be made simpler?<b>Disclaimer: this is just my opinion</b><br />
<br />
This must be a trick question. There is no easy answer for this.<br />
<br />
First we should define SELinux to be able to put the question into a context<br />
<br />
SELinux has three components: The LSM-Based system in the kernel, the tools and libraries, and lastly security policy<br />
<br />
We also need to determine what defines SELinux in compared to other LSM-Based systems in the kernel<br />
<br />
The answer to the latter question is Flexibility and configurability. Thats what defines SELinux. It a main property of SELinux. There are other LSM-Based system with other properties for example SMAC (simple mandatory access control) That system is defined by simplicity (but needless to say it lacks flexibility/configurability, at least compared to SELinux)<br />
<br />
It is easy to translate flexibility to complexity but the end result does not always have to be relatively complex<br />
<br />
Another thing to consider are constraints, with that i mean that for example SELinux must be optional, additional. It must be an add-on to the existing Linux DAC framework<br />
<br />
This prerequisite brings some more "complexity", There 3 more of those prerequisites (one of them is not optional for SELinux to work). To enforce mandatory integrity processes must be able to change type (role base access control). <br />
<br />
The other two prerequisites are optional (must be able to compartmentalise, must be able to enforce confidentiality) (multi category security/multi level security)<br />
<br />
Back to the question. We now have most considerations briefly explained.<br />
<br />
I Believe The core of SELinux (the LSM-Based System) cannot be made simpler. It is already as simple as can be considering all the requirrments.<br />
Can the tools and libraries make the experience simpler? Maybe a bit, but the main concepts and principles will still apply there is little one can do about that.<br />
<br />
The last component is what most people experience: the security policy<br />
<br />
So Lets look at the state of that. The policy can be build with the minimal set of requirements (e.g. only enforce integrity optionally/additionally e.g. by complementing traditional DAC)<br />
<br />
So we already can exclude some complexity and we do. We have different policy models for different requirements. For example if you have confidentiality requirements, which adds complexity, then you need the mls policy model.<br />
<br />
Lets look at a operating system: Fedora currently is a single distro that can basically considered general purpose. You can use it as a workstation, server, or your use case can be even more specific.<br />
But a vendor does not know beforehand how you are going to use it, and so every scenario must be supported.<br />
<br />
Here is the dilemma: security is never general. If you want to implement mandatory integrity/confidentiality in a flexible/configurable way by complementing traditional DAC on a general purpose system then you have a complex challenge on your hand which requires complex policy.<br />
<br />
So compromises were made: Lets not enforce mandatory integrity on the whole system, but only a part of it. Its give and take. Fine now things are a bit simpler but its not cheap. Now user sessions by default are not contained. To me this is already a great compromise because it basically says, were leaving workstation scenarios out in the cold with regard to mandatory integrity in the user space<br />
<br />
fortunately some level of mandatory integrity in the user space is still optionally available, but its a compromise and it does not get the attention that i think it deserves<br />
<br />
So its all about compromises. We have some ability to make things "simpler" and we already apply it.<br />
<br />
So how to make things (a bit) simpler and actually achieve security goals?<br />
<br />
We could create "profiles". For example Fedora webs erver edition. is a profile for a web server. web servers have (relatively) specific properties. So that from a security perspective enables us to implement a relatively specific security policy for that profile. We just target the web server. This makes the policy "simpler"<br />
<br />
Fedora Desktop edition has a policy that targets the user space.<br />
<br />
Does this solve anything? Not really if you still end up focussing on specific cases. it might help a bit but its still a compromise. Unless of course you really commit to all the profules you defined.<br />
<br />
There are more (less obvious) options but its all give and take, and its all with regard to the security policy implemented. The core of SELinux cannot be simplified ( with any significance) without SELinux losing its identity.<br />
<br />
So what about setroubleshoot? That is a great success story when it comes to simplifying SELinux?! Not really. Its just a buffed audit2why with a lot of bloat. (no offence) Is still a program that cannot make security decisions for you. All it can do is parse. reference and make it easy to report issues. It does not know when to transition or not.<br />
<br />
That is not because its a bad piece of software. its just that security policy is not something that is fixed so you cant hard-code solutions. and to put things into context and determine the security requirements and act on it requires a huge base of logic. Is it even worth trying to create that?<br />
<br />
Think about it from a security perspective: do you easily trust a third party with security decisions that affect your lively hood? Do you trust some code to make security decisions for you?<br />
<br />
And even if you do, youll miss out on the good still: configurability/flexibility.<br />
<br />
Why not instead focus on learning the core principles/concepts, and enable people to implement mandatory integrity that is tailored to their specific requirement?<br />
<br />
So how do you do that? CIL is a abstraction language/ compiler that aims to make this easier. Its is relatively simple and it can be used as a layer between a policy management program and the SElinux policy language. It makes things less pain full but still wont change the core principles and concepts.<br />
<br />
What it does do is optimise. Optimization can, i guess, in some ways be translated to making things more pleasurable and there by perceivably simpler.<br />
<br />
You ask me the question can SELinux be made simpler. my answer is no. but things can be improved and optimized. compromises can also be made<br />
<br />
But it does not change anything to the core principles and concepts.<br />
<br />
If you want (relatively) simple: look into Simple mandatory access control. You want "flexibility/configurability" embrace selinux<br />
<br />
For example on the one hand we make things "simpler" by by default not targeting user sessions, But on the other hand we enable an optional security model that adds a layer of complexity to achieve compartmentalization.<br />
<br />
Its all a matter of priorities<br />
<br />
Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com1tag:blogger.com,1999:blog-5024703430482213163.post-16715536516250972562012-12-01T10:05:00.001-08:002012-12-01T10:17:35.684-08:00Anatomy of a SELinux policy module: DropboxI was asked to write a SELinux policy module for Dropbox. For obvious reasons i do not use this user application myself but i was willing to make an exception for the sake of writing a SELinux policy configuration for Dropbox.<br />
<br />
The module was designed for and developed on a Fedora 18 (Beta) system.<br />
<br />
Before i start designing and writing a policy configuration for some application i usually do my home work first. That means reading up on the application as much as i can so that i have an idea what to expect.<br />
<br />
In this case i already had a rough idea about the applications functionality. I was interested in seeing what is installed where and when.<br />
<br />
And so i downloaded and extracted two packages from this location:<br />
<br />
https://www.dropbox.com/install<br />
<br />
I focussed on this package:<br />
<br />
https://dl-web.dropbox.com/u/17/dropbox-lnx.x86_64-1.6.2.tar.gz<br />
<br />
and also had a quick look at this:<br />
<br />
https://www.dropbox.com/download?dl=packages/fedora/nautilus-dropbox-1.4.0-1.fedora.x86_64.rpm<br />
<br />
Basically i downloaded both packages and extracted it to see what was in them.<br />
<br />
The dropbox-lnx.x86_64-1.6.2.tar.gz package is expected to be downloaded to "~" and to be extracted there. It extracts a directory called ".dropbox-dist" with various files in it.<br />
<br />
The installation guide suggests that one runs the "dropboxd" file that is location in the extracted "~/.dropbox-dist" location.<br />
<br />
And so i decided to just try it out.<br />
<br />
As it turns out the dropboxd programs runs another file in that location called "dropbox". Another file in that directory called "library.zip" turned out to be a "hard link" to " dropbox". I was also able to identify plenty library files by their ".so" extensions.<br />
<br />
Anyways; A graphical window popped up and presented me with a series of questions. I followed the directions and when i was done the window exited and the process installed two more directories in my home directories called "~/.dropbox" and "~/Dropbox" respectively.<br />
<br />
The " ~/.dropbox" directory has various files that seem to be configuration files of some sorts and the "~/Dropbox" directory is the location that gets synchronized.<br />
<br />
Now i' ve had a rough idea of the locations and the nature of the files that were installed.<br />
<br />
The next step was to think about design.<br />
<br />
Were using the common security models available to us: Role based access control and Type enforcement. The aim is to improve integrity of our processes and files.<br />
<br />
We must also do our best to support as much of the applications functionality as we possibly can.<br />
<br />
We need to maintain a sub-tile balance between usability and security.<br />
<br />
Designing policy configuration for applications that sit on top of a Desktop environment is more complicated than a text application that you can for example run from a console because they usually interact with components on the Desktop environment and operate on files maintained by the these components.<br />
<br />
In a stock Fedora SELinux policy configuration most of the Desktop enviroment is not targeted. The result of this design decision is that components of the Desktop enviroment run with the same attributes and permissions as the user running them.<br />
<br />
For us that means that we either target each Desktop environment component and each file they maintain that Dropbox interacts with, or we allow our targeted Dropbox application to interact with the components operating, and operate on files they maintain, with the attributes and permissions of the user.<br />
<br />
I decided to go with the latter for simplicity.<br />
<br />
With that in mind i set out some humble security goals to achieve:<br />
<br />
1. Protect user application configuration, data and cache files as much as possible.<br />
2. Protect and contain the Dropbox application and process as much as possible.<br />
<br />
What follows now is my current SELinux policy configuration for Dropbox. The nautilus plugin (nautilus-dropbox-1.4.0-1.fedora.x86_64.rpm) is NOT supported. At least not currently.<br />
<br />
This because i refuse to install it because it depends on libgnome which in turn depends on Orbit and Bonobo and i will do just about anything to not have that installed.<br />
<br />
Here is the configuration. Below the configuration i will touch on its properties in detail:<br />
<br />
1. The ~/mydopbox/mydropbox.te Type enforcement source policy file:<br />
<br />
<blockquote class="tr_bq">
<pre>policy_module(mydropbox, 1.0.0)
attribute dropbox_domain;
type dropbox_exec_t;
type dropbox_home_t;
userdom_user_home_content(dropbox_home_t)
type dropbox_tmp_t;
userdom_user_tmp_content(dropbox_tmp_t)
type dropbox_tmpfs_t;
userdom_user_tmpfs_content(dropbox_tmpfs_t)
type dropbox_port_t;
corenet_port(dropbox_port_t)
allow dropbox_domain self:capability dac_override; # mount
allow dropbox_domain self:netlink_route_socket r_netlink_socket_perms;
allow dropbox_domain self:process { execmem signal };
allow dropbox_domain self:shm create_shm_perms;
allow dropbox_domain self:tcp_socket create_stream_socket_perms;
allow dropbox_domain self:udp_socket create_socket_perms;
allow dropbox_domain dropbox_home_t:dir manage_dir_perms;
allow dropbox_domain dropbox_home_t:file manage_file_perms;
allow dropbox_domain dropbox_home_t:sock_file manage_sock_file_perms;
userdom_user_home_dir_filetrans(dropbox_domain, dropbox_home_t, dir, ".dropbox")
allow dropbox_domain dropbox_tmp_t:file { manage_file_perms mmap_file_perms };
files_tmp_filetrans(dropbox_domain, dropbox_tmp_t, file)
can_exec(dropbox_domain, dropbox_exec_t)
kernel_getattr_core_if(dropbox_domain)
corecmd_exec_shell(dropbox_domain)
corenet_tcp_bind_generic_node(dropbox_domain)
corenet_tcp_sendrecv_generic_if(dropbox_domain)
corenet_tcp_sendrecv_generic_node(dropbox_domain)
corenet_udp_bind_generic_node(dropbox_domain)
corenet_udp_sendrecv_generic_if(dropbox_domain)
corenet_udp_sendrecv_generic_node(dropbox_domain)
corenet_sendrecv_http_client_packets(dropbox_domain)
corenet_tcp_connect_http_port(dropbox_domain)
corenet_tcp_sendrecv_http_port(dropbox_domain)
allow dropbox_domain dropbox_port_t:{ tcp_socket udp_socket } name_bind; # temporary workaround: 17500
dev_list_sysfs(dropbox_domain)
dev_read_sysfs(dropbox_domain)
dev_read_urand(dropbox_domain)
dev_dontaudit_getattr_all_blk_files(dropbox_domain) # panic
dev_dontaudit_getattr_all_chr_files(dropbox_domain) # panic
fs_getattr_tmpfs(dropbox_domain)
fs_getattr_xattr_fs(dropbox_domain)
fs_rw_inherited_tmpfs_files(dropbox_domain) # this is that xserver shm thing
auth_read_passwd(dropbox_domain)
init_getattr_initctl(dropbox_domain)
libs_exec_ldconfig(dropbox_domain)
mount_exec(dropbox_domain)
mount_manage_pid_files(dropbox_domain) # mount: read/write /run/mount/utab
sysnet_exec_ifconfig(dropbox_domain)
sysnet_read_config(dropbox_domain)
userdom_manage_user_home_content_dirs(dropbox_domain)
userdom_manage_user_home_content_files(dropbox_domain)
userdom_mmap_user_home_content_files(dropbox_domain) # libraries in ~/.dropbox-dist
userdom_user_home_dir_filetrans_user_home_content(dropbox_domain, dir) # cannot use named file transition due to random names
userdom_use_user_terminals(dropbox_domain)
optional_policy(`
dbus_session_bus_client(dropbox_domain) # probably not actually optional
dbus_connect_session_bus(dropbox_domain) # probably not actually optional
')
optional_policy(`
gnome_read_generic_data_home_dirs(dropbox_domain) # searching ~/.local/share
gnome_read_home_config(dropbox_domain) # ibus, might not be optional
# hack
gen_require(`
type config_home_t;
')
allow dropbox_domain config_home_t:dir setattr_dir_perms;
')</pre>
</blockquote>
2. The ~/mydopbox/mydropbox.if Interface source policy file:<br />
<br />
<br />
<span style="color: red;"><span style="font-size: large;">Blogspot does not format this content properly: View<span style="color: #313739;">/Get</span> it here instead:</span></span><br />
<span style="color: red;"><span style="font-size: large;"><br /></span></span>
<span style="color: red;"><span style="font-size: large;">http://pastebin.com/zcfSK2n3</span></span><br />
<br />
<br />
<pre>## <summary>Dropbox is a free service that lets you bring all your photos, docs, and videos anywhere.</summary>
#######################################
## <summary>
## The role template for the dropbox module.
## </summary>
## <desc>
##
## This template creates a derived domains which are used
## for dropbox applications.
##
## </desc>
## <param name="role_prefix" />
## <summary>
## The prefix of the user domain (e.g., user
## is the prefix for user_t).
## </summary>
##
## <param name="user_role" />
## <summary>
## The role associated with the user domain.
## </summary>
##
## <param name="user_domain" />
## <summary>
## The type of the user domain.
## </summary>
##
#
template(`dropbox_role_template',`
gen_require(`
attribute dropbox_domain;
type dropbox_exec_t, dropbox_home_t, dropbox_tmpfs_t;
')
########################################
#
# Declarations
#
type $1_dropbox_t, dropbox_domain;
userdom_user_application_domain($1_dropbox_t, dropbox_exec_t)
role $2 types $1_dropbox_t;
########################################
#
# Policy
#
domtrans_pattern($3, dropbox_exec_t, $1_dropbox_t)
ps_process_pattern($3, $1_dropbox_t)
allow $3 $1_dropbox_t:process { ptrace signal_perms };
allow $1_dropbox_t $3:process signull;
allow $1_dropbox_t $3:unix_stream_socket connectto;
allow $3 dropbox_exec_t:file { manage_file_perms relabel_file_perms };
userdom_user_home_content_filetrans($3, dropbox_exec_t, file, "dropbox")
userdom_user_home_content_filetrans($3, dropbox_exec_t, file, "dropboxd")
userdom_user_home_content_filetrans($3, dropbox_exec_t, file, "library.zip")
allow $3 dropbox_home_t:dir { manage_dir_perms relabel_dir_perms };
allow $3 dropbox_home_t:file { manage_file_perms relabel_file_perms };
allow $3 dropbox_home_t:sock_file { manage_sock_file_perms relabel_sock_file_perms };
userdom_user_home_dir_filetrans($3, dropbox_home_t, dir, ".dropbox")
kernel_read_system_state($1_dropbox_t)
corecmd_bin_domtrans($1_dropbox_t, $3)
corenet_all_recvfrom_unlabeled($1_dropbox_t)
corenet_all_recvfrom_netlabel($1_dropbox_t)
logging_send_syslog_msg($1_dropbox_t) # might want to make this conditional if possible
optional_policy(`
dropbox_dbus_chat($1, $3) # probably not actually optional
')
optional_policy(`
xserver_user_x_domain_template($1_dropbox, $1_dropbox_t, dropbox_tmpfs_t) # might not be optional
')
')
########################################
## <summary>
## Send and receive messages from
## dropbox over dbus.
## </summary>
## <param name="role_prefix" />
## <summary>
## The prefix of the user domain (e.g., user
## is the prefix for user_t).
## </summary>
##
## <param name="domain" />
## <summary>
## Domain allowed access.
## </summary>
##
#
interface(`dropbox_dbus_chat',`
gen_require(`
type $1_dropbox_t;
class dbus send_msg;
')
allow $2 $1_dropbox_t:dbus send_msg;
allow $1_dropbox_t $2:dbus send_msg;
')</pre>
<br />
<pre> </pre>
3. The ~/mydopbox/mydropbox.fc File contexts source policy file:<br />
<br />
<br />
<blockquote class="tr_bq">
<pre>HOME_DIR/\.dropbox(/.*)? gen_context(system_u:object_r:dropbox_home_t,s0)
HOME_DIR/\.dropbox-dist/dropbox(d)? -- gen_context(system_u:object_r:dropbox_exec_t,s0)
HOME_DIR/\.dropbox-dist/library\.zip -- gen_context(system_u:object_r:dropbox_exec_t,s0)
</pre>
</blockquote>
Declaring types, classifying them and making sure that SELinux knows what to label what<br />
<br />
Note that the policy above is the current result. Many of the properties of Dropbox where discovered after studying the contents of the package by trial and error.<br />
<br />
<blockquote class="tr_bq">
<pre>type dropbox_exec_t;
</pre>
</blockquote>
This is the declaration of the type of the dropbox executable files. Since "library.zip" is a hard link of "dropbox", we need to make sure that both are labeled identical. The file "dropboxd" is also a Dropbox user application executable file.<br />
<br />
<blockquote class="tr_bq">
<pre>HOME_DIR/\.dropbox-dist/dropbox(d)? -- gen_context(system_u:object_r:dropbox_exec_t,s0)
HOME_DIR/\.dropbox-dist/library\.zip -- gen_context(system_u:object_r:dropbox_exec_t,s0)</pre>
</blockquote>
Above is how we instruct SELinux about where these Dropbox application executable files are located and how they should be labeled.<br />
<br />
<br />
<blockquote class="tr_bq">
<pre>type dropbox_home_t;
userdom_user_home_content(dropbox_home_t)</pre>
</blockquote>
This is the declaration of the Dropbox user configuration content located in "~/.dropbox" as well as the interface call that classifies the type as " user home content".<br />
<br />
<blockquote class="tr_bq">
<pre>HOME_DIR/\.dropbox(/.*)? gen_context(system_u:object_r:dropbox_home_t,s0)</pre>
</blockquote>
Here we tell SELinux that the ~/.dropbox directory and everything in it should be labeled with type "dropbox_home_t" which is the Dropbox user home content type.<br />
<br />
<blockquote class="tr_bq">
<pre>type dropbox_tmp_t;
userdom_user_tmp_content(dropbox_tmp_t)</pre>
</blockquote>
Dropbox maintains a file in " $TMP". Here we declare a type "dropbox_tmp_t" for this file and we classify this file "user tmp content" by calling the "userdom_user_tmp_content() interface with the "dropbox_tmp_t" file type parameter.<br />
<br />
SELinux does not have to be aware of the location of the file in "$TMP" since for reason that i will not touch on in this article it should not maintain any contexts in "$TMP". Hence there is no entry for this in the "~/mydropbox/mydropbox.fc" file.<br />
<br />
<blockquote class="tr_bq">
<pre>type dropbox_tmpfs_t;
userdom_user_tmpfs_content(dropbox_tmpfs_t)</pre>
</blockquote>
Dropbox opens a GTK window when you first run it to guide you through the installation process. Dropbox also has i icon in the taskbar that opens a settings window if you select it. The result is that Dropbox interacts with X server and operates on content maintained by X server.<br />
<br />
For this we have to declare a type for Dropbox shared memory in "/dev/shm". We classify this type "user tmpfs content".<br />
<br />
There is no need to specificy a file context for this content as SELinux should not maintain file contexts in this locations for the same reasons as it should not maintain them in "$TMP".<br />
<br />
<br />
<blockquote class="tr_bq">
<pre>type dropbox_port_t;
corenet_port(dropbox_port_t)</pre>
</blockquote>
Dropbox listens on the UDP and TCP network for connections on port 17500. We Declare a type for this port object and classify the type "corenet_port". This will allow us to tell SELinux that Dropbox may only bind TCP and UDP sockets to ports that are classified "dropbox_port_t".<br />
<br />
Ports are not files and thus their contexts should not be specified in the file context file (~/mydropbox/mydropbox.fc).<br />
<br />
Instead we need to , after we installed the policy module package, manually label the 17500 UDP and TCP ports type "dropbox_port_t"<br />
<br />
This is done by issuing the following command:<br />
<br />
<blockquote class="tr_bq">
semanage port -a -t dropbox_port_t -p tcp 17500<br />
semanage port -a -t dropbox_port_t -p udp 17500 </blockquote>
You may have noticed that we have not yet classified our " dropbox_exec_t" user application executable file type.<br />
<br />
You may also have notices that we have not yet declared and classified a type for the Dropbox process.<br />
<br />
This is because of the properties of this application and it is also related to my design decision.<br />
<br />
Dropbox runs Nautilus and Firefox on your behalf to open your "~/Dropbox" location and to direct you to the "www.dropbox.com" website respectively.<br />
<br />
These two applications are currently not targeted in Fedora and i have decided to not do that either.<br />
<br />
How can we tell SELinux that if Dropbox runs Nautilus or Firefox that it does that on behalf of the user and that SELinux thus should run these two applications with the attributes and permissions of the user rather than the attributes and permission of Dropbox?<br />
<br />
This requires that we create a template because not all SELinux users are created equal. We need to use the "user role prefix" to declare a derived Dropbox process type. This will allow use to create rules that specify with which attributes and permissions Dropbox should run Nautilus and Firefox.<br />
<br />
This is done in a template called "dropbox_role_template" that i have created in the "~/mydropbox/mydropbox.if" interface file.<br />
<br />
<blockquote class="tr_bq">
<pre> type $1_dropbox_t, dropbox_domain;
userdom_user_application_domain($1_dropbox_t, dropbox_exec_t)
role $2 types $1_dropbox_t;</pre>
<pre> </pre>
</blockquote>
The above declares a derived dropbox process type "$1_dropbox_t" where "$1" is the "user role prefix". It then goes on to classify this process "dropbox_domain" This is done by assigning it a "type attribute" that we i declared in the "~/mydropbox/mydropbox.te" type enforcement file. You can find it on top, right below the policy module declaration.<br />
<br />
Next we classify both the Dropbox process type as well as the Dropbox user application executable file type "user application domain". This interface has all the permissions needed to classify our process type "user application process" and our application executable file "user application executable file".<br />
<br />
The last rule is a "Role based access control" rule that allows the "calling" role access to the prefixed Dropbox type.<br />
<br />
Policy.<br />
<br />
<blockquote class="tr_bq">
<pre>domtrans_pattern($3, dropbox_exec_t, $1_dropbox_t)</pre>
</blockquote>
<br />
This rule is a domain transition rule, or if you like "process type transition rule". It tells SELinux that the "calling" user process type should transition to the derived Dropbox process type when it runs the Dropbox user application executable file.<br />
<br />
<br />
<pre> ps_process_pattern($3, $1_dropbox_t)
allow $3 $1_dropbox_t:process { ptrace signal_perms };</pre>
<br />
The above rules allow the calling user process type to "ps" processes labeled with the derived Dropbox process type as well as ptrace it and send all signals to it.<br />
<pre>logging_send_syslog_msg($1_dropbox_t) </pre>
<br />
This will allow Dropbox to for example show up in "top", " ps x" and it allows you to "strace", kill etc. the Dropbox process.<br />
<br />
<blockquote class="tr_bq">
<pre> allow $1_dropbox_t $3:process signull;
allow $1_dropbox_t $3:unix_stream_socket connectto;</pre>
</blockquote>
<br />
Here are some interesting rules. The first allows the derived Dropbox process type to send null signals to the calling user process type and the second one allows the derived Dropbox process type to connect to the calling user process type with a unix domain stream socket.<br />
<br />
The processes here labeled with the "calling user process types" aren' t actually the calling user. These are for example Nautilus or Firefox. Since we decided not to target them they are labeled with the " calling user process type".<br />
<br />
In this case Dropbox probably wants to see if Nautilus is already running, and Dropbox probably wants to communicate with Nautilus using a unix domain stream socket.<br />
<br />
These rules are problematic because they are coarse. You can't tell by just looking at these rules who "$3" or if you will the process labeled with the "calling user process type" really is. Is it Nautilus or is it Firefox? Maybe it another process that currently is not targeted.<br />
<br />
Basically it allows Dropbox to send null signals and talk using a unix domain stream socket to any application currently not targeted labeled with the "calling user process type".<br />
<br />
<blockquote class="tr_bq">
<pre> allow $3 dropbox_exec_t:file { manage_file_perms relabel_file_perms };
userdom_user_home_content_filetrans($3, dropbox_exec_t, file, "dropbox")
userdom_user_home_content_filetrans($3, dropbox_exec_t, file, "dropboxd")
userdom_user_home_content_filetrans($3, dropbox_exec_t, file, "library.zip")</pre>
</blockquote>
<br />
These rules allow processes labeled with the " calling user process type" to "manage and relabel" files labeled with the dropbox use application executable type " dropbox_exec_t".<br />
<br />
Users need to be able to manage and relabel content in their home directory as they own it.<br />
<br />
The other three rules are interesting as well. They use a pretty new feature called "named file type transitions",<br />
<br />
These rules tell SELinux that if a process labeled with the " calling user process type" create files with named "dropbox, dropboxd and library.zip" in directories that are labeled with the user home content type "user_home_t" that the files should be created with the dropbox user application executable file type "dropbox_exec_t".<br />
<br />
This is a important rule because proper labelling of files is of vital importance to the integrity of SELinux policy enforcement.<br />
<br />
When you extract the "dropbox-lnx.x86_64-1.6.2.tar.gz" into you home directory, this rule ensure that the Dropbox executable files automatically get the right security context.<br />
<br />
The file context specification for these files that we added to " ~/mydropbox/mydropbox.fc" ensure that if restorecon gets run on any and all of these files that they will stay labeled properly.<br />
<br />
<br />
<blockquote class="tr_bq">
<pre> allow $3 dropbox_home_t:dir { manage_dir_perms relabel_dir_perms };
allow $3 dropbox_home_t:file { manage_file_perms relabel_file_perms };
allow $3 dropbox_home_t:sock_file { manage_sock_file_perms relabel_sock_file_perms };
userdom_user_home_dir_filetrans($3, dropbox_home_t, dir, ".dropbox") </pre>
</blockquote>
<br />
The same applies to the above except that this applies to Dropbox user home content and it applies to files, directories and sock files.<br />
<br />
The named file transtion rule dictates that SELinux should make sure that processes with the calling user process type create directories with the name ".dropbox" in directories with type "user_home_dir_t" (~) with type "dropbox_home_t".<br />
<br />
Note: I should probably allow allow processes with the calling process type to manage and relabel files with type dropbox_tmp_t as well dropbox_tmpfs_t. <br />
<br />
<br />
<blockquote class="tr_bq">
<pre> kernel_read_system_state($1_dropbox_t)</pre>
</blockquote>
<br />
This rule allows the derived Dropbox process type to read generic system state files in "/proc", like for example "/proc/meminfo".<br />
<br />
We added this rule (and some other rules that would normally go into the type enforcement file) here because it uses type attributes and were also using our "dropbox_domain" type attribute in our type enforcement file to write rules.<br />
<br />
One can only assign type attribute to types. You cannot assign a type attribute to a type attribute and thus we decided to deal with this in this manner.<br />
<br />
<blockquote class="tr_bq">
<pre>corecmd_bin_domtrans($1_dropbox_t, $3)</pre>
</blockquote>
<br />
This is the rule that caused me to implement the "dropbox_role_template" template.<br />
<br />
It is what enables us to tell SELinux that dropbox should run application that are not targeted with the "calling user process type".<br />
<br />
Basically it dictates that when the derived Dropbox process type runs a file with the generic "bin_t" "core command executable type" that the process type should transition from "$1_dropbox_t" (the derived Dropbox process type) to "$3" ( the calling user process type)<br />
<br />
<blockquote class="tr_bq">
<pre> corenet_all_recvfrom_unlabeled($1_dropbox_t)
corenet_all_recvfrom_netlabel($1_dropbox_t)</pre>
</blockquote>
<br />
These rules allow the derived Dropbox process type to recv from all unlabeled and netlabel network connections.<br />
<br />
It is basically a rule that effectivily disabled SELinux network controls enforcement.<br />
<br />
These rules are here because again they use type attributes and one cannot assign type attributes to type attributes. That means we cannot use our "dropbox_domain" attribute to call these in our ~/mydropbox/mydropbox.te" file.<br />
<br />
<br />
<blockquote class="tr_bq">
<pre>logging_send_syslog_msg($1_dropbox_t) </pre>
</blockquote>
<br />
This rule allows the prefixed Dropbox process type to send messages to syslog. Same as above it uses type attributes and so i had to add it here instead of in the type enforcement file.<br />
<br />
<blockquote class="tr_bq">
<br />
<pre> optional_policy(`
dropbox_dbus_chat($1, $3) # probably not actually optional
')</pre>
</blockquote>
This allows the derived dropbox process type to communicate using DBUS with processes that are labeled with the "calling user process type". Probably Nautilus or some Gnome Desktop environment compoment like GVFS.<br />
<br />
Since None of them are targeted we are forced to allow the prefixed dropbox process type to communicate using DBUS with any process as long as its labeled with the "calling user process type".<br />
<br />
We could have used raw policy to write these rules here but since DBUS is a "object manager" and also since its good to have a " dropbox_dbus_chat" interface we decide to create one (you can find it below the "dropbox_role_template" template in "~/mydropbox/mydropbox.if" and to call it in our own module.<br />
<br />
The "optional_policy" block indicates that this module does not actually depend on the rule in the block. I was assuming that Dropbox does not depend on the presence of DBUS but i may well be mistaken.<br />
<br />
<blockquote class="tr_bq">
<pre> optional_policy(`
xserver_user_x_domain_template($1_dropbox, $1_dropbox_t, dropbox_tmpfs_t) # might not be optional
')</pre>
</blockquote>
<br />
This rule allows the derived Dropbox process type to interact with X server and to operate on files maintained by X server. It also makes our "dropbox_tmpfs_t" "user tmpfs content" available for use with X server.<br />
<br />
I was under the impression that Dropbox does not depend on X server since on their website they claim that Dropbox works on "any Linux server" but again i may be mistaken.<br />
<br />
<blockquote class="tr_bq">
<pre>allow dropbox_domain self:capability dac_override; # mount
allow dropbox_domain self:netlink_route_socket r_netlink_socket_perms;
allow dropbox_domain self:process { execmem signal };
allow dropbox_domain self:shm create_shm_perms;
allow dropbox_domain self:tcp_socket create_stream_socket_perms;
allow dropbox_domain self:udp_socket create_socket_perms;</pre>
</blockquote>
<br />
These are what i call " self-rules". Basically rules where a source process labeled with a process type interacts with or operates on itself.<br />
<br />
The first rule allow any Dropbox process type the "dac_override" capability. This capability is needed to override discretionary access controls.<br />
<br />
Dropbox runs the mount command with the derived Dropbox process type (rather than with a process type transition) which is a setuid command.<br />
<br />
When the command is run your shell sessions current "pwd" is probably "~/.dropbox-dist" since thats where you run dropboxd from. The root Linux user does (or might not) have access to that location as " $HOME" might have the "0700" attibutes. The "dac_override" access vector permission allow the process type to access it anyway from a SELinux perspective.<br />
<br />
The second rule is probably to read the routing table. Dropbox is a network application and so i am not surprised that it needs these permissions.<br />
<br />
The third rule allows all Dropbox process types to "execute anonymous memory", Basically memory that is world writable. It is usually a sign of bad programming practices but there are also legitimate use cases such as "just in time compiling". This rule also allows Dropbox process types to send generic signals to itself.<br />
<br />
The fourth rule allows Dropbox processes to create shared memory. This is for X server interaction and is related to the " dropbox_tmpfs_t" "user_tmpfs_content" type.<br />
<br />
The fifth and the sixth rule allows dropbox and any other process labeled with any dropbox process type to create tcp stream sockets and udp sockets. This is needed because Dropbox is listening on the network for connections (port udp/tcp 17500 dropbox_port_t)<br />
<br />
<blockquote class="tr_bq">
<pre>allow dropbox_domain dropbox_home_t:dir manage_dir_perms;
allow dropbox_domain dropbox_home_t:file manage_file_perms;
allow dropbox_domain dropbox_home_t:sock_file manage_sock_file_perms;
userdom_user_home_dir_filetrans(dropbox_domain, dropbox_home_t, dir, ".dropbox")</pre>
</blockquote>
<br />
These rules allow all Dropbox process types to "manage" directories, files and sock files that are labeled with the "dropbox_home_t" " user home content type". This is configuration content amongst other things. Stuff that could use protecting to ensure optimal integrity.<br />
<br />
The fourth rule is another named file type transition rule. It dictates that if any dropbox process type creates a directory with name ".dropbox" in directories with type " user_home_dir_t" which is "~" that the directory be created with the "dropbox_home_t" type. Thus file transitioning from "user_home_dir_t" to "dropbox_home_t".<br />
<br />
<br />
<blockquote class="tr_bq">
<pre>allow dropbox_domain dropbox_tmp_t:file { manage_file_perms mmap_file_perms };
files_tmp_filetrans(dropbox_domain, dropbox_tmp_t, file)
</pre>
</blockquote>
<br />
Dropbox maintains a file in "$TMP" with a random name. It also "mmaps" that file. The second rule dictates that if any Dropbox process type creates a file in a directory with type " tmp_t" that the file is created with the " dropbox_tmp_t" " user_tmp_content" type. Since this file has a random name i have to use a regular file type transition and i cannot use a named file type transition.<br />
<br />
<blockquote class="tr_bq">
<pre>can_exec(dropbox_domain, dropbox_exec_t)</pre>
</blockquote>
<br />
The dropboxd process executes the dropbox "user application executable file" Both dropboxd as well as dropbox are labeled with the " dropbox_exec_t" type. This rule allows all Dropbox process types to execute files with the dropbox_exec_t type without a process type transition.<br />
<br />
<blockquote class="tr_bq">
<br />
<pre>kernel_getattr_core_if(dropbox_domain)</pre>
</blockquote>
<br />
I am not sure why but Dropbox wants to get attribute of the core if file in "/proc". Fine.<br />
<br />
<br />
<blockquote class="tr_bq">
<pre>corecmd_exec_shell(dropbox_domain)</pre>
</blockquote>
<br />
This rule allows all Dropbox process types to run a shell without a process type transition.<br />
<br />
<br />
<blockquote class="tr_bq">
<pre>corenet_tcp_bind_generic_node(dropbox_domain)
corenet_tcp_sendrecv_generic_if(dropbox_domain)
corenet_tcp_sendrecv_generic_node(dropbox_domain)
corenet_udp_bind_generic_node(dropbox_domain)
corenet_udp_sendrecv_generic_if(dropbox_domain)
corenet_udp_sendrecv_generic_node(dropbox_domain)
corenet_sendrecv_http_client_packets(dropbox_domain)
corenet_tcp_connect_http_port(dropbox_domain)
corenet_tcp_sendrecv_http_port(dropbox_domain)
allow dropbox_domain dropbox_port_t:{ tcp_socket udp_socket } name_bind; # temporary workaround: 17500</pre>
</blockquote>
<br />
Network related rules. The first block of rules are "generic" in the sense that it basically does not support the use of the SELinux network controls. Or it supports them in the most generic way.<br />
<br />
The second block allows all dropbox process types to connect to TCP ports that are labeled with the "httpd_port_t" port type. Dropbox connects to "tcp:443" (their Dropbox web application). It allow Dropbox to send and receive client packets that are labeled with the httpd packet type and it allows Dropbox to send and receive traffic from http classified ports.<br />
<br />
The last rule of the bunch allows all dropbox process types to bind TCP and UDP sockets to ports that are labeled with the "dropbox_port_t" port type. We labeled UDP/TCP 17500 with that type.<br />
<br />
<blockquote class="tr_bq">
<pre>dev_list_sysfs(dropbox_domain)
dev_read_sysfs(dropbox_domain)
dev_read_urand(dropbox_domain)</pre>
</blockquote>
<br />
Above allows all Dropbox process types to list directories with the generic "sysfs_t" type. This is generic content in "/sys". The second rule allow Dropbox to actually read files with this type.<br />
<br />
The third rule allows all Dropbox process types to read character device nodes with "urandom_device_t" device node type. E.g. /dev/urandom.<br />
<br />
<blockquote class="tr_bq">
<pre>dev_dontaudit_getattr_all_blk_files(dropbox_domain) # panic
dev_dontaudit_getattr_all_chr_files(dropbox_domain) # panic</pre>
</blockquote>
<br />
"Dontaudit" is a access vector that tells SELinux to silently block a specified interaction or operation.<br />
<br />
In the above case we silently deny any Dropbox process type to get attributes of all block and character files that are classified "device_node".<br />
<br />
To expose " hidden denials" one needs to issue the "semodule -DB" command which will build the policy database without any " dontaudit" rules. To reinsert the "dontaudit" rules simply issue 'semodule -B".<br />
<br />
<blockquote class="tr_bq">
<pre>fs_getattr_tmpfs(dropbox_domain)
fs_getattr_xattr_fs(dropbox_domain)
fs_rw_inherited_tmpfs_files(dropbox_domain) # this is that xserver shm thing </pre>
</blockquote>
<br />
This allow all Dropbox process types to get attributes of filesystems with the "tmpfs_t" filesystem type. This a common access vector for processes that maintain content in the " /dev/shm" location.<br />
<br />
The second rule allow any Dropbox process type to get attribute of any filesystem that supports extended attributes. E.g. types that are classified "filesystem type" as well as "Extended attribute file system". This is to allow Dropbox to stat "/" which is a common thing to do.<br />
<br />
The Third rule is related to X server interaction. I am not sure why it is the way it is but it has been this way for as long as i can remember. Inherited means that it doesnt actually opens the "generic tmpfs" file but it still reads and writes it. That means that either Dropbox got passed a open file or that there is a leaked file descriptor. Since, if i remember correctly , things will break if you do not allow this, i assume that X server or whatever passed the open file to Dropbox and dropbox reads and write it.<br />
<br />
Note that the file is not labeled with the "dropbox_tmpfs_t" "user tmpfs content" file type either. Instead it is labeled with a generic type for content in "/dev/shm".<br />
<br />
<br />
<blockquote class="tr_bq">
<pre>auth_read_passwd(dropbox_domain)</pre>
</blockquote>
<br />
Allow all Dropbox process types to read files with the passwd_file_t file type. E.g. "/etc/passwd" amongst others.<br />
<br />
This could simply be a side effect from Dropbox running a bash shell. The shell needs to read the password file in order to get the information needed for the shell prompt (user name etc.)<br />
<br />
<br />
<blockquote class="tr_bq">
<pre>init_getattr_initctl(dropbox_domain)</pre>
</blockquote>
<br />
Get attributes of initctl (named pipe i believe it was)<br />
<br />
<blockquote class="tr_bq">
<pre>libs_exec_ldconfig(dropbox_domain)</pre>
</blockquote>
<br />
Execute ldconfig program without a process type transition. It probably runs ldconfig on that file it maintains in "$TMP" that it also mmaps.<br />
<br />
<blockquote class="tr_bq">
<pre>mount_exec(dropbox_domain)
mount_manage_pid_files(dropbox_domain) # mount: read/write /run/mount/utab</pre>
</blockquote>
Execute the mount command without a process type transition. Not sure what it does with mount. <br />
<br />
Mount reads and write /run/mount/utab which is labeled with the mount pid file type.<br />
<br />
<blockquote class="tr_bq">
<pre>sysnet_exec_ifconfig(dropbox_domain)
sysnet_read_config(dropbox_domain)</pre>
</blockquote>
<br />
Executes ifconfig command without a process type transition and read files that are classified network configuration files (net_conf_t) This is probably "/etc/resolve.conf"<br />
<br />
<blockquote class="tr_bq">
<pre>userdom_manage_user_home_content_dirs(dropbox_domain)
userdom_manage_user_home_content_files(dropbox_domain)
userdom_mmap_user_home_content_files(dropbox_domain) # libraries in ~/.dropbox-dist
userdom_user_home_dir_filetrans_user_home_content(dropbox_domain, dir) # cannot use named file transition due to random names
userdom_use_user_terminals(dropbox_domain)</pre>
</blockquote>
<br />
These are interesting. These rules allow all dropbox process types to operate on content maintained by processes labeled with the user process type.<br />
<br />
In some cases this is bad news but in our case we will have to embrace it.<br />
<br />
Here is why<br />
<br />
The first two rules allow all Dropbox process types to manage directories and files that are labeled with the generic user home content type (user_home_t)<br />
<br />
I decided to keep "~/Dropbox" location generic. The idea of Dropbox is that users can "drag and drop" content in there to synchronise with the Dropbox. Usually that is program Photos (~/Pictures), documents (~/Documents), maybe tunes (~/Audio or ~/Music). These locations should be generic since they are not related to any single user application.<br />
<br />
"Drag and dropping" equals "moving" if done on a single partition. When you move a file you also move its context and so we want "~/Dropbox" to have the same type as the content that is expected to be dropped in there.<br />
<br />
If a user is stupid enough to drop his " ~/.gnupg" or "~/.ssh" directory into the "~/Dropbox" then the dropbox process type will not be able to access that content. E.g. it wont be able to synchronize your sensitive files.<br />
<br />
Unless ofcourse if you really want it to. In that case you would first manually relabel the content to the generic user home content type (user_home_t) with the "chcon" command and them drop it into your Dropbox.<br />
<br />
So leaving "~/Dropbox" type "user_home_t" and allowing Dropbox to manage files and directories with the "user_home_t" seems to me the sensible thing to do here.<br />
<br />
The third rule is a bit more controversial. The Dropbox archive copies library files into ~/.dropbox-dist. I decided to only give "dropboxd, dropbox and library.zip" in there a private type for simplicitly but the side effect is the now all dropbox process types need to mmap generic user home content files (the libraries).<br />
<br />
The fourth rule is a file type transition rule. The Dropbox installed creates "~/Dropbox" which we want to have type "user_home_t". But this location has a fixed name so we could have used a named file transition rather than a normal file transition. However during installation Dropbox also create a directory in "~" with a random name andso we could not use a named file type transition for that anyways, and so it was decided to use this rule<br />
<br />
Basically it dictates that if any Dropbox process type creates a directory in a directory with type "user_home_dir_t" (~) that the directory should be created with the "user_home_t" generic user home content type.<br />
<br />
The fifth rule allows any dropbox process type to "use" user terminals. This will allow Dropbox to print any messages to the terminal when you run "./dropboxd"<br />
<br />
<blockquote class="tr_bq">
<pre>optional_policy(`
dbus_session_bus_client(dropbox_domain) # probably not actually optional
dbus_connect_session_bus(dropbox_domain) # probably not actually optional
')</pre>
</blockquote>
<br />
This will allow anydropbox domain to become a DBUS session bus client and to aquire service on the session bus. Since i was under the assumption that DBUS is not a requirement for Dropbox i wrapped these rules in a "optional_policy" block that basically tells the policy compiler that these rules are optional. E.g. if they are not available for use then do not sweat it and proceed.<br />
<br />
<br />
<blockquote class="tr_bq">
<pre>optional_policy(`
gnome_read_generic_data_home_dirs(dropbox_domain) # searching ~/.local/share
gnome_read_home_config(dropbox_domain) # ibus, might not be optional
# hack
gen_require(`
type config_home_t;
')
allow dropbox_domain config_home_t:dir setattr_dir_perms;
')</pre>
</blockquote>
<br />
These rules are related to content in X desktop (XDG) standard locations. Basically all Dropbox process types need to be able to read IBUS files in "~/.config" These IBUS files are labeled with the generic "config_home_t" user home content type.<br />
<br />
Dropbox is probably using some Gnome library that does this on behalf of Dropbox. It also wants to set attributes of generic "config_home_t" directories and search generic "data_home_t" directories (~/.local/share).<br />
<br />
Okay... I think i touched on everything now, except...<br />
<br />
How to actually implement this policy<br />
<br />
Create a working directory and change directory into it:<br />
<br />
<blockquote>
mkdir ~/mydropbox; cd ~/mydropbox;</blockquote>
Create three "mydropbox" source policy files:<br />
<br />
<blockquote class="tr_bq">
touch mydropbox.{te,if,fc}</blockquote>
Copy the policy above in their respective files<br />
<br />
Next, create another file:<br />
<br />
touch myunconfineduser.te<br />
<br />
and paste the following in that file:<br />
<br />
<blockquote class="tr_bq">
<pre>policy_module(myunconfineduser, 1.0.0)
gen_require(`
type unconfined_t;
role unconfined_r;
')
dropbox_role_template(unconfined, unconfined_r, unconfined_t)</pre>
</blockquote>
<br />
This is what actually calls or if you will activates the "dropbox_role_template()" that i have created in the "~/mydropbox/mydropbox.if" interface file.<br />
<br />
Now build the two policy packages. You may or may not need to install the "selinux-policy-devel" package for this:<br />
<br />
<blockquote class="tr_bq">
Make -f /usr/share/selinux/devel/Makefile</blockquote>
<br />
Next install the policy packages that were created in "~/mydropbox":<br />
<br />
<blockquote class="tr_bq">
sudo semodule -i mydropbox.pp myunconfineduser.pp</blockquote>
<br />
If you have already installed Dropbox then make sure to restore the context of the "~/.dropbox" directories and the "dropboxd, dropbox and library.zip" files in "~/.dropbox-dist":<br />
<br />
<blockquote class="tr_bq">
restorecon -R -v -F ~ </blockquote>
If you have not yet installed Dropbox:<br />
<br />
<blockquote class="tr_bq">
<pre class="command-line">cd ~ && wget -O - "https://www.dropbox.com/download?plat=lnx.x86_64" | tar xzf -</pre>
</blockquote>
<blockquote class="tr_bq">
<pre class="command-line">~/.dropbox-dist/dropboxd</pre>
</blockquote>
<br />
<b>Disclaimer:</b><br />
<br />
<b>I do not encourage nor endorse the use of Dropbox. Security means taking responsibility. Do not trust your content to third parties. </b>Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com0tag:blogger.com,1999:blog-5024703430482213163.post-5996432987340950082012-10-08T05:10:00.000-07:002012-10-08T05:21:59.297-07:00Easy ways to help improve refpolicy contribHere is what you can do to help improve refpolicy contrib for your distro and everyone else:<br />
<br />
1. See if the file context specification from the various modules in refpolicy contrib match the locations of the corresponding packages that your distribution uses.<br />
<br />
Here is how i do that on Fedora:<br />
<br />
I basically check each modules file context files.<br />
<br />
Find which package installs the executable file, either with the full path or if my package manager cannot find that using a wild card:<br />
<blockquote class="tr_bq">
<br />
yum whatprovides /usr/sbin/someapp</blockquote>
or if it cannot find that:<br />
<blockquote class="tr_bq">
yum whatprovides *\someapp</blockquote>
<br />
Then you should figure out which (applicable) locations that package installs.<br />
<br />
Applicable locations are among others:<br />
<br />
<i>/etc/someapp /etc/sysconfig/someapp /etc/default/someapp /var/lib/someapp /var/log/someapp /var/spool/someapp /etc/init.d/someapp /etc/rc.d/init.d/someapp /var/run/someapp /var/cache</i><br />
<br />
In Fedora i use the handy repoquery tool for that. This tool allows me to list the files that a specificied package installs without me actually having to install the package<br />
<br />
Example:<br />
<br />
<blockquote class="tr_bq">
repoquery -ql someapp | less</blockquote>
<br />
Labeling files properly is very important for SELinux operation and so you can improve your distributions SELinux experience by making use applicable files and locations are labeled correctly by fixing or adding the appropriate file context specification.<br />
<br />
2. Somewhat related to (1): label service etc files with a declared private type for etc files and allow the service to read files it owns with the private type, then also allow the "service"_admin() to find and manage content with that type.<br />
<br />
In the past we only use to label service etc files with a private"files config file" private type if the file has sensitive information.<br />
<br />
Later we came up with an idea to confine root using "service"_admin interfaces that give the caller access to manage a particular service and its files.<br />
<br />
However we do not want to give the "service"_admin access to manage generic etc_t files since that will allow the process to manage things it shouldnt, instead of just the configuration files for the service that the caller is allowed to manage.<br />
<br />
So we need to find each config file a confined service owns label that with a declared "files_config_file" file type, allow the owning service to read applicable content with that type and allow the service admin to get to and manage content with that type.<br />
<br />
You can use the method of (1) to find which etc files a package installs where<br />
<br />
Then if needed declare a new files_config_file type<br />
<br />
<b>type someapp_conf_t;</b><br />
<b>files_config_file(someapp_conf_t)</b><br />
<br />
Then make sure the file or directory is labeled correctly in the file context file. Some examples:<br />
<br />
Single configuration file:<br />
<br />
<b>/etc/someapp\.conf -- gen_context(system_u:object_r:someapp_conf_t,s0)</b><br />
<br />
A configuration directory and all its contents:<br />
<br />
<b>/etc/someapp(/.*)? gen_context(system_u:object_r:someapp_conf_t,s0)</b><br />
<br />
Then allow the service domain type to read the content:<br />
<br />
in case of a single file:<br />
<br />
<b>allow someapp_t someapp_conf_t:file read_file_perms;</b><br />
<br />
in case of a directories and its contents:<br />
<br />
<b>read_files_pattern(someapp_t, someapp_conf_t, someapp_conf_t)</b><br />
<br />
If your service domain type is not already allowed to read generic etc_t files (e.g. if it does not have a rule similar to for example: files_read_etc_files(someapp_t) then you will also need to allow the service domain type to traverse etc_t directories so that it can actually get to there:<br />
<br />
<b>files_search_etc(someapp_t)</b><br />
<br />
If the module has a service admin interface, for example someapp_admin in the someapp.if interface file, then add the rules that will allow the caller to get to and manage content with the new type:<br />
<br />
a. Import the type by adding for example;<br />
<br />
<b>type someapp_conf_t; </b><br />
<br />
to the existing "<i>gen_require(`')</i>" block on top of the interface.<br />
<br />
b. Add the rules to allow caller to get to and manage the content with the new type , for example:<br />
<br />
<b>files_search_etc($1)</b><br />
<b>admin_pattern($1, someapp_conf_t)</b><br />
<br />
Note: also consider environment files in /etc/sysconfig. We would want the service administrator to be able to manage those as well.<br />
<br />
If you are unsure about some specifics then look into existing source policy modules. Much efford goes into writing these modules as consistently as possible.<br />
<br />
This allows you to see patterns easily and will help you read the policy.<br />
<br />Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com4tag:blogger.com,1999:blog-5024703430482213163.post-16369180919571030712012-09-30T11:01:00.000-07:002012-09-30T11:07:20.073-07:00Determine whether Cron can execute jobs on behalf of the user with login user SELinux permissionsCron would run jobs on behalf of users in a "cronjob" domain. This domain is reasonable restricted compared to the domain in which most users operate.<br />
<br />
Fedora changed this behaviour to allow Cron to execute these jobs in the default login user domain of the user that owns the job.<br />
<br />
Recently i added a boolean to Reference policy that enables one to tune the policy to allow Cron to run user cronjobs in the default login user domain conditionaly.<br />
<br />
By default Cron will still execute the jobs in the Cron job domain but if you toggle the <i>cron_userdomain_transition</i> boolean to <b>true</b> then Cron will run the jobs in the default login user domain of the user owning the job.<br />
<br />
This allows Cron to run jobs with the SE-Linux permissions that the owner of the job has.<br />
<br />
Cron is SELinux aware. It queries the policy to see to which domain it should transition when running a job.<br />
<br />
It does not do a automatic domain transition because it does not actually execute the Cron job. Instead if uses <i>"setexec"</i> to domain transition.<br />
<br />
It looks to see to which domains the Cron job file is a entrypoint. Then it needs to be able to process transition to that domain and then it checks the default login user domain of a user and with this information it determines in which domain to execute the job<br />
<br />
By default:<br />
<br />
<blockquote class="tr_bq">
allow cronjob_t user_cron_spool_t:file entrypoint;<br />
allow crond_t cronjob_t:process transition;</blockquote>
<br />
Then there is a default context of for staff this is for example:<br />
<br />
<blockquote class="tr_bq">
system_r:crond_t:s0 staff_r:cronjob_t:s0</blockquote>
<br />
But when you tune the policy with <i>cron_userdomain_transition </i>then these rules will be replaced by:<br />
<br />
<blockquote class="tr_bq">
allow $1 user_cron_spool_t:file entrypoint;<br />
allow crond_t $1:process transition;</blockquote>
<br />
Where <b>$1</b> is the calling login user domain, and then it will look up the default login user domain and role, for staff this is for example:<br />
<br />
<blockquote class="tr_bq">
# semanage user -l | grep staff_u<br />
staff_u user SystemLow SystemLow-SystemHigh staff_r sysadm_r system_r unconfined_r</blockquote>
That means:<br />
<br />
<b>"staff_r:staff_t"</b><br />
<br />
Then Cron daemon has permission to run the job in the staff domain with the staff role.<br />
<br />
The benefits of running jobs in the login user domain are that now your Cron job can interact with your processes and operate on your files as if it were you interacting with your processes and operating on your files.<br />
<br />
Needless to say that other SE-Linux rules that apply to you now also apply to your Cron jobs.<br />
<br />
The policy may still have some rough edges but it was tested on Gentoo and is said to work. I did make some changes after that but hopefully i have not introduced regression.<br />
<br />
Currently Redhat distributions do not have this <i>cron_userdomain_transition </i>boolean and i am not sure if she will adopt it.Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com2tag:blogger.com,1999:blog-5024703430482213163.post-40358314566246350002012-06-27T08:15:00.001-07:002012-06-27T08:15:16.904-07:00Hard coded types create hard dependencies on selinux policyLong time no see.
I believe that applications like sandbox (sandbox_web_t) and sshd (chroot_user_t) hard code types. I do not like that but my personal opinion aside; This creates hard dependencies on SELinux policy.
If you do not have a policy that provides these types then you will end up with broken functionality.
I believe one example is that sandbox does not work in Debian because Debian selinux-policy does not provide the types that sandbox requires.
That is all folks.Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com0tag:blogger.com,1999:blog-5024703430482213163.post-42383269970616382222011-08-23T11:10:00.000-07:002011-08-23T11:17:12.742-07:00Git daemon and SELinux with RHEL6RHEL6 does not ship with a manual page for configuring Git daemon SELinux policy, and so decided to publish a demonstration on youtube:
<br />
<br />Part 1. Git system daemon, shared repositories.
<br />
<br />http://www.youtube.com/watch?v=vgm89P5nbBQ
<br />
<br />Part 2. Git session daemon, personal repositories.
<br />
<br />http://www.youtube.com/watch?v=XHEPj80217o
<br />
<br />By the way you can look at the manual page (source) here:
<br />
<br />http://git.fedorahosted.org/git/?p=selinux-policy.git;a=blob;f=man/man8/git_selinux.8;h=e9c43b190c394f8ea7e68d9dd29f45c831340bf5;hb=ccadbe7d6ae709cdfd3b06d496477e069a2f13eeDominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com0tag:blogger.com,1999:blog-5024703430482213163.post-38729354205171669582011-02-08T14:22:00.001-08:002011-02-08T14:22:41.900-08:00selinux q&a23:15 < someone> What's the difference between httpd_sys_rw_content_t and <br /> httpd_sys_content_rw_t?<br />23:19 < dgrift> none<br />23:19 < dgrift> their aliased<br />23:19 < dgrift> theyreDominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com2tag:blogger.com,1999:blog-5024703430482213163.post-89912801329919206612011-02-06T14:44:00.000-08:002011-02-06T14:53:32.788-08:00frequently asked questions: selinux booleans in detail.Q: <span style="font-style:italic;">"btw, anyone know if each of the selinux booleans are documented in detail somewhere?"</span><br /><br />A: two levels of detail here:<br /><br /> 1. <span style="font-weight:bold;">semanage boolean -l | grep httpd_enable_homedirs</span><br /> A written description (usually not very detailed) for the "httpd_enable_homedirs" boolean.<br /><br /> 2. <span style="font-weight:bold;">sesearch --allow -SC -T | grep httpd_enable_homedirs</span><br /> All the "allow" type statement rules and type transition rules related to the "httpd_enable_homedirs" boolean. Very detailed but hard to interpret.Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com1tag:blogger.com,1999:blog-5024703430482213163.post-55460429212013101132011-02-06T13:41:00.000-08:002011-02-06T13:49:16.553-08:00common issues -- part 122:13 < _Tassadar> hi<br />22:14 < _Tassadar> http://fedoraproject.org/wiki/SELinux/samba <- i'm reading this document, on how to <br /> configure selinux to allow samba to share a certain directory<br />22:14 < _Tassadar> now i'd like to share /data/files so i issued chcon -t samba_share_t /data/files<br />22:14 < _Tassadar> it worked, according to ls -Z<br />22:14 < _Tassadar> but access is still denied<br />22:15 < _Tassadar> should i recursively set that label to every file in the share as well?<br />22:16 < SwifT> _Tassadar: (without reading the file) check your AVC denials on what is actually denied, but I <br /> would say "yes, you'll probably want to recursively set the type"<br />22:17 < _Tassadar> SwifT: what is the best way to check my AVC denials?<br />22:17 < _Tassadar> it's a server, i don't have any gui tools<br />22:20 < dgrift> _Tassadar: try Fedora manage confined services<br />22:20 < _Tassadar> hm no new entries appear in /var/log/audit/audit.log<br />22:20 < SwifT> _Tassadar: depends on your system log configuration; try tail -f /var/log/messages or <br /> /var/log/audit.log<br />22:20 < _Tassadar> some stuff from cron appears every five mins, but nothing from smb<br />22:20 < dgrift> _Tassadar this is a common issue<br />22:20 < dgrift> its this:<br />22:21 < dgrift> youve created a new mountpoint called /data<br />22:21 < dgrift> selinux doesnt know that location<br />22:21 < dgrift> and so it labels it with a type: default_t<br />22:21 < dgrift> this is a type for locations unknown to selinux<br />22:21 < dgrift> and selinux silently denies access to type default_t<br />22:22 < dgrift> because it should not happen<br />22:22 < dgrift> all locations should be labelled properly<br />22:22 < _Tassadar> ah<br />22:22 < _Tassadar> i see<br />22:22 < dgrift> so how to fix it?:<br />22:22 < _Tassadar> with restorecon probably<br />22:22 < dgrift> well you should start by labelling /data<br />22:22 < dgrift> what type to label it, that depends on your requirements for /data<br />22:23 < _Tassadar> well it's all user data<br />22:23 < dgrift> var_t should probably do<br />22:23 < dgrift> i see<br />22:23 < _Tassadar> no binaries, no devices<br />22:23 < _Tassadar> lots of mp3's :)<br />22:23 < dgrift> whats in /data?<br />22:23 < dgrift> only dirs?<br />22:23 < _Tassadar> yes<br />22:23 < _Tassadar> /data/home/user1 /data/home/user2<br />22:24 < _Tassadar> /data/home/public_area<br />22:24 < _Tassadar> /data/public_area i mean<br />22:24 < dgrift> whats your distro?<br />22:24 < _Tassadar> Fedora 14<br />22:24 < dgrift> ok heres my suggestion<br />22:24 < dgrift> what is /data/home/user1 labelled?<br />22:24 < _Tassadar> nothing yet<br />22:25 < dgrift> but thats a user home dir?<br />22:25 < _Tassadar> drwx------. joe users unconfined_u:object_r:samba_share_t:s0 joe<br />22:25 < _Tassadar> well<br />22:25 < _Tassadar> i labelled it samba_share_t<br />22:25 < dgrift> ok<br />22:25 < _Tassadar> that's what the docs told me to do :)<br />22:26 < dgrift> what do you want?<br />22:26 < _Tassadar> well it doesn't work yet<br />22:26 < dgrift> what do you want with those dirs?<br />22:26 < _Tassadar> i would like the user to be able to mount his directory from a windows workstation<br />22:26 < dgrift> what is your requirement<br />22:26 < dgrift> i see<br />22:26 < _Tassadar> users are allowed read/write access to their own directories<br />22:26 < dgrift> and not use it locally?<br />22:26 < _Tassadar> and also in the public_area<br />22:26 < _Tassadar> no<br />22:26 < dgrift> ok<br />22:26 < _Tassadar> no shell access<br />22:27 < _Tassadar> no local processes are to be started from /data<br />22:27 < dgrift> so label /data root_t and the other dirs in there samba_share_t<br />22:27 < _Tassadar> recursively?<br />22:27 < dgrift> semanage -a -t root_t -f -d /data<br />22:28 < dgrift> semanage -a -t samba_share_t "/data/home(/.*)?"<br />22:28 < dgrift> restorecon -R -v /data<br />22:28 < dgrift> that will label the data dir root_t<br />22:28 < _Tassadar> nice<br />22:28 < _Tassadar> what does root_t mean?<br />22:28 < dgrift> and /data/home and all below it samba_share_t<br />22:29 < dgrift> it means it the type for filesystem roots<br />22:29 < dgrift> basically its accessable by all<br />22:29 < _Tassadar> oh okay, that makes sense in this case<br />22:29 < dgrift> see if it work<br />22:29 < _Tassadar> what would the -a option do?<br />22:29 < _Tassadar> my system doesn't know -a<br />22:29 < _Tassadar> oh<br />22:29 < _Tassadar> it does<br />22:29 < dgrift> oops<br />22:30 < _Tassadar> something else is wrong<br />22:30 < dgrift> non i made a booboo<br />22:30 < _Tassadar> okay<br />22:30 < dgrift> semanage fcontext -a -t root_t -f -d /data<br />22:30 < dgrift> semanage fcontext -a -t samba_share_t "/data/home(/.*)?"<br />22:30 < dgrift> restorecon -R -v /data<br />22:31 < _Tassadar> lol okay that could take a while<br />22:31 < _Tassadar> i'll run it without -v<br />22:31 < dgrift> hopefully it works for you<br />22:31 < dgrift> yes ok<br />22:31 < _Tassadar> it's a 11TB mount ;)<br />22:31 < dgrift> ouch....<br />22:31 < dgrift> all data on it?<br />22:31 < _Tassadar> yeah, no worries though, i'm not in a hurry<br />22:32 < _Tassadar> it's 60% used ;)<br />22:32 < dgrift> geez<br />22:32 < dgrift> i hope we get this right first time...<br />22:32 < dgrift> might want to test first<br />22:32 < dgrift> with a small dir<br />22:32 < _Tassadar> heh<br />22:32 < _Tassadar> i suppose so<br />22:32 < _Tassadar> ....<br />22:33 < dgrift> chcon -R -t samba_share_t /data/home/smalluserdir<br />22:33 < dgrift> chcon -t root_t /data<br />22:34 < _Tassadar> okay i'll try that<br />22:34 < dgrift> errr<br />22:34 < dgrift> its like this:<br />22:34 < dgrift> chcon -t root_t /data<br />22:34 < dgrift> chcon -t /data/home<br />22:34 < dgrift> err<br />22:34 < _Tassadar> ?<br />22:34 < _Tassadar> lol<br />22:34 < dgrift> chcon -t samba_share_t /data/home<br />22:34 < dgrift> chcon -R -t samba_share_t /data/home/smalluserdir<br />22:35 < dgrift> so three lines<br />22:35 < _Tassadar> yeah i understand, but restorecon is already running so /data and /data/home are already done <br /> ;)<br />22:35 < dgrift> because theres 3 dirs<br />22:35 < _Tassadar> i just tried with a small userdir and it works great !<br />22:35 < dgrift> ok<br />22:35 < _Tassadar> but, how do i keep everything neat<br />22:35 < _Tassadar> does restorecond do that?<br />22:35 < _Tassadar> i mean every time someone adds a file<br />22:36 < _Tassadar> it should get the right label immediately<br />22:36 < dgrift> it inherites the type of the parent dir<br />22:36 < dgrift> so should be fine<br />22:36 < _Tassadar> ah i see<br />22:36 < _Tassadar> so what does restorecond do then?<br />22:36 < dgrift> try it<br />22:36 < dgrift> well it watches directories for mislabelled files<br />22:36 < dgrift> but in your case its not applicable<br />22:37 < dgrift> because theres only one type<br />22:37 < _Tassadar> -rw-rw----. joe users unconfined_u:object_r:samba_share_t:s0 zzzzz.txt<br />22:37 < _Tassadar> yeah that works<br />22:37 < dgrift> samba_share_t<br />22:37 < _Tassadar> ah mislabelled, so not unlabelled<br />22:37 < _Tassadar> i understand<br />22:37 < _Tassadar> real 5m32.340s<br />22:37 < dgrift> well and unlabelled aswell<br />22:37 < _Tassadar> done :)<br />22:37 < dgrift> fast system<br />22:37 < _Tassadar> yeah :)<br />22:38 < dgrift> i should blog about this issue<br />22:38 < dgrift> its very common<br />22:38 < _Tassadar> definately<br />22:39 < dgrift> and people wonder why its not logging denials<br />22:39 < _Tassadar> yeah and the fact that audit.log doesn't show anything makes it hard to track for newbies like <br /> me<br />22:39 < _Tassadar> exactly :)<br />22:39 < dgrift> can i use this chat log?<br />22:39 < dgrift> to publish?<br />22:39 < _Tassadar> errrr :)<br />22:39 < _Tassadar> i supposeDominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com0tag:blogger.com,1999:blog-5024703430482213163.post-38222096847658122822011-01-24T06:35:00.000-08:002011-01-24T06:52:17.094-08:00Yet 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.<br /><br />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.<br /><br />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).<br /><br />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.<br /><br />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.<br /><br />http://www.youtube.com/watch?v=s4EyoW_7riQ<br /><br />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.<br /><br />http://www.youtube.com/watch?v=G5gUt1-ttGg<br /><br />part 3. Proceed with translation of raw policy to m4 macro language powered policy. Merge our loadable policy module into upstream tresys reference policy.<br /><br />http://www.youtube.com/watch?v=nbFnchVAgYs<br /><br />part 4. troubleshoot remaining issues and fix them.<br /><br />http://www.youtube.com/watch?v=rUGBgzTr92A<br /><br />If you have specific question with regard to the series above feel free to ask for clarification.Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com0tag:blogger.com,1999:blog-5024703430482213163.post-85430663068138620892010-12-16T03:08:00.000-08:002010-12-16T03:32:32.340-08:00Note to self: all the stuff a pulseaudio client needs.basically i figured out about three scenarios so far:<br /><br />1: The basics.<br />Pulseaudio is running normally, and the pulseaudio client needs to make some sound i guess<br /><br /># manage a pulse-shm file in /dev/shm<br />manage_files_pattern($1, $2_tmpfs_t, $2_tmpfs_t)<br />fs_tmpfs_filetrans($1_t, $2_tmpfs_t, file)<br />fs_getattr_tmpfs($1_t)<br /><br /># allow the user of the app to manage and relabel that file as well<br />allow $3 $2_tmpfs_t:file { relabel_file_perms manage_file_perms };<br /><br /># 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<br /># 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.<br />gnome_pulseaudio_client($1, $2)<br /># read write pulseaudio files in ~/pulse (a directory that is actually owned by gnome settings daemon)<br />gnome_rw_gsettingsd_pulseaudio_files($1)<br /># read gnome settings daemon home content for example some symlink in ~/.pulse to a pulseaudio sock file<br />gnome_read_gsettingsd_home_content($1)<br /># connect to pulseaudio with a unix stream socket<br />gnome_stream_connect_gsettingsd_pulseaudio($1, $2)<br /># search /tmp/pulse-*<br />gnome_search_gsettingsd_tmp_dirs($1)<br /># set attributes of ~/.pulse directory<br />gnome_setattr_gsettingsd_home_dirs($1)<br /><br /># manage /.cache sound-event-cache files.<br />xdg_manage_generic_user_cache_files($1)<br /><br />2: The not so basics.<br />These pulse client seem to be required to be able to (re) start the main pulseaudio process as well in some particular cases)<br /><br /># domain transition to the gnome settingsd daemon pulseaudio domain when pulseaudio is executed.<br />gnome_spec_domtrans_gsettingsd_pulseaudio($1, $2)<br /><br /><br />3: When pulseaudio is not running.<br />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.<br /><br /># the pulse client is trying to find pulseaudio on the network i guess...<br />allow $1 self:netlink_route_socket r_netlink_socket_perms;<br />allow $1 self:tcp_socket create_socket_perms;<br />allow $1 self:unix_dgram_socket sendto;<br /><br />corenet_all_recvfrom_netlabel($1_t)<br />corenet_all_recvfrom_unlabeled($1_t)<br />corenet_tcp_bind_generic_node($1_t)<br />corenet_tcp_sendrecv_generic_if($1_t)<br />corenet_tcp_sendrecv_generic_node($1_t)<br />corenet_tcp_connect_pulseaudio_port($1_t)<br />corenet_tcp_sendrecv_pulseaudio_port($1_t)<br />corenet_sendrecv_pulseaudio_client_packets($1_t)<br /><br /># if that isnt enough, the pulseaudio client wants to be a dbus system bus client. Dont ask me why but<br />its probably looking for pulseaudio run as a dbus system domain or init daemon.<br />dbus_system_bus_client($1)<br /><br />..Heck it may even need more like maybe sysnet_read_config, i have not been able to confirm this yet.<br /><br />The amount of access(policy) a simple gui application needs to be able to spit out a sound with pulseaudio is simply amazing.Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com1tag:blogger.com,1999:blog-5024703430482213163.post-75816805941492056212010-11-29T11:22:00.001-08:002010-11-30T10:08:08.286-08:00My Fedora 14 policy for the adventurous.My Fedora 14 policy for the adventurous.<br /><br />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.<br /><br />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)<br /><br />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.<br /><br />There are atleast some things to do if one decides to give it a spin.<br /><br />One should add the following directories to /etc/skel:<br />.config<br />.config/enchant<br />.config/gtk-2.0<br />.cache<br />.local<br />.local/share<br />.gnome2<br />.gnome2/accels<br /><br />One should also modify /usr/share/dracut/modules.d/98selinux/selinux-loadpolicy.sh<br /><br />comment out:<br /><br />mount --bind /dev "$NEWROOT/dev"<br />chroot "$NEWROOT" /sbin/restorecon -R /dev<br /><br />..and then use dracut to build a new initramfs for your current kernel.<br /><br />Also fix /root:<br /><br />semanage fcontext -a -e /home/joe /root<br />restorecon -R -v /root<br /><br />Typically you would:<br /><br />setenforce 0<br />rpm -ev selinux-policy selinux-policy-targeted<br />rpm -Uvh selinux-policy-2.20100524-1.fc14.noarch.rpm selinux-policy-bare_gui-2.20100524-1.fc14.noarch.rpm<br />edit /etc/selinux/config and set selinux back to enforcing and point to bare_gui instead of targeted<br />relabel the file system<br />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)<br />make sure to add the user to sudo:<br />echo "joe ALL=(ALL) ROLE=sysadm_r TYPE=sysadm_t ALL" > /etc/sudoers.d/joe<br />chmod 0440 /etc/sudoers.d/joe<br />reboot<br /><br />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.<br /><br />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.<br /><br />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.<br /><br />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.<br /><br />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.<br /><br />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.<br /><br />The apps you are able to run may not be confined perfectly yet for all use cases (its a lot of work). <br /><br />Stuff that works for me:<br /><br />a lot of default gnome apps/applets/session services<br /><br />totem<br />rhythmbox<br />evince<br />compiz<br />gedit<br />terminator<br />screen<br />mutt<br />irssi<br />firefox<br />thunderbird<br />eclipse<br />vinagre<br />empathy/telepathy<br />gpg<br />metacity<br />nautilus<br />gnome schedule<br />seahorse<br /><br />Stuff that is not supported (atleast):<br /><br />hal<br />mlocate<br /><br />So one should be able to do some of the basics.<br /><br />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.<br /><br />For example: protect access to your keyring, gpg data, ssh data, firefox data etc.<br /><br />Not protecting access to your generic ~/.porn directory<br /><br />So how would you get started?<br /><br />We you can get a tar ball of a recent snapshot here:<br /><br />http://217.19.30.59/~dgrift/stuff/<br /><br />Just put the tarball in your ~/rpmbuild/SOURCES directory. Extract the support/selinux-policy.spec from the tarball and put that into ~/rpmbuild/SPECS/<br />then just rpmbuild -ba ~/rpmbuild/SPECS/selinux-policy.spec<br />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.<br /><br />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.<br /><br />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. <br /><br />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.<br /><br />Questions comments? domg472 at gmail dot com<br /><br />Some background information:<br /><br />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.<br /><br />Why not base it on fedora policy?<br /><br />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.Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com0tag:blogger.com,1999:blog-5024703430482213163.post-3127647744877959402010-08-07T11:05:00.000-07:002010-08-07T11:11:04.107-07:00user home directory contextsSome 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.<br /><br />Without it, semodule (what use to be genhomedircon?) only creates contexts for the "__default__" login.<br /><br />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 whyDominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com0tag:blogger.com,1999:blog-5024703430482213163.post-12426563801498104362010-08-05T14:22:00.001-07:002010-08-05T15:15:16.538-07:00The 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.<br /><br />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.<br /><br />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.<br /><br />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.<br /><br />This, i believe can be achieved by called per_role_templates in per_role_templates.<br /><br />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<br /><br />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.<br /><br />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.<br /><br />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.<br /><br />Just to show you what a per role declaration template for a GUI app would look like:<br /><br /><blockquote><br />########################################<br />## <summary><br />## Role access for mozilla declarations.<br />## </summary><br />## <param name="role_prefix"><br />## <summary><br />## Prefix to be used<br />## </summary><br />## </param><br />## <param name="role"><br />## <summary><br />## Role allowed access<br />## </summary><br />## </param><br />#<br />interface(`mozilla_declarations_role',`<br /> gen_require(`<br /> attribute mozilla_domain;<br /> type mozilla_exec_t;<br /> ')<br /><br /> ## <desc><br /> ## <p><br /> ## Allow Mozilla to execute anonymous memory (execmem))<br /> ## files.<br /> ## </p><br /> ## </desc><br /> gen_tunable(mozilla_$1_execmem, false)<br /><br /> ## <desc><br /> ## <p><br /> ## Allow Mozilla to read all user home.<br /> ## files.<br /> ## </p><br /> ## </desc><br /> gen_tunable(mozilla_$1_read_content, false)<br /><br /> ## <desc><br /> ## <p><br /> ## Network access for mozilla.<br /> ## files.<br /> ## </p><br /> ## </desc><br /> gen_tunable(mozilla_$1_network_connect, false)<br /><br /> type $1_mozilla_t, mozilla_domain;<br /> application_domain($1_mozilla_t, mozilla_exec_t)<br /> ubac_constrained($1_mozilla_t)<br /><br /> role $2 types $1_mozilla_t;<br /><br /> xserver_object_types_template($1_mozilla)<br />')<br /></blockquote><br /><br />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.Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com2tag:blogger.com,1999:blog-5024703430482213163.post-46259052436985613832010-07-25T08:51:00.000-07:002010-07-25T08:52:29.820-07:00About 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.<br />The problem is that all restricted xwindows and the unconfined users have this attribute assigned to their dbus domain.<br /><br />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.<br /><br />Same goes for the dbus_connect_session_bus() interface in terms of which process that acquire service to which dbus session domains.<br /><br />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.<br /><br />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).<br /><br />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.<br /><br />By the way: i do not see how dbus can be considered optional.<br /><br />The end result is that domains started by dbus session domains can not be optional and should be compiled into the base module.<br /><br />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.<br /><br />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.<br /><br />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)<br /><br />########################################<br />## <summary><br />## Connect to the specified session BUS<br />## for service (acquire_svc).<br />## </summary><br />## <param name="role_prefix"><br />## <summary><br />## Prefix to be used.<br />## </summary><br />## </param><br />## <param name="domain"><br />## <summary><br />## Domain allowed access.<br />## </summary><br />## </param><br />#<br />interface(`dbus_connect_session_bus_to',`<br /> gen_require(`<br /> type $1_dbusd_t;<br /> class dbus acquire_svc;<br /> ')<br /><br /> allow $2 $1_dbusd_t:dbus acquire_svc;<br />')<br /><br />########################################<br />## <summary><br />## Allow a application domain to be started<br />## by the session dbus.<br />## </summary><br />## <param name="role_prefix"><br />## <summary><br />## Domain allowed to transition.<br />## </summary><br />## </param><br />## <param name="target_domain"><br />## <summary><br />## Type to be used as a domain.<br />## </summary><br />## </param><br />## <param name="entry_point"><br />## <summary><br />## Type of the program to be used as an<br />## entry point to this domain.<br />## </summary><br />## </param><br />#<br />interface(`dbus_session_domain',`<br /> gen_require(`<br /> type $1_dbusd_t;<br /> ')<br /><br /> domtrans_pattern($1_dbusd_t, $3, $2)<br /><br /> dbus_session_bus_client($2)<br /> dbus_connect_session_bus($2)<br />')<br /><br />Moral of this article: I would be nice if we came up with a proper solution for the issues i described.<br /><br />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...<br /><br />As always: Changes i have made can be reviewed in my Git repository.Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com0tag:blogger.com,1999:blog-5024703430482213163.post-51272956397069951792010-07-17T00:37:00.000-07:002010-07-17T01:28:50.898-07:00My 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)<br /><br />- 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:<br /><br />user_u: plain common user. should "feel" unrestricted, but domain transitions wherever possible. Also can not run setuid applications.<br /><br />staff_u: main difference with user_u is that staff users CAN run setuid applications.<br /><br />sysadmin_u: should be able to do most everything a normal root can by domain transitioning wherever possible.<br /><br />- 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.<br /><br />guest_u: least privilege restricted login users with only access via ssh, no network access. no setuid.<br />xguest_u: least privilege restricted login users with only access via xdm. no network access. no setuid.<br /><br />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)<br /><br />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.<br /><br />- 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)<br />Examples of base user usage is: webadm, dbadm<br /><br />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.<br /><br />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.<br /><br />Common users should always be able to run traceroute and ping but they should domain transition to the respective domains to do so.<br /><br />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.<br /><br />I ended up, removing the tunable_policy from the netutils type enforcement source policy file.<br /><br />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.<br /><br />Some other examples are that base users can run all applications and can run usr_t files.Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com0tag:blogger.com,1999:blog-5024703430482213163.post-81324970550512476732010-07-13T10:42:00.000-07:002010-07-13T10:44:06.494-07:00Rethinking 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.<br /><br />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.<br /><br />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.<br /><br />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.<br /><br />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.<br /><br />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.<br /><br />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.<br /><br />normal restricted users like guest only need to be able to manage generic user content.<br /><br />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.<br /><br />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.<br /><br />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.<br /><br />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.<br /><br />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.<br /><br />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.<br /><br />With this i hope to achieve that i can simplify user content and at the same time keep privileges as tight as possible.<br /><br />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.Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com0tag:blogger.com,1999:blog-5024703430482213163.post-55453776088971081182010-07-12T02:06:00.000-07:002010-07-12T02:23:29.387-07:00Targeted 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.<br /><br />The main property of my policy is that, besides the usual, it aims to confine the user space by default.<br />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.<br /><br />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.<br /><br />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:<br /><br />echo "joe ALL=(ALL) TYPE=unconfined_t ROLE=unconfined_r ALL" >> /etc/sudoers<br /><br />My policy adds some confinement for some user apps. Most notably currently:<br />firefox, nsplugin, totem, telepathy, mutt, thunderbird, elinks, irssi, metacity, gnome dvb, seahorse-daemon, vino_server and others.<br /><br />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.<br /><br />To make an rpm of my policy is pretty straight forward on fedora.<br />You can clone my refpolicy repository:<br /><br />git clone git://217.19.30.59/refpolicy.git<br /><br />or update it after you cloned it:<br /><br />cd refpolicy; git pull<br /><br />(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.<br /><br />To determine my main policy version either look at the tags or see "Version ; .." in the spec file in "redhat/selinux-policy.spec"<br /><br />Replace the version number with the version number in the following commands:<br /><br />git archive --format=tar --prefix=refpolicy-3.8.6/ refpolicy | gzip > ~/rpmbuild/SOURCES/refpolicy-3.8.6.tar.gz<br /><br />git diff refpolicy master > ~/rpmbuild/SOURCES/refpolicy-3.8.6.patch<br /><br />Make sure the path exists (install rpmdevtools) run rpmdev-setuptree.<br /><br />Next copy the redhat/selinux-policy.spec from the Git repository:<br /><br />cp redhat/selinux-policy.spec ~/rpmbuild/SPECS/<br /><br />And build the packages:<br /><br />cd ~/rpmbuild/SOURCES/; rpmbuild -ba ../SPECS/selinux-policy.spec<br /><br />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.<br /><br />This means you will lose any modifications that you may have made:<br /><br />setenforce 0<br />yum erase selinux-policy selinux-policy-targeted<br />mv /etc/selinux /etc/selinux.backup<br />yum install selinux*.rpm (the build rpms)<br />touch /.autorelabel && reboot<br /><br />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:<br />semanage login -a -s staff_u -r s0-s0:c0.c1023 joe<br />chcon -R -u staff_u /home/joe<br />chcon -R -u staff_u /tmp/joe<br />chcon -R -u staff_u /var/tmp/joe<br /><br />That should be sufficient.<br /><br />If pulseadio does not start, then remove ~/.esd_auth ~/.pulse /tmp/.esd* and relogin or restart pulse.<br />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.<br /><br />Be prepared to stumble on bugs, issues etcetera. Feel free to contact me if you have questions or comments. Patches welcome.<br /><br />I am using this policy myself on two desktop systems (fedora13/Gnome) and several headless servers.<br /><br />Warning: Only consider trying this if you are familiar to, and not intimidated by SELinux.Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com0tag:blogger.com,1999:blog-5024703430482213163.post-49284613133764293152010-02-14T13:29:00.000-08:002010-02-14T13:59:33.297-08:00About apache_content_templateIn refpolicy there are about eight modules that have calls to apache_content_template in their private policy. These template calls are located in optional policy blocks. This is so that these modules do not depend on the apache module being present. <br /><br />The problem is that seven out of these eight modules have file context specifications containing a executable type, that is declared in the apache content template, in their file context file. As far as i know file context specifications are never optional.<br /><br />So even though calls to apache content template are optional, they really aren't because the file context specifications that accompany them are not optional.<br /><br />This means that eight modules depend on the apache module being installed. Try to de-install the apache module (semodule -r apache) and you will be presented with some very unclear errors. Most people will not know what to do.<br /><br />So how can we fix that?<br /><br />Well here is an example. We use the apache_cgi_domain() instead:<br /><br />########################################<br />#<br /># BackupPC admin private declarations.<br />#<br /><br />type backuppc_admin_t, backuppc_domains;<br />type backuppc_admin_exec_t;<br />domain_type(backuppc_admin_t)<br />domain_entry_file(backuppc_admin_t, backuppc_admin_exec_t)<br />role system_r types backuppc_admin_t;<br /><br />########################################<br />#<br /># BackupPC admin private policy.<br />#<br /><br />optional_policy(`<br /> apache_cgi_domain(backuppc_admin_t, backuppc_admin_exec_t)<br />')<br /><br />/usr/share/BackupPC/sbin/BackupPC_Admin -- gen_context(system_u:object_r:backuppc_admin_exec_t, s0)<br /><br />This way we can make the call to apache_cgi_domain() *really* optional. It is a bit more work initially but in my view this is maintainable unlike apache_content_template.Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com1tag:blogger.com,1999:blog-5024703430482213163.post-61078221339177965572010-01-14T01:41:00.000-08:002010-01-14T11:27:29.764-08:00Test Git daemon policy.Clone my latest selinux-modules git repository:<br /><br />git clone git://84.245.6.206/selinux-modules.git<br />cd selinux-modules && make -f /usr/share/selinux/devel/Makefile gitd.pp<br />semodule -d git; semodule -i gitd.pp<br />cp gitd.if /usr/share/selinux/devel/include/services/gitd.if<br /><br />To test the Git session server you should build a custom module calling the gitd_session_role template for your role:<br /><br />echo "policy_module(mygittest, 1.0.0)" > mygittest.te;<br />echo "optional_policy(\`" >> mygittest.te;<br />echo "gen_require(\`" >> mygittest.te;<br />echo "# Assuming you want to test as unconfined_t" >> mygittest.te;<br />echo "type unconfined_t;" >> mygittest.te;<br />echo "role unconfined_r;" >> mygittest.te;<br />echo "')" >> mygittest.te;<br />echo "gitd_session_role(unconfined_r, unconfined_t)" >> mygittest.te;<br />echo "')" >> mygittest.te;<br /><br />make -f /usr/share/selinux/devel/Makefile mygittest.pp<br />semodule -i mygittest.pp<br /><br />Make sure that port tcp:9418 open and that tcp-wrappers is configured to accept connectivity on this port.<br /><br />install git-daemon and its dependencies: yum install git-daemon.<br /><br />You must edit /etc/xinetd.d/git. set "disable" to "no", "server" to "/usr/libexec/git-core/git-daemon", and remove the "daemon" argument from "server_args". Keep an eye on /var/log/messages in case it behaves strange.<br /><br />Restore the following contexts:<br /><br />restorecon -R -v /var/lib/git<br />restorecon -v /usr/libexec/git-core/git-daemon<br />restorecon -v ~/.gitconfig<br />restorecon -v ~/public_git<br /><br />Start xinetd: service xinetd start.<br /><br />Set up a default git shell user for generic shared repositories:<br /><br />groupadd git<br />useradd -Z git_shell_u -M -s /usr/bin/git-shell joe<br />usermod -a -G git joe<br />passwd joe<br /><br />Set up a bare "test" shared repostory:<br /><br />mkdir /var/lib/git/test.git<br />cd /var/lib/git/test.git && git --bare init<br />chown -R root:git /var/lib/git/test.git<br />chmod -R g+w /var/lib/git/test.git<br />chmod -R g+s /var/lib/git/test.git<br />chmod -R +t /var/lib/git/test.git<br /><br />From your "normal" user account clone the bare repository:<br /><br />git clone git://localhost/test.git<br />cd test<br /><br />Make changes to it:<br /><br />echo "test" > test;<br />git init<br />git add .<br />git commit -a -s -m "My initial commit."<br /><br />As user "joe" push to the shared repository:<br /><br />git push --all git+ssh://joe@localhost/var/lib/git/test.git<br />git pull<br />git status<br />git show<br /><br />Testing Git session:<br /><br />Stop xinetd and in your "normal" (we are done with "joe" for now) user home directory make sure ~/public_git exists.<br />restorecon -R -v /public_git<br />Previously we called a "gitd_session_role" template for users operating in the unconfined_t domain. This means when your id -Z returns: unconfined_u:unconfined_r:unconfined_t:s0, git with the daemon option will run in a Git session SELinux environment for you.<br /><br />Create a new personal repository in ~/public_git:<br /><br />mkdir ~/public_git/hello<br />cd ~/public_git/hello<br />git init<br />echo "hello" > hello<br />git add .<br />git commit -a -s -m "My initial commit."<br /><br />Serve your personal repository with the following command:<br /><br />git daemon --export-all --user-path=public_git<br /><br />In another terminal clone the repository:<br /><br />git clone git://localhost/~yourloginnamehere/hello<br /><br />Make a commit to it:<br /><br />cd hello<br />echo "bye" >> hello<br />git commit -a -s -m "Add good bye"<br /><br />Push the change to your personal repository:<br /><br />git push --all ssh://yourloginnamehere@localhost/~/public_git/hello<br /><br />Hosting personal repositories with Git system daemon.<br /><br />Stop your Git session daemon (ctrl-c) and start xinetd.<br /><br />Set the boolean to allow the Git system daemon to search user home directories for personal Git repositories to serve:<br /><br />setsebool gitd_system_enable_homedirs on<br /><br />Now clone the personal repository again:<br /><br />git clone git://localhost/~yourloginnamehere/hello<br />cd hello<br />echo "hi" >> hello<br />git commit -a -s -m "Added Hi."<br /><br />And push to the personal repository:<br /><br />git push --all ssh://yourloginnamehere@localhost/~/public_git/hello<br /><br />Create a customized Git Shell user that has access to a restricted shared repository (besides having access to any generic system repositories) Also create a restricted repository and allow our created Git shell user access to this new restricted repository.<br /><br />echo "policy_module(secret_git_shell, 1.0.0)" > secret_git_shell.te;<br />echo "gitd_role_template(secret_git_shell)" >> secret_git_shell.te;<br />echo "gitd_content_template(secret)" >> secret_git_shell.te;<br />echo "gitd_content_delegation(secret_git_shell_t, gitd_secret_content_t)" >> secret_git_shell.te;<br />echo "gen_user(secret_git_shell_u, user, secret_git_shell_r, s0, s0)" >> secret_git_shell.te;<br /><br />echo "/var/lib/git/secret\.git(/.*)? gen_context(system_u:object_r:gitd_secret_content_t, s0)" > secret_git_shell.fc;<br /><br />make -f /usr/share/selinux/devel/Makefile secret_git_shell.pp<br />semodule -i secret_git_shell.pp<br /><br />Create a secret Git shell user:<br /><br />useradd -Z secret_git_shell_u -M -s /usr/bin/git-shell jane<br />usermod -a -G git jane<br />passwd jane<br /><br />Create a bare secret shared repository:<br /><br />mkdir /var/lib/git/secret.git<br />cd /var/lib/git/secret.git && git --bare init<br />chown -R root:git /var/lib/git/secret.git<br />chmod -R g+w /var/lib/git/secret.git<br />chmod -R g+s /var/lib/git/secret.git<br />chmod -R +t /var/lib/git/secret.git<br /><br />Restore the context of the secret repository:<br /><br />restorecon -R -v /var/lib/git/secret.git<br /><br />Everyone can read it but only jane can push to it. As a "normal" user clone the secret repository.<br /><br />git clone git://localhost/secret.git<br />cd secret<br />echo "secret" > secret<br />git init<br />git add .<br />git commit -a -s -m "My first commit."<br /><br />Push it as user "jane"<br /><br />git push --all git+ssh://jane@localhost/var/lib/git/secret.git<br />git pull<br />git status<br />git show<br /><br />Make another commit:<br /><br />echo "Joe here" >> secret<br />git commit -a -s -m "add Joe here"<br /><br />Now try to push it as user "joe" (joe can push generic shared repositories but joe is not allowed to push to the secret repository)<br /><br />git push --all git+ssh://joe@localhost/var/lib/git/secret.gitDominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com0tag:blogger.com,1999:blog-5024703430482213163.post-12543844237212388552009-10-21T01:45:00.000-07:002009-10-21T03:03:07.916-07:00Git daemon, SELinux and Fedora 12 Beta.<span style="font-size:85%;"><span style="font-family: arial;">Recently i decided to redo my Git daemon domain and reinstall a Git daemon server.</span><br /><br /><span style="font-family: arial;">This article will explain the issues i had to consider.</span><br /><br /><span style="font-family: arial;">SELinux can be used to confined the Git daemon and Git Shell. I have not used SELinux in a optimal way here but i decided to implement a mix of MAC, DAC and Git ACL.</span><br /><br /><span style="font-family: arial;">As for SELinux i have installed the following module:</span><br /><br /><span style="font-family: arial;">gitd.te:<br /><br /></span><span style="font-family: arial;">[code]</span><br /><br /><span style="font-family: arial;">policy_module(gitd, 1.0.0)</span><br /><br /><span style="font-family: arial;">########################################</span><br /><span style="font-family: arial;">#</span><br /><span style="font-family: arial;"># Git daemon global private declarations.</span><br /><span style="font-family: arial;">#</span><br /><br /><span style="font-family: arial;">attribute gitd_type;</span><br /><span style="font-family: arial;">attribute gitd_content_type;</span><br /><br /><span style="font-family: arial;">type gitd_exec_t;</span><br /><br /><span style="font-family: arial;"># FIXME</span><br /><span style="font-family: arial;">type gitd_port_t;</span><br /><span style="font-family: arial;">corenet_port(gitd_port_t)</span><br /><br /><span style="font-family: arial;">########################################</span><br /><span style="font-family: arial;">#</span><br /><span style="font-family: arial;"># Git daemon system private declarations.</span><br /><span style="font-family: arial;">#</span><br /><br /><span style="font-family: arial;">## <desc></span><br /><span style="font-family: arial;">## <p></span><br /><span style="font-family: arial;">## Allow Git-shell to modify and execute public files</span><br /><span style="font-family: arial;">## used for public file transfer services. Directories/Files must</span><br /><span style="font-family: arial;">## be labeled public_content_rw_t.</span><br /><span style="font-family: arial;">## </p></span><br /><span style="font-family: arial;">## </desc></span><br /><span style="font-family: arial;"># gen_tunable(gitd_allow_anon_write, false)</span><br /><br /><span style="font-family: arial;">## <desc></span><br /><span style="font-family: arial;">## <p></span><br /><span style="font-family: arial;">## Allow Git daemon system to search home directories.</span><br /><span style="font-family: arial;">## </p></span><br /><span style="font-family: arial;">## </desc></span><br /><span style="font-family: arial;">gen_tunable(gitd_system_enable_homedirs, false)</span><br /><br /><span style="font-family: arial;">## <desc></span><br /><span style="font-family: arial;">## <p></span><br /><span style="font-family: arial;">## Allow Git daemon system to access cifs file systems.</span><br /><span style="font-family: arial;">## </p></span><br /><span style="font-family: arial;">## </desc></span><br /><span style="font-family: arial;">gen_tunable(gitd_system_use_cifs, false)</span><br /><br /><span style="font-family: arial;">## <desc></span><br /><span style="font-family: arial;">## <p></span><br /><span style="font-family: arial;">## Allow Git daemon system to access nfs file systems.</span><br /><span style="font-family: arial;">## </p></span><br /><span style="font-family: arial;">## </desc></span><br /><span style="font-family: arial;">gen_tunable(gitd_system_use_nfs, false)</span><br /><br /><span style="font-family: arial;">type gitd_system_t, gitd_type;</span><br /><span style="font-family: arial;">inetd_service_domain(gitd_system_t, gitd_exec_t)</span><br /><span style="font-family: arial;">role system_r types gitd_system_t;</span><br /><br /><span style="font-family: arial;">type gitd_shared_t, gitd_content_type;</span><br /><span style="font-family: arial;">files_type(gitd_shared_t)</span><br /><br /><span style="font-family: arial;"># permissive gitd_system_t;</span><br /><br /><span style="font-family: arial;">########################################</span><br /><span style="font-family: arial;">#</span><br /><span style="font-family: arial;"># Git shell private declarations.</span><br /><span style="font-family: arial;">#</span><br /><br /><span style="font-family: arial;">gen_require(`</span><br /><span style="font-family: arial;"> attribute unpriv_userdomain, userdomain;</span><br /><span style="font-family: arial;"> class context contains;</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">attribute gits_file_type;</span><br /><span style="font-family: arial;">attribute gits_usertype;</span><br /><br /><span style="font-family: arial;">type gits_t, userdomain, gits_usertype, unpriv_userdomain;</span><br /><span style="font-family: arial;">domain_type(gits_t)</span><br /><br /><span style="font-family: arial;">role gits_r types gits_t;</span><br /><span style="font-family: arial;">allow system_r gits_r;</span><br /><br /><span style="font-family: arial;">corecmd_shell_entry_type(gits_t)</span><br /><span style="font-family: arial;">corecmd_bin_entry_type(gits_t)</span><br /><br /><span style="font-family: arial;">domain_interactive_fd(gits_t)</span><br /><span style="font-family: arial;">domain_user_exemption_target(gits_t)</span><br /><br /><span style="font-family: arial;"># permissive gits_t;</span><br /><br /><span style="font-family: arial;">########################################</span><br /><span style="font-family: arial;">#</span><br /><span style="font-family: arial;"># Git daemon session session private declarations.</span><br /><span style="font-family: arial;">#</span><br /><br /><span style="font-family: arial;">## <desc></span><br /><span style="font-family: arial;">## <p></span><br /><span style="font-family: arial;">## Allow Git daemon session to bind</span><br /><span style="font-family: arial;">## tcp sockets to all unreserved ports.</span><br /><span style="font-family: arial;">## </p></span><br /><span style="font-family: arial;">## </desc></span><br /><span style="font-family: arial;">gen_tunable(gitd_session_bind_all_unreserved_ports, false)</span><br /><br /><span style="font-family: arial;">type gitd_session_t, gitd_type;</span><br /><span style="font-family: arial;">application_domain(gitd_session_t, gitd_exec_t)</span><br /><span style="font-family: arial;">ubac_constrained(gitd_session_t)</span><br /><br /><span style="font-family: arial;">type gitd_personal_t, gitd_content_type;</span><br /><span style="font-family: arial;">userdom_user_home_content(gitd_personal_t)</span><br /><br /><span style="font-family: arial;"># permissive gitd_session_t;</span><br /><br /><span style="font-family: arial;">########################################</span><br /><span style="font-family: arial;">#</span><br /><span style="font-family: arial;"># Git daemon global private policy.</span><br /><span style="font-family: arial;">#</span><br /><br /><span style="font-family: arial;">allow gitd_type self:fifo_file rw_fifo_file_perms;</span><br /><span style="font-family: arial;">allow gitd_type self:netlink_route_socket { create_socket_perms nlmsg_read };</span><br /><span style="font-family: arial;">allow gitd_type self:tcp_socket create_socket_perms;</span><br /><span style="font-family: arial;">allow gitd_type self:udp_socket create_socket_perms;</span><br /><span style="font-family: arial;">allow gitd_type self:unix_dgram_socket create_socket_perms;</span><br /><br /><span style="font-family: arial;"># FIXME</span><br /><span style="font-family: arial;">allow gitd_type gitd_port_t:tcp_socket name_bind;</span><br /><br /><span style="font-family: arial;">corenet_all_recvfrom_netlabel(gitd_type)</span><br /><span style="font-family: arial;">corenet_all_recvfrom_unlabeled(gitd_type)</span><br /><br /><span style="font-family: arial;">corenet_tcp_sendrecv_all_if(gitd_type)</span><br /><span style="font-family: arial;">corenet_tcp_sendrecv_all_nodes(gitd_type)</span><br /><span style="font-family: arial;">corenet_tcp_sendrecv_all_ports(gitd_type)</span><br /><br /><span style="font-family: arial;">corenet_tcp_bind_all_nodes(gitd_type)</span><br /><br /><span style="font-family: arial;">corecmd_exec_bin(gitd_type)</span><br /><br /><span style="font-family: arial;">files_read_etc_files(gitd_type)</span><br /><span style="font-family: arial;">files_read_usr_files(gitd_type)</span><br /><br /><span style="font-family: arial;">fs_search_auto_mountpoints(gitd_type)</span><br /><br /><span style="font-family: arial;">kernel_read_system_state(gitd_type)</span><br /><br /><span style="font-family: arial;">logging_send_syslog_msg(gitd_type)</span><br /><br /><span style="font-family: arial;">miscfiles_read_localization(gitd_type)</span><br /><br /><span style="font-family: arial;">sysnet_read_config(gitd_type)</span><br /><br /><span style="font-family: arial;">optional_policy(`</span><br /><span style="font-family: arial;"> nis_use_ypbind(gitd_type)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">optional_policy(`</span><br /><span style="font-family: arial;"> nscd_read_pid(gitd_type)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">########################################</span><br /><span style="font-family: arial;">#</span><br /><span style="font-family: arial;"># Git daemon system repository private policy.</span><br /><span style="font-family: arial;">#</span><br /><br /><span style="font-family: arial;">list_dirs_pattern(gitd_system_t, gitd_content_type, gitd_content_type)</span><br /><span style="font-family: arial;">read_files_pattern(gitd_system_t, gitd_content_type, gitd_content_type)</span><br /><span style="font-family: arial;">files_search_var(gitd_system_t)</span><br /><br /><span style="font-family: arial;"># This will not work since git-shell needs to execute gitd content thus public content files.</span><br /><span style="font-family: arial;"># There is currently no clean way to execute public content files.</span><br /><span style="font-family: arial;"># miscfiles_read_public_files(gitd_system_t)</span><br /><br /><span style="font-family: arial;">tunable_policy(`gitd_system_enable_homedirs', `</span><br /><span style="font-family: arial;"> userdom_search_user_home_dirs(gitd_system_t)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">tunable_policy(`gitd_system_enable_homedirs && use_nfs_home_dirs', `</span><br /><span style="font-family: arial;"> fs_list_nfs(gitd_system_t)</span><br /><span style="font-family: arial;"> fs_read_nfs_files(gitd_system_t)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">tunable_policy(`gitd_system_enable_homedirs && use_samba_home_dirs', `</span><br /><span style="font-family: arial;"> fs_list_cifs(gitd_system_t)</span><br /><span style="font-family: arial;"> fs_read_cifs_files(gitd_system_t)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">tunable_policy(`gitd_system_use_cifs', `</span><br /><span style="font-family: arial;"> fs_list_cifs(gitd_system_t)</span><br /><span style="font-family: arial;"> fs_read_cifs_files(gitd_system_t)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">tunable_policy(`gitd_system_use_nfs', `</span><br /><span style="font-family: arial;"> fs_list_nfs(gitd_system_t)</span><br /><span style="font-family: arial;"> fs_read_nfs_files(gitd_system_t)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">########################################</span><br /><span style="font-family: arial;">#</span><br /><span style="font-family: arial;"># Git shell private policy.</span><br /><span style="font-family: arial;">#</span><br /><br /><span style="font-family: arial;">allow gits_t self:context contains;</span><br /><span style="font-family: arial;">allow gits_t self:fifo_file rw_fifo_file_perms;</span><br /><br /><span style="font-family: arial;">corecmd_exec_bin(gits_t)</span><br /><br /><span style="font-family: arial;">kernel_read_system_state(gits_t)</span><br /><br /><span style="font-family: arial;">files_read_etc_files(gits_t)</span><br /><br /><span style="font-family: arial;">files_search_home(gits_t)</span><br /><br /><span style="font-family: arial;">gitd_execute_shared_files(gits_t)</span><br /><span style="font-family: arial;">gitd_manage_shared_content(gits_t)</span><br /><br /><span style="font-family: arial;">miscfiles_read_localization(gits_t)</span><br /><span style="font-family: arial;"># miscfiles_read_public_files(gits_t)</span><br /><br /><span style="font-family: arial;">ssh_rw_stream_sockets(gits_t)</span><br /><br /><span style="font-family: arial;"># FIXME</span><br /><span style="font-family: arial;"># This will not work since git-shell needs to execute gitd content thus public content files.</span><br /><span style="font-family: arial;"># There is currently no clean way to execute public content files.</span><br /><span style="font-family: arial;"># tunable_policy(`gitd_allow_anon_write', `</span><br /><span style="font-family: arial;"> # miscfiles_exec_public_files(gits_t)</span><br /><span style="font-family: arial;"> # miscfiles_manage_public_files(gits_t)</span><br /><span style="font-family: arial;"># ')</span><br /><br /><span style="font-family: arial;">tunable_policy(`gitd_system_enable_homedirs && use_nfs_home_dirs', `</span><br /><span style="font-family: arial;"> fs_exec_nfs_files(gits_t)</span><br /><span style="font-family: arial;"> fs_manage_nfs_dirs(gits_t)</span><br /><span style="font-family: arial;"> fs_manage_nfs_files(gits_t)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">tunable_policy(`gitd_system_enable_homedirs && use_samba_home_dirs', `</span><br /><span style="font-family: arial;"> fs_exec_cifs_files(gits_t)</span><br /><span style="font-family: arial;"> fs_manage_cifs_dirs(gits_t)</span><br /><span style="font-family: arial;"> fs_manage_cifs_files(gits_t)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">tunable_policy(`gitd_system_use_cifs', `</span><br /><span style="font-family: arial;"> fs_exec_cifs_files(gits_t)</span><br /><span style="font-family: arial;"> fs_manage_cifs_dirs(gits_t)</span><br /><span style="font-family: arial;"> fs_manage_cifs_files(gits_t)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">tunable_policy(`gitd_system_use_nfs', `</span><br /><span style="font-family: arial;"> fs_exec_nfs_files(gits_t)</span><br /><span style="font-family: arial;"> fs_manage_nfs_dirs(gits_t)</span><br /><span style="font-family: arial;"> fs_manage_nfs_files(gits_t)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">optional_policy(`</span><br /><span style="font-family: arial;"> nscd_read_pid(gits_t)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">########################################</span><br /><span style="font-family: arial;">#</span><br /><span style="font-family: arial;"># Git daemon session repository private policy.</span><br /><span style="font-family: arial;">#</span><br /><br /><span style="font-family: arial;">list_dirs_pattern(gitd_session_t, gitd_personal_t, gitd_personal_t)</span><br /><span style="font-family: arial;">read_files_pattern(gitd_session_t, gitd_personal_t, gitd_personal_t)</span><br /><span style="font-family: arial;">userdom_search_user_home_dirs(gitd_session_t)</span><br /><br /><span style="font-family: arial;">userdom_use_user_terminals(gitd_session_t)</span><br /><br /><span style="font-family: arial;">tunable_policy(`gitd_session_bind_all_unreserved_ports', `</span><br /><span style="font-family: arial;"> corenet_tcp_bind_all_unreserved_ports(gitd_session_t)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">tunable_policy(`use_nfs_home_dirs', `</span><br /><span style="font-family: arial;"> fs_list_nfs(gitd_session_t)</span><br /><span style="font-family: arial;"> fs_read_nfs_files(gitd_session_t)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">tunable_policy(`use_samba_home_dirs', `</span><br /><span style="font-family: arial;"> fs_list_cifs(gitd_session_t)</span><br /><span style="font-family: arial;"> fs_read_cifs_files(gitd_session_t)</span><br /><span style="font-family: arial;">')</span><br /><span style="font-family: arial;">[/code]</span><br /><br /><span style="font-family: arial;">gitd.if</span><br /><span style="font-family: arial;">[code]</span><br /><span style="font-family: arial;">## <summary>Git daemon is a really simple server for Git repositories.</summary></span><br /><span style="font-family: arial;">## <desc></span><br /><span style="font-family: arial;">## <p></span><br /><span style="font-family: arial;">## A really simple TCP git daemon that normally listens on</span><br /><span style="font-family: arial;">## port DEFAULT_GIT_PORT aka 9418. It waits for a</span><br /><span style="font-family: arial;">## connection asking for a service, and will serve that</span><br /><span style="font-family: arial;">## service if it is enabled.</span><br /><span style="font-family: arial;">## </p></span><br /><span style="font-family: arial;">## <p></span><br /><span style="font-family: arial;">## It verifies that the directory has the magic file</span><br /><span style="font-family: arial;">## git-daemon-export-ok, and it will refuse to export any</span><br /><span style="font-family: arial;">## git directory that has not explicitly been marked for</span><br /><span style="font-family: arial;">## export this way (unless the --export-all parameter is</span><br /><span style="font-family: arial;">## specified). If you pass some directory paths as</span><br /><span style="font-family: arial;">## git-daemon arguments, you can further restrict the</span><br /><span style="font-family: arial;">## offers to a whitelist comprising of those.</span><br /><span style="font-family: arial;">## </p></span><br /><span style="font-family: arial;">## <p></span><br /><span style="font-family: arial;">## By default, only upload-pack service is enabled, which</span><br /><span style="font-family: arial;">## serves git-fetch-pack and git-ls-remote clients, which</span><br /><span style="font-family: arial;">## are invoked from git-fetch, git-pull, and git-clone.</span><br /><span style="font-family: arial;">## </p></span><br /><span style="font-family: arial;">## <p></span><br /><span style="font-family: arial;">## This is ideally suited for read-only updates, i.e.,</span><br /><span style="font-family: arial;">## pulling from git repositories.</span><br /><span style="font-family: arial;">## </p></span><br /><span style="font-family: arial;">## <p></span><br /><span style="font-family: arial;">## An upload-archive also exists to serve git-archive.</span><br /><span style="font-family: arial;">## </p></span><br /><span style="font-family: arial;">## </desc></span><br /><br /><span style="font-family: arial;">#######################################</span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## Role access for Git daemon session.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## <param name="role"></span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## Role allowed access.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## </param></span><br /><span style="font-family: arial;">## <param name="domain"></span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## User domain for the role.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## </param></span><br /><span style="font-family: arial;">#</span><br /><span style="font-family: arial;">interface(`gitd_session_role', `</span><br /><span style="font-family: arial;"> gen_require(`</span><br /><span style="font-family: arial;"> type gitd_session_t, gitd_exec_t, gitd_personal_t;</span><br /><span style="font-family: arial;"> ')</span><br /><br /><span style="font-family: arial;"> ########################################</span><br /><span style="font-family: arial;"> #</span><br /><span style="font-family: arial;"> # Git daemon session shared declarations.</span><br /><span style="font-family: arial;"> #</span><br /><br /><span style="font-family: arial;"> ## <desc></span><br /><span style="font-family: arial;"> ## <p></span><br /><span style="font-family: arial;"> ## Allow transitions to the Git daemon</span><br /><span style="font-family: arial;"> ## session domain.</span><br /><span style="font-family: arial;"> ## </p></span><br /><span style="font-family: arial;"> ## </desc></span><br /><span style="font-family: arial;"> gen_tunable(gitd_session_transition, false)</span><br /><br /><span style="font-family: arial;"> role $1 types gitd_session_t;</span><br /><br /><span style="font-family: arial;"> ########################################</span><br /><span style="font-family: arial;"> #</span><br /><span style="font-family: arial;"> # Git daemon session shared policy.</span><br /><span style="font-family: arial;"> #</span><br /><br /><span style="font-family: arial;"> tunable_policy(`gitd_session_transition', `</span><br /><span style="font-family: arial;"> domtrans_pattern($2, gitd_exec_t, gitd_session_t)</span><br /><span style="font-family: arial;"> ', `</span><br /><span style="font-family: arial;"> can_exec($2, gitd_exec_t)</span><br /><span style="font-family: arial;"> ')</span><br /><br /><span style="font-family: arial;"> allow $2 gitd_session_t:process { ptrace signal_perms };</span><br /><span style="font-family: arial;"> ps_process_pattern($2, gitd_session_t)</span><br /><br /><span style="font-family: arial;"> exec_files_pattern($2, gitd_personal_t, gitd_personal_t)</span><br /><span style="font-family: arial;"> manage_dirs_pattern($2, gitd_personal_t, gitd_personal_t)</span><br /><span style="font-family: arial;"> manage_files_pattern($2, gitd_personal_t, gitd_personal_t)</span><br /><br /><span style="font-family: arial;"> relabel_dirs_pattern($2, gitd_personal_t, gitd_personal_t)</span><br /><span style="font-family: arial;"> relabel_files_pattern($2, gitd_personal_t, gitd_personal_t)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">########################################</span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## Allow the specified domain to execute</span><br /><span style="font-family: arial;">## Git daemon shared files.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## <param name="domain"></span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## Domain allowed access.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## </param></span><br /><span style="font-family: arial;">## <rolecap/></span><br /><span style="font-family: arial;">#</span><br /><span style="font-family: arial;">interface(`gitd_execute_shared_files', `</span><br /><span style="font-family: arial;"> gen_require(`</span><br /><span style="font-family: arial;"> type gitd_shared_t;</span><br /><span style="font-family: arial;"> ')</span><br /><br /><span style="font-family: arial;"> exec_files_pattern($1, gitd_shared_t, gitd_shared_t)</span><br /><span style="font-family: arial;"> files_search_var($1)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">########################################</span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## Allow the specified domain to manage</span><br /><span style="font-family: arial;">## Git daemon shared content.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## <param name="domain"></span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## Domain allowed access.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## </param></span><br /><span style="font-family: arial;">## <rolecap/></span><br /><span style="font-family: arial;">#</span><br /><span style="font-family: arial;">interface(`gitd_manage_shared_content', `</span><br /><span style="font-family: arial;"> gen_require(`</span><br /><span style="font-family: arial;"> type gitd_shared_t;</span><br /><span style="font-family: arial;"> ')</span><br /><br /><span style="font-family: arial;"> manage_dirs_pattern($1, gitd_shared_t, gitd_shared_t)</span><br /><span style="font-family: arial;"> manage_files_pattern($1, gitd_shared_t, gitd_shared_t)</span><br /><span style="font-family: arial;"> files_search_var($1)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">########################################</span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## Allow the specified domain to manage</span><br /><span style="font-family: arial;">## Git daemon personal content.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## <param name="domain"></span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## Domain allowed access.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## </param></span><br /><span style="font-family: arial;">## <rolecap/></span><br /><span style="font-family: arial;">#</span><br /><span style="font-family: arial;">interface(`gitd_manage_personal_content', `</span><br /><span style="font-family: arial;"> gen_require(`</span><br /><span style="font-family: arial;"> type gitd_personal_t;</span><br /><span style="font-family: arial;"> ')</span><br /><br /><span style="font-family: arial;"> manage_dirs_pattern($1, gitd_personal_t, gitd_personal_t)</span><br /><span style="font-family: arial;"> manage_files_pattern($1, gitd_personal_t, gitd_personal_t)</span><br /><span style="font-family: arial;"> files_search_home($1)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">########################################</span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## Allow the specified domain to read</span><br /><span style="font-family: arial;">## Git daemon personal content.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## <param name="domain"></span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## Domain allowed access.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## </param></span><br /><span style="font-family: arial;">## <rolecap/></span><br /><span style="font-family: arial;">#</span><br /><span style="font-family: arial;">interface(`gitd_read_personal_content', `</span><br /><span style="font-family: arial;"> gen_require(`</span><br /><span style="font-family: arial;"> type gitd_personal_t;</span><br /><span style="font-family: arial;"> ')</span><br /><br /><span style="font-family: arial;"> list_dirs_pattern($1, gitd_personal_t, gitd_personal_t)</span><br /><span style="font-family: arial;"> read_files_pattern($1, gitd_personal_t, gitd_personal_t)</span><br /><span style="font-family: arial;"> files_search_home($1)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">########################################</span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## Allow the specified domain to read</span><br /><span style="font-family: arial;">## Git daemon shared content.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## <param name="domain"></span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## Domain allowed access.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## </param></span><br /><span style="font-family: arial;">## <rolecap/></span><br /><span style="font-family: arial;">#</span><br /><span style="font-family: arial;">interface(`gitd_read_shared_content', `</span><br /><span style="font-family: arial;"> gen_require(`</span><br /><span style="font-family: arial;"> type gitd_shared_t;</span><br /><span style="font-family: arial;"> ')</span><br /><br /><span style="font-family: arial;"> list_dirs_pattern($1, gitd_shared_t, gitd_shared_t)</span><br /><span style="font-family: arial;"> read_files_pattern($1, gitd_shared_t, gitd_shared_t)</span><br /><span style="font-family: arial;"> files_search_var($1)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">########################################</span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## Allow the specified domain to relabel</span><br /><span style="font-family: arial;">## Git daemon shared content.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## <param name="domain"></span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## Domain allowed access.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## </param></span><br /><span style="font-family: arial;">## <rolecap/></span><br /><span style="font-family: arial;">#</span><br /><span style="font-family: arial;">interface(`gitd_relabel_shared_content', `</span><br /><span style="font-family: arial;"> gen_require(`</span><br /><span style="font-family: arial;"> type gitd_shared_t;</span><br /><span style="font-family: arial;"> ')</span><br /><br /><span style="font-family: arial;"> relabel_dirs_pattern($1, gitd_shared_t, gitd_shared_t)</span><br /><span style="font-family: arial;"> relabel_files_pattern($1, gitd_shared_t, gitd_shared_t)</span><br /><span style="font-family: arial;"> files_search_var($1)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">########################################</span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## Allow the specified domain to relabel</span><br /><span style="font-family: arial;">## Git daemon personal content.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## <param name="domain"></span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## Domain allowed access.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## </param></span><br /><span style="font-family: arial;">## <rolecap/></span><br /><span style="font-family: arial;">#</span><br /><span style="font-family: arial;">interface(`gitd_relabel_personal_content', `</span><br /><span style="font-family: arial;"> gen_require(`</span><br /><span style="font-family: arial;"> type gitd_personal_t;</span><br /><span style="font-family: arial;"> ')</span><br /><br /><span style="font-family: arial;"> relabel_dirs_pattern($1, gitd_personal_t, gitd_personal_t)</span><br /><span style="font-family: arial;"> relabel_files_pattern($1, gitd_personal_t, gitd_personal_t)</span><br /><span style="font-family: arial;"> files_search_home($1)</span><br /><span style="font-family: arial;">')</span><br /><br /><span style="font-family: arial;">########################################</span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## All of the rules required to administrate an</span><br /><span style="font-family: arial;">## Git daemon system environment</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## <param name="userdomain_prefix"></span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## Prefix of the domain. Example, user would be</span><br /><span style="font-family: arial;">## the prefix for the user_t domain.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## </param></span><br /><span style="font-family: arial;">## <param name="domain"></span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## Domain allowed access.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## </param></span><br /><span style="font-family: arial;">## <param name="role"></span><br /><span style="font-family: arial;">## <summary></span><br /><span style="font-family: arial;">## The role to be allowed to manage the Git daemon domain.</span><br /><span style="font-family: arial;">## </summary></span><br /><span style="font-family: arial;">## </param></span><br /><span style="font-family: arial;">## <rolecap/></span><br /><span style="font-family: arial;">#</span><br /><span style="font-family: arial;">interface(`gitd_system_admin', `</span><br /><span style="font-family: arial;"> gen_require(`</span><br /><span style="font-family: arial;"> type gitd_system_t, gitd_exec_t;</span><br /><span style="font-family: arial;"> ')</span><br /><br /><span style="font-family: arial;"> allow $1 gitd_system_t:process { getattr ptrace signal_perms };</span><br /><br /><span style="font-family: arial;"> kernel_search_proc($1)</span><br /><span style="font-family: arial;"> allow $1 git_system_t:dir list_dir_perms;</span><br /><span style="font-family: arial;"> read_files_pattern($1, gitd_system_t, gitd_system_t)</span><br /><span style="font-family: arial;"> read_lnk_files_pattern($1, gitd_system_t, gitd_system_t)</span><br /><br /><span style="font-family: arial;"> manage_files_pattern($1, gitd_exec_t, gitd_exec_t)</span><br /><br /><span style="font-family: arial;"> # This will not work since git-shell needs to execute gitd content thus public content files.</span><br /><span style="font-family: arial;"> # There is currently no clean way to execute public content files.</span><br /><span style="font-family: arial;"> # miscfiles_manage_public_files($1)</span><br /><br /><span style="font-family: arial;"> gitd_manage_shared_content($1)</span><br /><span style="font-family: arial;"> gitd_relabel_shared_content($1)</span><br /><br /><span style="font-family: arial;"> seutil_domtrans_setfiles($1)</span><br /><span style="font-family: arial;">')</span><br /><span style="font-family: arial;">[/code]</span><br /><br /><span style="font-family: arial;">gitd.fc</span><br /><span style="font-family: arial;">[code]HOME_DIR/public_git(/.*)? gen_context(system_u:object_r:gitd_personal_t, s0)</span><br /><span style="font-family: arial;">HOME_DIR/\.gitconfig -- gen_context(system_u:object_r:gitd_personal_t, s0)</span><br /><br /><span style="font-family: arial;">/srv/git(/.*)? gen_context(system_u:object_r:gitd_shared_t, s0)</span><br /><br /><span style="font-family: arial;">/usr/libexec/git-core/git-daemon -- gen_context(system_u:object_r:gitd_exec_t, s0)</span><br /><br /><span style="font-family: arial;"># Conflict with Fedora cgit fc spec.</span><br /><span style="font-family: arial;"># /var/lib/git(/.*)? gen_context(system_u:object_r:gitd_shared_t, s0)</span><br /><span style="font-family: arial;">[/code]</span><br /><br /><span style="font-family: arial;">I manually labelled tcp:9418 gitd_port_t</span><br /><span style="font-family: arial;">[code]</span><br /><span style="font-family: arial;">semanage port -a -t gitd_port_t -p tcp 9418</span><br /><span style="font-family: arial;">[/code]</span><br /><br />I also manually added a SELinux user mapping:<br /><br />semanage user -a -L s0 -r s0 -R "gits_r" -P gits_u<br /><br />echo "system_r:sshd_t:s0 gits_r:gits_t:s0" > /etc/selinux/targeted/contexts/users/gits_u<br /><br /><span style="font-family: arial;">I edited /etc/xinetd.d/git:</span><br /><span style="font-family: arial;">[code]</span><br /></span><pre class="bz_comment_text" id="comment_text_0"><span style="font-size:85%;"><span style="font-family: arial;"># default: off</span><br /><span style="font-family: arial;"># description: The git dæmon allows git repositories to be exported using \</span><br /><span style="font-family: arial;"># the git:// protocol.</span><br /><br /><span style="font-family: arial;">service git</span><br /><span style="font-family: arial;">{</span><br /><span style="font-family: arial;"> disable = no</span><br /><span style="font-family: arial;"> socket_type = stream</span><br /><span style="font-family: arial;"> type = UNLISTED</span><br /><span style="font-family: arial;"> port = 9418</span><br /><span style="font-family: arial;"> wait = no</span><br /><span style="font-family: arial;"> user = nobody</span><br /><span style="font-family: arial;"># server = /usr/bin/git</span><br /><span style="font-family: arial;"># server_args = daemon --base-path=/srv/git --export-all</span><br /><span style="font-family: arial;">--user-path=public_git --syslog --inetd --verbose</span><br /><span style="font-family: arial;"> server = /usr/libexec/git-core/git-daemon</span><br /><span style="font-family: arial;"> server_args = --base-path=/srv/git --export-all</span><br /><span style="font-family: arial;">--user-path=public_git --syslog --inetd --verbose</span><br /><span style="font-family: arial;"> log_on_failure += USERID</span><br /><span style="font-family: arial;"># xinetd doesn't do this by default. </span><span style="font-family: arial;" class="bz_closed"><a href="https://bugzilla.redhat.com/show_bug.cgi?id=195265" title="CLOSED ERRATA - xinetd doesn't listen on IPv6 by default.">bug #195265</a></span><br /><span style="font-family: arial;"> flags = IPv6</span><br /><span style="font-family: arial;">}</span><br /><span style="font-family: arial;">[/code]</span><br /><br /><span style="font-family: arial;">Basically the selinux policy has 3 parts. one part is for the gitd system inetd server. the second part is for running gitd as a unprivileged user, and the third part is policy for the system wide git-shell environment.<br />So we secure the system wide gitd process, gitd process that users run and the git-shell process that is used to push pull to shared repositories.<br /><br />When you compile git-daemon, configured it like above and install the selinux module, restore the contexts of the paths in gitd.fc. then start xinetd: youll notice that inetd_t is not allowed to bind to gitd_port_t.<br />You can simply use audit2allow with the -M option to allow inetd_t to bind to gitd_port on behalf of gitd_system_t<br /><br />I use DAC to give usergroups access to the particular repositories and i use git ACL to restrict access to branches, tags etc.<br /><br />I used this great web site do implement this:<br /><br />http://www.kernel.org/pub/software/scm/git/docs/everyday.html<br /><br />I wrote two simple scripts:<br /><br />1. to add new users<br />2. to add new repostiries<br /><br />create_repository:<br /><br />crepo.sh:<br />[code]<br />#!/bin/bash<br /><br /># crepo.sh <repository><br /><br />groupadd $1 || exit 1;<br />usermod -a -G $1 badabing || exit 1;<br /><br />mkdir /srv/git/$1.git || exit 1;<br />chmod -R +t /srv/git/$1.git || exit 1;<br />cd /srv/git/$1.git && git --bare init || exit 1;<br /><br />cp /home/dgrift/create_repository/update /srv/git/$1.git/hooks/ || exit 1;<br />cp /home/dgrift/create_repository/allowed-users /srv/git/$1.git/info/ || exit 1;<br /><br />chown -R nobody:$1 /srv/git/$1.git || exit 1;<br /><br />chmod -R g+s /srv/git/$1.git/branches || exit 1;<br />chmod -R g+s /srv/git/$1.git/hooks || exit 1;<br />chmod -R g+s /srv/git/$1.git/info || exit 1;<br />chmod -R g+s /srv/git/$1.git/objects || exit 1;<br />chmod -R g+s /srv/git/$1.git/refs || exit 1;<br />chmod -R g+w /srv/git/$1.git || exit 1;<br /><br />exit 0;<br /><br />#EOF<br />[/code]<br /><br />This script installs the git ACL files update and allowed-users:<br /><br />update:<br />[code]<br />http://www.kernel.org/pub/software/scm/git/docs/howto/update-hook-example.txt<br />[/code]<br /><br />allowed-users:<br />[code]<br />refs/heads/master badabing<br />+refs/heads/pu badabing<br />refs/heads/bw/.* badabing<br />refs/heads/tmp/.* .*<br />refs/tags/v[0-9].* badabing<br />[/code]<br /><br />I also created a script to do part of what is required to add new users (i havent tested this script yet:<br /><br />[code]<br />#!/bin/bash<br /><br /># agits.sh <username> <repository><br /><br />useradd -Z gits_u -s /usr/bin/git-shell $1 || exit 1;<br />usermod -a -G sshusers,$2 $1 || exit 1;<br /><br />echo "Do not forget to set a password!"<br />echo "Manually add entries for $1 in /etc/security/namespace.conf!"<br />echo "You may need to edit /srv/git/$2.git/info/allowed-users!"<br /><br /># TODO: usrquota<br /><br />exit 0;<br />[/code]<br /><br />By the way xinetd and selinux dont play nice so you may need to edit the xinetd init script:<br /><br />[code]<br />https://bugzilla.redhat.com/show_bug.cgi?id=529681<br />[/code]<br /><br />So that is basically it.<br />The SELinux policy for the git system service should work by default. Additionally there are some booleans to to toggle for example to allow the git system service to also host personal repositories in ~/public_git, allow git to use any unreserved port for mass git repostory hosting. enable disable transition to git_session_t which is the user daemon.<br />For this to work you must also enable git policy for users by creating a module:<br /><br />for example if you want unconfined users to transition to git domain if they run git daemon <...><br /><br />myunconfined.te:<br />[code]<br />policy_module(myunconfined, 0.0.1)<br />optional_policy(`<br />gen_require(`<br /> type unconfined_t;<br />')<br /><br />git_session_role(unconfined_r, unconfined_t)<br />[/code]<br /><br />build and install that:<br /><br />make -f /usr/share/selinux/devel/Makefile<br />sudo semodule -i myunconfined.pp<br /><br />That should work and make unconfined_t users transition to git_session_t when they run git daemon <...><br /><br />For me this setup works, but i have not thoroughly tested the git_session_t domain yet.<br /><br />Would be nice to get some feedback so that i can improve this.<br /><br /><br />The git selinux policy is malformed above use the command below to pull the current gitd policy from my git repository<br /><br />git clone git://</span></span><span style="display: inline;" id="ip"><span style="font-size:85%;"><span style="font-family: arial;">82.197.205.60/selinux-modules.git</span><br /></span><br /></span></pre>Dominick "domg472" Grifthttp://www.blogger.com/profile/11819170833190325982noreply@blogger.com0