WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-3.4-testing] fs-backend: fix default export and fil

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-3.4-testing] fs-backend: fix default export and filename checks
From: "Xen patchbot-3.4-testing" <patchbot-3.4-testing@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 29 Jun 2009 03:21:40 -0700
Delivery-date: Mon, 29 Jun 2009 03:25:14 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1246270480 -3600
# Node ID cd431361c965080aeb71454b1b2de35de7bfdab2
# Parent  30f2a949ff069e912dcb584893e08d167b7c5073
fs-backend: fix default export and filename checks

This patch changes fs-backend to use /var/lib/xen as default export
and check all the file names and paths given by the frontend against
the
export path, so that the frontend can only operate under the export
directory.

Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
xen-unstable changeset:   19860:53b3857e5705
xen-unstable date:        Sat Jun 27 10:47:38 2009 +0100
---
 tools/fs-back/fs-backend.c |    2 
 tools/fs-back/fs-ops.c     |  127 +++++++++++++++++++++++++--------------------
 2 files changed, 74 insertions(+), 55 deletions(-)

diff -r 30f2a949ff06 -r cd431361c965 tools/fs-back/fs-backend.c
--- a/tools/fs-back/fs-backend.c        Mon Jun 29 11:14:18 2009 +0100
+++ b/tools/fs-back/fs-backend.c        Mon Jun 29 11:14:40 2009 +0100
@@ -404,7 +404,7 @@ int main(void)
     xenbus_create_request_node();
     
     /* Create & register the default export */
-    export = create_export("default", "/exports");
+    export = create_export("default", "/var/lib/xen");
     xenbus_register_export(export);
 
     if (socketpair(PF_UNIX,SOCK_STREAM, 0, pipefds) == -1)
diff -r 30f2a949ff06 -r cd431361c965 tools/fs-back/fs-ops.c
--- a/tools/fs-back/fs-ops.c    Mon Jun 29 11:14:18 2009 +0100
+++ b/tools/fs-back/fs-ops.c    Mon Jun 29 11:14:40 2009 +0100
@@ -13,6 +13,7 @@
 #include <sys/statvfs.h>
 #include <sys/mount.h>
 #include <unistd.h>
+#include <ctype.h>
 #include "fs-backend.h"
 #include "fs-debug.h"
 
@@ -22,6 +23,25 @@
 
 
 #define BUFFER_SIZE 1024
