Skip to content

Commit

Permalink
Enhance subid check by using library function
Browse files Browse the repository at this point in the history
Signed-off-by: Martin Jackson <[email protected]>
  • Loading branch information
Martin Jackson committed Nov 28, 2022
1 parent f392a69 commit 2a129d7
Showing 1 changed file with 82 additions and 24 deletions.
106 changes: 82 additions & 24 deletions src/cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
//go:build linux && cgo && libsubid
// +build linux,cgo,libsubid

/*
* Copyright © 2019 – 2021 Red Hat Inc.
* Copyright © 2019 – 2022 Red Hat Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -26,6 +29,7 @@ import (
"path/filepath"
"strings"
"syscall"
"unsafe"

"github.com/containers/toolbox/pkg/podman"
"github.com/containers/toolbox/pkg/utils"
Expand All @@ -34,6 +38,25 @@ import (
"github.com/spf13/cobra"
)

/*
#cgo LDFLAGS: -l subid
#include <shadow/subid.h>
#include <stdlib.h>
#include <stdio.h>
const char *Prog = "storage";
FILE *shadow_logfd = NULL;
struct subid_range get_range(struct subid_range *ranges, int i)
{
shadow_logfd = stderr;
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"

var (
cgroupsVersion int

Expand Down Expand Up @@ -141,15 +164,15 @@ func preRun(cmd *cobra.Command, args []string) error {
logrus.Debugf("Running on a cgroups v%d host", cgroupsVersion)

if currentUser.Uid != "0" {
logrus.Debugf("Checking if /etc/subgid and /etc/subuid have entries for user %s",
logrus.Debugf("Checking for subuid and subgid have entries for user %s",
currentUser.Username)

if _, err := validateSubIDFile("/etc/subuid"); err != nil {
return newSubIDFileError()
if _, err := validateSubIDRange(currentUser.Username, true); err != nil {
return newSubIDError()
}

if _, err := validateSubIDFile("/etc/subgid"); err != nil {
return newSubIDFileError()
if _, err := validateSubIDRange(currentUser.Username, false); err != nil {
return newSubIDError()
}
}
}
Expand Down Expand Up @@ -319,9 +342,9 @@ func migrate() error {
return nil
}

func newSubIDFileError() error {
func newSubIDError() error {
var builder strings.Builder
fmt.Fprintf(&builder, "/etc/subgid and /etc/subuid don't have entries for user %s\n", currentUser.Username)
fmt.Fprintf(&builder, "Missing subuid and/or subgid entries for user %s\n", currentUser.Username)
fmt.Fprintf(&builder, "See the podman(1), subgid(5), subuid(5) and usermod(8) manuals for more\n")
fmt.Fprintf(&builder, "information.")

Expand Down Expand Up @@ -392,28 +415,63 @@ func setUpLoggers() error {
return nil
}

func validateSubIDFile(path string) (bool, error) {
logrus.Debugf("Validating sub-ID file %s", path)
func validateSubIDRange(username string, isUser bool) (ranges, error) {
var ret ranges

file, err := os.Open(path)
if err != nil {
logrus.Debugf("Validating sub-ID file: failed to open %s: %s", path, err)
return false, fmt.Errorf("failed to open %s", path)
if isUser {
queryType = "subuid"
} else {
queryType = "subgid"
}

uidstr := ""

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

if u, err := user.Lookup(username); err == nil {
uidstr = u.Uid
}

scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
cUsername := C.CString(username)
defer C.free(unsafe.Pointer(cUsername))

prefixes := []string{currentUser.Username + ":", currentUser.Uid + ":"}
cuidstr := C.CString(uidstr)
defer C.free(unsafe.Pointer(cuidstr))

for scanner.Scan() {
line := scanner.Text()
for _, prefix := range prefixes {
if strings.HasPrefix(line, prefix) {
return true, nil
}
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.get_range(cRanges, C.int(i))
newRange := subIDRange{
Start: int(r.start),
Length: int(r.count),
}
ret = append(ret, newRange)

return false, fmt.Errorf("failed to find an entry for user %s in %s", currentUser.Username, path)
logrus.Debugf("Found %s range %d for %s: start [%d] length [%d]",
querytype,
i,
username,
r.start,
r.count)
}
return ret, nil
}

0 comments on commit 2a129d7

Please sign in to comment.