aboutsummaryrefslogtreecommitdiff
blob: c54b522609ebd0d22e3d79f019e0751f2efe337d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link title="new" rel="stylesheet" href="http://www.gentoo.org/css/main.css" type="text/css">
<link REL="shortcut icon" HREF="http://www.gentoo.org/favicon.ico" TYPE="image/x-icon">
<link rel="search" type="application/opensearchdescription+xml" href="http://www.gentoo.org/search/www-gentoo-org.xml" title="Gentoo Website">
<link rel="search" type="application/opensearchdescription+xml" href="http://www.gentoo.org/search/forums-gentoo-org.xml" title="Gentoo Forums">
<link rel="search" type="application/opensearchdescription+xml" href="http://www.gentoo.org/search/bugs-gentoo-org.xml" title="Gentoo Bugzilla">
<link rel="search" type="application/opensearchdescription+xml" href="http://www.gentoo.org/search/packages-gentoo-org.xml" title="Gentoo Packages">
<link rel="search" type="application/opensearchdescription+xml" href="http://www.gentoo.org/search/archives-gentoo-org.xml" title="Gentoo List Archives">
<title>Gentoo Linux Documentation
--
  Gentoo Hardened SELinux Development</title>
</head>
<body style="margin:0px;" bgcolor="#ffffff"><table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td valign="top" height="125" bgcolor="#45347b"><a href="http://www.gentoo.org/"><img border="0" src="http://www.gentoo.org/images/gtop-www.jpg" alt="Gentoo Logo"></a></td></tr>
<tr><td valign="top" align="right" colspan="1" bgcolor="#ffffff"><table border="0" cellspacing="0" cellpadding="0" width="100%"><tr>
<td width="99%" class="content" valign="top" align="left">
<br><h1>Gentoo Hardened SELinux Development</h1>
<form name="contents" action="http://www.gentoo.org">
<b>Content</b>:
        <select name="url" size="1" OnChange="location.href=form.url.options[form.url.selectedIndex].value" style="font-family:sans-serif,Arial,Helvetica"><option value="#doc_chap1">1. Introduction</option>
<option value="#doc_chap2">2. Setting Up Your Environment</option>
<option value="#doc_chap3">3. A Domain Does Not Function Properly</option>
<option value="#doc_chap4">4. No Domain Exists (Yet)</option>
<option value="#doc_chap5">5. Policy Guidelines</option>
<option value="#doc_chap6">6. Submitting Patches</option>
<option value="#doc_chap7">7. Running Your Own Policy</option></select>
</form>
<p class="chaphead"><a name="doc_chap1"></a><span class="chapnum">1.
            </span>Introduction</p>
<p class="secthead"><a name="doc_chap1_sect1">About this document...</a></p>
<p>
Dealing with Mandatory Access Control is never easy. SELinux might be available
by default with Linux, enabling it can provide serious headaches - let alone
developing policies for it. Within Gentoo Hardened, we strive to offer a default
policy that is flexible enough to match the requirements of most of you (our 
users) yet remain manageable by the limited number of developers that we have.
To ensure that the policy we offer is up to date, we definitely need help from
end users and other developers, because developing policies requires intimate 
knowledge of the products they are written for. With over several thousand 
packages, this is just not feasible for a handful of us. Hence, this Gentoo
Hardened SELinux Development guide.
</p>
<p>
Within this document, we will try to explain how to set up an environment ready
to build policies yourself and provide patches to Gentoo Hardened. We also cover
how to deal with malfunctioning domains and even how to create your own, new 
domains from scratch (if we need to). Further down, we give an overview of the 
guidelines that we try to follow during the policy developments and finally
talk about how to properly create patches and submit them to our <a href="https://bugs.gentoo.org">bugzilla</a> service.
</p>
<p>
For those who want to run Gentoo Hardened with their own policies, we've also
added a chapter on just that. We know that our policy does not match everyone's
requirements, so we definitely want to help you run your own too.
</p>
<p class="secthead"><a name="doc_chap1_sect2">Intended audience</a></p>
<p>
This document is a must-read for everyone willing to provide patches or develop
the Gentoo Hardened SELinux policies.
</p>
<p>
Other SELinux advanced users might find this document interesting as well.
</p>
<p class="secthead"><a name="doc_chap1_sect3">What you need to know</a></p>
<p>
This document does assume prior knowledge on SELinux policies and the way the
reference policy works. For those that need a quick recap, here are the
highlights...
</p>
<ul>
  <li>
    SELinux uses <span class="emphasis">domains</span> and <span class="emphasis">types</span> to differentiate its various
    security objects. A domain is usually referred to as the security context
    of a process (or group of processes) whereas a type is usually referred to
    as the label given to a particular resource (file, directory, network
    interface, socket, network port, ...).
  </li>
  <li>
    <span class="emphasis">SELinux policies</span> describe what interaction is allowed between a
    domain and the other domains and types it needs to work with. If no policy
    allows for a particular activity, then the activity is denied.
  </li>
  <li>
    The structure in which policies are written are called <span class="emphasis">SELinux policy
    modules</span> which contain three parts: a <span class="emphasis">type enforcement file</span> (with
    suffix <span class="path" dir="ltr">.te</span>) that contains the intra-module permissions, an
    <span class="emphasis">interface file</span> (with suffix <span class="path" dir="ltr">.if</span>) that contains the
    inter-module permissions and a <span class="emphasis">file contexts file</span> (with suffix
    <span class="path" dir="ltr">.fc</span>) that contains the file context definitions for all file
    resources that are labeled with the type or types defined in the module
  </li>
  <li>
    Inter-domain privileges must be declared through functions in the
    <span class="emphasis">interface file</span> which can then be called 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 attributes
    to your own types or domains.
  </li>
</ul>
<p class="chaphead"><a name="doc_chap2"></a><span class="chapnum">2.
            </span>Setting Up Your Environment</p>
