Esempio n. 1
0
// OpenPackageFile opens a given snap file with the right backend
func OpenPackageFile(path string) (PackageFile, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	// look, libmagic!
	header := make([]byte, 20)
	if _, err := f.Read(header); err != nil {
		return nil, err
	}
	// note that we only support little endian squashfs for now
	if bytes.HasPrefix(header, []byte{'h', 's', 'q', 's'}) {
		return snapfs.New(path), nil
	}
	if strings.HasPrefix(string(header), "!<arch>\ndebian") {
		return clickdeb.Open(path)
	}

	return nil, fmt.Errorf("unknown header %v", header)
}
Esempio n. 2
0
// Open opens a given snap file with the right backend
func Open(path string) (File, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, fmt.Errorf("cannot open snap: %v", err)
	}
	defer f.Close()

	// look, libmagic!
	header := make([]byte, 20)
	if _, err := f.ReadAt(header, 0); err != nil {
		return nil, fmt.Errorf("cannot read snap: %v", err)
	}
	// Note that we only support little endian squashfs. There
	// is nothing else with squashfs 4.0.
	if bytes.HasPrefix(header, []byte{'h', 's', 'q', 's'}) {
		return squashfs.New(path), nil
	}
	if strings.HasPrefix(string(header), "!<arch>\ndebian") {
		return clickdeb.Open(path)
	}

	return nil, fmt.Errorf("cannot open snap: unknown header: %q", header)
}
Esempio n. 3
0
func unpackAndDropPrivs(snapFile, targetDir, rootDir string) error {

	d, err := clickdeb.Open(snapFile)
	if err != nil {
		return err
	}
	defer d.Close()

	if helpers.ShouldDropPrivs() {
		var dropPrivsUser string

		// first find out what user to use
		passFile := passwdFile(rootDir, "passwd")
		for _, dropPrivsUser = range dropPrivsUsers {
			_, err := readUID(dropPrivsUser, passFile)
			if err == nil {
				break
			}
		}

		// then get uid/gid
		uid, err := readUID(dropPrivsUser, passFile)
		if err != nil {
			return err
		}

		groupFile := passwdFile(rootDir, "group")
		gid, err := readUID(dropPrivsUser, groupFile)
		if err != nil {
			return err
		}

		if err := os.MkdirAll(targetDir, 0755); err != nil {
			return err
		}

		if err := os.Chown(targetDir, uid, gid); err != nil {
			return err
		}

		// Setuid and Setgid only apply to the current Linux thread, so make
		// sure we don't get moved.
		runtime.LockOSThread()

		// run prctl(PR_SET_NO_NEW_PRIVS)
		rc := C.prctl_no_new_privs()
		if rc < 0 {
			return fmt.Errorf("prctl(PR_SET_NO_NEW_PRIVS) failed with %v", rc)
		}

		if err := syscall.Setgroups([]int{gid}); err != nil {
			return fmt.Errorf("Setgroups([]{%d}) call failed: %v", gid, err)
		}

		if err := setgid(gid); err != nil {
			return fmt.Errorf("Setgid(%d) call failed: %v", gid, err)
		}
		if err := setuid(uid); err != nil {
			return fmt.Errorf("Setuid(%d) call failed: %v", uid, err)
		}

		// extra paranoia
		if syscall.Getuid() != uid || syscall.Getgid() != gid {
			return fmt.Errorf("Dropping privileges failed, uid is %v, gid is %v", syscall.Getuid(), syscall.Getgid())
		}
	}

	return d.UnpackAll(targetDir)
}