summaryrefslogtreecommitdiff
path: root/lib/replace
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2017-02-03 18:08:12 +0100
committerJeremy Allison <jra@samba.org>2017-02-10 18:33:17 +0100
commit738797d8ad6908de457786cc948dcde151e2b9e1 (patch)
treefdc127546618492a3d41f68ca8377e32f1522f61 /lib/replace
parente4d1f8354f97ab9007e4c5f7d164937bdc5cd6f1 (diff)
downloadsamba-738797d8ad6908de457786cc948dcde151e2b9e1.tar.gz
lib/replace: validate xattr namespace prefix on FreeBSD
We should validate the xattr name string ensuring it either begins with "sytem." or "user.". If it doesn't, we should fail the request with EINVAL. The FreeBSD xattr API uses namespaces but doesn't put the namespace name as a string prefix at the beginning of the xattr name. It gets passed as an additional int arg instead. On the other hand, our libreplace xattr API expects the caller to put a namespace prefix into the xattr name. Unfortunately the conversion and stripping of the namespace string prefix from the xattr name gives the following unexpected result on FreeBSD: rep_setxattr("foo.bar", ...) => xattr with name "bar" The code checks if the name begins with "system.", if it doesn't find it, it defaults to the user namespace and then does a strchr(name, '.') which skips *any* leading string before the first dot. Bug: https://bugzilla.samba.org/show_bug.cgi?id=12490 Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'lib/replace')
-rw-r--r--lib/replace/xattr.c105
1 files changed, 81 insertions, 24 deletions
diff --git a/lib/replace/xattr.c b/lib/replace/xattr.c
index ce52d1a581a..2479c21b553 100644
--- a/lib/replace/xattr.c
+++ b/lib/replace/xattr.c
@@ -61,11 +61,21 @@ ssize_t rep_getxattr (const char *path, const char *name, void *value, size_t si
#elif defined(HAVE_GETEA)
return getea(path, name, value, size);
#elif defined(HAVE_EXTATTR_GET_FILE)
- char *s;
ssize_t retval;
- int attrnamespace = (strncmp(name, "system", 6) == 0) ?
- EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
- const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1;
+ int attrnamespace;
+ const char *attrname;
+
+ if (strncmp(name, "system.", 7) == 0) {
+ attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
+ attrname = name + 7;
+ } else if (strncmp(name, "user.", 5) == 0) {
+ attrnamespace = EXTATTR_NAMESPACE_USER;
+ attrname = name + 5;
+ } else {
+ errno = EINVAL;
+ return -1;
+ }
+
/*
* The BSD implementation has a nasty habit of silently truncating
* the returned value to the size of the buffer, so we have to check
@@ -125,11 +135,20 @@ ssize_t rep_fgetxattr (int filedes, const char *name, void *value, size_t size)
#elif defined(HAVE_FGETEA)
return fgetea(filedes, name, value, size);
#elif defined(HAVE_EXTATTR_GET_FD)
- char *s;
ssize_t retval;
- int attrnamespace = (strncmp(name, "system", 6) == 0) ?
- EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
- const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1;
+ int attrnamespace;
+ const char *attrname;
+
+ if (strncmp(name, "system.", 7) == 0) {
+ attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
+ attrname = name + 7;
+ } else if (strncmp(name, "user.", 5) == 0) {
+ attrnamespace = EXTATTR_NAMESPACE_USER;
+ attrname = name + 5;
+ } else {
+ errno = EINVAL;
+ return -1;
+ }
if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
if (size == 0) {
@@ -414,10 +433,19 @@ int rep_removexattr (const char *path, const char *name)
#elif defined(HAVE_REMOVEEA)
return removeea(path, name);
#elif defined(HAVE_EXTATTR_DELETE_FILE)
- char *s;
- int attrnamespace = (strncmp(name, "system", 6) == 0) ?
- EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
- const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1;
+ int attrnamespace;
+ const char *attrname;
+
+ if (strncmp(name, "system.", 7) == 0) {
+ attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
+ attrname = name + 7;
+ } else if (strncmp(name, "user.", 5) == 0) {
+ attrnamespace = EXTATTR_NAMESPACE_USER;
+ attrname = name + 5;
+ } else {
+ errno = EINVAL;
+ return -1;
+ }
return extattr_delete_file(path, attrnamespace, attrname);
#elif defined(HAVE_ATTR_REMOVE)
@@ -455,10 +483,19 @@ int rep_fremovexattr (int filedes, const char *name)
#elif defined(HAVE_FREMOVEEA)
return fremoveea(filedes, name);
#elif defined(HAVE_EXTATTR_DELETE_FD)
- char *s;
- int attrnamespace = (strncmp(name, "system", 6) == 0) ?
- EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
- const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1;
+ int attrnamespace;
+ const char *attrname;
+
+ if (strncmp(name, "system.", 7) == 0) {
+ attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
+ attrname = name + 7;
+ } else if (strncmp(name, "user.", 5) == 0) {
+ attrnamespace = EXTATTR_NAMESPACE_USER;
+ attrname = name + 5;
+ } else {
+ errno = EINVAL;
+ return -1;
+ }
return extattr_delete_fd(filedes, attrnamespace, attrname);
#elif defined(HAVE_ATTR_REMOVEF)
@@ -496,11 +533,21 @@ int rep_setxattr (const char *path, const char *name, const void *value, size_t
#elif defined(HAVE_SETEA)
return setea(path, name, value, size, flags);
#elif defined(HAVE_EXTATTR_SET_FILE)
- char *s;
int retval = 0;
- int attrnamespace = (strncmp(name, "system", 6) == 0) ?
- EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
- const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1;
+ int attrnamespace;
+ const char *attrname;
+
+ if (strncmp(name, "system.", 7) == 0) {
+ attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
+ attrname = name + 7;
+ } else if (strncmp(name, "user.", 5) == 0) {
+ attrnamespace = EXTATTR_NAMESPACE_USER;
+ attrname = name + 5;
+ } else {
+ errno = EINVAL;
+ return -1;
+ }
+
if (flags) {
/* Check attribute existence */
retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
@@ -563,11 +610,21 @@ int rep_fsetxattr (int filedes, const char *name, const void *value, size_t size
#elif defined(HAVE_FSETEA)
return fsetea(filedes, name, value, size, flags);
#elif defined(HAVE_EXTATTR_SET_FD)
- char *s;
int retval = 0;
- int attrnamespace = (strncmp(name, "system", 6) == 0) ?
- EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
- const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1;
+ int attrnamespace;
+ const char *attrname;
+
+ if (strncmp(name, "system.", 7) == 0) {
+ attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
+ attrname = name + 7;
+ } else if (strncmp(name, "user.", 5) == 0) {
+ attrnamespace = EXTATTR_NAMESPACE_USER;
+ attrname = name + 5;
+ } else {
+ errno = EINVAL;
+ return -1;
+ }
+
if (flags) {
/* Check attribute existence */
retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);