diff options
| author | Chuck Lever <chuck.lever@oracle.com> | 2008-10-03 12:50:44 -0400 |
|---|---|---|
| committer | J. Bruce Fields <bfields@citi.umich.edu> | 2008-10-03 17:02:35 -0400 |
| commit | b85e4676344fc4d7ec5e0f62c3d3712e48bbe223 (patch) | |
| tree | a2a6c0226ea0f72536477dff2e123245a3621d9d /include/linux | |
| parent | dcff09f124f71d1d4fe61eb63c79e52f488ac22e (diff) | |
lockd: Add helper to sanity check incoming NOTIFY requests
lockd accepts SM_NOTIFY calls only from a privileged process on the
local system. If lockd uses an AF_INET6 listener, the sender's address
(ie the local rpc.statd) will be the IPv6 loopback address, not the
IPv4 loopback address.
Make sure the privilege test in nlmsvc_proc_sm_notify() and
nlm4svc_proc_sm_notify() works for both AF_INET and AF_INET6 family
addresses by refactoring the test into a helper and adding support for
IPv6 addresses.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/lockd/lockd.h | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index e6b070979287..b56d5aa9b194 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h | |||
| @@ -277,6 +277,47 @@ static inline struct inode *nlmsvc_file_inode(struct nlm_file *file) | |||
| 277 | return file->f_file->f_path.dentry->d_inode; | 277 | return file->f_file->f_path.dentry->d_inode; |
| 278 | } | 278 | } |
| 279 | 279 | ||
| 280 | static inline int __nlm_privileged_request4(const struct sockaddr *sap) | ||
| 281 | { | ||
| 282 | const struct sockaddr_in *sin = (struct sockaddr_in *)sap; | ||
| 283 | return (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) && | ||
| 284 | (ntohs(sin->sin_port) < 1024); | ||
| 285 | } | ||
| 286 | |||
| 287 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 288 | static inline int __nlm_privileged_request6(const struct sockaddr *sap) | ||
| 289 | { | ||
| 290 | const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; | ||
| 291 | return (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LOOPBACK) && | ||
| 292 | (ntohs(sin6->sin6_port) < 1024); | ||
| 293 | } | ||
| 294 | #else /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ | ||
| 295 | static inline int __nlm_privileged_request6(const struct sockaddr *sap) | ||
| 296 | { | ||
| 297 | return 0; | ||
| 298 | } | ||
| 299 | #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ | ||
| 300 | |||
| 301 | /* | ||
| 302 | * Ensure incoming requests are from local privileged callers. | ||
| 303 | * | ||
| 304 | * Return TRUE if sender is local and is connecting via a privileged port; | ||
| 305 | * otherwise return FALSE. | ||
| 306 | */ | ||
| 307 | static inline int nlm_privileged_requester(const struct svc_rqst *rqstp) | ||
| 308 | { | ||
| 309 | const struct sockaddr *sap = svc_addr(rqstp); | ||
| 310 | |||
| 311 | switch (sap->sa_family) { | ||
| 312 | case AF_INET: | ||
| 313 | return __nlm_privileged_request4(sap); | ||
| 314 | case AF_INET6: | ||
| 315 | return __nlm_privileged_request6(sap); | ||
| 316 | default: | ||
| 317 | return 0; | ||
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 280 | static inline int __nlm_cmp_addr4(const struct sockaddr *sap1, | 321 | static inline int __nlm_cmp_addr4(const struct sockaddr *sap1, |
| 281 | const struct sockaddr *sap2) | 322 | const struct sockaddr *sap2) |
| 282 | { | 323 | { |
