Created
February 7, 2020 03:47
-
-
Save cyphar/47cbc8fc4209af7f598605a61a0ecad7 to your computer and use it in GitHub Desktop.
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
// libpathrs: safe path resolution on Linux | |
// Copyright (C) 2019, 2020 Aleksa Sarai <cyphar@cyphar.com> | |
// Copyright (C) 2020 Maxim Zhiburt <zhiburt@gmail.com> | |
// Copyright (C) 2019, 2020 SUSE LLC | |
// | |
// This program is free software: you can redistribute it and/or modify it under | |
// the terms of the GNU Lesser General Public License as published by the Free | |
// Software Foundation, either version 3 of the License, or (at your option) any | |
// later version. | |
// | |
// This program is distributed in the hope that it will be useful, but WITHOUT ANY | |
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | |
// PARTICULAR PURPOSE. See the GNU General Public License for more details. | |
// | |
// You should have received a copy of the GNU Lesser General Public License along | |
// with this program. If not, see <https://www.gnu.org/licenses/>. | |
// Package main implements a program which print file content to stdout | |
// safely resolving paths with libpathrs. | |
package main | |
import ( | |
"fmt" | |
"io" | |
"os" | |
"sync" | |
"github.com/openSUSE/libpathrs/contrib/bindings/go/pathrs" | |
) | |
func unwrap(err error) error { | |
type unwrappable interface { | |
Unwrap() error | |
} | |
if wrappedErr, ok := err.(unwrappable); ok { | |
return wrappedErr.Unwrap() | |
} else { | |
return nil | |
} | |
} | |
func usage() { | |
fmt.Println("usage: cat <root> <unsafe-path>") | |
os.Exit(1) | |
} | |
func main() { | |
if len(os.Args) < 3 { | |
usage() | |
} | |
rootPath := os.Args[1] | |
path := os.Args[2] | |
root, err := pathrs.Open(rootPath) | |
if err != nil { | |
printPathError(err) | |
return | |
} | |
defer root.Close() | |
/* | |
roots := []*pathrs.Root{} | |
for i := 0; i < 512; i++ { | |
newRoot, err := root.Clone() | |
if err != nil { | |
printPathError(err) | |
return | |
} | |
roots = append(roots, newRoot) | |
} | |
*/ | |
startChan := make(chan struct{}) | |
var startThreadWg sync.WaitGroup | |
var endThreadWg sync.WaitGroup | |
for i := 0; i < 512; i++ { | |
startThreadWg.Add(1) | |
endThreadWg.Add(1) | |
go func() { | |
startThreadWg.Done() | |
<-startChan | |
/* | |
for _, root := range roots { | |
root.Close() | |
} | |
*/ | |
root, err := root.Clone() | |
if err != nil { | |
printPathError(err) | |
return | |
} | |
rawRoot, err := root.IntoRaw() | |
if err != nil { | |
printPathError(err) | |
return | |
} | |
defer rawRoot.Close() | |
root, err = pathrs.RootFromRaw(rawRoot) | |
if err != nil { | |
printPathError(err) | |
return | |
} | |
defer root.Close() | |
handle, err := root.Resolve(path) | |
if err != nil { | |
printPathError(err) | |
return | |
} | |
defer handle.Close() | |
rawHandle, err := handle.IntoRaw() | |
if err != nil { | |
printPathError(err) | |
return | |
} | |
defer rawHandle.Close() | |
handle, err = pathrs.HandleFromRaw(rawHandle) | |
if err != nil { | |
printPathError(err) | |
return | |
} | |
file, err := handle.Open() | |
if err != nil { | |
printPathError(err) | |
return | |
} | |
defer file.Close() | |
_, err = io.Copy(os.Stdout, file) | |
if err != nil { | |
fmt.Printf("Cannot write content of file to stdout, %v\n", err) | |
return | |
} | |
endThreadWg.Done() | |
}() | |
} | |
startThreadWg.Wait() | |
close(startChan) | |
endThreadWg.Wait() | |
} | |
func printPathError(err error) { | |
fmt.Println("Error", err) | |
fmt.Println("Unwrapped error", unwrap(err)) | |
fmt.Println("Backtrace:") | |
if pathrsErr, ok := err.(*pathrs.Error); ok { | |
fmt.Println(pathrsErr.Backtrace()) | |
} | |
//os.Exit(1) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment