[Mailman-Users] Problems with Mailman under 'secure' Linux kernels

Richard Barrett R.Barrett at ftel.co.uk
Thu Jan 10 17:25:28 CET 2002

Barry - thanks for bringing some rtfm to bear and sorry for wasting your time.

MM 2.0.8 $build/README.LINUX reads as follows which seems define the 
problem and solution pretty clearly:

Mailman - The GNU Mailing List Management System
Copyright (C) 1998,1999,2000,2001 by the Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA


GNU/Linux seems to be the most popular platform on which to run
Mailman, which really shouldn't be a big surprise.  Here are some
hints on getting Mailman to run on Linux:

If you are running secure_linux, you probably have restricted
hardlinks turned on.  Gergely Madarasz says that this not only
restricts hardlinks in /tmp, but also in any non +t directory.  This
can cause "Operation not permitted" errors in MailList.Save() -- you
will see a traceback.  You must turn restricted hardlinks off.  This
is also known under the name of Openwall Security Patches.

There is a workaround for this problem, you can use securelinux_fix.py
in the contrib directory (see the README.securelinux_fix.py). Note
that the script will not work until you move it in your installed
Mailman tree in the bin directory.

At 10:59 10/01/2002 -0500, Barry A. Warsaw wrote:

> >>>>> "MB" == Mike Burton <mburton at jo.birdsense.com> writes:
>     MB> Thank you, Richard.  This sounds like a reasonable answer to
>     MB> what is happening.  I'm not sure that I want to reload Lunix
>     MB> to accomplish setting up Mailman.  I certainly hope there is a
>     MB> workaround that someone can share.  I also didn't mention that
>     MB> this was only through the web interface.  I can use the mail
>     MB> interface to subscribe without incident.  Oh well, guess I'll
>     MB> just have to sit back and see if there is an answer for this
>     MB> problem that comes forth.  Otherwise I guess I'm just not
>     MB> going to be able to consider Mailman on my system.  Bummer...
>Has README.LINUX not helped?  I'm attaching a few files from Mailman
>2.1 just in case they have more useful or up-to-date information.
>The script itself is probably too MM2.1-centric, but it might be
>useful so I'm including it for completeness.
>-------------------- snip snip --------------------
>Mailman - The GNU Mailing List Management System
>Copyright (C) 1998,1999,2000,2001 by the Free Software Foundation, Inc.
>59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
>     GNU/Linux seems to be the most popular platform on which to run
>     Mailman.  Here are some hints on getting Mailman to run on Linux:
>     If you are getting errors with hard link creations and/or you are using
>     a special secure kernel (securelinux/openwall/grsecurity), see
>     contrib/README.check_perms_grsecurity.
>     Note that if you are using Linux Mandrake in secure mode, you are 
> probably
>     concerned by this.
>Local Variables:
>mode: text
>indent-tabs-mode: nil
>The check_perms_grsecurity.py script, if copied in your installed
>~mailman/bin/ directory and run from there will modify permissions of
>files so that Mailman with extra restrictions imposed by linux kernel security
>patches like securelinux/openwall in 2.2.x or grsecurity in 2.4.x
>The way it works is that it makes sure that the UID of any script that
>touches config.pck is `mailman'. What this means however is that
>scripts in ~mailman/bin will now only work if run as user mailman or
>root (the script then changes its UID and GID to mailman).
>To make grsecurity happy, we remove the group writeable bit on a directories
>that contain binaries.
>Marc MERLIN <marc_soft at merlins.org>/<marc_bts at vasoftware.com> - 2001/12/10
>#! @PYTHON@
># Copyright (C) 1998,1999,2000,2001,2002 by the Free Software Foundation, Inc.
># 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
># 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.
>"""Fixes for running Mailman under the `secure-linux' patch or grsecurity.
>Run check_perms -f and only then check_perms_grsecurity.py -f
>Note that you  will have to re-run  this script after a  mailman upgrade and
>that check_perms will undo part of what this script does
>If you use  Solar Designer's secure-linux patch, it prevents  a process from
>linking (hard link) to a file it doesn't own.
>Grsecurity (http://grsecurity.net/) can have  the same restriction depending
>on how it was built, including other restrictions like preventing you to run
>a program if it is located in a directory writable by a non root user.
>As a  result Mailman has to  be changed so that  the whole tree is  owned by
>Mailman, and  the CGIs and some  of the programs  in the bin tree  (the ones
>that lock config.pck  files) are SUID Mailman.  The idea  is that config.pck
>files have to be owned by the  mailman UID and only touched by programs that
>are UID mailman.
>At the  same time, We have  to make sure  that at least 3  directories under
>~mailman aren't writable by mailman: mail, cgi-bin, and bin
>Binary commands that are changed to be SUID mailman are also made unreadable
>and unrunnable  by people who aren't  in the mailman group.   This shouldn't
>affect much since most of those commands would fail work if you weren't part
>of the mailman group anyway.
>Scripts in ~mailman/bin/ are  not made suid or sgid, they need  to be run by
>user mailman or root to work.
>Marc <marc_soft at merlins.org>/<marc_bts at vasoftware.com>
>2000/10/27 - Initial version for secure_linux/openwall and mailman 2.0
>2001/12/09 - Updated version for grsecurity and mailman 2.1
>import sys
>import os
>import paths
>import re
>import glob
>from Mailman import mm_cfg
>from Mailman.mm_cfg import MAILMAN_UID, MAILMAN_GID
>from stat import *
># Directories that we don't want writable by mailman.
>dirstochownroot= ( 'mail', 'cgi-bin', 'bin' )
># Those are the programs that we patch so that they insist being run under the
># mailman uid or as root.
>binfilestopatch= ( 'add_members', 'change_pw', 'check_db', 'clone_member',
>         'config_list', 'newlist', 'qrunner', 'remove_members',
>         'rmlist', 'sync_members', 'update', 'withlist' )
>def main(argv):
>     binpath = paths.prefix + '/bin/'
>     droplib = binpath + 'CheckFixUid.py'
>     if len(argv) < 2 or argv[1] != "-f":
>         print __doc__
>         sys.exit(1)
>     print "Making select directories owned and writable by root only"
>     for dir in dirstochownroot:
>         dirpath = paths.prefix + '/' + dir
>         os.chown(dirpath, 0, MAILMAN_GID)
>         os.chmod(dirpath, 02755)
>         print dirpath
>     print
>     file = paths.prefix + '/data/last_mailman_version'
>     print "Making" + file + "owned by mailman (not root)"
>     os.chown(file, MAILMAN_UID, MAILMAN_GID)
>     print
>     if not os.path.exists(droplib):
>         print "Creating " + droplib
>         fp = open(droplib, 'w', 0644)
>         fp.write("""import sys
>import os
>from Mailman.mm_cfg import MAILMAN_UID, MAILMAN_GID
>class CheckFixUid:
>     if os.geteuid() == 0:
>         os.setgid(MAILMAN_GID)
>         os.setuid(MAILMAN_UID)
>     if os.geteuid() != MAILMAN_UID:
>         print "You need to run this script as root or mailman because it 
> was configured to run"
>         print "on a linux system with a security patch which restricts 
> hard links"
>         sys.exit()
>         fp.close()
>     else:
>         print "Skipping creation of " + droplib
>     print "\nMaking cgis setuid mailman"
>     cgis = glob.glob(paths.prefix + '/cgi-bin/*')
>     for file in cgis:
>         print file
>         os.chown(file, MAILMAN_UID, MAILMAN_GID)
>         os.chmod(file, 06755)
>     print "\nMaking mail wrapper setuid mailman"
>     file= paths.prefix + '/mail/wrapper'
>     os.chown(file, MAILMAN_UID, MAILMAN_GID)
>     os.chmod(file, 06755)
>     print file
>     print "\nEnsuring that all config.db/pck files are owned by Mailman"
>     cdbs = glob.glob(paths.prefix + '/lists/*/config.db*')
>     cpcks = glob.glob(paths.prefix + '/lists/*/config.pck*')
>     for file in cdbs + cpcks:
>         stat = os.stat(file)
>         if (stat[ST_UID] != MAILMAN_UID or stat[ST_GID] != MAILMAN_GID):
>             print file
>             os.chown(file, MAILMAN_UID, MAILMAN_GID)
>     print "\nPatching mailman scripts to change the uid to mailman"
>     for script in binfilestopatch:
>         filefd = open(script, "r")
>         file = filefd.readlines()
>         filefd.close()
>         patched = 0
>         try:
>             file.index("import CheckFixUid\n")
>             print "Not patching " + script + ", already patched"
>         except ValueError:
>             file.insert(file.index("import paths\n")+1, "import 
> CheckFixUid\n")
>             for i in range(len(file)-1, 0, -1):
>                 object=re.compile("^([  ]*)main\(").search(file[i])
>                 # Special hack to support patching of update
>                 object2=re.compile("^([     ]*).*=[ 
> ]*main\(").search(file[i])
>                 if object:
>                     print "Patching " + script
>                     file.insert(i,
>                         object.group(1) + "CheckFixUid.CheckFixUid()\n")
>                     patched=1
>                     break
>                 if object2:
>                     print "Patching " + script
>                     file.insert(i,
>                         object2.group(1) + "CheckFixUid.CheckFixUid()\n")
>                     patched=1
>                     break
>             if patched==0:
>                 print "Warning, file "+script+" couldn't be patched."
>                 print "If you use it, mailman may not function properly"
>             else:
>                 filefd=open(script, "w")
>                 filefd.writelines(file)

More information about the Mailman-Users mailing list