All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] libcap: add user namespace fscaps support
@ 2018-08-10 16:13 Christian Brauner
  2018-08-10 16:13 ` [PATCH 1/9] cap_file: use v3 xattr macros Christian Brauner
                   ` (8 more replies)
  0 siblings, 9 replies; 11+ messages in thread
From: Christian Brauner @ 2018-08-10 16:13 UTC (permalink / raw)
  To: linux-security-module

Hey everyone,

Starting with kernel 4.14 fcaps support in user namespaces was added.
libcap currently does not support fcaps in user namespaces. This series
adds support for fcaps in user namespaces. To this end two new functions
are introduced:

1. cap_get_nsowner()
   Get the uid associated with the capability sets as seen in the
   current user namespace.
   For example, assume that uid 0 in a non-initial userns is mapped to
   uid 1000000 on the host/initial user namespace. Further assume one of
   the following:
   a. A VFS_CAP_REVISION_2 capability has been set from within the
      non-initial user namespace.
   b. A VFS_CAP_REVISION_3 capability with nsowner 0 has been set from
      within said non-initial user namespace.
   c. A VFS_CAP_REVISION_3 capability with nsowner 100000 has been set
      from the initial user namespace.
   In any of these cases, cap_get_nsowner() will return 0 from within
   said non-initial user namespace, and will return 1000000 from the
   parent user namespace that wrote this mapping.

2. cap_set_nsowner()
   Set the owning uid associated with the capability sets.
   For example, assume that uid 0 in a non-initial userns is mapped to
   uid 1000000 on the host. Now, cap_set_nsowner() sets the uid for the
   capabilitiy sets to 1000000 in the parent (host) user namespace of
   the non-initial user namespace. This will cause a capability to be
   set that is useless on the host but interpreted in every user
   namespace that has established the same mapping.

More details on how to handle cases where libcap is compiled on a
VFS_CAP_REVISION_3 kernel but used on a VFS_CAP_REVISION_2 kernel can be
found in the individual commits.

Thanks!
Christian

Christian Brauner (9):
  cap_file: use v3 xattr macros
  capability: update to new uapi header
  cap_file: use struct vfs_ns_cap_data if possible
  cap_file: add new rootid argument
  cap_file: initialize rootid in _fcaps_load()
  capability: add cap_get_nsowner()
  cap_file: save rootid in _fcaps_save()
  cap_file: handle run- vs buildtime vfs cap support
  capability: add cap_set_nsowner()

 libcap/cap_file.c                      | 107 ++++++++++++++++++++++++-
 libcap/include/sys/capability.h        |   2 +
 libcap/include/uapi/linux/capability.h |  39 ++++++---
 libcap/libcap.h                        |   1 +
 4 files changed, 134 insertions(+), 15 deletions(-)

-- 
2.17.1

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/9] cap_file: use v3 xattr macros
  2018-08-10 16:13 [PATCH 0/9] libcap: add user namespace fscaps support Christian Brauner
@ 2018-08-10 16:13 ` Christian Brauner
  2018-08-13 16:11   ` Serge E. Hallyn
  2018-08-10 16:13 ` [PATCH 2/9] capability: update to new uapi header Christian Brauner
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 11+ messages in thread
From: Christian Brauner @ 2018-08-10 16:13 UTC (permalink / raw)
  To: linux-security-module

On kernels supporting VFS_CAP_REVISION_3 we should make use the new
macros.

Signed-off-by: Christian Brauner <christian@brauner.io>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
---
 libcap/cap_file.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/libcap/cap_file.c b/libcap/cap_file.c
index 76aac8c..228d806 100644
--- a/libcap/cap_file.c
+++ b/libcap/cap_file.c
@@ -59,6 +59,13 @@ static cap_t _fcaps_load(struct vfs_cap_data *rawvfscap, cap_t result,
 	break;
 #endif
 
+#ifdef VFS_CAP_REVISION_3
+    case VFS_CAP_REVISION_3:
+	tocopy = VFS_CAP_U32_3;
+	bytes -= XATTR_CAPS_SZ_3;
+	break;
+#endif
+
     default:
 	cap_free(result);
 	result = NULL;
@@ -125,9 +132,15 @@ static int _fcaps_save(struct vfs_cap_data *rawvfscap, cap_t cap_d,
 
 #ifdef _LINUX_CAPABILITY_VERSION_3
     case _LINUX_CAPABILITY_VERSION_3:
+#ifdef VFS_CAP_REVISION_3
+	magic = VFS_CAP_REVISION_3;
+	tocopy = VFS_CAP_U32_3;
+	*bytes_p = XATTR_CAPS_SZ_3;
+#else
 	magic = VFS_CAP_REVISION_2;
 	tocopy = VFS_CAP_U32_2;
 	*bytes_p = XATTR_CAPS_SZ_2;
+#endif
 	break;
 #endif
 
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/9] capability: update to new uapi header
  2018-08-10 16:13 [PATCH 0/9] libcap: add user namespace fscaps support Christian Brauner
  2018-08-10 16:13 ` [PATCH 1/9] cap_file: use v3 xattr macros Christian Brauner
