From: Ka-Cheong Poon Date: Mon, 12 Feb 2018 16:39:21 +0000 (-0800) Subject: IB/ipoib: ioctls IPOIBACLNADD and IPOIBACLNGET do not work correctly X-Git-Tag: v4.1.12-124.31.3~1132 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=61920a6db770a6e1af7276fc16f306922fe6379c;p=users%2Fjedix%2Flinux-maple.git IB/ipoib: ioctls IPOIBACLNADD and IPOIBACLNGET do not work correctly There is a problem in using the ips pointer in ipoib_do_ioctl(). It does incorrect pointer arithmetic for the new ioctls since ips is an u32 pointer. It should use a struct in6_addr pointer instead of using the ips pointer directly. The end result is that it does not work correctly if a list of ACLs are modified. Orabug: 27533123 Signed-off-by: Ka-Cheong Poon Reviewed-by: Yuval Shaia --- diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ioctl.c b/drivers/infiniband/ulp/ipoib/ipoib_ioctl.c index 9e417b1fb358..c1ac10d8a9a6 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ioctl.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ioctl.c @@ -44,6 +44,7 @@ int ipoib_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ssize_t list_count, i; u64 guid, subnet_prefix; struct in6_addr addr6; + struct in6_addr *ip6s; char uuid[UUID_SZ]; struct ib_cm_acl *acl; char *buf; @@ -117,6 +118,7 @@ int ipoib_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ib_cm_acl_scan(acl, &list, &list_count); + ip6s = (struct in6_addr *)req_data.ips; for (i = req_data.from_idx; (i < list_count) && (i < req_data.sz) ; i++) { /* Need to skip entries with IPv6 address for old @@ -145,9 +147,8 @@ int ipoib_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) * the pointer size to an u32 and in6_addr are * the same. */ - rc |= copy_to_user((struct in6_addr *) - &req_data.ips[i - - req_data.from_idx], + rc |= copy_to_user(ip6s + i - + req_data.from_idx, &list[i].ip, sizeof(list[i].ip)); rc |= copy_to_user((req_data.uuids + i * UUID_SZ), @@ -180,6 +181,7 @@ int ipoib_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) addr6.s6_addr32[2] = htonl(0xFFFF); } + ip6s = (struct in6_addr *)req_data.ips; for (i = 0; i < req_data.sz; i++) { rc = copy_from_user(&subnet_prefix, &req_data.subnet_prefixes[i], @@ -196,8 +198,7 @@ int ipoib_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) * ips should actually be a pointer to a list * of struct in6_addr. */ - rc |= copy_from_user(&addr6, - &req_data.ips[i], + rc |= copy_from_user(&addr6, ip6s + i, sizeof(addr6)); rc |= copy_from_user(&uuid, (req_data.uuids + i * UUID_SZ),