Skip to content

Commit cf0d7e7

Browse files
keesamschuma-ntap
authored andcommitted
NFS: Avoid memcpy() run-time warning for struct sockaddr overflows
The 'nfs_server' and 'mount_server' structures include a union of 'struct sockaddr' (with the older 16 bytes max address size) and 'struct sockaddr_storage' which is large enough to hold all the supported sa_family types (128 bytes max size). The runtime memcpy() buffer overflow checker is seeing attempts to write beyond the 16 bytes as an overflow, but the actual expected size is that of 'struct sockaddr_storage'. Plumb the use of 'struct sockaddr_storage' more completely through-out NFS, which results in adjusting the memcpy() buffers to the correct union members. Avoids this false positive run-time warning under CONFIG_FORTIFY_SOURCE: memcpy: detected field-spanning write (size 28) of single field "&ctx->nfs_server.address" at fs/nfs/namespace.c:178 (size 16) Reported-by: kernel test robot <[email protected]> Link: https://lore.kernel.org/all/[email protected] Cc: Trond Myklebust <[email protected]> Cc: Anna Schumaker <[email protected]> Cc: [email protected] Signed-off-by: Kees Cook <[email protected]> Signed-off-by: Anna Schumaker <[email protected]>
1 parent 121affd commit cf0d7e7

14 files changed

+51
-51
lines changed

