From: Drew Kluemke <[email protected]>

Multiple NFS reply handlers (rpc_lookup_reply, nfs_mount_reply,
nfs_umountall_reply, nfs_lookup_reply, nfs_readlink_reply) copy network
data into a stack-allocated struct rpc_t without verifying that the UDP
payload length fits within the buffer. A malicious or malformed NFS
server response with len > sizeof(rpc_pkt) overwrites the stack frame.

Add a bounds check before each memcpy to drop oversized packets.

Signed-off-by: Drew Kluemke <[email protected]>
Signed-off-by: Sriram Sriram <[email protected]>
---
 net/nfs-common.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/net/nfs-common.c b/net/nfs-common.c
index 637fcfd9bb8..226e3fe5798 100644
--- a/net/nfs-common.c
+++ b/net/nfs-common.c
@@ -503,6 +503,8 @@ static int rpc_lookup_reply(int prog, uchar *pkt, unsigned 
int len)
 {
        struct rpc_t rpc_pkt;
 
+       if (len > sizeof(rpc_pkt.u.data))
+               return -NFS_RPC_DROP;
        memcpy(&rpc_pkt.u.data[0], pkt, len);
 
        if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
@@ -532,6 +534,8 @@ static int nfs_mount_reply(uchar *pkt, unsigned int len)
        struct rpc_t rpc_pkt;
        int ret;
 
+       if (len > sizeof(rpc_pkt.u.data))
+               return -NFS_RPC_DROP;
        memcpy(&rpc_pkt.u.data[0], pkt, len);
 
        if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
@@ -561,6 +565,8 @@ static int nfs_umountall_reply(uchar *pkt, unsigned int len)
 {
        struct rpc_t rpc_pkt;
 
+       if (len > sizeof(rpc_pkt.u.data))
+               return -NFS_RPC_DROP;
        memcpy(&rpc_pkt.u.data[0], pkt, len);
 
        if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
@@ -584,6 +590,8 @@ static int nfs_lookup_reply(uchar *pkt, unsigned int len)
        struct rpc_t rpc_pkt;
        int ret;
 
+       if (len > sizeof(rpc_pkt.u.data))
+               return -NFS_RPC_DROP;
        memcpy(&rpc_pkt.u.data[0], pkt, len);
 
        if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
@@ -645,6 +653,8 @@ static int nfs_readlink_reply(uchar *pkt, unsigned int len)
        int rlen;
        int nfsv3_data_offset = 0;
 
+       if (len > sizeof(rpc_pkt))
+               return -NFS_RPC_DROP;
        memcpy((unsigned char *)&rpc_pkt, pkt, len);
 
        if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
-- 
2.49.0

Reply via email to