Skip to content

Commit

Permalink
pick: Add initial support for libsubid
Browse files Browse the repository at this point in the history
Pick and adapt apptainer/apptainer#2433

Original description:

This commit adds support for remote access to /etc/subuid and
/etc/subgid mappings from ldap services using libsubid. Requires
shadow-utils + libsubid.

Code ported from podman / container storage.

Signed-off-by: Andrew E. Bruno <[email protected]>
  • Loading branch information
aebruno authored and dtrudg committed Jan 15, 2025
1 parent 05ebeaa commit 3c962f2
Show file tree
Hide file tree
Showing 14 changed files with 255 additions and 12 deletions.
1 change: 1 addition & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ commands:
libfuse-dev \
libglib2.0-dev \
libseccomp-dev \
libsubid-dev \
libtool \
pkg-config \
squashfs-tools \
Expand Down
1 change: 1 addition & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ run:
- apparmor
- e2e_test
- fakeroot_engine
- libsubid
- seccomp
- selinux
- singularity_engine
Expand Down
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"--fast"
],
"go.buildFlags": [
"-tags=apparmor,fakeroot_engine,seccomp,selinux,singularity_engine,sylog"
"-tags=apparmor,fakeroot_engine,libsubid,seccomp,selinux,singularity_engine,sylog"
],
"go.testTags": "apparmor,fakeroot_engine,seccomp,selinux,singularity_engine,sylog,e2e_test,integration_test"
}
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
- Use correct username (not user's name) when computing `singularity oci` conmon
/ singularity state dir.

### New Features & Functionality

- Add support for libsubid. Sub[ug]id mappings will be retrieved from e.g. LDAP
via libsubid and sssd if Singularity is built with libsubid support (default
when libsubid headers are available).

## 4.2.2 \[2024-12-20\]

### Bug Fixes
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ The following have contributed code and/or documentation to this repository.
- Alexander Grund <[email protected]>
- Amanda Duffy <[email protected]>
- Ana Guerrero Lopez <[email protected]>
- Andrew Bruno <[email protected]>
- Ángel Bejarano <[email protected]>
- Apuã Paquola <[email protected]>
- Aron Öfjörð Jóhannesson <[email protected]>
Expand Down
16 changes: 16 additions & 0 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ sudo apt-get install -y \
zlib1g-dev
```

To include support for libsubid on Ubuntu 24.04 and above:

```sh
sudo apt-get install -y libsubid-dev
```

### RHEL / Alma Linux / Rocky Linux 8+ and Fedora

```sh
Expand All @@ -59,6 +65,16 @@ sudo yum install -y \
zlib-devel
```

To include support for libsubid:

```sh
# EL
sudo dnf --enablerepo=devel install shadow-utils-subid-devel

# Fedora
sudo dnf install shadow-utils-subid-devel
```

### SLES / openSUSE Leap

```sh
Expand Down
8 changes: 8 additions & 0 deletions LICENSE_THIRD_PARTY.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,14 @@ The source files:

Contain code from the podman project, under the Apache License, Version 2.0.

## github.com/containers/storage

The source file:

* `internal/pkg/fakeroot/idtools_supported.go`

Contains code from the podman project, under the Apache License, Version 2.0.

## github.com/containers/conmon

The source files:
Expand Down
6 changes: 6 additions & 0 deletions dist/rpm/singularity-ce.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ Requires: fuse
# FUSE 3 for squashfuse
Requires: fuse3
%endif
# Libsubid on EL / OpenSuseTumbleweed
%if "%{_target_vendor}" == "suse" && 0%{?suse_version} > 1600
BuildRequires: libsubid-devel
%else
BuildRequires: shadow-utils-subid-devel
%endif

Provides: %{name}-runtime

Expand Down
27 changes: 17 additions & 10 deletions internal/pkg/fakeroot/fakeroot.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// Copyright (c) 2019-2021, Sylabs Inc. All rights reserved.
// Copyright (c) 2019-2025, Sylabs Inc. All rights reserved.
// Copyright (c) Contributors to the Apptainer project, established as
// Apptainer a Series of LF Projects LLC.
// This software is licensed under a 3-clause BSD license. Please consult the
// LICENSE.md file distributed with the sources of this project regarding your
// rights to use or distribute this software.
Expand Down Expand Up @@ -300,19 +302,24 @@ func (c *Config) GetUserEntry(username string) (*Entry, error) {
if err != nil {
return nil, fmt.Errorf("could not retrieve user information for %s: %s", username, err)
}
for _, entry := range c.entries {

entries, err := c.getMappingEntries(u)
if err != nil {
return nil, fmt.Errorf("failed to look up mapping entries for user %s: %w", username, err)
}

for _, entry := range entries {
if entry.invalid {
continue
}
if entry.UID == u.UID {
if entry.Count == validRangeCount {
return entry, nil
} else if entry.Count > validRangeCount {
largeRangeEntries = append(largeRangeEntries, entry)
continue
}
entryCount++

if entry.Count == validRangeCount {
return entry, nil
} else if entry.Count > validRangeCount {
largeRangeEntries = append(largeRangeEntries, entry)
continue
}
entryCount++
}
var largestEntry *Entry

Expand Down
123 changes: 123 additions & 0 deletions internal/pkg/fakeroot/idtools_supported.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
//go:build linux && cgo && libsubid
// +build linux,cgo,libsubid

// Portions of this code was adopted from github.com/containers/storage
// Copyright (C) The Linux Foundation and its contributors.
// Original source released under: Apache 2.0 license
// See: https://github.com/containers/storage/blob/main/pkg/idtools/idtools_supported.go
//
// Copyright (c) Contributors to the Apptainer project, established as
// Apptainer a Series of LF Projects LLC.
// Copyright (c) 2019-2025, Sylabs Inc. All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the
// LICENSE.md file distributed with the sources of this project regarding your
// rights to use or distribute this software.

package fakeroot

import (
"errors"
"fmt"
"strings"
"unsafe"

"github.com/sylabs/singularity/v4/internal/pkg/util/user"
)

/*
#cgo LDFLAGS: -l subid
#include <shadow/subid.h>
#include <stdlib.h>
#include <stdio.h>
struct subid_range singularity_get_range(struct subid_range *ranges, int i)
{
return ranges[i];
}
#if !defined(SUBID_ABI_MAJOR) || (SUBID_ABI_MAJOR < 4)
# define subid_get_uid_ranges get_subuid_ranges
# define subid_get_gid_ranges get_subgid_ranges
#endif
*/
import "C"

func readSubid(user *user.User, isUser bool) ([]*Entry, error) {
ret := make([]*Entry, 0)
uidstr := fmt.Sprintf("%d", user.UID)

if user.Name == "ALL" {
return nil, errors.New("username ALL not supported")
}

cUsername := C.CString(user.Name)
defer C.free(unsafe.Pointer(cUsername))

cuidstr := C.CString(uidstr)
defer C.free(unsafe.Pointer(cuidstr))

var nRanges C.int
var cRanges *C.struct_subid_range
if isUser {
nRanges = C.subid_get_uid_ranges(cUsername, &cRanges)
if nRanges <= 0 {
nRanges = C.subid_get_uid_ranges(cuidstr, &cRanges)
}
} else {
nRanges = C.subid_get_gid_ranges(cUsername, &cRanges)
if nRanges <= 0 {
nRanges = C.subid_get_gid_ranges(cuidstr, &cRanges)
}
}
if nRanges < 0 {
return nil, errors.New("cannot read subids")
}
defer C.free(unsafe.Pointer(cRanges))

for i := 0; i < int(nRanges); i++ {
r := C.singularity_get_range(cRanges, C.int(i))
line := fmt.Sprintf("%d:%d:%d", user.UID, r.start, r.count)
ret = append(
ret,
&Entry{
UID: user.UID,
Start: uint32(r.start),
Count: uint32(r.count),
disabled: false,
line: line,
})
}
return ret, nil
}

func readSubuid(user *user.User) ([]*Entry, error) {
return readSubid(user, true)
}

func readSubgid(user *user.User) ([]*Entry, error) {
return readSubid(user, false)
}

func (c *Config) getMappingEntries(user *user.User) ([]*Entry, error) {
entries := make([]*Entry, 0)
for _, entry := range c.entries {
if entry.UID == user.UID {
entries = append(entries, entry)
}
}

var subidEntries []*Entry
var err error
if strings.Contains(c.file.Name(), "gid") {
subidEntries, err = readSubgid(user)
} else {
subidEntries, err = readSubuid(user)
}

if err != nil {
return nil, err
}

return append(entries, subidEntries...), nil
}
26 changes: 26 additions & 0 deletions internal/pkg/fakeroot/idtools_unsupported.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//go:build !linux || !libsubid || !cgo
// +build !linux !libsubid !cgo

// Copyright (c) Contributors to the Apptainer project, established as
// Apptainer a Series of LF Projects LLC.
// Copyright (c) 2019-2025, Sylabs Inc. All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the
// LICENSE.md file distributed with the sources of this project regarding your
// rights to use or distribute this software.

package fakeroot

import (
"github.com/sylabs/singularity/v4/internal/pkg/util/user"
)

func (c *Config) getMappingEntries(user *user.User) ([]*Entry, error) {
entries := make([]*Entry, 0)
for _, entry := range c.entries {
if entry.UID == user.UID {
entries = append(entries, entry)
}
}

return entries, nil
}
11 changes: 10 additions & 1 deletion mconfig
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/sh -
# Copyright (c) 2019-2024, Sylabs Inc. All rights reserved.
# Copyright (c) 2019-2025, Sylabs Inc. All rights reserved.
# Copyright (c) 2015-2018, Yannick Cote <[email protected]>. All rights reserved.
# Copyright (c) Contributors to the Apptainer project, established as
# Apptainer a Series of LF Projects LLC.
Expand Down Expand Up @@ -62,6 +62,7 @@ with_conmon=1
with_squashfuse=1
with_suid=1
with_seccomp_check=1
with_libsubid=1

builddir=
prefix=
Expand Down Expand Up @@ -117,6 +118,7 @@ usage_args () {
echo
echo " Singularity options:"
echo " --without-suid do not install SUID binary (linux only)"
echo " --without-libsubid do not compile libsubid support even if available (linux only)"
echo " --without-network do not compile/install network plugins (linux only)"
echo " --without-seccomp do not compile/install seccomp support (linux only)"
echo
Expand Down Expand Up @@ -376,6 +378,8 @@ while [ $# -ne 0 ]; do
verbose=1; shift;;
--without-suid)
with_suid=0; shift;;
--without-libsubid)
with_libsubid=0; shift;;
--without-network)
with_network=0; shift;;
--without-seccomp)
Expand Down Expand Up @@ -783,6 +787,11 @@ if [ "$appsec" = "1" ]; then
cat $makeit_fragsdir/go_appsec_opts.mk >> $makeit_makefile
fi

if [ "$libsubid" = "1" ]; then
drawline $makeit_fragsdir/go_libsubid_opts.mk
cat $makeit_fragsdir/go_libsubid_opts.mk >> $makeit_makefile
fi

if [ "$build_runtime" = "1" ]; then
drawline $makeit_fragsdir/go_runtime_opts.mk
cat $makeit_fragsdir/go_runtime_opts.mk >> $makeit_makefile
Expand Down
37 changes: 37 additions & 0 deletions mlocal/checks/project-post.chk
Original file line number Diff line number Diff line change
Expand Up @@ -518,3 +518,40 @@ config_add_def UNSQUASHFS_PATH \"${unsquashfs_path}\"
echo

config_add_footer

########################
# libsubid
########################
if [ "$with_libsubid" = "1" ];then
printf " checking: libsubid support... "
testprog=$makeit_testprogdir/test_libsubid
cat > ${testprog}.c << "EOF"
#include <shadow/subid.h>
#include <stdio.h>
#include <stdlib.h>
const char *Prog = "test";
FILE *shadow_logfd = NULL;
int main() {
struct subid_range *ranges = NULL;
#if SUBID_ABI_MAJOR >= 4
subid_get_uid_ranges("root", &ranges);
#else
get_subuid_ranges("root", &ranges);
#endif
free(ranges);
return 0;
}
EOF
if ! $tgtcc -x c -o $testprog ${testprog}.c -l subid >/dev/null 2>&1; then
echo "no"
else
if ! $testprog; then
echo "no"
else
echo "yes"
libsubid=1
fi
fi
fi
2 changes: 2 additions & 0 deletions mlocal/frags/go_libsubid_opts.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GO_TAGS += libsubid
GO_TAGS_SUID += libsubid

0 comments on commit 3c962f2

Please sign in to comment.