Skip to content

Commit

Permalink
Merge pull request #386 from sylabs/master
Browse files Browse the repository at this point in the history
Merge master to release-3.9 for 3.9.0-rc.2
  • Loading branch information
dtrudg authored Oct 28, 2021
2 parents 2993c7c + c4593d5 commit e85e9b0
Show file tree
Hide file tree
Showing 28 changed files with 392 additions and 290 deletions.
39 changes: 39 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
# SingularityCE Changelog

## v3.9.0-rc.2 \[2021-10-28\]

This is a _release candidate_ for SingularityCE 3.9.0

### Security related fixes

- Due to trusting a path to an executable that was incorrectly
generated in code that could be manipulated by an unprivileged user,
privilege escalation was possible when using the new `--nvccli` GPU
configuration option. This vulnerability affected the 3.9.0-rc.1
release candidate only. Stable releases of SingularityCE are not
impacted.

All users who have installed 3.9.0-rc.1 should update to 3.9.0-rc.2

Thanks to @cclerget for reporting this issue.

### Changed defaults / behaviours

- The location of the `cryptsetup`, `ldconfig` and `nvidia-container-cli`
binaries are always taken from `singularity.conf`. No `$PATH` search is
performed.

### Bug fixes

- Ensure a build with `--nvccli` runs using `nvidia-container-cli` and
not the legacy gpu support.
- Advise on limitations and provide workaround for inability to run
`%test` in `--fakeroot` `--nvccli` builds.

## v3.9.0-rc.1 \[2021-10-14\]

This is a _release candidate_ for SingularityCE 3.9.0
Expand Down Expand Up @@ -95,6 +125,15 @@ This is a _release candidate_ for SingularityCE 3.9.0
- The `oci` commands will operate on systems that use the v2 unified cgroups
hierarchy.

## v3.8.4 \[2021-10-28\]

### Bug fixes

- Update `oras-go` dependency to address push failures to some registry
configurations.
- Implement context cancellation when a signal is received in several CLI
commands.

## v3.8.3 \[2021-09-01\]

