Exemple #1
0
func op(fn string) (fd int, err error) {
	fdh, err := unix.Open(fn, unix.O_RDWR, 0)
	if err != nil {
		return -1, err
	}

	// mask := ^unix.S_IXGRP
	//    p :=   unix.S_ISGID & mask
	err = unix.Fchmod(int(fdh), unix.S_ISGID|unix.S_IRUSR|unix.S_IWUSR /*| unix.S_IRGRP | unix.S_IWGRP*/)
	if err != nil {
		return -1, err
	}
	return int(fdh), nil
}
Exemple #2
0
func MakeNetworkNS(containerID string) string {
	namespace := "/var/run/netns/" + containerID

	err := os.MkdirAll("/var/run/netns", 0600)
	Expect(err).NotTo(HaveOccurred())

	// create an empty file at the mount point
	mountPointFd, err := os.Create(namespace)
	Expect(err).NotTo(HaveOccurred())
	mountPointFd.Close()

	var wg sync.WaitGroup
	wg.Add(1)

	// do namespace work in a dedicated goroutine, so that we can safely
	// Lock/Unlock OSThread without upsetting the lock/unlock state of
	// the caller of this function.  See block comment above.
	go (func() {
		defer wg.Done()

		runtime.LockOSThread()
		defer runtime.UnlockOSThread()

		defer GinkgoRecover()

		// capture current thread's original netns
		currentThreadNetNSPath := getCurrentThreadNetNSPath()
		originalNetNS, err := unix.Open(currentThreadNetNSPath, unix.O_RDONLY, 0)
		Expect(err).NotTo(HaveOccurred())
		defer unix.Close(originalNetNS)

		// create a new netns on the current thread
		err = unix.Unshare(unix.CLONE_NEWNET)
		Expect(err).NotTo(HaveOccurred())

		// bind mount the new netns from the current thread onto the mount point
		err = unix.Mount(currentThreadNetNSPath, namespace, "none", unix.MS_BIND, "")
		Expect(err).NotTo(HaveOccurred())

		// reset current thread's netns to the original
		_, _, e1 := unix.Syscall(unix.SYS_SETNS, uintptr(originalNetNS), uintptr(unix.CLONE_NEWNET), 0)
		Expect(e1).To(BeZero())
	})()

	wg.Wait()

	return namespace
}
Exemple #3
0
// TestFcntlFlock tests whether the file locking structure matches
// the calling convention of each kernel.
func TestFcntlFlock(t *testing.T) {
	name := filepath.Join(os.TempDir(), "TestFcntlFlock")
	fd, err := unix.Open(name, unix.O_CREAT|unix.O_RDWR|unix.O_CLOEXEC, 0)
	if err != nil {
		t.Fatalf("Open failed: %v", err)
	}
	defer unix.Unlink(name)
	defer unix.Close(fd)
	flock := unix.Flock_t{
		Type:  unix.F_RDLCK,
		Start: 0, Len: 0, Whence: 1,
	}
	if err := unix.FcntlFlock(uintptr(fd), unix.F_GETLK, &flock); err != nil {
		t.Fatalf("FcntlFlock failed: %v", err)
	}
}
Exemple #4
0
// hackDump returns the value dump as a string.
func hackDump(v llvm.Value) (string, error) {
	// Open temp file.
	// TODO: Use an in-memory file instead of /tmp/x.
	fd, err := unix.Open("/tmp/x", unix.O_WRONLY|unix.O_TRUNC|unix.O_CREAT, 0644)
	if err != nil {
		return "", errutil.Err(err)
	}

	// Store original stderr.
	stderr, err := unix.Dup(2)
	if err != nil {
		return "", errutil.Err(err)
	}

	// Capture stderr and redirect its output to the temp file.
	err = unix.Dup2(fd, 2)
	if err != nil {
		return "", errutil.Err(err)
	}
	err = unix.Close(fd)
	if err != nil {
		return "", errutil.Err(err)
	}

	// Dump value.
	v.Dump()
	C.fflush_stderr()

	// Restore stderr.
	err = unix.Dup2(stderr, 2)
	if err != nil {
		return "", errutil.Err(err)
	}
	err = unix.Close(stderr)
	if err != nil {
		return "", errutil.Err(err)
	}

	// Return content of temp file.
	buf, err := ioutil.ReadFile("/tmp/x")
	if err != nil {
		return "", errutil.Err(err)
	}
	return string(buf), nil
}
Exemple #5
0
func makeNetworkNS(containerID string) string {
	namespace := "/var/run/netns/" + containerID
	pid := unix.Getpid()
	tid := unix.Gettid()

	err := os.MkdirAll("/var/run/netns", 0600)
	Expect(err).NotTo(HaveOccurred())

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()
	go (func() {
		defer GinkgoRecover()

		err = unix.Unshare(unix.CLONE_NEWNET)
		Expect(err).NotTo(HaveOccurred())

		fd, err := os.Create(namespace)
		Expect(err).NotTo(HaveOccurred())
		defer fd.Close()

		err = unix.Mount("/proc/self/ns/net", namespace, "none", unix.MS_BIND, "")
		Expect(err).NotTo(HaveOccurred())
	})()

	Eventually(namespace).Should(BeAnExistingFile())

	fd, err := unix.Open(fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid), unix.O_RDONLY, 0)
	Expect(err).NotTo(HaveOccurred())

	defer unix.Close(fd)

	_, _, e1 := unix.Syscall(unix.SYS_SETNS, uintptr(fd), uintptr(unix.CLONE_NEWNET), 0)
	Expect(e1).To(BeZero())

	return namespace
}
Exemple #6
0
// addWatch adds name to the watched file set.
// The flags are interpreted as described in kevent(2).
// Returns the real path to the file which was added, if any, which may be different from the one passed in the case of symlinks.
func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
	var isDir bool
	// Make ./name and name equivalent
	name = filepath.Clean(name)

	w.mu.Lock()
	if w.isClosed {
		w.mu.Unlock()
		return "", errors.New("kevent instance already closed")
	}
	watchfd, alreadyWatching := w.watches[name]
	// We already have a watch, but we can still override flags.
	if alreadyWatching {
		isDir = w.paths[watchfd].isDir
	}
	w.mu.Unlock()

	if !alreadyWatching {
		fi, err := os.Lstat(name)
		if err != nil {
			return "", err
		}

		// Don't watch sockets.
		if fi.Mode()&os.ModeSocket == os.ModeSocket {
			return "", nil
		}

		// Don't watch named pipes.
		if fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe {
			return "", nil
		}

		// Follow Symlinks
		// Unfortunately, Linux can add bogus symlinks to watch list without
		// issue, and Windows can't do symlinks period (AFAIK). To  maintain
		// consistency, we will act like everything is fine. There will simply
		// be no file events for broken symlinks.
		// Hence the returns of nil on errors.
		if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
			name, err = filepath.EvalSymlinks(name)
			if err != nil {
				return "", nil
			}

			w.mu.Lock()
			_, alreadyWatching = w.watches[name]
			w.mu.Unlock()

			if alreadyWatching {
				return name, nil
			}

			fi, err = os.Lstat(name)
			if err != nil {
				return "", nil
			}
		}

		watchfd, err = unix.Open(name, openMode, 0700)
		if watchfd == -1 {
			return "", err
		}

		isDir = fi.IsDir()
	}

	const registerAdd = unix.EV_ADD | unix.EV_CLEAR | unix.EV_ENABLE
	if err := register(w.kq, []int{watchfd}, registerAdd, flags); err != nil {
		unix.Close(watchfd)
		return "", err
	}

	if !alreadyWatching {
		w.mu.Lock()
		w.watches[name] = watchfd
		w.paths[watchfd] = pathInfo{name: name, isDir: isDir}
		w.mu.Unlock()
	}

	if isDir {
		// Watch the directory if it has not been watched before,
		// or if it was watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles)
		w.mu.Lock()

		watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE &&
			(!alreadyWatching || (w.dirFlags[name]&unix.NOTE_WRITE) != unix.NOTE_WRITE)
		// Store flags so this watch can be updated later
		w.dirFlags[name] = flags
		w.mu.Unlock()

		if watchDir {
			if err := w.watchDirectoryFiles(name); err != nil {
				return "", err
			}
		}
	}
	return name, nil
}
// Copyright (C) 2016  Arista Networks, Inc.
// Use of this source code is governed by the Apache License 2.0
// that can be found in the COPYING file.

package netns

import "golang.org/x/sys/unix"

// close closes the file descriptor mapped to a network namespace
func (h nsHandle) close() error {
	return unix.Close(int(h))
}

// fd returns the handle as a uintptr
func (h nsHandle) fd() int {
	return int(h)
}

// getNs returns a file descriptor mapping to the given network namespace
var getNs = func(nsName string) (handle, error) {
	fd, err := unix.Open(nsName, unix.O_RDONLY, 0)
	return nsHandle(fd), err
}

// setNs sets the process's network namespace
var setNs = func(h handle) error {
	return unix.Setns(h.fd(), unix.CLONE_NEWNET)
}