diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/super.c | 124 |
1 files changed, 79 insertions, 45 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index b880db18035b..c4ee8b3a27c1 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -1196,6 +1196,67 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args, | |||
1196 | } | 1196 | } |
1197 | 1197 | ||
1198 | /* | 1198 | /* |
1199 | * Split "dev_name" into "hostname:export_path". | ||
1200 | * | ||
1201 | * Note: caller frees hostname and export path, even on error. | ||
1202 | */ | ||
1203 | static int nfs_parse_devname(const char *dev_name, | ||
1204 | char **hostname, size_t maxnamlen, | ||
1205 | char **export_path, size_t maxpathlen) | ||
1206 | { | ||
1207 | size_t len; | ||
1208 | char *colon, *comma; | ||
1209 | |||
1210 | colon = strchr(dev_name, ':'); | ||
1211 | if (colon == NULL) | ||
1212 | goto out_bad_devname; | ||
1213 | |||
1214 | len = colon - dev_name; | ||
1215 | if (len > maxnamlen) | ||
1216 | goto out_hostname; | ||
1217 | |||
1218 | /* N.B. caller will free nfs_server.hostname in all cases */ | ||
1219 | *hostname = kstrndup(dev_name, len, GFP_KERNEL); | ||
1220 | if (!*hostname) | ||
1221 | goto out_nomem; | ||
1222 | |||
1223 | /* kill possible hostname list: not supported */ | ||
1224 | comma = strchr(*hostname, ','); | ||
1225 | if (comma != NULL) { | ||
1226 | if (comma == *hostname) | ||
1227 | goto out_bad_devname; | ||
1228 | *comma = '\0'; | ||
1229 | } | ||
1230 | |||
1231 | colon++; | ||
1232 | len = strlen(colon); | ||
1233 | if (len > maxpathlen) | ||
1234 | goto out_path; | ||
1235 | *export_path = kstrndup(colon, len, GFP_KERNEL); | ||
1236 | if (!*export_path) | ||
1237 | goto out_nomem; | ||
1238 | |||
1239 | dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", *export_path); | ||
1240 | return 0; | ||
1241 | |||
1242 | out_bad_devname: | ||
1243 | dfprintk(MOUNT, "NFS: device name not in host:path format\n"); | ||
1244 | return -EINVAL; | ||
1245 | |||
1246 | out_nomem: | ||
1247 | dfprintk(MOUNT, "NFS: not enough memory to parse device name\n"); | ||
1248 | return -ENOMEM; | ||
1249 | |||
1250 | out_hostname: | ||
1251 | dfprintk(MOUNT, "NFS: server hostname too long\n"); | ||
1252 | return -ENAMETOOLONG; | ||
1253 | |||
1254 | out_path: | ||
1255 | dfprintk(MOUNT, "NFS: export pathname too long\n"); | ||
1256 | return -ENAMETOOLONG; | ||
1257 | } | ||
1258 | |||
1259 | /* | ||
1199 | * Validate the NFS2/NFS3 mount data | 1260 | * Validate the NFS2/NFS3 mount data |
1200 | * - fills in the mount root filehandle | 1261 | * - fills in the mount root filehandle |
1201 | * | 1262 | * |
@@ -1323,8 +1384,6 @@ static int nfs_validate_mount_data(void *options, | |||
1323 | 1384 | ||
1324 | break; | 1385 | break; |
1325 | default: { | 1386 | default: { |
1326 | unsigned int len; | ||
1327 | char *c; | ||
1328 | int status; | 1387 | int status; |
1329 | 1388 | ||
1330 | if (nfs_parse_mount_options((char *)options, args) == 0) | 1389 | if (nfs_parse_mount_options((char *)options, args) == 0) |
@@ -1334,21 +1393,17 @@ static int nfs_validate_mount_data(void *options, | |||
1334 | &args->nfs_server.address)) | 1393 | &args->nfs_server.address)) |
1335 | goto out_no_address; | 1394 | goto out_no_address; |
1336 | 1395 | ||
1337 | c = strchr(dev_name, ':'); | 1396 | status = nfs_parse_devname(dev_name, |
1338 | if (c == NULL) | 1397 | &args->nfs_server.hostname, |
1339 | return -EINVAL; | 1398 | PAGE_SIZE, |
1340 | len = c - dev_name; | 1399 | &args->nfs_server.export_path, |
1341 | /* N.B. caller will free nfs_server.hostname in all cases */ | 1400 | NFS_MAXPATHLEN); |
1342 | args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL); | 1401 | if (!status) |
1343 | if (!args->nfs_server.hostname) | 1402 | status = nfs_try_mount(args, mntfh); |
1344 | goto out_nomem; | ||
1345 | 1403 | ||
1346 | c++; | 1404 | kfree(args->nfs_server.export_path); |
1347 | if (strlen(c) > NFS_MAXPATHLEN) | 1405 | args->nfs_server.export_path = NULL; |
1348 | return -ENAMETOOLONG; | ||
1349 | args->nfs_server.export_path = c; | ||
1350 | 1406 | ||
1351 | status = nfs_try_mount(args, mntfh); | ||
1352 | if (status) | 1407 | if (status) |
1353 | return status; | 1408 | return status; |
1354 | 1409 | ||
@@ -1958,7 +2013,7 @@ static int nfs4_validate_mount_data(void *options, | |||
1958 | 2013 | ||
1959 | break; | 2014 | break; |
1960 | default: { | 2015 | default: { |
1961 | unsigned int len; | 2016 | int status; |
1962 | 2017 | ||
1963 | if (nfs_parse_mount_options((char *)options, args) == 0) | 2018 | if (nfs_parse_mount_options((char *)options, args) == 0) |
1964 | return -EINVAL; | 2019 | return -EINVAL; |
@@ -1977,34 +2032,17 @@ static int nfs4_validate_mount_data(void *options, | |||
1977 | goto out_inval_auth; | 2032 | goto out_inval_auth; |
1978 | } | 2033 | } |
1979 | 2034 | ||
1980 | /* | ||
1981 | * Split "dev_name" into "hostname:mntpath". | ||
1982 | */ | ||
1983 | c = strchr(dev_name, ':'); | ||
1984 | if (c == NULL) | ||
1985 | return -EINVAL; | ||
1986 | /* while calculating len, pretend ':' is '\0' */ | ||
1987 | len = c - dev_name; | ||
1988 | if (len > NFS4_MAXNAMLEN) | ||
1989 | return -ENAMETOOLONG; | ||
1990 | /* N.B. caller will free nfs_server.hostname in all cases */ | ||
1991 | args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL); | ||
1992 | if (!args->nfs_server.hostname) | ||
1993 | goto out_nomem; | ||
1994 | |||
1995 | c++; /* step over the ':' */ | ||
1996 | len = strlen(c); | ||
1997 | if (len > NFS4_MAXPATHLEN) | ||
1998 | return -ENAMETOOLONG; | ||
1999 | args->nfs_server.export_path = kstrndup(c, len, GFP_KERNEL); | ||
2000 | if (!args->nfs_server.export_path) | ||
2001 | goto out_nomem; | ||
2002 | |||
2003 | dprintk("NFS: MNTPATH: '%s'\n", args->nfs_server.export_path); | ||
2004 | |||
2005 | if (args->client_address == NULL) | 2035 | if (args->client_address == NULL) |
2006 | goto out_no_client_address; | 2036 | goto out_no_client_address; |
2007 | 2037 | ||
2038 | status = nfs_parse_devname(dev_name, | ||
2039 | &args->nfs_server.hostname, | ||
2040 | NFS4_MAXNAMLEN, | ||
2041 | &args->nfs_server.export_path, | ||
2042 | NFS4_MAXPATHLEN); | ||
2043 | if (status < 0) | ||
2044 | return status; | ||
2045 | |||
2008 | break; | 2046 | break; |
2009 | } | 2047 | } |
2010 | } | 2048 | } |
@@ -2020,10 +2058,6 @@ out_inval_auth: | |||
2020 | data->auth_flavourlen); | 2058 | data->auth_flavourlen); |
2021 | return -EINVAL; | 2059 | return -EINVAL; |
2022 | 2060 | ||
2023 | out_nomem: | ||
2024 | dfprintk(MOUNT, "NFS4: not enough memory to handle mount options\n"); | ||
2025 | return -ENOMEM; | ||
2026 | |||
2027 | out_no_address: | 2061 | out_no_address: |
2028 | dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n"); | 2062 | dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n"); |
2029 | return -EINVAL; | 2063 | return -EINVAL; |