<p class="secthead"><a name="doc_chap2_sect1">Patching the reference policy</a></p>
<p>
Gentoo Hardened builds its policy upon the <a href="http://oss.tresys.com/projects/refpolicy">reference policy</a> as
provided by <a href="http://www.tresys.com">Tresys</a> and managed through
an active <a href="http://oss.tresys.com/projects/refpolicy/wiki/HowToContribute">community</a>.
I suggest to use two workspaces when dealing with SELinux policies for Gentoo
Hardened: the <span class="path" dir="ltr">hardened</span> one for the Gentoo patched policy, and a 
<span class="path" dir="ltr">local</span> one in which you work and make your patches in.
</p>
<p>
Of course, using a source control system like git can be helpful too. For now,
Gentoo Hardened doesn't have a git repository where its policies are based from
(yet). That might sound a bit dull, but it forces the developers to remain as
close to upstream as possible (and contribute the changes upstream too so that
newer releases include them automatically). You can definitely use a source
control system yourself - the only reason we do not use it in this document is
that it is easier to document without ;-)
</p>
<p>
Let's create the first workspace:
</p>
<a name="doc_chap2_pre1"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing2.1: Creating the SELinux policy workspace</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~$ <span class="code-input">mkdir dev/hardened</span>
~$ <span class="code-input">cd dev/hardened</span>
~$ <span class="code-input">ebuild /usr/portage/sec-policy/selinux-base-policy/selinux-base-policy-2.20110726-r3.ebuild prepare</span>
~$ <span class="code-input">cp -r /var/tmp/portage/sec-policy/selinux-base-policy-2.20110726-r3/work/refpolicy .</span>
~$ <span class="code-input">rm -rf /var/tmp/portage/sec-policy/selinux-base-policy-2.20110726-r3</span>
</pre></td></tr>
</table>
<p>
As result, you now have a subdirectory called <span class="path" dir="ltr">refpolicy</span> inside
<span class="path" dir="ltr">dev/hardened</span>. This directory contains all the SELinux policy rules
available. Now the <span class="path" dir="ltr">dev/hardened</span> workspace is patched with the
Gentoo Hardened SELinux patches applicable to the policy. Gentoo Hardened has
two "flavors" of patches:
</p>
<ol>
  <li>
    patches in the <span class="emphasis">patchbundle</span> contain the majority of patches
  </li>
  <li>
    <span class="emphasis">module patches</span> that contain the permissions affecting the
    domains and types that are defined in a single module (for instance, all
    interaction between <span class="path" dir="ltr">portage_t</span> and <span class="path" dir="ltr">portage_exec_t</span>
    or even <span class="path" dir="ltr">portage_t</span> and <span class="path" dir="ltr">portage_fetch_t</span>)
  </li>
