[Dovecot] SELinux and "i_stream_read() failed: Permission denied"

James Butler jbutler at thebestdefense.com
Thu Apr 16 02:47:03 EEST 2009


Not a problem ... sharing a solution (this time)! Please correct my
understanding of the process, if required.

"i_stream_read() failed: Permission denied" is an error message generated
when a large-ish file (>128kb in my case) is attached to a message that
has been passed to Dovecot's deliver program when SELinux is being
enforced.

In my case, these messages are first run through Spamassassin, then passed
to deliver, however the SELinux policy that is being violated relates to
deliver, and not to Spamassassin, even though I do NOT generate the errors
WITHOUT running Spamassassin. I'm not going to guess as to why that is.
The policies below resolve the issue, and now large-ish (even LARGE)
attachments come through without a whimper with
Postfix+Spamassassin+Dovecot.

The problem is that deliver is not running with the correct SELinux policy
to be able to write to the global /tmp directory (in my case, after
receiving the big attachment from SA), even if that directory's
permissions allow it. (Bless you, SELinux!) Small-ish file attachments do
not trigger this deliver functionality.

Here's a complete error message, and its subsequent errors in the course
of delivering a large-ish message+attachment:

===================================================
deliver(user): unlink(/tmp/dovecot.deliver.. \
  1239836047.9469.46242b1037005551) failed: Permission denied
deliver(user): copy: i_stream_read() failed: Permission denied
deliver(user): read(mail, uid=1) failed: Permission denied
deliver(user): read(mail, uid=1) failed: Permission denied
deliver(user): msgid=: save failed to INBOX: Internal error occurred. \
  Refer to server log for more information. [2009-04-15 17:54:07]
===================================================

This is the final error series received before the policies were finally
updated, and shows an error during deliver's attempt to "unlink()"
(remove) the temporary file. Previous errors occurred during attempts to
"stat()"  and "creat()" (sic) the temporary files.

Basically, the "dovecot_deliver_t" context needs to be able to create,
read, write and remove files in the /tmp directory ("tmp_t" context).

Below, I am pasting my "local_postfix.te" SELinux policy file. It includes
instructions for using it, and for figuring out how to do other SELinux
policy adjustments on your own. This is my COMPLETE Postfix+Dovecot
SELinux policy group. I also have policies for Spamassassin, if anyone
wants them. If you are running Sendmail or another MTA instead of Postfix,
you can build on what you find below and establish your own policies.

I hope this proves useful. Again, please feel free to correct any
misunderstandings I may be promoting with this message.

Use at your own risk, please! No guarantees ... it just worked, for me.

James

## NOTE: I have broken lines in the following using the standard "\"
notation to fix the email format better. However the local_postfix.te file
should NOT have ANY lines broken. Remove my "\" notation and keep the
lines together and you should be okay. ##

####### HOW TO USE THIS ####################################################
# SELinux, Postfix, Dovecot                                                #
# SELinux needs help resolving Postfix+Dovecot context issues.             #
# This file + the following instructions should get you                    #
# on your way to resolving the policies between those contexts.            #
#                                                                          #
# 1) Create this file with the data shown below:                           #
#     local_postfix.te                                                     #
# 2) Compile this file:                                                    #
#     checkmodule -M -m -o local_postfix.mod local_postfix.te              #
# 3) Create SELinux policy package:                                        #
#     semodule_package -o local_postfix.pp -m local_postfix.mod            #
# 4) Move policy package to normal SELinux modules directory:              #
#     mv local_postfix.pp /etc/selinux/targeted/modules/active/modules/    #
# 5) Update kernel with new policy package:                                #
#     semodule -i \                                                        #
#       /etc/selinux/targeted/modules/active/modules/local_postfix.pp      #
#                                                                          #
# Test: Send mail from remote to this system.                              #
# Check /var/log/maillog for mail errors and                               #
# /var/log/messages & /var/log/audit/audit.log for more specific           #
# SELinux errors                                                           #
# Also, SELinux will provide the command (sealert...) for more details     #
# Use the error info you see in messages (or sealert...) to create         #
# new entries in local_postfix.te, then re-compile, package                #
# and update the kernel.                                                   #
#                                                                          #
# Alternately, you can use this to generate a .te file automatically       #
# from the SELinux errors displayed in /var/log/audit/audit.log (or        #
# from /var/log/messages IF you do NOT have audit installed):              #
#                                                                          #
#  audit2allow -m local -l -i /var/log/audit/audit.log > local_postfix.te  #
#                                                                          #
# (This is also helpful if you can't guess the correct domain/policy to    #
# use from reading the error messages.) Take the new stuff from what       #
# audit2allow creates and add it to this file, then re-compile, package    #
# and update the kernel.                                                   #
############################################################################

