diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2008-12-11 17:56:44 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2009-01-06 11:53:56 -0500 |
commit | d1208f70738c91f13b4eadb1b7a694082e439da2 (patch) | |
tree | 756e10b06467f9a9fd52f977a886b736def6f9f0 | |
parent | 49b5699b3fc22b363534c509c1b7dba06bc677bf (diff) |
NLM: nlm_privileged_requester() doesn't recognize mapped loopback address
Commit b85e4676 added the nlm_privileged_requester() helper to check
whether an RPC request was sent from a local privileged caller. It
recognizes IPv4 privileged callers (from "127.0.0.1"), and IPv6
privileged callers (from "::1").
However, IPV6_ADDR_LOOPBACK is not set for the mapped IPv4 loopback
address (::ffff:7f00:0001), so the test breaks when the kernel's RPC
service is IPv6-enabled but user space is calling via the IPv4
loopback address. This is actually the most common case for IPv6-
enabled RPC services on Linux.
Rewrite the IPv6 check to handle the mapped IPv4 loopback address as
well as a normal IPv6 loopback address.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-rw-r--r-- | include/linux/lockd/lockd.h | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index 6ab0449bc828..80d7e8a8257d 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h | |||
@@ -299,8 +299,14 @@ static inline int __nlm_privileged_request4(const struct sockaddr *sap) | |||
299 | static inline int __nlm_privileged_request6(const struct sockaddr *sap) | 299 | static inline int __nlm_privileged_request6(const struct sockaddr *sap) |
300 | { | 300 | { |
301 | const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; | 301 | const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; |
302 | return (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LOOPBACK) && | 302 | |
303 | (ntohs(sin6->sin6_port) < 1024); | 303 | if (ntohs(sin6->sin6_port) > 1023) |
304 | return 0; | ||
305 | |||
306 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED) | ||
307 | return ipv4_is_loopback(sin6->sin6_addr.s6_addr32[3]); | ||
308 | |||
309 | return ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LOOPBACK; | ||
304 | } | 310 | } |
305 | #else /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ | 311 | #else /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ |
306 | static inline int __nlm_privileged_request6(const struct sockaddr *sap) | 312 | static inline int __nlm_privileged_request6(const struct sockaddr *sap) |