<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">diff --git a/include/linux/socket.h b/include/linux/socket.h
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -90,6 +90,7 @@ struct cmsghdr {
 #define CMSG_ALIGN(len) ( ((len)+sizeof(long)-1) &amp; ~(sizeof(long)-1) )
 
 #define CMSG_DATA(cmsg)	((void *)((char *)(cmsg) + CMSG_ALIGN(sizeof(struct cmsghdr))))
+#define CMSG_DATA_USER(cmsg)	((void __user *)((char __user *)(cmsg) + CMSG_ALIGN(sizeof(struct cmsghdr))))
 #define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(len))
 #define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
 
@@ -297,7 +298,15 @@ extern int verify_iovec(struct msghdr *m
 extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len);
 extern int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, int __user *ulen);
 extern int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr);
-extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
+extern int __put_cmsg(struct msghdr *msg, int level, int type,
+		      int len, void *data, struct cmsghdr __user *cm);
+
+static inline int put_cmsg(struct msghdr *msg, int level, int type,
+			   int len, void *data)
+{
+	return __put_cmsg(msg, level, type, len, data,
+			  (struct cmsghdr __user *)msg-&gt;msg_control);
+}
 
 #endif
 #endif /* not kernel and not glibc */
diff --git a/include/net/compat.h b/include/net/compat.h
--- a/include/net/compat.h
+++ b/include/net/compat.h
@@ -32,7 +32,16 @@ extern int verify_compat_iovec(struct ms
 extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr __user *,unsigned);
 extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned);
 extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *);
-extern int put_cmsg_compat(struct msghdr*, int, int, int, void *);
+
+extern int __put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len,
+			     void *data, struct cmsghdr __user *kcm);
+static inline int put_cmsg_compat(struct msghdr *kmsg, int level, int type,
+				  int len, void *data)
+{
+	return __put_cmsg_compat(kmsg, level, type, len, data,
+				 (struct cmsghdr __user *)kmsg-&gt;msg_control);
+}
+
 extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, unsigned char *,
 		int);
 
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h
--- a/include/net/transp_v6.h
+++ b/include/net/transp_v6.h
@@ -30,9 +30,16 @@ extern int				udpv6_connect(struct sock 
 						      struct sockaddr *uaddr,
 						      int addr_len);
 
-extern int			datagram_recv_ctl(struct sock *sk,
-						  struct msghdr *msg,
-						  struct sk_buff *skb);
+extern int __datagram_recv_ctl(struct sock *sk, struct msghdr *msg,
+			       struct cmsghdr __user *cmsg,
+			       struct sk_buff *skb);
+extern inline int datagram_recv_ctl(struct sock *sk, struct msghdr *msg,
+				    struct sk_buff *skb)
+{
+	return __datagram_recv_ctl(sk, msg,
+				   (struct cmsghdr __user *)msg-&gt;msg_control,
+				   skb);
+}
 
 extern int			datagram_send_ctl(struct msghdr *msg,
 						  struct flowi *fl,
diff --git a/net/compat.c b/net/compat.c
--- a/net/compat.c
+++ b/net/compat.c
@@ -205,10 +205,11 @@ out_free_efault:
 	return -EFAULT;
 }
 
-int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data)
+int __put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len,
+		      void *data, struct cmsghdr __user *kcm)
 {
 	struct compat_timeval ctv;
-	struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg-&gt;msg_control;
+	struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *)kcm;
 	struct compat_cmsghdr cmhdr;
 	int cmlen;
 
diff --git a/net/core/scm.c b/net/core/scm.c
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -164,15 +164,15 @@ error:
 	return err;
 }
 
