Add defensive size validation to bpf_sock_addr_set_sun_path() before
writing to the sockaddr buffer. While the underlying buffer is guaranteed
to be sockaddr_storage (128 bytes) from the bind() syscall path, the
function should validate that "sa_kern->uaddrlen" is sufficient for the
sockaddr_un structure being written.

The validation checks that the available buffer size ("sa_kern->uaddrlen")
can accommodate both the sockaddr_un header and the requested path length
before performing the memcpy() operation.

Signed-off-by: Kees Cook <[email protected]>
---
 net/core/filter.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/net/core/filter.c b/net/core/filter.c
index b96b5ffc7eb3..fa6c5baf0bf3 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -12089,6 +12089,7 @@ __bpf_kfunc int bpf_sock_addr_set_sun_path(struct 
bpf_sock_addr_kern *sa_kern,
                                           const u8 *sun_path, u32 sun_path__sz)
 {
        struct sockaddr_un *un;
+       size_t required_size;
 
        if (sa_kern->sk->sk_family != AF_UNIX)
                return -EINVAL;
@@ -12099,9 +12100,14 @@ __bpf_kfunc int bpf_sock_addr_set_sun_path(struct 
bpf_sock_addr_kern *sa_kern,
        if (sun_path__sz == 0 || sun_path__sz > UNIX_PATH_MAX)
                return -EINVAL;
 
+       /* Validate that the buffer is large enough for sockaddr_un + path */
+       required_size = offsetof(struct sockaddr_un, sun_path) + sun_path__sz;
+       if (sa_kern->uaddrlen < required_size)
+               return -EINVAL;
+
        un = (struct sockaddr_un *)sa_kern->uaddr;
        memcpy(un->sun_path, sun_path, sun_path__sz);
-       sa_kern->uaddrlen = offsetof(struct sockaddr_un, sun_path) + 
sun_path__sz;
+       sa_kern->uaddrlen = required_size;
 
        return 0;
 }
-- 
2.34.1


Reply via email to