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 /net/ceph | |
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>
Diffstat (limited to 'net/ceph')
-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)); |