diff options
| author | Jeff Layton <jlayton@kernel.org> | 2019-05-06 09:38:46 -0400 |
|---|---|---|
| committer | Ilya Dryomov <idryomov@gmail.com> | 2019-05-07 13:43:05 -0400 |
| commit | cede185b1ba3118e1912385db4812a37d9e9b205 (patch) | |
| tree | f5a68565273af192c4029845b087afd38c744b63 | |
| parent | b91a7bdca4439e286f26cdd6c15ed338e6a9fda2 (diff) | |
libceph: fix unaligned accesses in ceph_entity_addr handling
GCC9 is throwing a lot of warnings about unaligned access. This patch
fixes some of them by changing most of the sockaddr handling functions
to take a pointer to struct ceph_entity_addr instead of struct
sockaddr_storage. The lower functions can then make copies or do
unaligned accesses as needed.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
| -rw-r--r-- | net/ceph/messenger.c | 77 |
1 files changed, 37 insertions, 40 deletions
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 3083988ce729..3e0cc9808ae4 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
| @@ -449,7 +449,7 @@ static void set_sock_callbacks(struct socket *sock, | |||
| 449 | */ | 449 | */ |
| 450 | static int ceph_tcp_connect(struct ceph_connection *con) | 450 | static int ceph_tcp_connect(struct ceph_connection *con) |
| 451 | { | 451 | { |
| 452 | struct sockaddr_storage *paddr = &con->peer_addr.in_addr; | 452 | struct sockaddr_storage ss = con->peer_addr.in_addr; /* align */ |
| 453 | struct socket *sock; | 453 | struct socket *sock; |
| 454 | unsigned int noio_flag; | 454 | unsigned int noio_flag; |
| 455 | int ret; | 455 | int ret; |
| @@ -458,7 +458,7 @@ static int ceph_tcp_connect(struct ceph_connection *con) | |||
| 458 | 458 | ||
| 459 | /* sock_create_kern() allocates with GFP_KERNEL */ | 459 | /* sock_create_kern() allocates with GFP_KERNEL */ |
| 460 | noio_flag = memalloc_noio_save(); | 460 | noio_flag = memalloc_noio_save(); |
| 461 | ret = sock_create_kern(read_pnet(&con->msgr->net), paddr->ss_family, | 461 | ret = sock_create_kern(read_pnet(&con->msgr->net), ss.ss_family, |
| 462 | SOCK_STREAM, IPPROTO_TCP, &sock); | 462 | SOCK_STREAM, IPPROTO_TCP, &sock); |
| 463 | memalloc_noio_restore(noio_flag); | 463 | memalloc_noio_restore(noio_flag); |
| 464 | if (ret) | 464 | if (ret) |
| @@ -474,7 +474,7 @@ static int ceph_tcp_connect(struct ceph_connection *con) | |||
| 474 | dout("connect %s\n", ceph_pr_addr(&con->peer_addr.in_addr)); | 474 | dout("connect %s\n", ceph_pr_addr(&con->peer_addr.in_addr)); |
| 475 | 475 | ||
| 476 | con_sock_state_connecting(con); | 476 | con_sock_state_connecting(con); |
| 477 | ret = sock->ops->connect(sock, (struct sockaddr *)paddr, sizeof(*paddr), | 477 | ret = sock->ops->connect(sock, (struct sockaddr *)&ss, sizeof(ss), |
| 478 | O_NONBLOCK); | 478 | O_NONBLOCK); |
| 479 | if (ret == -EINPROGRESS) { | 479 | if (ret == -EINPROGRESS) { |
| 480 | dout("connect %s EINPROGRESS sk_state = %u\n", | 480 | dout("connect %s EINPROGRESS sk_state = %u\n", |
| @@ -1795,14 +1795,15 @@ static int verify_hello(struct ceph_connection *con) | |||
| 1795 | return 0; | 1795 | return 0; |
| 1796 | } | 1796 | } |
| 1797 | 1797 | ||
| 1798 | static bool addr_is_blank(struct sockaddr_storage *ss) | 1798 | static bool addr_is_blank(struct ceph_entity_addr *addr) |
| 1799 | { | 1799 | { |
| 1800 | struct in_addr *addr = &((struct sockaddr_in *)ss)->sin_addr; | 1800 | struct sockaddr_storage ss = addr->in_addr; /* align */ |
| 1801 | struct in6_addr *addr6 = &((struct sockaddr_in6 *)ss)->sin6_addr; | 1801 | struct in_addr *addr4 = &((struct sockaddr_in *)&ss)->sin_addr; |
| 1802 | struct in6_addr *addr6 = &((struct sockaddr_in6 *)&ss)->sin6_addr; | ||
| 1802 | 1803 | ||
| 1803 | switch (ss->ss_family) { | 1804 | switch (ss.ss_family) { |
| 1804 | case AF_INET: | 1805 | case AF_INET: |
| 1805 | return addr->s_addr == htonl(INADDR_ANY); | 1806 | return addr4->s_addr == htonl(INADDR_ANY); |
| 1806 | case AF_INET6: | 1807 | case AF_INET6: |
| 1807 | return ipv6_addr_any(addr6); | 1808 | return ipv6_addr_any(addr6); |
| 1808 | default: | 1809 | default: |
| @@ -1810,25 +1811,25 @@ static bool addr_is_blank(struct sockaddr_storage *ss) | |||
| 1810 | } | 1811 | } |
| 1811 | } | 1812 | } |
| 1812 | 1813 | ||
| 1813 | static int addr_port(struct sockaddr_storage *ss) | 1814 | static int addr_port(struct ceph_entity_addr *addr) |
| 1814 | { | 1815 | { |
| 1815 | switch (ss->ss_family) { | 1816 | switch (get_unaligned(&addr->in_addr.ss_family)) { |
| 1816 | case AF_INET: | 1817 | case AF_INET: |
| 1817 | return ntohs(((struct sockaddr_in *)ss)->sin_port); | 1818 | return ntohs(get_unaligned(&((struct sockaddr_in *)&addr->in_addr)->sin_port)); |
| 1818 | case AF_INET6: | 1819 | case AF_INET6: |
| 1819 | return ntohs(((struct sockaddr_in6 *)ss)->sin6_port); | 1820 | return ntohs(get_unaligned(&((struct sockaddr_in6 *)&addr->in_addr)->sin6_port)); |
| 1820 | } | 1821 | } |
| 1821 | return 0; | 1822 | return 0; |
| 1822 | } | 1823 | } |
| 1823 | 1824 | ||
| 1824 | static void addr_set_port(struct sockaddr_storage *ss, int p) | 1825 | static void addr_set_port(struct ceph_entity_addr *addr, int p) |
| 1825 | { | 1826 | { |
| 1826 | switch (ss->ss_family) { | 1827 | switch (get_unaligned(&addr->in_addr.ss_family)) { |
| 1827 | case AF_INET: | 1828 | case AF_INET: |
| 1828 | ((struct sockaddr_in *)ss)->sin_port = htons(p); | 1829 | put_unaligned(htons(p), &((struct sockaddr_in *)&addr->in_addr)->sin_port); |
| 1829 | break; | 1830 | break; |
| 1830 | case AF_INET6: | 1831 | case AF_INET6: |
| 1831 | ((struct sockaddr_in6 *)ss)->sin6_port = htons(p); | 1832 | put_unaligned(htons(p), &((struct sockaddr_in6 *)&addr->in_addr)->sin6_port); |
| 1832 | break; | 1833 | break; |
| 1833 | } | 1834 | } |
| 1834 | } | 1835 | } |
| @@ -1836,21 +1837,18 @@ static void addr_set_port(struct sockaddr_storage *ss, int p) | |||
| 1836 | /* | 1837 | /* |
| 1837 | * Unlike other *_pton function semantics, zero indicates success. | 1838 | * Unlike other *_pton function semantics, zero indicates success. |
| 1838 | */ | 1839 | */ |
| 1839 | static int ceph_pton(const char *str, size_t len, struct sockaddr_storage *ss, | 1840 | static int ceph_pton(const char *str, size_t len, struct ceph_entity_addr *addr, |
| 1840 | char delim, const char **ipend) | 1841 | char delim, const char **ipend) |
| 1841 | { | 1842 | { |
| 1842 | struct sockaddr_in *in4 = (struct sockaddr_in *) ss; | 1843 | memset(&addr->in_addr, 0, sizeof(addr->in_addr)); |
| 1843 | struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) ss; | ||
| 1844 | |||
| 1845 | memset(ss, 0, sizeof(*ss)); | ||
| 1846 | 1844 | ||
| 1847 | if (in4_pton(str, len, (u8 *)&in4->sin_addr.s_addr, delim, ipend)) { | 1845 | if (in4_pton(str, len, (u8 *)&((struct sockaddr_in *)&addr->in_addr)->sin_addr.s_addr, delim, ipend)) { |
| 1848 | ss->ss_family = AF_INET; | 1846 | put_unaligned(AF_INET, &addr->in_addr.ss_family); |
| 1849 | return 0; | 1847 | return 0; |
| 1850 | } | 1848 | } |
| 1851 | 1849 | ||
| 1852 | if (in6_pton(str, len, (u8 *)&in6->sin6_addr.s6_addr, delim, ipend)) { | 1850 | if (in6_pton(str, len, (u8 *)&((struct sockaddr_in6 *)&addr->in_addr)->sin6_addr.s6_addr, delim, ipend)) { |
| 1853 | ss->ss_family = AF_INET6; | 1851 | put_unaligned(AF_INET6, &addr->in_addr.ss_family); |
| 1854 | return 0; | 1852 | return 0; |
| 1855 | } | 1853 | } |
| 1856 | 1854 | ||
| @@ -1862,7 +1860,7 @@ static int ceph_pton(const char *str, size_t len, struct sockaddr_storage *ss, | |||
| 1862 | */ | 1860 | */ |
| 1863 | #ifdef CONFIG_CEPH_LIB_USE_DNS_RESOLVER | 1861 | #ifdef CONFIG_CEPH_LIB_USE_DNS_RESOLVER |
| 1864 | static int ceph_dns_resolve_name(const char *name, size_t namelen, | 1862 | static int ceph_dns_resolve_name(const char *name, size_t namelen, |
| 1865 | struct sockaddr_storage *ss, char delim, const char **ipend) | 1863 | struct ceph_entity_addr *addr, char delim, const char **ipend) |
| 1866 | { | 1864 | { |
| 1867 | const char *end, *delim_p; | 1865 | const char *end, *delim_p; |
| 1868 | char *colon_p, *ip_addr = NULL; | 1866 | char *colon_p, *ip_addr = NULL; |
| @@ -1891,7 +1889,7 @@ static int ceph_dns_resolve_name(const char *name, size_t namelen, | |||
| 1891 | /* do dns_resolve upcall */ | 1889 | /* do dns_resolve upcall */ |
| 1892 | ip_len = dns_query(NULL, name, end - name, NULL, &ip_addr, NULL); | 1890 | ip_len = dns_query(NULL, name, end - name, NULL, &ip_addr, NULL); |
| 1893 | if (ip_len > 0) | 1891 | if (ip_len > 0) |
| 1894 | ret = ceph_pton(ip_addr, ip_len, ss, -1, NULL); | 1892 | ret = ceph_pton(ip_addr, ip_len, addr, -1, NULL); |
| 1895 | else | 1893 | else |
| 1896 | ret = -ESRCH; | 1894 | ret = -ESRCH; |
| 1897 | 1895 | ||
| @@ -1900,13 +1898,13 @@ static int ceph_dns_resolve_name(const char *name, size_t namelen, | |||
| 1900 | *ipend = end; | 1898 | *ipend = end; |
| 1901 | 1899 | ||
| 1902 | pr_info("resolve '%.*s' (ret=%d): %s\n", (int)(end - name), name, | 1900 | pr_info("resolve '%.*s' (ret=%d): %s\n", (int)(end - name), name, |
| 1903 | ret, ret ? "failed" : ceph_pr_addr(ss)); | 1901 | ret, ret ? "failed" : ceph_pr_addr(&addr->in_addr)); |
| 1904 | 1902 | ||
| 1905 | return ret; | 1903 | return ret; |
| 1906 | } | 1904 | } |
| 1907 | #else | 1905 | #else |
| 1908 | static inline int ceph_dns_resolve_name(const char *name, size_t namelen, | 1906 | static inline int ceph_dns_resolve_name(const char *name, size_t namelen, |
| 1909 | struct sockaddr_storage *ss, char delim, const char **ipend) | 1907 | struct ceph_entity_addr *addr, char delim, const char **ipend) |
| 1910 | { | 1908 | { |
| 1911 | return -EINVAL; | 1909 | return -EINVAL; |
| 1912 | } | 1910 | } |
| @@ -1917,13 +1915,13 @@ static inline int ceph_dns_resolve_name(const char *name, size_t namelen, | |||
| 1917 | * then try to extract a hostname to resolve using userspace DNS upcall. | 1915 | * then try to extract a hostname to resolve using userspace DNS upcall. |
| 1918 | */ | 1916 | */ |
| 1919 | static int ceph_parse_server_name(const char *name, size_t namelen, | 1917 | static int ceph_parse_server_name(const char *name, size_t namelen, |
| 1920 | struct sockaddr_storage *ss, char delim, const char **ipend) | 1918 | struct ceph_entity_addr *addr, char delim, const char **ipend) |
| 1921 | { | 1919 | { |
| 1922 | int ret; | 1920 | int ret; |
| 1923 | 1921 | ||
| 1924 | ret = ceph_pton(name, namelen, ss, delim, ipend); | 1922 | ret = ceph_pton(name, namelen, addr, delim, ipend); |
| 1925 | if (ret) | 1923 | if (ret) |
| 1926 | ret = ceph_dns_resolve_name(name, namelen, ss, delim, ipend); | 1924 | ret = ceph_dns_resolve_name(name, namelen, addr, delim, ipend); |
| 1927 | 1925 | ||
| 1928 | return ret; | 1926 | return ret; |
| 1929 | } | 1927 | } |
| @@ -1942,7 +1940,6 @@ int ceph_parse_ips(const char *c, const char *end, | |||
| 1942 | dout("parse_ips on '%.*s'\n", (int)(end-c), c); | 1940 | dout("parse_ips on '%.*s'\n", (int)(end-c), c); |
| 1943 | for (i = 0; i < max_count; i++) { | 1941 | for (i = 0; i < max_count; i++) { |
| 1944 | const char *ipend; | 1942 | const char *ipend; |
| 1945 | struct sockaddr_storage *ss = &addr[i].in_addr; | ||
| 1946 | int port; | 1943 | int port; |
| 1947 | char delim = ','; | 1944 | char delim = ','; |
| 1948 | 1945 | ||
| @@ -1951,7 +1948,7 @@ int ceph_parse_ips(const char *c, const char *end, | |||
| 1951 | p++; | 1948 | p++; |
| 1952 | } | 1949 | } |
| 1953 | 1950 | ||
| 1954 | ret = ceph_parse_server_name(p, end - p, ss, delim, &ipend); | 1951 | ret = ceph_parse_server_name(p, end - p, &addr[i], delim, &ipend); |
| 1955 | if (ret) | 1952 | if (ret) |
| 1956 | goto bad; | 1953 | goto bad; |
| 1957 | ret = -EINVAL; | 1954 | ret = -EINVAL; |
| @@ -1982,9 +1979,9 @@ int ceph_parse_ips(const char *c, const char *end, | |||
| 1982 | port = CEPH_MON_PORT; | 1979 | port = CEPH_MON_PORT; |
| 1983 | } | 1980 | } |
| 1984 | 1981 | ||
| 1985 | addr_set_port(ss, port); | 1982 | addr_set_port(&addr[i], port); |
| 1986 | 1983 | ||
| 1987 | dout("parse_ips got %s\n", ceph_pr_addr(ss)); | 1984 | dout("parse_ips got %s\n", ceph_pr_addr(&addr[i].in_addr)); |
| 1988 | 1985 | ||
| 1989 | if (p == end) | 1986 | if (p == end) |
| 1990 | break; | 1987 | break; |
| @@ -2023,7 +2020,7 @@ static int process_banner(struct ceph_connection *con) | |||
| 2023 | */ | 2020 | */ |
| 2024 | if (memcmp(&con->peer_addr, &con->actual_peer_addr, | 2021 | if (memcmp(&con->peer_addr, &con->actual_peer_addr, |
| 2025 | sizeof(con->peer_addr)) != 0 && | 2022 | sizeof(con->peer_addr)) != 0 && |
| 2026 | !(addr_is_blank(&con->actual_peer_addr.in_addr) && | 2023 | !(addr_is_blank(&con->actual_peer_addr) && |
| 2027 | con->actual_peer_addr.nonce == con->peer_addr.nonce)) { | 2024 | con->actual_peer_addr.nonce == con->peer_addr.nonce)) { |
| 2028 | pr_warn("wrong peer, want %s/%d, got %s/%d\n", | 2025 | pr_warn("wrong peer, want %s/%d, got %s/%d\n", |
| 2029 | ceph_pr_addr(&con->peer_addr.in_addr), | 2026 | ceph_pr_addr(&con->peer_addr.in_addr), |
| @@ -2037,13 +2034,13 @@ static int process_banner(struct ceph_connection *con) | |||
| 2037 | /* | 2034 | /* |
| 2038 | * did we learn our address? | 2035 | * did we learn our address? |
| 2039 | */ | 2036 | */ |
| 2040 | if (addr_is_blank(&con->msgr->inst.addr.in_addr)) { | 2037 | if (addr_is_blank(&con->msgr->inst.addr)) { |
| 2041 | int port = addr_port(&con->msgr->inst.addr.in_addr); | 2038 | int port = addr_port(&con->msgr->inst.addr); |
| 2042 | 2039 | ||
| 2043 | memcpy(&con->msgr->inst.addr.in_addr, | 2040 | memcpy(&con->msgr->inst.addr.in_addr, |
| 2044 | &con->peer_addr_for_me.in_addr, | 2041 | &con->peer_addr_for_me.in_addr, |
| 2045 | sizeof(con->peer_addr_for_me.in_addr)); | 2042 | sizeof(con->peer_addr_for_me.in_addr)); |
| 2046 | addr_set_port(&con->msgr->inst.addr.in_addr, port); | 2043 | addr_set_port(&con->msgr->inst.addr, port); |
| 2047 | encode_my_addr(con->msgr); | 2044 | encode_my_addr(con->msgr); |
| 2048 | dout("process_banner learned my addr is %s\n", | 2045 | dout("process_banner learned my addr is %s\n", |
| 2049 | ceph_pr_addr(&con->msgr->inst.addr.in_addr)); | 2046 | ceph_pr_addr(&con->msgr->inst.addr.in_addr)); |
