From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from pigeon.gentoo.org ([208.92.234.80] helo=lists.gentoo.org) by finch.gentoo.org with esmtp (Exim 4.60) (envelope-from <gentoo-commits+bounces-338282-garchives=archives.gentoo.org@lists.gentoo.org>) id 1QDb7X-0006AQ-Fc for garchives@archives.gentoo.org; Sat, 23 Apr 2011 11:35:34 +0000 Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id B1C4A1C019; Sat, 23 Apr 2011 11:35:19 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) by pigeon.gentoo.org (Postfix) with ESMTP id 326FB1C019 for <gentoo-commits@lists.gentoo.org>; Sat, 23 Apr 2011 11:35:19 +0000 (UTC) Received: from pelican.gentoo.org (unknown [66.219.59.40]) (using TLSv1 with cipher ADH-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 615A51B4017 for <gentoo-commits@lists.gentoo.org>; Sat, 23 Apr 2011 11:35:18 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by pelican.gentoo.org (Postfix) with ESMTP id C90D18034E for <gentoo-commits@lists.gentoo.org>; Sat, 23 Apr 2011 11:35:17 +0000 (UTC) From: "Sven Vermeulen" <sven.vermeulen@siphos.be> To: gentoo-commits@lists.gentoo.org Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Sven Vermeulen" <sven.vermeulen@siphos.be> Message-ID: <bdb128145f81f05f094fb220d4df1a1768458779.SwifT@gentoo> Subject: [gentoo-commits] proj/hardened-docs:master commit in: html/ X-VCS-Repository: proj/hardened-docs X-VCS-Files: html/selinux-development.html X-VCS-Directories: html/ X-VCS-Committer: SwifT X-VCS-Committer-Name: Sven Vermeulen X-VCS-Revision: bdb128145f81f05f094fb220d4df1a1768458779 Date: Sat, 23 Apr 2011 11:35:17 +0000 (UTC) Precedence: bulk List-Post: <mailto:gentoo-commits@lists.gentoo.org> List-Help: <mailto:gentoo-commits+help@lists.gentoo.org> List-Unsubscribe: <mailto:gentoo-commits+unsubscribe@lists.gentoo.org> List-Subscribe: <mailto:gentoo-commits+subscribe@lists.gentoo.org> List-Id: Gentoo Linux mail <gentoo-commits.gentoo.org> X-BeenThere: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: quoted-printable X-Archives-Salt: X-Archives-Hash: 320a4e6574162eb37fb40358ec906a0c commit: bdb128145f81f05f094fb220d4df1a1768458779 Author: Sven Vermeulen <sven.vermeulen <AT> siphos <DOT> be> AuthorDate: Sat Apr 23 11:32:27 2011 +0000 Commit: Sven Vermeulen <sven.vermeulen <AT> siphos <DOT> be> CommitDate: Sat Apr 23 11:32:27 2011 +0000 URL: http://git.overlays.gentoo.org/gitweb/?p=3Dproj/hardened-docs= .git;a=3Dcommit;h=3Dbdb12814 update previews --- html/selinux-development.html | 654 +++++++++++++++++++++++++++++++++++= +++--- 1 files changed, 618 insertions(+), 36 deletions(-) diff --git a/html/selinux-development.html b/html/selinux-development.htm= l index 72f7a56..9767824 100644 --- a/html/selinux-development.html +++ b/html/selinux-development.html @@ -97,6 +97,12 @@ highlights... <span class=3D"emphasis">interface file</span> which can then be cal= led by other modules. This includes the necessary permissions to allow domain transitions </li> + <li> + SELinux uses attributes to make multiple domains manageable. Domains= can + have certain permissions against all domains or types that are given= a + particular attribute. Be aware of this when you start assigning attr= ibutes + to your own types or domains. + </li> </ul> <p class=3D"chaphead"><a name=3D"doc_chap2"></a><span class=3D"chapnum">= 2. </span>Setting Up Your Environment</p> @@ -209,14 +215,14 @@ one: <a name=3D"doc_chap2_pre4"></a><table class=3D"ntable" width=3D"100%" ce= llspacing=3D"0" cellpadding=3D"0" border=3D"0"> <tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing2.4: Sett= ing up a local workspace</p></td></tr> <tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> -~$ <span class=3D"code-input">mkdir dev/local</span> -~$ <span class=3D"code-input">cp -r dev/hardened/strict dev/local/</span= > +~$ <span class=3D"code-input">cd dev/hardened</span> +~$ <span class=3D"code-input">cp -r strict strict.local/</span> </pre></td></tr> </table> <p class=3D"secthead"><a name=3D"doc_chap2_sect4">Navigating the policy = workspace</a></p> <p> The main location you will work with is -<span class=3D"path" dir=3D"ltr">dev/local/strict/policy/modules</span>.= This location is subdivided in +<span class=3D"path" dir=3D"ltr">dev/hardened/strict.local/policy/module= s</span>. This location is subdivided in categories: </p> <dl> @@ -244,7 +250,7 @@ Inside the categories, the modules are available usin= g their three files <a name=3D"doc_chap2_pre5"></a><table class=3D"ntable" width=3D"100%" ce= llspacing=3D"0" cellpadding=3D"0" border=3D"0"> <tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing2.5: List= ing the available sudo files</p></td></tr> <tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> -~$ <span class=3D"code-input">cd dev/local/strict/policy/modules/admin</= span> +~$ <span class=3D"code-input">cd dev/hardened/strict.local/policy/module= s/admin</span> ~$ <span class=3D"code-input">ls sudo.*</span> sudo.fc sudo.if sudo.te </pre></td></tr> @@ -257,7 +263,7 @@ To build a module, go to the location where the modul= e code is. Then, run <a name=3D"doc_chap2_pre6"></a><table class=3D"ntable" width=3D"100%" ce= llspacing=3D"0" cellpadding=3D"0" border=3D"0"> <tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing2.6: Buil= ding the portage module</p></td></tr> <tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> -~$ <span class=3D"code-input">cd dev/local/strict/policy/modules/admin</= span> +~$ <span class=3D"code-input">cd dev/hardened/strict.local/policy/module= s/admin</span> ~$ <span class=3D"code-input">make -f ../../../support/Makefile.devel po= rtage.pp</span> </pre></td></tr> </table> @@ -272,7 +278,7 @@ If you want to build the base policy, run <span class= =3D"code" dir=3D"ltr">make base <a name=3D"doc_chap2_pre7"></a><table class=3D"ntable" width=3D"100%" ce= llspacing=3D"0" cellpadding=3D"0" border=3D"0"> <tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing2.7: Buil= ding the base policy</p></td></tr> <tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> -~$ <span class=3D"code-input">cd dev/local/strict</span> +~$ <span class=3D"code-input">cd dev/hardened/strict.local</span> ~$ <span class=3D"code-input">make base</span> </pre></td></tr> </table> @@ -406,7 +412,9 @@ find the AVC denials you are looking for. <p> The next step is to see if we are dealing with the right security contex= ts. This does require a bit of insight in how both the application (that is faili= ng) and -the policy relate to each other. +the policy relate to each other. In essence, you want to make sure that = the +process is running in the right domain and is trying to work on the righ= t target +type. </p> <p> Say you are having issues with SELinux (re)labeling and you notice the f= ollowing @@ -557,7 +565,7 @@ creating an additional domain or type can be benefici= al. <p> A noticeable example is Portage' support for CVS/SVN/GIT ebuilds (the so= -called live ebuilds). These ebuilds get their repository and store it in the -<span class=3D"path" dir=3D"ltr">distfiles/svn+src</span> location, whic= h was by default labelled +<span class=3D"path" dir=3D"ltr">distfiles/svn+src</span> location, whic= h was by default labeled <span class=3D"path" dir=3D"ltr">portage_ebuild_t</span> with only read-= access for the <span class=3D"path" dir=3D"ltr">portage_sandbox_t</span> domain. Howeve= r, with those live ebuilds, the <span class=3D"path" dir=3D"ltr">portage_sandbox_t</span> domain also ne= eds write privileges to this @@ -573,67 +581,641 @@ need to create the proper interface functions in t= he target domain and call these functions from the source domain. </p> <p> -TODO extend this explanation, use a common example, like mysql_stream_co= nnect in -postfix. +Interface functions are the APIs that a module provides towards other SE= Linux +modules when they need to interact with the domains. For instance, the +<span class=3D"path" dir=3D"ltr">mysql</span> module provides, amongst o= ther functions, the +<span class=3D"code" dir=3D"ltr">mysql_stream_connect</span> interface: +</p> +<a name=3D"doc_chap3_pre12"></a><table class=3D"ntable" width=3D"100%" c= ellspacing=3D"0" cellpadding=3D"0" border=3D"0"> +<tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing3.12: mys= ql_stream_connect interface</p></td></tr> +<tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> +######################################## +## <summary> +## Connect to MySQL using a unix domain stream socket. +## </summary> +## <param name=3D"domain"> +## <summary> +## Domain allowed access. +## </summary> +## </param> +## <rolecap/> +# +interface(`mysql_stream_connect',` + gen_require(` + type mysqld_t, mysqld_var_run_t, mysqld_db_t; + ') + + stream_connect_pattern($1, mysqld_var_run_t, mysqld_var_run_t, m= ysqld_t) + stream_connect_pattern($1, mysqld_db_t, mysqld_var_run_t, mysqld= _t) +') +</pre></td></tr> +</table> +<p> +The interface declares that the domain passed on as its first (and only) +argument gets the rights offered by <span class=3D"code" dir=3D"ltr">str= eam_connect_pattern</span>, which is a +macro (defined in <span class=3D"path" dir=3D"ltr">policy/support/ipc_pa= tterns.spt</span> that looks like +so: +</p> +<a name=3D"doc_chap3_pre13"></a><table class=3D"ntable" width=3D"100%" c= ellspacing=3D"0" cellpadding=3D"0" border=3D"0"> +<tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing3.13: str= eam_connect_pattern</p></td></tr> +<tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> +define(`stream_connect_pattern',` + allow $1 $2:dir search_dir_perms; + allow $1 $3:sock_file write_sock_file_perms; + allow $1 $4:unix_stream_socket connectto; +') +</pre></td></tr> +</table> +<p> +Modules that need to interact with MySQL through a Unix domain stream so= cket +(<span class=3D"path" dir=3D"ltr">/var/run/mysqld/mysqld.sock</span>) wi= ll need the proper permissions to +work with the target type (<span class=3D"path" dir=3D"ltr">mysqld_var_r= un_t</span>). Modules cannot just +set <span class=3D"emphasis">allow</span> statements towards <span class= =3D"path" dir=3D"ltr">mysqld_var_run_t</span> as they do not +know this type. Instead, they call the <span class=3D"code" dir=3D"ltr">= mysql_stream_connect</span> interface, +like the <span class=3D"path" dir=3D"ltr">postfix.te</span> file does: </p> +<a name=3D"doc_chap3_pre14"></a><table class=3D"ntable" width=3D"100%" c= ellspacing=3D"0" cellpadding=3D"0" border=3D"0"> +<tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing3.14: Pos= tfix module calling mysql_stream_connect</p></td></tr> +<tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> +optional_policy(` + mysql_stream_connect(postfix_master_t) + mysql_stream_connect(postfix_cleanup_t) + mysql_stream_connect(postfix_local_t) +') +</pre></td></tr> +</table> <p> -TODO explain that changes in the interface require rebuilds and reinstal= lations -of the base (package, not only .pp file, due to includes). tell that thi= s is the -reason why selinux-base-policy has that many revisions. +If the change you need is adding existing interface calls to the module = (in=20 +the <span class=3D"path" dir=3D"ltr">.te</span> file) then you should be= able to test it easily by building +the changed module and loading it. However, if you need to change the in= terface +of your module itself (in the <span class=3D"path" dir=3D"ltr">.if</span= > file) you will eventually need +to rebuild the base policy and even provide and install a new +<span class=3D"path" dir=3D"ltr">sec-policy/selinux-base-policy</span> p= ackage as the interfaces are placed +in <span class=3D"path" dir=3D"ltr">/usr/share/selinux/strict/include</s= pan>. This is one of the reasons +why the <span class=3D"path" dir=3D"ltr">sec-policy/selinux-base-policy<= /span> package in Gentoo Hardened +has a high revision number (and many updates). </p> <p class=3D"chaphead"><a name=3D"doc_chap4"></a><span class=3D"chapnum">= 4. </span>No Domain Exists (Yet)</p> <p class=3D"secthead"><a name=3D"doc_chap4_sect1">Reuse existing domains= </a></p> <p> -TODO talk about potentially reusing domains (like apache module providin= g the -various httpd_* domains which can be reused by lighttpd). Talk about ass= igning -the proper labels to the files to see if that is sufficient. +If you are facing problems because you run an application which has no d= omain +itself (and hence is probably running in the <span class=3D"path" dir=3D= "ltr">user_t</span>, +<span class=3D"path" dir=3D"ltr">staff_t</span> or <span class=3D"path" = dir=3D"ltr">sysadm_t</span> domains - or even tries to run in +the <span class=3D"path" dir=3D"ltr">initrc_t</span> domain), you will n= eed to create one. But before we do +that, it might be possible that the application can work within the doma= in +definition of a different application. </p> -<p class=3D"secthead"><a name=3D"doc_chap4_sect2">Copy from existing dom= ains</a></p> <p> -TODO talk about finding a similar module (apps or service) and start fro= m a -(slimmed-down) domain. Not recommended as it might already open too much= , but it -is a good start, if not to just look at with every denial you get later.= Keep it -short, most information is in next section. +One example here is lighttpd. This lightweight HTTPd service "uses" the +definitions offered by the <span class=3D"path" dir=3D"ltr">apache</span= > module. By marking its executable +file <span class=3D"path" dir=3D"ltr">httpd_exec_t</span> it runs in the= <span class=3D"path" dir=3D"ltr">httpd_t</span> domain and +uses the same policy like Apache. By labeling the files according to the +<span class=3D"path" dir=3D"ltr">apache.fc</span> definitions (but now f= or lighttpd) it might Just Work +=E2=84=A2 +</p> +<p> +Reusing existing domains requires that you at least consider the followi= ng +aspects: +</p> +<ul> + <li> + Will the application run on the same system as the application for w= hich the + domain is originally intended? If so, then both might run in the sam= e domain + (and as such have more privileges towards each other than intended) = which + might not be what you want. + </li> + <li> + Do you need to enhance (read: add additional privileges) the master = domain? + If so, make sure that you don't add more privileges than the origina= l domain + would ever need to the extend that these privileges become a securit= y risk. + </li> +</ul> +<p class=3D"secthead"><a name=3D"doc_chap4_sect2">(Do Not) Copy from exi= sting domains</a></p> +<p> +If reusing existing domains introduces too many risks, you'll need to cr= eate a +new domain for the application. Many people would be inclined to copy th= e domain +definition of a similar application and work from there. Although this i= s a +viable approach, it is considered a bad practice because you start by pr= oviding +privileges to the domain that are never needed, and removing privileges = from a +domain later is very difficult. Even more, if you are not the author of = the +modules, most developers will not even try to remove them as they assume= that +the author of the domain had a good reason to add it in the first place.= This is +one of the reasons why upstream takes great care in accepting patches - = they +must be properly documented before they are accepted. +</p> +<p> +Instead, create a domain from scratch but take a close eye on the domain= you +belief is very similar. Issues that arise during the module development = might be +quickly resolved by looking at how the original domain is defined. </p> <p class=3D"secthead"><a name=3D"doc_chap4_sect3">Starting from scratch<= /a></p> <p> -TODO talk about defining the proper domains, set proper types (like file= _type or -application_type), refer to refpolicy guidelines +To start the development of a new module from scratch, first identify th= e +domain(s) you want to have. An application that, in its entire lifespan = only +constitutes of a single process, will most likely only have one domain. = For +instance, the Skype client will have just <span class=3D"path" dir=3D"lt= r">skype_t</span>. However, +applications that have multiple processes running might need multiple do= mains +too. For instance, the Postfix application runs a master +(<span class=3D"path" dir=3D"ltr">postfix_master_t</span>), queue manage= r (<span class=3D"path" dir=3D"ltr">postfix_qmgr_t</span>) and +pickup service (<span class=3D"path" dir=3D"ltr">postfix_pickup_t</span>= ), but depending on the commands +you execute, it will also have (short-lived) processes running as +<span class=3D"path" dir=3D"ltr">postfix_cleanup_t</span>, <span class=3D= "path" dir=3D"ltr">postfix_bounce_t</span>, etc.) It is +considered a best practice to start with a fine-grained model for domain= s +and only later decide if merging multiple domains into one is beneficial= . +Splitting domains later is more difficult. Don't forget to look at the +client-side aspect too! +</p> +<p> +Next, define the types that each domain interacts with. This of course i= ncludes +the binary (like <span class=3D"path" dir=3D"ltr">skype_exec_t</span>) b= ut do not forget resources like +</p> +<ul> + <li> + The configuration file(s) in <span class=3D"path" dir=3D"ltr">/etc</= span> (f.i. + <span class=3D"path" dir=3D"ltr">postfix_etc_t</span>) + </li> + <li> + PID files (f.i. <span class=3D"path" dir=3D"ltr">sshd_var_run_t</spa= n>) + </li> + <li> + Spool files (f.i. <span class=3D"path" dir=3D"ltr">postfix_spool_t</= span>) + </li> + <li> + Variable data files (f.i. <span class=3D"path" dir=3D"ltr">snmpd_var= _lib_t</span>) + </li> + <li> + Log files (f.i. <span class=3D"path" dir=3D"ltr">zebra_log_t</span>) + </li> + <li> + Cache files (f.i. <span class=3D"path" dir=3D"ltr">squid_cache_t</sp= an>) + </li> + <li> + (User) content files (f.i. <span class=3D"path" dir=3D"ltr">httpd_sy= s_content_t</span> and + <span class=3D"path" dir=3D"ltr">httpd_user_content_t</span>) + </li> +</ul> +<p> +Also, try to separate types that are used by other domains as well. This= way, +the other domains can only interact with those files or resources that a= re +labeled accordingly, rather than interact with a broad spectrum of files= . The +distinction that the <span class=3D"path" dir=3D"ltr">apache</span> modu= le makes between system-provided +content (like phpmyadmin files) and user-provided content (in the +<span class=3D"path" dir=3D"ltr">public_html</span> directory in the use= rs' home directories) seems (and +is) very logical, but one could wrongly say that for Apache itself, the = access +controls are the same. Although that might be true, both types are clear= ly used +in different ways so this mandates the use of different domains. +</p> +<p> +Once you have defined those types too, start writing down the intra-doma= in +permissions. Right now is a good time to look at other modules to see ho= w they +do things. Start with defining the accesses towards the domains. +</p> +<a name=3D"doc_chap4_pre1"></a><table class=3D"ntable" width=3D"100%" ce= llspacing=3D"0" cellpadding=3D"0" border=3D"0"> +<tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing4.1: Snip= pet from the spamassassin module</p></td></tr> +<tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> +type spamassassin_t; +type spamassassin_exec_t; +application_domain(spamassassin_t, spamassassin_exec_t) +ubac_constrained(spamassassin_t) +</pre></td></tr> +</table> +<p> +This small snippet defines many things. The first two lines just mention= the new +types (the <span class=3D"path" dir=3D"ltr">spamassassin_t</span> domain= and +<span class=3D"path" dir=3D"ltr">spamassassin_exec_t</span> type). The <= span class=3D"code" dir=3D"ltr">application_domain</span> interface +marks <span class=3D"path" dir=3D"ltr">spamassassin_t</span> as an appli= cation domain type (it gets the +<span class=3D"path" dir=3D"ltr">application_domain_type</span> and <spa= n class=3D"path" dir=3D"ltr">domain</span> attributes and a +few default permissions (like allowing that it sends SIGCHLD and SIGNULL= to +init). It also marks <span class=3D"path" dir=3D"ltr">spamassassin_exec_= t</span> as an applications' +executable type (<span class=3D"path" dir=3D"ltr">application_exec_type<= /span> and <span class=3D"path" dir=3D"ltr">exec_type</span> +attributes) so that it can be executed by regular users (these domains h= ave +execute rights against all resources that have the +<span class=3D"path" dir=3D"ltr">application_exec_type</span> attribute = set. Finally, it marks the +<span class=3D"path" dir=3D"ltr">spamassassin_t</span> domain as a const= rained domain for user-based access +controls. In other words, if SELinux users <span class=3D"path" dir=3D"l= tr">user_u</span> and +<span class=3D"path" dir=3D"ltr">staff_u</span> launch the application i= n <span class=3D"path" dir=3D"ltr">spamassassin_t</span> +domains, then the domains are segregated from each other (the intra-doma= in rules +inside <span class=3D"path" dir=3D"ltr">spamassassin_t</span> are only v= alid for communication within the +same SELinux user, not between SELinux users). +</p> +<p> +Attributes are an important aspect in SELinux policy development. They m= ake +managing the domains easier, but you should always consider the implicat= ions +when you add an attribute to one of your types. It usually means that a = whole +lot of permissions are suddenly granted between other domains and yours. +</p> +<p> +Next, set the proper intra-domain permissions. For instance, allow your = domain +to read its configuration files as well as more access inside its own +<span class=3D"path" dir=3D"ltr">/var/lib</span> location: +</p> +<a name=3D"doc_chap4_pre2"></a><table class=3D"ntable" width=3D"100%" ce= llspacing=3D"0" cellpadding=3D"0" border=3D"0"> +<tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing4.2: Snip= pet from openca module</p></td></tr> +<tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> +allow openca_ca_t openca_etc_t:file read_file_perms; +allow openca_ca_t openca_etc_t:dir list_dir_perms; + +manage_dirs_pattern(openca_ca_t, openca_var_lib_t, openca_var_lib_t) +manage_files_pattern(openca_ca_t, openca_var_lib_t, openca_var_lib_t) +</pre></td></tr> +</table> +<p> +The majority of work in developing SELinux policy modules is using and c= hoosing +the right interfaces. Having a few functions available to browse through= all the +available information is always interesting, so you might want to use th= e +following function definitions (definitely not mandatory - this is only = to help +people skim through the policy definitions): +</p> +<a name=3D"doc_chap4_pre3"></a><table class=3D"ntable" width=3D"100%" ce= llspacing=3D"0" cellpadding=3D"0" border=3D"0"> +<tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing4.3: SELi= nux policy development function definitions</p></td></tr> +<tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> +POLICY_LOCATION=3D"http://www.gentoo.org/path/to/your/refpolicy"; + +# sefindif - Find interface definitions that have a string that matches = the +# given regular expression +sefindif() { + REGEXP=3D"$1"; + cd ${POLICY_LOCATION}/policy/modules; + for FILE in */*.if; + do + awk "http://www.gentoo.org/(interface\(|template\()/ { NAME=3D\$NF; = P=3D0 }; /${REGEXP}/ { if (P=3D=3D0) {P=3D1; print NAME}; print };" ${FIL= E} | sed -e "s:^:${FILE}\: :g"; + done +} + +# seshowif - Show the interface definition +seshowif() { + INTERFACE=3D"$1"; + cd ${POLICY_LOCATION}/policy/modules; + for FILE in */*.if; + do + grep -A 9999 "\(interface(\`${INTERFACE}'\|template(\`${INTERFACE}'\= )" ${FILE} | grep -B 9999 -m 1 "^')"; + done +} + +# sefinddef - Find macro definitions that have a string that matches the= given +# regular expression +sefinddef() { + REGEXP=3D"$1"; + grep -H "define(\`.*${REGEXP}.*" ${POLICY_LOCATION}/policy/support/* |= sed -e 's:.*\/\([^(]*\):\1:g' +} + +# seshowdef - Show the macro definition +seshowdef() { + MACRONAME=3D"$1"; + cd ${POLICY_LOCATION}/policy/support; + for FILE in *.spt; + do + grep -A 9999 "define(\`${MACRONAME}'" ${FILE} | grep -B 999 -m 1 "')= "; + done +} +</pre></td></tr> +</table> +<p> +These functions can then be used to find the information / interfaces yo= u are +looking for. For instance, you need the application to read the postfix +configuration files: +</p> +<a name=3D"doc_chap4_pre4"></a><table class=3D"ntable" width=3D"100%" ce= llspacing=3D"0" cellpadding=3D"0" border=3D"0"> +<tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing4.4: Look= ing for the interface(s) needed</p></td></tr> +<tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> +~$ <span class=3D"code-input">sefindif postfix_etc_t</span> +services/postfix.if: template(`postfix_domain_template',` +services/postfix.if: allow postfix_$1_t postfix_etc_t:dir list_dir_pe= rms; +services/postfix.if: read_files_pattern(postfix_$1_t, postfix_etc_t, = postfix_etc_t) +services/postfix.if: read_lnk_files_pattern(postfix_$1_t, postfix_etc= _t, postfix_etc_t) +<span class=3D"code-comment">services/postfix.if: interface(`postfix_rea= d_config',` +services/postfix.if: type postfix_etc_t; +services/postfix.if: read_files_pattern($1, postfix_etc_t, postfix_et= c_t) +services/postfix.if: read_lnk_files_pattern($1, postfix_etc_t, postfi= x_etc_t)</span> +services/postfix.if: interface(`postfix_config_filetrans',` +services/postfix.if: type postfix_etc_t; +services/postfix.if: filetrans_pattern($1, postfix_etc_t, $2, $3) + +~$ <span class=3D"code-input">seshowif postfix_read_config</span> +interface(`postfix_read_config',` + gen_require(` + type postfix_etc_t; + ') + + read_files_pattern($1, postfix_etc_t, postfix_etc_t) + read_lnk_files_pattern($1, postfix_etc_t, postfix_etc_t) + files_search_etc($1) +') +</pre></td></tr> +</table> +<p> +Same thing if you want to look for the correct macro definition (usually= , if you +notice something but you cannot find it as an interface, then it is most= likely +a macro): +</p> +<a name=3D"doc_chap4_pre5"></a><table class=3D"ntable" width=3D"100%" ce= llspacing=3D"0" cellpadding=3D"0" border=3D"0"> +<tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing4.5: Look= ing for the right macros</p></td></tr> +<tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> +<span class=3D"code-comment"># Suppose you need to read, write, connect,= ... to a socket</span> +~$ <span class=3D"code-input">sefinddef connect</span> +ipc_patterns.spt:define(`stream_connect_pattern',` +<span class=3D"code-comment">obj_perm_sets.spt:define(`rw_socket_perms',= `{ ioctl read getattr write setattr append bind connect getopt setopt sh= utdown }')</span> +obj_perm_sets.spt:define(`connected_socket_perms', `{ create ioctl read = getattr write setattr append bind getopt setopt shutdown }') +obj_perm_sets.spt:define(`connected_stream_socket_perms', `{ connected_s= ocket_perms listen accept }') + +<span class=3D"code-comment"># To see what the ps_process_pattern is abo= ut</span> +~$ <span class=3D"code-input">seshowdef ps_process_pattern</span> +define(`ps_process_pattern',` + allow $1 $2:dir list_dir_perms; + allow $1 $2:file read_file_perms; + allow $1 $2:lnk_file read_lnk_file_perms; + allow $1 $2:process getattr; +') +</pre></td></tr> +</table> +<p> +As we strive to bring most of our patches upstream, please do consider t= he <a href=3D"http://oss.tresys.com/projects/refpolicy/wiki/HowToContribu= te">contribution +guidelines</a> of the reference policy project. The project has a docume= nted +style guide, naming convention and an online API reference (for the vari= ous +interfaces). +</p> +<p> +Note that, the moment you create a new module, you'll need to create the= proper +role interfaces (if it is an application that is directly called from a = user +domain). Take a look at <span class=3D"code" dir=3D"ltr">tvtime_role</sp= an> and how it is used in the +<span class=3D"path" dir=3D"ltr">staff.te</span> and <span class=3D"path= " dir=3D"ltr">sysadm.te</span> role definitions. </p> <p class=3D"secthead"><a name=3D"doc_chap4_sect4">Testing new modules</a= ></p> <p> -TODO talk about users trying to do maximum testing (all the way). Also, = if they -want to support unconfined domains too, how they can do this (and should= test). +When you test your application, test it in as many ways as possible. If = your +application is a command-line application, run it both from a regular te= rminal +(tty) as well as a virtual one (in an xterm). See if it still works if y= ou run +it in a screen session. Try out all functions and features that the appl= ication +supports. +</p> +<p> +This rigorous testing is necessary because SELinux denies everything tha= t isn't +explicitly allowed. If you do not test certain features, chances are tha= t the +module does not provide the necessary permissions and as such, users wil= l be +impacted. </p> +<p> +To test out a new module, load it (<span class=3D"code" dir=3D"ltr">semo= dule -i modulename.pp</span>) and relabel +the files affiliated with the application (either through <span class=3D= "code" dir=3D"ltr">rlpkg</span> or using +<span class=3D"code" dir=3D"ltr">restorecon</span>). Consider the follow= ing testing activities if applicable (not +all domains are interactive domains, so please read the activities with = your +domain definition in mind): +</p> +<ul> + <li> + Sending signals to the application (if you need to be able to kill i= t, try + killing it) + </li> + <li> + Run it both as a regular user (<span class=3D"path" dir=3D"ltr">user= _u</span>) as well as + administrative users (if applicable). If your domain needs to suppor= t + unconfined domains/users, run it from an unconfined user domain too. + </li> + <li> + Run it from a terminal, console, screen, sudo, ... + </li> + <li> + Change the applications' configuration file (including rendering it = useless + with syntax errors) and look at the applications' behavior. Especial= ly + syntax failures as that might trigger the application to log things = at + places that you haven't discovered earlier. + </li> +</ul> <p class=3D"chaphead"><a name=3D"doc_chap5"></a><span class=3D"chapnum">= 5. </span>Policy Guidelines</p> +<p class=3D"secthead"><a name=3D"doc_chap5_sect1">Cosmetic denials</a></= p> <p> -TODO dealing with cosmetic denials +When working on policy modules, you'll notice that the application is tr= ying to +do things which are denied, but have no obvious effect on the applicatio= ns +functionality. This is to be expected: many applications do not handle f= ile +descriptors properly (file descriptor leaks are common) or applications = read +attributes of files but don't do anything with it. You'll notice that yo= u learn +a lot from the application while writing its policy ;-) </p> <p> -TODO resources - gentoo selinux policy, refpolicy guidelines +Gentoo Hardened's idea here is to only allow what is actually needed by = the +application. Cosmetic denials are to be <span class=3D"code" dir=3D"ltr"= >dontaudit</span>'ed. Gentoo Hardened +uses the <span class=3D"code" dir=3D"ltr">gentoo_try_dontaudit</span> bo= olean for this: +</p> +<a name=3D"doc_chap5_pre1"></a><table class=3D"ntable" width=3D"100%" ce= llspacing=3D"0" cellpadding=3D"0" border=3D"0"> +<tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing5.1: Exam= ple usage of gentoo_try_dontaudit</p></td></tr> +<tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> +<span class=3D"code-comment"># Hide sshd_t calling module_request from t= he kernel_t domain</span> +tunable_policy(`gentoo_try_dontaudit',` + kernel_dontaudit_request_load_module(sshd_t) +') +</pre></td></tr> +</table> +<p class=3D"secthead"><a name=3D"doc_chap5_sect2">Gentoo Hardened SELinu= x policy</a></p> +<p> +To streamline the policy development efforts, Gentoo Hardened as a <a hr= ef=3D"selinux-policy.xml">SELinux Policy</a> document explaining the +principles used during policy development and the implementation guideli= nes we +strive to follow during development. +</p> +<p> +Such a policy is important because we want to have a consistent security= policy +that users and developers can relate to. By following the policy, we hop= e that +other developers can quickly jump in and work on it further. </p> <p class=3D"chaphead"><a name=3D"doc_chap6"></a><span class=3D"chapnum">= 6. </span>Submitting Patches</p> +<p class=3D"secthead"><a name=3D"doc_chap6_sect1">File context patches</= a></p> +<p> +If you are able to fix a problem by adding the proper file contexts (usi= ng +<span class=3D"code" dir=3D"ltr">semanage fcontext -a</span>), please co= nsider the following: +</p> +<ul> + <li> + If the location for which you set the context deviates from the stan= dard + location as either intended by the project or Gentoo itself, it migh= t be + best to document it in the forums or elsewhere. We will not change f= ile + contexts to match every ones configuration, unless the file context = change + is apparent for each installation. + </li> + <li> + Developers might not immediately push file context changes in new po= licy + module packages to keep the amount of policy module changes low. Ins= tead, + these changes can be stacked and pushed when other changes occur as = well. + </li> +</ul> <p> -TODO differentiate between base patch and module patch. +If you believe that the change is needed for everyone using Gentoo Harde= ned with +SELinux, create a <a href=3D"https://bugs.gentoo.org">bugreport</a> and = assign +it to <span class=3D"code" dir=3D"ltr">selinux@gentoo.org</span>. In the= bugreport, mention the file context you +think is necessary and why. </p> +<p class=3D"secthead"><a name=3D"doc_chap6_sect2">Module patches</a></p> <p> -TODO perhaps talk about file context patches. Perhaps we will not make a= new -build release for it, but stage it to be included in the next release wh= en a -non-filecontext patch is added? +Module patches with changes that are intra-module (and have no effect ou= tside) +are best generated from the <span class=3D"path" dir=3D"ltr">policy/modu= les</span> location: +</p> +<a name=3D"doc_chap6_pre1"></a><table class=3D"ntable" width=3D"100%" ce= llspacing=3D"0" cellpadding=3D"0" border=3D"0"> +<tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing6.1: Exam= ple generating patch for modular changes</p></td></tr> +<tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> +~$ <span class=3D"code-input">cd dev/hardened/strict.local/policy/module= s</span> +~$ <span class=3D"code-input">diff -ut ../../../strict/policy/modules/se= rvices/openct.te services/openct.te</span> +--- ../../../../strict/policy/modules/services/openct.te 2011-04-22 23= :28:17.932918002 +0200 ++++ services/openct.te 2011-04-23 09:55:08.156918002 +0200 +@@ -47,6 +47,10 @@ +=20 + miscfiles_read_localization(openct_t) +=20 ++tunable_policy(`gentoo_try_dontaudit',` ++ kernel_dontaudit_read_system_state(openct_t) ++') ++ + userdom_dontaudit_use_unpriv_user_fds(openct_t) + userdom_dontaudit_search_user_home_dirs(openct_t) +</pre></td></tr> +</table> +<p> +Attach this patch to the <a href=3D"https://bugs.gentoo.org">bugreport</= a> +explaining why it is needed. If you think the patch itself is not obviou= s, make +sure that the necessary comments are in place <span class=3D"emphasis">i= nside the patch</span> for future +reference. +</p> +<p> +Please have a separate patch file per module (do not combine multiple mo= dules in +a single patch). +</p> +<p class=3D"secthead"><a name=3D"doc_chap6_sect3">Base policy patches</a= ></p> +<p> +If a patch extends a single module, or it includes interface changes on = a +module, you'll need to create a patch for the base policy. In this case,= the +patch is best made from the upper location. +</p> +<a name=3D"doc_chap6_pre2"></a><table class=3D"ntable" width=3D"100%" ce= llspacing=3D"0" cellpadding=3D"0" border=3D"0"> +<tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing6.2: Gene= rating a base policy patch</p></td></tr> +<tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> +~$ <span class=3D"code-input">cd dev/hardened/strict.local</span> +~$ <span class=3D"code-input">diff -ut ../strict/policy/modules/services= /openct.if policy/modules/services/openct.if</span> +--- ../strict/policy/modules/services/openct.if 2011-04-22 23:28:17.9= 18918002 +0200 ++++ policy/modules/services/openct.if 2011-04-23 10:01:38.75391800= 1 +0200 +@@ -15,7 +15,7 @@ + type openct_t; + ') +=20 +- allow $1 openct_t:process signull; ++ allow $1 openct_t:process { signull sigchld }; + ') +=20 + ######################################## +</pre></td></tr> +</table> +<p> +Attach this patch to the <a href=3D"https://bugs.gentoo.org">bugreport</= a> +explaining why it is needed. If you think the patch itself is not obviou= s, make +sure that the necessary comments are in place <span class=3D"emphasis">i= nside the patch</span> for future +reference. +</p> +<p> +Please have a separate patch file per major change (do not combine multi= ple +unrelated changes in a single patch). </p> <p class=3D"chaphead"><a name=3D"doc_chap7"></a><span class=3D"chapnum">= 7. </span>Running Your Own Policy</p> +<p class=3D"secthead"><a name=3D"doc_chap7_sect1">Creating a local overl= ay</a></p> +<p> +If you want to use your own policy rather than Gentoo's, we seriously re= commend +to use a local overlay which uses the same package names and constructs.= This +allows your policy to integrate properly with the other Gentoo packages = (which +might depend on the SELinux packages). For instance, when you install op= enldap, +it will still properly depend on the <span class=3D"path" dir=3D"ltr">se= c-policy/selinux-ldap</span> +package even if you provide it completely. +</p> +<p> +To do so, first create a local overlay and copy the content of the +<span class=3D"path" dir=3D"ltr">sec-policy</span> category inside it. +</p> +<a name=3D"doc_chap7_pre1"></a><table class=3D"ntable" width=3D"100%" ce= llspacing=3D"0" cellpadding=3D"0" border=3D"0"> +<tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing7.1: Crea= ting a local overlay</p></td></tr> +<tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> +~$ <span class=3D"code-input">mkdir dev/overlay</span> +~$ <span class=3D"code-input">cp -r /usr/portage/sec-policy dev/overlay<= /span> +</pre></td></tr> +</table> +<p> +Next, tell Portage to not synchronise the <span class=3D"path" dir=3D"lt= r">sec-policy</span> category of +the main tree anymore. To do so, create the file +<span class=3D"path" dir=3D"ltr">/etc/portage/rsync_excludes</span> with= the following content: +</p> +<a name=3D"doc_chap7_pre2"></a><table class=3D"ntable" width=3D"100%" ce= llspacing=3D"0" cellpadding=3D"0" border=3D"0"> +<tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing7.2: Rsyn= c exclusion information</p></td></tr> +<tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> +sec-policy/ +</pre></td></tr> +</table> +<p> +Finally, add your current overlay by editing <span class=3D"path" dir=3D= "ltr">/etc/make.conf</span>: +</p> +<a name=3D"doc_chap7_pre3"></a><table class=3D"ntable" width=3D"100%" ce= llspacing=3D"0" cellpadding=3D"0" border=3D"0"> +<tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing7.3: Edit= ing make.conf</p></td></tr> +<tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> +PORTDIR_OVERLAY=3D"${PORTDIR_OVERLAY} /home/user/dev/overlay" +</pre></td></tr> +</table> +<p> +From now onwards, Gentoo Portage will only use your local overlay (you c= an +remove <span class=3D"path" dir=3D"ltr">/usr/portage/sec-policy</span> i= f you don't want Portage to even +reuse the current set of packages. +</p> +<p class=3D"secthead"><a name=3D"doc_chap7_sect2">Updating module packag= es</a></p> <p> -TODO describe how to create your own overlay with modules and patchbundl= es. Also -usable for developers to stage their ebuild / patch submissions before a= ctually -putting in git repo. Ensure that naming is consistent (so that ebuild -dependencies of packages remain). +To create or update a module package, you can use the following skeleton= for the +ebuilds: </p> +<a name=3D"doc_chap7_pre4"></a><table class=3D"ntable" width=3D"100%" ce= llspacing=3D"0" cellpadding=3D"0" border=3D"0"> +<tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing7.4: Skel= eton for ebuilds, example for postfix</p></td></tr> +<tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> +# Copyright 1999-2011 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +<span class=3D"code-comment"># Set the MODS variable to the refpolicy na= me used, so services/postfix.te gives "postfix"</span> +MODS=3D"postfix" +IUSE=3D"" + +inherit selinux-policy-2 + +DESCRIPTION=3D"SELinux policy for postfix" + +KEYWORDS=3D"~amd64 ~x86" + +<span class=3D"code-comment"># POLICY_PATCH is optional (only when you h= ave a patch), without it just uses the=20 +# refpolicy version.</span> +POLICY_PATCH=3D"${FILESDIR}/fix-services-postfix-r3.patch" +</pre></td></tr> +</table> +<p> +The patch(es) that you can put in the <span class=3D"path" dir=3D"ltr">f= iles/</span> location (and referred to +in the <span class=3D"code" dir=3D"ltr">POLICY_PATCH</span>) should be m= ade as defined earlier in this document. +You can put multiple patches in this variable if you want. +</p> +<p> +Don't forget to run <span class=3D"code" dir=3D"ltr">repoman manifest</s= pan> with every change, and run +<span class=3D"code" dir=3D"ltr">repoman scan</span> to check for potent= ial mistakes. +</p> +<p class=3D"secthead"><a name=3D"doc_chap7_sect3">Updating base package<= /a></p> +<p> +To provide updates on the base policy, it is recommended to keep all pat= ches you +made centrally in a directory (say <span class=3D"path" dir=3D"ltr">dev/= hardened/base-patches</span>). When +you want to create a new <span class=3D"path" dir=3D"ltr">sec-policy/sel= inux-base-policy</span> release, +create a patchbundle from your patch directory, put the bundle in the +<span class=3D"path" dir=3D"ltr">files</span> location, create the updat= ed ebuild and try it out. +</p> +<a name=3D"doc_chap7_pre5"></a><table class=3D"ntable" width=3D"100%" ce= llspacing=3D"0" cellpadding=3D"0" border=3D"0"> +<tr><td bgcolor=3D"#7a5ada"><p class=3D"codetitle">Code Listing7.5: Buil= ding a base policy package</p></td></tr> +<tr><td bgcolor=3D"#eeeeff" align=3D"left" dir=3D"ltr"><pre> +~$ <span class=3D"code-input">cd dev/hardened/base-patches</span> +~$ <span class=3D"code-input">tar cjvf ../overlay/sec-policy/selinux-bas= e-policy/files/patchbundle-selinux-base-policy-2.20101213-r13.tar.bz2 *</= span> +~$ <span class=3D"code-input">cd ../overlay/sec-policy/selinux-base-poli= cy</span> +~$ <span class=3D"code-input">cp selinux-base-policy-2.20101213-r12.ebui= ld selinux-base-policy-2.20101213-r13.ebuild</span> +</pre></td></tr> +</table> <p> -TODO describe how to exclude sec-policy in regular rsync +Don't forget to run <span class=3D"code" dir=3D"ltr">repoman manifest</s= pan> and <span class=3D"code" dir=3D"ltr">repoman scan</span>. You can +then install <span class=3D"path" dir=3D"ltr">sec-policy/selinux-base-po= licy-2.20101213-r13</span> and test +it out. </p> <br><p class=3D"copyright"> The contents of this document are licensed under the <a href=3D"http= ://creativecommons.org/licenses/by-sa/2.5">Creative Commons -