Sendmail milters in Fedora 8

Paul Howarth paul at city-fan.org
Tue Jun 3 10:44:12 UTC 2008


Daniel J Walsh wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Paul Howarth wrote:
>> Daniel J Walsh wrote:
>>> -----BEGIN PGP SIGNED MESSAGE-----
>>> Hash: SHA1
>>>
>>> Paul Howarth wrote:
>>>> On Tue, 15 Jan 2008 14:53:18 -0500
>>>> Daniel J Walsh <dwalsh at redhat.com> wrote:
>>>>
>>>>> -----BEGIN PGP SIGNED MESSAGE-----
>>>>> Hash: SHA1
>>>>>
>>>>> Paul Howarth wrote:
>>>>>> Daniel J Walsh wrote:
>>>>>>> -----BEGIN PGP SIGNED MESSAGE-----
>>>>>>> Hash: SHA1
>>>>>>>
>>>>>>> Paul Howarth wrote:
>>>>>>>> Daniel J Walsh wrote:
>>>>>>>>> -----BEGIN PGP SIGNED MESSAGE-----
>>>>>>>>> Hash: SHA1
>>>>>>>>>
>>>>>>>>> Paul Howarth wrote:
>>>>>>>>>> Hi Dan,
>>>>>>>>>>
>>>>>>>>>> Daniel J Walsh wrote:
>>>>>>>>>>> -----BEGIN PGP SIGNED MESSAGE-----
>>>>>>>>>>> Hash: SHA1
>>>>>>>>>>>
>>>>>>>>>>> Paul Howarth wrote:
>>>>>>>>>>>> Paul Howarth wrote:
>>>>>>>>>>>>> Since upgrading my mail server from Fedora 7 to Fedora 8,
>>>>>>>>>>>>> I've come across some problems with the sockets used for
>>>>>>>>>>>>> communication between
>>>>>>>>>>>>> sendmail and two of the "milter" plugins I'm using with it,
>>>>>>>>>>>>> namely milter-regex and spamass-milter. It's very likely
>>>>>>>>>>>>> that other milters
>>>>>>>>>>>>> will have similar issues.
>>>>>>>>>>>>>
>>>>>>>>>>>>> The sockets used are created when the milter starts, as
>>>>>>>>>>>>> follows:
>>>>>>>>>>>>>
>>>>>>>>>>>>> milter-regex:
>>>>>>>>>>>>> /var/spool/milter-regex/sock (var_spool_t, inherited from
>>>>>>>>>>>>> parent directory)
>>>>>>>>>>>>>
>>>>>>>>>>>>> spamass-milter:
>>>>>>>>>>>>> /var/run/spamass-milter/spamass-milter.sock
>>>>>>>>>>>>> (spamd_var_run_t, in policy)
>>>>>>>>>>>>>
>>>>>>>>>>>>> These are pretty well the upstream locations, though I'm
>>>>>>>>>>>>> open to moving the milter-regex socket from /var/spool
>>>>>>>>>>>>> to /var/run or elsewhere for consistency.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Since moving to Fedora 8, I've had to add the following to
>>>>>>>>>>>>> local policy to get these milters working:
>>>>>>>>>>>>>
>>>>>>>>>>>>> allow sendmail_t spamd_var_run_t:dir { search getattr };
>>>>>>>>>>>>> allow sendmail_t spamd_var_run_t:sock_file { getattr write };
>>>>>>>>>>>>> allow sendmail_t var_spool_t:sock_file { getattr write };
>>>>>>>>>>>>> allow sendmail_t initrc_t:unix_stream_socket { read write
>>>>>>>>>>>>> connectto };
>>>>>>>>>>>>>
>>>>>>>>>>>>> The last of these is the strangest, and relates to Bug
>>>>>>>>>>>>> #425958
>>>>>>>>>>>>> (https://bugzilla.redhat.com/show_bug.cgi?id=425958). Whilst
>>>>>>>>>>>>> the socket file itself has the context listed above, the
>>>>>>>>>>>>> unix domain socket that sendmail connects to is still
>>>>>>>>>>>>> initrc_t, as can be seen from the output of "netstat -lpZ":
>>>>>>>>>>>>>
>>>>>>>>>>>>> ...
>>>>>>>>>>>>> unix  2      [ ACC ]     STREAM     LISTENING     14142
>>>>>>>>>>>>> 5853/spamass-milter system_u:system_r:initrc_t:s0
>>>>>>>>>>>>> /var/run/spamass-milter/spamass-milter.sock
>>>>>>>>>>>>> unix  2      [ ACC ]     STREAM     LISTENING     13794
>>>>>>>>>>>>> 5779/milter-regex   system_u:system_r:initrc_t:s0
>>>>>>>>>>>>> /var/spool/milter-regex/sock
>>>>>>>>>>>>> ...
>>>>>>>>>>>>>
>>>>>>>>>>>>> So, my questions are:
>>>>>>>>>>>>>
>>>>>>>>>>>>> 1. Why are the sockets still initrc_t?
>>>>>>>>>>>>> 2. Is this a kernel issue or a userspace issue that should be
>>>>>>>>>>>>> fixed in
>>>>>>>>>>>>> the milters?
>>>>>>>>>>>>> 3. Should there be a standard place for milter sockets to
>>>>>>>>>>>>> live, and if
>>>>>>>>>>>>> so, where?
>>>>>>>>>>>>> 4. How come this worked OK in Fedora 7 and previous releases?
>>>>>>>>>>>> Looking at the source code for these applications, I see that
>>>>>>>>>>>> both of
>>>>>>>>>>>> them use the smfi_setconn() function in the sendmail milter
>>>>>>>>>>>> library to
>>>>>>>>>>>> set up the sockets. It's therefore likely that this problem is
>>>>>>>>>>>> common to
>>>>>>>>>>>> all milter applications that use unix domain sockets.
>>>>>>>>>>>>
>>>>>>>>>>>> I'm now of the opinion that moving the directory locations
>>>>>>>>>>>> for these sockets is a bad idea - it would need corresponding
>>>>>>>>>>>> changes in people's
>>>>>>>>>>>> sendmail configuration files, which would lead to problems for
>>>>>>>>>>>> people
>>>>>>>>>>>> doing package updates, or installing from upstream sources.
>>>>>>>>>>>> Setting different context types for the directories (e.g. make
>>>>>>>>>>>> /var/spool/milter-regex spamd_var_run_t) would seem a better
>>>>>>>>>>>> option, along with policy tweaks to allow sendmail to do the
>>>>>>>>>>>> permissions checks
>>>>>>>>>>>> and write to the sockets).
>>>>>>>>>>>>
>>>>>>>>>>>> I'm still confused about the initrc_t sockets though.
>>>>>>>>>>>>
>>>>>>>>>>>> Paul.
>>>>>>>>>>>>
>>>>>>>>>>>> -- 
>>>>>>>>>>>> fedora-selinux-list mailing list
>>>>>>>>>>>> fedora-selinux-list at redhat.com
>>>>>>>>>>>> https://www.redhat.com/mailman/listinfo/fedora-selinux-list
>>>>>>>>>>> Ok I will add this to the next update.
>>>>>>>>>> What exactly is "this"? The 4 "allow" rules mentioned above, the
>>>>>>>>>> context
>>>>>>>>>> type change for /var/spool/milter-regex mentioned later, both?
>>>>>>>>>>
>>>>>>>>>> Cheers, Paul.
>>>>>>>>>>
>>>>>>>>> Context change for /var/spool/milter-regex to spamd_var_run_t.
>>>>>>>>> sendmail
>>>>>>>>> can already use sockets in this directory.
>>>>>>>> So that includes the:
>>>>>>>>
>>>>>>>> allow sendmail_t initrc_t:unix_stream_socket { read write
>>>>>>>> connectto }
>>>>>>>>
>>>>>>>> ?
>>>>>>>>
>>>>>>>> Cheers, Paul.
>>>>>>>>
>>>>>>> Nope.  I don't know what is running as initrc_t and I would bet
>>>>>>> this is a leaked file descriptor.  Or at least a redirectiron of
>>>>>>> stdin/stdout.
>>>>>> I don't think it's a leaked file descriptor - that would be
>>>>>> dontaudit-able, right? By not allowing communications with the
>>>>>> initrc_t:unix_stream_socket, the milter fails to work:
>>>>>>
>>>>>> ==> /var/log/audit/audit.log <==
>>>>>> type=AVC msg=audit(1200408212.783:142453): avc:  denied
>>>>>> { connectto } for  pid=7805 comm="sendmail"
>>>>>> path="/var/spool/milter-regex/sock"
>>>>>> scontext=system_u:system_r:sendmail_t:s0
>>>>>> tcontext=system_u:system_r:initrc_t:s0 tclass=unix_stream_socket
>>>>>> type=SYSCALL msg=audit(1200408212.783:142453): arch=40000003
>>>>>> syscall=102 success=no exit=-13 a0=3 a1=bfd9f600 a2=b7f79bd4 a3=0
>>>>>> items=0 ppid=7764 pid=7805 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0
>>>>>> egid=51 sgid=51 fsgid=51 tty=(none) comm="sendmail"
>>>>>> exe="/usr/sbin/sendmail.sendmail"
>>>>>> subj=system_u:system_r:sendmail_t:s0 key=(null)
>>>>>>
>>>>>> ==> /var/log/maillog <==
>>>>>> Jan 15 14:43:32 goalkeeper sendmail[7805]: NOQUEUE: connect from
>>>>>> ard120.neoplus.adsl.tpnet.pl [83.26.189.120]
>>>>>> Jan 15 14:43:32 goalkeeper sendmail[7805]: AUTH: available
>>>>>> mech=CRAM-MD5 DIGEST-MD5, allowed mech=CRAM-MD5 DIGEST-MD5 LOGIN
>>>>>> PLAIN Jan 15 14:43:32 goalkeeper sendmail[7805]: m0FEhW21007805:
>>>>>> Milter (milter-regex): error connecting to filter: Permission denied
>>>>>> Jan 15 14:43:32 goalkeeper sendmail[7805]: m0FEhW21007805: Milter
>>>>>> (milter-regex): to error state
>>>>>> Jan 15 14:43:32 goalkeeper sendmail[7805]: m0FEhW21007805: Milter:
>>>>>> initialization failed, temp failing commands
>>>>>> Jan 15 14:43:32 goalkeeper sendmail[7805]: m0FEhW21007805: SMTP MAIL
>>>>>> command (<pathrusim at zombanewmedia.com>) from
>>>>>> ard120.neoplus.adsl.tpnet.pl [83.26.189.120] tempfailed (due to
>>>>>> previous checks)
>>>>>>
>>>>>>
>>>>>> The initrc_t type shows up in netstat but not in ls:
>>>>>> # netstat -aZp | grep initrc
>>>>>> tcp        0      0 goalkeeper.intra.:bacula-fd *:*     LISTEN    
>>>>>> 5864/bacula-fd      system_u:system_r:initrc_t:s0
>>>>>> udp        0      0 rbldns.intra.cit:domain     *:*               
>>>>>> 5885/rbldnsd        system_u:system_r:initrc_t:s0
>>>>>> unix  2      [ ACC ]     STREAM     LISTENING     14142
>>>>>> 5853/spamass-milter system_u:system_r:initrc_t:s0
>>>>>> /var/run/spamass-milter/spamass-milter.sock
>>>>>> unix  2      [ ACC ]     STREAM     LISTENING     13794
>>>>>> 5779/milter-regex   system_u:system_r:initrc_t:s0
>>>>>> /var/spool/milter-regex/sock
>>>>>> unix  2      [ ]         DGRAM                    2150436
>>>>>> 5779/milter-regex   system_u:system_r:initrc_t:s0
>>>>>> unix  2      [ ]         DGRAM                    14141
>>>>>> 5853/spamass-milter system_u:system_r:initrc_t:s0
>>>>>> # ls -lZ /var/run/spamass-milter/spamass-milter.sock
>>>>>> /var/spool/milter-regex/sock
>>>>>> srwxr-xr-x  sa-milt sa-milt system_u:object_r:spamd_var_run_t:s0
>>>>>> /var/run/spamass-milter/spamass-milter.sock
>>>>>> srw-------  mregex  mregex  system_u:object_r:spamd_var_run_t:s0
>>>>>> /var/spool/milter-regex/sock
>>>>>>
>>>>>>
>>>>>> Paul.
>>>>>>
>>>>>>
>>>>> Ok then I guess we need to label
>>>>>
>>>>> chcon -t spamd_exec_t /usr/sbin/spamass-milter
>>>>>
>>>>> And then build policy off of that.
>>>> Whilst that might result in a solution for spamass-milter, it's not
>>>> going to help milter-regex or potentially any other milter (they're all
>>>> likely to use the same libmilter [sendmail] API for setting up the
>>>> sockets).
>>>>
>>>> There seems to be something odd about sockets in general; the netstat
>>>> output quoted above shows a couple of network-listening sockets with
>>>> type initrc_t too, from a further two non-milter programs, namely
>>>> bacula and rbldnsd. I also see the same issue with nasd and rpc.quotad.
>>>> though I can also see a bunch of listening sockets with
>>>> system_u:system_r:unconfined_t on my desktop.
>>>>
>>>> Why might some of these apps transition to unconfined_t and others not?
>>>>
>>>> And why does "ls" show a different type than "netstat"?
>>>>
>>>> Paul.
>>> ls is showing file context and netstat is showing processes.
>>>
>>> Processes running as unconfined_t were started by unconfined_t without
>>> going through an initrc_exec_t type.  So either you started these
>>> processes directly or the label of their start up script is wrong
>>>
>>> ls -lZ /etc/init.d/*
>>>
>>> restorecon -R -v /etc/init.d
>>>
>>> Should fix.
>> I suspect that the stuff running in unconfined_t gets started as part of
>>  a Gnome session rather than via an initscript.
>>
>>> So we need to allow sendmail to read sockets setup by initrc_t?
>> Is it true to say (I think it is) that any process started via an
>> initscript that doesn't transition to another domain (e.g. stuff that
>> nobody has written policy for yet) will be in initrc_t?
>>
>> If so, the following is currently needed.
>>
>>> Adding
>>> init_stream_connect_script(mailserver_delivery)
>>> init_rw_script_stream_sockets(mailserver_delivery)
>>>
>>>
>>> Will allow all programs that deliver mail to read/write/connectto
>>> initrc_t unix_stream_sockets.
>> This looks right for now, though I'm tempted to hack together policy for
>> my two milters at least. What I was thinking of was creating a
>> milter_template along the lines of the apache_content_template that
>> could be used as a starting point for milter applications (all of which
>> will communicate with sendmail [and postfix too for that metter] in the
>> same way), and then add on anything necessary for each individual milter
>> (some of which would require nothing else, some would require database
>> connectivity etc.).
>>
>> Paul.
>>
> Sounds good.

I've finally got round to a first pass at this, largely because of Bug 
#447247, where it's clear that new policy for spamass-milter is needed. 
The policy I've written supports both of the milters that I maintain in 
Fedora, namely milter-regex and spamass-milter.

Comments appreciated.

# more milters.{if,fc,te}
::::::::::::::
milters.if
::::::::::::::
## <summary>Milter mail filters</summary>

########################################
## <summary>
##	Create a set of derived types for various
##	mail filter applications using the milter interface.
## </summary>
## <param name="milter_name">
##	<summary>
##	The name to be used for deriving type names.
##	</summary>
## </param>
#
template(`milter_template',`

	# Type that the milter application runs as
	type milter_$1_t;
	domain_type(milter_$1_t)
	role system_r types milter_$1_t;

	# Type for the executable file
	type milter_$1_exec_t;
	init_daemon_domain(milter_$1_t, milter_$1_exec_t)

	# This type is for pidfiles etc.
	type milter_$1_var_run_t;
	files_type(milter_$1_var_run_t);

	# This type is for spool/cache data etc.
	type milter_$1_cache_t;
	files_type(milter_$1_cache_t);

	# This type is for spool/cache data etc.
	type milter_$1_spool_t;
	files_type(milter_$1_spool_t);

	# This type is for state data etc.
	type milter_$1_var_lib_t;
	files_type(milter_$1_var_lib_t);

	# Generic rules from policygentool
	files_read_etc_files(milter_$1_t)
	libs_use_ld_so(milter_$1_t)
	libs_use_shared_libs(milter_$1_t)
	miscfiles_read_localization(milter_$1_t)
	sysnet_dns_name_resolve(milter_$1_t)
	init_use_fds(milter_$1_t)
	init_use_script_ptys(milter_$1_t)
	domain_use_interactive_fds(milter_$1_t)

	# Allow communication with MTA over a TCP socket
	# hack since this port has no interfaces since it does not have 
net_contexts
	gen_require(`
		type milter_port_t;
	')
	allow milter_$1_t milter_port_t:tcp_socket name_bind;
	corenet_tcp_bind_generic_node(milter_$1_t)
	allow milter_$1_t self:tcp_socket { listen accept };

	# Things that most milters will need to do
	allow milter_$1_t self:fifo_file rw_fifo_file_perms;
	logging_send_syslog_msg(milter_$1_t)

')

########################################
## <summary>
##	MTA communication with spamass-milter socket
## </summary>
## <param name="domain">
##	<summary>
##	Domain allowed access.
##	</summary>
## </param>
#
interface(`milter_spamass_stream_connect',`
	gen_require(`
		type milter_spamass_var_run_t, milter_spamass_t;
	')
	stream_connect_pattern($1,milter_spamass_var_run_t,milter_spamass_var_run_t,milter_spamass_t)
')

########################################
## <summary>
##	Allow read/write unix stream sockets from spamass-milter
## </summary>
## <param name="domain">
##      <summary>
##      Domain allowed access.
##      </summary>
## </param>
#
interface(`milter_spamass_rw_stream_sockets',`
         gen_require(`
                 type milter_spamass_t;
         ')

	allow $1 milter_spamass_t:unix_stream_socket { read write };
')


########################################
## <summary>
##	MTA communication with milter-regex socket
## </summary>
## <param name="domain">
##	<summary>
##	Domain allowed access.
##	</summary>
## </param>
#
interface(`milter_regex_stream_connect',`
	gen_require(`
		type milter_regex_spool_t, milter_regex_t;
	')
	stream_connect_pattern($1,milter_regex_spool_t,milter_regex_spool_t,milter_regex_t)
')
::::::::::::::
milters.fc
::::::::::::::
#================= contexts for milter-regex =================

/usr/sbin/milter-regex		-- 
gen_context(system_u:object_r:milter_regex_exec_t,s0)

/var/spool/milter-regex(/.*)?	 
gen_context(system_u:object_r:milter_regex_spool_t,s0)

#================= contexts for spamass-milter =================

/usr/sbin/spamass-milter	-- 
gen_context(system_u:object_r:milter_spamass_exec_t,s0)

/var/run/spamass-milter\.pid	-- 
gen_context(system_u:object_r:milter_spamass_var_run_t,s0)
/var/run/spamass-milter(/.*)?	 
gen_context(system_u:object_r:milter_spamass_var_run_t,s0)


::::::::::::::
milters.te
::::::::::::::
policy_module(milters,0.0.7)

require {
	attribute port_type;
}

type milter_port_t, port_type;

#============= milter-regex policy ==============
milter_template(regex)

# Config is in /etc/mail/milter-regex.conf
mta_read_config(milter_regex_t)

# The milter creates a socket in /var/spool/milter-regex/
# for communication with sendmail
files_search_spool(milter_regex_t)
manage_sock_files_pattern(milter_regex_t,milter_regex_spool_t,milter_regex_spool_t)

# It removes any existing socket (not owned by root) whilst running as root
# and then calls setgid() and setuid() to drop privileges
allow milter_regex_t self:capability { setuid setgid dac_override };


#============= spamass-milter policy ==============
milter_template(spamass)

# The milter creates a socket in /var/run/spamass-milter/
# for communication with sendmail
manage_files_pattern(milter_spamass_t,milter_spamass_var_run_t,milter_spamass_var_run_t)
manage_sock_files_pattern(milter_spamass_t,milter_spamass_var_run_t,milter_spamass_var_run_t)

# The main job of the milter is to pipe spam through spamc and act on 
the result
spamassassin_domtrans_spamc(milter_spamass_t)

# When used with -b or -B options, the milter invokes sendmail to send mail
# to a spamtrap address, using popen()
corecmd_exec_shell(milter_spamass_t)
corecmd_read_bin_symlinks(milter_spamass_t)
corecmd_search_bin(milter_spamass_t)
kernel_read_system_state(milter_spamass_t)
mta_send_mail(milter_spamass_t)


#============= extra stuff that will need adding to other modules 
=============
require {
	class file append;
	type sendmail_t;
	type spamc_t;
	type system_mail_t;
	type user_home_t;
}

#============= sendmail_t ==============
milter_spamass_stream_connect(sendmail_t)
milter_regex_stream_connect(sendmail_t)

#============= system_mail_t ==============
milter_spamass_rw_stream_sockets(system_mail_t)

#============= spamc_t ==============
# Leaky file descriptor when delivering local mail when passing through 
spamc?
#
# procmail log
userdom_dontaudit_append_unpriv_home_content_files(spamc_t)
#
# message body for locally-originated mail
mta_dontaudit_rw_queue(spamc_t)




Paul.




More information about the fedora-selinux-list mailing list