}
 
 static int
-cifs_parse_mount_options(char *options, const char *devname,
+cifs_parse_mount_options(const char *mountdata, const char *devname,
                         struct smb_vol *vol)
 {
        char *value, *data, *end;
+       char *mountdata_copy, *options;
        unsigned int  temp_len, i, j;
        char separator[2];
        short int override_uid = -1;
 
        vol->actimeo = CIFS_DEF_ACTIMEO;
 
-       if (!options)
-               return 1;
+       if (!mountdata)
+               goto cifs_parse_mount_err;
+
+       mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
+       if (!mountdata_copy)
+               goto cifs_parse_mount_err;
 
+       options = mountdata_copy;
        end = options + strlen(options);
        if (strncmp(options, "sep=", 4) == 0) {
                if (options[4] != 0) {
                        if (!value) {
                                printk(KERN_WARNING
                                       "CIFS: invalid or missing username\n");
-                               return 1;       /* needs_arg; */
+                               goto cifs_parse_mount_err;
                        } else if (!*value) {
                                /* null user, ie anonymous, authentication */
                                vol->nullauth = 1;
                        }
                        if (strnlen(value, MAX_USERNAME_SIZE) <
                                                MAX_USERNAME_SIZE) {
-                               vol->username = value;
+                               vol->username = kstrdup(value, GFP_KERNEL);
+                               if (!vol->username) {
+                                       printk(KERN_WARNING "CIFS: no memory "
+                                                           "for username\n");
+                                       goto cifs_parse_mount_err;
+                               }
                        } else {
                                printk(KERN_WARNING "CIFS: username too long\n");
-                               return 1;
+                               goto cifs_parse_mount_err;
                        }
                } else if (strnicmp(data, "pass", 4) == 0) {
                        if (!value) {
                                if (vol->password == NULL) {
                                        printk(KERN_WARNING "CIFS: no memory "
                                                            "for password\n");
-                                       return 1;
+                                       goto cifs_parse_mount_err;
                                }
                                for (i = 0, j = 0; i < temp_len; i++, j++) {
                                        vol->password[j] = value[i];
                                if (vol->password == NULL) {
                                        printk(KERN_WARNING "CIFS: no memory "
                                                            "for password\n");
-                                       return 1;
+                                       goto cifs_parse_mount_err;
                                }
                                strcpy(vol->password, value);
                        }
                                vol->UNCip = NULL;
                        } else if (strnlen(value, INET6_ADDRSTRLEN) <
                                                        INET6_ADDRSTRLEN) {
-                               vol->UNCip = value;
+                               vol->UNCip = kstrdup(value, GFP_KERNEL);
+                               if (!vol->UNCip) {
+                                       printk(KERN_WARNING "CIFS: no memory "
+                                                           "for UNC IP\n");
+                                       goto cifs_parse_mount_err;
+                               }
                        } else {
                                printk(KERN_WARNING "CIFS: ip address "
                                                    "too long\n");
-                               return 1;
+                               goto cifs_parse_mount_err;
                        }
                } else if (strnicmp(data, "sec", 3) == 0) {
                        if (!value || !*value) {
                                /* vol->secFlg |= CIFSSEC_MUST_SEAL |
                                        CIFSSEC_MAY_KRB5; */
                                cERROR(1, "Krb5 cifs privacy not supported");
-                               return 1;
+                               goto cifs_parse_mount_err;
                        } else if (strnicmp(value, "krb5", 4) == 0) {
                                vol->secFlg |= CIFSSEC_MAY_KRB5;
                        } else if (strnicmp(value, "ntlmsspi", 8) == 0) {
                                vol->nullauth = 1;
                        } else {
                                cERROR(1, "bad security option: %s", value);
-                               return 1;
+                               goto cifs_parse_mount_err;
                        }
                } else if (strnicmp(data, "vers", 3) == 0) {
                        if (!value || !*value) {
                        if (!value || !*value) {
                                printk(KERN_WARNING "CIFS: invalid path to "
                                                    "network resource\n");
-                               return 1;       /* needs_arg; */
+                               goto cifs_parse_mount_err;
                        }
                        if ((temp_len = strnlen(value, 300)) < 300) {
                                vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
                                if (vol->UNC == NULL)
-                                       return 1;
+                                       goto cifs_parse_mount_err;
                                strcpy(vol->UNC, value);
                                if (strncmp(vol->UNC, "//", 2) == 0) {
                                        vol->UNC[0] = '\\';
                                        printk(KERN_WARNING
                                               "CIFS: UNC Path does not begin "
                                               "with // or \\\\ \n");
-                                       return 1;
+                                       goto cifs_parse_mount_err;
                                }
                        } else {
                                printk(KERN_WARNING "CIFS: UNC name too long\n");
-                               return 1;
+                               goto cifs_parse_mount_err;
                        }
                } else if ((strnicmp(data, "domain", 3) == 0)
                           || (strnicmp(data, "workgroup", 5) == 0)) {
                        if (!value || !*value) {
                                printk(KERN_WARNING "CIFS: invalid domain name\n");
-                               return 1;       /* needs_arg; */
+                               goto cifs_parse_mount_err;
                        }
                        /* BB are there cases in which a comma can be valid in
                        a domain name and need special handling? */
                        if (strnlen(value, 256) < 256) {
-                               vol->domainname = value;
+                               vol->domainname = kstrdup(value, GFP_KERNEL);
+                               if (!vol->domainname) {
+                                       printk(KERN_WARNING "CIFS: no memory "
+                                                           "for domainname\n");
+                                       goto cifs_parse_mount_err;
+                               }
                                cFYI(1, "Domain name set");
                        } else {
                                printk(KERN_WARNING "CIFS: domain name too "
                                                    "long\n");
-                               return 1;
+                               goto cifs_parse_mount_err;
                        }
                } else if (strnicmp(data, "srcaddr", 7) == 0) {
                        vol->srcaddr.ss_family = AF_UNSPEC;
                        if (!value || !*value) {
                                printk(KERN_WARNING "CIFS: srcaddr value"
                                       " not specified.\n");
-                               return 1;       /* needs_arg; */
+                               goto cifs_parse_mount_err;
                        }
                        i = cifs_convert_address((struct sockaddr *)&vol->srcaddr,
                                                 value, strlen(value));
                                printk(KERN_WARNING "CIFS:  Could not parse"
                                       " srcaddr: %s\n",
                                       value);
-                               return 1;
+                               goto cifs_parse_mount_err;
                        }
                } else if (strnicmp(data, "prefixpath", 10) == 0) {
                        if (!value || !*value) {
                                printk(KERN_WARNING
                                        "CIFS: invalid path prefix\n");
-                               return 1;       /* needs_argument */
+                               goto cifs_parse_mount_err;
                        }
                        if ((temp_len = strnlen(value, 1024)) < 1024) {
                                if (value[0] != '/')
                                        temp_len++;  /* missing leading slash */
                                vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
                                if (vol->prepath == NULL)
-                                       return 1;
+                                       goto cifs_parse_mount_err;
                                if (value[0] != '/') {
                                        vol->prepath[0] = '/';
                                        strcpy(vol->prepath+1, value);
                                cFYI(1, "prefix path %s", vol->prepath);
                        } else {
                                printk(KERN_WARNING "CIFS: prefix too long\n");
-                               return 1;
+                               goto cifs_parse_mount_err;
                        }
                } else if (strnicmp(data, "iocharset", 9) == 0) {
                        if (!value || !*value) {
                                printk(KERN_WARNING "CIFS: invalid iocharset "
                                                    "specified\n");
-                               return 1;       /* needs_arg; */
+                               goto cifs_parse_mount_err;
                        }
                        if (strnlen(value, 65) < 65) {
-                               if (strnicmp(value, "default", 7))
-                                       vol->iocharset = value;
+                               if (strnicmp(value, "default", 7)) {
+                                       vol->iocharset = kstrdup(value,
+                                                                GFP_KERNEL);
+
+                                       if (!vol->iocharset) {
+                                               printk(KERN_WARNING "CIFS: no "
+                                                                  "memory for"
+                                                                  "charset\n");
+                                               goto cifs_parse_mount_err;
+                                       }
+                               }
                                /* if iocharset not set then load_nls_default
                                   is used by caller */
                                cFYI(1, "iocharset set to %s", value);
                        } else {
                                printk(KERN_WARNING "CIFS: iocharset name "
                                                    "too long.\n");
-                               return 1;
+                               goto cifs_parse_mount_err;
                        }
                } else if (!strnicmp(data, "uid", 3) && value && *value) {
                        vol->linux_uid = simple_strtoul(value, &value, 0);
                                if (vol->actimeo > CIFS_MAX_ACTIMEO) {
                                        cERROR(1, "CIFS: attribute cache"
                                                        "timeout too large");
-                                       return 1;
+                                       goto cifs_parse_mount_err;
                                }
                        }
                } else if (strnicmp(data, "credentials", 4) == 0) {
 #ifndef CONFIG_CIFS_FSCACHE
                        cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE"
                                  "kernel config option set");
-                       return 1;
+                       goto cifs_parse_mount_err;
 #endif
                        vol->fsc = true;
                } else if (strnicmp(data, "mfsymlinks", 10) == 0) {
                if (devname == NULL) {
                        printk(KERN_WARNING "CIFS: Missing UNC name for mount "
                                                "target\n");
-                       return 1;
+                       goto cifs_parse_mount_err;
                }
                if ((temp_len = strnlen(devname, 300)) < 300) {
                        vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
                        if (vol->UNC == NULL)
-                               return 1;
+                               goto cifs_parse_mount_err;
                        strcpy(vol->UNC, devname);
                        if (strncmp(vol->UNC, "//", 2) == 0) {
                                vol->UNC[0] = '\\';
                        } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
                                printk(KERN_WARNING "CIFS: UNC Path does not "
                                                    "begin with // or \\\\ \n");
-                               return 1;
+                               goto cifs_parse_mount_err;
                        }
                        value = strpbrk(vol->UNC+2, "/\\");
                        if (value)
                                *value = '\\';
                } else {
                        printk(KERN_WARNING "CIFS: UNC name too long\n");
-                       return 1;
+                       goto cifs_parse_mount_err;
                }
        }
 
        if (vol->multiuser && !(vol->secFlg & CIFSSEC_MAY_KRB5)) {
                cERROR(1, "Multiuser mounts currently require krb5 "
                          "authentication!");
-               return 1;
+               goto cifs_parse_mount_err;
        }
 
        if (vol->UNCip == NULL)
                printk(KERN_NOTICE "CIFS: ignoring forcegid mount option "
                                   "specified with no gid= option.\n");
 
+       kfree(mountdata_copy);
        return 0;
+
+cifs_parse_mount_err:
+       kfree(mountdata_copy);
+       return 1;
 }
 
 /** Returns true if srcaddr isn't specified and rhs isn't
                return;
 
        volume_info = *pvolume_info;
+       kfree(volume_info->username);
        kzfree(volume_info->password);
        kfree(volume_info->UNC);
+       kfree(volume_info->UNCip);
+       kfree(volume_info->domainname);
+       kfree(volume_info->iocharset);
        kfree(volume_info->prepath);
        kfree(volume_info);
        *pvolume_info = NULL;