Skip to content

Commit 2991b77

Browse files
sprasad-microsoftsmfrench
authored andcommitted
cifs: fix sockaddr comparison in iface_cmp
iface_cmp used to simply do a memcmp of the two provided struct sockaddrs. The comparison needs to do more based on the address family. Similar logic was already present in cifs_match_ipaddr. Doing something similar now. Signed-off-by: Shyam Prasad N <sprasad@microsoft.com> Reported-by: kernel test robot <lkp@intel.com> Reported-by: Dan Carpenter <error27@gmail.com> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent 50e63d6 commit 2991b77

4 files changed

Lines changed: 88 additions & 37 deletions

File tree

fs/smb/client/cifsglob.h

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -970,43 +970,6 @@ release_iface(struct kref *ref)
970970
kfree(iface);
971971
}
972972

973-
/*
974-
* compare two interfaces a and b
975-
* return 0 if everything matches.
976-
* return 1 if a has higher link speed, or rdma capable, or rss capable
977-
* return -1 otherwise.
978-
*/
979-
static inline int
980-
iface_cmp(struct cifs_server_iface *a, struct cifs_server_iface *b)
981-
{
982-
int cmp_ret = 0;
983-
984-
WARN_ON(!a || !b);
985-
if (a->speed == b->speed) {
986-
if (a->rdma_capable == b->rdma_capable) {
987-
if (a->rss_capable == b->rss_capable) {
988-
cmp_ret = memcmp(&a->sockaddr, &b->sockaddr,
989-
sizeof(a->sockaddr));
990-
if (!cmp_ret)
991-
return 0;
992-
else if (cmp_ret > 0)
993-
return 1;
994-
else
995-
return -1;
996-
} else if (a->rss_capable > b->rss_capable)
997-
return 1;
998-
else
999-
return -1;
1000-
} else if (a->rdma_capable > b->rdma_capable)
1001-
return 1;
1002-
else
1003-
return -1;
1004-
} else if (a->speed > b->speed)
1005-
return 1;
1006-
else
1007-
return -1;
1008-
}
1009-
1010973
struct cifs_chan {
1011974
unsigned int in_reconnect : 1; /* if session setup in progress for this channel */
1012975
struct TCP_Server_Info *server;

fs/smb/client/cifsproto.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ extern int cifs_handle_standard(struct TCP_Server_Info *server,
8787
struct mid_q_entry *mid);
8888
extern int smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx);
8989
extern int smb3_parse_opt(const char *options, const char *key, char **val);
90+
extern int cifs_ipaddr_cmp(struct sockaddr *srcaddr, struct sockaddr *rhs);
9091
extern bool cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs);
9192
extern int cifs_discard_remaining_data(struct TCP_Server_Info *server);
9293
extern int cifs_call_async(struct TCP_Server_Info *server,

fs/smb/client/connect.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,6 +1288,56 @@ cifs_demultiplex_thread(void *p)
12881288
module_put_and_kthread_exit(0);
12891289
}
12901290

1291+
int
1292+
cifs_ipaddr_cmp(struct sockaddr *srcaddr, struct sockaddr *rhs)
1293+
{
1294+
struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
1295+
struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
1296+
struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
1297+
struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
1298+
1299+
switch (srcaddr->sa_family) {
1300+
case AF_UNSPEC:
1301+
switch (rhs->sa_family) {
1302+
case AF_UNSPEC:
1303+
return 0;
1304+
case AF_INET:
1305+
case AF_INET6:
1306+
return 1;
1307+
default:
1308+
return -1;
1309+
}
1310+
case AF_INET: {
1311+
switch (rhs->sa_family) {
1312+
case AF_UNSPEC:
1313+
return -1;
1314+
case AF_INET:
1315+
return memcmp(saddr4, vaddr4,
1316+
sizeof(struct sockaddr_in));
1317+
case AF_INET6:
1318+
return 1;
1319+
default:
1320+
return -1;
1321+
}
1322+
}
1323+
case AF_INET6: {
1324+
switch (rhs->sa_family) {
1325+
case AF_UNSPEC:
1326+
case AF_INET:
1327+
return -1;
1328+
case AF_INET6:
1329+
return memcmp(saddr6,
1330+
vaddr6,
1331+
sizeof(struct sockaddr_in6));
1332+
default:
1333+
return -1;
1334+
}
1335+
}
1336+
default:
1337+
return -1; /* don't expect to be here */
1338+
}
1339+
}
1340+
12911341
/*
12921342
* Returns true if srcaddr isn't specified and rhs isn't specified, or
12931343
* if srcaddr is specified and matches the IP address of the rhs argument

fs/smb/client/smb2ops.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,43 @@ smb3_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
510510
return rsize;
511511
}
512512

513+
/*
514+
* compare two interfaces a and b
515+
* return 0 if everything matches.
516+
* return 1 if a is rdma capable, or rss capable, or has higher link speed
517+
* return -1 otherwise.
518+
*/
519+
static int
520+
iface_cmp(struct cifs_server_iface *a, struct cifs_server_iface *b)
521+
{
522+
int cmp_ret = 0;
523+
524+
WARN_ON(!a || !b);
525+
if (a->rdma_capable == b->rdma_capable) {
526+
if (a->rss_capable == b->rss_capable) {
527+
if (a->speed == b->speed) {
528+
cmp_ret = cifs_ipaddr_cmp((struct sockaddr *) &a->sockaddr,
529+
(struct sockaddr *) &b->sockaddr);
530+
if (!cmp_ret)
531+
return 0;
532+
else if (cmp_ret > 0)
533+
return 1;
534+
else
535+
return -1;
536+
} else if (a->speed > b->speed)
537+
return 1;
538+
else
539+
return -1;
540+
} else if (a->rss_capable > b->rss_capable)
541+
return 1;
542+
else
543+
return -1;
544+
} else if (a->rdma_capable > b->rdma_capable)
545+
return 1;
546+
else
547+
return -1;
548+
}
549+
513550
static int
514551
parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
515552
size_t buf_len, struct cifs_ses *ses, bool in_mount)

0 commit comments

Comments
 (0)