#! /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 # # import os, sys, getopt import re ########################### Interface File ############################# interface="""\ ## policy for TEMPLATETYPE ######################################## ## ## Execute a domain transition to run TEMPLATETYPE. ## ## ## ## Domain allowed to transition. ## ## # interface(`TEMPLATETYPE_domtrans',` gen_require(` type TEMPLATETYPE_t, TEMPLATETYPE_exec_t; ') domain_auto_trans($1,TEMPLATETYPE_exec_t,TEMPLATETYPE_t) 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_logfile=""" # log files type TEMPLATETYPE_var_log_t; logging_log_file(TEMPLATETYPE_var_log_t) """ te_pidfile=""" # pid files type TEMPLATETYPE_var_run_t; files_pid_file(TEMPLATETYPE_var_run_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: 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 libfile: newte= newte + re.sub("TEMPLATETYPE", module, te_libfile) if logfile: newte= newte + re.sub("TEMPLATETYPE", module, te_logfile) if pidfile: newte= newte + re.sub("TEMPLATETYPE", module, te_pidfile) newte= newte + re.sub("TEMPLATETYPE", module, te_sep) if libfile: newte= newte + re.sub("TEMPLATETYPE", module, te_libfile2) if logfile: newte= newte + re.sub("TEMPLATETYPE", module, te_logfile2) if pidfile: newte= newte + re.sub("TEMPLATETYPE", module, te_pidfile2) 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/devel/Makefile to compile your policy package. Then use the semodule tool to load it. # /usr/share/selinux/devel/policygentool myapp /usr/bin/myapp # make -f /usr/share/selinux/devel/Makefile # semodule -i 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 # service 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 )