forked from containers/buildah
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[release-1.37] fix TOCTOU error when bind and cache mounts use "src" values
- Loading branch information
Showing
28 changed files
with
1,251 additions
and
252 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package open | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"syscall" | ||
) | ||
|
||
// InChroot opens the file at `path` after chrooting to `root` and then | ||
// changing its working directory to `wd`. Both `wd` and `path` are evaluated | ||
// in the chroot. | ||
// Returns a file handle, an Errno value if there was an error and the | ||
// underlying error was a standard library error code, and a non-empty error if | ||
// one was detected. | ||
func InChroot(root, wd, path string, mode int, perm uint32) (fd int, errno syscall.Errno, err error) { | ||
requests := requests{ | ||
Root: root, | ||
Wd: wd, | ||
Open: []request{ | ||
{ | ||
Path: path, | ||
Mode: mode, | ||
Perms: perm, | ||
}, | ||
}, | ||
} | ||
results := inChroot(requests) | ||
if len(results.Open) != 1 { | ||
return -1, 0, fmt.Errorf("got %d results back instead of 1", len(results.Open)) | ||
} | ||
if results.Open[0].Err != "" { | ||
if results.Open[0].Errno != 0 { | ||
err = fmt.Errorf("%s: %w", results.Open[0].Err, results.Open[0].Errno) | ||
} else { | ||
err = errors.New(results.Open[0].Err) | ||
} | ||
} | ||
return int(results.Open[0].Fd), results.Open[0].Errno, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package open | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"os" | ||
"strings" | ||
|
||
"github.com/containers/storage/pkg/reexec" | ||
"github.com/sirupsen/logrus" | ||
"golang.org/x/sys/unix" | ||
) | ||
|
||
const ( | ||
bindFdToPathCommand = "buildah-bind-fd-to-path" | ||
) | ||
|
||
func init() { | ||
reexec.Register(bindFdToPathCommand, bindFdToPathMain) | ||
} | ||
|
||
// BindFdToPath creates a bind mount from the open file (which is actually a | ||
// directory) to the specified location. If it succeeds, the caller will need | ||
// to unmount the targetPath when it's finished using it. Regardless, it | ||
// closes the passed-in descriptor. | ||
func BindFdToPath(fd uintptr, targetPath string) error { | ||
f := os.NewFile(fd, "passed-in directory descriptor") | ||
defer func() { | ||
if err := f.Close(); err != nil { | ||
logrus.Debugf("closing descriptor %d after attempting to bind to %q: %v", fd, targetPath, err) | ||
} | ||
}() | ||
pipeReader, pipeWriter, err := os.Pipe() | ||
if err != nil { | ||
return err | ||
} | ||
cmd := reexec.Command(bindFdToPathCommand) | ||
cmd.Stdin = pipeReader | ||
var stdout bytes.Buffer | ||
var stderr bytes.Buffer | ||
cmd.Stdout, cmd.Stderr = &stdout, &stderr | ||
cmd.ExtraFiles = append(cmd.ExtraFiles, f) | ||
|
||
err = cmd.Start() | ||
pipeReader.Close() | ||
if err != nil { | ||
pipeWriter.Close() | ||
return fmt.Errorf("starting child: %w", err) | ||
} | ||
|
||
encoder := json.NewEncoder(pipeWriter) | ||
if err := encoder.Encode(&targetPath); err != nil { | ||
return fmt.Errorf("sending target path to child: %w", err) | ||
} | ||
pipeWriter.Close() | ||
err = cmd.Wait() | ||
trimmedOutput := strings.TrimSpace(stdout.String()) + strings.TrimSpace(stderr.String()) | ||
if err != nil { | ||
if len(trimmedOutput) > 0 { | ||
err = fmt.Errorf("%s: %w", trimmedOutput, err) | ||
} | ||
} else { | ||
if len(trimmedOutput) > 0 { | ||
err = errors.New(trimmedOutput) | ||
} | ||
} | ||
return err | ||
} | ||
|
||
func bindFdToPathMain() { | ||
var targetPath string | ||
decoder := json.NewDecoder(os.Stdin) | ||
if err := decoder.Decode(&targetPath); err != nil { | ||
fmt.Fprintf(os.Stderr, "error decoding target path") | ||
os.Exit(1) | ||
} | ||
if err := unix.Fchdir(3); err != nil { | ||
fmt.Fprintf(os.Stderr, "fchdir(): %v", err) | ||
os.Exit(1) | ||
} | ||
if err := unix.Mount(".", targetPath, "bind", unix.MS_BIND, ""); err != nil { | ||
fmt.Fprintf(os.Stderr, "bind-mounting passed-in directory to %q: %v", targetPath, err) | ||
os.Exit(1) | ||
} | ||
os.Exit(0) | ||
} |
Oops, something went wrong.