## Bug fixes
Expand Down
4 changes: 1 addition & 3 deletions cmd/internal/cli/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ func actionPreRun(cmd *cobra.Command, args []string) {
userPath := strings.Join([]string{os.Getenv("PATH"), defaultPath}, ":")
os.Setenv("USER_PATH", userPath)

ctx := context.TODO()

replaceURIWithImage(ctx, cmd, args)
replaceURIWithImage(cmd.Context(), cmd, args)

// --compat infers other options that give increased OCI / Docker compatibility
// Excludes uts/user/net namespaces as these are restrictive for many Singularity
Expand Down
12 changes: 3 additions & 9 deletions cmd/internal/cli/actions_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -784,14 +784,9 @@ func SetGPUConfig(engineConfig *singularityConfig.EngineConfig) error {
// from starter, so fall back to legacy NV handling until that workflow is refactored heavily.
fakeRootPriv := IsFakeroot && engineConfig.File.AllowSetuid && (buildcfg.SINGULARITY_SUID_INSTALL == 1)
if !fakeRootPriv {
nvCCLIPath, err := gpu.GetNvCCLIPath()
if err == nil {
return setNvCCLIConfig(engineConfig, nvCCLIPath)
}
sylog.Warningf("While looking for nividia-container-cli: %v", err)
return setNvCCLIConfig(engineConfig)
}
sylog.Infof("nvidia-container-cli not available / not supported - using legacy GPU configuration")
return setNVLegacyConfig(engineConfig)
return fmt.Errorf("--fakeroot does not support --nvccli in set-uid installations")
}

if Rocm {
Expand All @@ -801,10 +796,9 @@ func SetGPUConfig(engineConfig *singularityConfig.EngineConfig) error {
}

// setNvCCLIConfig sets up EngineConfig entries for NVIDIA GPU configuration via nvidia-container-cli
func setNvCCLIConfig(engineConfig *singularityConfig.EngineConfig, nvcCLIPath string) (err error) {
func setNvCCLIConfig(engineConfig *singularityConfig.EngineConfig) (err error) {
sylog.Debugf("Using nvidia-container-cli for GPU setup")
engineConfig.SetNvCCLI(true)
engineConfig.SetNvCCLIPath(nvcCLIPath)

// When we use --contain we don't mount the NV devices by default in the nvidia-container-cli flow,
// they must be mounted via specifying with`NVIDIA_VISIBLE_DEVICES`. This differs from the legacy
Expand Down
11 changes: 7 additions & 4 deletions cmd/internal/cli/build_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ import (
)

func fakerootExec(cmdArgs []string) {
if buildArgs.nvccli && !buildArgs.noTest {
sylog.Warningf("Due to writable-tmpfs limitations, %%test sections will fail with --nvccli & --fakeroot")
sylog.Infof("Use -T / --notest to disable running tests during the build")
}

useSuid := buildcfg.SINGULARITY_SUID_INSTALL == 1

short := "-" + buildFakerootFlag.ShortHand
Expand Down Expand Up @@ -95,8 +100,6 @@ func fakerootExec(cmdArgs []string) {
}

func runBuild(cmd *cobra.Command, args []string) {
ctx := context.TODO()

if buildArgs.nvidia {
if buildArgs.remote {
sylog.Fatalf("--nv option is not supported for remote build")
Expand Down Expand Up @@ -150,9 +153,9 @@ func runBuild(cmd *cobra.Command, args []string) {
}

if buildArgs.remote {
runBuildRemote(ctx, cmd, dest, spec)
runBuildRemote(cmd.Context(), cmd, dest, spec)
} else {
runBuildLocal(ctx, cmd, dest, spec)
runBuildLocal(cmd.Context(), cmd, dest, spec)
}
sylog.Infof("Build complete: %s", dest)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/internal/cli/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ var deleteImageCmd = &cobra.Command{
sylog.Fatalf("Error while getting library client config: %v", err)
}

ctx, cancel := context.WithTimeout(context.TODO(), time.Duration(deleteImageTimeout)*time.Second)
ctx, cancel := context.WithTimeout(cmd.Context(), time.Duration(deleteImageTimeout)*time.Second)
defer cancel()

if err := singularity.DeleteImage(ctx, libraryConfig, r, deleteImageArch); err != nil {
Expand Down
5 changes: 1 addition & 4 deletions cmd/internal/cli/key_newpair.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
package cli

import (
"context"
"errors"
"fmt"
"os"
Expand Down Expand Up @@ -90,8 +89,6 @@ type keyNewPairOptions struct {
}

func runNewPairCmd(cmd *cobra.Command, args []string) {
ctx := context.TODO()

keyring := sypgp.NewHandle("")

opts, err := collectInput(cmd)
Expand Down Expand Up @@ -120,7 +117,7 @@ func runNewPairCmd(cmd *cobra.Command, args []string) {
sylog.Fatalf("Keyserver client failed: %s", err)
}

if err := sypgp.PushPubkey(ctx, key, co...); err != nil {
if err := sypgp.PushPubkey(cmd.Context(), key, co...); err != nil {
fmt.Printf("Failed to push newly created key to keystore: %s\n", err)
} else {
fmt.Println("Key successfully pushed to keystore")
Expand Down
4 changes: 1 addition & 3 deletions cmd/internal/cli/key_pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,12 @@ var KeyPullCmd = &cobra.Command{
Args: cobra.ExactArgs(1),
DisableFlagsInUseLine: true,
Run: func(cmd *cobra.Command, args []string) {
ctx := context.TODO()

co, err := getKeyserverClientOpts(keyServerURI, endpoint.KeyserverPullOp)
if err != nil {
sylog.Fatalf("Keyserver client failed: %s", err)
}

if err := doKeyPullCmd(ctx, args[0], co...); err != nil {
if err := doKeyPullCmd(cmd.Context(), args[0], co...); err != nil {
sylog.Errorf("pull failed: %s", err)
os.Exit(2)
}
Expand Down
4 changes: 1 addition & 3 deletions cmd/internal/cli/key_push.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,12 @@ var KeyPushCmd = &cobra.Command{
Args: cobra.ExactArgs(1),
DisableFlagsInUseLine: true,
Run: func(cmd *cobra.Command, args []string) {
ctx := context.TODO()

co, err := getKeyserverClientOpts(keyServerURI, endpoint.KeyserverPushOp)
if err != nil {
sylog.Fatalf("Keyserver client failed: %s", err)
}

if err := doKeyPushCmd(ctx, args[0], co...); err != nil {
if err := doKeyPushCmd(cmd.Context(), args[0], co...); err != nil {
sylog.Errorf("push failed: %s", err)
os.Exit(2)
}
Expand Down
4 changes: 1 addition & 3 deletions cmd/internal/cli/key_search.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,12 @@ var KeySearchCmd = &cobra.Command{
Args: cobra.ExactArgs(1),
DisableFlagsInUseLine: true,
Run: func(cmd *cobra.Command, args []string) {
ctx := context.TODO()

co, err := getKeyserverClientOpts(keyServerURI, endpoint.KeyserverSearchOp)
if err != nil {
sylog.Fatalf("Keyserver client failed: %s", err)
}

if err := doKeySearchCmd(ctx, args[0], co...); err != nil {
if err := doKeySearchCmd(cmd.Context(), args[0], co...); err != nil {
sylog.Errorf("search failed: %s", err)
os.Exit(2)
}
Expand Down
14 changes: 3 additions & 11 deletions cmd/internal/cli/oci_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
package cli

import (
"context"

"github.com/spf13/cobra"
"github.com/sylabs/singularity/docs"
"github.com/sylabs/singularity/internal/app/singularity"
Expand Down Expand Up @@ -186,9 +184,7 @@ var OciRunCmd = &cobra.Command{
DisableFlagsInUseLine: true,
PreRun: CheckRoot,
Run: func(cmd *cobra.Command, args []string) {
ctx := context.TODO()

if err := singularity.OciRun(ctx, args[0], &ociArgs); err != nil {
if err := singularity.OciRun(cmd.Context(), args[0], &ociArgs); err != nil {
sylog.Fatalf("%s", err)
}
},
Expand Down Expand Up @@ -220,9 +216,7 @@ var OciDeleteCmd = &cobra.Command{
DisableFlagsInUseLine: true,
PreRun: CheckRoot,
Run: func(cmd *cobra.Command, args []string) {
ctx := context.TODO()

if err := singularity.OciDelete(ctx, args[0]); err != nil {
if err := singularity.OciDelete(cmd.Context(), args[0]); err != nil {
sylog.Fatalf("%s", err)
}
},
Expand Down Expand Up @@ -280,9 +274,7 @@ var OciAttachCmd = &cobra.Command{
DisableFlagsInUseLine: true,
PreRun: CheckRoot,
Run: func(cmd *cobra.Command, args []string) {
ctx := context.TODO()

if err := singularity.OciAttach(ctx, args[0]); err != nil {
if err := singularity.OciAttach(cmd.Context(), args[0]); err != nil {
sylog.Fatalf("%s", err)
}
},
Expand Down
7 changes: 2 additions & 5 deletions cmd/internal/cli/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
package cli

import (
"context"
"fmt"

"github.com/spf13/cobra"
Expand Down Expand Up @@ -80,8 +79,6 @@ var PushCmd = &cobra.Command{
DisableFlagsInUseLine: true,
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
ctx := context.TODO()

file, dest := args[0], args[1]

transport, ref := uri.Split(dest)
Expand Down Expand Up @@ -119,7 +116,7 @@ var PushCmd = &cobra.Command{
FrontendURI: feURL,
}

err = singularity.LibraryPush(ctx, pushSpec, lc, co)
err = singularity.LibraryPush(cmd.Context(), pushSpec, lc, co)
if err == singularity.ErrLibraryUnsigned {
fmt.Printf("TIP: You can push unsigned images with 'singularity push -U %s'.\n", file)
fmt.Printf("TIP: Learn how to sign your own containers by using 'singularity help sign'\n\n")
Expand All @@ -136,7 +133,7 @@ var PushCmd = &cobra.Command{
sylog.Fatalf("Unable to make docker oci credentials: %s", err)
}

if err := oras.UploadImage(file, ref, ociAuth); err != nil {
if err := oras.UploadImage(cmd.Context(), file, ref, ociAuth); err != nil {
sylog.Fatalf("Unable to push image to oci registry: %v", err)
}
sylog.Infof("Upload complete")
Expand Down
42 changes: 21 additions & 21 deletions e2e/pull/pull.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2019-2020, Sylabs Inc. All rights reserved.
// Copyright (c) 2019-2021, 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.
Expand All @@ -8,6 +8,7 @@
package pull

import (
"context"
"fmt"
"io/ioutil"
"os"
Expand All @@ -17,15 +18,12 @@ import (

"github.com/containerd/containerd/reference"
"github.com/containerd/containerd/remotes/docker"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/sylabs/singularity/e2e/internal/e2e"
"github.com/sylabs/singularity/e2e/internal/testhelper"
syoras "github.com/sylabs/singularity/internal/pkg/client/oras"
"github.com/sylabs/singularity/internal/pkg/util/uri"
"golang.org/x/sys/unix"
"oras.land/oras-go/pkg/content"
"oras.land/oras-go/pkg/context"
"oras.land/oras-go/pkg/oras"
)

Expand Down Expand Up @@ -413,13 +411,12 @@ func checkPullResult(t *testing.T, tt testStruct) {
// to test the pull validation
// We can also set the layer mediaType - so we can push images with older media types
// to verify that they can still be pulled.
func orasPushNoCheck(file, ref, layerMediaType string) error {
func orasPushNoCheck(path, ref, layerMediaType string) error {
ref = strings.TrimPrefix(ref, "//")

spec, err := reference.Parse(ref)
if err != nil {
err = errors.Wrapf(err, "parse OCI reference %s", ref)
return fmt.Errorf("unable to parse oci reference: %+v", err)
return fmt.Errorf("unable to parse oci reference: %w", err)
}

// Hostname() will panic if there is no '/' in the locator
Expand All @@ -436,29 +433,32 @@ func orasPushNoCheck(file, ref, layerMediaType string) error {

resolver := docker.NewResolver(docker.ResolverOptions{})

store := content.NewFileStore("")
store := content.NewFile("")
defer store.Close()

conf, err := store.Add("$config", syoras.SifConfigMediaTypeV1, "/dev/null")
// Get the filename from path and use it as the name in the file store
name := filepath.Base(path)

desc, err := store.Add(name, layerMediaType, path)
if err != nil {
err = errors.Wrap(err, "adding manifest config to file store")
return fmt.Errorf("unable to add manifest config to FileStore: %+v", err)
return fmt.Errorf("unable to add SIF to store: %w", err)
}
conf.Annotations = nil

// use last element of filepath as file name in annotation
fileName := filepath.Base(file)
desc, err := store.Add(fileName, layerMediaType, file)
manifest, manifestDesc, config, configDesc, err := content.GenerateManifestAndConfig(nil, nil, desc)
if err != nil {
err = errors.Wrap(err, "adding manifest SIF file to file store")
return fmt.Errorf("unable to add SIF file to FileStore: %+v", err)
return fmt.Errorf("unable to generate manifest and config: %w", err)
}

if err := store.Load(configDesc, config); err != nil {
return fmt.Errorf("unable to load config: %w", err)
}

descriptors := []ocispec.Descriptor{desc}
if err := store.StoreManifest(spec.String(), manifestDesc, manifest); err != nil {
return fmt.Errorf("unable to store manifest: %w", err)
}

if _, err := oras.Push(context.Background(), resolver, spec.String(), store, descriptors, oras.WithConfig(conf)); err != nil {
err = errors.Wrap(err, "pushing to oras")
return fmt.Errorf("unable to push: %+v", err)
if _, err := oras.Copy(context.Background(), store, spec.String(), resolver, ""); err != nil {
return fmt.Errorf("unable to push: %w", err)
}

return nil
Expand Down
Loading

0 comments on commit e85e9b0

Please sign in to comment.