</ol>
<p>
When we develop changes on the SELinux policy, we currently try to put those
changes in the patchbundle as soon as possible. Currently, the
<span class="code" dir="ltr">selinux-base-policy</span> package is updated fast enough to hold off module
patches and wait for a new release of <span class="code" dir="ltr">selinux-base-policy</span> (after which
the SELinux modules themselves can just refer to the new base policy to get
their patches).
</p>
<p>
However, when the <span class="code" dir="ltr">selinux-base-policy</span> is more stable, then patches might
be made part of the modules themselves. In that case, a <span class="emphasis">module patch</span> is
made.
</p>
<table class="ncontent" width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td bgcolor="#bbffbb"><p class="note"><b>Note: </b>
Every time a new revision comes out, you'll need to clean the
<span class="path" dir="ltr">dev/hardened</span> workspace and rebuild it.
</p></td></tr></table>
<p class="secthead"><a name="doc_chap2_sect2">Add specific module files</a></p>
<p>
If you want to or need to work on the policy of a SELinux module (rather than
the base policy), check its ebuild to see if it holds any additional patches
(mentioned through the <span class="code" dir="ltr">POLICY_PATCH</span> variable). If not, then you can work
off the snapshot taken earlier in this guide.
</p>
<p>
However, if a patch (or set of patches) is applied as well, you either need to
apply those manually on the snapshot, or use the following tactics to create a
snapshot just for this module:
</p>
<a name="doc_chap2_pre2"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing2.2: Updating the dev/hardened workspace</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~$ <span class="code-input">ls dev/hardened/refpolicy/policy/modules/*/postfix.te</span>
dev/hardened/refpolicy/policy/modules/services/postfix.te
<span class="code-comment">                                      ^^^^^^^^</span>
~$ <span class="code-input">ebuild /usr/portage/sec-policy/selinux-postfix/selinux-postfix-2.20110726-r1.ebuild prepare</span>

<span class="code-comment"># Next, we copy the postfix.te and postfix.fc files.
# Do NOT copy the postfix.if file (as the one available there is a stub)</span>
~$ <span class="code-input">cp /var/tmp/portage/sec-policy/selinux-postfix-2.20110726-r1/work/strict/postfix.te \
  dev/hardened/refpolicy/policy/modules/services/</span>
<span class="code-comment">                                        ^^^^^^^^</span>
~$ <span class="code-input">cp /var/tmp/portage/sec-policy/selinux-postfix-2.20110726-r1/work/strict/postfix.fc \
  dev/hardened/refpolicy/policy/modules/services/</span>
<span class="code-comment">                                        ^^^^^^^^</span>
~$ <span class="code-input">rm -rf /var/tmp/portage/sec-policy/selinux-postfix-2.20110726-r1</span>
</pre></td></tr>
</table>
<p class="secthead"><a name="doc_chap2_sect3">Setting up a local workspace</a></p>
<p>
Setting up a local workspace (where we will create changes and generate patches
out of later) is easy: just copy the <span class="path" dir="ltr">dev/hardened</span> one:
</p>
<a name="doc_chap2_pre3"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing2.3: Setting up a local workspace</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~$ <span class="code-input">cd dev/hardened</span>
~$ <span class="code-input">cp -r refpolicy refpolicy.local/</span>
</pre></td></tr>
</table>
<p class="secthead"><a name="doc_chap2_sect4">Navigating the policy workspace</a></p>
<p>
The main location you will work with is
<span class="path" dir="ltr">dev/hardened/refpolicy.local/policy/modules</span>. This location is subdivided in
categories:
</p>
<dl>
  <dt>admin</dt>
  <dd>Administrative SELinux policy modules (portage, logrotate, sudo, ...)</dd>
  <dt>apps</dt>
  <dd>Application SELinux policy modules (evolution, mozilla, screen, ...)</dd>
  <dt>kernel</dt>
  <dd>Kernel specific SELinux policy domains (corenetwork, kernel, ...)</dd>
  <dt>roles</dt>
  <dd>Domains specific to SELinux roles (sysadm, user, staff, ...)</dd>
  <dt>services</dt>
  <dd>Daemon SELinux policy modules (postfix, apache, squid, ...)</dd>
  <dt>system</dt>
  <dd>Core SELinux policy modules (selinuxutil, mount, iptables, ...)</dd>
</dl>
<p>
The categorization is arbitrary and serves no purpose other than keeping the
modules a but separated. Each module must have a unique name, regardless of the
category!
</p>
<p>
Inside the categories, the modules are available using their three files
</p>
<a name="doc_chap2_pre4"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing2.4: Listing the available sudo files</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~$ <span class="code-input">cd dev/hardened/refpolicy.local/policy/modules/admin</span>
~$ <span class="code-input">ls sudo.*</span>
sudo.fc    sudo.if     sudo.te
</pre></td></tr>
</table>
<p class="secthead"><a name="doc_chap2_sect5">Building a module</a></p>
<p>
To build a module, go to the location where the module code is. Then, run
<span class="code" dir="ltr">make</span> with the development Makefile as provided by the reference policy.
</p>
<table class="ncontent" width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td bgcolor="#bbffbb"><p class="note"><b>Note: </b>
You can ignore warnings about duplicate interface definitions and such. That is
because the Makefile will include both the existing interfaces as well as the
current working directory - which of course contains the same interfaces.
</p></td></tr></table>
<a name="doc_chap2_pre5"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing2.5: Building the portage module</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~$ <span class="code-input">cd dev/hardened/refpolicy.local/policy/modules/admin</span>
~$ <span class="code-input">make -f /usr/share/selinux/strict/include/Makefile portage.pp</span>
</pre></td></tr>
</table>
<p>
You now have a <span class="path" dir="ltr">portage.pp</span> file available which you can load (using
<span class="code" dir="ltr">semodule -i portage.pp</span>).
</p>
<p class="secthead"><a name="doc_chap2_sect6">Building the base policy</a></p>
<p>
If you want to build the base policy, run <span class="code" dir="ltr">make base</span>.
</p>
<a name="doc_chap2_pre6"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing2.6: Building the base policy</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~$ <span class="code-input">cd dev/hardened/refpolicy.local</span>
~$ <span class="code-input">make base</span>
</pre></td></tr>
</table>
<p>
The result should be a <span class="path" dir="ltr">base.pp</span> file that you can load using
<span class="code" dir="ltr">semodule -b base.pp</span>. However, if you intend to do a bit more than just
test this base policy quickly, it is seriously recommended to create your own
Gentoo overlay for your own <span class="path" dir="ltr">selinux-base-policy</span> and install that
one as installing a base policy is not only about the policy module itself, but
also about the include files that will then be stored in
<span class="path" dir="ltr">/usr/share/selinux/strict/include</span>.
</p>
<p class="chaphead"><a name="doc_chap3"></a><span class="chapnum">3.
            </span>A Domain Does Not Function Properly</p>
<p class="secthead"><a name="doc_chap3_sect1">Introduction</a></p>
<p>
The most likely problem that you are hitting is that a domain does exist in
Gentoo Hardened SELinux, but that it isn't functioning as it should. To solve
this problem, it is adviseable to use the following sequence of investigations:
</p>
<ol>
  <li>
    Is it really SELinux that is restraining your system?
  </li>
  <li>
    Is the problem related to wrong resource labels / security contexts?
  </li>
  <li>
    Is the problem related to intra-module permissions?
  </li>
  <li>
    Is the problem related to inter-module permissions?
  </li>
</ol>
<p class="secthead"><a name="doc_chap3_sect2">Check if SELinux is to blame</a></p>
<p>
Make sure that the problem you are seeing is a SELinux-triggered problem. An
easy way to find out is to run SELinux in permissive mode and try again:
</p>
<a name="doc_chap3_pre1"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing3.1: Switching to permissive mode</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~# <span class="code-input">setenforce 0</span>
</pre></td></tr>
</table>
<p>
This only works if the problem is <span class="emphasis">not</span> to do with a SELinux-aware
application (unlike <span class="code" dir="ltr">init</span> or <span class="code" dir="ltr">sudo</span> which are linked to the
libselinux library). SELinux-aware applications might alter their behavior if
SELinux is set on the system regardless of it running in permissive mode or not.
A prime example is <span class="code" dir="ltr">vixie-cron</span> (as can be seen in <a href="https://bugs.gentoo.org/show_bug.cgi?id=257111">bug #257111</a>). But
for applications that are not SELinux aware, this is the easiest method to find
out if SELinux is to blame or not.
</p>
<p>
If running your system in permissive mode works around the problem, read on. If
it doesn't, check the regular permissions (<span class="code" dir="ltr">strace</span>'ing the application
might be a good idea too).
</p>
<p class="secthead"><a name="doc_chap3_sect3">Get the proper AVC denials</a></p>
<p>
Assuming that we now know that SELinux is to blame, we need to make sure that we
get the proper AVC denials. Either locate the proper denials in
<span class="path" dir="ltr">/var/log/avc.log</span> (or <span class="path" dir="ltr">audit.log</span>) around the time that
you encountered the issue, or run <span class="code" dir="ltr">tail -f /var/log/avc.log</span> and reproduce
the problem.
</p>
<a name="doc_chap3_pre2"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing3.2: Example denials</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~# <span class="code-input">tail -f /var/log/avc.log</span>
Apr 22 15:03:33 www1 kernel: [16053.303739] type=1400 audit(1303477413.188:283):
avc:  denied  { dac_read_search } for  pid=21758 comm="rm" capability=2
scontext=root:sysadm_r:portage_t tcontext=root:sysadm_r:portage_t
tclass=capability
</pre></td></tr>
</table>
<p>
Analyzing the meaning of the AVC denial is covered by <a href="selinux/selinux-handbook.xml?part=2&amp;chap=3#avclog">Looking
at the AVC Log</a> in the Gentoo Hardened SELinux handbook. The denial should
give you a pointer where to look for. However, it is possible that no denial is
occurring, or at least no relevant ones.
</p>
<p>
A first step to get potentially more denials is to switch the
<span class="code" dir="ltr">gentoo_try_dontaudit</span> boolean off. This boolean is used by the Gentoo
Hardened SELinux developers to hide denials which they assume are cosmetic. As
these developers are known to have a human side (as well), they are known to
make mistakes ;-)
</p>
<a name="doc_chap3_pre3"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing3.3: Disabling gentoo's dontaudit statements</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~# <span class="code-input">setsebool gentoo_try_dontaudit off</span>
</pre></td></tr>
</table>
<p>
Retry getting the proper AVC denials.
</p>
<p>
If it still doesn't work, you can disable all <span class="emphasis">dontaudit</span> statements:
</p>
<a name="doc_chap3_pre4"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing3.4: Disabling all dontaudit statements</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~# <span class="code-input">semodule -R -D -B</span>
</pre></td></tr>
</table>
<p>
Retry getting the proper AVC denials.
</p>
<p>
The moment you get the denials you are looking for, isolate them and then undo
the changes you made earlier:
</p>
<a name="doc_chap3_pre5"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing3.5: Resetting the auditing defaults</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~# <span class="code-input">setsebool gentoo_try_dontaudit on</span>
~# <span class="code-input">semodule -R -B</span>
</pre></td></tr>
</table>
<p>
If you still do not see any denials, then check out the <span class="code" dir="ltr">dmesg</span> output for
other problems. It is possible that SELinux is not even getting to the point of
the policy, which you will not notice by looking at the AVC denials alone.
However, the chance of this to happen is very slim - most of the time, you'll
find the AVC denials you are looking for.
</p>
<p class="secthead"><a name="doc_chap3_sect4">Deducing the correct security contexts</a></p>
<p>
The next step is to see if we are dealing with the right security contexts. This
does require a bit of insight in how both the application (that is failing) and
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 right target
type.
</p>
<p>
Say you are having issues with SELinux (re)labeling and you notice the following
AVC denial:
</p>
<a name="doc_chap3_pre6"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing3.6: AVC denial for setfiles</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
Apr 16 14:39:57 testsys kernel: [  115.778484] type=1400
audit(1302957597.827:224): avc:  denied  { create } for  pid=3584
comm="setfiles" scontext=root:sysadm_r:<span class="code-comment">sysadm_t</span> tcontext=root:sysadm_r:sysadm_t
tclass=netlink_audit_socket
</pre></td></tr>
</table>
<p>
In this case, <span class="code" dir="ltr">setfiles</span> is running in the <span class="path" dir="ltr">sysadm_t</span> domain
even though it should run in <span class="path" dir="ltr">setfiles_t</span>. So check the security
context of the <span class="code" dir="ltr">setfiles</span> binary as well as the transition rules:
</p>
<a name="doc_chap3_pre7"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing3.7: Checking setfiles context and rules</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~# <span class="code-input">ls -lZ /sbin/setfiles</span>
-rwxr-xr-x. 1 root root <span class="code-comment">system_u:object_r:bin_t</span> 26464 Apr  9 22:22 /sbin/setfiles
~# <span class="code-input">sesearch -s sysadm_t -t setfiles_t -c process -p transition -A -d</span>
Found 1 semantic av rules:
    allow sysadm_t setfiles_t : process transition ;
~# <span class="code-input">sesearch -s sysadm_t -t setfiles_exec_t -c file -p execute -A -d</span>
...
~# <span class="code-input">sesearch -s setfiles_t -t setfiles_exec_t -c file -p entrypoint -A -d</span>
...
</pre></td></tr>
</table>
<p>
In the above (forced) situation, the problem is with the security context of the
binary - it should have been <span class="path" dir="ltr">setfiles_exec_t</span> instead of
<span class="path" dir="ltr">bin_t</span>. Usually, entry points are named similarly (like
<span class="path" dir="ltr">portage_exec_t</span> or <span class="path" dir="ltr">sudo_exec_t</span>). If you are not certain
about which domain it should be, use <span class="code" dir="ltr">sesearch</span>
</p>
<a name="doc_chap3_pre8"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing3.8: Using sesearch to find the entrypoint type for a domain</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~# <span class="code-input">sesearch -s setfiles_t -c file -p entrypoint -A -d</span>
Found 1 semantic av rules:
   allow setfiles_t setfiles_exec_t : file { ioctl ... execute entrypoint open } ;
</pre></td></tr>
</table>
<p>
The <span class="code" dir="ltr">sesearch</span> utility is extremely powerful to query the SELinux policy
(which is currently in memory). I also advise you to use the <span class="code" dir="ltr">-C</span> switch to
see which rules are trigged by certain SELinux booleans:
</p>
<a name="doc_chap3_pre9"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing3.9: Looking for boolean-triggered settings</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~# <span class="code-input">sesearch -s named_t -t named_zone_t -c file -A -d -C</span>
Found 2 semantic av rules:
   allow named_t named_zone_t : file { ioctl read getattr lock open } ; 
DT allow named_t named_zone_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ; [ named_write_master_zones ]
</pre></td></tr>
</table>
<p>
In the above example, the <span class="path" dir="ltr">named_t</span> domain only has write privileges
on files labeled <span class="path" dir="ltr">named_zone_t</span> if the
<span class="path" dir="ltr">named_write_master_zones</span> boolean is set (which it currently isn't,
otherwise the line would stat with ET instead of DT).
</p>
<p>
To gain a bit of insight in the various, available domains, use <span class="code" dir="ltr">seinfo</span>:
</p>
<a name="doc_chap3_pre10"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing3.10: Getting a list of available domains</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~# <span class="code-input">seinfo -t | grep named</span>
   named_var_run_t
   named_checkconf_exec_t
   named_conf_t
   named_initrc_exec_t
   named_log_t
   named_exec_t
   named_zone_t
   named_t
   named_cache_t
   named_tmp_t
</pre></td></tr>
</table>
<p>
To gain a bit of insight in the (current) file context rules, use
<span class="code" dir="ltr">semanage</span>:
</p>
<a name="doc_chap3_pre11"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing3.11: Getting the list of current file context rules</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~# <span class="code-input">semanage fcontext -l | grep named</span>
/etc/bind(/.*)?                                    all files        system_u:object_r:named_zone_t 
/etc/bind/named\.conf                              regular file     system_u:object_r:named_conf_t 
/etc/rc\.d/init\.d/named                           regular file     system_u:object_r:named_initrc_exec_t 
/etc/rc\.d/init\.d/unbound                         regular file     system_u:object_r:named_initrc_exec_t 
/etc/rndc.*                                        regular file     system_u:object_r:named_conf_t 
/etc/unbound(/.*)?                                 all files        system_u:object_r:named_conf_t 
/usr/sbin/lwresd                                   regular file     system_u:object_r:named_exec_t 
/usr/sbin/named                                    regular file     system_u:object_r:named_exec_t 
/usr/sbin/named-checkconf                          regular file     system_u:object_r:named_checkconf_exec_t 
/usr/sbin/unbound                                  regular file     system_u:object_r:named_exec_t 
/var/bind(/.*)?                                    all files        system_u:object_r:named_cache_t 
/var/bind/pri(/.*)?                                all files        system_u:object_r:named_zone_t 
/var/log/named.*                                   regular file     system_u:object_r:named_log_t 
/var/run/bind(/.*)?                                all files        system_u:object_r:named_var_run_t 
/var/run/named(/.*)?                               all files        system_u:object_r:named_var_run_t 
/var/run/ndc                                       socket           system_u:object_r:named_var_run_t 
/var/run/unbound(/.*)?                             all files        system_u:object_r:named_var_run_t 
</pre></td></tr>
</table>
<p>
Most of the time, fixing domain issues is a matter of relabeling files (or
updating the configuration to match the contexts already defined - both work).
</p>
<p class="secthead"><a name="doc_chap3_sect5">Intra-module permissions are missing</a></p>
<p>
It is possible that you get a denial between correct security contexts, but
that the permission is just never granted. In this case, you can choose between
two things:
</p>
<ol>
  <li>
    Enhance the module so that the particular permission is granted, or
  </li>
  <li>
    Enhance the module with an additional type where the permission is granted,
    and assign this type/label to the related resources
  </li>
</ol>
<p>
In both cases you will need to edit the module files (most likely the
<span class="path" dir="ltr">.te</span> file), build the module, load it, perhaps even relabel the
files or the package and retry. It is also a good idea to take a look at
upstream (latest refpolicy repository or the repositories of Fedora and co) and
see if they have already solved this problem or not.
</p>
<p>
Granting additional permissions between existing domains is the easiest, but
might introduce additional problems: if this permission is only needed in a
particular case yet you grant it for all files and resources related to those
domains, then you are opening up the policy beyond what is necessary. Often,
creating an additional domain or type can be beneficial.
</p>
<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="path" dir="ltr">distfiles/svn+src</span> location, which was by default labeled
<span class="path" dir="ltr">portage_ebuild_t</span> with only read-access for the
<span class="path" dir="ltr">portage_sandbox_t</span> domain. However, with those live ebuilds, the
<span class="path" dir="ltr">portage_sandbox_t</span> domain also needs write privileges to this
location. Rather than allowing <span class="path" dir="ltr">portage_sandbox_t</span> write privileges
to <span class="path" dir="ltr">portage_ebuild_t</span>, a new type was created called
<span class="path" dir="ltr">portage_svnsrc_t</span> for just this location and the rights are
transferred towards type.
</p>
<p class="secthead"><a name="doc_chap3_sect6">Inter-module permissions are needed</a></p>
<p>
If the solution for the problem requires permissions between modules, then you
need to create the proper interface functions in the target domain and call
these functions from the source domain.
</p>
<p>
Interface functions are the APIs that a module provides towards other SELinux
modules when they need to interact with the domains. For instance, the
<span class="path" dir="ltr">mysql</span> module provides, amongst other functions, the
<span class="code" dir="ltr">mysql_stream_connect</span> interface:
</p>
<a name="doc_chap3_pre12"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing3.12: mysql_stream_connect interface</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
########################################
## &lt;summary&gt;
##      Connect to MySQL using a unix domain stream socket.
## &lt;/summary&gt;
## &lt;param name="domain"&gt;
##      &lt;summary&gt;
##      Domain allowed access.
##      &lt;/summary&gt;
## &lt;/param&gt;
## &lt;rolecap/&gt;
#
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, mysqld_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="code" dir="ltr">stream_connect_pattern</span>, which is a
macro (defined in <span class="path" dir="ltr">policy/support/ipc_patterns.spt</span> that looks like
so:
</p>
<a name="doc_chap3_pre13"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing3.13: stream_connect_pattern</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="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 socket
(<span class="path" dir="ltr">/var/run/mysqld/mysqld.sock</span>) will need the proper permissions to
work with the target type (<span class="path" dir="ltr">mysqld_var_run_t</span>). Modules cannot just
set <span class="emphasis">allow</span> statements towards <span class="path" dir="ltr">mysqld_var_run_t</span> as they do not
know this type. Instead, they call the <span class="code" dir="ltr">mysql_stream_connect</span> interface,
like the <span class="path" dir="ltr">postfix.te</span> file does:
</p>
<a name="doc_chap3_pre14"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing3.14: Postfix module calling mysql_stream_connect</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="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>
If the change you need is adding existing interface calls to the module (in 
the <span class="path" dir="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 interface
of your module itself (in the <span class="path" dir="ltr">.if</span> file) you will eventually need
to rebuild the base policy and even provide and install a new
<span class="path" dir="ltr">sec-policy/selinux-base-policy</span> package as the interfaces are placed
in <span class="path" dir="ltr">/usr/share/selinux/strict/include</span>. This is one of the reasons
why the <span class="path" dir="ltr">sec-policy/selinux-base-policy</span> package in Gentoo Hardened
has a high revision number (and many updates).
</p>
<p class="chaphead"><a name="doc_chap4"></a><span class="chapnum">4.
            </span>No Domain Exists (Yet)</p>
<p class="secthead"><a name="doc_chap4_sect1">Reuse existing domains</a></p>
<p>
If you are facing problems because you run an application which has no domain
itself (and hence is probably running in the <span class="path" dir="ltr">user_t</span>,
<span class="path" dir="ltr">staff_t</span> or <span class="path" dir="ltr">sysadm_t</span> domains - or even tries to run in
the <span class="path" dir="ltr">initrc_t</span> domain), you will need to create one. But before we do
that, it might be possible that the application can work within the domain
definition of a different application.
</p>
<p>
One example here is lighttpd. This lightweight HTTPd service "uses" the
definitions offered by the <span class="path" dir="ltr">apache</span> module. By marking its executable
file <span class="path" dir="ltr">httpd_exec_t</span> it runs in the <span class="path" dir="ltr">httpd_t</span> domain and
uses the same policy like Apache. By labeling the files according to the
<span class="path" dir="ltr">apache.fc</span> definitions (but now for lighttpd) it might Just Work
™
</p>
<p>
Reusing existing domains requires that you at least consider the following
aspects:
</p>
<ul>
  <li>
    Will the application run on the same system as the application for which the
    domain is originally intended? If so, then both might run in the same 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 original domain
    would ever need to the extend that these privileges become a security risk.
  </li>
</ul>
<p class="secthead"><a name="doc_chap4_sect2">(Do Not) Copy from existing domains</a></p>
<p>
If reusing existing domains introduces too many risks, you'll need to create a
new domain for the application. Many people would be inclined to copy the domain
definition of a similar application and work from there. Although this is a
viable approach, it is considered a bad practice because you start by providing
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="secthead"><a name="doc_chap4_sect3">Starting from scratch</a></p>
<p>
To start the development of a new module from scratch, first identify the
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="path" dir="ltr">skype_t</span>. However,
applications that have multiple processes running might need multiple domains
too. For instance, the Postfix application runs a master
(<span class="path" dir="ltr">postfix_master_t</span>), queue manager (<span class="path" dir="ltr">postfix_qmgr_t</span>) and
pickup service (<span class="path" dir="ltr">postfix_pickup_t</span>), but depending on the commands
you execute, it will also have (short-lived) processes running as
<span class="path" dir="ltr">postfix_cleanup_t</span>, <span class="path" dir="ltr">postfix_bounce_t</span>, etc.) It is
considered a best practice to start with a fine-grained model for domains
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 includes
the binary (like <span class="path" dir="ltr">skype_exec_t</span>) but do not forget resources like
</p>
<ul>
  <li>
    The configuration file(s) in <span class="path" dir="ltr">/etc</span> (f.i.
    <span class="path" dir="ltr">postfix_etc_t</span>)
  </li>
  <li>
    PID files (f.i. <span class="path" dir="ltr">sshd_var_run_t</span>)
  </li>
  <li>
    Spool files (f.i. <span class="path" dir="ltr">postfix_spool_t</span>)
  </li>
  <li>
    Variable data files (f.i. <span class="path" dir="ltr">snmpd_var_lib_t</span>)
  </li>
  <li>
    Log files (f.i. <span class="path" dir="ltr">zebra_log_t</span>)
  </li>
  <li>
    Cache files (f.i. <span class="path" dir="ltr">squid_cache_t</span>)
  </li>
  <li>
    (User) content files (f.i. <span class="path" dir="ltr">httpd_sys_content_t</span> and
    <span class="path" dir="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 are
labeled accordingly, rather than interact with a broad spectrum of files. The
distinction that the <span class="path" dir="ltr">apache</span> module makes between system-provided
content (like phpmyadmin files) and user-provided content (in the
<span class="path" dir="ltr">public_html</span> directory in the users' 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 clearly 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-domain
permissions. Right now is a good time to look at other modules to see how they
do things. Start with defining the accesses towards the domains.
</p>
<a name="doc_chap4_pre1"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing4.1: Snippet from the spamassassin module</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="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="path" dir="ltr">spamassassin_t</span> domain and
<span class="path" dir="ltr">spamassassin_exec_t</span> type). The <span class="code" dir="ltr">application_domain</span> interface
marks <span class="path" dir="ltr">spamassassin_t</span> as an application domain type (it gets the
<span class="path" dir="ltr">application_domain_type</span> and <span class="path" dir="ltr">domain</span> attributes and a
few default permissions (like allowing that it sends SIGCHLD and SIGNULL to
init). It also marks <span class="path" dir="ltr">spamassassin_exec_t</span> as an applications'
executable type (<span class="path" dir="ltr">application_exec_type</span> and <span class="path" dir="ltr">exec_type</span>
attributes) so that it can be executed by regular users (these domains have
execute rights against all resources that have the
<span class="path" dir="ltr">application_exec_type</span> attribute set. Finally, it marks the
<span class="path" dir="ltr">spamassassin_t</span> domain as a constrained domain for user-based access
controls. In other words, if SELinux users <span class="path" dir="ltr">user_u</span> and
<span class="path" dir="ltr">staff_u</span> launch the application in <span class="path" dir="ltr">spamassassin_t</span>
domains, then the domains are segregated from each other (the intra-domain rules
inside <span class="path" dir="ltr">spamassassin_t</span> are only valid for communication within the
same SELinux user, not between SELinux users).
</p>
<p>
Attributes are an important aspect in SELinux policy development. They make
managing the domains easier, but you should always consider the implications
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="path" dir="ltr">/var/lib</span> location:
</p>
<a name="doc_chap4_pre2"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing4.2: Snippet from openca module</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="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 choosing
the right interfaces. Having a few functions available to browse through all the
available information is always interesting, so you might want to use the
following function definitions (definitely not mandatory - this is only to help
people skim through the policy definitions):
</p>
<a name="doc_chap4_pre3"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing4.3: SELinux policy development function definitions</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
POLICY_LOCATION="http://www.gentoo.org/path/to/your/refpolicy";

# sefindif - Find interface definitions that have a string that matches the
# given regular expression
sefindif() {
  REGEXP="$1";
  cd ${POLICY_LOCATION}/policy/modules;
  for FILE in */*.if;
  do
    awk "http://www.gentoo.org/(interface\(|template\()/ { NAME=\$NF; P=0 }; /${REGEXP}/ { if (P==0) {P=1; print NAME}; print };" ${FILE} | sed -e "s:^:${FILE}\: :g";
  done
}

