Skip to content

Commit b85e467

Browse files
chuckleverJ. Bruce Fields
authored andcommitted
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>
1 parent dcff09f commit b85e467

3 files changed

Lines changed: 45 additions & 8 deletions

File tree

fs/lockd/svc4proc.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -421,11 +421,9 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
421421
{
422422
struct sockaddr_in saddr;
423423

424-
memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr));
425-
426424
dprintk("lockd: SM_NOTIFY called\n");
427-
if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
428-
|| ntohs(saddr.sin_port) >= 1024) {
425+
426+
if (!nlm_privileged_requester(rqstp)) {
429427
char buf[RPC_MAX_ADDRBUFLEN];
430428
printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
431429
svc_print_addr(rqstp, buf, sizeof(buf)));

fs/lockd/svcproc.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -453,11 +453,9 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
453453
{
454454
struct sockaddr_in saddr;
455455

456-
memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr));
457-
458456
dprintk("lockd: SM_NOTIFY called\n");
459-
if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
460-
|| ntohs(saddr.sin_port) >= 1024) {
457+
458+
if (!nlm_privileged_requester(rqstp)) {
461459
char buf[RPC_MAX_ADDRBUFLEN];
462460
printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
463461
svc_print_addr(rqstp, buf, sizeof(buf)));

include/linux/lockd/lockd.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,47 @@ static inline struct inode *nlmsvc_file_inode(struct nlm_file *file)
277277
return file->f_file->f_path.dentry->d_inode;
278278
}
279279

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+
280321
static inline int __nlm_cmp_addr4(const struct sockaddr *sap1,
281322
const struct sockaddr *sap2)
282323
{

0 commit comments

Comments
 (0)