func GetArtifact(destDir, source, checksum string, logger *log.Logger) (string, error) { if source == "" { return "", fmt.Errorf("Source url is empty in Artifact Getter") } u, err := url.Parse(source) if err != nil { return "", err } // if checksum is seperate, apply to source if checksum != "" { source = strings.Join([]string{source, fmt.Sprintf("checksum=%s", checksum)}, "?") logger.Printf("[DEBUG] client.getter: Applying checksum to Artifact Source URL, new url: %s", source) } artifactFile := filepath.Join(destDir, path.Base(u.Path)) if err := gg.GetFile(artifactFile, source); err != nil { return "", fmt.Errorf("Error downloading artifact: %s", err) } // Add execution permissions to the newly downloaded artifact if runtime.GOOS != "windows" { if err := syscall.Chmod(artifactFile, 0755); err != nil { logger.Printf("[ERR] driver.raw_exec: Error making artifact executable: %s", err) } } return artifactFile, nil }
/* ============================================================================================ */ func ChMod(filename string, mode int) bool { err := syscall.Chmod(filename, uint32(mode)) if err == nil { return true } return false }
func main() { flag.Parse() if len(flag.Args()) < 2 { flag.PrintDefaults() log.Fatalf("usage: chmod mode filepath") } octval, err := strconv.ParseUint(flag.Args()[0], 8, 32) if err != nil { log.Fatalf("Unable to decode mode. Please use an octal value. arg was %s, err was %v", flag.Args()[0], err) } else if octval > 0777 { log.Fatalf("Invalid octal value. Value larger than 777, was %o", octval) } mode := uint32(octval) var errors string for _, arg := range flag.Args()[1:] { if err := syscall.Chmod(arg, mode); err != nil { errors += fmt.Sprintf("Unable to chmod, filename was %s, err was %v\n", arg, err) } } if errors != "" { log.Fatalf(errors) } }
func (inode *SpecialInode) writeMetadata(name string) error { if err := os.Lchown(name, int(inode.Uid), int(inode.Gid)); err != nil { return err } if err := syscall.Chmod(name, uint32(inode.Mode)); err != nil { return err } t := time.Unix(inode.MtimeSeconds, int64(inode.MtimeNanoSeconds)) return os.Chtimes(name, t, t) }
// Chmod implements pathfs.Filesystem. func (fs *FS) Chmod(path string, mode uint32, context *fuse.Context) (code fuse.Status) { if fs.isFiltered(path) { return fuse.EPERM } cPath, err := fs.getBackingPath(path) if err != nil { return fuse.ToStatus(err) } // os.Chmod goes through the "syscallMode" translation function that messes // up the suid and sgid bits. So use syscall.Chmod directly. err = syscall.Chmod(cPath, mode) return fuse.ToStatus(err) }
func (inode *DirectoryInode) write(name string) error { if inode.make(name) != nil { os.RemoveAll(name) if err := inode.make(name); err != nil { return err } } if err := os.Lchown(name, int(inode.Uid), int(inode.Gid)); err != nil { return err } if inode.Mode & ^modePerm != syscall.S_IFDIR { if err := syscall.Chmod(name, uint32(inode.Mode)); err != nil { return err } } return nil }
func createTarFile(path, extractDir string, hdr *tar.Header, reader *tar.Reader) error { switch hdr.Typeflag { case tar.TypeDir: // Create directory unless it exists as a directory already. // In that case we just want to merge the two if fi, err := os.Lstat(path); !(err == nil && fi.IsDir()) { if err := os.Mkdir(path, os.FileMode(hdr.Mode)); err != nil { return err } } case tar.TypeReg, tar.TypeRegA: // Source is regular file file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, os.FileMode(hdr.Mode)) if err != nil { return err } if _, err := io.Copy(file, reader); err != nil { file.Close() return err } file.Close() case tar.TypeBlock, tar.TypeChar, tar.TypeFifo: mode := uint32(hdr.Mode & 07777) switch hdr.Typeflag { case tar.TypeBlock: mode |= syscall.S_IFBLK case tar.TypeChar: mode |= syscall.S_IFCHR case tar.TypeFifo: mode |= syscall.S_IFIFO } if err := syscall.Mknod(path, mode, int(mkdev(hdr.Devmajor, hdr.Devminor))); err != nil { return err } case tar.TypeLink: if err := os.Link(filepath.Join(extractDir, hdr.Linkname), path); err != nil { return err } case tar.TypeSymlink: if err := os.Symlink(hdr.Linkname, path); err != nil { return err } case tar.TypeXGlobalHeader: utils.Debugf("PAX Global Extended Headers found and ignored") return nil default: return fmt.Errorf("Unhandled tar header type %d\n", hdr.Typeflag) } if err := syscall.Lchown(path, hdr.Uid, hdr.Gid); err != nil { return err } // There is no LChmod, so ignore mode for symlink. Also, this // must happen after chown, as that can modify the file mode if hdr.Typeflag != tar.TypeSymlink { if err := syscall.Chmod(path, uint32(hdr.Mode&07777)); err != nil { return err } } ts := []syscall.Timespec{timeToTimespec(hdr.AccessTime), timeToTimespec(hdr.ModTime)} // syscall.UtimesNano doesn't support a NOFOLLOW flag atm, and if hdr.Typeflag != tar.TypeSymlink { if err := syscall.UtimesNano(path, ts); err != nil { return err } } else { if err := LUtimesNano(path, ts); err != nil { return err } } return nil }
func (constor *Constor) SetAttr(input *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status { var err error uid := -1 gid := -1 inode := constor.inodemap.findInodePtr(input.NodeId) if inode == nil { constor.error("inode nil") return fuse.EIO } constor.log("%s %d", inode.id, input.Valid) // if ((input.Valid & fuse.FATTR_FH) !=0) && ((input.Valid & (fuse.FATTR_ATIME | fuse.FATTR_MTIME)) == 0) { if ((input.Valid & fuse.FATTR_FH) != 0) && ((input.Valid & fuse.FATTR_SIZE) != 0) { ptr := uintptr(input.Fh) F := constor.getfd(ptr) if F == nil { constor.error("F == nil for %s", inode.id) return fuse.EIO } if F.layer != 0 && inode.layer == -1 { /* FIXME handle this valid case */ // file is in lower layer, opened, deleted, setattr-called constor.error("FSetAttr F.layer=%d inode.layer=%d", F.layer, inode.layer) return fuse.EIO } if F.layer != 0 && inode.layer != 0 { err := constor.copyup(inode) if err != nil { constor.error("copyup failed for %s - %s", inode.id, err) return fuse.ToStatus(err) } path := constor.getPath(0, inode.id) syscall.Close(F.fd) fd, err := syscall.Open(path, F.flags, 0) if err != nil { constor.error("open failed on %s - %s", path, err) return fuse.ToStatus(err) } F.fd = fd F.layer = 0 constor.log("reset fd for %s", path) } else if F.layer != 0 && inode.layer == 0 { // when some other process already has done a copyup syscall.Close(F.fd) path := constor.getPath(0, inode.id) fd, err := syscall.Open(path, F.flags, 0) if err != nil { constor.error("open failed on %s - %s", path, err) return fuse.ToStatus(err) } F.fd = fd F.layer = 0 constor.log("reset fd for %s", path) } if F.layer != 0 { constor.error("layer not 0") return fuse.EIO } if input.Valid&fuse.FATTR_MODE != 0 { permissions := uint32(07777) & input.Mode err = syscall.Fchmod(F.fd, permissions) if err != nil { constor.error("Fchmod failed on %s - %d : %s", F.id, permissions, err) return fuse.ToStatus(err) } } if input.Valid&(fuse.FATTR_UID) != 0 { uid = int(input.Uid) } if input.Valid&(fuse.FATTR_GID) != 0 { gid = int(input.Gid) } if input.Valid&(fuse.FATTR_UID|fuse.FATTR_GID) != 0 { err = syscall.Fchown(F.fd, uid, gid) if err != nil { constor.error("Fchown failed on %s - %d %d : %s", F.id, uid, gid, err) return fuse.ToStatus(err) } } if input.Valid&fuse.FATTR_SIZE != 0 { err := syscall.Ftruncate(F.fd, int64(input.Size)) if err != nil { constor.error("Ftruncate failed on %s - %d : %s", F.id, input.Size, err) return fuse.ToStatus(err) } } if input.Valid&(fuse.FATTR_ATIME|fuse.FATTR_MTIME|fuse.FATTR_ATIME_NOW|fuse.FATTR_MTIME_NOW) != 0 { now := time.Now() var tv []syscall.Timeval tv = make([]syscall.Timeval, 2) if input.Valid&fuse.FATTR_ATIME_NOW != 0 { tv[0].Sec = now.Unix() tv[0].Usec = now.UnixNano() / 1000 } else { tv[0].Sec = int64(input.Atime) tv[0].Usec = int64(input.Atimensec / 1000) } if input.Valid&fuse.FATTR_MTIME_NOW != 0 { tv[1].Sec = now.Unix() tv[1].Usec = now.UnixNano() / 1000 } else { tv[1].Sec = int64(input.Atime) tv[1].Usec = int64(input.Atimensec / 1000) } err := syscall.Futimes(F.fd, tv) if err != nil { constor.error("Futimes failed on %s : %s", F.id, err) return fuse.ToStatus(err) } } stat := syscall.Stat_t{} err = syscall.Fstat(F.fd, &stat) if err != nil { constor.error("Fstat failed on %s : %s", F.id, err) return fuse.ToStatus(err) } attr := (*fuse.Attr)(&out.Attr) attr.FromStat(&stat) attr.Ino = idtoino(inode.id) return fuse.OK } if inode.layer == -1 { return fuse.ENOENT } if inode.layer != 0 { err = constor.copyup(inode) if err != nil { constor.error("copyup failed for %s - %s", inode.id, err) return fuse.ToStatus(err) } } stat := syscall.Stat_t{} path := constor.getPath(0, inode.id) // just to satisfy PJD tests if input.Valid == 0 { err = syscall.Lchown(path, uid, gid) if err != nil { return fuse.ToStatus(err) } } if input.Valid&fuse.FATTR_MODE != 0 { permissions := uint32(07777) & input.Mode err = syscall.Chmod(path, permissions) if err != nil { constor.error("Lchmod failed on %s - %d : %s", path, permissions, err) return fuse.ToStatus(err) } } if input.Valid&(fuse.FATTR_UID) != 0 { uid = int(input.Uid) } if input.Valid&(fuse.FATTR_GID) != 0 { gid = int(input.Gid) } if input.Valid&(fuse.FATTR_UID|fuse.FATTR_GID) != 0 { constor.log("%s %d %d", path, uid, gid) err = syscall.Lchown(path, uid, gid) if err != nil { constor.error("Lchown failed on %s - %d %d : %s", path, uid, gid, err) return fuse.ToStatus(err) } } if input.Valid&fuse.FATTR_SIZE != 0 { err = syscall.Truncate(path, int64(input.Size)) if err != nil { constor.error("Truncate failed on %s - %d : %s", path, input.Size, err) return fuse.ToStatus(err) } } if input.Valid&(fuse.FATTR_ATIME|fuse.FATTR_MTIME|fuse.FATTR_ATIME_NOW|fuse.FATTR_MTIME_NOW) != 0 { now := time.Now() var atime *time.Time var mtime *time.Time if input.Valid&fuse.FATTR_ATIME_NOW != 0 { atime = &now } else { t := time.Unix(int64(input.Atime), int64(input.Atimensec)) atime = &t } if input.Valid&fuse.FATTR_MTIME_NOW != 0 { mtime = &now } else { t := time.Unix(int64(input.Mtime), int64(input.Mtimensec)) mtime = &t } fi, err := os.Lstat(path) if err != nil { return fuse.ToStatus(err) } if fi.Mode()&os.ModeSymlink != os.ModeSymlink { // FIXME: there is no Lchtimes err = os.Chtimes(path, *atime, *mtime) if err != nil { constor.error("Chtimes failed on %s : %s", path, err) return fuse.ToStatus(err) } } else { constor.error("Chtimes on Symlink not supported") } } attr := (*fuse.Attr)(&out.Attr) err = constor.Lstat(inode.layer, inode.id, &stat) if err != nil { constor.error("Lstat failed on %s : %s", inode.id, err) return fuse.ToStatus(err) } attr.FromStat(&stat) attr.Ino = stat.Ino return fuse.ToStatus(err) }
// Chmod changes the mode of the named file to mode. // If the file is a symbolic link, it changes the mode of the link's target. func Chmod(name string, mode int) Error { if e := syscall.Chmod(name, mode); e != 0 { return &PathError{"chmod", name, Errno(e)} } return nil }
// Chmod changes the mode of the named file to mode. // If the file is a symbolic link, it changes the mode of the link's target. func Chmod(name string, mode uint32) error { if e := syscall.Chmod(name, mode); iserror(e) { return &PathError{"chmod", name, Errno(e)} } return nil }
func main() { host := os.Getenv("ISUCON5_DB_HOST") if host == "" { host = "localhost" } portstr := os.Getenv("ISUCON5_DB_PORT") if portstr == "" { portstr = "3306" } port, err := strconv.Atoi(portstr) if err != nil { log.Fatalf("Failed to read DB port number from an environment variable ISUCON5_DB_PORT.\nError: %s", err.Error()) } user := os.Getenv("ISUCON5_DB_USER") if user == "" { user = "******" } password := os.Getenv("ISUCON5_DB_PASSWORD") dbname := os.Getenv("ISUCON5_DB_NAME") if dbname == "" { dbname = "isucon5q" } ssecret := os.Getenv("ISUCON5_SESSION_SECRET") if ssecret == "" { ssecret = "beermoris" } db, err = sql.Open("mysql", user+":"+password+"@tcp("+host+":"+strconv.Itoa(port)+")/"+dbname+"?loc=Local&parseTime=true") if err != nil { log.Fatalf("Failed to connect to DB: %s.", err.Error()) } defer db.Close() store = sessions.NewCookieStore([]byte(ssecret)) r := mux.NewRouter() l := r.Path("/login").Subrouter() l.Methods("GET").HandlerFunc(myHandler(GetLogin)) l.Methods("POST").HandlerFunc(myHandler(PostLogin)) r.Path("/logout").Methods("GET").HandlerFunc(myHandler(GetLogout)) p := r.Path("/profile/{account_name}").Subrouter() p.Methods("GET").HandlerFunc(myHandler(GetProfile)) p.Methods("POST").HandlerFunc(myHandler(PostProfile)) d := r.PathPrefix("/diary").Subrouter() d.HandleFunc("/entries/{account_name}", myHandler(ListEntries)).Methods("GET") d.HandleFunc("/entry", myHandler(PostEntry)).Methods("POST") d.HandleFunc("/entry/{entry_id}", myHandler(GetEntry)).Methods("GET") d.HandleFunc("/comment/{entry_id}", myHandler(PostComment)).Methods("POST") r.HandleFunc("/footprints", myHandler(GetFootprints)).Methods("GET") r.HandleFunc("/friends", myHandler(GetFriends)).Methods("GET") r.HandleFunc("/friends/{account_name}", myHandler(PostFriends)).Methods("POST") r.HandleFunc("/initialize", myHandler(GetInitialize)) r.HandleFunc("/", myHandler(GetIndex)) r.PathPrefix("/").Handler(http.FileServer(http.Dir("../static"))) //log.Fatal(http.ListenAndServe(":8080", r)) listen, _ := net.Listen("unix", "/run/sock-shared/isuxi.go.sock") syscall.Chmod("/run/sock-shared/isuxi.go.sock", 0777) log.Fatal(http.Serve(listen, r)) }
func (k *PosixKernel) Chmod(path string, mode uint32) uint64 { return Errno(syscall.Chmod(path, mode)) }
func (constor *Constor) copyup(inode *Inode) error { constor.log("%s", inode.id) if inode.layer == 0 { return nil } src := constor.getPath(inode.layer, inode.id) if src == "" { return syscall.EIO } dst := constor.getPath(0, inode.id) if dst == "" { return syscall.EIO } fi, err := os.Lstat(src) if err != nil { return err } if fi.Mode()&os.ModeSymlink == os.ModeSymlink { linkName, err := os.Readlink(src) if err != nil { return err } err = os.Symlink(linkName, dst) if err != nil { return err } } else if fi.Mode()&os.ModeDir == os.ModeDir { err := os.Mkdir(dst, fi.Mode()) if err != nil { return err } } else { in, err := os.Open(src) if err != nil { return err } defer in.Close() out, err := os.Create(dst) if err != nil { return err } defer out.Close() _, err = io.Copy(out, in) if err != nil { return err } err = out.Close() if err != nil { return err } } stat := syscall.Stat_t{} if err = syscall.Lstat(src, &stat); err != nil { return err } if fi.Mode()&os.ModeSymlink != os.ModeSymlink { if err = syscall.Chmod(dst, stat.Mode); err != nil { return err } } if err = syscall.Lchown(dst, int(stat.Uid), int(stat.Gid)); err != nil { return err } links, err := Lgetxattr(src, LINKSXATTR) if err == nil && len(links) > 0 { err := Lsetxattr(dst, LINKSXATTR, links, 0) if err != nil { return err } } if fi.Mode()&os.ModeSymlink != os.ModeSymlink { if err = syscall.UtimesNano(dst, []syscall.Timespec{stat.Atim, stat.Mtim}); err != nil { return err } } inode.layer = 0 constor.log("done", inode.id) return nil }
// Given a filepath, set it's permission bits directly func Chmod(filepath string, b PermissionBits) error { if e := syscall.Chmod(filepath, syscallMode(b)); e != nil { return &os.PathError{"chmod", filepath, e} } return nil }
func (inode *DirectoryInode) writeMetadata(name string) error { if err := os.Lchown(name, int(inode.Uid), int(inode.Gid)); err != nil { return err } return syscall.Chmod(name, uint32(inode.Mode)) }
func (constor *Constor) SetAttr(input *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status { constor.log("%d %d", input.NodeId, input.Valid) var err error uid := -1 gid := -1 // if ((input.Valid & fuse.FATTR_FH) !=0) && ((input.Valid & (fuse.FATTR_ATIME | fuse.FATTR_MTIME)) == 0) { if ((input.Valid & fuse.FATTR_FH) != 0) && ((input.Valid & fuse.FATTR_SIZE) != 0) { ptr := uintptr(input.Fh) F := constor.getfd(ptr) if F == nil { constor.error("F == nil") return fuse.EIO } if F.layer != 0 { constor.error("layer not 0") return fuse.EIO } constor.log("Ftruncate %d", ptr) err := syscall.Ftruncate(F.fd, int64(input.Size)) if err != nil { constor.error("%s", err) return fuse.ToStatus(err) } stat := syscall.Stat_t{} err = syscall.Fstat(F.fd, &stat) if err != nil { constor.error("%s", err) return fuse.ToStatus(err) } attr := (*fuse.Attr)(&out.Attr) attr.FromStat(&stat) attr.Ino = input.NodeId return fuse.OK } inode, err := constor.inodemap.findInode(input.NodeId) if err != nil { return fuse.ToStatus(err) } if inode.layer != 0 { err = constor.copyup(inode) if err != nil { constor.log("%s", err) return fuse.ToStatus(err) } } stat := syscall.Stat_t{} path, err := constor.dentrymap.getPath(input.NodeId) if err != nil { constor.log("%s", err) return fuse.ToStatus(err) } pathl := Path.Join(constor.layers[0], path) // just to satisfy PJD tests if input.Valid == 0 { err = os.Lchown(pathl, uid, gid) if err != nil { return fuse.ToStatus(err) } } if input.Valid&fuse.FATTR_MODE != 0 { permissions := uint32(07777) & input.Mode err = syscall.Chmod(pathl, permissions) if err != nil { return fuse.ToStatus(err) } } if input.Valid&(fuse.FATTR_UID) != 0 { uid = int(input.Uid) } if input.Valid&(fuse.FATTR_GID) != 0 { gid = int(input.Gid) } if input.Valid&(fuse.FATTR_UID|fuse.FATTR_GID) != 0 { constor.log("%s %d %d", pathl, uid, gid) err = os.Lchown(pathl, uid, gid) if err != nil { return fuse.ToStatus(err) } } if input.Valid&fuse.FATTR_SIZE != 0 { err = os.Truncate(pathl, int64(input.Size)) if err != nil { return fuse.ToStatus(err) } } if input.Valid&(fuse.FATTR_ATIME|fuse.FATTR_MTIME|fuse.FATTR_ATIME_NOW|fuse.FATTR_MTIME_NOW) != 0 { now := time.Now() var atime *time.Time var mtime *time.Time if input.Valid&fuse.FATTR_ATIME_NOW != 0 { atime = &now } else { t := time.Unix(int64(input.Atime), int64(input.Atimensec)) atime = &t } if input.Valid&fuse.FATTR_MTIME_NOW != 0 { mtime = &now } else { t := time.Unix(int64(input.Mtime), int64(input.Mtimensec)) mtime = &t } fi, err := os.Lstat(pathl) if err != nil { return fuse.ToStatus(err) } if fi.Mode()&os.ModeSymlink != os.ModeSymlink { // FIXME: there is no Lchtimes err = os.Chtimes(pathl, *atime, *mtime) if err != nil { constor.log("%s", err) return fuse.ToStatus(err) } } } attr := (*fuse.Attr)(&out.Attr) err = syscall.Lstat(pathl, &stat) if err != nil { return fuse.ToStatus(err) } attr.FromStat(&stat) attr.Ino = input.NodeId return fuse.ToStatus(err) }
func (constor *Constor) copyup(inode *Inode) error { src, err := constor.getPath(inode.ino) if err != nil { return err } dst, err := constor.dentrymap.getPath(inode.ino) if err != nil { return err } err = constor.createPath(Path.Dir(dst)) if err != nil { return err } dst = Path.Join(constor.layers[0], dst) fi, err := os.Lstat(src) if err != nil { return err } if fi.Mode()&os.ModeSymlink == os.ModeSymlink { linkName, err := os.Readlink(src) if err != nil { return err } err = os.Symlink(linkName, dst) if err != nil { return err } } else if fi.Mode()&os.ModeDir == os.ModeDir { err := os.Mkdir(dst, fi.Mode()) if err != nil { return err } } else { in, err := os.Open(src) if err != nil { return err } defer in.Close() out, err := os.Create(dst) if err != nil { return err } defer out.Close() _, err = io.Copy(out, in) if err != nil { return err } err = out.Close() if err != nil { return err } } stat := syscall.Stat_t{} if err = syscall.Lstat(src, &stat); err != nil { return err } if fi.Mode()&os.ModeSymlink != os.ModeSymlink { if err = syscall.Chmod(dst, stat.Mode); err != nil { return err } } if err = syscall.Lchown(dst, int(stat.Uid), int(stat.Gid)); err != nil { return err } if fi.Mode()&os.ModeSymlink != os.ModeSymlink { if err = syscall.UtimesNano(dst, []syscall.Timespec{stat.Atim, stat.Mtim}); err != nil { return err } } inoitoa := strconv.Itoa(int(stat.Ino)) inobyte := []byte(inoitoa) // if err = syscall.Setxattr(dst, INOXATTR, inobyte, 0); err != nil { // return err // } if err = Lsetxattr(dst, INOXATTR, inobyte, 0); err != nil { return err } inode.layer = 0 path, err := constor.dentrymap.getPath(inode.ino) constor.log("ino %d file %s", inode.ino, path) return nil }
// Chmod changes the mode of the named file to mode. // If the file is a symbolic link, it changes the mode of the link's target. // If there is an error, it will be of type *PathError. func Chmod(name string, mode FileMode) error { if e := syscall.Chmod(name, syscallMode(mode)); e != nil { return &PathError{"chmod", name, e} } return nil }
func (d *ExecDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, error) { // Get the command to be ran command, ok := task.Config["command"] if !ok || command == "" { return nil, fmt.Errorf("missing command for exec driver") } // Check if an artificat is specified and attempt to download it source, ok := task.Config["artifact_source"] if ok && source != "" { // Proceed to download an artifact to be executed. // We use go-getter to support a variety of protocols, but need to change // file permissions of the resulted download to be executable // Create a location to download the artifact. taskDir, ok := ctx.AllocDir.TaskDirs[d.DriverContext.taskName] if !ok { return nil, fmt.Errorf("Could not find task directory for task: %v", d.DriverContext.taskName) } destDir := filepath.Join(taskDir, allocdir.TaskLocal) artifactName := path.Base(source) artifactFile := filepath.Join(destDir, artifactName) if err := getter.GetFile(artifactFile, source); err != nil { return nil, fmt.Errorf("Error downloading artifact for Exec driver: %s", err) } // Add execution permissions to the newly downloaded artifact if err := syscall.Chmod(artifactFile, 0755); err != nil { log.Printf("[ERR] driver.exec: Error making artifact executable: %s", err) } } // Get the environment variables. envVars := TaskEnvironmentVariables(ctx, task) // Look for arguments var args []string if argRaw, ok := task.Config["args"]; ok { args = append(args, argRaw) } // Setup the command cmd := executor.Command(command, args...) if err := cmd.Limit(task.Resources); err != nil { return nil, fmt.Errorf("failed to constrain resources: %s", err) } // Populate environment variables cmd.Command().Env = envVars.List() if err := cmd.ConfigureTaskDir(d.taskName, ctx.AllocDir); err != nil { return nil, fmt.Errorf("failed to configure task directory: %v", err) } if err := cmd.Start(); err != nil { return nil, fmt.Errorf("failed to start command: %v", err) } // Return a driver handle h := &execHandle{ cmd: cmd, doneCh: make(chan struct{}), waitCh: make(chan error, 1), } go h.run() return h, nil }
// ApplyLayer parses a diff in the standard layer format from `layer`, and // applies it to the directory `dest`. func ApplyLayer(dest string, layer Archive) error { // We need to be able to set any perms oldmask := syscall.Umask(0) defer syscall.Umask(oldmask) layer, err := DecompressStream(layer) if err != nil { return err } tr := tar.NewReader(layer) var dirs []*tar.Header // Iterate through the files in the archive. for { hdr, err := tr.Next() if err == io.EOF { // end of tar archive break } if err != nil { return err } // Normalize name, for safety and for a simple is-root check hdr.Name = filepath.Clean(hdr.Name) if !strings.HasSuffix(hdr.Name, "/") { // Not the root directory, ensure that the parent directory exists // This happened in some tests where an image had a tarfile without any // parent directories parent := filepath.Dir(hdr.Name) parentPath := filepath.Join(dest, parent) if _, err := os.Lstat(parentPath); err != nil && os.IsNotExist(err) { err = os.MkdirAll(parentPath, 600) if err != nil { return err } } } // Skip AUFS metadata dirs if strings.HasPrefix(hdr.Name, ".wh..wh.") { continue } path := filepath.Join(dest, hdr.Name) base := filepath.Base(path) if strings.HasPrefix(base, ".wh.") { originalBase := base[len(".wh."):] originalPath := filepath.Join(filepath.Dir(path), originalBase) if err := os.RemoveAll(originalPath); err != nil { return err } } else { // If path exits we almost always just want to remove and replace it // The only exception is when it is a directory *and* the file from // the layer is also a directory. Then we want to merge them (i.e. // just apply the metadata from the layer). hasDir := false if fi, err := os.Lstat(path); err == nil { if fi.IsDir() && hdr.Typeflag == tar.TypeDir { hasDir = true } else { if err := os.RemoveAll(path); err != nil { return err } } } switch hdr.Typeflag { case tar.TypeDir: if !hasDir { err = os.Mkdir(path, os.FileMode(hdr.Mode)) if err != nil { return err } } dirs = append(dirs, hdr) case tar.TypeReg, tar.TypeRegA: // Source is regular file file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, os.FileMode(hdr.Mode)) if err != nil { return err } if _, err := io.Copy(file, tr); err != nil { file.Close() return err } file.Close() case tar.TypeBlock, tar.TypeChar, tar.TypeFifo: mode := uint32(hdr.Mode & 07777) switch hdr.Typeflag { case tar.TypeBlock: mode |= syscall.S_IFBLK case tar.TypeChar: mode |= syscall.S_IFCHR case tar.TypeFifo: mode |= syscall.S_IFIFO } if err := syscall.Mknod(path, mode, int(mkdev(hdr.Devmajor, hdr.Devminor))); err != nil { return err } case tar.TypeLink: if err := os.Link(filepath.Join(dest, hdr.Linkname), path); err != nil { return err } case tar.TypeSymlink: if err := os.Symlink(hdr.Linkname, path); err != nil { return err } default: utils.Debugf("unhandled type %d\n", hdr.Typeflag) } if err = syscall.Lchown(path, hdr.Uid, hdr.Gid); err != nil { return err } // There is no LChmod, so ignore mode for symlink. Also, this // must happen after chown, as that can modify the file mode if hdr.Typeflag != tar.TypeSymlink { err = syscall.Chmod(path, uint32(hdr.Mode&07777)) if err != nil { return err } } // Directories must be handled at the end to avoid further // file creation in them to modify the mtime if hdr.Typeflag != tar.TypeDir { ts := []syscall.Timespec{timeToTimespec(hdr.AccessTime), timeToTimespec(hdr.ModTime)} // syscall.UtimesNano doesn't support a NOFOLLOW flag atm, and if hdr.Typeflag != tar.TypeSymlink { if err := syscall.UtimesNano(path, ts); err != nil { return err } } else { if err := LUtimesNano(path, ts); err != nil { return err } } } } } for _, hdr := range dirs { path := filepath.Join(dest, hdr.Name) ts := []syscall.Timespec{timeToTimespec(hdr.AccessTime), timeToTimespec(hdr.ModTime)} if err := syscall.UtimesNano(path, ts); err != nil { return err } } return nil }
// The test will only work when running as root. func TestActivate(t *testing.T) { // create temporary directory to test chrooting tmp, err := ioutil.TempDir("", "mitigationtest") if err != nil { t.Fatal(err) } defer os.Remove(tmp) err = syscall.Chmod(tmp, 0755) if err != nil { t.Fatal("Could not change temporary directory permissions!") } // improve cpu usage to test for broken os implementations of setuid() runtime.GOMAXPROCS(2) // create some go routines as root to later test them var sync chan bool = make(chan bool) for i := 0; i < TEST_ROUTINES_COUNT; i++ { go func() { // no op sync <- true }() } for i := 0; i < TEST_ROUTINES_COUNT; i++ { <-sync } // modify environment err = os.Setenv("malicous_env", "bad string") if err != nil { t.Fatal("Cannot setup environment variables!") } if len(os.Environ()) == 0 { t.Fatal("Environ() or Setenv() are broken!") } // do it! Activate(TEST_UID, TEST_GID, tmp) // verify uids uid := syscall.Getuid() if uid != TEST_UID { t.Error("Failed to change UID") } euid := syscall.Geteuid() if euid != TEST_UID { t.Error("Failed to change EUID") } // verify gid gid := syscall.Getgid() if gid != TEST_GID { t.Error("Failed to change GID") } // verify groups gids, err := syscall.Getgroups() if err != nil { t.Fatal("Could not get group list") } if len(gids) > 1 { t.Error("Not all groups are dropped!") } else if len(gids) == 1 { if gids[0] != TEST_GID { t.Error("Not all foreign groups are dropped!") } } // verify directory dh, err := os.Open("/") if err != nil { t.Fatal("Cannot open my root directory", err) } files, err := dh.Readdir(-1) if err != nil { t.Fatal("Cannot read my root directory") } if len(files) > 0 { t.Error("Root not changed to empty temporary directory!") } // verify environment if len(os.Environ()) > 0 { t.Error("Environment variables found!") } // test setuid() behaviour var results chan int = make(chan int) // start multiple goroutines, in a good OS, all all routines // should be switched to the new user for i := 0; i < TEST_ROUTINES_COUNT; i++ { go func() { results <- syscall.Getuid() }() } // check the results for i := 0; i < TEST_ROUTINES_COUNT; i++ { uid := <-results if uid != TEST_UID { t.Error("false uid: ", uid, " (you are using an unsafe os, read the package documentation!)") break } } }