Protect VFS plugin internal files.
authorFrantišek Dvořák <valtri@civ.zcu.cz>
Sat, 19 Oct 2013 19:15:58 +0000 (21:15 +0200)
committerFrantišek Dvořák <valtri@civ.zcu.cz>
Fri, 21 Feb 2014 13:36:45 +0000 (14:36 +0100)
src/Vfs.h
src/VfsAuthn.cpp
src/VfsNs.cpp

index 89e366e..5888334 100644 (file)
--- a/src/Vfs.h
+++ b/src/Vfs.h
@@ -12,6 +12,9 @@
 #include <dmlite/cpp/poolmanager.h>
 
 
+#define VFS_FILE ".#vfs."
+#define VFS_FILE_LENGTH 6
+
 #ifdef DEBUG
   #ifdef __GNUC__
     #define debug(MSG, ARGS...) syslog(LOG_DEBUG, "%s::%s(): " MSG, getImplId().c_str(), __func__, ##ARGS)
index cf2823b..a9e37c2 100644 (file)
@@ -6,8 +6,8 @@
 #include "Vfs.h"
 #include "VfsAuthn.h"
 
-#define VFS_USERS ".#vfs.users"
-#define VFS_GROUPS ".#vfs.groups"
+#define VFS_USERS_FILE ".#vfs.users"
+#define VFS_GROUPS_FILE ".#vfs.groups"
 #define VFS_UID_START 500
 #define VFS_GID_START 500
 
@@ -330,7 +330,7 @@ void VfsAuthn::vfsReload() throw (DmException) {
 
   this->users_.clear();
   this->uids_.clear();
-  f = new std::ifstream((this->prefix_ + VFS_USERS).c_str());
+  f = new std::ifstream((this->prefix_ + VFS_USERS_FILE).c_str());
   if (f->is_open()) {
     n = 0;
     while (std::getline(*f, entrypp)) {
@@ -358,7 +358,7 @@ void VfsAuthn::vfsReload() throw (DmException) {
 
   this->groups_.clear();
   this->gids_.clear();
-  f = new std::ifstream((this->prefix_ + VFS_GROUPS).c_str());
+  f = new std::ifstream((this->prefix_ + VFS_GROUPS_FILE).c_str());
   if (f->is_open()) {
     n = 0;
     while (std::getline(*f, entrypp)) {
@@ -393,8 +393,8 @@ void VfsAuthn::vfsSaveUsers() throw (DmException) {
 
   if (this->noSync_) return;
 
-  name = this->prefix_ + VFS_USERS;
-  newName = this->prefix_ + ".new" + VFS_USERS;
+  name = this->prefix_ + VFS_USERS_FILE;
+  newName = this->prefix_ + ".new" + VFS_USERS_FILE;
 
   f.open(newName.c_str());
   if (!f)
@@ -418,8 +418,8 @@ void VfsAuthn::vfsSaveGroups() throw (DmException) {
 
   if (this->noSync_) return;
 
-  name = this->prefix_ + VFS_GROUPS;
-  newName = this->prefix_ + ".new" + VFS_GROUPS;
+  name = this->prefix_ + VFS_GROUPS_FILE;
+  newName = this->prefix_ + ".new" + VFS_GROUPS_FILE;
 
   f.open(newName.c_str());
   if (!f)
index efdc8a2..ff3d9b7 100644 (file)
@@ -17,6 +17,8 @@
 #include "Vfs.h"
 #include "VfsNs.h"
 
+#define IS_VFS_FILE(NAME) (strncmp((NAME), VFS_FILE, VFS_FILE_LENGTH) == 0)
+
 using namespace dmlite;
 
 
@@ -729,12 +731,15 @@ struct dirent* VfsCatalog::readDir(Directory* dir) throw (DmException)
   if (privateDir == NULL)
     vfsThrow(DMLITE_SYSERR(EFAULT), "Tried to read a null directory");
 
-  errno = 0;
-  ent = readdir(privateDir->dir);
-  if (!ent && errno)
-    vfsThrow(errno, "readdir() on '%s' failed", privateDir->path.c_str());
+  do {
+    errno = 0;
+    ent = readdir(privateDir->dir);
+    if (!ent && errno)
+      vfsThrow(errno, "readdir() on '%s' failed", privateDir->path.c_str());
+
+    debug("result %s", ent ? ent->d_name : "(null)");
+  } while (ent && IS_VFS_FILE(ent->d_name));
 
-  debug("result %s", ent ? ent->d_name : "(null)");
   return static_cast<struct dirent*>(ent);
 }
 
@@ -991,10 +996,19 @@ const std::string VfsCatalog::getLocalPath(const std::string &path) {
 ///
 int VfsCatalog::vfsCheckPermissions(const std::string& path, mode_t mode) {
   int ret = 1;
+  const char *name;
 
+  // only configured subjects (user names)
   if (this->allowCurrent) {
     if ((mode & S_IWRITE) != 0) ret = this->allowWriteCurrent ? 0 : 1;
-    else return 0;
+    else ret = 0;
+  }
+
+  // forbid files starting VFS_FILE
+  if (ret == 0) {
+    name = path.c_str();
+    if (name[0] == '/') name++;
+    ret = (IS_VFS_FILE(name));
   }
 
   return ret;