@ 2018-08-10 16:13 ` Christian Brauner
  2018-08-10 16:13 ` [PATCH 3/9] cap_file: use struct vfs_ns_cap_data if possible Christian Brauner
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Christian Brauner @ 2018-08-10 16:13 UTC (permalink / raw)
  To: linux-security-module

I'm not completely sure why libcap effectively vendors a copy of the
capability uapi header but I assume there's a good reason for it. But
let's update it to the newest version.

Signed-off-by: Christian Brauner <christian@brauner.io>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
---
 libcap/include/uapi/linux/capability.h | 39 +++++++++++++++++---------
 1 file changed, 26 insertions(+), 13 deletions(-)

diff --git a/libcap/include/uapi/linux/capability.h b/libcap/include/uapi/linux/capability.h
index 432e023..4a2d916 100644
--- a/libcap/include/uapi/linux/capability.h
+++ b/libcap/include/uapi/linux/capability.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 /*
  * This is <linux/capability.h>
  *
@@ -7,16 +8,14 @@
  *
  * See here for the libcap library ("POSIX draft" compliance):
  *
- * http://www.kernel.org/pub/linux/libs/security/linux-privs/
+ * ftp://www.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.6/
  */
 
-#ifndef _UAPI_LINUX_CAPABILITY_H
-#define _UAPI_LINUX_CAPABILITY_H
+#ifndef _LINUX_CAPABILITY_H
+#define _LINUX_CAPABILITY_H
 
 #include <linux/types.h>
 
-struct task_struct;
-
 /* User-level do most of the mapping between kernel and user
    capabilities based on the version tag given by the kernel. The
    kernel might be somewhat backwards compatible, but don't bet on
@@ -62,9 +61,13 @@ typedef struct __user_cap_data_struct {
 #define VFS_CAP_U32_2           2
 #define XATTR_CAPS_SZ_2         (sizeof(__le32)*(1 + 2*VFS_CAP_U32_2))
 
-#define XATTR_CAPS_SZ           XATTR_CAPS_SZ_2
-#define VFS_CAP_U32             VFS_CAP_U32_2
-#define VFS_CAP_REVISION	VFS_CAP_REVISION_2
+#define VFS_CAP_REVISION_3	0x03000000
+#define VFS_CAP_U32_3           2
+#define XATTR_CAPS_SZ_3         (sizeof(__le32)*(2 + 2*VFS_CAP_U32_3))
+
+#define XATTR_CAPS_SZ           XATTR_CAPS_SZ_3
+#define VFS_CAP_U32             VFS_CAP_U32_3
+#define VFS_CAP_REVISION	VFS_CAP_REVISION_3
 
 struct vfs_cap_data {
 	__le32 magic_etc;            /* Little endian */
@@ -74,7 +77,18 @@ struct vfs_cap_data {
 	} data[VFS_CAP_U32];
 };
 
