ceph: avoid accessing / when mounting a subpath
authorYan, Zheng <zyan@redhat.com>
Wed, 14 Sep 2016 06:53:05 +0000 (14:53 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 3 Oct 2016 14:13:50 +0000 (16:13 +0200)
Accessing / causes failuire if the client has caps that restrict path

Signed-off-by: Yan, Zheng <zyan@redhat.com>
fs/ceph/super.c

index e247f6f..a29ffce 100644 (file)
@@ -396,10 +396,12 @@ static int parse_mount_options(struct ceph_mount_options **pfsopt,
         */
        dev_name_end = strchr(dev_name, '/');
        if (dev_name_end) {
-               fsopt->server_path = kstrdup(dev_name_end, GFP_KERNEL);
-               if (!fsopt->server_path) {
-                       err = -ENOMEM;
-                       goto out;
+               if (strlen(dev_name_end) > 1) {
+                       fsopt->server_path = kstrdup(dev_name_end, GFP_KERNEL);
+                       if (!fsopt->server_path) {
+                               err = -ENOMEM;
+                               goto out;
+                       }
                }
        } else {
                dev_name_end = dev_name + strlen(dev_name);
@@ -788,15 +790,10 @@ static struct dentry *open_root_dentry(struct ceph_fs_client *fsc,
                struct inode *inode = req->r_target_inode;
                req->r_target_inode = NULL;
                dout("open_root_inode success\n");
-               if (ceph_ino(inode) == CEPH_INO_ROOT &&
-                   fsc->sb->s_root == NULL) {
-                       root = d_make_root(inode);
-                       if (!root) {
-                               root = ERR_PTR(-ENOMEM);
-                               goto out;
-                       }
-               } else {
-                       root = d_obtain_root(inode);
+               root = d_make_root(inode);
+               if (!root) {
+                       root = ERR_PTR(-ENOMEM);
+                       goto out;
                }
                ceph_init_dentry(root);
                dout("open_root_inode success, root dentry is %p\n", root);
@@ -825,17 +822,24 @@ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc)
        mutex_lock(&fsc->client->mount_mutex);
 
        if (!fsc->sb->s_root) {
+               const char *path;
                err = __ceph_open_session(fsc->client, started);
                if (err < 0)
                        goto out;
 
-               dout("mount opening root\n");
-               root = open_root_dentry(fsc, "", started);
+               if (!fsc->mount_options->server_path) {
+                       path = "";
+                       dout("mount opening path \\t\n");
+               } else {
+                       path = fsc->mount_options->server_path + 1;
+                       dout("mount opening path %s\n", path);
+               }
+               root = open_root_dentry(fsc, path, started);
                if (IS_ERR(root)) {
                        err = PTR_ERR(root);
                        goto out;
                }
-               fsc->sb->s_root = root;
+               fsc->sb->s_root = dget(root);
                first = 1;
 
                err = ceph_fs_debugfs_init(fsc);
@@ -843,19 +847,6 @@ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc)
                        goto fail;
        }
 
-       if (!fsc->mount_options->server_path) {
-               root = fsc->sb->s_root;
-               dget(root);
-       } else {
-               const char *path = fsc->mount_options->server_path + 1;
-               dout("mount opening path %s\n", path);
-               root = open_root_dentry(fsc, path, started);
-               if (IS_ERR(root)) {
-                       err = PTR_ERR(root);
-                       goto fail;
-               }
-       }
-
        fsc->mount_state = CEPH_MOUNT_MOUNTED;
        dout("mount success\n");
        mutex_unlock(&fsc->client->mount_mutex);