Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

supplemental groups

  • Loading branch information...
commit 4091de9686a9bbc948f8e1bdd0164797933f120f 1 parent ca7de7b
@bradfitz authored
Showing with 96 additions and 2 deletions.
  1. +1 −0  .gitignore
  2. +8 −2 exec.go
  3. +69 −0 groups.go
  4. +18 −0 runsit.go
View
1  .gitignore
@@ -5,4 +5,5 @@ _obj
a.out
runsit
test/daemon/testdaemon
+_cgo_export.h
View
10 exec.go
@@ -33,8 +33,9 @@ import (
// in the environment variable _RUNSIT_LAUNCH_INFO. The child then
// drops root and execs itself to be the requested process.
type LaunchRequest struct {
- Uid int // or 0 to not change
- Gid int // or 0 to not change
+ Uid int // or 0 to not change
+ Gid int // or 0 to not change
+ Gids []int // supplemental
Path string
Env []string
Argv []string // must include Path as argv[0]
@@ -100,6 +101,11 @@ func MaybeBecomeChildProcess() {
log.Fatalf("failed to Setgid(%d): %v", lr.Gid, err)
}
}
+ if len(lr.Gids) != 0 {
+ if err := SetGroups(lr.Gids); err != nil {
+ log.Printf("setgroups: %v", err)
+ }
+ }
if lr.Uid != 0 {
if err := syscall.Setuid(lr.Uid); err != nil {
log.Fatalf("failed to Setuid(%d): %v", lr.Uid, err)
View
69 groups.go
@@ -0,0 +1,69 @@
+/*
+Copyright 2011 Google Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// +build cgo
+
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "os"
+ "strconv"
+ "strings"
+ "unsafe"
+)
+
+/*
+#include <grp.h>
+*/
+import "C"
+
+func SetGroups(gids []int) error {
+ if len(gids) == 0 {
+ return nil
+ }
+ list := make([]C.gid_t, len(gids))
+ for i, gid := range gids {
+ list[i] = C.gid_t(gid)
+ }
+ _, err := C.setgroups(C.size_t(len(list)), (*_Ctype___gid_t)(unsafe.Pointer(&list[0])))
+ return err
+}
+
+func LookupGroupId(group string) (gid int, err error) {
+ f, err := os.Open("/etc/group")
+ if err != nil {
+ return
+ }
+ defer f.Close()
+ br := bufio.NewReader(f)
+ for {
+ s, err := br.ReadString('\n')
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return 0, err
+ }
+ p := strings.Split(s, ":")
+ if len(p) >= 3 && p[0] == group {
+ return strconv.Atoi(p[2])
+ }
+ }
+ return 0, fmt.Errorf("group %q not found", group)
+}
View
18 runsit.go
@@ -322,6 +322,7 @@ func (t *Task) updateFromConfig(jc jsonconfig.Obj) (err error) {
stdEnv := jc.OptionalBool("standardEnv", true)
userStr := jc.OptionalString("user", "")
+ groupStr := jc.OptionalString("group", "")
// TODO: group? requires http://code.google.com/p/go/issues/detail?id=2617
var runas *user.User
if userStr != "" {
@@ -382,6 +383,7 @@ func (t *Task) updateFromConfig(jc jsonconfig.Obj) (err error) {
bin := jc.RequiredString("binary")
dir := jc.OptionalString("cwd", "")
args := jc.OptionalList("args")
+ groups := jc.OptionalList("groups")
if err := jc.Validate(); err != nil {
return t.configError("configuration error: %v", err)
}
@@ -415,6 +417,22 @@ func (t *Task) updateFromConfig(jc jsonconfig.Obj) (err error) {
lr.Uid = runas.Uid
lr.Gid = runas.Gid
}
+ if groupStr != "" {
+ gid, err := LookupGroupId(groupStr)
+ if err != nil {
+ return t.configError("error looking up group %q: %v", groupStr, err)
+ }
+ lr.Gid = gid // primary group
+ }
+
+ // supplemental groups:
+ for _, group := range groups {
+ gid, err := LookupGroupId(group)
+ if err != nil {
+ return t.configError("error looking up group %q: %v", group, err)
+ }
+ lr.Gids = append(lr.Gids, gid)
+ }
cmd, outPipe, errPipe, err := lr.start(extraFiles)
if err != nil {
Please sign in to comment.
Something went wrong with that request. Please try again.