Bug 1393404 - No supplementary group defined in systemd-nspawn container
Summary: No supplementary group defined in systemd-nspawn container
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: Fedora
Classification: Fedora
Component: systemd
Version: rawhide
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
Assignee: systemd-maint
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2016-11-09 13:09 UTC by Vít Ondruch
Modified: 2016-11-22 23:17 UTC (History)
14 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2016-11-22 23:17:49 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description Vít Ondruch 2016-11-09 13:09:25 UTC
Description of problem:
Trying to build Ruby with --new-chroot option, the test suite hangs on TestFileUtils#test_chown_R_force test. As it turns out, the test expects to have some supplementary groups of the calling process available, but while they are available using --old-chroot, they are not available using --new-chroot. I submitted ticket to upstream to improve the test [1], but I'd expect --{new,old}-chroot to provide the same experience.


Version-Release number of selected component (if applicable):
$ rpm -q mock
mock-1.3.2-1.fc26.noarch


How reproducible:


Steps to Reproduce:
1.
2.
3.

Actual results:
Supplementary groups of the calling process are not available.

Expected results:
There are some supplementary groups of the calling process available.


Additional info:
This [2] is the implementation of Process.groups method, which is internally used by the test case [3].

I tried to prepare simple reproducer in C:

```
$ cat getgroups.c 
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <limits.h>


main()
{
   gid_t groupIDs[NGROUPS_MAX];
   int i, count;

   if ((count = getgroups(NGROUPS_MAX, groupIDs)) == -1)
      perror("getgroups error");
   else
      if (count)
         for (i = 0; i < count; i++)
            printf("Group ID %d = %d\n", i + 1, (int) groupIDs[i]);
      else
            printf("No supplementary group\n");
}

$ gcc getgroups.c 
getgroups.c:7:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
 main()
 ^~~~
```

and execute it:

```
$ mock -r ruby --unpriv --old-chroot --chroot '/builddir/getgroups/a.out'
INFO: mock.py version 1.3.2 starting (python version = 3.5.2)...
Start: init plugins
INFO: selinux enabled
INFO: {'cache_topdir': '/var/cache/mock', 'cachedir': '/var/cache/mock/ruby', 'basedir': '/var/lib/mock/ruby', 'root': 'ruby', 'opts': '-o %(resultdir)s %(resultdir)s', 'cmd': 'createrepo_c', 'resultdir': '/var/lib/mock/ruby/result'}
INFO: enabled package signing
Finish: init plugins
Start: run
Start: chroot init
INFO: LVM plugin enabled. Allocated pool data: 36.71%. Allocated metadata: 20.2%.
INFO: calling preinit hooks
INFO: enabled root cache
INFO: enabled dnf cache
Start: cleaning dnf metadata
Finish: cleaning dnf metadata
Mock Version: 1.3.2
INFO: Mock Version: 1.3.2
Finish: chroot init
INFO: Running in chroot: ['/builddir/getgroups/a.out']
Start: chroot ['/builddir/getgroups/a.out']
Group ID 1 = 135
Finish: chroot ['/builddir/getgroups/a.out']
Finish: run



$ mock -r ruby --unpriv --new-chroot --chroot '/builddir/getgroups/a.out'
INFO: mock.py version 1.3.2 starting (python version = 3.5.2)...
Start: init plugins
INFO: selinux disabled
INFO: {'cmd': 'createrepo_c', 'root': 'ruby', 'cachedir': '/var/cache/mock/ruby', 'opts': '-o %(resultdir)s %(resultdir)s', 'basedir': '/var/lib/mock/ruby', 'resultdir': '/var/lib/mock/ruby/result', 'cache_topdir': '/var/cache/mock'}
INFO: enabled package signing
Finish: init plugins
Start: run
Start: chroot init
INFO: LVM plugin enabled. Allocated pool data: 36.71%. Allocated metadata: 20.2%.
INFO: calling preinit hooks
INFO: enabled root cache
INFO: enabled dnf cache
Start: cleaning dnf metadata
Finish: cleaning dnf metadata
Mock Version: 1.3.2
INFO: Mock Version: 1.3.2
Finish: chroot init
INFO: Running in chroot: ['/builddir/getgroups/a.out']
Start: chroot ['/builddir/getgroups/a.out']
No supplementary group
Finish: chroot ['/builddir/getgroups/a.out']
Finish: run
```

As you can see, the --old-chroot variant returns one group, while the --new-chroot does not return any group.


[1] https://bugs.ruby-lang.org/issues/12910
[2] https://github.com/ruby/ruby/blob/911f3d95033f54c0e02107873cbb4219e0ba377c/process.c#L5823
[3] https://github.com/ruby/ruby/blob/911f3d95033f54c0e02107873cbb4219e0ba377c/test/fileutils/test_fileutils.rb#L145

Comment 1 Miroslav Suchý 2016-11-09 13:35:33 UTC
I am able to reproduce it with plain systemd-nspawn:

[mirek@triple//tmp]1$ sudo /usr/bin/systemd-nspawn -q -M 36cda89a9cf74a088c47a782bda54299 -D /var/lib/mock/fedora-25-x86_64/root --setenv=HOSTNAME=mock --setenv=HOME=/builddir -u 1000 /bin/sh -i -l
[sudo] password for mirek: 
sh-4.3$ /a.out 
No supplementary group
sh-4.3$ id
uid=1000(mockbuild) gid=135(mockbuild) groups=135(mockbuild)

Note, that I'm not sure if "supplementary groups" should include the primary group. But it seems that this is default behaviour outside of container.

Comment 2 Zbigniew Jędrzejewski-Szmek 2016-11-22 23:17:49 UTC
The getgroups(2) man page is pretty clear:

       It is unspecified  whether  the effective group ID of the
       calling process is included in the  returned  list.
       (Thus,  an  application should also call getegid(2)
       and add or remove the resulting value.)

I don't think there's any bug here.


Note You need to log in before you can comment on or make changes to this bug.