-#ifndef __KERNEL__
+/*
+ * same as vfs_cap_data but with a rootid at the end
+ */
+struct vfs_ns_cap_data {
+	__le32 magic_etc;
+	struct {
+		__le32 permitted;    /* Little endian */
+		__le32 inheritable;  /* Little endian */
+	} data[VFS_CAP_U32];
+	__le32 rootid;
+};
+
 
 /*
  * Backwardly compatible definition for source code - trapped in a
@@ -84,7 +98,6 @@ struct vfs_cap_data {
 #define _LINUX_CAPABILITY_VERSION  _LINUX_CAPABILITY_VERSION_1
 #define _LINUX_CAPABILITY_U32S     _LINUX_CAPABILITY_U32S_1
 
-#endif
 
 
 /**
@@ -207,7 +220,7 @@ struct vfs_cap_data {
 #define CAP_SYS_MODULE       16
 
 /* Allow ioperm/iopl access */
-/* Allow sending USB messages to any device via /proc/bus/usb */
+/* Allow sending USB messages to any device via /dev/bus/usb */
 
 #define CAP_SYS_RAWIO        17
 
@@ -349,7 +362,7 @@ struct vfs_cap_data {
 
 /* Allow reading the audit log via multicast netlink socket */
 
-#define CAP_AUDIT_READ       37
+#define CAP_AUDIT_READ		37
 
 
 #define CAP_LAST_CAP         CAP_AUDIT_READ
@@ -364,4 +377,4 @@ struct vfs_cap_data {
 #define CAP_TO_MASK(x)      (1 << ((x) & 31)) /* mask for indexed __u32 */
 
 
-#endif /* _UAPI_LINUX_CAPABILITY_H */
+#endif /* _LINUX_CAPABILITY_H */
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/9] cap_file: use struct vfs_ns_cap_data if possible
  2018-08-10 16:13 [PATCH 0/9] libcap: add user namespace fscaps support Christian Brauner
  2018-08-10 16:13 ` [PATCH 1/9] cap_file: use v3 xattr macros Christian Brauner
  2018-08-10 16:13 ` [PATCH 2/9] capability: update to new uapi header Christian Brauner
@ 2018-08-10 16:13 ` Christian Brauner
  2018-08-10 16:13 ` [PATCH 4/9] cap_file: add new rootid argument Christian Brauner
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Christian Brauner @ 2018-08-10 16:13 UTC (permalink / raw)
  To: linux-security-module

On kernels with VFS_CAP_REVISION_3 we should use struct_vfs_ns_cap_data.

Signed-off-by: Christian Brauner <christian@brauner.io>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
---
 libcap/cap_file.c | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/libcap/cap_file.c b/libcap/cap_file.c
index 228d806..9b8f11e 100644
--- a/libcap/cap_file.c
+++ b/libcap/cap_file.c
@@ -37,8 +37,12 @@ extern int fremovexattr(int, const char *);
 #define FIXUP_32BITS(x) (x)
 #endif
 
-static cap_t _fcaps_load(struct vfs_cap_data *rawvfscap, cap_t result,
+#ifdef VFS_CAP_REVISION_3
+static cap_t _fcaps_load(struct vfs_ns_cap_data *rawvfscap, cap_t result,
 			 int bytes)
+#else
+static cap_t _fcaps_load(struct vfs_cap_data *rawvfscap, cap_t result, int bytes)
+#endif
 {
     __u32 magic_etc;
     unsigned tocopy, i;
@@ -102,8 +106,12 @@ static cap_t _fcaps_load(struct vfs_cap_data *rawvfscap, cap_t result,
     return result;
 }
 
-static int _fcaps_save(struct vfs_cap_data *rawvfscap, cap_t cap_d,
+#ifdef VFS_CAP_REVISION_3
+static int _fcaps_save(struct vfs_ns_cap_data *rawvfscap, cap_t cap_d,
 		       int *bytes_p)
+#else
+static int _fcaps_save(struct vfs_cap_data *rawvfscap, cap_t cap_d, int *bytes_p)
+#endif
 {
     __u32 eff_not_zero, magic;
     unsigned tocopy, i;
@@ -203,7 +211,11 @@ cap_t cap_get_fd(int fildes)
     /* allocate a new capability set */
     result = cap_init();
     if (result) {
+#ifdef VFS_CAP_REVISION_3
+	struct vfs_ns_cap_data rawvfscap;
+#else
 	struct vfs_cap_data rawvfscap;
+#endif
 	int sizeofcaps;
 
 	_cap_debug("getting fildes capabilities");
@@ -233,7 +245,11 @@ cap_t cap_get_file(const char *filename)
     /* allocate a new capability set */
     result = cap_init();
     if (result) {
+#ifdef VFS_CAP_REVISION_3
+	struct vfs_ns_cap_data rawvfscap;
+#else
 	struct vfs_cap_data rawvfscap;
+#endif
 	int sizeofcaps;
 
 	_cap_debug("getting filename capabilities");
@@ -259,7 +275,11 @@ cap_t cap_get_file(const char *filename)
 
 int cap_set_fd(int fildes, cap_t cap_d)
 {
+#ifdef VFS_CAP_REVISION_3
+    struct vfs_ns_cap_data rawvfscap;
+#else
     struct vfs_cap_data rawvfscap;
+#endif
     int sizeofcaps;
     struct stat buf;
 
@@ -291,7 +311,11 @@ int cap_set_fd(int fildes, cap_t cap_d)
 
 int cap_set_file(const char *filename, cap_t cap_d)
 {
+#ifdef VFS_CAP_REVISION_3
+    struct vfs_ns_cap_data rawvfscap;
+#else
     struct vfs_cap_data rawvfscap;
+#endif
     int sizeofcaps;
     struct stat buf;
 
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/9] cap_file: add new rootid argument
  2018-08-10 16:13 [PATCH 0/9] libcap: add user namespace fscaps support Christian Brauner
                   ` (2 preceding siblings ...)
  2018-08-10 16:13 ` [PATCH 3/9] cap_file: use struct vfs_ns_cap_data if possible Christian Brauner
@ 2018-08-10 16:13 ` Christian Brauner
  2018-08-10 16:13 ` [PATCH 5/9] cap_file: initialize rootid in _fcaps_load() Christian Brauner
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Christian Brauner @ 2018-08-10 16:13 UTC (permalink / raw)
  To: linux-security-module

Newer kernels support setting file capabilities in user namespaces. In
addition to directly setting file capabilites in a user namespaces they
can also be set in lieu of another user namespace by passing a uid down
to the kernel which will convert it to an appropriate kuid_t
representation.
This commit adds a new rootid argument to the internal struct
_cap_struct so that we can store the rootid when the kernel supports
VFS_CAP_REVISION_3 and returns a struct vfs_ns_cap_data.

Signed-off-by: Christian Brauner <christian@brauner.io>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
---
 libcap/libcap.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libcap/libcap.h b/libcap/libcap.h
index 2596c11..9abe4a2 100644
--- a/libcap/libcap.h
+++ b/libcap/libcap.h
@@ -118,6 +118,7 @@ struct _cap_struct {
 	struct __user_cap_data_struct set;
 	__u32 flat[NUMBER_OF_CAP_SETS];
     } u[_LIBCAP_CAPABILITY_U32S];
+    uid_t rootid;
 };
 
 /* the maximum bits supportable */
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 5/9] cap_file: initialize rootid in _fcaps_load()
  2018-08-10 16:13 [PATCH 0/9] libcap: add user namespace fscaps support Christian Brauner
                   ` (3 preceding siblings ...)
  2018-08-10 16:13 ` [PATCH 4/9] cap_file: add new rootid argument Christian Brauner
@ 2018-08-10 16:13 ` Christian Brauner
  2018-08-10 16:13 ` [PATCH 6/9] capability: add cap_get_nsowner() Christian Brauner
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Christian Brauner @ 2018-08-10 16:13 UTC (permalink / raw)
  To: linux-security-module

When the kernel supports namespaced file capabilites (VFS_REVISION_3) it
will return a struct vfs_ns_cap_data that will contain an additional
rootid field recording the rootid of the file capability sets in the
current user namespace.

When libcap has been compiled on a kernel that supports
VFS_CAP_REVISION_3 but is used on a kernel that does not support
VFS_CAP_REVISION_3 we need to initialize the root id of struct
vfs_ns_cap_data to zero so that no invalid data is passed along when a
VFS_REVISION_2 fcap was set on the file.

Signed-off-by: Christian Brauner <christian@brauner.io>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
---
 libcap/cap_file.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/libcap/cap_file.c b/libcap/cap_file.c
index 9b8f11e..eb98bf7 100644
--- a/libcap/cap_file.c
+++ b/libcap/cap_file.c
@@ -103,6 +103,13 @@ static cap_t _fcaps_load(struct vfs_cap_data *rawvfscap, cap_t result, int bytes
 	i++;
     }
 
+#ifdef VFS_CAP_REVISION_3
+    /* The kernel returns the rootid as a _le32. In case we're on a big endian
+     * machine we need to fix this up.
+     */
+    result->rootid = FIXUP_32BITS(rawvfscap->rootid);
+#endif
+
     return result;
 }
 
@@ -221,6 +228,7 @@ cap_t cap_get_fd(int fildes)
 	_cap_debug("getting fildes capabilities");
 
 	/* fill the capability sets via a system call */
+	rawvfscap.rootid = 0;
 	sizeofcaps = fgetxattr(fildes, XATTR_NAME_CAPS,
 			       &rawvfscap, sizeof(rawvfscap));
 	if (sizeofcaps < ssizeof(rawvfscap.magic_etc)) {
@@ -255,6 +263,7 @@ cap_t cap_get_file(const char *filename)
 	_cap_debug("getting filename capabilities");
 
 	/* fill the capability sets via a system call */
+	rawvfscap.rootid = 0;
 	sizeofcaps = getxattr(filename, XATTR_NAME_CAPS,
 			      &rawvfscap, sizeof(rawvfscap));
 	if (sizeofcaps < ssizeof(rawvfscap.magic_etc)) {
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 6/9] capability: add cap_get_nsowner()
  2018-08-10 16:13 [PATCH 0/9] libcap: add user namespace fscaps support Christian Brauner
                   ` (4 preceding siblings ...)
  2018-08-10 16:13 ` [PATCH 5/9] cap_file: initialize rootid in _fcaps_load() Christian Brauner
@ 2018-08-10 16:13 ` Christian Brauner
  2018-08-10 16:13 ` [PATCH 7/9] cap_file: save rootid in _fcaps_save() Christian Brauner
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Christian Brauner @ 2018-08-10 16:13 UTC (permalink / raw)
  To: linux-security-module

cap_get_nsowner() allows to retrieve the rootid of the file capability sets
in the current user namespace.

Signed-off-by: Christian Brauner <christian@brauner.io>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
---
 libcap/cap_file.c               | 16 ++++++++++++++++
 libcap/include/sys/capability.h |  1 +
 2 files changed, 17 insertions(+)

diff --git a/libcap/cap_file.c b/libcap/cap_file.c
index eb98bf7..7acd60c 100644
--- a/libcap/cap_file.c
+++ b/libcap/cap_file.c
@@ -277,6 +277,16 @@ cap_t cap_get_file(const char *filename)
     return result;
 }
 
+/*
+ * Get rootid as seen in the current user namespace for the file capability
+ * sets.
+ */
+
+uid_t cap_get_nsowner(cap_t cap_d)
+{
+	return cap_d->rootid;
+}
+
 /*
  * Set the capabilities of an open file, as specified by its file
  * descriptor.
@@ -363,6 +373,12 @@ cap_t cap_get_file(const char *filename)
     return NULL;
 }
 
+uid_t cap_get_nsowner(cap_t cap_d)
+{
+    errno = EINVAL;
+    return -1;
+}
+
 int cap_set_fd(int fildes, cap_t cap_d)
 {
     errno = EINVAL;
diff --git a/libcap/include/sys/capability.h b/libcap/include/sys/capability.h
index 0976fa7..42d8154 100644
--- a/libcap/include/sys/capability.h
+++ b/libcap/include/sys/capability.h
@@ -82,6 +82,7 @@ extern int     cap_clear_flag(cap_t, cap_flag_t);
 /* libcap/cap_file.c */
 extern cap_t   cap_get_fd(int);
 extern cap_t   cap_get_file(const char *);
+extern uid_t   cap_get_nsowner(cap_t);
 extern int     cap_set_fd(int, cap_t);
 extern int     cap_set_file(const char *, cap_t);
 
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 7/9] cap_file: save rootid in _fcaps_save()
  2018-08-10 16:13 [PATCH 0/9] libcap: add user namespace fscaps support Christian Brauner
                   ` (5 preceding siblings ...)
  2018-08-10 16:13 ` [PATCH 6/9] capability: add cap_get_nsowner() Christian Brauner
@ 2018-08-10 16:13 ` Christian Brauner
  2018-08-10 16:13 ` [PATCH 8/9] cap_file: handle run- vs buildtime vfs cap support Christian Brauner
  2018-08-10 16:13 ` [PATCH 9/9] capability: add cap_set_nsowner() Christian Brauner
  8 siblings, 0 replies; 11+ messages in thread
From: Christian Brauner @ 2018-08-10 16:13 UTC (permalink / raw)
  To: linux-security-module

When the kernel supports namespaced file capabilites (VFS_REVISION_3) it
will take a struct vfs_ns_cap_data that will contain an additional
rootid field recording a rootid.
It can be used to set the rootid of a target user namespace as seen in
the current user namespace. This allows a user namespace to set file
capabilities in lieu of another user namespace.

Signed-off-by: Christian Brauner <christian@brauner.io>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
---
 libcap/cap_file.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/libcap/cap_file.c b/libcap/cap_file.c
index 7acd60c..57c6e3f 100644
--- a/libcap/cap_file.c
+++ b/libcap/cap_file.c
@@ -197,6 +197,13 @@ static int _fcaps_save(struct vfs_cap_data *rawvfscap, cap_t cap_d, int *bytes_p
 	}
     }
 
+#ifdef VFS_CAP_REVISION_3
+    /* The kernel expects the rootid to be a _le32. In case we're on a big
+     * endian machine we need to fix this up.
+     */
+    rawvfscap->rootid = FIXUP_32BITS(cap_d->rootid);
+#endif
+
     if (eff_not_zero == 0) {
 	rawvfscap->magic_etc = FIXUP_32BITS(magic);
     } else {
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 8/9] cap_file: handle run- vs buildtime vfs cap support
  2018-08-10 16:13 [PATCH 0/9] libcap: add user namespace fscaps support Christian Brauner
                   ` (6 preceding siblings ...)
  2018-08-10 16:13 ` [PATCH 7/9] cap_file: save rootid in _fcaps_save() Christian Brauner
@ 2018-08-10 16:13 ` Christian Brauner
  2018-08-10 16:13 ` [PATCH 9/9] capability: add cap_set_nsowner() Christian Brauner
  8 siblings, 0 replies; 11+ messages in thread
From: Christian Brauner @ 2018-08-10 16:13 UTC (permalink / raw)
  To: linux-security-module

If libcap was compiled on a kernel supporting VFS_CAP_REVISION_3 but
running on a kernel that does not support VFS_CAP_REVISION_3 we should
always pass down a legacy struct vfs_cap_data if the rootid is 0. On
kernels supporting VFS_CAP_REVISION_3 the kernel will take care of
translating it from VFS_CAP_REVISION_2 to a VFS_CAP_REVISION_3 version.
We can elegantly handle both cases by setting magic to
VFS_CAP_REVISION_2 and only passing down XATTR_CAPS_SZ_2 bytes which
will leave out the rootid field.
If the rootid field is not 0 then we will pass down the
VFS_CAP_REVISION_3 and XATTR_CAPS_SZ_3. On kernels supporting
VFS_CAP_REVISION_3 this will succeed on kernels not supporting
VFS_CAP_REVISION_3 this will fail. The failure on kernels not supporting
VFS_CAP_REVISION_3 is wanted since the user explicitly requested an
unprivileged file capability but the kernel does not actually support
it. So fail hard.

Signed-off-by: Christian Brauner <christian@brauner.io>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
---
 libcap/cap_file.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/libcap/cap_file.c b/libcap/cap_file.c
index 57c6e3f..a1f3891 100644
--- a/libcap/cap_file.c
+++ b/libcap/cap_file.c
@@ -202,6 +202,24 @@ static int _fcaps_save(struct vfs_cap_data *rawvfscap, cap_t cap_d, int *bytes_p
      * endian machine we need to fix this up.
      */
     rawvfscap->rootid = FIXUP_32BITS(cap_d->rootid);
+    if (rawvfscap->rootid == 0) {
+	/* If libcap was compiled on a kernel supporting VFS_CAP_REVISION_3 but
+	 * running on a kernel that does not support VFS_CAP_REVISION_3 we
+	 * should always pass down a legacy struct vfs_cap_data if the rootid is
+	 * 0. On kernels supporting VFS_CAP_REVISION_3 the kernel will take care
+	 * of translating it from VFS_CAP_REVISION_2 to a VFS_CAP_REVISION_3
+	 * version.  We can elegantly handle both cases by setting magic to
+	 * VFS_CAP_REVISION_2 and only passing down XATTR_CAPS_SZ_2 bytes which
+	 * will leave out the rootid field.  If the rootid field is not 0 then
+	 * we will pass down the VFS_CAP_REVISION_3 and XATTR_CAPS_SZ_3. On
+	 * kernels supporting VFS_CAP_REVISION_3 this will succeed on kernels
+	 * not supporting VFS_CAP_REVISION_3 this will fail. The failure on kernels
+	 * not supporting VFS_CAP_REVISION_3 is wanted since the user explicitly
+	 * requested an unprivileged file capability but the kernel does not
+	 * actually support it. So fail hard. */
+	magic = VFS_CAP_REVISION_2;
+	*bytes_p = XATTR_CAPS_SZ_2;
+    }
 #endif
 
     if (eff_not_zero == 0) {
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 9/9] capability: add cap_set_nsowner()
  2018-08-10 16:13 [PATCH 0/9] libcap: add user namespace fscaps support Christian Brauner
                   ` (7 preceding siblings ...)
  2018-08-10 16:13 ` [PATCH 8/9] cap_file: handle run- vs buildtime vfs cap support Christian Brauner
@ 2018-08-10 16:13 ` Christian Brauner
  8 siblings, 0 replies; 11+ messages in thread
From: Christian Brauner @ 2018-08-10 16:13 UTC (permalink / raw)
  To: linux-security-module

cap_set_nsowner() allows to set the rootid of file capability sets. It can
be used to set the rootid of a target user namespace as seen in the
current user namespace. This allows a user namespace to set file
capabilities in lieu of another user namespace.

Signed-off-by: Christian Brauner <christian@brauner.io>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
---
 libcap/cap_file.c               | 16 ++++++++++++++++
 libcap/include/sys/capability.h |  1 +
 2 files changed, 17 insertions(+)

diff --git a/libcap/cap_file.c b/libcap/cap_file.c
index a1f3891..9a1643c 100644
--- a/libcap/cap_file.c
+++ b/libcap/cap_file.c
@@ -384,6 +384,16 @@ int cap_set_file(const char *filename, cap_t cap_d)
     return setxattr(filename, XATTR_NAME_CAPS, &rawvfscap, sizeofcaps, 0);
 }
 
+/*
+ * Set rootid for the file capability sets.
+ */
+
+int cap_set_nsowner(cap_t cap_d, uid_t rootid)
+{
+	cap_d->rootid = rootid;
+	return 0;
+}
+
 #else /* ie. ndef VFS_CAP_U32 */
 
 cap_t cap_get_fd(int fildes)
@@ -416,4 +426,10 @@ int cap_set_file(const char *filename, cap_t cap_d)
     return -1;
 }
 
+void cap_set_nsowner(cap_t cap_d, uid_t rootid)
+{
+	errno = EINVAL;
+	return -1;
+}
+
 #endif /* def VFS_CAP_U32 */
diff --git a/libcap/include/sys/capability.h b/libcap/include/sys/capability.h
index 42d8154..a9515b6 100644
--- a/libcap/include/sys/capability.h
+++ b/libcap/include/sys/capability.h
@@ -85,6 +85,7 @@ extern cap_t   cap_get_file(const char *);
 extern uid_t   cap_get_nsowner(cap_t);
 extern int     cap_set_fd(int, cap_t);
 extern int     cap_set_file(const char *, cap_t);
+extern int     cap_set_nsowner(cap_t, uid_t);
 
 /* libcap/cap_proc.c */
 extern cap_t   cap_get_proc(void);
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 1/9] cap_file: use v3 xattr macros
  2018-08-10 16:13 ` [PATCH 1/9] cap_file: use v3 xattr macros Christian Brauner
@ 2018-08-13 16:11   ` Serge E. Hallyn
  0 siblings, 0 replies; 11+ messages in thread
From: Serge E. Hallyn @ 2018-08-13 16:11 UTC (permalink / raw)
  To: linux-security-module

Quoting Christian Brauner (christian at brauner.io):
> On kernels supporting VFS_CAP_REVISION_3 we should make use the new
> macros.
> 
> Signed-off-by: Christian Brauner <christian@brauner.io>
> Reviewed-by: Serge Hallyn <serge@hallyn.com>

Hi Andrew,

are you open to taking this patchset (or one like it) in
libcap2?

thanks,
-serge

> ---
>  libcap/cap_file.c | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> diff --git a/libcap/cap_file.c b/libcap/cap_file.c
> index 76aac8c..228d806 100644
> --- a/libcap/cap_file.c
> +++ b/libcap/cap_file.c
> @@ -59,6 +59,13 @@ static cap_t _fcaps_load(struct vfs_cap_data *rawvfscap, cap_t result,
>  	break;
>  #endif
>  
> +#ifdef VFS_CAP_REVISION_3
> +    case VFS_CAP_REVISION_3:
> +	tocopy = VFS_CAP_U32_3;
> +	bytes -= XATTR_CAPS_SZ_3;
> +	break;
> +#endif
> +
>      default:
>  	cap_free(result);
>  	result = NULL;
> @@ -125,9 +132,15 @@ static int _fcaps_save(struct vfs_cap_data *rawvfscap, cap_t cap_d,
>  
>  #ifdef _LINUX_CAPABILITY_VERSION_3
>      case _LINUX_CAPABILITY_VERSION_3:
> +#ifdef VFS_CAP_REVISION_3
> +	magic = VFS_CAP_REVISION_3;
> +	tocopy = VFS_CAP_U32_3;
> +	*bytes_p = XATTR_CAPS_SZ_3;
> +#else
>  	magic = VFS_CAP_REVISION_2;
>  	tocopy = VFS_CAP_U32_2;
>  	*bytes_p = XATTR_CAPS_SZ_2;
> +#endif
>  	break;
>  #endif
>  
> -- 
> 2.17.1

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2018-08-13 16:11 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-10 16:13 [PATCH 0/9] libcap: add user namespace fscaps support Christian Brauner
2018-08-10 16:13 ` [PATCH 1/9] cap_file: use v3 xattr macros Christian Brauner
2018-08-13 16:11   ` Serge E. Hallyn
2018-08-10 16:13 ` [PATCH 2/9] capability: update to new uapi header Christian Brauner
2018-08-10 16:13 ` [PATCH 3/9] cap_file: use struct vfs_ns_cap_data if possible Christian Brauner
2018-08-10 16:13 ` [PATCH 4/9] cap_file: add new rootid argument Christian Brauner
2018-08-10 16:13 ` [PATCH 5/9] cap_file: initialize rootid in _fcaps_load() Christian Brauner
2018-08-10 16:13 ` [PATCH 6/9] capability: add cap_get_nsowner() Christian Brauner
2018-08-10 16:13 ` [PATCH 7/9] cap_file: save rootid in _fcaps_save() Christian Brauner
2018-08-10 16:13 ` [PATCH 8/9] cap_file: handle run- vs buildtime vfs cap support Christian Brauner
2018-08-10 16:13 ` [PATCH 9/9] capability: add cap_set_nsowner() Christian Brauner

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.