fs/nfs/client.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ EXPORT_SYMBOL_GPL(nfs_put_client);
280280
static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *data)
281281
{
282282
struct nfs_client *clp;
283-
const struct sockaddr *sap = data->addr;
283+
const struct sockaddr *sap = (struct sockaddr *)data->addr;
284284
struct nfs_net *nn = net_generic(data->net, nfs_net_id);
285285
int error;
286286

@@ -666,7 +666,7 @@ static int nfs_init_server(struct nfs_server *server,
666666
struct rpc_timeout timeparms;
667667
struct nfs_client_initdata cl_init = {
668668
.hostname = ctx->nfs_server.hostname,
669-
.addr = (const struct sockaddr *)&ctx->nfs_server.address,
669+
.addr = &ctx->nfs_server._address,
670670
.addrlen = ctx->nfs_server.addrlen,
671671
.nfs_mod = ctx->nfs_mod,
672672
.proto = ctx->nfs_server.protocol,

fs/nfs/dns_resolve.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@
1616
#include "dns_resolve.h"
1717

1818
ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen,
19-
struct sockaddr *sa, size_t salen)
19+
struct sockaddr_storage *ss, size_t salen)
2020
{
21+
struct sockaddr *sa = (struct sockaddr *)ss;
2122
ssize_t ret;
2223
char *ip_addr = NULL;
2324
int ip_len;
@@ -341,7 +342,7 @@ static int do_cache_lookup_wait(struct cache_detail *cd,
341342
}
342343

343344
ssize_t nfs_dns_resolve_name(struct net *net, char *name,
344-
size_t namelen, struct sockaddr *sa, size_t salen)
345+
size_t namelen, struct sockaddr_storage *ss, size_t salen)
345346
{
346347
struct nfs_dns_ent key = {
347348
.hostname = name,
@@ -354,7 +355,7 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name,
354355
ret = do_cache_lookup_wait(nn->nfs_dns_resolve, &key, &item);
355356
if (ret == 0) {
356357
if (salen >= item->addrlen) {
357-
memcpy(sa, &item->addr, item->addrlen);
358+
memcpy(ss, &item->addr, item->addrlen);
358359
ret = item->addrlen;
359360
} else
360361
ret = -EOVERFLOW;

fs/nfs/dns_resolve.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@ extern void nfs_dns_resolver_cache_destroy(struct net *net);
3232
#endif
3333

3434
extern ssize_t nfs_dns_resolve_name(struct net *net, char *name,
35-
size_t namelen, struct sockaddr *sa, size_t salen);
35+
size_t namelen, struct sockaddr_storage *sa, size_t salen);
3636

3737
#endif

fs/nfs/fs_context.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,9 @@ static const struct constant_table nfs_secflavor_tokens[] = {
273273
* Address family must be initialized, and address must not be
274274
* the ANY address for that family.
275275
*/
276-
static int nfs_verify_server_address(struct sockaddr *addr)
276+
static int nfs_verify_server_address(struct sockaddr_storage *addr)
277277
{
278-
switch (addr->sa_family) {
278+
switch (addr->ss_family) {
279279
case AF_INET: {
280280
struct sockaddr_in *sa = (struct sockaddr_in *)addr;
281281
return sa->sin_addr.s_addr != htonl(INADDR_ANY);
@@ -969,7 +969,7 @@ static int nfs23_parse_monolithic(struct fs_context *fc,
969969
{
970970
struct nfs_fs_context *ctx = nfs_fc2context(fc);
971971
struct nfs_fh *mntfh = ctx->mntfh;
972-
struct sockaddr *sap = (struct sockaddr *)&ctx->nfs_server.address;
972+
struct sockaddr_storage *sap = &ctx->nfs_server._address;
973973
int extra_flags = NFS_MOUNT_LEGACY_INTERFACE;
974974
int ret;
975975

@@ -1044,7 +1044,7 @@ static int nfs23_parse_monolithic(struct fs_context *fc,
10441044
memcpy(sap, &data->addr, sizeof(data->addr));
10451045
ctx->nfs_server.addrlen = sizeof(data->addr);
10461046
ctx->nfs_server.port = ntohs(data->addr.sin_port);
1047-
if (sap->sa_family != AF_INET ||
1047+
if (sap->ss_family != AF_INET ||
10481048
!nfs_verify_server_address(sap))
10491049
goto out_no_address;
10501050

@@ -1200,7 +1200,7 @@ static int nfs4_parse_monolithic(struct fs_context *fc,
12001200
struct nfs4_mount_data *data)
12011201
{
12021202
struct nfs_fs_context *ctx = nfs_fc2context(fc);
1203-
struct sockaddr *sap = (struct sockaddr *)&ctx->nfs_server.address;
1203+
struct sockaddr_storage *sap = &ctx->nfs_server._address;
12041204
int ret;
12051205
char *c;
12061206

@@ -1314,7 +1314,7 @@ static int nfs_fs_context_validate(struct fs_context *fc)
13141314
{
13151315
struct nfs_fs_context *ctx = nfs_fc2context(fc);
13161316
struct nfs_subversion *nfs_mod;
1317-
struct sockaddr *sap = (struct sockaddr *)&ctx->nfs_server.address;
1317+
struct sockaddr_storage *sap = &ctx->nfs_server._address;
13181318
int max_namelen = PAGE_SIZE;
13191319
int max_pathlen = NFS_MAXPATHLEN;
13201320
int port = 0;
@@ -1540,7 +1540,7 @@ static int nfs_init_fs_context(struct fs_context *fc)
15401540
ctx->version = nfss->nfs_client->rpc_ops->version;
15411541
ctx->minorversion = nfss->nfs_client->cl_minorversion;
15421542

1543-
memcpy(&ctx->nfs_server.address, &nfss->nfs_client->cl_addr,
1543+
memcpy(&ctx->nfs_server._address, &nfss->nfs_client->cl_addr,
15441544
ctx->nfs_server.addrlen);
15451545

15461546
if (fc->net_ns != net) {

fs/nfs/internal.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ static inline fmode_t flags_to_mode(int flags)
6969
struct nfs_client_initdata {
7070
unsigned long init_flags;
7171
const char *hostname; /* Hostname of the server */
72-
const struct sockaddr *addr; /* Address of the server */
72+
const struct sockaddr_storage *addr; /* Address of the server */
7373
const char *nodename; /* Hostname of the client */
7474
const char *ip_addr; /* IP address of the client */
7575
size_t addrlen;
@@ -180,7 +180,7 @@ static inline struct nfs_fs_context *nfs_fc2context(const struct fs_context *fc)
180180

181181
/* mount_clnt.c */
182182
struct nfs_mount_request {
183-
struct sockaddr *sap;
183+
struct sockaddr_storage *sap;
184184
size_t salen;
185185
char *hostname;
186186
char *dirpath;
@@ -223,7 +223,7 @@ extern void nfs4_server_set_init_caps(struct nfs_server *);
223223
extern struct nfs_server *nfs4_create_server(struct fs_context *);
224224
extern struct nfs_server *nfs4_create_referral_server(struct fs_context *);
225225
extern int nfs4_update_server(struct nfs_server *server, const char *hostname,
226-
struct sockaddr *sap, size_t salen,
226+
struct sockaddr_storage *sap, size_t salen,
227227
struct net *net);
228228
extern void nfs_free_server(struct nfs_server *server);
229229
extern struct nfs_server *nfs_clone_server(struct nfs_server *,
@@ -235,15 +235,15 @@ extern int nfs_client_init_status(const struct nfs_client *clp);
235235
extern int nfs_wait_client_init_complete(const struct nfs_client *clp);
236236
extern void nfs_mark_client_ready(struct nfs_client *clp, int state);
237237
extern struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
238-
const struct sockaddr *ds_addr,
238+
const struct sockaddr_storage *ds_addr,
239239
int ds_addrlen, int ds_proto,
240240
unsigned int ds_timeo,
241241
unsigned int ds_retrans,
242242
u32 minor_version);
243243
extern struct rpc_clnt *nfs4_find_or_create_ds_client(struct nfs_client *,
244244
struct inode *);
245245
extern struct nfs_client *nfs3_set_ds_client(struct nfs_server *mds_srv,
246-
const struct sockaddr *ds_addr, int ds_addrlen,
246+
const struct sockaddr_storage *ds_addr, int ds_addrlen,
247247
int ds_proto, unsigned int ds_timeo,
248248
unsigned int ds_retrans);
249249
#ifdef CONFIG_PROC_FS
@@ -894,13 +894,13 @@ static inline bool nfs_error_is_fatal_on_server(int err)
894894
* Select between a default port value and a user-specified port value.
895895
* If a zero value is set, then autobind will be used.
896896
*/
897-
static inline void nfs_set_port(struct sockaddr *sap, int *port,
897+
static inline void nfs_set_port(struct sockaddr_storage *sap, int *port,
898898
const unsigned short default_port)
899899
{
900900
if (*port == NFS_UNSPEC_PORT)
901901
*port = default_port;
902902

903-
rpc_set_port(sap, *port);
903+
rpc_set_port((struct sockaddr *)sap, *port);
904904
}
905905

906906
struct nfs_direct_req {

fs/nfs/mount_clnt.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ int nfs_mount(struct nfs_mount_request *info, int timeo, int retrans)
158158
struct rpc_create_args args = {
159159
.net = info->net,
160160
.protocol = info->protocol,
161-
.address = info->sap,
161+
.address = (struct sockaddr *)info->sap,
162162
.addrsize = info->salen,
163163
.timeout = &mnt_timeout,
164164
.servername = info->hostname,
@@ -245,7 +245,7 @@ void nfs_umount(const struct nfs_mount_request *info)
245245
struct rpc_create_args args = {
246246
.net = info->net,
247247
.protocol = IPPROTO_UDP,
248-
.address = info->sap,
248+
.address = (struct sockaddr *)info->sap,
249249
.addrsize = info->salen,
250250
.timeout = &nfs_umnt_timeout,
251251
.servername = info->hostname,

fs/nfs/namespace.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ struct vfsmount *nfs_d_automount(struct path *path)
175175
}
176176

177177
/* for submounts we want the same server; referrals will reassign */
178-
memcpy(&ctx->nfs_server.address, &client->cl_addr, client->cl_addrlen);
178+
memcpy(&ctx->nfs_server._address, &client->cl_addr, client->cl_addrlen);
179179
ctx->nfs_server.addrlen = client->cl_addrlen;
180180
ctx->nfs_server.port = server->port;
181181

fs/nfs/nfs3client.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ struct nfs_server *nfs3_clone_server(struct nfs_server *source,
7878
* the MDS.
7979
*/
8080
struct nfs_client *nfs3_set_ds_client(struct nfs_server *mds_srv,
81-
const struct sockaddr *ds_addr, int ds_addrlen,
81+
const struct sockaddr_storage *ds_addr, int ds_addrlen,
8282
int ds_proto, unsigned int ds_timeo, unsigned int ds_retrans)
8383
{
8484
struct rpc_timeout ds_timeout;
@@ -98,7 +98,7 @@ struct nfs_client *nfs3_set_ds_client(struct nfs_server *mds_srv,
9898
char buf[INET6_ADDRSTRLEN + 1];
9999

100100
/* fake a hostname because lockd wants it */
101-
if (rpc_ntop(ds_addr, buf, sizeof(buf)) <= 0)
101+
if (rpc_ntop((struct sockaddr *)ds_addr, buf, sizeof(buf)) <= 0)
102102
return ERR_PTR(-EINVAL);
103103
cl_init.hostname = buf;
104104

fs/nfs/nfs4_fs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ struct rpc_clnt *nfs4_negotiate_security(struct rpc_clnt *, struct inode *,
281281
int nfs4_submount(struct fs_context *, struct nfs_server *);
282282
int nfs4_replace_transport(struct nfs_server *server,
283283
const struct nfs4_fs_locations *locations);
284-
size_t nfs_parse_server_name(char *string, size_t len, struct sockaddr *sa,
284+
size_t nfs_parse_server_name(char *string, size_t len, struct sockaddr_storage *ss,
285285
size_t salen, struct net *net, int port);
286286
/* nfs4proc.c */
287287
extern int nfs4_handle_exception(struct nfs_server *, int, struct nfs4_exception *);

fs/nfs/nfs4client.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,7 @@ nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
889889
*/
890890
static int nfs4_set_client(struct nfs_server *server,
891891
const char *hostname,
892-
const struct sockaddr *addr,
892+
const struct sockaddr_storage *addr,
893893
const size_t addrlen,
894894
const char *ip_addr,
895895
int proto, const struct rpc_timeout *timeparms,
@@ -924,7 +924,7 @@ static int nfs4_set_client(struct nfs_server *server,
924924
__set_bit(NFS_CS_MIGRATION, &cl_init.init_flags);
925925
if (test_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status))
926926
__set_bit(NFS_CS_TSM_POSSIBLE, &cl_init.init_flags);
927-
server->port = rpc_get_port(addr);
927+
server->port = rpc_get_port((struct sockaddr *)addr);
928928

929929
/* Allocate or find a client reference we can use */
930930
clp = nfs_get_client(&cl_init);
@@ -960,7 +960,7 @@ static int nfs4_set_client(struct nfs_server *server,
960960
* the MDS.
961961
*/
962962
struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
963-
const struct sockaddr *ds_addr, int ds_addrlen,
963+
const struct sockaddr_storage *ds_addr, int ds_addrlen,
964964
int ds_proto, unsigned int ds_timeo, unsigned int ds_retrans,
965965
u32 minor_version)
966966
{
@@ -980,7 +980,7 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
980980
};
981981
char buf[INET6_ADDRSTRLEN + 1];
982982

983-
if (rpc_ntop(ds_addr, buf, sizeof(buf)) <= 0)
983+
if (rpc_ntop((struct sockaddr *)ds_addr, buf, sizeof(buf)) <= 0)
984984
return ERR_PTR(-EINVAL);
985985
cl_init.hostname = buf;
986986

@@ -1148,7 +1148,7 @@ static int nfs4_init_server(struct nfs_server *server, struct fs_context *fc)
11481148
/* Get a client record */
11491149
error = nfs4_set_client(server,
11501150
ctx->nfs_server.hostname,
1151-
&ctx->nfs_server.address,
1151+
&ctx->nfs_server._address,
11521152
ctx->nfs_server.addrlen,
11531153
ctx->client_address,
11541154
ctx->nfs_server.protocol,
@@ -1238,7 +1238,7 @@ struct nfs_server *nfs4_create_referral_server(struct fs_context *fc)
12381238
rpc_set_port(&ctx->nfs_server.address, NFS_RDMA_PORT);
12391239
error = nfs4_set_client(server,
12401240
ctx->nfs_server.hostname,
1241-
&ctx->nfs_server.address,
1241+
&ctx->nfs_server._address,
12421242
ctx->nfs_server.addrlen,
12431243
parent_client->cl_ipaddr,
12441244
XPRT_TRANSPORT_RDMA,
@@ -1254,7 +1254,7 @@ struct nfs_server *nfs4_create_referral_server(struct fs_context *fc)
12541254
rpc_set_port(&ctx->nfs_server.address, NFS_PORT);
12551255
error = nfs4_set_client(server,
12561256
ctx->nfs_server.hostname,
1257-
&ctx->nfs_server.address,
1257+
&ctx->nfs_server._address,
12581258
ctx->nfs_server.addrlen,
12591259
parent_client->cl_ipaddr,
12601260
XPRT_TRANSPORT_TCP,
@@ -1303,14 +1303,14 @@ struct nfs_server *nfs4_create_referral_server(struct fs_context *fc)
13031303
* Returns zero on success, or a negative errno value.
13041304
*/
13051305
int nfs4_update_server(struct nfs_server *server, const char *hostname,
1306-
struct sockaddr *sap, size_t salen, struct net *net)
1306+
struct sockaddr_storage *sap, size_t salen, struct net *net)
13071307
{
13081308
struct nfs_client *clp = server->nfs_client;
13091309
struct rpc_clnt *clnt = server->client;
13101310
struct xprt_create xargs = {
13111311
.ident = clp->cl_proto,
13121312
.net = net,
1313-
.dstaddr = sap,
1313+
.dstaddr = (struct sockaddr *)sap,
13141314
.addrlen = salen,
13151315
.servername = hostname,
13161316
};

0 commit comments

Comments
 (0)