Skip to content

Commit

Permalink
Improve Uid & Gid support
Browse files Browse the repository at this point in the history
The purpose of this PR is to allow file systems to:
1. Create inodes with the UID and GID of the calling process
2. Support chown
  • Loading branch information
Manuel Valls Fernández committed Sep 21, 2019
1 parent 659cc51 commit 13353bc
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 18 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ before_install:
# For linux: install fuse.
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
sudo apt-get install -qq fuse;
sudo echo user_allow_other > /etc/fuse.conf;
fi

# For macOS: update homebrew and then install osxfuse.
Expand Down
20 changes: 19 additions & 1 deletion conversions.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ func convertInMessage(
inMsg *buffer.InMessage,
outMsg *buffer.OutMessage,
protocol fusekernel.Protocol) (o interface{}, err error) {
switch inMsg.Header().Opcode {
header := inMsg.Header()

switch header.Opcode {
case fusekernel.OpLookup:
buf := inMsg.ConsumeBytes(inMsg.Len())
n := len(buf)
Expand Down Expand Up @@ -93,6 +95,14 @@ func convertInMessage(
to.Mtime = &t
}

if valid&fusekernel.SetattrUid != 0 {
to.Uid = &in.Uid
}

if valid&fusekernel.SetattrGid != 0 {
to.Gid = &in.Gid
}

case fusekernel.OpForget:
type input fusekernel.ForgetIn
in := (*input)(inMsg.Consume(unsafe.Sizeof(input{})))
Expand Down Expand Up @@ -132,6 +142,8 @@ func convertInMessage(
// opcode is mkdir. But we want the correct mode to go through, so ensure
// that os.ModeDir is set.
Mode: convertFileMode(in.Mode) | os.ModeDir,
Uid: header.Uid,
Gid: header.Gid,
}

case fusekernel.OpMknod:
Expand All @@ -153,6 +165,8 @@ func convertInMessage(
Parent: fuseops.InodeID(inMsg.Header().Nodeid),
Name: string(name),
Mode: convertFileMode(in.Mode),
Uid: header.Uid,
Gid: header.Gid,
}

case fusekernel.OpCreate:
Expand All @@ -174,6 +188,8 @@ func convertInMessage(
Parent: fuseops.InodeID(inMsg.Header().Nodeid),
Name: string(name),
Mode: convertFileMode(in.Mode),
Uid: header.Uid,
Gid: header.Gid,
}

case fusekernel.OpSymlink:
Expand All @@ -194,6 +210,8 @@ func convertInMessage(
Parent: fuseops.InodeID(inMsg.Header().Nodeid),
Name: string(newName),
Target: string(target),
Uid: header.Uid,
Gid: header.Gid,
}

case fusekernel.OpRename:
Expand Down
18 changes: 18 additions & 0 deletions fuseops/ops.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ type SetInodeAttributesOp struct {
Mode *os.FileMode
Atime *time.Time
Mtime *time.Time
Uid *uint32
Gid *uint32

// Set by the file system: the new attributes for the inode, and the time at
// which they should expire. See notes on
Expand Down Expand Up @@ -228,6 +230,10 @@ type MkDirOp struct {
Name string
Mode os.FileMode

// The uid and gid of the parent process
Uid uint32
Gid uint32

// Set by the file system: information about the inode that was created.
//
// The lookup count for the inode is implicitly incremented. See notes on
Expand Down Expand Up @@ -255,6 +261,10 @@ type MkNodeOp struct {
Name string
Mode os.FileMode

// The uid and gid of the parent process
Uid uint32
Gid uint32

// Set by the file system: information about the inode that was created.
//
// The lookup count for the inode is implicitly incremented. See notes on
Expand All @@ -280,6 +290,10 @@ type CreateFileOp struct {
Name string
Mode os.FileMode

// The uid and gid of the parent process
Uid uint32
Gid uint32

// Set by the file system: information about the inode that was created.
//
// The lookup count for the inode is implicitly incremented. See notes on
Expand All @@ -306,6 +320,10 @@ type CreateSymlinkOp struct {
// The name of the symlink to create.
Name string

// The uid and gid of the parent process
Uid uint32
Gid uint32

// The target of the symlink.
Target string

Expand Down
14 changes: 13 additions & 1 deletion samples/memfs/inode.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,9 @@ func (in *inode) WriteAt(p []byte, off int64) (n int, err error) {
func (in *inode) SetAttributes(
size *uint64,
mode *os.FileMode,
mtime *time.Time) {
mtime *time.Time,
uid *uint32,
gid *uint32) {
// Update the modification time.
in.attrs.Mtime = time.Now()

Expand Down Expand Up @@ -381,4 +383,14 @@ func (in *inode) SetAttributes(
if mtime != nil {
in.attrs.Mtime = *mtime
}

// Change uid?
if uid != nil {
in.attrs.Uid = *uid
}

// Change gid?
if gid != nil {
in.attrs.Gid = *gid
}
}
28 changes: 12 additions & 16 deletions samples/memfs/memfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ import (
type memFS struct {
fuseutil.NotImplementedFileSystem

// The UID and GID that every inode receives.
uid uint32
gid uint32

/////////////////////////
// Mutable state
/////////////////////////
Expand Down Expand Up @@ -73,8 +69,6 @@ func NewMemFS(
// Set up the basic struct.
fs := &memFS{
inodes: make([]*inode, fuseops.RootInodeID+1),
uid: uid,
gid: gid,
}

// Set up the root inode.
Expand Down Expand Up @@ -250,7 +244,7 @@ func (fs *memFS) SetInodeAttributes(
inode := fs.getInodeOrDie(op.Inode)

// Handle the request.
inode.SetAttributes(op.Size, op.Mode, op.Mtime)
inode.SetAttributes(op.Size, op.Mode, op.Mtime, op.Uid, op.Gid)

// Fill in the response.
op.Attributes = inode.attrs
Expand Down Expand Up @@ -283,8 +277,8 @@ func (fs *memFS) MkDir(
childAttrs := fuseops.InodeAttributes{
Nlink: 1,
Mode: op.Mode,
Uid: fs.uid,
Gid: fs.gid,
Uid: op.Uid,
Gid: op.Gid,
}

// Allocate a child.
Expand All @@ -311,15 +305,17 @@ func (fs *memFS) MkNode(
fs.mu.Lock()
defer fs.mu.Unlock()

op.Entry, err = fs.createFile(op.Parent, op.Name, op.Mode)
op.Entry, err = fs.createFile(op.Parent, op.Name, op.Mode, op.Uid, op.Gid)
return
}

// LOCKS_REQUIRED(fs.mu)
func (fs *memFS) createFile(
parentID fuseops.InodeID,
name string,
mode os.FileMode) (entry fuseops.ChildInodeEntry, err error) {
mode os.FileMode,
uid uint32,
gid uint32) (entry fuseops.ChildInodeEntry, err error) {
// Grab the parent, which we will update shortly.
parent := fs.getInodeOrDie(parentID)

Expand All @@ -340,8 +336,8 @@ func (fs *memFS) createFile(
Mtime: now,
Ctime: now,
Crtime: now,
Uid: fs.uid,
Gid: fs.gid,
Uid: uid,
Gid: gid,
}

// Allocate a child.
Expand All @@ -368,7 +364,7 @@ func (fs *memFS) CreateFile(
fs.mu.Lock()
defer fs.mu.Unlock()

op.Entry, err = fs.createFile(op.Parent, op.Name, op.Mode)
op.Entry, err = fs.createFile(op.Parent, op.Name, op.Mode, op.Uid, op.Gid)
return
}

Expand Down Expand Up @@ -398,8 +394,8 @@ func (fs *memFS) CreateSymlink(
Mtime: now,
Ctime: now,
Crtime: now,
Uid: fs.uid,
Gid: fs.gid,
Uid: op.Uid,
Gid: op.Gid,
}

// Allocate a child.
Expand Down
32 changes: 32 additions & 0 deletions samples/memfs/memfs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"io"
"io/ioutil"
"os"
"os/exec"
"os/user"
"path"
"reflect"
Expand Down Expand Up @@ -97,6 +98,14 @@ type memFSTest struct {

func (t *memFSTest) SetUp(ti *TestInfo) {
t.Server = memfs.NewMemFS(currentUid(), currentGid())

// If the OS is linux, we need to specify allow_other for
// sudo to work
if os.Getenv("TRAVIS_OS_NAME") == "linux" {
t.SampleTest.MountConfig.Options = make(map[string]string)
t.SampleTest.MountConfig.Options["allow_other"] = ""
}

t.SampleTest.SetUp(ti)
}

Expand Down Expand Up @@ -1007,6 +1016,29 @@ func (t *MemFSTest) Chmod() {
ExpectEq(0754, fi.Mode())
}

func (t *MemFSTest) Chown() {
var err error
fileName := path.Join(t.Dir, "foo")

// Create a file.
err = ioutil.WriteFile(fileName, []byte(""), 0600)
AssertEq(nil, err)

// Chown it.
err = exec.Command("sudo", "chown", "50:51", fileName).Run()
AssertEq(nil, err)

// Stat it.
fi, err := os.Stat(fileName)
AssertEq(nil, err)
stat, ok := fi.Sys().(*syscall.Stat_t)

if ok {
ExpectEq(50, stat.Uid)
ExpectEq(51, stat.Gid)
}
}

func (t *MemFSTest) Chtimes() {
var err error
fileName := path.Join(t.Dir, "foo")
Expand Down

0 comments on commit 13353bc

Please sign in to comment.