From 8cf07b2ad1ed8c6646c48a74e9ecbb2bfeecb322 Mon Sep 17 00:00:00 2001 From: baude Date: Wed, 1 Nov 2017 13:59:11 -0500 Subject: libpod create and run patched version of the same code that went into crio Signed-off-by: baude --- cmd/kpod/user.go | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 cmd/kpod/user.go (limited to 'cmd/kpod/user.go') diff --git a/cmd/kpod/user.go b/cmd/kpod/user.go new file mode 100644 index 000000000..3e2e308c5 --- /dev/null +++ b/cmd/kpod/user.go @@ -0,0 +1,121 @@ +package main + +// #include +// #include +// #include +// #include +// #include +// #include +// typedef FILE * pFILE; +import "C" + +import ( + "fmt" + "os/user" + "path/filepath" + "sync" + "syscall" + "unsafe" + + "github.com/pkg/errors" +) + +func fopenContainerFile(rootdir, filename string) (C.pFILE, error) { + var st, lst syscall.Stat_t + + ctrfile := filepath.Join(rootdir, filename) + cctrfile := C.CString(ctrfile) + defer C.free(unsafe.Pointer(cctrfile)) + mode := C.CString("r") + defer C.free(unsafe.Pointer(mode)) + f, err := C.fopen(cctrfile, mode) + if f == nil || err != nil { + return nil, errors.Wrapf(err, "error opening %q", ctrfile) + } + if err = syscall.Fstat(int(C.fileno(f)), &st); err != nil { + return nil, errors.Wrapf(err, "fstat(%q)", ctrfile) + } + if err = syscall.Lstat(ctrfile, &lst); err != nil { + return nil, errors.Wrapf(err, "lstat(%q)", ctrfile) + } + if st.Dev != lst.Dev || st.Ino != lst.Ino { + return nil, errors.Errorf("%q is not a regular file", ctrfile) + } + return f, nil +} + +var ( + lookupUser, lookupGroup sync.Mutex +) + +func lookupUserInContainer(rootdir, username string) (uint64, uint64, error) { + name := C.CString(username) + defer C.free(unsafe.Pointer(name)) + + f, err := fopenContainerFile(rootdir, "/etc/passwd") + if err != nil { + return 0, 0, err + } + defer C.fclose(f) + + lookupUser.Lock() + defer lookupUser.Unlock() + + pwd := C.fgetpwent(f) + for pwd != nil { + if C.strcmp(pwd.pw_name, name) != 0 { + pwd = C.fgetpwent(f) + continue + } + return uint64(pwd.pw_uid), uint64(pwd.pw_gid), nil + } + + return 0, 0, user.UnknownUserError(fmt.Sprintf("error looking up user %q", username)) +} + +func lookupGroupForUIDInContainer(rootdir string, userid uint64) (string, uint64, error) { + f, err := fopenContainerFile(rootdir, "/etc/passwd") + if err != nil { + return "", 0, err + } + defer C.fclose(f) + + lookupUser.Lock() + defer lookupUser.Unlock() + + pwd := C.fgetpwent(f) + for pwd != nil { + if uint64(pwd.pw_uid) != userid { + pwd = C.fgetpwent(f) + continue + } + return C.GoString(pwd.pw_name), uint64(pwd.pw_gid), nil + } + + return "", 0, user.UnknownUserError(fmt.Sprintf("error looking up user with UID %d", userid)) +} + +func lookupGroupInContainer(rootdir, groupname string) (uint64, error) { + name := C.CString(groupname) + defer C.free(unsafe.Pointer(name)) + + f, err := fopenContainerFile(rootdir, "/etc/group") + if err != nil { + return 0, err + } + defer C.fclose(f) + + lookupGroup.Lock() + defer lookupGroup.Unlock() + + grp := C.fgetgrent(f) + for grp != nil { + if C.strcmp(grp.gr_name, name) != 0 { + grp = C.fgetgrent(f) + continue + } + return uint64(grp.gr_gid), nil + } + + return 0, user.UnknownGroupError(fmt.Sprintf("error looking up group %q", groupname)) +} -- cgit v1.2.3-54-g00ecf