module local_postfix 1.0;

require {
        type admin_home_t;
        type bin_t;
        type default_t;
        type dovecot_t;
        type dovecot_deliver_t;
        type dovecot_deliver_exec_t;
        type dovecot_var_log_t;
        type etc_runtime_t;
        type fs_t;
        type home_root_t;
        type httpd_config_t;
        type httpd_t;
        type initrc_t;
        type postfix_etc_t;
        type postfix_local_t;
        type postfix_master_t;
        type postfix_postdrop_t;
        type postfix_postqueue_exec_t;
        type postfix_public_t;
        type postfix_pipe_t;
        type sendmail_t;
        type sendmail_exec_t;
        type src_t;
        type tmp_t;
        type usr_t;
        type user_home_dir_t;
        type user_home_t;
        type var_log_t;
        class capability { sys_nice chown };
        class file { append create execute execute_no_trans \
          getattr ioctl link lock read rename setattr write unlink };
        class dir { add_name getattr create read remove_name \
          rename write search setattr rmdir };
        class fifo_file { getattr write };
        class filesystem getattr;
        class sock_file write;
        class unix_stream_socket { connectto getattr read write };
}

#============= dovecot_t ===============
allow dovecot_t home_root_t:file { create getattr link lock \
 read rename setattr unlink write };
allow dovecot_t home_root_t:dir { add_name create remove_name write };

#============= dovecot_deliver_t ==============
allow dovecot_deliver_t tmp_t:dir getattr;
allow dovecot_deliver_t fs_t:filesystem getattr;
allow dovecot_deliver_t dovecot_var_log_t:file append;
allow dovecot_deliver_t initrc_t:unix_stream_socket connectto;
allow dovecot_deliver_t tmp_t:dir { add_name remove_name search write };
allow dovecot_deliver_t tmp_t:file { create read unlink write };
allow dovecot_deliver_t var_log_t:dir search;
allow dovecot_deliver_t var_log_t:file append;

#============ httpd_t =================
allow httpd_t postfix_etc_t:dir search;

#============= postfix_local_t ==============
allow postfix_local_t home_root_t:file { create getattr link unlink write };
allow postfix_local_t admin_home_t:dir { create read write };
allow postfix_local_t home_root_t:dir { add_name create remove_name write };
allow postfix_local_t clamd_var_lib_t:dir { add_name create remove_name \
 rename setattr write read };
allow postfix_local_t clamd_var_lib_t:file { create link lock read rename \
 getattr setattr unlink write };
allow postfix_local_t home_root_t:dir { rename setattr };
allow postfix_local_t self:capability { sys_nice chown };
allow postfix_local_t sendmail_exec_t:file { read execute ioctl \
 execute_no_trans };
allow postfix_local_t spamc_exec_t:file { execute execute_no_trans \
 getattr read };
allow postfix_local_t usr_t:file { append execute execute_no_trans \
 read getattr write };
allow postfix_local_t default_t:file { create getattr read write }; allow
postfix_local_t default_t:dir { add_name remove_name search write }; allow
postfix_local_t user_home_dir_t:file { read write getattr rename };

#============= postfix_master_t ===============
allow postfix_master_t src_t:dir search;

#============= postfix_pipe_t ==============
allow postfix_pipe_t bin_t:file { execute execute_no_trans read }; allow
postfix_pipe_t postfix_public_t:sock_file write;

#============= postfix_postdrop_t ===============
allow postfix_postdrop_t initrc_t:fifo_file { write getattr };
allow postfix_postdrop_t postfix_local_t:unix_stream_socket { getattr \
 read write };
allow postfix_postdrop_t user_home_t:file append;

#============= sendmail_t ==============
allow sendmail_t postfix_local_t:fifo_file { getattr write };
allow sendmail_t postfix_postqueue_exec_t:file { execute \
 execute_no_trans read };






More information about the dovecot mailing list