Re: [PATCH 1/3] xattr: Enable security.capability in user namespaces
Hi Stefan, [auto build test WARNING on linus/master] [also build test WARNING on v4.12-rc6 next-20170623] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Stefan-Berger/Enable-namespaced-file-capabilities/20170625-001722 coccinelle warnings: (new ones prefixed by >>) >> fs/xattr.c:516:10-17: WARNING opportunity for kstrdep (strcpy on line 519) Please review and possibly fold the followup patch. --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Re: [PATCH 1/3] xattr: Enable security.capability in user namespaces
Hi Stefan, [auto build test WARNING on linus/master] [also build test WARNING on v4.12-rc6 next-20170623] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Stefan-Berger/Enable-namespaced-file-capabilities/20170625-001722 coccinelle warnings: (new ones prefixed by >>) >> fs/xattr.c:516:10-17: WARNING opportunity for kstrdep (strcpy on line 519) Please review and possibly fold the followup patch. --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
[PATCH 1/3] xattr: Enable security.capability in user namespaces
This patch enables security.capability in user namespaces but also takes a more general approach to enabling extended attributes in user namespaces. The following rules describe the approach using security.foo as a 'user namespace enabled' extended attribute: Reading of extended attributes: 1) Reading security.foo from a user namespace will read security.foo@uid= of the parent user namespace instead with uid being the mapping of root in that parent user namespace. An exception is if root is mapped to uid 0 on the host, and in this case we will read security.foo directly. --> reading security.foo will read security.foo@uid=1000 for uid mapping of root to 1000. 2) All security.foo@uid= with valid uid mapping in the user namespace can be read. The uid within the user namespace will be mapped to the corresponding uid on the host and that uid will be used in the name of the extended attribute. -> reading security.foo@uid=1 will read security.foo@uid=1001 for uid mapping of root to 1000, size of at least 2. All security.foo@uid= can be read (by root) on the host with values of also being subject to checking for valid mappings. 3) No other security.foo* can be read. The same rules for reading apply to writing and removing of user namespace enabled extended attributes. When listing extended attributes of a file, only those are presented to the user namespace that have a valid mapping. Besides that, names of the extended attributes are adjusted to represent the mapping. This means that if root is mapped to uid 1000 on the host, the security.foo@uid=1000 will be listed as security.foo in the user namespace, security.foo@uid=1001 becomes security.foo@uid=1 and so on. Signed-off-by: Stefan BergerSigned-off-by: Serge Hallyn Reviewed-by: Serge Hallyn --- fs/xattr.c | 433 ++- security/commoncap.c | 36 ++-- security/selinux/hooks.c | 9 +- 3 files changed, 462 insertions(+), 16 deletions(-) diff --git a/fs/xattr.c b/fs/xattr.c index 464c94b..64c4b40 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -133,11 +133,405 @@ xattr_permission(struct inode *inode, const char *name, int mask) return inode_permission(inode, mask); } +/* + * A list of extended attributes that are supported in user namespaces + */ +static const char *const userns_xattrs[] = { + XATTR_NAME_CAPS, + NULL +}; + +/* + * xattrs_is_userns_supported - Check whether an xattr is supported in userns + * + * @name: full name of the extended attribute + * @prefix: do a prefix match (true) or a full match (false) + * + * This function returns < 0 if not supported, an index into userns_xattrs[] + * otherwise. + */ +static int +xattr_is_userns_supported(const char *name, int prefix) +{ + int i; + + if (!name) + return -1; + + for (i = 0; userns_xattrs[i]; i++) { + if (prefix) { + if (!strncmp(userns_xattrs[i], name, +strlen(userns_xattrs[i]))) + return i; + } else { + if (!strcmp(userns_xattrs[i], name)) + return i; + } + } + return -1; +} + +/* + * xattr_write_uid - print a string in the format of "%s@uid=%u", which + * includes a prefix strig + * + * @uid: the uid + * @prefix: prefix string; may be NULL + * + * This function returns a buffer with the string, or a NULL pointer in + * case of out-of-memory error. + */ +static char * +xattr_write_uid(uid_t uid, const char *prefix) +{ + size_t buflen; + char *buffer; + + buflen = sizeof("@uid=") - 1 + sizeof("4294967295") - 1 + 1; + if (prefix) + buflen += strlen(prefix); + + buffer = kmalloc(buflen, GFP_KERNEL); + if (!buffer) + return NULL; + + if (uid == 0) + *buffer = 0; + else + sprintf(buffer, "%s@uid=%u", + (prefix) ? prefix : "", + uid); + + return buffer; +} + +/* + * xattr_parse_uid_from_kuid - parse string in the format @uid=; consider + * user namespaces and check mappings + * + * @uidstr : string in the format "@uid=" + * @userns : the user namespace to consult for uid mappings + * @n_uidstr : returned pointer holding the rewritten @uid= string with + * the uid remapped + * + * This function returns an error code or 0 in case of success. In case + * of success, 'n_uidstr' will hold a valid string. + */ +static int +xattr_parse_uid_from_kuid(const char *uidstr, struct user_namespace *userns, + char **n_uidstr) +{ + int n; + uid_t muid, p_uid; + char d; + kuid_t tuid; + + *n_uidstr = NULL; + + n =
[PATCH 1/3] xattr: Enable security.capability in user namespaces
This patch enables security.capability in user namespaces but also takes a more general approach to enabling extended attributes in user namespaces. The following rules describe the approach using security.foo as a 'user namespace enabled' extended attribute: Reading of extended attributes: 1) Reading security.foo from a user namespace will read security.foo@uid= of the parent user namespace instead with uid being the mapping of root in that parent user namespace. An exception is if root is mapped to uid 0 on the host, and in this case we will read security.foo directly. --> reading security.foo will read security.foo@uid=1000 for uid mapping of root to 1000. 2) All security.foo@uid= with valid uid mapping in the user namespace can be read. The uid within the user namespace will be mapped to the corresponding uid on the host and that uid will be used in the name of the extended attribute. -> reading security.foo@uid=1 will read security.foo@uid=1001 for uid mapping of root to 1000, size of at least 2. All security.foo@uid= can be read (by root) on the host with values of also being subject to checking for valid mappings. 3) No other security.foo* can be read. The same rules for reading apply to writing and removing of user namespace enabled extended attributes. When listing extended attributes of a file, only those are presented to the user namespace that have a valid mapping. Besides that, names of the extended attributes are adjusted to represent the mapping. This means that if root is mapped to uid 1000 on the host, the security.foo@uid=1000 will be listed as security.foo in the user namespace, security.foo@uid=1001 becomes security.foo@uid=1 and so on. Signed-off-by: Stefan Berger Signed-off-by: Serge Hallyn Reviewed-by: Serge Hallyn --- fs/xattr.c | 433 ++- security/commoncap.c | 36 ++-- security/selinux/hooks.c | 9 +- 3 files changed, 462 insertions(+), 16 deletions(-) diff --git a/fs/xattr.c b/fs/xattr.c index 464c94b..64c4b40 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -133,11 +133,405 @@ xattr_permission(struct inode *inode, const char *name, int mask) return inode_permission(inode, mask); } +/* + * A list of extended attributes that are supported in user namespaces + */ +static const char *const userns_xattrs[] = { + XATTR_NAME_CAPS, + NULL +}; + +/* + * xattrs_is_userns_supported - Check whether an xattr is supported in userns + * + * @name: full name of the extended attribute + * @prefix: do a prefix match (true) or a full match (false) + * + * This function returns < 0 if not supported, an index into userns_xattrs[] + * otherwise. + */ +static int +xattr_is_userns_supported(const char *name, int prefix) +{ + int i; + + if (!name) + return -1; + + for (i = 0; userns_xattrs[i]; i++) { + if (prefix) { + if (!strncmp(userns_xattrs[i], name, +strlen(userns_xattrs[i]))) + return i; + } else { + if (!strcmp(userns_xattrs[i], name)) + return i; + } + } + return -1; +} + +/* + * xattr_write_uid - print a string in the format of "%s@uid=%u", which + * includes a prefix strig + * + * @uid: the uid + * @prefix: prefix string; may be NULL + * + * This function returns a buffer with the string, or a NULL pointer in + * case of out-of-memory error. + */ +static char * +xattr_write_uid(uid_t uid, const char *prefix) +{ + size_t buflen; + char *buffer; + + buflen = sizeof("@uid=") - 1 + sizeof("4294967295") - 1 + 1; + if (prefix) + buflen += strlen(prefix); + + buffer = kmalloc(buflen, GFP_KERNEL); + if (!buffer) + return NULL; + + if (uid == 0) + *buffer = 0; + else + sprintf(buffer, "%s@uid=%u", + (prefix) ? prefix : "", + uid); + + return buffer; +} + +/* + * xattr_parse_uid_from_kuid - parse string in the format @uid=; consider + * user namespaces and check mappings + * + * @uidstr : string in the format "@uid=" + * @userns : the user namespace to consult for uid mappings + * @n_uidstr : returned pointer holding the rewritten @uid= string with + * the uid remapped + * + * This function returns an error code or 0 in case of success. In case + * of success, 'n_uidstr' will hold a valid string. + */ +static int +xattr_parse_uid_from_kuid(const char *uidstr, struct user_namespace *userns, + char **n_uidstr) +{ + int n; + uid_t muid, p_uid; + char d; + kuid_t tuid; + + *n_uidstr = NULL; + + n = sscanf(uidstr, "@uid=%u%c", _uid, ); + if (n != 1) +