[lxc-devel] [lxd/master] Fix ACL handling

stgraber on Github lxc-bot at linuxcontainers.org
Mon Oct 16 06:23:34 UTC 2017


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20171016/7c0bc35f/attachment.bin>
-------------- next part --------------
From e5a84ebe5544434fc7c7b36ec181053937e9b031 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Sun, 15 Oct 2017 21:53:49 -0400
Subject: [PATCH 1/2] shared/idmap: Make ACL failures more verbose
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This is related to #3946

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 shared/idmap/shift_linux.go | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/shared/idmap/shift_linux.go b/shared/idmap/shift_linux.go
index b470da4fb..c8afff208 100644
--- a/shared/idmap/shift_linux.go
+++ b/shared/idmap/shift_linux.go
@@ -136,7 +136,7 @@ func ShiftACL(path string, shiftIds func(uid int64, gid int64) (int64, int64)) e
 
 		ret = C.acl_get_tag_type(ent, &tag)
 		if ret == -1 {
-			return fmt.Errorf("Failed to change ACLs on %s", path)
+			return fmt.Errorf("Failed to get ACLs for %s", path)
 		}
 
 		idp := (*C.id_t)(C.acl_get_qualifier(ent))
@@ -158,8 +158,9 @@ func ShiftACL(path string, shiftIds func(uid int64, gid int64) (int64, int64)) e
 		if updateACL {
 			ret = C.acl_set_qualifier(ent, unsafe.Pointer(&newId))
 			if ret == -1 {
-				return fmt.Errorf("Failed to change ACLs on %s", path)
+				return fmt.Errorf("Failed to set ACL qualifier on %s", path)
 			}
+
 			ret = C.acl_set_file(cpath, C.ACL_TYPE_ACCESS, acl)
 			if ret == -1 {
 				return fmt.Errorf("Failed to change ACLs on %s", path)

From e9e74d866437373ae2ffb61aa159d05322e31ce3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 16 Oct 2017 02:21:26 -0400
Subject: [PATCH 2/2] shared/idmap: Fix numerous issues
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This resolves two main problems:

 - Lack of support for default entries
 - Accidental re-ordering of the original ACL struct, causing later
   entries to be skipped if the new uid/gid of the previous entry causes
   re-ordering.

Closes #3946

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 shared/idmap/shift_linux.go | 87 ++++++++++++++++++++++++++++++++-------------
 1 file changed, 63 insertions(+), 24 deletions(-)

diff --git a/shared/idmap/shift_linux.go b/shared/idmap/shift_linux.go
index c8afff208..d351e0116 100644
--- a/shared/idmap/shift_linux.go
+++ b/shared/idmap/shift_linux.go
@@ -115,57 +115,96 @@ func ShiftACL(path string, shiftIds func(uid int64, gid int64) (int64, int64)) e
 		return nil
 	}
 
+	err = shiftAclType(path, C.ACL_TYPE_ACCESS, shiftIds)
+	if err != nil {
+		return err
+	}
+
+	err = shiftAclType(path, C.ACL_TYPE_DEFAULT, shiftIds)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func shiftAclType(path string, aclType _Ctype_acl_type_t, shiftIds func(uid int64, gid int64) (int64, int64)) error {
+	// Convert the path to something usable with cgo
 	cpath := C.CString(path)
 	defer C.free(unsafe.Pointer(cpath))
 
-	acl := C.acl_get_file(cpath, C.ACL_TYPE_ACCESS)
+	// Read the current ACL set for the requested type
+	acl := C.acl_get_file(cpath, aclType)
 	if acl == nil {
 		return nil
 	}
 	defer C.acl_free(unsafe.Pointer(acl))
 
+	newAcl := C.acl_init(0)
+	defer C.acl_free(unsafe.Pointer(newAcl))
+
+	// Iterate through all ACL entries
+	update := false
 	for entryId := C.ACL_FIRST_ENTRY; ; entryId = C.ACL_NEXT_ENTRY {
 		var ent C.acl_entry_t
+		var newEnt C.acl_entry_t
 		var tag C.acl_tag_t
-		updateACL := false
 
+		// Get the ACL entry
 		ret := C.acl_get_entry(acl, C.int(entryId), &ent)
-		if ret != 1 {
+		if ret == 0 {
 			break
+		} else if ret < 0 {
+			return fmt.Errorf("Failed to get the ACL entry for %s", path)
 		}
 
-		ret = C.acl_get_tag_type(ent, &tag)
+		// Setup the new entry
+		ret = C.acl_create_entry(&newAcl, &newEnt)
 		if ret == -1 {
-			return fmt.Errorf("Failed to get ACLs for %s", path)
+			return fmt.Errorf("Failed to allocate a new ACL entry for %s", path)
 		}
 
-		idp := (*C.id_t)(C.acl_get_qualifier(ent))
-		if idp == nil {
+		ret = C.acl_copy_entry(newEnt, ent)
+		if ret == -1 {
+			return fmt.Errorf("Failed to copy the ACL entry for %s", path)
+		}
+
+		// Get the ACL type
+		ret = C.acl_get_tag_type(newEnt, &tag)
+		if ret == -1 {
+			return fmt.Errorf("Failed to get the ACL type for %s", path)
+		}
+
+		// We only care about user and group ACLs, copy anything else
+		if tag != C.ACL_USER && tag != C.ACL_GROUP {
 			continue
 		}
 
-		var newId int64
-		switch tag {
-		case C.ACL_USER:
-			newId, _ = shiftIds((int64)(*idp), -1)
-			updateACL = true
+		// Get the value
+		idp := (*C.id_t)(C.acl_get_qualifier(newEnt))
+		if idp == nil {
+			return fmt.Errorf("Failed to get current ACL value for %s", path)
+		}
+
+		// Shift the value
+		newId, _ := shiftIds((int64)(*idp), -1)
 
-		case C.ACL_GROUP:
-			_, newId = shiftIds(-1, (int64)(*idp))
-			updateACL = true
+		// Update the new entry with the shifted value
+		ret = C.acl_set_qualifier(newEnt, unsafe.Pointer(&newId))
+		if ret == -1 {
+			return fmt.Errorf("Failed to set ACL qualifier on %s", path)
 		}
 
-		if updateACL {
-			ret = C.acl_set_qualifier(ent, unsafe.Pointer(&newId))
-			if ret == -1 {
-				return fmt.Errorf("Failed to set ACL qualifier on %s", path)
-			}
+		update = true
+	}
 
-			ret = C.acl_set_file(cpath, C.ACL_TYPE_ACCESS, acl)
-			if ret == -1 {
-				return fmt.Errorf("Failed to change ACLs on %s", path)
-			}
+	// Update the on-disk ACLs to match
+	if update {
+		ret := C.acl_set_file(cpath, aclType, newAcl)
+		if ret == -1 {
+			return fmt.Errorf("Failed to change ACLs on %s", path)
 		}
 	}
+
 	return nil
 }


More information about the lxc-devel mailing list