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)