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