Skip to content

Commit

Permalink
Enhance subid check by using library function
Browse files Browse the repository at this point in the history
Fix tab

Declare structs

Error correctly if no ranges found

Signed-off-by: Martin Jackson <[email protected]>
  • Loading branch information
Martin Jackson authored and mhjacks committed Nov 30, 2022
1 parent d0fe8c4 commit 42308b0
Showing 1 changed file with 87 additions and 24 deletions.
111 changes: 87 additions & 24 deletions src/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,26 @@

package cmd

/*
#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"

import (
"bufio"
"errors"
"fmt"
"io/ioutil"
Expand All @@ -26,6 +44,7 @@ import (
"path/filepath"
"strings"
"syscall"
"unsafe"

"github.com/containers/toolbox/pkg/podman"
"github.com/containers/toolbox/pkg/utils"
Expand Down Expand Up @@ -66,6 +85,13 @@ type exitError struct {
err error
}

type subIDRange struct {
Start int
Length int
}

type ranges []subIDRange

func (e *exitError) Error() string {
if e.err != nil {
return e.err.Error()
Expand Down Expand Up @@ -141,15 +167,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 +345,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 +418,65 @@ 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)
queryType := ""

if isUser {
queryType = "subuid"
} else {
queryType = "subgid"
}

scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
uidstr := ""

prefixes := []string{currentUser.Username + ":", currentUser.Uid + ":"}
if username == "ALL" {
return nil, errors.New("username ALL not supported")
}

for scanner.Scan() {
line := scanner.Text()
for _, prefix := range prefixes {
if strings.HasPrefix(line, prefix) {
return true, nil
}
if u, err := user.Lookup(username); err == nil {
uidstr = u.Uid
}

cUsername := C.CString(username)
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))

return false, fmt.Errorf("failed to find an entry for user %s in %s", currentUser.Username, path)
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)

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 42308b0

Please sign in to comment.