/usr/bin/policygentool is in selinux-policy-dev 2:2.20180114-1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
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 | #! /usr/bin/env python
# Copyright (C) 2006 Red Hat
# see file 'COPYING' for use and warranty information
#
# policygentool is a tool for the initial generation of SELinux policy
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
# arch-tag: 4c33ae23-a363-4ace-bae9-86fb8a792206
import os, sys, getopt
import re
########################### Interface File #############################
interface="""\
## <summary>policy for TEMPLATETYPE</summary>
########################################
## <summary>
## Execute a domain transition to run TEMPLATETYPE.
## </summary>
## <param name=\"domain\">
## <summary>
## Domain allowed to transition.
## </summary>
## </param>
#
interface(`TEMPLATETYPE_domtrans',`
gen_require(`
type TEMPLATETYPE_t, TEMPLATETYPE_exec_t;
')
domain_auto_transition_pattern($1,TEMPLATETYPE_exec_t,TEMPLATETYPE_t)
allow $1 TEMPLATETYPE_t:fd use;
allow TEMPLATETYPE_t $1:fd use;
allow TEMPLATETYPE_t $1:fifo_file rw_file_perms;
allow TEMPLATETYPE_t $1:process sigchld;
')
"""
########################### Type Enforcement File #############################
te="""\
policy_module(TEMPLATETYPE,1.0.0)
########################################
#
# Declarations
#
type TEMPLATETYPE_t;
type TEMPLATETYPE_exec_t;
domain_type(TEMPLATETYPE_t)
init_daemon_domain(TEMPLATETYPE_t, TEMPLATETYPE_exec_t)
"""
te_pidfile="""
# pid files
type TEMPLATETYPE_var_run_t;
files_pid_file(TEMPLATETYPE_var_run_t)
"""
te_logfile="""
# log files
type TEMPLATETYPE_var_log_t;
logging_log_file(TEMPLATETYPE_var_log_t)
"""
te_libfile="""
# var/lib files
type TEMPLATETYPE_var_lib_t;
files_type(TEMPLATETYPE_var_lib_t)
"""
te_sep="""
########################################
#
# TEMPLATETYPE local policy
#
# Check in /etc/selinux/refpolicy/include for macros to use instead of allow rules.
# Some common macros (you might be able to remove some)
files_read_etc_files(TEMPLATETYPE_t)
libs_use_ld_so(TEMPLATETYPE_t)
libs_use_shared_libs(TEMPLATETYPE_t)
miscfiles_read_localization(TEMPLATETYPE_t)
## internal communication is often done using fifo and unix sockets.
allow TEMPLATETYPE_t self:fifo_file { read write };
allow TEMPLATETYPE_t self:unix_stream_socket create_stream_socket_perms;
"""
te_pidfile2="""
# pid file
allow TEMPLATETYPE_t TEMPLATETYPE_var_run_t:file manage_file_perms;
allow TEMPLATETYPE_t TEMPLATETYPE_var_run_t:sock_file manage_file_perms;
allow TEMPLATETYPE_t TEMPLATETYPE_var_run_t:dir rw_dir_perms;
files_pid_filetrans(TEMPLATETYPE_t,TEMPLATETYPE_var_run_t, { file sock_file })
"""
te_logfile2="""
# log files
allow TEMPLATETYPE_t TEMPLATETYPE_var_log_t:file create_file_perms;
allow TEMPLATETYPE_t TEMPLATETYPE_var_log_t:sock_file create_file_perms;
allow TEMPLATETYPE_t TEMPLATETYPE_var_log_t:dir { rw_dir_perms setattr };
logging_log_filetrans(TEMPLATETYPE_t,TEMPLATETYPE_var_log_t,{ sock_file file dir })
"""
te_libfile2="""
# var/lib files for TEMPLATETYPE
allow TEMPLATETYPE_t TEMPLATETYPE_var_lib_t:file create_file_perms;
allow TEMPLATETYPE_t TEMPLATETYPE_var_lib_t:sock_file create_file_perms;
allow TEMPLATETYPE_t TEMPLATETYPE_var_lib_t:dir create_dir_perms;
files_var_lib_filetrans(TEMPLATETYPE_t,TEMPLATETYPE_var_lib_t, { file dir sock_file })
"""
te_network2="""
## Networking basics (adjust to your needs!)
sysnet_dns_name_resolve(TEMPLATETYPE_t)
corenet_tcp_sendrecv_all_if(TEMPLATETYPE_t)
corenet_tcp_sendrecv_all_nodes(TEMPLATETYPE_t)
corenet_tcp_sendrecv_all_ports(TEMPLATETYPE_t)
corenet_non_ipsec_sendrecv(TEMPLATETYPE_t)
corenet_tcp_connect_http_port(TEMPLATETYPE_t)
#corenet_tcp_connect_all_ports(TEMPLATETYPE_t)
## if it is a network daemon, consider these:
#corenet_tcp_bind_all_ports(TEMPLATETYPE_t)
#corenet_tcp_bind_all_nodes(TEMPLATETYPE_t)
allow TEMPLATETYPE_t self:tcp_socket { listen accept };
"""
te_initsc2="""
# Init script handling
init_use_fds(TEMPLATETYPE_t)
init_use_script_ptys(TEMPLATETYPE_t)
domain_use_interactive_fds(TEMPLATETYPE_t)
"""
########################### File Context ##################################
fc="""\
# TEMPLATETYPE executable will have:
# label: system_u:object_r:TEMPLATETYPE_exec_t
# MLS sensitivity: s0
# MCS categories: <none>
EXECUTABLE -- gen_context(system_u:object_r:TEMPLATETYPE_exec_t,s0)
"""
fc_pidfile="""\
FILENAME gen_context(system_u:object_r:TEMPLATETYPE_var_run_t,s0)
"""
fc_logfile="""\
FILENAME gen_context(system_u:object_r:TEMPLATETYPE_var_log_t,s0)
"""
fc_libfile="""\
FILENAME gen_context(system_u:object_r:TEMPLATETYPE_var_lib_t,s0)
"""
def errorExit(error):
sys.stderr.write("%s: " % sys.argv[0])
sys.stderr.write("%s\n" % error)
sys.stderr.flush()
sys.exit(1)
def write_te_file(module, pidfile, logfile, libfile, network, initsc):
file="%s.te" % module
newte=re.sub("TEMPLATETYPE", module, te)
if pidfile:
newte= newte + re.sub("TEMPLATETYPE", module, te_pidfile)
if logfile:
newte= newte + re.sub("TEMPLATETYPE", module, te_logfile)
if libfile:
newte= newte + re.sub("TEMPLATETYPE", module, te_libfile)
newte= newte + re.sub("TEMPLATETYPE", module, te_sep)
if pidfile:
newte= newte + re.sub("TEMPLATETYPE", module, te_pidfile2)
if logfile:
newte= newte + re.sub("TEMPLATETYPE", module, te_logfile2)
if libfile:
newte= newte + re.sub("TEMPLATETYPE", module, te_libfile2)
if network:
newte= newte + re.sub("TEMPLATETYPE", module, te_network2)
if initsc:
newte= newte + re.sub("TEMPLATETYPE", module, te_initsc2)
if os.path.exists(file):
errorExit("%s already exists" % file)
fd = open(file, 'w')
fd.write(newte)
fd.close()
def write_if_file(module):
file="%s.if" % module
newif=re.sub("TEMPLATETYPE", module, interface)
if os.path.exists(file):
errorExit("%s already exists" % file)
fd = open(file, 'w')
fd.write(newif)
fd.close()
def write_fc_file(module, executable, pidfile, logfile, libfile):
file="%s.fc" % module
temp=re.sub("TEMPLATETYPE", module, fc)
newfc=re.sub("EXECUTABLE", executable, temp)
if pidfile:
temp=re.sub("TEMPLATETYPE", module, fc_pidfile)
newfc=newfc + re.sub("FILENAME", pidfile, temp)
if logfile:
temp=re.sub("TEMPLATETYPE", module, fc_logfile)
newfc=newfc + re.sub("FILENAME", logfile, temp)
if libfile:
temp=re.sub("TEMPLATETYPE", module, fc_libfile)
newfc=newfc + re.sub("FILENAME", libfile, temp)
if os.path.exists(file):
errorExit("%s already exists" % file)
fd = open(file, 'w')
fd.write(newfc)
fd.close()
def gen_policy(module, executable, pidfile, logfile, libfile, initsc, network):
write_te_file(module, pidfile, logfile, libfile, initsc, network)
write_if_file(module)
write_fc_file(module, executable, pidfile, logfile, libfile)
if __name__ == '__main__':
def usage(message = ""):
print '%s ModuleName Executable' % sys.argv[0]
sys.exit(1)
if len(sys.argv) != 3:
usage()
print """\n
This tool generate three files for policy development, A Type Enforcement (te)
file, a File Context (fc), and a Interface File(if). Most of the policy rules
will be written in the te file. Use the File Context file to associate file
paths with security context. Use the interface rules to allow other protected
domains to interact with the newly defined domains.
After generating these files use the /usr/share/selinux/POLICY-NAME/include/Makefile to
compile your policy package. Then use the semodule tool to load it.
# /usr/bin/policygentool myapp /usr/bin/myapp
# echo 'HEADERDIR:=/usr/share/selinux/refpolicy-targeted/include' >Makefile
# echo 'include $(HEADERDIR)/Makefile' >> Makefile
# make
# semodule -l myapp.pp
# restorecon -R -v /usr/bin/myapp "all files defined in myapp.fc"
Now you can turn on permissive mode, start your application and avc messages
will be generated. You can use audit2allow to help translate the avc messages
into policy.
# setenforce 0
# /etc/init.d/myapp start
# audit2allow -R -i /var/log/audit/audit.log
Return to continue:"""
sys.stdin.readline().rstrip()
print 'If the module uses pidfiles, what is the pidfile called?'
pidfile = sys.stdin.readline().rstrip()
if pidfile == "":
pidfile = None
print 'If the module uses logfiles, where are they stored?'
logfile = sys.stdin.readline().rstrip()
if logfile == "":
logfile = None
print 'If the module has var/lib files, where are they stored?'
libfile = sys.stdin.readline().rstrip()
if libfile == "":
libfile = None
print 'Does the module have a init script? [yN]'
initsc = sys.stdin.readline().rstrip()
if initsc == "" or initsc == "n" or initsc == "N":
initsc = False
elif initsc == "y" or initsc == "Y":
initsc = True
else:
raise "Please answer with 'y' or 'n'!"
print 'Does the module use the network? [yN]'
network = sys.stdin.readline().rstrip()
if network == "" or network == "n" or network == "N":
network = False
elif network == "y" or network == "Y":
network = True
else:
raise "Please answer with 'y' or 'n'!"
gen_policy(
module=sys.argv[1],
executable=sys.argv[2],
pidfile=pidfile,
logfile=logfile,
libfile=libfile,
initsc=initsc,
network=network
)
|