aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/client.c4
-rw-r--r--fs/nfs/internal.h6
-rw-r--r--fs/nfs/super.c54
3 files changed, 40 insertions, 24 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index ba114faf195f..906613362a56 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -581,7 +581,7 @@ static int nfs_init_server(struct nfs_server *server,
581 struct nfs_client_initdata cl_init = { 581 struct nfs_client_initdata cl_init = {
582 .hostname = data->nfs_server.hostname, 582 .hostname = data->nfs_server.hostname,
583 .addr = (const struct sockaddr *)&data->nfs_server.address, 583 .addr = (const struct sockaddr *)&data->nfs_server.address,
584 .addrlen = sizeof(data->nfs_server.address), 584 .addrlen = data->nfs_server.addrlen,
585 .rpc_ops = &nfs_v2_clientops, 585 .rpc_ops = &nfs_v2_clientops,
586 }; 586 };
587 struct nfs_client *clp; 587 struct nfs_client *clp;
@@ -1018,7 +1018,7 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
1018 error = nfs4_set_client(server, 1018 error = nfs4_set_client(server,
1019 data->nfs_server.hostname, 1019 data->nfs_server.hostname,
1020 (struct sockaddr *)&data->nfs_server.address, 1020 (struct sockaddr *)&data->nfs_server.address,
1021 sizeof(data->nfs_server.address), 1021 data->nfs_server.addrlen,
1022 data->client_address, 1022 data->client_address,
1023 data->auth_flavors[0], 1023 data->auth_flavors[0],
1024 data->nfs_server.protocol, 1024 data->nfs_server.protocol,
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 75dd4e252cae..a80621199086 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -42,7 +42,8 @@ struct nfs_parsed_mount_data {
42 char *client_address; 42 char *client_address;
43 43
44 struct { 44 struct {
45 struct sockaddr_in address; 45 struct sockaddr_storage address;
46 size_t addrlen;
46 char *hostname; 47 char *hostname;
47 unsigned int version; 48 unsigned int version;
48 unsigned short port; 49 unsigned short port;
@@ -50,7 +51,8 @@ struct nfs_parsed_mount_data {
50 } mount_server; 51 } mount_server;
51 52
52 struct { 53 struct {
53 struct sockaddr_in address; 54 struct sockaddr_storage address;
55 size_t addrlen;
54 char *hostname; 56 char *hostname;
55 char *export_path; 57 char *export_path;
56 int protocol; 58 int protocol;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 041fe9e9b74d..7efc6a34b56b 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -649,15 +649,18 @@ static int nfs_verify_server_address(struct sockaddr *addr)
649 * to punt the mount. 649 * to punt the mount.
650 */ 650 */
651static void nfs_parse_server_address(char *value, 651static void nfs_parse_server_address(char *value,
652 struct sockaddr *sap) 652 struct sockaddr *sap,
653 size_t *len)
653{ 654{
654 struct sockaddr_in *ap = (void *)sap; 655 struct sockaddr_in *ap = (void *)sap;
655 656
656 ap->sin_family = AF_INET; 657 ap->sin_family = AF_INET;
658 *len = sizeof(*ap);
657 if (in4_pton(value, -1, (u8 *)&ap->sin_addr.s_addr, '\0', NULL)) 659 if (in4_pton(value, -1, (u8 *)&ap->sin_addr.s_addr, '\0', NULL))
658 return; 660 return;
659 661
660 sap->sa_family = AF_UNSPEC; 662 sap->sa_family = AF_UNSPEC;
663 *len = 0;
661} 664}
662 665
663/* 666/*
@@ -984,7 +987,8 @@ static int nfs_parse_mount_options(char *raw,
984 if (string == NULL) 987 if (string == NULL)
985 goto out_nomem; 988 goto out_nomem;
986 nfs_parse_server_address(string, (struct sockaddr *) 989 nfs_parse_server_address(string, (struct sockaddr *)
987 &mnt->nfs_server.address); 990 &mnt->nfs_server.address,
991 &mnt->nfs_server.addrlen);
988 kfree(string); 992 kfree(string);
989 break; 993 break;
990 case Opt_clientaddr: 994 case Opt_clientaddr:
@@ -1004,7 +1008,8 @@ static int nfs_parse_mount_options(char *raw,
1004 if (string == NULL) 1008 if (string == NULL)
1005 goto out_nomem; 1009 goto out_nomem;
1006 nfs_parse_server_address(string, (struct sockaddr *) 1010 nfs_parse_server_address(string, (struct sockaddr *)
1007 &mnt->mount_server.address); 1011 &mnt->mount_server.address,
1012 &mnt->mount_server.addrlen);
1008 kfree(string); 1013 kfree(string);
1009 break; 1014 break;
1010 1015
@@ -1049,9 +1054,9 @@ out_unknown:
1049static int nfs_try_mount(struct nfs_parsed_mount_data *args, 1054static int nfs_try_mount(struct nfs_parsed_mount_data *args,
1050 struct nfs_fh *root_fh) 1055 struct nfs_fh *root_fh)
1051{ 1056{
1052 struct sockaddr_in sin; 1057 struct sockaddr *sap = (struct sockaddr *)&args->mount_server.address;
1053 int status;
1054 char *hostname; 1058 char *hostname;
1059 int status;
1055 1060
1056 if (args->mount_server.version == 0) { 1061 if (args->mount_server.version == 0) {
1057 if (args->flags & NFS_MOUNT_VER3) 1062 if (args->flags & NFS_MOUNT_VER3)
@@ -1068,21 +1073,23 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
1068 /* 1073 /*
1069 * Construct the mount server's address. 1074 * Construct the mount server's address.
1070 */ 1075 */
1071 if (args->mount_server.address.sin_addr.s_addr != INADDR_ANY) 1076 if (args->mount_server.address.ss_family == AF_UNSPEC) {
1072 sin = args->mount_server.address; 1077 memcpy(sap, &args->nfs_server.address,
1073 else 1078 args->nfs_server.addrlen);
1074 sin = args->nfs_server.address; 1079 args->mount_server.addrlen = args->nfs_server.addrlen;
1080 }
1081
1075 /* 1082 /*
1076 * autobind will be used if mount_server.port == 0 1083 * autobind will be used if mount_server.port == 0
1077 */ 1084 */
1078 nfs_set_port((struct sockaddr *)&sin, args->mount_server.port); 1085 nfs_set_port(sap, args->mount_server.port);
1079 1086
1080 /* 1087 /*
1081 * Now ask the mount server to map our export path 1088 * Now ask the mount server to map our export path
1082 * to a file handle. 1089 * to a file handle.
1083 */ 1090 */
1084 status = nfs_mount((struct sockaddr *) &sin, 1091 status = nfs_mount(sap,
1085 sizeof(sin), 1092 args->mount_server.addrlen,
1086 hostname, 1093 hostname,
1087 args->nfs_server.export_path, 1094 args->nfs_server.export_path,
1088 args->mount_server.version, 1095 args->mount_server.version,
@@ -1165,9 +1172,6 @@ static int nfs_validate_mount_data(void *options,
1165 memset(mntfh->data + mntfh->size, 0, 1172 memset(mntfh->data + mntfh->size, 0,
1166 sizeof(mntfh->data) - mntfh->size); 1173 sizeof(mntfh->data) - mntfh->size);
1167 1174
1168 if (!nfs_verify_server_address((struct sockaddr *) &data->addr))
1169 goto out_no_address;
1170
1171 /* 1175 /*
1172 * Translate to nfs_parsed_mount_data, which nfs_fill_super 1176 * Translate to nfs_parsed_mount_data, which nfs_fill_super
1173 * can deal with. 1177 * can deal with.
@@ -1182,7 +1186,14 @@ static int nfs_validate_mount_data(void *options,
1182 args->acregmax = data->acregmax; 1186 args->acregmax = data->acregmax;
1183 args->acdirmin = data->acdirmin; 1187 args->acdirmin = data->acdirmin;
1184 args->acdirmax = data->acdirmax; 1188 args->acdirmax = data->acdirmax;
1185 args->nfs_server.address = data->addr; 1189
1190 memcpy(&args->nfs_server.address, &data->addr,
1191 sizeof(data->addr));
1192 args->nfs_server.addrlen = sizeof(data->addr);
1193 if (!nfs_verify_server_address((struct sockaddr *)
1194 &args->nfs_server.address))
1195 goto out_no_address;
1196
1186 if (!(data->flags & NFS_MOUNT_TCP)) 1197 if (!(data->flags & NFS_MOUNT_TCP))
1187 args->nfs_server.protocol = XPRT_TRANSPORT_UDP; 1198 args->nfs_server.protocol = XPRT_TRANSPORT_UDP;
1188 /* N.B. caller will free nfs_server.hostname in all cases */ 1199 /* N.B. caller will free nfs_server.hostname in all cases */
@@ -1655,6 +1666,7 @@ static int nfs4_validate_mount_data(void *options,
1655 struct nfs_parsed_mount_data *args, 1666 struct nfs_parsed_mount_data *args,
1656 const char *dev_name) 1667 const char *dev_name)
1657{ 1668{
1669 struct sockaddr_in *ap;
1658 struct nfs4_mount_data *data = (struct nfs4_mount_data *)options; 1670 struct nfs4_mount_data *data = (struct nfs4_mount_data *)options;
1659 char *c; 1671 char *c;
1660 1672
@@ -1675,11 +1687,13 @@ static int nfs4_validate_mount_data(void *options,
1675 1687
1676 switch (data->version) { 1688 switch (data->version) {
1677 case 1: 1689 case 1:
1678 if (data->host_addrlen != sizeof(args->nfs_server.address)) 1690 ap = (struct sockaddr_in *)&args->nfs_server.address;
1691 if (data->host_addrlen > sizeof(args->nfs_server.address))
1692 goto out_no_address;
1693 if (data->host_addrlen == 0)
1679 goto out_no_address; 1694 goto out_no_address;
1680 if (copy_from_user(&args->nfs_server.address, 1695 args->nfs_server.addrlen = data->host_addrlen;
1681 data->host_addr, 1696 if (copy_from_user(ap, data->host_addr, data->host_addrlen))
1682 sizeof(args->nfs_server.address)))
1683 return -EFAULT; 1697 return -EFAULT;
1684 if (!nfs_verify_server_address((struct sockaddr *) 1698 if (!nfs_verify_server_address((struct sockaddr *)
1685 &args->nfs_server.address)) 1699 &args->nfs_server.address))