Module Name: src Committed By: manu Date: Sun Aug 10 03:22:33 UTC 2014
Modified Files: src/lib/libperfuse: ops.c perfuse_priv.h subr.c Log Message: - Make sure non root users cannot access system namespace attributes - honour namespace specification when listing attributes - Also fix message memory leak introduced by previous commit To generate a diff of this commit: cvs rdiff -u -r1.65 -r1.66 src/lib/libperfuse/ops.c cvs rdiff -u -r1.31 -r1.32 src/lib/libperfuse/perfuse_priv.h cvs rdiff -u -r1.19 -r1.20 src/lib/libperfuse/subr.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libperfuse/ops.c diff -u src/lib/libperfuse/ops.c:1.65 src/lib/libperfuse/ops.c:1.66 --- src/lib/libperfuse/ops.c:1.65 Sat Aug 9 19:06:50 2014 +++ src/lib/libperfuse/ops.c Sun Aug 10 03:22:33 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ops.c,v 1.65 2014/08/09 19:06:50 manu Exp $ */ +/* $NetBSD: ops.c,v 1.66 2014/08/10 03:22:33 manu Exp $ */ /*- * Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved. @@ -3323,6 +3323,10 @@ perfuse_node_getextattr(struct puffs_use char *np; int error; + /* system namespace attrs are not accessible to non root users */ + if (attrns == EXTATTR_NAMESPACE_SYSTEM && !puffs_cred_isjuggernaut(pcr)) + return EPERM; + node_ref(opc); ps = puffs_getspecific(pu); attrname = perfuse_native_ns(attrns, attrname, fuse_attrname); @@ -3367,6 +3371,7 @@ perfuse_node_getextattr(struct puffs_use if (resid != NULL) { if (*resid < len) { error = ERANGE; + ps->ps_destroy_msg(pm); goto out; } @@ -3396,6 +3401,10 @@ perfuse_node_setextattr(struct puffs_use char *np; int error; + /* system namespace attrs are not accessible to non root users */ + if (attrns == EXTATTR_NAMESPACE_SYSTEM && !puffs_cred_isjuggernaut(pcr)) + return EPERM; + node_ref(opc); ps = puffs_getspecific(pu); attrname = perfuse_native_ns(attrns, attrname, fuse_attrname); @@ -3436,9 +3445,13 @@ perfuse_node_listextattr(struct puffs_us struct fuse_getxattr_out *fgo; struct fuse_out_header *foh; char *np; - size_t len, puffs_len; + size_t len, puffs_len, i, attrlen, outlen; int error; + /* system namespace attrs are not accessible to non root users */ + if (attrns == EXTATTR_NAMESPACE_SYSTEM && !puffs_cred_isjuggernaut(pcr)) + return EPERM; + node_ref(opc); ps = puffs_getspecific(pu); @@ -3478,28 +3491,44 @@ perfuse_node_listextattr(struct puffs_us np = (char *)(void *)(foh + 1); puffs_len = foh->len - sizeof(*foh); - if (attrs != NULL) { -#ifdef PUFFS_EXTATTR_LIST_LENPREFIX - /* - * Convert the FUSE reply to length prefixed strings - * if this is what the kernel wants. - */ - if (flag & PUFFS_EXTATTR_LIST_LENPREFIX) { - size_t i, attrlen; + if (attrsize != NULL) + *attrsize = puffs_len; - for (i = 0; i < puffs_len; i += attrlen + 1) { - attrlen = strlen(np + i); - (void)memmove(np + i + 1, np + i, attrlen); - *(np + i) = (uint8_t)attrlen; - } + if (attrs != NULL) { + if (*resid < puffs_len) { + error = ERANGE; + ps->ps_destroy_msg(pm); + goto out; } + + outlen = 0; + + for (i = 0; i < puffs_len; i += attrlen + 1) { + attrlen = strlen(np + i); + + /* + * Filter attributes per namespace + */ + if (!perfuse_ns_match(attrns, np + i)) + continue; + +#ifdef PUFFS_EXTATTR_LIST_LENPREFIX + /* + * Convert the FUSE reply to length prefixed strings + * if this is what the kernel wants. + */ + if (flag & PUFFS_EXTATTR_LIST_LENPREFIX) { + (void)memcpy(attrs + outlen + 1, + np + i, attrlen); + *(attrs + outlen) = (uint8_t)attrlen; + } else #endif /* PUFFS_EXTATTR_LIST_LENPREFIX */ - (void)memcpy(attrs, np, puffs_len); - *resid -= puffs_len; - } + (void)memcpy(attrs + outlen, np + i, attrlen + 1); + outlen += attrlen + 1; + } - if (attrsize != NULL) - *attrsize = puffs_len; + *resid -= outlen; + } ps->ps_destroy_msg(pm); error = 0; @@ -3520,6 +3549,10 @@ perfuse_node_deleteextattr(struct puffs_ char *np; int error; + /* system namespace attrs are not accessible to non root users */ + if (attrns == EXTATTR_NAMESPACE_SYSTEM && !puffs_cred_isjuggernaut(pcr)) + return EPERM; + node_ref(opc); ps = puffs_getspecific(pu); Index: src/lib/libperfuse/perfuse_priv.h diff -u src/lib/libperfuse/perfuse_priv.h:1.31 src/lib/libperfuse/perfuse_priv.h:1.32 --- src/lib/libperfuse/perfuse_priv.h:1.31 Sat Jul 21 05:49:42 2012 +++ src/lib/libperfuse/perfuse_priv.h Sun Aug 10 03:22:33 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: perfuse_priv.h,v 1.31 2012/07/21 05:49:42 manu Exp $ */ +/* $NetBSD: perfuse_priv.h,v 1.32 2014/08/10 03:22:33 manu Exp $ */ /*- * Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved. @@ -186,6 +186,7 @@ uint64_t perfuse_get_fh(puffs_cookie_t, uint64_t perfuse_next_unique(struct puffs_usermount *); char *perfuse_node_path(struct perfuse_state *, puffs_cookie_t); int perfuse_node_close_common(struct puffs_usermount *, puffs_cookie_t, int); +int perfuse_ns_match(const int, const char *); const char *perfuse_native_ns(const int, const char *, char *); char *perfuse_fs_mount(int, ssize_t); Index: src/lib/libperfuse/subr.c diff -u src/lib/libperfuse/subr.c:1.19 src/lib/libperfuse/subr.c:1.20 --- src/lib/libperfuse/subr.c:1.19 Sat Jul 21 05:49:42 2012 +++ src/lib/libperfuse/subr.c Sun Aug 10 03:22:33 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: subr.c,v 1.19 2012/07/21 05:49:42 manu Exp $ */ +/* $NetBSD: subr.c,v 1.20 2014/08/10 03:22:33 manu Exp $ */ /*- * Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved. @@ -215,6 +215,20 @@ perfuse_node_path(struct perfuse_state * return buf; } +int +perfuse_ns_match(const int attrnamespace, const char *attrname) +{ + const char *system_ns[] = { "system.", "trusted.", "security", NULL }; + int i; + + for (i = 0; system_ns[i]; i++) { + if (strncmp(attrname, system_ns[i], strlen(system_ns[i])) == 0) + return (attrnamespace == EXTATTR_NAMESPACE_SYSTEM); + } + + return (attrnamespace == EXTATTR_NAMESPACE_USER); +} + const char * perfuse_native_ns(const int attrnamespace, const char *attrname, char *fuse_attrname)