+
+static int check_export_path(const char *export_path, const char *path)
+{
+    int i;
+    if (!export_path || !path)
+        return -1;
+    if (strlen(path) < strlen(export_path))
+        return -1;
+    if (strstr(path, "..") != NULL)
+        return -1;
+    for (i = 0; i < strlen(path); i++) {
+        if (!isascii(path[i]))
+            return -1;
+    }
+    if (strncmp(export_path, path, strlen(export_path)))
+        return -1;
+    else
+        return 0;
+}
 
 static unsigned short get_request(struct fs_mount *mount, struct fsif_request 
*req)
 {
@@ -47,7 +67,7 @@ static int get_fd(struct fs_mount *mount
 
 static void dispatch_file_open(struct fs_mount *mount, struct fsif_request 
*req)
 {
-    char *file_name, full_path[BUFFER_SIZE];
+    char *file_name;
     int fd;
     RING_IDX rsp_idx;
     fsif_response_t *rsp;
@@ -62,15 +82,14 @@ static void dispatch_file_open(struct fs
    
     req_id = req->id;
     FS_DEBUG("File open issued for %s\n", file_name); 
-    assert(BUFFER_SIZE > 
-           strlen(file_name) + strlen(mount->export->export_path) + 1); 
-    snprintf(full_path, sizeof(full_path), "%s/%s",
-           mount->export->export_path, file_name);
-    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
-    FS_DEBUG("Issuing open for %s\n", full_path);
+    if (check_export_path(mount->export->export_path, file_name) < 0) {
+        FS_DEBUG("Filename check failed\n");
+        fd = -1;
+        goto out;
+    }
     fd = get_fd(mount);
     if (fd >= 0) {
-        int real_fd = open(full_path, O_RDWR);
+        int real_fd = open(file_name, O_RDWR);
         if (real_fd < 0)
             fd = -1;
         else
@@ -79,6 +98,8 @@ static void dispatch_file_open(struct fs
             FS_DEBUG("Got FD: %d for real %d\n", fd, real_fd);
         }
     }
+out:
+    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
     /* We can advance the request consumer index, from here on, the request
      * should not be used (it may be overrinden by a response) */
     mount->ring.req_cons++;
@@ -349,7 +370,7 @@ static void dispatch_truncate(struct fs_
 
 static void dispatch_remove(struct fs_mount *mount, struct fsif_request *req)
 {
-    char *file_name, full_path[BUFFER_SIZE];
+    char *file_name;
     int ret;
     RING_IDX rsp_idx;
     fsif_response_t *rsp;
@@ -364,14 +385,14 @@ static void dispatch_remove(struct fs_mo
    
     req_id = req->id;
     FS_DEBUG("File remove issued for %s\n", file_name); 
-    assert(BUFFER_SIZE > 
-           strlen(file_name) + strlen(mount->export->export_path) + 1); 
-    snprintf(full_path, sizeof(full_path), "%s/%s",
-           mount->export->export_path, file_name);
+    if (check_export_path(mount->export->export_path, file_name) < 0) {
+        FS_DEBUG("Filename check failed\n");
+        ret = -1;
+    } else {
+        ret = remove(file_name);
+    }
+    FS_DEBUG("Got ret: %d\n", ret);
     assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
-    FS_DEBUG("Issuing remove for %s\n", full_path);
-    ret = remove(full_path);
-    FS_DEBUG("Got ret: %d\n", ret);
     /* We can advance the request consumer index, from here on, the request
      * should not be used (it may be overrinden by a response) */
     mount->ring.req_cons++;
@@ -389,7 +410,6 @@ static void dispatch_rename(struct fs_mo
 static void dispatch_rename(struct fs_mount *mount, struct fsif_request *req)
 {
     char *buf, *old_file_name, *new_file_name;
-    char old_full_path[BUFFER_SIZE], new_full_path[BUFFER_SIZE];
     int ret;
     RING_IDX rsp_idx;
     fsif_response_t *rsp;
@@ -407,18 +427,15 @@ static void dispatch_rename(struct fs_mo
     new_file_name = buf + req->u.frename.new_name_offset;
     FS_DEBUG("File rename issued for %s -> %s (buf=%s)\n", 
             old_file_name, new_file_name, buf); 
-    assert(BUFFER_SIZE > 
-           strlen(old_file_name) + strlen(mount->export->export_path) + 1); 
-    assert(BUFFER_SIZE > 
-           strlen(new_file_name) + strlen(mount->export->export_path) + 1); 
-    snprintf(old_full_path, sizeof(old_full_path), "%s/%s",
-           mount->export->export_path, old_file_name);
-    snprintf(new_full_path, sizeof(new_full_path), "%s/%s",
-           mount->export->export_path, new_file_name);
+    if (check_export_path(mount->export->export_path, old_file_name) < 0 ||
+        check_export_path(mount->export->export_path, new_file_name) < 0) {
+        FS_DEBUG("Filename check failed\n");
+        ret = -1;
+    } else {
+        ret = rename(old_file_name, new_file_name);
+    }
+    FS_DEBUG("Got ret: %d\n", ret);
     assert(xc_gnttab_munmap(mount->gnth, buf, 1) == 0);
-    FS_DEBUG("Issuing rename for %s -> %s\n", old_full_path, new_full_path);
-    ret = rename(old_full_path, new_full_path);
-    FS_DEBUG("Got ret: %d\n", ret);
     /* We can advance the request consumer index, from here on, the request
      * should not be used (it may be overrinden by a response) */
     mount->ring.req_cons++;
@@ -435,7 +452,7 @@ static void dispatch_rename(struct fs_mo
 
 static void dispatch_create(struct fs_mount *mount, struct fsif_request *req)
 {
-    char *file_name, full_path[BUFFER_SIZE];
+    char *file_name;
     int ret;
     int8_t directory;
     int32_t mode;
@@ -453,27 +470,26 @@ static void dispatch_create(struct fs_mo
                                         PROT_READ);
    
     req_id = req->id;
-    FS_DEBUG("File create issued for %s\n", file_name); 
-    assert(BUFFER_SIZE > 
-           strlen(file_name) + strlen(mount->export->export_path) + 1); 
-    snprintf(full_path, sizeof(full_path), "%s/%s",
-           mount->export->export_path, file_name);
-    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
+    if (check_export_path(mount->export->export_path, file_name) < 0) {
+        FS_DEBUG("Filename check failed\n");
+        ret = -1;
+        goto out;
+    }
     /* We can advance the request consumer index, from here on, the request
      * should not be used (it may be overrinden by a response) */
     mount->ring.req_cons++;
 
     if(directory)
     {
-        FS_DEBUG("Issuing create for directory: %s\n", full_path);
-        ret = mkdir(full_path, mode);
+        FS_DEBUG("Issuing create for directory: %s\n", file_name);
+        ret = mkdir(file_name, mode);
     }
     else
     {
-        FS_DEBUG("Issuing create for file: %s\n", full_path);
+        FS_DEBUG("Issuing create for file: %s\n", file_name);
         ret = get_fd(mount);
         if (ret >= 0) {
-            int real_fd = creat(full_path, mode); 
+            int real_fd = creat(file_name, mode);
             if (real_fd < 0)
                 ret = -1;
             else
@@ -483,6 +499,8 @@ static void dispatch_create(struct fs_mo
             }
         }
     }
+out:
+    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
     FS_DEBUG("Got ret %d (errno=%d)\n", ret, errno);
 
     /* Get a response from the ring */
@@ -495,8 +513,8 @@ static void dispatch_create(struct fs_mo
 
 static void dispatch_list(struct fs_mount *mount, struct fsif_request *req)
 {
-    char *file_name, *buf, full_path[BUFFER_SIZE];
-    uint32_t offset, nr_files, error_code; 
+    char *file_name, *buf;
+    uint32_t offset = 0, nr_files = 0, error_code = 0;
     uint64_t ret_val;
     RING_IDX rsp_idx;
     fsif_response_t *rsp;
@@ -514,17 +532,18 @@ static void dispatch_list(struct fs_moun
    
     req_id = req->id;
     FS_DEBUG("Dir list issued for %s\n", file_name); 
-    assert(BUFFER_SIZE > 
-           strlen(file_name) + strlen(mount->export->export_path) + 1); 
-    snprintf(full_path, sizeof(full_path), "%s/%s",
-           mount->export->export_path, file_name);
+    if (check_export_path(mount->export->export_path, file_name) < 0) {
+        FS_DEBUG("Filename check failed\n");
+        error_code = 1;
+        goto error_out;
+    }
     /* We can advance the request consumer index, from here on, the request
      * should not be used (it may be overrinden by a response) */
     mount->ring.req_cons++;
 
     ret_val = 0;
     nr_files = 0;
-    dir = opendir(full_path);
+    dir = opendir(file_name);
     if(dir == NULL)
     {
         error_code = errno;
@@ -596,7 +615,7 @@ static void dispatch_chmod(struct fs_mou
 
 static void dispatch_fs_space(struct fs_mount *mount, struct fsif_request *req)
 {
-    char *file_name, full_path[BUFFER_SIZE];
+    char *file_name;
     RING_IDX rsp_idx;
     fsif_response_t *rsp;
     uint16_t req_id;
@@ -612,16 +631,16 @@ static void dispatch_fs_space(struct fs_
    
     req_id = req->id;
     FS_DEBUG("Fs space issued for %s\n", file_name); 
-    assert(BUFFER_SIZE > 
-           strlen(file_name) + strlen(mount->export->export_path) + 1); 
-    snprintf(full_path, sizeof(full_path), "%s/%s",
-           mount->export->export_path, file_name);
-    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
-    FS_DEBUG("Issuing fs space for %s\n", full_path);
-    ret = statvfs(full_path, &stat);
+    if (check_export_path(mount->export->export_path, file_name) < 0) {
+        FS_DEBUG("Filename check failed\n");
+        ret = -1;
+    } else {
+        ret = statvfs(file_name, &stat);
+    }
     if(ret >= 0)
         ret = stat.f_bsize * stat.f_bfree;
 
+    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
     /* We can advance the request consumer index, from here on, the request
      * should not be used (it may be overrinden by a response) */
     mount->ring.req_cons++;

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-3.4-testing] fs-backend: fix default export and filename checks, Xen patchbot-3.4-testing <=