# seshowif - Show the interface definition
seshowif() {
  INTERFACE="$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="$1";
  grep -H "define(\`.*${REGEXP}.*" ${POLICY_LOCATION}/policy/support/* | sed -e 's:.*\/\([^(]*\):\1:g'
}

# seshowdef - Show the macro definition
seshowdef() {
  MACRONAME="$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 you are
looking for. For instance, you need the application to read the postfix
configuration files:
</p>
<a name="doc_chap4_pre4"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing4.4: Looking for the interface(s) needed</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~$ <span class="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_perms;
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="code-comment">services/postfix.if: interface(`postfix_read_config',`
services/postfix.if:            type postfix_etc_t;
services/postfix.if:    read_files_pattern($1, postfix_etc_t, postfix_etc_t)
services/postfix.if:    read_lnk_files_pattern($1, postfix_etc_t, postfix_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="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="doc_chap4_pre5"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing4.5: Looking for the right macros</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
<span class="code-comment"># Suppose you need to read, write, connect, ... to a socket</span>
~$ <span class="code-input">sefinddef connect</span>
ipc_patterns.spt:define(`stream_connect_pattern',`
<span class="code-comment">obj_perm_sets.spt:define(`rw_socket_perms', `{ ioctl read getattr write setattr append bind connect getopt setopt shutdown }')</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_socket_perms listen accept }')

<span class="code-comment"># To see what the ps_process_pattern is about</span>
~$ <span class="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 the <a href="http://oss.tresys.com/projects/refpolicy/wiki/HowToContribute">contribution
guidelines</a> of the reference policy project. The project has a documented
style guide, naming convention and an online API reference (for the various
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="code" dir="ltr">tvtime_role</span> and how it is used in the
<span class="path" dir="ltr">staff.te</span> and <span class="path" dir="ltr">sysadm.te</span> role definitions.
</p>
<p class="secthead"><a name="doc_chap4_sect4">Testing new modules</a></p>
<p>
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 terminal
(tty) as well as a virtual one (in an xterm). See if it still works if you run
it in a screen session. Try out all functions and features that the application
supports.
</p>
<p>
This rigorous testing is necessary because SELinux denies everything that isn't
explicitly allowed. If you do not test certain features, chances are that the
module does not provide the necessary permissions and as such, users will be
impacted.
</p>
<p>
To test out a new module, load it (<span class="code" dir="ltr">semodule -i modulename.pp</span>) and relabel
the files affiliated with the application (either through <span class="code" dir="ltr">rlpkg</span> or using
<span class="code" dir="ltr">restorecon</span>). Consider the following 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 it, try
    killing it)
  </li>
  <li>
    Run it both as a regular user (<span class="path" dir="ltr">user_u</span>) as well as
    administrative users (if applicable). If your domain needs to support
    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. Especially
    syntax failures as that might trigger the application to log things at
    places that you haven't discovered earlier.
  </li>
</ul>
<p class="chaphead"><a name="doc_chap5"></a><span class="chapnum">5.
            </span>Policy Guidelines</p>
<p class="secthead"><a name="doc_chap5_sect1">Cosmetic denials</a></p>
<p>
When working on policy modules, you'll notice that the application is trying to
do things which are denied, but have no obvious effect on the applications
functionality. This is to be expected: many applications do not handle file
descriptors properly (file descriptor leaks are common) or applications read
attributes of files but don't do anything with it. You'll notice that you learn
a lot from the application while writing its policy ;-)
</p>
<p>
Gentoo Hardened's idea here is to only allow what is actually needed by the
application. Cosmetic denials are to be <span class="code" dir="ltr">dontaudit</span>'ed. Gentoo Hardened
uses the <span class="code" dir="ltr">gentoo_try_dontaudit</span> boolean for this:
</p>
<a name="doc_chap5_pre1"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing5.1: Example usage of gentoo_try_dontaudit</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
<span class="code-comment"># Hide sshd_t calling module_request from the kernel_t domain</span>
tunable_policy(`gentoo_try_dontaudit',`
        kernel_dontaudit_request_load_module(sshd_t)
')
</pre></td></tr>
</table>
<p class="secthead"><a name="doc_chap5_sect2">Gentoo Hardened SELinux policy</a></p>
<p>
To streamline the policy development efforts, Gentoo Hardened as a <a href="selinux-policy.xml">SELinux Policy</a> document explaining the
principles used during policy development and the implementation guidelines 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 hope that
other developers can quickly jump in and work on it further.
</p>
<p class="chaphead"><a name="doc_chap6"></a><span class="chapnum">6.
            </span>Submitting Patches</p>
<p class="secthead"><a name="doc_chap6_sect1">File context patches</a></p>
<p>
If you are able to fix a problem by adding the proper file contexts (using
<span class="code" dir="ltr">semanage fcontext -a</span>), please consider the following:
</p>
<ul>
  <li>
    If the location for which you set the context deviates from the standard
    location as either intended by the project or Gentoo itself, it might be
    best to document it in the forums or elsewhere. We will not change file
    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 policy
    module packages to keep the amount of policy module changes low. Instead,
    these changes can be stacked and pushed when other changes occur as well.
  </li>
</ul>
<p>
If you believe that the change is needed for everyone using Gentoo Hardened with
SELinux, create a <a href="https://bugs.gentoo.org">bugreport</a> and assign
it to <span class="code" dir="ltr">selinux@gentoo.org</span>. In the bugreport, mention the file context you
think is necessary and why.
</p>
<p class="secthead"><a name="doc_chap6_sect2">Module patches</a></p>
<p>
Module patches with changes that are intra-module (and have no effect outside)
are best generated from the <span class="path" dir="ltr">policy/modules</span> location:
</p>
<a name="doc_chap6_pre1"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing6.1: Example generating patch for modular changes</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~$ <span class="code-input">cd dev/hardened/refpolicy.local/policy/modules</span>
~$ <span class="code-input">diff -ut ../../../refpolicy/policy/modules/services/openct.te services/openct.te</span>
--- ../../../../refpolicy/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 @@
 
 miscfiles_read_localization(openct_t)
 
+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="https://bugs.gentoo.org">bugreport</a>
explaining why it is needed. If you think the patch itself is not obvious, make
sure that the necessary comments are in place <span class="emphasis">inside the patch</span> for future
reference.
</p>
<p>
Please have a separate patch file per module (do not combine multiple modules in
a single patch).
</p>
<p class="secthead"><a name="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="doc_chap6_pre2"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing6.2: Generating a base policy patch</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~$ <span class="code-input">cd dev/hardened/refpolicy.local</span>
~$ <span class="code-input">diff -ut ../refpolicy/policy/modules/services/openct.if policy/modules/services/openct.if</span>
--- ../strict/policy/modules/services/openct.if    2011-04-22 23:28:17.918918002 +0200
+++ policy/modules/services/openct.if       2011-04-23 10:01:38.753918001 +0200
@@ -15,7 +15,7 @@
                 type openct_t;
         ')
 
-        allow $1 openct_t:process signull;
+        allow $1 openct_t:process { signull sigchld };
 ')
 
 ########################################
</pre></td></tr>
</table>
<p>
Attach this patch to the <a href="https://bugs.gentoo.org">bugreport</a>
explaining why it is needed. If you think the patch itself is not obvious, make
sure that the necessary comments are in place <span class="emphasis">inside the patch</span> for future
reference.
</p>
<p>
Please have a separate patch file per major change (do not combine multiple
unrelated changes in a single patch).
</p>
<p class="chaphead"><a name="doc_chap7"></a><span class="chapnum">7.
            </span>Running Your Own Policy</p>
<p class="secthead"><a name="doc_chap7_sect1">Creating a local overlay</a></p>
<p>
If you want to use your own policy rather than Gentoo's, we seriously recommend
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 openldap,
it will still properly depend on the <span class="path" dir="ltr">sec-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="path" dir="ltr">sec-policy</span> category inside it.
</p>
<a name="doc_chap7_pre1"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing7.1: Creating a local overlay</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
~$ <span class="code-input">mkdir dev/overlay</span>
~$ <span class="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="path" dir="ltr">sec-policy</span> category of
the main tree anymore. To do so, create the file
<span class="path" dir="ltr">/etc/portage/rsync_excludes</span> with the following content:
</p>
<a name="doc_chap7_pre2"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing7.2: Rsync exclusion information</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
sec-policy/
</pre></td></tr>
</table>
<p>
Finally, add your current overlay by editing <span class="path" dir="ltr">/etc/make.conf</span>:
</p>
<a name="doc_chap7_pre3"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing7.3: Editing make.conf</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
PORTDIR_OVERLAY="${PORTDIR_OVERLAY} /home/user/dev/overlay"
</pre></td></tr>
</table>
<p>
From now onwards, Gentoo Portage will only use your local overlay (you can
remove <span class="path" dir="ltr">/usr/portage/sec-policy</span> if you don't want Portage to even
reuse the current set of packages.
</p>
<p class="secthead"><a name="doc_chap7_sect2">Updating module packages</a></p>
<p>
To create or update a module package, you can use the following skeleton for the
ebuilds:
</p>
<a name="doc_chap7_pre4"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing7.4: Skeleton for ebuilds, example for postfix</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
# Copyright 1999-2011 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
EAPI="4"

IUSE=""
<span class="code-comment"># Set the MODS variable to the refpolicy name used, so services/postfix.te gives "postfix"</span>
MODS="postfix"
<span class="code-comment"># BASEPOL is optional, set it to the selinux-base-policy version which
# includes the latest patch (or interface you use in the policy)</span>
BASEPOL="2.20110726-r3"

inherit selinux-policy-2

DESCRIPTION="SELinux policy for postfix"
KEYWORDS="~amd64 ~x86"

<span class="code-comment"># POLICY_PATCH is optional (only when you have a module patch)</span>
POLICY_PATCH="${FILESDIR}/fix-services-postfix-r3.patch"
</pre></td></tr>
</table>
<p>
The patch(es) that you can put in the <span class="path" dir="ltr">files/</span> location (and referred to
in the <span class="code" dir="ltr">POLICY_PATCH</span>) should be made 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="code" dir="ltr">repoman manifest</span> with every change, and run
<span class="code" dir="ltr">repoman scan</span> to check for potential mistakes.
</p>
<p class="secthead"><a name="doc_chap7_sect3">Updating base package</a></p>
<p>
To provide updates on the base policy, it is recommended to keep all patches you
made centrally in a directory (say <span class="path" dir="ltr">dev/hardened/base-patches</span>). When
you want to create a new <span class="path" dir="ltr">sec-policy/selinux-base-policy</span> release,
create a patchbundle from your patch directory, put the bundle in the
<span class="path" dir="ltr">files</span> location, create the updated ebuild and try it out.
</p>
<a name="doc_chap7_pre5"></a><table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr><td bgcolor="#7a5ada"><p class="codetitle">Code Listing7.5: Building a base policy package</p></td></tr>
<tr><td bgcolor="#eeeeff" align="left" dir="ltr"><pre>
<span class="code-comment"># Go to the location where all patches are currently extracted</span>
~$ <span class="code-input">cd dev/hardened/base-patches</span>

<span class="code-comment"># Add the patches you want to include, cfr Submitting Patches</span>
<span class="code-comment"># Then, create a new patch bundle</span>
~$ <span class="code-input">tar cjvf ../overlay/sec-policy/selinux-base-policy/files/patchbundle-selinux-base-policy-2.20110726-r3.tar.bz2 *</span>

<span class="code-comment"># Finally, bump the revision of the ebuild in the overlay</span>
~$ <span class="code-input">cd ../overlay/sec-policy/selinux-base-policy</span>
~$ <span class="code-input">cp selinux-base-policy-2.20110726-r3.ebuild selinux-base-policy-2.20110726-r4.ebuild</span>
</pre></td></tr>
</table>
<p>
Don't forget to run <span class="code" dir="ltr">repoman manifest</span> and <span class="code" dir="ltr">repoman scan</span>. You can
then install <span class="path" dir="ltr">sec-policy/selinux-base-policy-2.20110726-r4</span> and test
it out.
</p>
<br><p class="copyright">
	The contents of this document, unless otherwise expressly stated, are licensed under the <a href="http://creativecommons.org/licenses/by-sa/2.5">CC-BY-SA-2.5</a> license. The <a href="http://www.gentoo.org/main/en/name-logo.xml"> Gentoo Name and Logo Usage Guidelines </a> apply.
  </p>
<!--
  <rdf:RDF xmlns="http://web.resource.org/cc/"
      xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  
  <license rdf:about="http://creativecommons.org/licenses/by-sa/2.5/">
    
     <permits rdf:resource="http://web.resource.org/cc/Reproduction" />
     <permits rdf:resource="http://web.resource.org/cc/Distribution" />
     <requires rdf:resource="http://web.resource.org/cc/Notice" />
     <requires rdf:resource="http://web.resource.org/cc/Attribution" />
     <permits rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
     <requires rdf:resource="http://web.resource.org/cc/ShareAlike" />
  </License>
  </rdf:RDF>
--><br>
</td>
<td width="1%" bgcolor="#dddaec" valign="top"><table border="0" cellspacing="4px" cellpadding="4px">
<tr><td class="topsep" align="center"><p class="altmenu"><a title="View a printer-friendly version" class="altlink" href="selinux-development.xml?style=printable">Print</a></p></td></tr>
<tr><td class="topsep" align="center"><p class="alttext">Page updated November 22, 2011</p></td></tr>
<tr><td class="topsep" align="left"><p class="alttext"><b>Summary: </b>
When planning to help Gentoo Hardened in the development of SELinux policies,
or when trying to debug existing policies, this document should help you get
acquainted with the necessary resources, trips and tricks to get along.
</p></td></tr>
<tr><td align="left" class="topsep"><p class="alttext">
  <a href="mailto:sven.vermeulen@siphos.be" class="altlink"><b>Sven Vermeulen</b></a>
<br><i>Author</i><br></p></td></tr>
<tr lang="en"><td align="center" class="topsep">
<p class="alttext"><b>Donate</b> to support our development efforts.
        </p>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_xclick"><input type="hidden" name="business" value="paypal@gentoo.org"><input type="hidden" name="item_name" value="Gentoo Linux Support"><input type="hidden" name="item_number" value="1000"><input type="hidden" name="image_url" value="http://www.gentoo.org/images/paypal.png"><input type="hidden" name="no_shipping" value="1"><input type="hidden" name="return" value="http://www.gentoo.org"><input type="hidden" name="cancel_return" value="http://www.gentoo.org"><input type="image" src="http://images.paypal.com/images/x-click-but21.gif" name="submit" alt="Donate to Gentoo">
</form>
</td></tr>
<tr lang="en"><td align="center"><iframe src="http://sidebar.gentoo.org" scrolling="no" width="125" height="850" frameborder="0" style="border:0px padding:0x" marginwidth="0" marginheight="0"><p>Your browser does not support iframes.</p></iframe></td></tr>
</table></td>
</tr></table></td></tr>
<tr><td colspan="2" align="right" class="infohead">
Copyright 2001-2012 Gentoo Foundation, Inc. Questions, Comments? <a class="highlight" href="http://www.gentoo.org/main/en/contact.xml">Contact us</a>.
</td></tr>
</table></body>
</html>