udp: do not expect udp headers in recv cmsg IP_CMSG_CHECKSUM
[cascardo/linux.git] / net / ipv4 / ip_sockglue.c
index 035ad64..279471c 100644 (file)
@@ -106,7 +106,8 @@ static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb,
                return;
 
        if (offset != 0)
-               csum = csum_sub(csum, csum_partial(skb->data, offset, 0));
+               csum = csum_sub(csum, csum_partial(skb_transport_header(skb),
+                                                  offset, 0));
 
        put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum);
 }
@@ -219,11 +220,12 @@ void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb,
 }
 EXPORT_SYMBOL(ip_cmsg_recv_offset);
 
-int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc,
+int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc,
                 bool allow_ipv6)
 {
        int err, val;
        struct cmsghdr *cmsg;
+       struct net *net = sock_net(sk);
 
        for_each_cmsghdr(cmsg, msg) {
                if (!CMSG_OK(msg, cmsg))
@@ -244,6 +246,12 @@ int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc,
                        continue;
                }
 #endif
+               if (cmsg->cmsg_level == SOL_SOCKET) {
+                       if (__sock_cmsg_send(sk, msg, cmsg, &ipc->sockc))
+                               return -EINVAL;
+                       continue;
+               }
+
                if (cmsg->cmsg_level != SOL_IP)
                        continue;
                switch (cmsg->cmsg_type) {
@@ -635,7 +643,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
                if (err)
                        break;
                old = rcu_dereference_protected(inet->inet_opt,
-                                               sock_owned_by_user(sk));
+                                               lockdep_sock_is_held(sk));
                if (inet->is_icsk) {
                        struct inet_connection_sock *icsk = inet_csk(sk);
 #if IS_ENABLED(CONFIG_IPV6)
@@ -1295,7 +1303,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
                struct ip_options_rcu *inet_opt;
 
                inet_opt = rcu_dereference_protected(inet->inet_opt,
-                                                    sock_owned_by_user(sk));
+                                                    lockdep_sock_is_held(sk));
                opt->optlen = 0;
                if (inet_opt)
                        memcpy(optbuf, &inet_opt->opt,