[lxc-devel] [lxd/master] shared/idmap: Shift fscaps
stgraber on Github
lxc-bot at linuxcontainers.org
Thu Aug 2 20:00:11 UTC 2018
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 370 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180802/3275e772/attachment.bin>
-------------- next part --------------
From a2fb8e28ad2884f4922ab0673beef3755965d0b7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 2 Aug 2018 00:36:25 -0400
Subject: [PATCH] shared/idmap: Shift fscaps
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Closes #4862
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
shared/idmap/idmapset_linux.go | 30 ++++++++++++++--
shared/idmap/shift_linux.go | 63 +++++++++++++++++++++++++++++-----
2 files changed, 82 insertions(+), 11 deletions(-)
diff --git a/shared/idmap/idmapset_linux.go b/shared/idmap/idmapset_linux.go
index 8c6da8120..91c5c4e9f 100644
--- a/shared/idmap/idmapset_linux.go
+++ b/shared/idmap/idmapset_linux.go
@@ -13,6 +13,7 @@ import (
"strings"
"github.com/lxc/lxd/shared"
+ "github.com/lxc/lxd/shared/logger"
)
type IdRange struct {
@@ -505,6 +506,7 @@ func (set *IdmapSet) doUidshiftIntoContainer(dir string, testmode bool, how stri
uid := int64(intUid)
gid := int64(intGid)
+ caps := []byte{}
var newuid, newgid int64
switch how {
@@ -517,16 +519,38 @@ func (set *IdmapSet) doUidshiftIntoContainer(dir string, testmode bool, how stri
if testmode {
fmt.Printf("I would shift %q to %d %d\n", path, newuid, newgid)
} else {
+ // Dump capabilities
+ if fi.Mode()&os.ModeSymlink == 0 {
+ caps, err = GetCaps(path)
+ if err != nil {
+ return err
+ }
+ }
+
+ // Shift owner
err = ShiftOwner(dir, path, int(newuid), int(newgid))
if err != nil {
return err
}
- err = ShiftACL(path, func(uid int64, gid int64) (int64, int64) { return set.doShiftIntoNs(uid, gid, how) })
- if err != nil {
- return err
+ if fi.Mode()&os.ModeSymlink == 0 {
+ // Shift POSIX ACLs
+ err = ShiftACL(path, func(uid int64, gid int64) (int64, int64) { return set.doShiftIntoNs(uid, gid, how) })
+ if err != nil {
+ return err
+ }
+
+ // Shift capabilities
+ if len(caps) != 0 {
+ rootUid, _ := set.ShiftIntoNs(0, 0)
+ err = SetCaps(path, caps, rootUid)
+ if err != nil {
+ logger.Warnf("Unable to set file capabilities on %s", path)
+ }
+ }
}
}
+
return nil
}
diff --git a/shared/idmap/shift_linux.go b/shared/idmap/shift_linux.go
index d351e0116..e1864bef6 100644
--- a/shared/idmap/shift_linux.go
+++ b/shared/idmap/shift_linux.go
@@ -5,8 +5,9 @@ package idmap
import (
"fmt"
- "os"
"unsafe"
+
+ "github.com/lxc/lxd/shared"
)
// #cgo LDFLAGS: -lacl
@@ -18,11 +19,33 @@ import (
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/capability.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/acl.h>
+// Needs to be included at the end
+#include <attr/xattr.h>
+
+int set_caps(char *path, char *caps, ssize_t len, uint32_t uid) {
+ ssize_t ret;
+ struct vfs_ns_cap_data ns_xattr;
+
+ memset(&ns_xattr, 0, sizeof(ns_xattr));
+ memcpy(&ns_xattr, caps, len);
+ ns_xattr.magic_etc &= ~(VFS_CAP_REVISION_1 | VFS_CAP_REVISION_2);
+ ns_xattr.magic_etc |= VFS_CAP_REVISION_3 | VFS_CAP_FLAGS_EFFECTIVE;
+ ns_xattr.rootid = uid;
+
+ ret = setxattr(path, "security.capability", &ns_xattr, sizeof(ns_xattr), 0);
+ if (ret < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
int shiftowner(char *basepath, char *path, int uid, int gid) {
struct stat sb;
int fd, r;
@@ -102,20 +125,44 @@ func ShiftOwner(basepath string, path string, uid int, gid int) error {
if r != 0 {
return fmt.Errorf("Failed to change ownership of: %s", path)
}
+
return nil
}
-// ShiftACL updates uid and gid for file ACLs when entering/exiting a namespace
-func ShiftACL(path string, shiftIds func(uid int64, gid int64) (int64, int64)) error {
- finfo, err := os.Lstat(path)
+// GetCaps extracts the list of capabilities effective on the file
+func GetCaps(path string) ([]byte, error) {
+ xattrs, err := shared.GetAllXattr(path)
if err != nil {
- return err
+ return nil, err
}
- if finfo.Mode()&os.ModeSymlink != 0 {
- return nil
+
+ valueStr, ok := xattrs["security.capability"]
+ if !ok {
+ return nil, nil
}
- err = shiftAclType(path, C.ACL_TYPE_ACCESS, shiftIds)
+ return []byte(valueStr), nil
+}
+
+// SetCaps applies the caps for a particular root uid
+func SetCaps(path string, caps []byte, uid int64) error {
+ cpath := C.CString(path)
+ defer C.free(unsafe.Pointer(cpath))
+
+ ccaps := C.CString(string(caps))
+ defer C.free(unsafe.Pointer(ccaps))
+
+ r := C.set_caps(cpath, ccaps, C.ssize_t(len(caps)), C.uint32_t(uid))
+ if r != 0 {
+ return fmt.Errorf("Failed to apply capabilities to: %s", path)
+ }
+
+ return nil
+}
+
+// ShiftACL updates uid and gid for file ACLs when entering/exiting a namespace
+func ShiftACL(path string, shiftIds func(uid int64, gid int64) (int64, int64)) error {
+ err := shiftAclType(path, C.ACL_TYPE_ACCESS, shiftIds)
if err != nil {
return err
}
More information about the lxc-devel
mailing list