Skip to content

Commit

Permalink
lockd: Add helper to sanity check incoming NOTIFY requests
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Chuck Lever authored and J. Bruce Fields committed Oct 3, 2008
1 parent dcff09f commit b85e467
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 8 deletions.
6 changes: 2 additions & 4 deletions fs/lockd/svc4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,11 +421,9 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
{
struct sockaddr_in saddr;

memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr));

dprintk("lockd: SM_NOTIFY called\n");
if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
|| ntohs(saddr.sin_port) >= 1024) {

if (!nlm_privileged_requester(rqstp)) {
char buf[RPC_MAX_ADDRBUFLEN];
printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
svc_print_addr(rqstp, buf, sizeof(buf)));
Expand Down
6 changes: 2 additions & 4 deletions fs/lockd/svcproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,11 +453,9 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
{
struct sockaddr_in saddr;

memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr));

dprintk("lockd: SM_NOTIFY called\n");
if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
|| ntohs(saddr.sin_port) >= 1024) {

if (!nlm_privileged_requester(rqstp)) {
char buf[RPC_MAX_ADDRBUFLEN];
printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
svc_print_addr(rqstp, buf, sizeof(buf)));
Expand Down
41 changes: 41 additions & 0 deletions include/linux/lockd/lockd.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,47 @@ static inline struct inode *nlmsvc_file_inode(struct nlm_file *file)
return file->f_file->f_path.dentry->d_inode;
}

static inline int __nlm_privileged_request4(const struct sockaddr *sap)
{
const struct sockaddr_in *sin = (struct sockaddr_in *)sap;
return (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) &&
(ntohs(sin->sin_port) < 1024);
}

#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static inline int __nlm_privileged_request6(const struct sockaddr *sap)
{
const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
return (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LOOPBACK) &&
(ntohs(sin6->sin6_port) < 1024);
}
#else /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
static inline int __nlm_privileged_request6(const struct sockaddr *sap)
{
return 0;
}
#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */

/*
* Ensure incoming requests are from local privileged callers.
*
* Return TRUE if sender is local and is connecting via a privileged port;
* otherwise return FALSE.
*/
static inline int nlm_privileged_requester(const struct svc_rqst *rqstp)
{
const struct sockaddr *sap = svc_addr(rqstp);

switch (sap->sa_family) {
case AF_INET:
return __nlm_privileged_request4(sap);
case AF_INET6:
return __nlm_privileged_request6(sap);
default:
return 0;
}
}

static inline int __nlm_cmp_addr4(const struct sockaddr *sap1,
const struct sockaddr *sap2)
{
Expand Down

0 comments on commit b85e467

Please sign in to comment.