-int put_cmsg(struct msghdr * msg, int level, int type, int len, void *data)
+int __put_cmsg(struct msghdr * msg, int level, int type, int len, void *data,
+	       struct cmsghdr __user *cm)
 {
-	struct cmsghdr __user *cm = (struct cmsghdr __user *)msg-&gt;msg_control;
 	struct cmsghdr cmhdr;
 	int cmlen = CMSG_LEN(len);
 	int err;
 
 	if (MSG_CMSG_COMPAT &amp; msg-&gt;msg_flags)
-		return put_cmsg_compat(msg, level, type, len, data);
+		return __put_cmsg_compat(msg, level, type, len, data, cm);
 
 	if (cm==NULL || msg-&gt;msg_controllen &lt; sizeof(*cm)) {
 		msg-&gt;msg_flags |= MSG_CTRUNC;
@@ -189,7 +189,7 @@ int put_cmsg(struct msghdr * msg, int le
 	err = -EFAULT;
 	if (copy_to_user(cm, &amp;cmhdr, sizeof cmhdr))
 		goto out; 
-	if (copy_to_user(CMSG_DATA(cm), data, cmlen - sizeof(struct cmsghdr)))
+	if (copy_to_user(CMSG_DATA_USER(cm), data, cmlen - sizeof(struct cmsghdr)))
 		goto out;
 	cmlen = CMSG_SPACE(len);
 	msg-&gt;msg_control += cmlen;
@@ -221,7 +221,7 @@ void scm_detach_fds(struct msghdr *msg, 
 	if (fdnum &lt; fdmax)
 		fdmax = fdnum;
 
-	for (i=0, cmfptr=(int __user *)CMSG_DATA(cm); i&lt;fdmax; i++, cmfptr++)
+	for (i=0, cmfptr=(int __user *)CMSG_DATA_USER(cm); i&lt;fdmax; i++, cmfptr++)
 	{
 		int new_fd;
 		err = security_file_receive(fp[i]);
@@ -285,6 +285,6 @@ struct scm_fp_list *scm_fp_dup(struct sc
 
 EXPORT_SYMBOL(__scm_destroy);
 EXPORT_SYMBOL(__scm_send);
-EXPORT_SYMBOL(put_cmsg);
+EXPORT_SYMBOL(__put_cmsg);
 EXPORT_SYMBOL(scm_detach_fds);
 EXPORT_SYMBOL(scm_fp_dup);
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -1032,7 +1032,6 @@ int ip_getsockopt(struct sock *sk, int l
 			if (sk-&gt;sk_type != SOCK_STREAM)
 				return -ENOPROTOOPT;
 
-			msg.msg_control = optval;
 			msg.msg_controllen = len;
 			msg.msg_flags = 0;
 
@@ -1042,11 +1041,15 @@ int ip_getsockopt(struct sock *sk, int l
 				info.ipi_addr.s_addr = inet-&gt;rcv_saddr;
 				info.ipi_spec_dst.s_addr = inet-&gt;rcv_saddr;
 				info.ipi_ifindex = inet-&gt;mc_index;
-				put_cmsg(&amp;msg, SOL_IP, IP_PKTINFO, sizeof(info), &amp;info);
+				__put_cmsg(&amp;msg, SOL_IP, IP_PKTINFO,
+					   sizeof(info), &amp;info,
+					   (struct cmsghdr __user *)optval);
 			}
 			if (inet-&gt;cmsg_flags &amp; IP_CMSG_TTL) {
 				int hlim = inet-&gt;mc_ttl;
-				put_cmsg(&amp;msg, SOL_IP, IP_TTL, sizeof(hlim), &amp;hlim);
+				__put_cmsg(&amp;msg, SOL_IP, IP_TTL,
+					   sizeof(hlim), &amp;hlim,
+					   (struct cmsghdr __user *)optval);
 			}
 			len -= msg.msg_controllen;
 			return put_user(len, optlen);
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -370,9 +370,8 @@ out:
 	return err;
 }
 
-
-
-int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
+int __datagram_recv_ctl(struct sock *sk, struct msghdr *msg,
+			struct cmsghdr __user *cmsg, struct sk_buff *skb)
 {
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct inet6_skb_parm *opt = IP6CB(skb);
@@ -382,33 +381,33 @@ int datagram_recv_ctl(struct sock *sk, s
 
 		src_info.ipi6_ifindex = opt-&gt;iif;
 		ipv6_addr_copy(&amp;src_info.ipi6_addr, &amp;skb-&gt;nh.ipv6h-&gt;daddr);
-		put_cmsg(msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &amp;src_info);
+		__put_cmsg(msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &amp;src_info, cmsg);
 	}
 
 	if (np-&gt;rxopt.bits.rxhlim) {
 		int hlim = skb-&gt;nh.ipv6h-&gt;hop_limit;
-		put_cmsg(msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &amp;hlim);
+		__put_cmsg(msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &amp;hlim, cmsg);
 	}
 
 	if (np-&gt;rxopt.bits.rxflow &amp;&amp; (*(u32*)skb-&gt;nh.raw &amp; IPV6_FLOWINFO_MASK)) {
 		u32 flowinfo = *(u32*)skb-&gt;nh.raw &amp; IPV6_FLOWINFO_MASK;
-		put_cmsg(msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &amp;flowinfo);
+		__put_cmsg(msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &amp;flowinfo, cmsg);
 	}
 	if (np-&gt;rxopt.bits.hopopts &amp;&amp; opt-&gt;hop) {
 		u8 *ptr = skb-&gt;nh.raw + opt-&gt;hop;
-		put_cmsg(msg, SOL_IPV6, IPV6_HOPOPTS, (ptr[1]+1)&lt;&lt;3, ptr);
+		__put_cmsg(msg, SOL_IPV6, IPV6_HOPOPTS, (ptr[1]+1)&lt;&lt;3, ptr, cmsg);
 	}
 	if (np-&gt;rxopt.bits.dstopts &amp;&amp; opt-&gt;dst0) {
 		u8 *ptr = skb-&gt;nh.raw + opt-&gt;dst0;
-		put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, (ptr[1]+1)&lt;&lt;3, ptr);
+		__put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, (ptr[1]+1)&lt;&lt;3, ptr, cmsg);
 	}
 	if (np-&gt;rxopt.bits.srcrt &amp;&amp; opt-&gt;srcrt) {
 		struct ipv6_rt_hdr *rthdr = (struct ipv6_rt_hdr *)(skb-&gt;nh.raw + opt-&gt;srcrt);
-		put_cmsg(msg, SOL_IPV6, IPV6_RTHDR, (rthdr-&gt;hdrlen+1) &lt;&lt; 3, rthdr);
+		__put_cmsg(msg, SOL_IPV6, IPV6_RTHDR, (rthdr-&gt;hdrlen+1) &lt;&lt; 3, rthdr, cmsg);
 	}
 	if (np-&gt;rxopt.bits.dstopts &amp;&amp; opt-&gt;dst1) {
 		u8 *ptr = skb-&gt;nh.raw + opt-&gt;dst1;
-		put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, (ptr[1]+1)&lt;&lt;3, ptr);
+		__put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, (ptr[1]+1)&lt;&lt;3, ptr, cmsg);
 	}
 	return 0;
 }
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -571,11 +571,11 @@ int ipv6_getsockopt(struct sock *sk, int
 	{
 		struct msghdr msg;
 		struct sk_buff *skb;
+		struct cmsghdr __user *cmsg;
 
 		if (sk-&gt;sk_type != SOCK_STREAM)
 			return -ENOPROTOOPT;
 
-		msg.msg_control = optval;
 		msg.msg_controllen = len;
 		msg.msg_flags = 0;
 
@@ -585,8 +585,10 @@ int ipv6_getsockopt(struct sock *sk, int
 			atomic_inc(&amp;skb-&gt;users);
 		release_sock(sk);
 
+		cmsg = (struct cmsghdr __user *)optval;
+
 		if (skb) {
-			int err = datagram_recv_ctl(sk, &amp;msg, skb);
+			int err = __datagram_recv_ctl(sk, &amp;msg, cmsg, skb);
 			kfree_skb(skb);
 			if (err)
 				return err;
@@ -595,11 +597,13 @@ int ipv6_getsockopt(struct sock *sk, int
 				struct in6_pktinfo src_info;
 				src_info.ipi6_ifindex = np-&gt;mcast_oif;
 				ipv6_addr_copy(&amp;src_info.ipi6_addr, &amp;np-&gt;daddr);
-				put_cmsg(&amp;msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &amp;src_info);
+				__put_cmsg(&amp;msg, SOL_IPV6, IPV6_PKTINFO,
+					   sizeof(src_info), &amp;src_info, cmsg);
 			}
 			if (np-&gt;rxopt.bits.rxhlim) {
 				int hlim = np-&gt;mcast_hops;
-				put_cmsg(&amp;msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &amp;hlim);
+				__put_cmsg(&amp;msg, SOL_IPV6, IPV6_HOPLIMIT,
+					   sizeof(hlim), &amp;hlim, cmsg);
 			}
 		}
 		len -= msg.msg_controllen;
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -1,12 +1,12 @@
 #include &lt;linux/config.h&gt;
 #include &lt;linux/init.h&gt;
+#include &lt;linux/netfilter_ipv6.h&gt;
 
 #ifdef CONFIG_NETFILTER
 
 #include &lt;linux/kernel.h&gt;
 #include &lt;linux/ipv6.h&gt;
 #include &lt;linux/netfilter.h&gt;
-#include &lt;linux/netfilter_ipv6.h&gt;
 #include &lt;net/dst.h&gt;
 #include &lt;net/ipv6.h&gt;
 #include &lt;net/ip6_route.h&gt;
</pre></body></html>