summaryrefslogtreecommitdiff
blob: 50dacd0e5a49197fbcda740428b4d1313dadaf88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
Index: sys/kern/uipc_usrreq.c
===================================================================
--- sys/kern/uipc_usrreq.c	(revision 225745)
+++ sys/kern/uipc_usrreq.c	(working copy)
@@ -462,6 +462,8 @@
 	unp = sotounpcb(so);
 	KASSERT(unp != NULL, ("uipc_bind: unp == NULL"));
 
+	if (soun->sun_len > sizeof(struct sockaddr_un))
+		return (EINVAL);
 	namelen = soun->sun_len - offsetof(struct sockaddr_un, sun_path);
 	if (namelen <= 0)
 		return (EINVAL);
@@ -1252,6 +1254,8 @@
 	unp = sotounpcb(so);
 	KASSERT(unp != NULL, ("unp_connect: unp == NULL"));
 
+	if (nam->sa_len > sizeof(struct sockaddr_un))
+		return (EINVAL);
 	len = nam->sa_len - offsetof(struct sockaddr_un, sun_path);
 	if (len <= 0)
 		return (EINVAL);
Index: sys/compat/linux/linux_socket.c
===================================================================
--- sys/compat/linux/linux_socket.c	(revision 225919)
+++ sys/compat/linux/linux_socket.c	(working copy)
@@ -104,6 +104,7 @@
 	int oldv6size;
 	struct sockaddr_in6 *sin6;
 #endif
+	int namelen;
 
 	if (*osalen < 2 || *osalen > UCHAR_MAX || !osa)
 		return (EINVAL);
@@ -166,6 +167,20 @@
 		}
 	}
 
+	if ((bdom == AF_LOCAL) && (*osalen > sizeof(struct sockaddr_un))) {
+		for (namelen = 0;
+		    namelen < *osalen - offsetof(struct sockaddr_un, sun_path);
+		    namelen++)
+			if (!((struct sockaddr_un *)kosa)->sun_path[namelen])
+				break;
+		if (namelen + offsetof(struct sockaddr_un, sun_path) >
+		    sizeof(struct sockaddr_un)) {
+			error = EINVAL;
+			goto out;
+		}
+		alloclen = sizeof(struct sockaddr_un);
+	}
+
 	sa = (struct sockaddr *) kosa;
 	sa->sa_family = bdom;
 	sa->sa_len = alloclen;