LCOV - code coverage report
Current view: top level - net/ipv4 - ip_sockglue.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 77 997 7.7 %
Date: 2021-04-22 12:43:58 Functions: 6 37 16.2 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * INET         An implementation of the TCP/IP protocol suite for the LINUX
       4             :  *              operating system.  INET is implemented using the  BSD Socket
       5             :  *              interface as the means of communication with the user level.
       6             :  *
       7             :  *              The IP to API glue.
       8             :  *
       9             :  * Authors:     see ip.c
      10             :  *
      11             :  * Fixes:
      12             :  *              Many            :       Split from ip.c , see ip.c for history.
      13             :  *              Martin Mares    :       TOS setting fixed.
      14             :  *              Alan Cox        :       Fixed a couple of oopses in Martin's
      15             :  *                                      TOS tweaks.
      16             :  *              Mike McLagan    :       Routing by source
      17             :  */
      18             : 
      19             : #include <linux/module.h>
      20             : #include <linux/types.h>
      21             : #include <linux/mm.h>
      22             : #include <linux/skbuff.h>
      23             : #include <linux/ip.h>
      24             : #include <linux/icmp.h>
      25             : #include <linux/inetdevice.h>
      26             : #include <linux/netdevice.h>
      27             : #include <linux/slab.h>
      28             : #include <net/sock.h>
      29             : #include <net/ip.h>
      30             : #include <net/icmp.h>
      31             : #include <net/tcp_states.h>
      32             : #include <linux/udp.h>
      33             : #include <linux/igmp.h>
      34             : #include <linux/netfilter.h>
      35             : #include <linux/route.h>
      36             : #include <linux/mroute.h>
      37             : #include <net/inet_ecn.h>
      38             : #include <net/route.h>
      39             : #include <net/xfrm.h>
      40             : #include <net/compat.h>
      41             : #include <net/checksum.h>
      42             : #if IS_ENABLED(CONFIG_IPV6)
      43             : #include <net/transp_v6.h>
      44             : #endif
      45             : #include <net/ip_fib.h>
      46             : 
      47             : #include <linux/errqueue.h>
      48             : #include <linux/uaccess.h>
      49             : 
      50             : #include <linux/bpfilter.h>
      51             : 
      52             : /*
      53             :  *      SOL_IP control messages.
      54             :  */
      55             : 
      56           0 : static void ip_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb)
      57             : {
      58           0 :         struct in_pktinfo info = *PKTINFO_SKB_CB(skb);
      59             : 
      60           0 :         info.ipi_addr.s_addr = ip_hdr(skb)->daddr;
      61             : 
      62           0 :         put_cmsg(msg, SOL_IP, IP_PKTINFO, sizeof(info), &info);
      63           0 : }
      64             : 
      65           0 : static void ip_cmsg_recv_ttl(struct msghdr *msg, struct sk_buff *skb)
      66             : {
      67           0 :         int ttl = ip_hdr(skb)->ttl;
      68           0 :         put_cmsg(msg, SOL_IP, IP_TTL, sizeof(int), &ttl);
      69           0 : }
      70             : 
      71           0 : static void ip_cmsg_recv_tos(struct msghdr *msg, struct sk_buff *skb)
      72             : {
      73           0 :         put_cmsg(msg, SOL_IP, IP_TOS, 1, &ip_hdr(skb)->tos);
      74           0 : }
      75             : 
      76           0 : static void ip_cmsg_recv_opts(struct msghdr *msg, struct sk_buff *skb)
      77             : {
      78           0 :         if (IPCB(skb)->opt.optlen == 0)
      79             :                 return;
      80             : 
      81           0 :         put_cmsg(msg, SOL_IP, IP_RECVOPTS, IPCB(skb)->opt.optlen,
      82           0 :                  ip_hdr(skb) + 1);
      83             : }
      84             : 
      85             : 
      86           0 : static void ip_cmsg_recv_retopts(struct net *net, struct msghdr *msg,
      87             :                                  struct sk_buff *skb)
      88             : {
      89           0 :         unsigned char optbuf[sizeof(struct ip_options) + 40];
      90           0 :         struct ip_options *opt = (struct ip_options *)optbuf;
      91             : 
      92           0 :         if (IPCB(skb)->opt.optlen == 0)
      93           0 :                 return;
      94             : 
      95           0 :         if (ip_options_echo(net, opt, skb)) {
      96           0 :                 msg->msg_flags |= MSG_CTRUNC;
      97           0 :                 return;
      98             :         }
      99           0 :         ip_options_undo(opt);
     100             : 
     101           0 :         put_cmsg(msg, SOL_IP, IP_RETOPTS, opt->optlen, opt->__data);
     102             : }
     103             : 
     104           0 : static void ip_cmsg_recv_fragsize(struct msghdr *msg, struct sk_buff *skb)
     105             : {
     106           0 :         int val;
     107             : 
     108           0 :         if (IPCB(skb)->frag_max_size == 0)
     109           0 :                 return;
     110             : 
     111           0 :         val = IPCB(skb)->frag_max_size;
     112           0 :         put_cmsg(msg, SOL_IP, IP_RECVFRAGSIZE, sizeof(val), &val);
     113             : }
     114             : 
     115           0 : static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb,
     116             :                                   int tlen, int offset)
     117             : {
     118           0 :         __wsum csum = skb->csum;
     119             : 
     120           0 :         if (skb->ip_summed != CHECKSUM_COMPLETE)
     121           0 :                 return;
     122             : 
     123           0 :         if (offset != 0) {
     124           0 :                 int tend_off = skb_transport_offset(skb) + tlen;
     125           0 :                 csum = csum_sub(csum, skb_checksum(skb, tend_off, offset, 0));
     126             :         }
     127             : 
     128           0 :         put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum);
     129             : }
     130             : 
     131           0 : static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
     132             : {
     133           0 :         char *secdata;
     134           0 :         u32 seclen, secid;
     135           0 :         int err;
     136             : 
     137           0 :         err = security_socket_getpeersec_dgram(NULL, skb, &secid);
     138           0 :         if (err)
     139           0 :                 return;
     140             : 
     141             :         err = security_secid_to_secctx(secid, &secdata, &seclen);
     142             :         if (err)
     143             :                 return;
     144             : 
     145             :         put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata);
     146             :         security_release_secctx(secdata, seclen);
     147             : }
     148             : 
     149           0 : static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb)
     150             : {
     151           0 :         __be16 _ports[2], *ports;
     152           0 :         struct sockaddr_in sin;
     153             : 
     154             :         /* All current transport protocols have the port numbers in the
     155             :          * first four bytes of the transport header and this function is
     156             :          * written with this assumption in mind.
     157             :          */
     158           0 :         ports = skb_header_pointer(skb, skb_transport_offset(skb),
     159             :                                    sizeof(_ports), &_ports);
     160           0 :         if (!ports)
     161           0 :                 return;
     162             : 
     163           0 :         sin.sin_family = AF_INET;
     164           0 :         sin.sin_addr.s_addr = ip_hdr(skb)->daddr;
     165           0 :         sin.sin_port = ports[1];
     166           0 :         memset(sin.sin_zero, 0, sizeof(sin.sin_zero));
     167             : 
     168           0 :         put_cmsg(msg, SOL_IP, IP_ORIGDSTADDR, sizeof(sin), &sin);
     169             : }
     170             : 
     171           0 : void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk,
     172             :                          struct sk_buff *skb, int tlen, int offset)
     173             : {
     174           0 :         struct inet_sock *inet = inet_sk(sk);
     175           0 :         unsigned int flags = inet->cmsg_flags;
     176             : 
     177             :         /* Ordered by supposed usage frequency */
     178           0 :         if (flags & IP_CMSG_PKTINFO) {
     179           0 :                 ip_cmsg_recv_pktinfo(msg, skb);
     180             : 
     181           0 :                 flags &= ~IP_CMSG_PKTINFO;
     182           0 :                 if (!flags)
     183             :                         return;
     184             :         }
     185             : 
     186           0 :         if (flags & IP_CMSG_TTL) {
     187           0 :                 ip_cmsg_recv_ttl(msg, skb);
     188             : 
     189           0 :                 flags &= ~IP_CMSG_TTL;
     190           0 :                 if (!flags)
     191             :                         return;
     192             :         }
     193             : 
     194           0 :         if (flags & IP_CMSG_TOS) {
     195           0 :                 ip_cmsg_recv_tos(msg, skb);
     196             : 
     197           0 :                 flags &= ~IP_CMSG_TOS;
     198           0 :                 if (!flags)
     199             :                         return;
     200             :         }
     201             : 
     202           0 :         if (flags & IP_CMSG_RECVOPTS) {
     203           0 :                 ip_cmsg_recv_opts(msg, skb);
     204             : 
     205           0 :                 flags &= ~IP_CMSG_RECVOPTS;
     206           0 :                 if (!flags)
     207             :                         return;
     208             :         }
     209             : 
     210           0 :         if (flags & IP_CMSG_RETOPTS) {
     211           0 :                 ip_cmsg_recv_retopts(sock_net(sk), msg, skb);
     212             : 
     213           0 :                 flags &= ~IP_CMSG_RETOPTS;
     214           0 :                 if (!flags)
     215             :                         return;
     216             :         }
     217             : 
     218           0 :         if (flags & IP_CMSG_PASSSEC) {
     219           0 :                 ip_cmsg_recv_security(msg, skb);
     220             : 
     221           0 :                 flags &= ~IP_CMSG_PASSSEC;
     222           0 :                 if (!flags)
     223             :                         return;
     224             :         }
     225             : 
     226           0 :         if (flags & IP_CMSG_ORIGDSTADDR) {
     227           0 :                 ip_cmsg_recv_dstaddr(msg, skb);
     228             : 
     229           0 :                 flags &= ~IP_CMSG_ORIGDSTADDR;
     230           0 :                 if (!flags)
     231             :                         return;
     232             :         }
     233             : 
     234           0 :         if (flags & IP_CMSG_CHECKSUM)
     235           0 :                 ip_cmsg_recv_checksum(msg, skb, tlen, offset);
     236             : 
     237           0 :         if (flags & IP_CMSG_RECVFRAGSIZE)
     238           0 :                 ip_cmsg_recv_fragsize(msg, skb);
     239             : }
     240             : EXPORT_SYMBOL(ip_cmsg_recv_offset);
     241             : 
     242           0 : int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc,
     243             :                  bool allow_ipv6)
     244             : {
     245           0 :         int err, val;
     246           0 :         struct cmsghdr *cmsg;
     247           0 :         struct net *net = sock_net(sk);
     248             : 
     249           0 :         for_each_cmsghdr(cmsg, msg) {
     250           0 :                 if (!CMSG_OK(msg, cmsg))
     251             :                         return -EINVAL;
     252             : #if IS_ENABLED(CONFIG_IPV6)
     253             :                 if (allow_ipv6 &&
     254             :                     cmsg->cmsg_level == SOL_IPV6 &&
     255             :                     cmsg->cmsg_type == IPV6_PKTINFO) {
     256             :                         struct in6_pktinfo *src_info;
     257             : 
     258             :                         if (cmsg->cmsg_len < CMSG_LEN(sizeof(*src_info)))
     259             :                                 return -EINVAL;
     260             :                         src_info = (struct in6_pktinfo *)CMSG_DATA(cmsg);
     261             :                         if (!ipv6_addr_v4mapped(&src_info->ipi6_addr))
     262             :                                 return -EINVAL;
     263             :                         if (src_info->ipi6_ifindex)
     264             :                                 ipc->oif = src_info->ipi6_ifindex;
     265             :                         ipc->addr = src_info->ipi6_addr.s6_addr32[3];
     266             :                         continue;
     267             :                 }
     268             : #endif
     269           0 :                 if (cmsg->cmsg_level == SOL_SOCKET) {
     270           0 :                         err = __sock_cmsg_send(sk, msg, cmsg, &ipc->sockc);
     271           0 :                         if (err)
     272           0 :                                 return err;
     273           0 :                         continue;
     274             :                 }
     275             : 
     276           0 :                 if (cmsg->cmsg_level != SOL_IP)
     277           0 :                         continue;
     278           0 :                 switch (cmsg->cmsg_type) {
     279           0 :                 case IP_RETOPTS:
     280           0 :                         err = cmsg->cmsg_len - sizeof(struct cmsghdr);
     281             : 
     282             :                         /* Our caller is responsible for freeing ipc->opt */
     283           0 :                         err = ip_options_get(net, &ipc->opt,
     284             :                                              KERNEL_SOCKPTR(CMSG_DATA(cmsg)),
     285             :                                              err < 40 ? err : 40);
     286           0 :                         if (err)
     287           0 :                                 return err;
     288             :                         break;
     289           0 :                 case IP_PKTINFO:
     290             :                 {
     291           0 :                         struct in_pktinfo *info;
     292           0 :                         if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct in_pktinfo)))
     293             :                                 return -EINVAL;
     294           0 :                         info = (struct in_pktinfo *)CMSG_DATA(cmsg);
     295           0 :                         if (info->ipi_ifindex)
     296           0 :                                 ipc->oif = info->ipi_ifindex;
     297           0 :                         ipc->addr = info->ipi_spec_dst.s_addr;
     298           0 :                         break;
     299             :                 }
     300           0 :                 case IP_TTL:
     301           0 :                         if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)))
     302             :                                 return -EINVAL;
     303           0 :                         val = *(int *)CMSG_DATA(cmsg);
     304           0 :                         if (val < 1 || val > 255)
     305             :                                 return -EINVAL;
     306           0 :                         ipc->ttl = val;
     307           0 :                         break;
     308           0 :                 case IP_TOS:
     309           0 :                         if (cmsg->cmsg_len == CMSG_LEN(sizeof(int)))
     310           0 :                                 val = *(int *)CMSG_DATA(cmsg);
     311           0 :                         else if (cmsg->cmsg_len == CMSG_LEN(sizeof(u8)))
     312           0 :                                 val = *(u8 *)CMSG_DATA(cmsg);
     313             :                         else
     314             :                                 return -EINVAL;
     315           0 :                         if (val < 0 || val > 255)
     316             :                                 return -EINVAL;
     317           0 :                         ipc->tos = val;
     318           0 :                         ipc->priority = rt_tos2priority(ipc->tos);
     319           0 :                         break;
     320             : 
     321             :                 default:
     322             :                         return -EINVAL;
     323             :                 }
     324             :         }
     325             :         return 0;
     326             : }
     327             : 
     328           0 : static void ip_ra_destroy_rcu(struct rcu_head *head)
     329             : {
     330           0 :         struct ip_ra_chain *ra = container_of(head, struct ip_ra_chain, rcu);
     331             : 
     332           0 :         sock_put(ra->saved_sk);
     333           0 :         kfree(ra);
     334           0 : }
     335             : 
     336           0 : int ip_ra_control(struct sock *sk, unsigned char on,
     337             :                   void (*destructor)(struct sock *))
     338             : {
     339           0 :         struct ip_ra_chain *ra, *new_ra;
     340           0 :         struct ip_ra_chain __rcu **rap;
     341           0 :         struct net *net = sock_net(sk);
     342             : 
     343           0 :         if (sk->sk_type != SOCK_RAW || inet_sk(sk)->inet_num == IPPROTO_RAW)
     344             :                 return -EINVAL;
     345             : 
     346           0 :         new_ra = on ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL;
     347           0 :         if (on && !new_ra)
     348             :                 return -ENOMEM;
     349             : 
     350           0 :         mutex_lock(&net->ipv4.ra_mutex);
     351           0 :         for (rap = &net->ipv4.ra_chain;
     352           0 :              (ra = rcu_dereference_protected(*rap,
     353             :                         lockdep_is_held(&net->ipv4.ra_mutex))) != NULL;
     354           0 :              rap = &ra->next) {
     355           0 :                 if (ra->sk == sk) {
     356           0 :                         if (on) {
     357           0 :                                 mutex_unlock(&net->ipv4.ra_mutex);
     358           0 :                                 kfree(new_ra);
     359           0 :                                 return -EADDRINUSE;
     360             :                         }
     361             :                         /* dont let ip_call_ra_chain() use sk again */
     362           0 :                         ra->sk = NULL;
     363           0 :                         RCU_INIT_POINTER(*rap, ra->next);
     364           0 :                         mutex_unlock(&net->ipv4.ra_mutex);
     365             : 
     366           0 :                         if (ra->destructor)
     367           0 :                                 ra->destructor(sk);
     368             :                         /*
     369             :                          * Delay sock_put(sk) and kfree(ra) after one rcu grace
     370             :                          * period. This guarantee ip_call_ra_chain() dont need
     371             :                          * to mess with socket refcounts.
     372             :                          */
     373           0 :                         ra->saved_sk = sk;
     374           0 :                         call_rcu(&ra->rcu, ip_ra_destroy_rcu);
     375           0 :                         return 0;
     376             :                 }
     377             :         }
     378           0 :         if (!new_ra) {
     379           0 :                 mutex_unlock(&net->ipv4.ra_mutex);
     380           0 :                 return -ENOBUFS;
     381             :         }
     382           0 :         new_ra->sk = sk;
     383           0 :         new_ra->destructor = destructor;
     384             : 
     385           0 :         RCU_INIT_POINTER(new_ra->next, ra);
     386           0 :         rcu_assign_pointer(*rap, new_ra);
     387           0 :         sock_hold(sk);
     388           0 :         mutex_unlock(&net->ipv4.ra_mutex);
     389             : 
     390           0 :         return 0;
     391             : }
     392             : 
     393           0 : static void ipv4_icmp_error_rfc4884(const struct sk_buff *skb,
     394             :                                     struct sock_ee_data_rfc4884 *out)
     395             : {
     396           0 :         switch (icmp_hdr(skb)->type) {
     397             :         case ICMP_DEST_UNREACH:
     398             :         case ICMP_TIME_EXCEEDED:
     399             :         case ICMP_PARAMETERPROB:
     400           0 :                 ip_icmp_error_rfc4884(skb, out, sizeof(struct icmphdr),
     401           0 :                                       icmp_hdr(skb)->un.reserved[1] * 4);
     402             :         }
     403           0 : }
     404             : 
     405           0 : void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
     406             :                    __be16 port, u32 info, u8 *payload)
     407             : {
     408           0 :         struct sock_exterr_skb *serr;
     409             : 
     410           0 :         skb = skb_clone(skb, GFP_ATOMIC);
     411           0 :         if (!skb)
     412             :                 return;
     413             : 
     414           0 :         serr = SKB_EXT_ERR(skb);
     415           0 :         serr->ee.ee_errno = err;
     416           0 :         serr->ee.ee_origin = SO_EE_ORIGIN_ICMP;
     417           0 :         serr->ee.ee_type = icmp_hdr(skb)->type;
     418           0 :         serr->ee.ee_code = icmp_hdr(skb)->code;
     419           0 :         serr->ee.ee_pad = 0;
     420           0 :         serr->ee.ee_info = info;
     421           0 :         serr->ee.ee_data = 0;
     422           0 :         serr->addr_offset = (u8 *)&(((struct iphdr *)(icmp_hdr(skb) + 1))->daddr) -
     423           0 :                                    skb_network_header(skb);
     424           0 :         serr->port = port;
     425             : 
     426           0 :         if (skb_pull(skb, payload - skb->data)) {
     427           0 :                 if (inet_sk(sk)->recverr_rfc4884)
     428           0 :                         ipv4_icmp_error_rfc4884(skb, &serr->ee.ee_rfc4884);
     429             : 
     430           0 :                 skb_reset_transport_header(skb);
     431           0 :                 if (sock_queue_err_skb(sk, skb) == 0)
     432             :                         return;
     433             :         }
     434           0 :         kfree_skb(skb);
     435             : }
     436             : 
     437           0 : void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 info)
     438             : {
     439           0 :         struct inet_sock *inet = inet_sk(sk);
     440           0 :         struct sock_exterr_skb *serr;
     441           0 :         struct iphdr *iph;
     442           0 :         struct sk_buff *skb;
     443             : 
     444           0 :         if (!inet->recverr)
     445             :                 return;
     446             : 
     447           0 :         skb = alloc_skb(sizeof(struct iphdr), GFP_ATOMIC);
     448           0 :         if (!skb)
     449             :                 return;
     450             : 
     451           0 :         skb_put(skb, sizeof(struct iphdr));
     452           0 :         skb_reset_network_header(skb);
     453           0 :         iph = ip_hdr(skb);
     454           0 :         iph->daddr = daddr;
     455             : 
     456           0 :         serr = SKB_EXT_ERR(skb);
     457           0 :         serr->ee.ee_errno = err;
     458           0 :         serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL;
     459           0 :         serr->ee.ee_type = 0;
     460           0 :         serr->ee.ee_code = 0;
     461           0 :         serr->ee.ee_pad = 0;
     462           0 :         serr->ee.ee_info = info;
     463           0 :         serr->ee.ee_data = 0;
     464           0 :         serr->addr_offset = (u8 *)&iph->daddr - skb_network_header(skb);
     465           0 :         serr->port = port;
     466             : 
     467           0 :         __skb_pull(skb, skb_tail_pointer(skb) - skb->data);
     468           0 :         skb_reset_transport_header(skb);
     469             : 
     470           0 :         if (sock_queue_err_skb(sk, skb))
     471           0 :                 kfree_skb(skb);
     472             : }
     473             : 
     474             : /* For some errors we have valid addr_offset even with zero payload and
     475             :  * zero port. Also, addr_offset should be supported if port is set.
     476             :  */
     477           0 : static inline bool ipv4_datagram_support_addr(struct sock_exterr_skb *serr)
     478             : {
     479           0 :         return serr->ee.ee_origin == SO_EE_ORIGIN_ICMP ||
     480           0 :                serr->ee.ee_origin == SO_EE_ORIGIN_LOCAL || serr->port;
     481             : }
     482             : 
     483             : /* IPv4 supports cmsg on all imcp errors and some timestamps
     484             :  *
     485             :  * Timestamp code paths do not initialize the fields expected by cmsg:
     486             :  * the PKTINFO fields in skb->cb[]. Fill those in here.
     487             :  */
     488           0 : static bool ipv4_datagram_support_cmsg(const struct sock *sk,
     489             :                                        struct sk_buff *skb,
     490             :                                        int ee_origin)
     491             : {
     492           0 :         struct in_pktinfo *info;
     493             : 
     494           0 :         if (ee_origin == SO_EE_ORIGIN_ICMP)
     495             :                 return true;
     496             : 
     497           0 :         if (ee_origin == SO_EE_ORIGIN_LOCAL)
     498             :                 return false;
     499             : 
     500             :         /* Support IP_PKTINFO on tstamp packets if requested, to correlate
     501             :          * timestamp with egress dev. Not possible for packets without iif
     502             :          * or without payload (SOF_TIMESTAMPING_OPT_TSONLY).
     503             :          */
     504           0 :         info = PKTINFO_SKB_CB(skb);
     505           0 :         if (!(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_CMSG) ||
     506           0 :             !info->ipi_ifindex)
     507             :                 return false;
     508             : 
     509           0 :         info->ipi_spec_dst.s_addr = ip_hdr(skb)->saddr;
     510           0 :         return true;
     511             : }
     512             : 
     513             : /*
     514             :  *      Handle MSG_ERRQUEUE
     515             :  */
     516           0 : int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
     517             : {
     518           0 :         struct sock_exterr_skb *serr;
     519           0 :         struct sk_buff *skb;
     520           0 :         DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name);
     521           0 :         struct {
     522             :                 struct sock_extended_err ee;
     523             :                 struct sockaddr_in       offender;
     524             :         } errhdr;
     525           0 :         int err;
     526           0 :         int copied;
     527             : 
     528           0 :         err = -EAGAIN;
     529           0 :         skb = sock_dequeue_err_skb(sk);
     530           0 :         if (!skb)
     531           0 :                 goto out;
     532             : 
     533           0 :         copied = skb->len;
     534           0 :         if (copied > len) {
     535           0 :                 msg->msg_flags |= MSG_TRUNC;
     536           0 :                 copied = len;
     537             :         }
     538           0 :         err = skb_copy_datagram_msg(skb, 0, msg, copied);
     539           0 :         if (unlikely(err)) {
     540           0 :                 kfree_skb(skb);
     541           0 :                 return err;
     542             :         }
     543           0 :         sock_recv_timestamp(msg, sk, skb);
     544             : 
     545           0 :         serr = SKB_EXT_ERR(skb);
     546             : 
     547           0 :         if (sin && ipv4_datagram_support_addr(serr)) {
     548           0 :                 sin->sin_family = AF_INET;
     549           0 :                 sin->sin_addr.s_addr = *(__be32 *)(skb_network_header(skb) +
     550           0 :                                                    serr->addr_offset);
     551           0 :                 sin->sin_port = serr->port;
     552           0 :                 memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
     553           0 :                 *addr_len = sizeof(*sin);
     554             :         }
     555             : 
     556           0 :         memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
     557           0 :         sin = &errhdr.offender;
     558           0 :         memset(sin, 0, sizeof(*sin));
     559             : 
     560           0 :         if (ipv4_datagram_support_cmsg(sk, skb, serr->ee.ee_origin)) {
     561           0 :                 sin->sin_family = AF_INET;
     562           0 :                 sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
     563           0 :                 if (inet_sk(sk)->cmsg_flags)
     564           0 :                         ip_cmsg_recv(msg, skb);
     565             :         }
     566             : 
     567           0 :         put_cmsg(msg, SOL_IP, IP_RECVERR, sizeof(errhdr), &errhdr);
     568             : 
     569             :         /* Now we could try to dump offended packet options */
     570             : 
     571           0 :         msg->msg_flags |= MSG_ERRQUEUE;
     572           0 :         err = copied;
     573             : 
     574           0 :         consume_skb(skb);
     575             : out:
     576             :         return err;
     577             : }
     578             : 
     579           4 : static void __ip_sock_set_tos(struct sock *sk, int val)
     580             : {
     581           4 :         if (sk->sk_type == SOCK_STREAM) {
     582           4 :                 val &= ~INET_ECN_MASK;
     583           4 :                 val |= inet_sk(sk)->tos & INET_ECN_MASK;
     584             :         }
     585           4 :         if (inet_sk(sk)->tos != val) {
     586           4 :                 inet_sk(sk)->tos = val;
     587           4 :                 sk->sk_priority = rt_tos2priority(val);
     588           4 :                 sk_dst_reset(sk);
     589             :         }
     590           4 : }
     591             : 
     592           0 : void ip_sock_set_tos(struct sock *sk, int val)
     593             : {
     594           0 :         lock_sock(sk);
     595           0 :         __ip_sock_set_tos(sk, val);
     596           0 :         release_sock(sk);
     597           0 : }
     598             : EXPORT_SYMBOL(ip_sock_set_tos);
     599             : 
     600           0 : void ip_sock_set_freebind(struct sock *sk)
     601             : {
     602           0 :         lock_sock(sk);
     603           0 :         inet_sk(sk)->freebind = true;
     604           0 :         release_sock(sk);
     605           0 : }
     606             : EXPORT_SYMBOL(ip_sock_set_freebind);
     607             : 
     608           0 : void ip_sock_set_recverr(struct sock *sk)
     609             : {
     610           0 :         lock_sock(sk);
     611           0 :         inet_sk(sk)->recverr = true;
     612           0 :         release_sock(sk);
     613           0 : }
     614             : EXPORT_SYMBOL(ip_sock_set_recverr);
     615             : 
     616           0 : int ip_sock_set_mtu_discover(struct sock *sk, int val)
     617             : {
     618           0 :         if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_OMIT)
     619             :                 return -EINVAL;
     620           0 :         lock_sock(sk);
     621           0 :         inet_sk(sk)->pmtudisc = val;
     622           0 :         release_sock(sk);
     623           0 :         return 0;
     624             : }
     625             : EXPORT_SYMBOL(ip_sock_set_mtu_discover);
     626             : 
     627           0 : void ip_sock_set_pktinfo(struct sock *sk)
     628             : {
     629           0 :         lock_sock(sk);
     630           0 :         inet_sk(sk)->cmsg_flags |= IP_CMSG_PKTINFO;
     631           0 :         release_sock(sk);
     632           0 : }
     633             : EXPORT_SYMBOL(ip_sock_set_pktinfo);
     634             : 
     635             : /*
     636             :  *      Socket option code for IP. This is the end of the line after any
     637             :  *      TCP,UDP etc options on an IP socket.
     638             :  */
     639           5 : static bool setsockopt_needs_rtnl(int optname)
     640             : {
     641           5 :         switch (optname) {
     642             :         case IP_ADD_MEMBERSHIP:
     643             :         case IP_ADD_SOURCE_MEMBERSHIP:
     644             :         case IP_BLOCK_SOURCE:
     645             :         case IP_DROP_MEMBERSHIP:
     646             :         case IP_DROP_SOURCE_MEMBERSHIP:
     647             :         case IP_MSFILTER:
     648             :         case IP_UNBLOCK_SOURCE:
     649             :         case MCAST_BLOCK_SOURCE:
     650             :         case MCAST_MSFILTER:
     651             :         case MCAST_JOIN_GROUP:
     652             :         case MCAST_JOIN_SOURCE_GROUP:
     653             :         case MCAST_LEAVE_GROUP:
     654             :         case MCAST_LEAVE_SOURCE_GROUP:
     655             :         case MCAST_UNBLOCK_SOURCE:
     656             :                 return true;
     657             :         }
     658           5 :         return false;
     659             : }
     660             : 
     661           0 : static int set_mcast_msfilter(struct sock *sk, int ifindex,
     662             :                               int numsrc, int fmode,
     663             :                               struct sockaddr_storage *group,
     664             :                               struct sockaddr_storage *list)
     665             : {
     666           0 :         int msize = IP_MSFILTER_SIZE(numsrc);
     667           0 :         struct ip_msfilter *msf;
     668           0 :         struct sockaddr_in *psin;
     669           0 :         int err, i;
     670             : 
     671           0 :         msf = kmalloc(msize, GFP_KERNEL);
     672           0 :         if (!msf)
     673             :                 return -ENOBUFS;
     674             : 
     675           0 :         psin = (struct sockaddr_in *)group;
     676           0 :         if (psin->sin_family != AF_INET)
     677           0 :                 goto Eaddrnotavail;
     678           0 :         msf->imsf_multiaddr = psin->sin_addr.s_addr;
     679           0 :         msf->imsf_interface = 0;
     680           0 :         msf->imsf_fmode = fmode;
     681           0 :         msf->imsf_numsrc = numsrc;
     682           0 :         for (i = 0; i < numsrc; ++i) {
     683           0 :                 psin = (struct sockaddr_in *)&list[i];
     684             : 
     685           0 :                 if (psin->sin_family != AF_INET)
     686           0 :                         goto Eaddrnotavail;
     687           0 :                 msf->imsf_slist[i] = psin->sin_addr.s_addr;
     688             :         }
     689           0 :         err = ip_mc_msfilter(sk, msf, ifindex);
     690           0 :         kfree(msf);
     691           0 :         return err;
     692             : 
     693           0 : Eaddrnotavail:
     694           0 :         kfree(msf);
     695           0 :         return -EADDRNOTAVAIL;
     696             : }
     697             : 
     698           0 : static int copy_group_source_from_sockptr(struct group_source_req *greqs,
     699             :                 sockptr_t optval, int optlen)
     700             : {
     701           0 :         if (in_compat_syscall()) {
     702           0 :                 struct compat_group_source_req gr32;
     703             : 
     704           0 :                 if (optlen != sizeof(gr32))
     705           0 :                         return -EINVAL;
     706           0 :                 if (copy_from_sockptr(&gr32, optval, sizeof(gr32)))
     707             :                         return -EFAULT;
     708           0 :                 greqs->gsr_interface = gr32.gsr_interface;
     709           0 :                 greqs->gsr_group = gr32.gsr_group;
     710           0 :                 greqs->gsr_source = gr32.gsr_source;
     711             :         } else {
     712           0 :                 if (optlen != sizeof(*greqs))
     713             :                         return -EINVAL;
     714           0 :                 if (copy_from_sockptr(greqs, optval, sizeof(*greqs)))
     715           0 :                         return -EFAULT;
     716             :         }
     717             : 
     718             :         return 0;
     719             : }
     720             : 
     721           0 : static int do_mcast_group_source(struct sock *sk, int optname,
     722             :                 sockptr_t optval, int optlen)
     723             : {
     724           0 :         struct group_source_req greqs;
     725           0 :         struct ip_mreq_source mreqs;
     726           0 :         struct sockaddr_in *psin;
     727           0 :         int omode, add, err;
     728             : 
     729           0 :         err = copy_group_source_from_sockptr(&greqs, optval, optlen);
     730           0 :         if (err)
     731             :                 return err;
     732             : 
     733           0 :         if (greqs.gsr_group.ss_family != AF_INET ||
     734           0 :             greqs.gsr_source.ss_family != AF_INET)
     735             :                 return -EADDRNOTAVAIL;
     736             : 
     737           0 :         psin = (struct sockaddr_in *)&greqs.gsr_group;
     738           0 :         mreqs.imr_multiaddr = psin->sin_addr.s_addr;
     739           0 :         psin = (struct sockaddr_in *)&greqs.gsr_source;
     740           0 :         mreqs.imr_sourceaddr = psin->sin_addr.s_addr;
     741           0 :         mreqs.imr_interface = 0; /* use index for mc_source */
     742             : 
     743           0 :         if (optname == MCAST_BLOCK_SOURCE) {
     744             :                 omode = MCAST_EXCLUDE;
     745             :                 add = 1;
     746           0 :         } else if (optname == MCAST_UNBLOCK_SOURCE) {
     747             :                 omode = MCAST_EXCLUDE;
     748             :                 add = 0;
     749           0 :         } else if (optname == MCAST_JOIN_SOURCE_GROUP) {
     750           0 :                 struct ip_mreqn mreq;
     751             : 
     752           0 :                 psin = (struct sockaddr_in *)&greqs.gsr_group;
     753           0 :                 mreq.imr_multiaddr = psin->sin_addr;
     754           0 :                 mreq.imr_address.s_addr = 0;
     755           0 :                 mreq.imr_ifindex = greqs.gsr_interface;
     756           0 :                 err = ip_mc_join_group_ssm(sk, &mreq, MCAST_INCLUDE);
     757           0 :                 if (err && err != -EADDRINUSE)
     758           0 :                         return err;
     759           0 :                 greqs.gsr_interface = mreq.imr_ifindex;
     760           0 :                 omode = MCAST_INCLUDE;
     761           0 :                 add = 1;
     762             :         } else /* MCAST_LEAVE_SOURCE_GROUP */ {
     763             :                 omode = MCAST_INCLUDE;
     764             :                 add = 0;
     765             :         }
     766           0 :         return ip_mc_source(add, omode, sk, &mreqs, greqs.gsr_interface);
     767             : }
     768             : 
     769           0 : static int ip_set_mcast_msfilter(struct sock *sk, sockptr_t optval, int optlen)
     770             : {
     771           0 :         struct group_filter *gsf = NULL;
     772           0 :         int err;
     773             : 
     774           0 :         if (optlen < GROUP_FILTER_SIZE(0))
     775             :                 return -EINVAL;
     776           0 :         if (optlen > sysctl_optmem_max)
     777             :                 return -ENOBUFS;
     778             : 
     779           0 :         gsf = memdup_sockptr(optval, optlen);
     780           0 :         if (IS_ERR(gsf))
     781           0 :                 return PTR_ERR(gsf);
     782             : 
     783             :         /* numsrc >= (4G-140)/128 overflow in 32 bits */
     784           0 :         err = -ENOBUFS;
     785           0 :         if (gsf->gf_numsrc >= 0x1ffffff ||
     786           0 :             gsf->gf_numsrc > sock_net(sk)->ipv4.sysctl_igmp_max_msf)
     787           0 :                 goto out_free_gsf;
     788             : 
     789           0 :         err = -EINVAL;
     790           0 :         if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen)
     791           0 :                 goto out_free_gsf;
     792             : 
     793           0 :         err = set_mcast_msfilter(sk, gsf->gf_interface, gsf->gf_numsrc,
     794           0 :                                  gsf->gf_fmode, &gsf->gf_group, gsf->gf_slist);
     795           0 : out_free_gsf:
     796           0 :         kfree(gsf);
     797           0 :         return err;
     798             : }
     799             : 
     800           0 : static int compat_ip_set_mcast_msfilter(struct sock *sk, sockptr_t optval,
     801             :                 int optlen)
     802             : {
     803           0 :         const int size0 = offsetof(struct compat_group_filter, gf_slist);
     804           0 :         struct compat_group_filter *gf32;
     805           0 :         unsigned int n;
     806           0 :         void *p;
     807           0 :         int err;
     808             : 
     809           0 :         if (optlen < size0)
     810             :                 return -EINVAL;
     811           0 :         if (optlen > sysctl_optmem_max - 4)
     812             :                 return -ENOBUFS;
     813             : 
     814           0 :         p = kmalloc(optlen + 4, GFP_KERNEL);
     815           0 :         if (!p)
     816             :                 return -ENOMEM;
     817           0 :         gf32 = p + 4; /* we want ->gf_group and ->gf_slist aligned */
     818             : 
     819           0 :         err = -EFAULT;
     820           0 :         if (copy_from_sockptr(gf32, optval, optlen))
     821           0 :                 goto out_free_gsf;
     822             : 
     823             :         /* numsrc >= (4G-140)/128 overflow in 32 bits */
     824           0 :         n = gf32->gf_numsrc;
     825           0 :         err = -ENOBUFS;
     826           0 :         if (n >= 0x1ffffff)
     827           0 :                 goto out_free_gsf;
     828             : 
     829           0 :         err = -EINVAL;
     830           0 :         if (offsetof(struct compat_group_filter, gf_slist[n]) > optlen)
     831           0 :                 goto out_free_gsf;
     832             : 
     833             :         /* numsrc >= (4G-140)/128 overflow in 32 bits */
     834           0 :         err = -ENOBUFS;
     835           0 :         if (n > sock_net(sk)->ipv4.sysctl_igmp_max_msf)
     836           0 :                 goto out_free_gsf;
     837           0 :         err = set_mcast_msfilter(sk, gf32->gf_interface, n, gf32->gf_fmode,
     838           0 :                                  &gf32->gf_group, gf32->gf_slist);
     839           0 : out_free_gsf:
     840           0 :         kfree(p);
     841           0 :         return err;
     842             : }
     843             : 
     844           0 : static int ip_mcast_join_leave(struct sock *sk, int optname,
     845             :                 sockptr_t optval, int optlen)
     846             : {
     847           0 :         struct ip_mreqn mreq = { };
     848           0 :         struct sockaddr_in *psin;
     849           0 :         struct group_req greq;
     850             : 
     851           0 :         if (optlen < sizeof(struct group_req))
     852             :                 return -EINVAL;
     853           0 :         if (copy_from_sockptr(&greq, optval, sizeof(greq)))
     854             :                 return -EFAULT;
     855             : 
     856           0 :         psin = (struct sockaddr_in *)&greq.gr_group;
     857           0 :         if (psin->sin_family != AF_INET)
     858             :                 return -EINVAL;
     859           0 :         mreq.imr_multiaddr = psin->sin_addr;
     860           0 :         mreq.imr_ifindex = greq.gr_interface;
     861           0 :         if (optname == MCAST_JOIN_GROUP)
     862           0 :                 return ip_mc_join_group(sk, &mreq);
     863           0 :         return ip_mc_leave_group(sk, &mreq);
     864             : }
     865             : 
     866           0 : static int compat_ip_mcast_join_leave(struct sock *sk, int optname,
     867             :                 sockptr_t optval, int optlen)
     868             : {
     869           0 :         struct compat_group_req greq;
     870           0 :         struct ip_mreqn mreq = { };
     871           0 :         struct sockaddr_in *psin;
     872             : 
     873           0 :         if (optlen < sizeof(struct compat_group_req))
     874             :                 return -EINVAL;
     875           0 :         if (copy_from_sockptr(&greq, optval, sizeof(greq)))
     876             :                 return -EFAULT;
     877             : 
     878           0 :         psin = (struct sockaddr_in *)&greq.gr_group;
     879           0 :         if (psin->sin_family != AF_INET)
     880             :                 return -EINVAL;
     881           0 :         mreq.imr_multiaddr = psin->sin_addr;
     882           0 :         mreq.imr_ifindex = greq.gr_interface;
     883             : 
     884           0 :         if (optname == MCAST_JOIN_GROUP)
     885           0 :                 return ip_mc_join_group(sk, &mreq);
     886           0 :         return ip_mc_leave_group(sk, &mreq);
     887             : }
     888             : 
     889           5 : static int do_ip_setsockopt(struct sock *sk, int level, int optname,
     890             :                 sockptr_t optval, unsigned int optlen)
     891             : {
     892           5 :         struct inet_sock *inet = inet_sk(sk);
     893           5 :         struct net *net = sock_net(sk);
     894           5 :         int val = 0, err;
     895           5 :         bool needs_rtnl = setsockopt_needs_rtnl(optname);
     896             : 
     897           5 :         switch (optname) {
     898           5 :         case IP_PKTINFO:
     899             :         case IP_RECVTTL:
     900             :         case IP_RECVOPTS:
     901             :         case IP_RECVTOS:
     902             :         case IP_RETOPTS:
     903             :         case IP_TOS:
     904             :         case IP_TTL:
     905             :         case IP_HDRINCL:
     906             :         case IP_MTU_DISCOVER:
     907             :         case IP_RECVERR:
     908             :         case IP_ROUTER_ALERT:
     909             :         case IP_FREEBIND:
     910             :         case IP_PASSSEC:
     911             :         case IP_TRANSPARENT:
     912             :         case IP_MINTTL:
     913             :         case IP_NODEFRAG:
     914             :         case IP_BIND_ADDRESS_NO_PORT:
     915             :         case IP_UNICAST_IF:
     916             :         case IP_MULTICAST_TTL:
     917             :         case IP_MULTICAST_ALL:
     918             :         case IP_MULTICAST_LOOP:
     919             :         case IP_RECVORIGDSTADDR:
     920             :         case IP_CHECKSUM:
     921             :         case IP_RECVFRAGSIZE:
     922             :         case IP_RECVERR_RFC4884:
     923           5 :                 if (optlen >= sizeof(int)) {
     924           5 :                         if (copy_from_sockptr(&val, optval, sizeof(val)))
     925             :                                 return -EFAULT;
     926           0 :                 } else if (optlen >= sizeof(char)) {
     927           0 :                         unsigned char ucval;
     928             : 
     929           0 :                         if (copy_from_sockptr(&ucval, optval, sizeof(ucval)))
     930           0 :                                 return -EFAULT;
     931           0 :                         val = (int) ucval;
     932             :                 }
     933             :         }
     934             : 
     935             :         /* If optlen==0, it is equivalent to val == 0 */
     936             : 
     937           5 :         if (optname == IP_ROUTER_ALERT)
     938           0 :                 return ip_ra_control(sk, val ? 1 : 0, NULL);
     939           5 :         if (ip_mroute_opt(optname))
     940             :                 return ip_mroute_setsockopt(sk, optname, optval, optlen);
     941             : 
     942           5 :         err = 0;
     943           5 :         if (needs_rtnl)
     944           0 :                 rtnl_lock();
     945           5 :         lock_sock(sk);
     946             : 
     947           5 :         switch (optname) {
     948           0 :         case IP_OPTIONS:
     949             :         {
     950           0 :                 struct ip_options_rcu *old, *opt = NULL;
     951             : 
     952           0 :                 if (optlen > 40)
     953           0 :                         goto e_inval;
     954           0 :                 err = ip_options_get(sock_net(sk), &opt, optval, optlen);
     955           0 :                 if (err)
     956             :                         break;
     957           0 :                 old = rcu_dereference_protected(inet->inet_opt,
     958             :                                                 lockdep_sock_is_held(sk));
     959           0 :                 if (inet->is_icsk) {
     960           0 :                         struct inet_connection_sock *icsk = inet_csk(sk);
     961             : #if IS_ENABLED(CONFIG_IPV6)
     962             :                         if (sk->sk_family == PF_INET ||
     963             :                             (!((1 << sk->sk_state) &
     964             :                                (TCPF_LISTEN | TCPF_CLOSE)) &&
     965             :                              inet->inet_daddr != LOOPBACK4_IPV6)) {
     966             : #endif
     967           0 :                                 if (old)
     968           0 :                                         icsk->icsk_ext_hdr_len -= old->opt.optlen;
     969           0 :                                 if (opt)
     970           0 :                                         icsk->icsk_ext_hdr_len += opt->opt.optlen;
     971           0 :                                 icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
     972             : #if IS_ENABLED(CONFIG_IPV6)
     973             :                         }
     974             : #endif
     975             :                 }
     976           0 :                 rcu_assign_pointer(inet->inet_opt, opt);
     977           0 :                 if (old)
     978           0 :                         kfree_rcu(old, rcu);
     979             :                 break;
     980             :         }
     981           1 :         case IP_PKTINFO:
     982           1 :                 if (val)
     983           1 :                         inet->cmsg_flags |= IP_CMSG_PKTINFO;
     984             :                 else
     985           0 :                         inet->cmsg_flags &= ~IP_CMSG_PKTINFO;
     986             :                 break;
     987           0 :         case IP_RECVTTL:
     988           0 :                 if (val)
     989           0 :                         inet->cmsg_flags |=  IP_CMSG_TTL;
     990             :                 else
     991           0 :                         inet->cmsg_flags &= ~IP_CMSG_TTL;
     992             :                 break;
     993           0 :         case IP_RECVTOS:
     994           0 :                 if (val)
     995           0 :                         inet->cmsg_flags |=  IP_CMSG_TOS;
     996             :                 else
     997           0 :                         inet->cmsg_flags &= ~IP_CMSG_TOS;
     998             :                 break;
     999           0 :         case IP_RECVOPTS:
    1000           0 :                 if (val)
    1001           0 :                         inet->cmsg_flags |=  IP_CMSG_RECVOPTS;
    1002             :                 else
    1003           0 :                         inet->cmsg_flags &= ~IP_CMSG_RECVOPTS;
    1004             :                 break;
    1005           0 :         case IP_RETOPTS:
    1006           0 :                 if (val)
    1007           0 :                         inet->cmsg_flags |= IP_CMSG_RETOPTS;
    1008             :                 else
    1009           0 :                         inet->cmsg_flags &= ~IP_CMSG_RETOPTS;
    1010             :                 break;
    1011           0 :         case IP_PASSSEC:
    1012           0 :                 if (val)
    1013           0 :                         inet->cmsg_flags |= IP_CMSG_PASSSEC;
    1014             :                 else
    1015           0 :                         inet->cmsg_flags &= ~IP_CMSG_PASSSEC;
    1016             :                 break;
    1017           0 :         case IP_RECVORIGDSTADDR:
    1018           0 :                 if (val)
    1019           0 :                         inet->cmsg_flags |= IP_CMSG_ORIGDSTADDR;
    1020             :                 else
    1021           0 :                         inet->cmsg_flags &= ~IP_CMSG_ORIGDSTADDR;
    1022             :                 break;
    1023           0 :         case IP_CHECKSUM:
    1024           0 :                 if (val) {
    1025           0 :                         if (!(inet->cmsg_flags & IP_CMSG_CHECKSUM)) {
    1026           0 :                                 inet_inc_convert_csum(sk);
    1027           0 :                                 inet->cmsg_flags |= IP_CMSG_CHECKSUM;
    1028             :                         }
    1029             :                 } else {
    1030           0 :                         if (inet->cmsg_flags & IP_CMSG_CHECKSUM) {
    1031           0 :                                 inet_dec_convert_csum(sk);
    1032           0 :                                 inet->cmsg_flags &= ~IP_CMSG_CHECKSUM;
    1033             :                         }
    1034             :                 }
    1035             :                 break;
    1036           0 :         case IP_RECVFRAGSIZE:
    1037           0 :                 if (sk->sk_type != SOCK_RAW && sk->sk_type != SOCK_DGRAM)
    1038           0 :                         goto e_inval;
    1039           0 :                 if (val)
    1040           0 :                         inet->cmsg_flags |= IP_CMSG_RECVFRAGSIZE;
    1041             :                 else
    1042           0 :                         inet->cmsg_flags &= ~IP_CMSG_RECVFRAGSIZE;
    1043             :                 break;
    1044           4 :         case IP_TOS:    /* This sets both TOS and Precedence */
    1045           4 :                 __ip_sock_set_tos(sk, val);
    1046           4 :                 break;
    1047           0 :         case IP_TTL:
    1048           0 :                 if (optlen < 1)
    1049           0 :                         goto e_inval;
    1050           0 :                 if (val != -1 && (val < 1 || val > 255))
    1051           0 :                         goto e_inval;
    1052           0 :                 inet->uc_ttl = val;
    1053           0 :                 break;
    1054           0 :         case IP_HDRINCL:
    1055           0 :                 if (sk->sk_type != SOCK_RAW) {
    1056             :                         err = -ENOPROTOOPT;
    1057             :                         break;
    1058             :                 }
    1059           0 :                 inet->hdrincl = val ? 1 : 0;
    1060           0 :                 break;
    1061           0 :         case IP_NODEFRAG:
    1062           0 :                 if (sk->sk_type != SOCK_RAW) {
    1063             :                         err = -ENOPROTOOPT;
    1064             :                         break;
    1065             :                 }
    1066           0 :                 inet->nodefrag = val ? 1 : 0;
    1067           0 :                 break;
    1068           0 :         case IP_BIND_ADDRESS_NO_PORT:
    1069           0 :                 inet->bind_address_no_port = val ? 1 : 0;
    1070           0 :                 break;
    1071           0 :         case IP_MTU_DISCOVER:
    1072           0 :                 if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_OMIT)
    1073           0 :                         goto e_inval;
    1074           0 :                 inet->pmtudisc = val;
    1075           0 :                 break;
    1076           0 :         case IP_RECVERR:
    1077           0 :                 inet->recverr = !!val;
    1078           0 :                 if (!val)
    1079           0 :                         skb_queue_purge(&sk->sk_error_queue);
    1080             :                 break;
    1081           0 :         case IP_RECVERR_RFC4884:
    1082           0 :                 if (val < 0 || val > 1)
    1083           0 :                         goto e_inval;
    1084           0 :                 inet->recverr_rfc4884 = !!val;
    1085           0 :                 break;
    1086           0 :         case IP_MULTICAST_TTL:
    1087           0 :                 if (sk->sk_type == SOCK_STREAM)
    1088           0 :                         goto e_inval;
    1089           0 :                 if (optlen < 1)
    1090           0 :                         goto e_inval;
    1091           0 :                 if (val == -1)
    1092           0 :                         val = 1;
    1093           0 :                 if (val < 0 || val > 255)
    1094           0 :                         goto e_inval;
    1095           0 :                 inet->mc_ttl = val;
    1096           0 :                 break;
    1097           0 :         case IP_MULTICAST_LOOP:
    1098           0 :                 if (optlen < 1)
    1099           0 :                         goto e_inval;
    1100           0 :                 inet->mc_loop = !!val;
    1101           0 :                 break;
    1102           0 :         case IP_UNICAST_IF:
    1103             :         {
    1104           0 :                 struct net_device *dev = NULL;
    1105           0 :                 int ifindex;
    1106           0 :                 int midx;
    1107             : 
    1108           0 :                 if (optlen != sizeof(int))
    1109           0 :                         goto e_inval;
    1110             : 
    1111           0 :                 ifindex = (__force int)ntohl((__force __be32)val);
    1112           0 :                 if (ifindex == 0) {
    1113           0 :                         inet->uc_index = 0;
    1114           0 :                         err = 0;
    1115           0 :                         break;
    1116             :                 }
    1117             : 
    1118           0 :                 dev = dev_get_by_index(sock_net(sk), ifindex);
    1119           0 :                 err = -EADDRNOTAVAIL;
    1120           0 :                 if (!dev)
    1121             :                         break;
    1122             : 
    1123           0 :                 midx = l3mdev_master_ifindex(dev);
    1124           0 :                 dev_put(dev);
    1125             : 
    1126           0 :                 err = -EINVAL;
    1127           0 :                 if (sk->sk_bound_dev_if && midx != sk->sk_bound_dev_if)
    1128             :                         break;
    1129             : 
    1130           0 :                 inet->uc_index = ifindex;
    1131           0 :                 err = 0;
    1132           0 :                 break;
    1133             :         }
    1134           0 :         case IP_MULTICAST_IF:
    1135             :         {
    1136           0 :                 struct ip_mreqn mreq;
    1137           0 :                 struct net_device *dev = NULL;
    1138           0 :                 int midx;
    1139             : 
    1140           0 :                 if (sk->sk_type == SOCK_STREAM)
    1141           0 :                         goto e_inval;
    1142             :                 /*
    1143             :                  *      Check the arguments are allowable
    1144             :                  */
    1145             : 
    1146           0 :                 if (optlen < sizeof(struct in_addr))
    1147           0 :                         goto e_inval;
    1148             : 
    1149           0 :                 err = -EFAULT;
    1150           0 :                 if (optlen >= sizeof(struct ip_mreqn)) {
    1151           0 :                         if (copy_from_sockptr(&mreq, optval, sizeof(mreq)))
    1152             :                                 break;
    1153             :                 } else {
    1154           0 :                         memset(&mreq, 0, sizeof(mreq));
    1155           0 :                         if (optlen >= sizeof(struct ip_mreq)) {
    1156           0 :                                 if (copy_from_sockptr(&mreq, optval,
    1157             :                                                       sizeof(struct ip_mreq)))
    1158             :                                         break;
    1159           0 :                         } else if (optlen >= sizeof(struct in_addr)) {
    1160           0 :                                 if (copy_from_sockptr(&mreq.imr_address, optval,
    1161             :                                                       sizeof(struct in_addr)))
    1162             :                                         break;
    1163             :                         }
    1164             :                 }
    1165             : 
    1166           0 :                 if (!mreq.imr_ifindex) {
    1167           0 :                         if (mreq.imr_address.s_addr == htonl(INADDR_ANY)) {
    1168           0 :                                 inet->mc_index = 0;
    1169           0 :                                 inet->mc_addr  = 0;
    1170           0 :                                 err = 0;
    1171           0 :                                 break;
    1172             :                         }
    1173           0 :                         dev = ip_dev_find(sock_net(sk), mreq.imr_address.s_addr);
    1174           0 :                         if (dev)
    1175           0 :                                 mreq.imr_ifindex = dev->ifindex;
    1176             :                 } else
    1177           0 :                         dev = dev_get_by_index(sock_net(sk), mreq.imr_ifindex);
    1178             : 
    1179             : 
    1180           0 :                 err = -EADDRNOTAVAIL;
    1181           0 :                 if (!dev)
    1182             :                         break;
    1183             : 
    1184           0 :                 midx = l3mdev_master_ifindex(dev);
    1185             : 
    1186           0 :                 dev_put(dev);
    1187             : 
    1188           0 :                 err = -EINVAL;
    1189           0 :                 if (sk->sk_bound_dev_if &&
    1190           0 :                     mreq.imr_ifindex != sk->sk_bound_dev_if &&
    1191             :                     midx != sk->sk_bound_dev_if)
    1192             :                         break;
    1193             : 
    1194           0 :                 inet->mc_index = mreq.imr_ifindex;
    1195           0 :                 inet->mc_addr  = mreq.imr_address.s_addr;
    1196           0 :                 err = 0;
    1197           0 :                 break;
    1198             :         }
    1199             : 
    1200           0 :         case IP_ADD_MEMBERSHIP:
    1201             :         case IP_DROP_MEMBERSHIP:
    1202             :         {
    1203           0 :                 struct ip_mreqn mreq;
    1204             : 
    1205           0 :                 err = -EPROTO;
    1206           0 :                 if (inet_sk(sk)->is_icsk)
    1207             :                         break;
    1208             : 
    1209           0 :                 if (optlen < sizeof(struct ip_mreq))
    1210           0 :                         goto e_inval;
    1211           0 :                 err = -EFAULT;
    1212           0 :                 if (optlen >= sizeof(struct ip_mreqn)) {
    1213           0 :                         if (copy_from_sockptr(&mreq, optval, sizeof(mreq)))
    1214             :                                 break;
    1215             :                 } else {
    1216           0 :                         memset(&mreq, 0, sizeof(mreq));
    1217           0 :                         if (copy_from_sockptr(&mreq, optval,
    1218             :                                               sizeof(struct ip_mreq)))
    1219             :                                 break;
    1220             :                 }
    1221             : 
    1222           0 :                 if (optname == IP_ADD_MEMBERSHIP)
    1223           0 :                         err = ip_mc_join_group(sk, &mreq);
    1224             :                 else
    1225           0 :                         err = ip_mc_leave_group(sk, &mreq);
    1226             :                 break;
    1227             :         }
    1228           0 :         case IP_MSFILTER:
    1229             :         {
    1230           0 :                 struct ip_msfilter *msf;
    1231             : 
    1232           0 :                 if (optlen < IP_MSFILTER_SIZE(0))
    1233           0 :                         goto e_inval;
    1234           0 :                 if (optlen > sysctl_optmem_max) {
    1235             :                         err = -ENOBUFS;
    1236             :                         break;
    1237             :                 }
    1238           0 :                 msf = memdup_sockptr(optval, optlen);
    1239           0 :                 if (IS_ERR(msf)) {
    1240           0 :                         err = PTR_ERR(msf);
    1241           0 :                         break;
    1242             :                 }
    1243             :                 /* numsrc >= (1G-4) overflow in 32 bits */
    1244           0 :                 if (msf->imsf_numsrc >= 0x3ffffffcU ||
    1245           0 :                     msf->imsf_numsrc > net->ipv4.sysctl_igmp_max_msf) {
    1246           0 :                         kfree(msf);
    1247           0 :                         err = -ENOBUFS;
    1248           0 :                         break;
    1249             :                 }
    1250           0 :                 if (IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) {
    1251           0 :                         kfree(msf);
    1252           0 :                         err = -EINVAL;
    1253           0 :                         break;
    1254             :                 }
    1255           0 :                 err = ip_mc_msfilter(sk, msf, 0);
    1256           0 :                 kfree(msf);
    1257           0 :                 break;
    1258             :         }
    1259           0 :         case IP_BLOCK_SOURCE:
    1260             :         case IP_UNBLOCK_SOURCE:
    1261             :         case IP_ADD_SOURCE_MEMBERSHIP:
    1262             :         case IP_DROP_SOURCE_MEMBERSHIP:
    1263             :         {
    1264           0 :                 struct ip_mreq_source mreqs;
    1265           0 :                 int omode, add;
    1266             : 
    1267           0 :                 if (optlen != sizeof(struct ip_mreq_source))
    1268           0 :                         goto e_inval;
    1269           0 :                 if (copy_from_sockptr(&mreqs, optval, sizeof(mreqs))) {
    1270             :                         err = -EFAULT;
    1271           0 :                         break;
    1272             :                 }
    1273           0 :                 if (optname == IP_BLOCK_SOURCE) {
    1274             :                         omode = MCAST_EXCLUDE;
    1275             :                         add = 1;
    1276           0 :                 } else if (optname == IP_UNBLOCK_SOURCE) {
    1277             :                         omode = MCAST_EXCLUDE;
    1278             :                         add = 0;
    1279           0 :                 } else if (optname == IP_ADD_SOURCE_MEMBERSHIP) {
    1280           0 :                         struct ip_mreqn mreq;
    1281             : 
    1282           0 :                         mreq.imr_multiaddr.s_addr = mreqs.imr_multiaddr;
    1283           0 :                         mreq.imr_address.s_addr = mreqs.imr_interface;
    1284           0 :                         mreq.imr_ifindex = 0;
    1285           0 :                         err = ip_mc_join_group_ssm(sk, &mreq, MCAST_INCLUDE);
    1286           0 :                         if (err && err != -EADDRINUSE)
    1287             :                                 break;
    1288           0 :                         omode = MCAST_INCLUDE;
    1289           0 :                         add = 1;
    1290             :                 } else /* IP_DROP_SOURCE_MEMBERSHIP */ {
    1291             :                         omode = MCAST_INCLUDE;
    1292             :                         add = 0;
    1293             :                 }
    1294           0 :                 err = ip_mc_source(add, omode, sk, &mreqs, 0);
    1295           0 :                 break;
    1296             :         }
    1297             :         case MCAST_JOIN_GROUP:
    1298             :         case MCAST_LEAVE_GROUP:
    1299           0 :                 if (in_compat_syscall())
    1300           0 :                         err = compat_ip_mcast_join_leave(sk, optname, optval,
    1301             :                                                          optlen);
    1302             :                 else
    1303           0 :                         err = ip_mcast_join_leave(sk, optname, optval, optlen);
    1304             :                 break;
    1305           0 :         case MCAST_JOIN_SOURCE_GROUP:
    1306             :         case MCAST_LEAVE_SOURCE_GROUP:
    1307             :         case MCAST_BLOCK_SOURCE:
    1308             :         case MCAST_UNBLOCK_SOURCE:
    1309           0 :                 err = do_mcast_group_source(sk, optname, optval, optlen);
    1310           0 :                 break;
    1311             :         case MCAST_MSFILTER:
    1312           0 :                 if (in_compat_syscall())
    1313           0 :                         err = compat_ip_set_mcast_msfilter(sk, optval, optlen);
    1314             :                 else
    1315           0 :                         err = ip_set_mcast_msfilter(sk, optval, optlen);
    1316             :                 break;
    1317           0 :         case IP_MULTICAST_ALL:
    1318           0 :                 if (optlen < 1)
    1319           0 :                         goto e_inval;
    1320           0 :                 if (val != 0 && val != 1)
    1321           0 :                         goto e_inval;
    1322           0 :                 inet->mc_all = val;
    1323           0 :                 break;
    1324             : 
    1325           0 :         case IP_FREEBIND:
    1326           0 :                 if (optlen < 1)
    1327           0 :                         goto e_inval;
    1328           0 :                 inet->freebind = !!val;
    1329           0 :                 break;
    1330             : 
    1331           0 :         case IP_IPSEC_POLICY:
    1332             :         case IP_XFRM_POLICY:
    1333           0 :                 err = -EPERM;
    1334           0 :                 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
    1335             :                         break;
    1336           0 :                 err = xfrm_user_policy(sk, optname, optval, optlen);
    1337           0 :                 break;
    1338             : 
    1339           0 :         case IP_TRANSPARENT:
    1340           0 :                 if (!!val && !ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) &&
    1341           0 :                     !ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
    1342             :                         err = -EPERM;
    1343             :                         break;
    1344             :                 }
    1345           0 :                 if (optlen < 1)
    1346           0 :                         goto e_inval;
    1347           0 :                 inet->transparent = !!val;
    1348           0 :                 break;
    1349             : 
    1350           0 :         case IP_MINTTL:
    1351           0 :                 if (optlen < 1)
    1352           0 :                         goto e_inval;
    1353           0 :                 if (val < 0 || val > 255)
    1354           0 :                         goto e_inval;
    1355           0 :                 inet->min_ttl = val;
    1356           0 :                 break;
    1357             : 
    1358             :         default:
    1359             :                 err = -ENOPROTOOPT;
    1360             :                 break;
    1361             :         }
    1362           5 :         release_sock(sk);
    1363           5 :         if (needs_rtnl)
    1364           0 :                 rtnl_unlock();
    1365             :         return err;
    1366             : 
    1367           0 : e_inval:
    1368           0 :         release_sock(sk);
    1369           0 :         if (needs_rtnl)
    1370           0 :                 rtnl_unlock();
    1371             :         return -EINVAL;
    1372             : }
    1373             : 
    1374             : /**
    1375             :  * ipv4_pktinfo_prepare - transfer some info from rtable to skb
    1376             :  * @sk: socket
    1377             :  * @skb: buffer
    1378             :  *
    1379             :  * To support IP_CMSG_PKTINFO option, we store rt_iif and specific
    1380             :  * destination in skb->cb[] before dst drop.
    1381             :  * This way, receiver doesn't make cache line misses to read rtable.
    1382             :  */
    1383           2 : void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb)
    1384             : {
    1385           2 :         struct in_pktinfo *pktinfo = PKTINFO_SKB_CB(skb);
    1386           2 :         bool prepare = (inet_sk(sk)->cmsg_flags & IP_CMSG_PKTINFO) ||
    1387             :                        ipv6_sk_rxinfo(sk);
    1388             : 
    1389           2 :         if (prepare && skb_rtable(skb)) {
    1390             :                 /* skb->cb is overloaded: prior to this point it is IP{6}CB
    1391             :                  * which has interface index (iif) as the first member of the
    1392             :                  * underlying inet{6}_skb_parm struct. This code then overlays
    1393             :                  * PKTINFO_SKB_CB and in_pktinfo also has iif as the first
    1394             :                  * element so the iif is picked up from the prior IPCB. If iif
    1395             :                  * is the loopback interface, then return the sending interface
    1396             :                  * (e.g., process binds socket to eth0 for Tx which is
    1397             :                  * redirected to loopback in the rtable/dst).
    1398             :                  */
    1399           0 :                 struct rtable *rt = skb_rtable(skb);
    1400           0 :                 bool l3slave = ipv4_l3mdev_skb(IPCB(skb)->flags);
    1401             : 
    1402           0 :                 if (pktinfo->ipi_ifindex == LOOPBACK_IFINDEX)
    1403           0 :                         pktinfo->ipi_ifindex = inet_iif(skb);
    1404           0 :                 else if (l3slave && rt && rt->rt_iif)
    1405           0 :                         pktinfo->ipi_ifindex = rt->rt_iif;
    1406             : 
    1407           0 :                 pktinfo->ipi_spec_dst.s_addr = fib_compute_spec_dst(skb);
    1408             :         } else {
    1409           2 :                 pktinfo->ipi_ifindex = 0;
    1410           2 :                 pktinfo->ipi_spec_dst.s_addr = 0;
    1411             :         }
    1412           2 :         skb_dst_drop(skb);
    1413           2 : }
    1414             : 
    1415           5 : int ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
    1416             :                 unsigned int optlen)
    1417             : {
    1418           5 :         int err;
    1419             : 
    1420           5 :         if (level != SOL_IP)
    1421             :                 return -ENOPROTOOPT;
    1422             : 
    1423           5 :         err = do_ip_setsockopt(sk, level, optname, optval, optlen);
    1424             : #if IS_ENABLED(CONFIG_BPFILTER_UMH)
    1425             :         if (optname >= BPFILTER_IPT_SO_SET_REPLACE &&
    1426             :             optname < BPFILTER_IPT_SET_MAX)
    1427             :                 err = bpfilter_ip_set_sockopt(sk, optname, optval, optlen);
    1428             : #endif
    1429             : #ifdef CONFIG_NETFILTER
    1430             :         /* we need to exclude all possible ENOPROTOOPTs except default case */
    1431           5 :         if (err == -ENOPROTOOPT && optname != IP_HDRINCL &&
    1432           0 :                         optname != IP_IPSEC_POLICY &&
    1433             :                         optname != IP_XFRM_POLICY &&
    1434           0 :                         !ip_mroute_opt(optname))
    1435           0 :                 err = nf_setsockopt(sk, PF_INET, optname, optval, optlen);
    1436             : #endif
    1437             :         return err;
    1438             : }
    1439             : EXPORT_SYMBOL(ip_setsockopt);
    1440             : 
    1441             : /*
    1442             :  *      Get the options. Note for future reference. The GET of IP options gets
    1443             :  *      the _received_ ones. The set sets the _sent_ ones.
    1444             :  */
    1445             : 
    1446           4 : static bool getsockopt_needs_rtnl(int optname)
    1447             : {
    1448           4 :         switch (optname) {
    1449             :         case IP_MSFILTER:
    1450             :         case MCAST_MSFILTER:
    1451             :                 return true;
    1452             :         }
    1453           4 :         return false;
    1454             : }
    1455             : 
    1456           0 : static int ip_get_mcast_msfilter(struct sock *sk, void __user *optval,
    1457             :                 int __user *optlen, int len)
    1458             : {
    1459           0 :         const int size0 = offsetof(struct group_filter, gf_slist);
    1460           0 :         struct group_filter __user *p = optval;
    1461           0 :         struct group_filter gsf;
    1462           0 :         int num;
    1463           0 :         int err;
    1464             : 
    1465           0 :         if (len < size0)
    1466             :                 return -EINVAL;
    1467           0 :         if (copy_from_user(&gsf, p, size0))
    1468             :                 return -EFAULT;
    1469             : 
    1470           0 :         num = gsf.gf_numsrc;
    1471           0 :         err = ip_mc_gsfget(sk, &gsf, p->gf_slist);
    1472           0 :         if (err)
    1473             :                 return err;
    1474           0 :         if (gsf.gf_numsrc < num)
    1475             :                 num = gsf.gf_numsrc;
    1476           0 :         if (put_user(GROUP_FILTER_SIZE(num), optlen) ||
    1477           0 :             copy_to_user(p, &gsf, size0))
    1478           0 :                 return -EFAULT;
    1479             :         return 0;
    1480             : }
    1481             : 
    1482           0 : static int compat_ip_get_mcast_msfilter(struct sock *sk, void __user *optval,
    1483             :                 int __user *optlen, int len)
    1484             : {
    1485           0 :         const int size0 = offsetof(struct compat_group_filter, gf_slist);
    1486           0 :         struct compat_group_filter __user *p = optval;
    1487           0 :         struct compat_group_filter gf32;
    1488           0 :         struct group_filter gf;
    1489           0 :         int num;
    1490           0 :         int err;
    1491             : 
    1492           0 :         if (len < size0)
    1493             :                 return -EINVAL;
    1494           0 :         if (copy_from_user(&gf32, p, size0))
    1495             :                 return -EFAULT;
    1496             : 
    1497           0 :         gf.gf_interface = gf32.gf_interface;
    1498           0 :         gf.gf_fmode = gf32.gf_fmode;
    1499           0 :         num = gf.gf_numsrc = gf32.gf_numsrc;
    1500           0 :         gf.gf_group = gf32.gf_group;
    1501             : 
    1502           0 :         err = ip_mc_gsfget(sk, &gf, p->gf_slist);
    1503           0 :         if (err)
    1504             :                 return err;
    1505           0 :         if (gf.gf_numsrc < num)
    1506             :                 num = gf.gf_numsrc;
    1507           0 :         len = GROUP_FILTER_SIZE(num) - (sizeof(gf) - sizeof(gf32));
    1508           0 :         if (put_user(len, optlen) ||
    1509           0 :             put_user(gf.gf_fmode, &p->gf_fmode) ||
    1510           0 :             put_user(gf.gf_numsrc, &p->gf_numsrc))
    1511           0 :                 return -EFAULT;
    1512             :         return 0;
    1513             : }
    1514             : 
    1515           4 : static int do_ip_getsockopt(struct sock *sk, int level, int optname,
    1516             :                             char __user *optval, int __user *optlen)
    1517             : {
    1518           4 :         struct inet_sock *inet = inet_sk(sk);
    1519           4 :         bool needs_rtnl = getsockopt_needs_rtnl(optname);
    1520           4 :         int val, err = 0;
    1521           4 :         int len;
    1522             : 
    1523           4 :         if (level != SOL_IP)
    1524             :                 return -EOPNOTSUPP;
    1525             : 
    1526           4 :         if (ip_mroute_opt(optname))
    1527             :                 return ip_mroute_getsockopt(sk, optname, optval, optlen);
    1528             : 
    1529           4 :         if (get_user(len, optlen))
    1530             :                 return -EFAULT;
    1531           4 :         if (len < 0)
    1532             :                 return -EINVAL;
    1533             : 
    1534           4 :         if (needs_rtnl)
    1535           0 :                 rtnl_lock();
    1536           4 :         lock_sock(sk);
    1537             : 
    1538           4 :         switch (optname) {
    1539           4 :         case IP_OPTIONS:
    1540             :         {
    1541           4 :                 unsigned char optbuf[sizeof(struct ip_options)+40];
    1542           4 :                 struct ip_options *opt = (struct ip_options *)optbuf;
    1543           4 :                 struct ip_options_rcu *inet_opt;
    1544             : 
    1545           4 :                 inet_opt = rcu_dereference_protected(inet->inet_opt,
    1546             :                                                      lockdep_sock_is_held(sk));
    1547           4 :                 opt->optlen = 0;
    1548           4 :                 if (inet_opt)
    1549           0 :                         memcpy(optbuf, &inet_opt->opt,
    1550             :                                sizeof(struct ip_options) +
    1551           0 :                                inet_opt->opt.optlen);
    1552           4 :                 release_sock(sk);
    1553             : 
    1554           4 :                 if (opt->optlen == 0)
    1555           4 :                         return put_user(0, optlen);
    1556             : 
    1557           0 :                 ip_options_undo(opt);
    1558             : 
    1559           0 :                 len = min_t(unsigned int, len, opt->optlen);
    1560           0 :                 if (put_user(len, optlen))
    1561             :                         return -EFAULT;
    1562           0 :                 if (copy_to_user(optval, opt->__data, len))
    1563           0 :                         return -EFAULT;
    1564             :                 return 0;
    1565             :         }
    1566           0 :         case IP_PKTINFO:
    1567           0 :                 val = (inet->cmsg_flags & IP_CMSG_PKTINFO) != 0;
    1568           0 :                 break;
    1569           0 :         case IP_RECVTTL:
    1570           0 :                 val = (inet->cmsg_flags & IP_CMSG_TTL) != 0;
    1571           0 :                 break;
    1572           0 :         case IP_RECVTOS:
    1573           0 :                 val = (inet->cmsg_flags & IP_CMSG_TOS) != 0;
    1574           0 :                 break;
    1575           0 :         case IP_RECVOPTS:
    1576           0 :                 val = (inet->cmsg_flags & IP_CMSG_RECVOPTS) != 0;
    1577           0 :                 break;
    1578           0 :         case IP_RETOPTS:
    1579           0 :                 val = (inet->cmsg_flags & IP_CMSG_RETOPTS) != 0;
    1580           0 :                 break;
    1581           0 :         case IP_PASSSEC:
    1582           0 :                 val = (inet->cmsg_flags & IP_CMSG_PASSSEC) != 0;
    1583           0 :                 break;
    1584           0 :         case IP_RECVORIGDSTADDR:
    1585           0 :                 val = (inet->cmsg_flags & IP_CMSG_ORIGDSTADDR) != 0;
    1586           0 :                 break;
    1587           0 :         case IP_CHECKSUM:
    1588           0 :                 val = (inet->cmsg_flags & IP_CMSG_CHECKSUM) != 0;
    1589           0 :                 break;
    1590           0 :         case IP_RECVFRAGSIZE:
    1591           0 :                 val = (inet->cmsg_flags & IP_CMSG_RECVFRAGSIZE) != 0;
    1592           0 :                 break;
    1593           0 :         case IP_TOS:
    1594           0 :                 val = inet->tos;
    1595           0 :                 break;
    1596             :         case IP_TTL:
    1597             :         {
    1598           0 :                 struct net *net = sock_net(sk);
    1599           0 :                 val = (inet->uc_ttl == -1 ?
    1600           0 :                        net->ipv4.sysctl_ip_default_ttl :
    1601             :                        inet->uc_ttl);
    1602           0 :                 break;
    1603             :         }
    1604           0 :         case IP_HDRINCL:
    1605           0 :                 val = inet->hdrincl;
    1606           0 :                 break;
    1607           0 :         case IP_NODEFRAG:
    1608           0 :                 val = inet->nodefrag;
    1609           0 :                 break;
    1610           0 :         case IP_BIND_ADDRESS_NO_PORT:
    1611           0 :                 val = inet->bind_address_no_port;
    1612           0 :                 break;
    1613           0 :         case IP_MTU_DISCOVER:
    1614           0 :                 val = inet->pmtudisc;
    1615           0 :                 break;
    1616           0 :         case IP_MTU:
    1617             :         {
    1618           0 :                 struct dst_entry *dst;
    1619           0 :                 val = 0;
    1620           0 :                 dst = sk_dst_get(sk);
    1621           0 :                 if (dst) {
    1622           0 :                         val = dst_mtu(dst);
    1623           0 :                         dst_release(dst);
    1624             :                 }
    1625           0 :                 if (!val) {
    1626           0 :                         release_sock(sk);
    1627           0 :                         return -ENOTCONN;
    1628             :                 }
    1629             :                 break;
    1630             :         }
    1631           0 :         case IP_RECVERR:
    1632           0 :                 val = inet->recverr;
    1633           0 :                 break;
    1634           0 :         case IP_RECVERR_RFC4884:
    1635           0 :                 val = inet->recverr_rfc4884;
    1636           0 :                 break;
    1637           0 :         case IP_MULTICAST_TTL:
    1638           0 :                 val = inet->mc_ttl;
    1639           0 :                 break;
    1640           0 :         case IP_MULTICAST_LOOP:
    1641           0 :                 val = inet->mc_loop;
    1642           0 :                 break;
    1643           0 :         case IP_UNICAST_IF:
    1644           0 :                 val = (__force int)htonl((__u32) inet->uc_index);
    1645           0 :                 break;
    1646           0 :         case IP_MULTICAST_IF:
    1647             :         {
    1648           0 :                 struct in_addr addr;
    1649           0 :                 len = min_t(unsigned int, len, sizeof(struct in_addr));
    1650           0 :                 addr.s_addr = inet->mc_addr;
    1651           0 :                 release_sock(sk);
    1652             : 
    1653           0 :                 if (put_user(len, optlen))
    1654             :                         return -EFAULT;
    1655           0 :                 if (copy_to_user(optval, &addr, len))
    1656           0 :                         return -EFAULT;
    1657             :                 return 0;
    1658             :         }
    1659           0 :         case IP_MSFILTER:
    1660             :         {
    1661           0 :                 struct ip_msfilter msf;
    1662             : 
    1663           0 :                 if (len < IP_MSFILTER_SIZE(0)) {
    1664           0 :                         err = -EINVAL;
    1665           0 :                         goto out;
    1666             :                 }
    1667           0 :                 if (copy_from_user(&msf, optval, IP_MSFILTER_SIZE(0))) {
    1668           0 :                         err = -EFAULT;
    1669           0 :                         goto out;
    1670             :                 }
    1671           0 :                 err = ip_mc_msfget(sk, &msf,
    1672             :                                    (struct ip_msfilter __user *)optval, optlen);
    1673           0 :                 goto out;
    1674             :         }
    1675             :         case MCAST_MSFILTER:
    1676           0 :                 if (in_compat_syscall())
    1677           0 :                         err = compat_ip_get_mcast_msfilter(sk, optval, optlen,
    1678             :                                                            len);
    1679             :                 else
    1680           0 :                         err = ip_get_mcast_msfilter(sk, optval, optlen, len);
    1681           0 :                 goto out;
    1682           0 :         case IP_MULTICAST_ALL:
    1683           0 :                 val = inet->mc_all;
    1684           0 :                 break;
    1685           0 :         case IP_PKTOPTIONS:
    1686             :         {
    1687           0 :                 struct msghdr msg;
    1688             : 
    1689           0 :                 release_sock(sk);
    1690             : 
    1691           0 :                 if (sk->sk_type != SOCK_STREAM)
    1692             :                         return -ENOPROTOOPT;
    1693             : 
    1694           0 :                 msg.msg_control_is_user = true;
    1695           0 :                 msg.msg_control_user = optval;
    1696           0 :                 msg.msg_controllen = len;
    1697           0 :                 msg.msg_flags = in_compat_syscall() ? MSG_CMSG_COMPAT : 0;
    1698             : 
    1699           0 :                 if (inet->cmsg_flags & IP_CMSG_PKTINFO) {
    1700           0 :                         struct in_pktinfo info;
    1701             : 
    1702           0 :                         info.ipi_addr.s_addr = inet->inet_rcv_saddr;
    1703           0 :                         info.ipi_spec_dst.s_addr = inet->inet_rcv_saddr;
    1704           0 :                         info.ipi_ifindex = inet->mc_index;
    1705           0 :                         put_cmsg(&msg, SOL_IP, IP_PKTINFO, sizeof(info), &info);
    1706             :                 }
    1707           0 :                 if (inet->cmsg_flags & IP_CMSG_TTL) {
    1708           0 :                         int hlim = inet->mc_ttl;
    1709           0 :                         put_cmsg(&msg, SOL_IP, IP_TTL, sizeof(hlim), &hlim);
    1710             :                 }
    1711           0 :                 if (inet->cmsg_flags & IP_CMSG_TOS) {
    1712           0 :                         int tos = inet->rcv_tos;
    1713           0 :                         put_cmsg(&msg, SOL_IP, IP_TOS, sizeof(tos), &tos);
    1714             :                 }
    1715           0 :                 len -= msg.msg_controllen;
    1716           0 :                 return put_user(len, optlen);
    1717             :         }
    1718           0 :         case IP_FREEBIND:
    1719           0 :                 val = inet->freebind;
    1720           0 :                 break;
    1721           0 :         case IP_TRANSPARENT:
    1722           0 :                 val = inet->transparent;
    1723           0 :                 break;
    1724           0 :         case IP_MINTTL:
    1725           0 :                 val = inet->min_ttl;
    1726           0 :                 break;
    1727           0 :         default:
    1728           0 :                 release_sock(sk);
    1729           0 :                 return -ENOPROTOOPT;
    1730             :         }
    1731           0 :         release_sock(sk);
    1732             : 
    1733           0 :         if (len < sizeof(int) && len > 0 && val >= 0 && val <= 255) {
    1734           0 :                 unsigned char ucval = (unsigned char)val;
    1735           0 :                 len = 1;
    1736           0 :                 if (put_user(len, optlen))
    1737           0 :                         return -EFAULT;
    1738           0 :                 if (copy_to_user(optval, &ucval, 1))
    1739             :                         return -EFAULT;
    1740             :         } else {
    1741           0 :                 len = min_t(unsigned int, sizeof(int), len);
    1742           0 :                 if (put_user(len, optlen))
    1743             :                         return -EFAULT;
    1744           0 :                 if (copy_to_user(optval, &val, len))
    1745           0 :                         return -EFAULT;
    1746             :         }
    1747             :         return 0;
    1748             : 
    1749           0 : out:
    1750           0 :         release_sock(sk);
    1751           0 :         if (needs_rtnl)
    1752           0 :                 rtnl_unlock();
    1753             :         return err;
    1754             : }
    1755             : 
    1756           4 : int ip_getsockopt(struct sock *sk, int level,
    1757             :                   int optname, char __user *optval, int __user *optlen)
    1758             : {
    1759           4 :         int err;
    1760             : 
    1761           4 :         err = do_ip_getsockopt(sk, level, optname, optval, optlen);
    1762             : 
    1763             : #if IS_ENABLED(CONFIG_BPFILTER_UMH)
    1764             :         if (optname >= BPFILTER_IPT_SO_GET_INFO &&
    1765             :             optname < BPFILTER_IPT_GET_MAX)
    1766             :                 err = bpfilter_ip_get_sockopt(sk, optname, optval, optlen);
    1767             : #endif
    1768             : #ifdef CONFIG_NETFILTER
    1769             :         /* we need to exclude all possible ENOPROTOOPTs except default case */
    1770           4 :         if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS &&
    1771           0 :                         !ip_mroute_opt(optname)) {
    1772           0 :                 int len;
    1773             : 
    1774           0 :                 if (get_user(len, optlen))
    1775             :                         return -EFAULT;
    1776             : 
    1777           0 :                 err = nf_getsockopt(sk, PF_INET, optname, optval, &len);
    1778           0 :                 if (err >= 0)
    1779           0 :                         err = put_user(len, optlen);
    1780           0 :                 return err;
    1781             :         }
    1782             : #endif
    1783             :         return err;
    1784             : }
    1785             : EXPORT_SYMBOL(ip_getsockopt);

Generated by: LCOV version 1.14