|
@@ -818,10 +818,11 @@ extract_hostname(const char *unc)
|
|
|
}
|
|
|
|
|
|
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;
|
|
@@ -861,9 +862,14 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|
|
|
|
|
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) {
|
|
@@ -889,17 +895,22 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|
|
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) {
|
|
@@ -963,7 +974,7 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|
|
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];
|
|
@@ -979,7 +990,7 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|
|
if (vol->password == NULL) {
|
|
|
printk(KERN_WARNING "CIFS: no memory "
|
|
|
"for password\n");
|
|
|
- return 1;
|
|
|
+ goto cifs_parse_mount_err;
|
|
|
}
|
|
|
strcpy(vol->password, value);
|
|
|
}
|
|
@@ -989,11 +1000,16 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|
|
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) {
|
|
@@ -1006,7 +1022,7 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|
|
/* 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) {
|
|
@@ -1036,7 +1052,7 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|
|
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) {
|
|
@@ -1060,12 +1076,12 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|
|
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] = '\\';
|
|
@@ -1074,27 +1090,32 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|
|
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;
|
|
@@ -1102,7 +1123,7 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|
|
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));
|
|
@@ -1110,20 +1131,20 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|
|
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);
|
|
@@ -1132,24 +1153,33 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|
|
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);
|
|
@@ -1262,7 +1292,7 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|
|
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) {
|
|
@@ -1406,7 +1436,7 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|
|
#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) {
|
|
@@ -1421,12 +1451,12 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|
|
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] = '\\';
|
|
@@ -1434,21 +1464,21 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|
|
} 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)
|
|
@@ -1466,7 +1496,12 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|
|
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
|
|
@@ -2707,8 +2742,12 @@ cleanup_volume_info(struct smb_vol **pvolume_info)
|
|
|
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;
|