Proposal: Set supplementary groups via ‘os.initgroups’ (was: Support for Initializing the Supplementary Group List.)

Ben Finney ben+python at benfinney.id.au
Wed Dec 17 04:31:13 UTC 2014


I think this is a feasible addition, and it meets the need several
developers have requested. Below, I go through the combinations and
propose new behaviour.


On 18-Jul-2014, Malcolm Purvis wrote:

> I'm not sure about whether it should be made compulsory. Daemons can
> run as root, and at present setting the uid and gid are optional, so
> requiring initgroups could introduce unexpected behaviour.

I can see the following relevant variables:

* Which UID is the process running as before ‘DaemonContext.open()’?
  If that's the superuser, ‘os.initgroups’ will work, otherwise it
  raises ‘OSError’.

  This is also the case for ‘os.setgid’ though, so running as
  non-superuser will cause either call to fail.

* Is the specified UID in the ‘passwd’ table? If it is, looking for
  the corresponding username will succeed. If not, we have no username
  to pass to ‘os.initgroups’.

Are there other relevant variables?


> Generally you'd want to set all of the supplementary groups or none
> at all. There is an underlying system call, setgroups(2) which can
> be used to set an arbitrary collection of groups, but initgroups()
> provides the common behaviour.

I have had several people request setting the OS-defined groups for
the user; none have expressed interest in specifying which groups to
set. I think this use case can be ignored for now.


Presently, ‘DaemonContext.open’ is documented to “Set the process UID
and GID to the `uid` and `gid` attribute values.” That will remain the
same if instead of ‘os.setgid’ we use ‘os.initgroups’, because the
latter also sets the specified GID.

So it seems the backward-compatibility concerns are not large; we are
doing more, but losing no existing behaviour.


Given the above, I propose the following new behaviour:

* A new option, ‘DaemonContext.initgroups’, defaulting to True.

* The normal code path in ‘DaemonContext.open’ (actually the helper
  function ‘change_process_owner’) replaces the ‘os.setgid’ call with
  a call to ‘os.initgroups’.

  For calling ‘os.initgroups’, the username parameter is derived from
  the ‘DaemonContext.uid’ value. The GID parameter is the
  ‘DaemonContext.gid’ value.

  * The ‘os.setgid’ function is called instead, if any of the following
    is true:

    * If the ‘DaemonContext.initgroups’ option is false.

    * If the ‘DaemonContext.uid’ value is not found in the ‘passwd’
      table, instead ‘os.setgid’ is called (duplicating current
      behaviour in this condition).

      There are no supplementary groups to be found in this case
      anyway, so the call is equivalent.

* If the ‘os.initgroups’ call, or the ‘os.setgid’ call, fails with an
  OSError, a corresponding DaemonOSEnvironmentError is raised. (This
  is the same behaviour with the current ‘os.setgid’ call, but bears
  mentioning.)

Does that sound like the right behaviour?

-- 
 \      “At my lemonade stand I used to give the first glass away free |
  `\          and charge five dollars for the second glass. The refill |
_o__)                            contained the antidote.” —Emo Philips |
Ben Finney <ben at benfinney.id.au>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.alioth.debian.org/pipermail/python-daemon-devel/attachments/20141217/49203dd8/attachment.sig>


More information about the python-daemon-devel mailing list