I’m trying to configure dovecot lmtp in multi-user mode. My error logs are filled with messages saying that an imap process cannot do a setuid to another user:

May 21 22:28:46 imap(pid 17441 user myuser): Fatal: setuid(512(myuser) from userdb lookup) failed with euid=501(adminuser): Operation not permitted (This binary should probably be called with process user set to 512(myuser) instead of 501(adminuser))

I see that others have had similar issues, but I am not able to apply any of the fixes or workarounds to solve this issue (e.g. setting libexec/dovecot/imap as setuid-root). I’ve also tried other fixes like setting the permissions to 0777 on the userdb auth for postfix smtpd.

According to the code (restrict-access.c, linked below), it appears that when a user authenticates, an imap worker process is launched that has the bid of the authenticator. When another user authenticates, this last process is used, but it does not have the permissions to perform a setuid to the new user, resulting in the Fatal error that appears in the logs.

Is this a bug, or a configuration issue? I’ve posted my doveconf below.

Any pointers would be greatly appreciated.

Steve


Related:

Code at https://github.com/dovecot/core/blob/master/src/lib/restrict-access.c:

doveconf -n:
# 2.3.0.1 (ffd8a29): /opt/local/etc/dovecot/dovecot.conf
# Pigeonhole version 0.5.0.1 (d33dca20)
# OS: Darwin 18.6.0 x86_64  apfs
auth_cache_size = 10 M
auth_gssapi_hostname = $ALL
auth_krb5_keytab = /opt/local/etc/dovecot/imap.keytab
auth_mechanisms = plain gssapi
auth_realms = host.domain.tld
auth_socket_path = /opt/local/var/run/dovecot/auth-userdb
auth_username_format = %Ln
debug_log_path = /opt/local/var/log/mail/mail-debug.log
default_internal_user = _dovecot
default_login_user = _dovenull
disable_plaintext_auth = no
first_valid_gid = 6
first_valid_uid = 6
imap_id_log = *
imap_id_send = "name" * "version" *
imap_idle_notify_interval = 29 mins
imap_urlauth_submit_user = submit
info_log_path = /opt/local/var/log/mail/mail-info.log
last_valid_gid = 100
lda_mailbox_autocreate = yes
log_path = /opt/local/var/log/mail/mail-err.log
login_log_format_elements = user=<%u> method=%m rip=%r lip=%l mpid=%e %c
mail_access_groups = mail
mail_attachment_dir = /private/var/mail/tld.domain.mail/attachments
mail_attachment_fs = sis posix:mode=0666
mail_debug = yes
mail_gid = mail
mail_home = /private/var/mail/tld.domain.mail
mail_location = mdbox:/private/var/mail/tld.domain.mail/%Ln/mdbox
mail_log_prefix = "%s(pid %p user %u): "
mail_plugins = quota zlib acl fts fts_solr fts_lucene
mail_privileged_group = mail
mail_uid = _dovecot
managesieve_notify_capability = mailto
managesieve_sieve_capability = fileinto reject envelope encoded-character vacation subaddress comparator-i;ascii-numeric relational regex imap4flags copy include variables body enotify environment mailbox date index ihave duplicate mime foreverypart extracttext imapsieve vnd.dovecot.imapsieve
mdbox_rotate_size = 200 M
namespace inbox {
  inbox = yes
  location = 
  mailbox Archive {
    auto = subscribe
    special_use = \Archive
  }
  mailbox Drafts {
    auto = subscribe
    special_use = \Drafts
  }
  mailbox Junk {
    auto = create
    special_use = \Junk
  }
  mailbox Notspam_train {
    auto = create
    special_use = \Junk
  }
  mailbox Sent {
    auto = subscribe
    special_use = \Sent
  }
  mailbox Spam_train {
    auto = create
    special_use = \Junk
  }
  mailbox Trash {
    auto = create
    special_use = \Trash
  }
  prefix = 
  separator = /
}
passdb {
  driver = pam
  name = pam
}
plugin {
  fts = solr
  fts_autoindex = yes
  fts_autoindex_exclude = \Junk
  imapsieve_mailbox1_before = file:/opt/local/etc/dovecot/sieve/report-spam.sieve
  imapsieve_mailbox1_causes = COPY APPEND
  imapsieve_mailbox1_name = Spam_train
  imapsieve_mailbox2_before = file:/opt/local/etc/dovecot/sieve/report-ham.sieve
  imapsieve_mailbox2_causes = COPY APPEND
  imapsieve_mailbox2_name = Notspam_train
  mail_log_events = delete undelete expunge copy mailbox_delete mailbox_rename
  mail_log_fields = uid box msgid from subject size flags
  quota_grace = 10%%
  quota_rule = *:storage=16G
  quota_rule2 = Trash:storage=+256M
  quota_warning = storage=100%% quota-exceeded %u
  quota_warning2 = storage=80%% quota-warning %u
  recipient_delimiter = +
  sieve = /private/var/mail/tld.domain.mail/rules/%Ln/dovecot.sieve
  sieve_after = /opt/local/etc/dovecot/sieve-after.d
  sieve_before = /opt/local/etc/dovecot/sieve-before.d
  sieve_dir = /private/var/mail/tld.domain.mail/rules/%Ln/%u
  sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment
  sieve_pipe_bin_dir = /opt/local/etc/dovecot/sieve
  sieve_plugins = sieve_imapsieve sieve_extprograms
  sieve_quota_max_storage = 50M
}
postmaster_address = postmaster@domain.tld
protocols = imap lmtp sieve
quota_full_tempfail = yes
sendmail_path = /opt/local/sbin/sendmail
service auth-worker {
  user = root
}
service auth {
  extra_groups = _keytabusers
  idle_kill = 15 mins
  unix_listener /opt/local/var/spool/postfix/private/auth {
    group = mail
    mode = 0660
    user = _postfix
  }
}
service imap-login {
  inet_listener imap {
    address = 127.0.0.1, ::1
    port = 143
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }
  process_min_avail = 6
  service_count = 0
  vsz_limit = 2 G
}
service imap {
  client_limit = 16
  process_limit = 200
  process_min_avail = 6
  service_count = 0
}
service lmtp {
  unix_listener /opt/local/var/spool/postfix/private/dovecot-lmtp {
    group = mail
    mode = 0660
    user = _postfix
  }
}
ssl = required
ssl_ca = </etc/certificates/chain.pem
ssl_cert = </etc/certificates/cert.pem
ssl_cipher_list = ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
ssl_dh =  # hidden, use -P to show it
ssl_key =  # hidden, use -P to show it
ssl_min_protocol = TLSv1.2
ssl_prefer_server_ciphers = yes
userdb {
  driver = passwd
  name = passwd
}
verbose_proctitle = yes
protocol lda {
  mail_fsync = optimized
  mail_plugins = quota zlib acl fts fts_solr fts_lucene sieve
}
protocol imap {
  mail_max_userip_connections = 50
  mail_plugins = quota zlib acl fts fts_solr fts_lucene imap_acl imap_quota imap_zlib imap_sieve
}
protocol lmtp {
  mail_fsync = optimized
  mail_plugins = quota zlib acl fts fts_solr fts_lucene sieve
}