]> git.proxmox.com Git - mirror_spl-debian.git/commitdiff
Update vn_set_pwd() to allow user|kernal address for filename
authorBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 22 Apr 2010 19:48:40 +0000 (12:48 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 22 Apr 2010 19:53:58 +0000 (12:53 -0700)
During module init spl_setup()->The vn_set_pwd("/") was failing
with -EFAULT because user_path_dir() and __user_walk() both
expect 'filename' to be a user space address and it's not in
this case.  To handle this the data segment size is increased
to to ensure strncpy_from_user() does not fail with -EFAULT.

Additionally, I've added a printk() warning to catch this and
log it to the console if it ever reoccurs.  I thought everything
was working properly here because there consequences of this
failing are subtle and usually non-critical.

module/spl/spl-generic.c
module/spl/spl-vnode.c

index 290c5275dc4e5679bd6dd279ec234640002c0f6c..aaf1a4c10d0f386920e6ed1baf04068658074982 100644 (file)
@@ -444,12 +444,16 @@ spl_fini(void)
 void
 spl_setup(void)
 {
+        int rc;
+
         /*
          * At module load time the pwd is set to '/' on a Solaris system.
          * On a Linux system will be set to whatever directory the caller
          * was in when executing insmod/modprobe.
          */
-        vn_set_pwd("/");
+        rc = vn_set_pwd("/");
+        if (rc)
+                printk("SPL: Warning unable to set pwd to '/': %d\n", rc);
 }
 EXPORT_SYMBOL(spl_setup);
 
index 12e09b7817b29d358b363e17a031220ed0a92148..77652a5a259902f4b1ecb4ee2332cc879c30fe10 100644 (file)
@@ -647,9 +647,22 @@ vn_set_pwd(const char *filename)
 {
 #ifdef HAVE_2ARGS_SET_FS_PWD
         struct path path;
+#else
+        struct nameidata nd;
+#endif /* HAVE_2ARGS_SET_FS_PWD */
+        mm_segment_t saved_fs;
         int rc;
         ENTRY;
 
+        /*
+         * user_path_dir() and __user_walk() both expect 'filename' to be
+         * a user space address so we must briefly increase the data segment
+         * size to ensure strncpy_from_user() does not fail with -EFAULT.
+         */
+        saved_fs = get_fs();
+        set_fs(get_ds());
+
+#ifdef HAVE_2ARGS_SET_FS_PWD
         rc = user_path_dir(filename, &path);
         if (rc)
                 GOTO(out, rc);
@@ -663,10 +676,6 @@ vn_set_pwd(const char *filename)
 dput_and_out:
         path_put(&path);
 #else
-        struct nameidata nd;
-        int rc;
-        ENTRY;
-
         rc = __user_walk(filename,
                          LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_CHDIR, &nd);
         if (rc)
@@ -682,6 +691,8 @@ dput_and_out:
         vn_path_release(&nd);
 #endif /* HAVE_2ARGS_SET_FS_PWD */
 out:
+       set_fs(saved_fs);
+
         RETURN(-rc);
 } /* vn_set_pwd() */
 EXPORT_SYMBOL(vn_set_pwd);