mirror of https://github.com/xSmurf/oz.git
parent
7f9c8b1c1c
commit
3c920c4fc1
@ -0,0 +1,18 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/subgraph/oz/oz-mount"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
runtime.LockOSThread()
|
||||||
|
runtime.GOMAXPROCS(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
defer runtime.UnlockOSThread()
|
||||||
|
|
||||||
|
mount.Main(mount.MOUNT)
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/subgraph/oz/oz-mount"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
runtime.LockOSThread()
|
||||||
|
runtime.GOMAXPROCS(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
defer runtime.UnlockOSThread()
|
||||||
|
|
||||||
|
mount.Main(mount.UMOUNT)
|
||||||
|
}
|
@ -0,0 +1,128 @@
|
|||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
int enter_mount_namespace(void) {
|
||||||
|
if (geteuid() != 0) {
|
||||||
|
fprintf(stderr, "E Must run as root\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// Do some minimal verification to check that oz-daemon is the parent
|
||||||
|
pid_t ppid = getppid();
|
||||||
|
//ppid = 10252;
|
||||||
|
if (checkProcessName(ppid, "oz-daemon") != 0) {
|
||||||
|
fprintf(stderr, "E unable to verify that oz-daemon is parent\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse namespace pid from environment
|
||||||
|
char *envv, *envvend;
|
||||||
|
long nspid;
|
||||||
|
envv = getenv("_OZ_NSPID");
|
||||||
|
if (envv == NULL) {
|
||||||
|
fprintf(stderr, "E unable to get namespace pid from environment\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
errno = 0;
|
||||||
|
nspid = strtol(envv, &envvend, 10);
|
||||||
|
if ((errno == ERANGE && (nspid == LONG_MAX || nspid == LONG_MIN))
|
||||||
|
|| (errno != 0 && nspid == 0)) {
|
||||||
|
fprintf(stderr, "E unable to parse namespace pid from environment\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (envvend == envv || nspid < 0) {
|
||||||
|
fprintf(stderr, "E unable to parse namespace pid from environment\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the target is an instance of oz-init
|
||||||
|
if (checkProcessName(nspid, "oz-init") != 0) {
|
||||||
|
fprintf(stderr, "E unable to verify that oz-init is the target\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char nspath[PATH_MAX];
|
||||||
|
if (snprintf(nspath, PATH_MAX-1, "/proc/%ld/ns", nspid) < 0) {
|
||||||
|
fprintf(stderr, "E unable to parse namespace path `/proc/%ld/ns`\n", nspid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
printf("D Opening: %s\n", nspath);
|
||||||
|
|
||||||
|
// Start opening the namespace
|
||||||
|
struct stat st;
|
||||||
|
int tfd, fd;
|
||||||
|
tfd = open(nspath, O_DIRECTORY | O_RDONLY);
|
||||||
|
if (tfd == -1) {
|
||||||
|
fprintf(stderr, "E failed to open child namespace\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// Symlinks on all namespaces exist for dead processes, but they can't be opened
|
||||||
|
if (fstatat(tfd, "mnt", &st, AT_SYMLINK_NOFOLLOW) == -1) {
|
||||||
|
if (errno == ENOENT) {
|
||||||
|
fprintf(stderr, "E failed to open child namespace\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fd = openat(tfd, "mnt", O_RDONLY);
|
||||||
|
if (fd == -1) {
|
||||||
|
fprintf(stderr, "E failed to open child mount namespace: %s\n", nspath);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// Set the namespace.
|
||||||
|
if (setns(fd, 0) == -1) {
|
||||||
|
fprintf(stderr, "E failed to setns for: %s\n", nspath);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int checkProcessName(pid_t pid, char *pname) {
|
||||||
|
FILE *fp;
|
||||||
|
char *line = NULL;
|
||||||
|
char pproc[PATH_MAX];
|
||||||
|
char cline[PATH_MAX];
|
||||||
|
size_t len = 0;
|
||||||
|
ssize_t read;
|
||||||
|
|
||||||
|
if (snprintf(cline, PATH_MAX-1, "Name: %s\n", pname) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snprintf(pproc, PATH_MAX-1, "/proc/%ld/status", pid) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = fopen(pproc, "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int retval = -1;
|
||||||
|
while (retval == -1 && (read = getline(&line, &len, fp)) != -1) {
|
||||||
|
if (hasPrefix(line, "Name:") >= 0) {
|
||||||
|
retval = strcmp(cline, line);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
if (line) {
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hasPrefix(const char *str, const char *pre) {
|
||||||
|
size_t lenpre = strlen(pre),
|
||||||
|
lenstr = strlen(str);
|
||||||
|
return lenstr < lenpre ? -1 : strncmp(pre, str, lenpre);
|
||||||
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
// +build linux,!gccgo
|
||||||
|
package mount
|
||||||
|
|
||||||
|
// extern int enter_mount_namespace(void);
|
||||||
|
/*
|
||||||
|
#include <stdlib.h>
|
||||||
|
__attribute__((constructor)) void init(void) {
|
||||||
|
if (enter_mount_namespace() < 0) {
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/subgraph/oz"
|
||||||
|
"github.com/subgraph/oz/fs"
|
||||||
|
|
||||||
|
"github.com/op/go-logging"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MOUNT = 1 << iota
|
||||||
|
UMOUNT
|
||||||
|
)
|
||||||
|
|
||||||
|
func Main(mode int) {
|
||||||
|
log := createLogger()
|
||||||
|
config, err := loadConfig()
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Could not load configuration: %s\n", oz.DefaultConfigPath, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fsys := fs.NewFilesystem(config, log)
|
||||||
|
for fii, fpath := range os.Args {
|
||||||
|
if fii == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(fpath, "/home/") {
|
||||||
|
log.Warning("Ignored `%s`, only files inside of home are permitted!", fpath)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch mode {
|
||||||
|
case MOUNT:
|
||||||
|
mount(fpath, fsys, log)
|
||||||
|
case UMOUNT:
|
||||||
|
unmount(fpath, fsys, log)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func mount(fpath string, fsys *fs.Filesystem, log *logging.Logger) {
|
||||||
|
if _, err := os.Stat(fpath); err == nil {
|
||||||
|
//log.Notice("Adding file `%s`.", fpath)
|
||||||
|
if err := fsys.BindPath(fpath, fs.BindCanCreate, nil); err != nil {
|
||||||
|
log.Error("%v while adding `%s`!", err, fpath)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmount(fpath string, fsys *fs.Filesystem, log *logging.Logger) {
|
||||||
|
sbpath := path.Join(fsys.Root(), fpath)
|
||||||
|
if _, err := os.Stat(sbpath); err == nil {
|
||||||
|
//log.Notice("Removing file `%s`.", fpath)
|
||||||
|
if err := fsys.UnbindPath(fpath); err != nil {
|
||||||
|
log.Error("%v while removing `%s`!", err, fpath)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Error("%v error while removing `%s`!", err, fpath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createLogger() *logging.Logger {
|
||||||
|
l := logging.MustGetLogger("oz-init")
|
||||||
|
be := logging.NewLogBackend(os.Stderr, "", 0)
|
||||||
|
f := logging.MustStringFormatter("%{level:.1s} %{message}")
|
||||||
|
fbe := logging.NewBackendFormatter(be, f)
|
||||||
|
logging.SetBackend(fbe)
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadConfig() (*oz.Config, error) {
|
||||||
|
config, err := oz.LoadConfig(oz.DefaultConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
config = oz.NewDefaultConfig()
|
||||||
|
} else {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
Loading…
Reference in new issue