12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * NET An implementation of the SOCKET network access protocol.
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Version: @(#)socket.c 1.1.93 18/02/95
61da177e4SLinus Torvalds *
71da177e4SLinus Torvalds * Authors: Orest Zborowski, <obz@Kodak.COM>
802c30a84SJesper Juhl * Ross Biro
91da177e4SLinus Torvalds * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
101da177e4SLinus Torvalds *
111da177e4SLinus Torvalds * Fixes:
121da177e4SLinus Torvalds * Anonymous : NOTSOCK/BADF cleanup. Error fix in
131da177e4SLinus Torvalds * shutdown()
141da177e4SLinus Torvalds * Alan Cox : verify_area() fixes
151da177e4SLinus Torvalds * Alan Cox : Removed DDI
161da177e4SLinus Torvalds * Jonathan Kamens : SOCK_DGRAM reconnect bug
171da177e4SLinus Torvalds * Alan Cox : Moved a load of checks to the very
181da177e4SLinus Torvalds * top level.
191da177e4SLinus Torvalds * Alan Cox : Move address structures to/from user
201da177e4SLinus Torvalds * mode above the protocol layers.
211da177e4SLinus Torvalds * Rob Janssen : Allow 0 length sends.
221da177e4SLinus Torvalds * Alan Cox : Asynchronous I/O support (cribbed from the
231da177e4SLinus Torvalds * tty drivers).
241da177e4SLinus Torvalds * Niibe Yutaka : Asynchronous I/O for writes (4.4BSD style)
251da177e4SLinus Torvalds * Jeff Uphoff : Made max number of sockets command-line
261da177e4SLinus Torvalds * configurable.
271da177e4SLinus Torvalds * Matti Aarnio : Made the number of sockets dynamic,
281da177e4SLinus Torvalds * to be allocated when needed, and mr.
291da177e4SLinus Torvalds * Uphoff's max is used as max to be
301da177e4SLinus Torvalds * allowed to allocate.
311da177e4SLinus Torvalds * Linus : Argh. removed all the socket allocation
321da177e4SLinus Torvalds * altogether: it's in the inode now.
331da177e4SLinus Torvalds * Alan Cox : Made sock_alloc()/sock_release() public
341da177e4SLinus Torvalds * for NetROM and future kernel nfsd type
351da177e4SLinus Torvalds * stuff.
361da177e4SLinus Torvalds * Alan Cox : sendmsg/recvmsg basics.
371da177e4SLinus Torvalds * Tom Dyas : Export net symbols.
381da177e4SLinus Torvalds * Marcin Dalecki : Fixed problems with CONFIG_NET="n".
391da177e4SLinus Torvalds * Alan Cox : Added thread locking to sys_* calls
401da177e4SLinus Torvalds * for sockets. May have errors at the
411da177e4SLinus Torvalds * moment.
421da177e4SLinus Torvalds * Kevin Buhr : Fixed the dumb errors in the above.
431da177e4SLinus Torvalds * Andi Kleen : Some small cleanups, optimizations,
441da177e4SLinus Torvalds * and fixed a copy_from_user() bug.
451da177e4SLinus Torvalds * Tigran Aivazian : sys_send(args) calls sys_sendto(args, NULL, 0)
461da177e4SLinus Torvalds * Tigran Aivazian : Made listen(2) backlog sanity checks
471da177e4SLinus Torvalds * protocol-independent
481da177e4SLinus Torvalds *
491da177e4SLinus Torvalds * This module is effectively the top level interface to the BSD socket
501da177e4SLinus Torvalds * paradigm.
511da177e4SLinus Torvalds *
521da177e4SLinus Torvalds * Based upon Swansea University Computer Society NET3.039
531da177e4SLinus Torvalds */
541da177e4SLinus Torvalds
55aef2fedaSJakub Kicinski #include <linux/bpf-cgroup.h>
56cc69837fSJakub Kicinski #include <linux/ethtool.h>
571da177e4SLinus Torvalds #include <linux/mm.h>
581da177e4SLinus Torvalds #include <linux/socket.h>
591da177e4SLinus Torvalds #include <linux/file.h>
602dc334f1SDavid Howells #include <linux/splice.h>
611da177e4SLinus Torvalds #include <linux/net.h>
621da177e4SLinus Torvalds #include <linux/interrupt.h>
63aaca0bdcSUlrich Drepper #include <linux/thread_info.h>
6455737fdaSStephen Hemminger #include <linux/rcupdate.h>
651da177e4SLinus Torvalds #include <linux/netdevice.h>
661da177e4SLinus Torvalds #include <linux/proc_fs.h>
671da177e4SLinus Torvalds #include <linux/seq_file.h>
684a3e2f71SArjan van de Ven #include <linux/mutex.h>
691da177e4SLinus Torvalds #include <linux/if_bridge.h>
7020380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h>
71408eccceSDaniel Borkmann #include <linux/ptp_classify.h>
721da177e4SLinus Torvalds #include <linux/init.h>
731da177e4SLinus Torvalds #include <linux/poll.h>
741da177e4SLinus Torvalds #include <linux/cache.h>
751da177e4SLinus Torvalds #include <linux/module.h>
761da177e4SLinus Torvalds #include <linux/highmem.h>
771da177e4SLinus Torvalds #include <linux/mount.h>
78fba9be49SDavid Howells #include <linux/pseudo_fs.h>
791da177e4SLinus Torvalds #include <linux/security.h>
801da177e4SLinus Torvalds #include <linux/syscalls.h>
811da177e4SLinus Torvalds #include <linux/compat.h>
821da177e4SLinus Torvalds #include <linux/kmod.h>
833ec3b2fbSDavid Woodhouse #include <linux/audit.h>
84d86b5e0eSAdrian Bunk #include <linux/wireless.h>
851b8d7ae4SEric W. Biederman #include <linux/nsproxy.h>
861fd7317dSNick Black #include <linux/magic.h>
875a0e3ad6STejun Heo #include <linux/slab.h>
88600e1779SMasatake YAMATO #include <linux/xattr.h>
89c8e8cd57SJeremy Cline #include <linux/nospec.h>
908c3c447bSPaolo Abeni #include <linux/indirect_call_wrapper.h>
918e9fad0eSBreno Leitao #include <linux/io_uring.h>
921da177e4SLinus Torvalds
937c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
941da177e4SLinus Torvalds #include <asm/unistd.h>
951da177e4SLinus Torvalds
961da177e4SLinus Torvalds #include <net/compat.h>
9787de87d5SDavid S. Miller #include <net/wext.h>
98f8451725SHerbert Xu #include <net/cls_cgroup.h>
991da177e4SLinus Torvalds
1001da177e4SLinus Torvalds #include <net/sock.h>
1011da177e4SLinus Torvalds #include <linux/netfilter.h>
1021da177e4SLinus Torvalds
1036b96018bSArnd Bergmann #include <linux/if_tun.h>
1046b96018bSArnd Bergmann #include <linux/ipv6_route.h>
1056b96018bSArnd Bergmann #include <linux/route.h>
106c7dc504eSArnd Bergmann #include <linux/termios.h>
1076b96018bSArnd Bergmann #include <linux/sockios.h>
108076bb0c8SEliezer Tamir #include <net/busy_poll.h>
109f24b9be5SWillem de Bruijn #include <linux/errqueue.h>
110d7c08826SYangbo Lu #include <linux/ptp_clock_kernel.h>
1116e6eda44SYunhui Cui #include <trace/events/sock.h>
11206021292SEliezer Tamir
113e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL
11464b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly;
11564b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly;
11606021292SEliezer Tamir #endif
1176b96018bSArnd Bergmann
1188ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to);
1198ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from);
1201da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1211da177e4SLinus Torvalds
1221da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
123a11e1d43SLinus Torvalds static __poll_t sock_poll(struct file *file,
124a11e1d43SLinus Torvalds struct poll_table_struct *wait);
12589bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
12689bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12789bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
12889bbfc95SShaun Pereira unsigned int cmd, unsigned long arg);
12989bbfc95SShaun Pereira #endif
1301da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1319c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1329c55e01cSJens Axboe struct pipe_inode_info *pipe, size_t len,
1339c55e01cSJens Axboe unsigned int flags);
1342bfc6685SDavid Howells static void sock_splice_eof(struct file *file);
135542d3065SArnd Bergmann
136542d3065SArnd Bergmann #ifdef CONFIG_PROC_FS
sock_show_fdinfo(struct seq_file * m,struct file * f)137542d3065SArnd Bergmann static void sock_show_fdinfo(struct seq_file *m, struct file *f)
138542d3065SArnd Bergmann {
139542d3065SArnd Bergmann struct socket *sock = f->private_data;
1401ded5e5aSEric Dumazet const struct proto_ops *ops = READ_ONCE(sock->ops);
141542d3065SArnd Bergmann
1421ded5e5aSEric Dumazet if (ops->show_fdinfo)
1431ded5e5aSEric Dumazet ops->show_fdinfo(m, sock);
144542d3065SArnd Bergmann }
145542d3065SArnd Bergmann #else
146542d3065SArnd Bergmann #define sock_show_fdinfo NULL
147542d3065SArnd Bergmann #endif
1481da177e4SLinus Torvalds
1491da177e4SLinus Torvalds /*
1501da177e4SLinus Torvalds * Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1511da177e4SLinus Torvalds * in the operation structures but are done directly via the socketcall() multiplexor.
1521da177e4SLinus Torvalds */
1531da177e4SLinus Torvalds
154da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1551da177e4SLinus Torvalds .owner = THIS_MODULE,
1561da177e4SLinus Torvalds .llseek = no_llseek,
1578ae5e030SAl Viro .read_iter = sock_read_iter,
1588ae5e030SAl Viro .write_iter = sock_write_iter,
1591da177e4SLinus Torvalds .poll = sock_poll,
1601da177e4SLinus Torvalds .unlocked_ioctl = sock_ioctl,
16189bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
16289bbfc95SShaun Pereira .compat_ioctl = compat_sock_ioctl,
16389bbfc95SShaun Pereira #endif
1648e9fad0eSBreno Leitao .uring_cmd = io_uring_cmd_sock,
1651da177e4SLinus Torvalds .mmap = sock_mmap,
1661da177e4SLinus Torvalds .release = sock_close,
1671da177e4SLinus Torvalds .fasync = sock_fasync,
1682dc334f1SDavid Howells .splice_write = splice_to_socket,
1699c55e01cSJens Axboe .splice_read = sock_splice_read,
1702bfc6685SDavid Howells .splice_eof = sock_splice_eof,
171b4653342SKirill Tkhai .show_fdinfo = sock_show_fdinfo,
1721da177e4SLinus Torvalds };
1731da177e4SLinus Torvalds
174fe0bdbdeSYejune Deng static const char * const pf_family_names[] = {
175fe0bdbdeSYejune Deng [PF_UNSPEC] = "PF_UNSPEC",
176fe0bdbdeSYejune Deng [PF_UNIX] = "PF_UNIX/PF_LOCAL",
177fe0bdbdeSYejune Deng [PF_INET] = "PF_INET",
178fe0bdbdeSYejune Deng [PF_AX25] = "PF_AX25",
179fe0bdbdeSYejune Deng [PF_IPX] = "PF_IPX",
180fe0bdbdeSYejune Deng [PF_APPLETALK] = "PF_APPLETALK",
181fe0bdbdeSYejune Deng [PF_NETROM] = "PF_NETROM",
182fe0bdbdeSYejune Deng [PF_BRIDGE] = "PF_BRIDGE",
183fe0bdbdeSYejune Deng [PF_ATMPVC] = "PF_ATMPVC",
184fe0bdbdeSYejune Deng [PF_X25] = "PF_X25",
185fe0bdbdeSYejune Deng [PF_INET6] = "PF_INET6",
186fe0bdbdeSYejune Deng [PF_ROSE] = "PF_ROSE",
187fe0bdbdeSYejune Deng [PF_DECnet] = "PF_DECnet",
188fe0bdbdeSYejune Deng [PF_NETBEUI] = "PF_NETBEUI",
189fe0bdbdeSYejune Deng [PF_SECURITY] = "PF_SECURITY",
190fe0bdbdeSYejune Deng [PF_KEY] = "PF_KEY",
191fe0bdbdeSYejune Deng [PF_NETLINK] = "PF_NETLINK/PF_ROUTE",
192fe0bdbdeSYejune Deng [PF_PACKET] = "PF_PACKET",
193fe0bdbdeSYejune Deng [PF_ASH] = "PF_ASH",
194fe0bdbdeSYejune Deng [PF_ECONET] = "PF_ECONET",
195fe0bdbdeSYejune Deng [PF_ATMSVC] = "PF_ATMSVC",
196fe0bdbdeSYejune Deng [PF_RDS] = "PF_RDS",
197fe0bdbdeSYejune Deng [PF_SNA] = "PF_SNA",
198fe0bdbdeSYejune Deng [PF_IRDA] = "PF_IRDA",
199fe0bdbdeSYejune Deng [PF_PPPOX] = "PF_PPPOX",
200fe0bdbdeSYejune Deng [PF_WANPIPE] = "PF_WANPIPE",
201fe0bdbdeSYejune Deng [PF_LLC] = "PF_LLC",
202fe0bdbdeSYejune Deng [PF_IB] = "PF_IB",
203fe0bdbdeSYejune Deng [PF_MPLS] = "PF_MPLS",
204fe0bdbdeSYejune Deng [PF_CAN] = "PF_CAN",
205fe0bdbdeSYejune Deng [PF_TIPC] = "PF_TIPC",
206fe0bdbdeSYejune Deng [PF_BLUETOOTH] = "PF_BLUETOOTH",
207fe0bdbdeSYejune Deng [PF_IUCV] = "PF_IUCV",
208fe0bdbdeSYejune Deng [PF_RXRPC] = "PF_RXRPC",
209fe0bdbdeSYejune Deng [PF_ISDN] = "PF_ISDN",
210fe0bdbdeSYejune Deng [PF_PHONET] = "PF_PHONET",
211fe0bdbdeSYejune Deng [PF_IEEE802154] = "PF_IEEE802154",
212fe0bdbdeSYejune Deng [PF_CAIF] = "PF_CAIF",
213fe0bdbdeSYejune Deng [PF_ALG] = "PF_ALG",
214fe0bdbdeSYejune Deng [PF_NFC] = "PF_NFC",
215fe0bdbdeSYejune Deng [PF_VSOCK] = "PF_VSOCK",
216fe0bdbdeSYejune Deng [PF_KCM] = "PF_KCM",
217fe0bdbdeSYejune Deng [PF_QIPCRTR] = "PF_QIPCRTR",
218fe0bdbdeSYejune Deng [PF_SMC] = "PF_SMC",
219fe0bdbdeSYejune Deng [PF_XDP] = "PF_XDP",
220bc49d816SJeremy Kerr [PF_MCTP] = "PF_MCTP",
221fe0bdbdeSYejune Deng };
222fe0bdbdeSYejune Deng
2231da177e4SLinus Torvalds /*
2241da177e4SLinus Torvalds * The protocol list. Each protocol is registered in here.
2251da177e4SLinus Torvalds */
2261da177e4SLinus Torvalds
2271da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
228190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
2291da177e4SLinus Torvalds
2301da177e4SLinus Torvalds /*
23189bddce5SStephen Hemminger * Support routines.
23289bddce5SStephen Hemminger * Move socket addresses back and forth across the kernel/user
2331da177e4SLinus Torvalds * divide and look after the messy bits.
2341da177e4SLinus Torvalds */
2351da177e4SLinus Torvalds
2361da177e4SLinus Torvalds /**
2371da177e4SLinus Torvalds * move_addr_to_kernel - copy a socket address into kernel space
2381da177e4SLinus Torvalds * @uaddr: Address in user space
2391da177e4SLinus Torvalds * @kaddr: Address in kernel space
2401da177e4SLinus Torvalds * @ulen: Length in user space
2411da177e4SLinus Torvalds *
2421da177e4SLinus Torvalds * The address is copied into kernel space. If the provided address is
2431da177e4SLinus Torvalds * too long an error code of -EINVAL is returned. If the copy gives
2441da177e4SLinus Torvalds * invalid addresses -EFAULT is returned. On a success 0 is returned.
2451da177e4SLinus Torvalds */
2461da177e4SLinus Torvalds
move_addr_to_kernel(void __user * uaddr,int ulen,struct sockaddr_storage * kaddr)24743db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr)
2481da177e4SLinus Torvalds {
249230b1839SYOSHIFUJI Hideaki if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
2501da177e4SLinus Torvalds return -EINVAL;
2511da177e4SLinus Torvalds if (ulen == 0)
2521da177e4SLinus Torvalds return 0;
2531da177e4SLinus Torvalds if (copy_from_user(kaddr, uaddr, ulen))
2541da177e4SLinus Torvalds return -EFAULT;
2553ec3b2fbSDavid Woodhouse return audit_sockaddr(ulen, kaddr);
2561da177e4SLinus Torvalds }
2571da177e4SLinus Torvalds
2581da177e4SLinus Torvalds /**
2591da177e4SLinus Torvalds * move_addr_to_user - copy an address to user space
2601da177e4SLinus Torvalds * @kaddr: kernel space address
2611da177e4SLinus Torvalds * @klen: length of address in kernel
2621da177e4SLinus Torvalds * @uaddr: user space address
2631da177e4SLinus Torvalds * @ulen: pointer to user length field
2641da177e4SLinus Torvalds *
2651da177e4SLinus Torvalds * The value pointed to by ulen on entry is the buffer length available.
2661da177e4SLinus Torvalds * This is overwritten with the buffer space used. -EINVAL is returned
2671da177e4SLinus Torvalds * if an overlong buffer is specified or a negative buffer size. -EFAULT
2681da177e4SLinus Torvalds * is returned if either the buffer or the length field are not
2691da177e4SLinus Torvalds * accessible.
2701da177e4SLinus Torvalds * After copying the data up to the limit the user specifies, the true
2711da177e4SLinus Torvalds * length of the data is written over the length limit the user
2721da177e4SLinus Torvalds * specified. Zero is returned for a success.
2731da177e4SLinus Torvalds */
2741da177e4SLinus Torvalds
move_addr_to_user(struct sockaddr_storage * kaddr,int klen,void __user * uaddr,int __user * ulen)27543db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
27611165f14Sstephen hemminger void __user *uaddr, int __user *ulen)
2771da177e4SLinus Torvalds {
2781da177e4SLinus Torvalds int err;
2791da177e4SLinus Torvalds int len;
2801da177e4SLinus Torvalds
28168c6beb3SHannes Frederic Sowa BUG_ON(klen > sizeof(struct sockaddr_storage));
28289bddce5SStephen Hemminger err = get_user(len, ulen);
28389bddce5SStephen Hemminger if (err)
2841da177e4SLinus Torvalds return err;
2851da177e4SLinus Torvalds if (len > klen)
2861da177e4SLinus Torvalds len = klen;
28768c6beb3SHannes Frederic Sowa if (len < 0)
2881da177e4SLinus Torvalds return -EINVAL;
28989bddce5SStephen Hemminger if (len) {
290d6fe3945SSteve Grubb if (audit_sockaddr(klen, kaddr))
291d6fe3945SSteve Grubb return -ENOMEM;
2921da177e4SLinus Torvalds if (copy_to_user(uaddr, kaddr, len))
2931da177e4SLinus Torvalds return -EFAULT;
2941da177e4SLinus Torvalds }
2951da177e4SLinus Torvalds /*
2961da177e4SLinus Torvalds * "fromlen shall refer to the value before truncation.."
2971da177e4SLinus Torvalds * 1003.1g
2981da177e4SLinus Torvalds */
2991da177e4SLinus Torvalds return __put_user(klen, ulen);
3001da177e4SLinus Torvalds }
3011da177e4SLinus Torvalds
30208009a76SAlexey Dobriyan static struct kmem_cache *sock_inode_cachep __ro_after_init;
3031da177e4SLinus Torvalds
sock_alloc_inode(struct super_block * sb)3041da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
3051da177e4SLinus Torvalds {
3061da177e4SLinus Torvalds struct socket_alloc *ei;
30789bddce5SStephen Hemminger
308fd60b288SMuchun Song ei = alloc_inode_sb(sb, sock_inode_cachep, GFP_KERNEL);
3091da177e4SLinus Torvalds if (!ei)
3101da177e4SLinus Torvalds return NULL;
311333f7909SAl Viro init_waitqueue_head(&ei->socket.wq.wait);
312333f7909SAl Viro ei->socket.wq.fasync_list = NULL;
313333f7909SAl Viro ei->socket.wq.flags = 0;
3141da177e4SLinus Torvalds
3151da177e4SLinus Torvalds ei->socket.state = SS_UNCONNECTED;
3161da177e4SLinus Torvalds ei->socket.flags = 0;
3171da177e4SLinus Torvalds ei->socket.ops = NULL;
3181da177e4SLinus Torvalds ei->socket.sk = NULL;
3191da177e4SLinus Torvalds ei->socket.file = NULL;
3201da177e4SLinus Torvalds
3211da177e4SLinus Torvalds return &ei->vfs_inode;
3221da177e4SLinus Torvalds }
3231da177e4SLinus Torvalds
sock_free_inode(struct inode * inode)3246d7855c5SAl Viro static void sock_free_inode(struct inode *inode)
3251da177e4SLinus Torvalds {
32643815482SEric Dumazet struct socket_alloc *ei;
32743815482SEric Dumazet
32843815482SEric Dumazet ei = container_of(inode, struct socket_alloc, vfs_inode);
32943815482SEric Dumazet kmem_cache_free(sock_inode_cachep, ei);
3301da177e4SLinus Torvalds }
3311da177e4SLinus Torvalds
init_once(void * foo)33251cc5068SAlexey Dobriyan static void init_once(void *foo)
3331da177e4SLinus Torvalds {
3341da177e4SLinus Torvalds struct socket_alloc *ei = (struct socket_alloc *)foo;
3351da177e4SLinus Torvalds
3361da177e4SLinus Torvalds inode_init_once(&ei->vfs_inode);
3371da177e4SLinus Torvalds }
3381da177e4SLinus Torvalds
init_inodecache(void)3391e911632Syuan linyu static void init_inodecache(void)
3401da177e4SLinus Torvalds {
3411da177e4SLinus Torvalds sock_inode_cachep = kmem_cache_create("sock_inode_cache",
3421da177e4SLinus Torvalds sizeof(struct socket_alloc),
34389bddce5SStephen Hemminger 0,
34489bddce5SStephen Hemminger (SLAB_HWCACHE_ALIGN |
34589bddce5SStephen Hemminger SLAB_RECLAIM_ACCOUNT |
3465d097056SVladimir Davydov SLAB_MEM_SPREAD | SLAB_ACCOUNT),
34720c2df83SPaul Mundt init_once);
3481e911632Syuan linyu BUG_ON(sock_inode_cachep == NULL);
3491da177e4SLinus Torvalds }
3501da177e4SLinus Torvalds
351b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
3521da177e4SLinus Torvalds .alloc_inode = sock_alloc_inode,
3536d7855c5SAl Viro .free_inode = sock_free_inode,
3541da177e4SLinus Torvalds .statfs = simple_statfs,
3551da177e4SLinus Torvalds };
3561da177e4SLinus Torvalds
357c23fbb6bSEric Dumazet /*
358c23fbb6bSEric Dumazet * sockfs_dname() is called from d_path().
359c23fbb6bSEric Dumazet */
sockfs_dname(struct dentry * dentry,char * buffer,int buflen)360c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
361c23fbb6bSEric Dumazet {
3620f60d288SAl Viro return dynamic_dname(buffer, buflen, "socket:[%lu]",
363c5ef6035SDavid Howells d_inode(dentry)->i_ino);
364c23fbb6bSEric Dumazet }
365c23fbb6bSEric Dumazet
3663ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
367c23fbb6bSEric Dumazet .d_dname = sockfs_dname,
3681da177e4SLinus Torvalds };
3691da177e4SLinus Torvalds
sockfs_xattr_get(const struct xattr_handler * handler,struct dentry * dentry,struct inode * inode,const char * suffix,void * value,size_t size)370bba0bd31SAndreas Gruenbacher static int sockfs_xattr_get(const struct xattr_handler *handler,
371bba0bd31SAndreas Gruenbacher struct dentry *dentry, struct inode *inode,
372bba0bd31SAndreas Gruenbacher const char *suffix, void *value, size_t size)
373bba0bd31SAndreas Gruenbacher {
374bba0bd31SAndreas Gruenbacher if (value) {
375bba0bd31SAndreas Gruenbacher if (dentry->d_name.len + 1 > size)
376bba0bd31SAndreas Gruenbacher return -ERANGE;
377bba0bd31SAndreas Gruenbacher memcpy(value, dentry->d_name.name, dentry->d_name.len + 1);
378bba0bd31SAndreas Gruenbacher }
379bba0bd31SAndreas Gruenbacher return dentry->d_name.len + 1;
380bba0bd31SAndreas Gruenbacher }
381bba0bd31SAndreas Gruenbacher
382bba0bd31SAndreas Gruenbacher #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
383bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
384bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
385bba0bd31SAndreas Gruenbacher
386bba0bd31SAndreas Gruenbacher static const struct xattr_handler sockfs_xattr_handler = {
387bba0bd31SAndreas Gruenbacher .name = XATTR_NAME_SOCKPROTONAME,
388bba0bd31SAndreas Gruenbacher .get = sockfs_xattr_get,
389bba0bd31SAndreas Gruenbacher };
390bba0bd31SAndreas Gruenbacher
sockfs_security_xattr_set(const struct xattr_handler * handler,struct mnt_idmap * idmap,struct dentry * dentry,struct inode * inode,const char * suffix,const void * value,size_t size,int flags)3914a590153SAndreas Gruenbacher static int sockfs_security_xattr_set(const struct xattr_handler *handler,
39239f60c1cSChristian Brauner struct mnt_idmap *idmap,
3934a590153SAndreas Gruenbacher struct dentry *dentry, struct inode *inode,
3944a590153SAndreas Gruenbacher const char *suffix, const void *value,
3954a590153SAndreas Gruenbacher size_t size, int flags)
3964a590153SAndreas Gruenbacher {
3974a590153SAndreas Gruenbacher /* Handled by LSM. */
3984a590153SAndreas Gruenbacher return -EAGAIN;
3994a590153SAndreas Gruenbacher }
4004a590153SAndreas Gruenbacher
4014a590153SAndreas Gruenbacher static const struct xattr_handler sockfs_security_xattr_handler = {
4024a590153SAndreas Gruenbacher .prefix = XATTR_SECURITY_PREFIX,
4034a590153SAndreas Gruenbacher .set = sockfs_security_xattr_set,
4044a590153SAndreas Gruenbacher };
4054a590153SAndreas Gruenbacher
406bba0bd31SAndreas Gruenbacher static const struct xattr_handler *sockfs_xattr_handlers[] = {
407bba0bd31SAndreas Gruenbacher &sockfs_xattr_handler,
4084a590153SAndreas Gruenbacher &sockfs_security_xattr_handler,
409bba0bd31SAndreas Gruenbacher NULL
410bba0bd31SAndreas Gruenbacher };
411bba0bd31SAndreas Gruenbacher
sockfs_init_fs_context(struct fs_context * fc)412fba9be49SDavid Howells static int sockfs_init_fs_context(struct fs_context *fc)
413c74a1cbbSAl Viro {
414fba9be49SDavid Howells struct pseudo_fs_context *ctx = init_pseudo(fc, SOCKFS_MAGIC);
415fba9be49SDavid Howells if (!ctx)
416fba9be49SDavid Howells return -ENOMEM;
417fba9be49SDavid Howells ctx->ops = &sockfs_ops;
418fba9be49SDavid Howells ctx->dops = &sockfs_dentry_operations;
419fba9be49SDavid Howells ctx->xattr = sockfs_xattr_handlers;
420fba9be49SDavid Howells return 0;
421c74a1cbbSAl Viro }
422c74a1cbbSAl Viro
423c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
424c74a1cbbSAl Viro
425c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
426c74a1cbbSAl Viro .name = "sockfs",
427fba9be49SDavid Howells .init_fs_context = sockfs_init_fs_context,
428c74a1cbbSAl Viro .kill_sb = kill_anon_super,
429c74a1cbbSAl Viro };
430c74a1cbbSAl Viro
4311da177e4SLinus Torvalds /*
4321da177e4SLinus Torvalds * Obtains the first available file descriptor and sets it up for use.
4331da177e4SLinus Torvalds *
43439d8c1b6SDavid S. Miller * These functions create file structures and maps them to fd space
43539d8c1b6SDavid S. Miller * of the current process. On success it returns file descriptor
4361da177e4SLinus Torvalds * and file struct implicitly stored in sock->file.
4371da177e4SLinus Torvalds * Note that another thread may close file descriptor before we return
4381da177e4SLinus Torvalds * from this function. We use the fact that now we do not refer
4391da177e4SLinus Torvalds * to socket after mapping. If one day we will need it, this
4401da177e4SLinus Torvalds * function will increment ref. count on file by 1.
4411da177e4SLinus Torvalds *
4421da177e4SLinus Torvalds * In any case returned fd MAY BE not valid!
4431da177e4SLinus Torvalds * This race condition is unavoidable
4441da177e4SLinus Torvalds * with shared fd spaces, we cannot solve it inside kernel,
4451da177e4SLinus Torvalds * but we take care of internal coherence yet.
4461da177e4SLinus Torvalds */
4471da177e4SLinus Torvalds
4488a3c245cSPedro Tammela /**
4498a3c245cSPedro Tammela * sock_alloc_file - Bind a &socket to a &file
4508a3c245cSPedro Tammela * @sock: socket
4518a3c245cSPedro Tammela * @flags: file status flags
4528a3c245cSPedro Tammela * @dname: protocol name
4538a3c245cSPedro Tammela *
4548a3c245cSPedro Tammela * Returns the &file bound with @sock, implicitly storing it
4558a3c245cSPedro Tammela * in sock->file. If dname is %NULL, sets to "".
456649c15c7SThadeu Lima de Souza Cascardo *
457649c15c7SThadeu Lima de Souza Cascardo * On failure @sock is released, and an ERR pointer is returned.
458649c15c7SThadeu Lima de Souza Cascardo *
4598a3c245cSPedro Tammela * This function uses GFP_KERNEL internally.
4608a3c245cSPedro Tammela */
4618a3c245cSPedro Tammela
sock_alloc_file(struct socket * sock,int flags,const char * dname)462aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
4631da177e4SLinus Torvalds {
4647cbe66b6SAl Viro struct file *file;
4651da177e4SLinus Torvalds
466d93aa9d8SAl Viro if (!dname)
467d93aa9d8SAl Viro dname = sock->sk ? sock->sk->sk_prot_creator->name : "";
46839d8c1b6SDavid S. Miller
469d93aa9d8SAl Viro file = alloc_file_pseudo(SOCK_INODE(sock), sock_mnt, dname,
470d93aa9d8SAl Viro O_RDWR | (flags & O_NONBLOCK),
471cc3808f8SAl Viro &socket_file_ops);
472b5ffe634SViresh Kumar if (IS_ERR(file)) {
4738e1611e2SAl Viro sock_release(sock);
47439b65252SAnatol Pomozov return file;
475cc3808f8SAl Viro }
4761da177e4SLinus Torvalds
477fe34db06SJens Axboe file->f_mode |= FMODE_NOWAIT;
4781da177e4SLinus Torvalds sock->file = file;
47907dc3f07SBenjamin LaHaise file->private_data = sock;
480d8e464ecSLinus Torvalds stream_open(SOCK_INODE(sock), file);
48128407630SAl Viro return file;
4821da177e4SLinus Torvalds }
48356b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file);
4841da177e4SLinus Torvalds
sock_map_fd(struct socket * sock,int flags)48556b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags)
48639d8c1b6SDavid S. Miller {
48739d8c1b6SDavid S. Miller struct file *newfile;
48828407630SAl Viro int fd = get_unused_fd_flags(flags);
489ce4bb04cSAl Viro if (unlikely(fd < 0)) {
490ce4bb04cSAl Viro sock_release(sock);
4911da177e4SLinus Torvalds return fd;
492ce4bb04cSAl Viro }
4931da177e4SLinus Torvalds
494aab174f0SLinus Torvalds newfile = sock_alloc_file(sock, flags, NULL);
4954546e44cSEnrico Weigelt if (!IS_ERR(newfile)) {
4961da177e4SLinus Torvalds fd_install(fd, newfile);
4971da177e4SLinus Torvalds return fd;
4981da177e4SLinus Torvalds }
49928407630SAl Viro
50028407630SAl Viro put_unused_fd(fd);
50128407630SAl Viro return PTR_ERR(newfile);
5021da177e4SLinus Torvalds }
5031da177e4SLinus Torvalds
5048a3c245cSPedro Tammela /**
5058a3c245cSPedro Tammela * sock_from_file - Return the &socket bounded to @file.
5068a3c245cSPedro Tammela * @file: file
5078a3c245cSPedro Tammela *
508dba4a925SFlorent Revest * On failure returns %NULL.
5098a3c245cSPedro Tammela */
5108a3c245cSPedro Tammela
sock_from_file(struct file * file)511dba4a925SFlorent Revest struct socket *sock_from_file(struct file *file)
5126cb153caSBenjamin LaHaise {
5136cb153caSBenjamin LaHaise if (file->f_op == &socket_file_ops)
514da214a47SJens Axboe return file->private_data; /* set in sock_alloc_file */
5156cb153caSBenjamin LaHaise
5166cb153caSBenjamin LaHaise return NULL;
5176cb153caSBenjamin LaHaise }
518406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
5196cb153caSBenjamin LaHaise
5201da177e4SLinus Torvalds /**
5211da177e4SLinus Torvalds * sockfd_lookup - Go from a file number to its socket slot
5221da177e4SLinus Torvalds * @fd: file handle
5231da177e4SLinus Torvalds * @err: pointer to an error code return
5241da177e4SLinus Torvalds *
5251da177e4SLinus Torvalds * The file handle passed in is locked and the socket it is bound
526241c4667SRosen, Rami * to is returned. If an error occurs the err pointer is overwritten
5271da177e4SLinus Torvalds * with a negative errno code and NULL is returned. The function checks
5281da177e4SLinus Torvalds * for both invalid handles and passing a handle which is not a socket.
5291da177e4SLinus Torvalds *
5301da177e4SLinus Torvalds * On a success the socket object pointer is returned.
5311da177e4SLinus Torvalds */
5321da177e4SLinus Torvalds
sockfd_lookup(int fd,int * err)5331da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
5341da177e4SLinus Torvalds {
5351da177e4SLinus Torvalds struct file *file;
5361da177e4SLinus Torvalds struct socket *sock;
5371da177e4SLinus Torvalds
53889bddce5SStephen Hemminger file = fget(fd);
53989bddce5SStephen Hemminger if (!file) {
5401da177e4SLinus Torvalds *err = -EBADF;
5411da177e4SLinus Torvalds return NULL;
5421da177e4SLinus Torvalds }
54389bddce5SStephen Hemminger
544dba4a925SFlorent Revest sock = sock_from_file(file);
545dba4a925SFlorent Revest if (!sock) {
546dba4a925SFlorent Revest *err = -ENOTSOCK;
5471da177e4SLinus Torvalds fput(file);
548dba4a925SFlorent Revest }
5496cb153caSBenjamin LaHaise return sock;
5501da177e4SLinus Torvalds }
551c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
5521da177e4SLinus Torvalds
sockfd_lookup_light(int fd,int * err,int * fput_needed)5536cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
5546cb153caSBenjamin LaHaise {
55500e188efSAl Viro struct fd f = fdget(fd);
5566cb153caSBenjamin LaHaise struct socket *sock;
5576cb153caSBenjamin LaHaise
5583672558cSHua Zhong *err = -EBADF;
55900e188efSAl Viro if (f.file) {
560dba4a925SFlorent Revest sock = sock_from_file(f.file);
56100e188efSAl Viro if (likely(sock)) {
562ce787a5aSMiaohe Lin *fput_needed = f.flags & FDPUT_FPUT;
5631da177e4SLinus Torvalds return sock;
56400e188efSAl Viro }
565dba4a925SFlorent Revest *err = -ENOTSOCK;
56600e188efSAl Viro fdput(f);
5676cb153caSBenjamin LaHaise }
5686cb153caSBenjamin LaHaise return NULL;
5691da177e4SLinus Torvalds }
5701da177e4SLinus Torvalds
sockfs_listxattr(struct dentry * dentry,char * buffer,size_t size)571600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
572600e1779SMasatake YAMATO size_t size)
573600e1779SMasatake YAMATO {
574600e1779SMasatake YAMATO ssize_t len;
575600e1779SMasatake YAMATO ssize_t used = 0;
576600e1779SMasatake YAMATO
577c5ef6035SDavid Howells len = security_inode_listsecurity(d_inode(dentry), buffer, size);
578600e1779SMasatake YAMATO if (len < 0)
579600e1779SMasatake YAMATO return len;
580600e1779SMasatake YAMATO used += len;
581600e1779SMasatake YAMATO if (buffer) {
582600e1779SMasatake YAMATO if (size < used)
583600e1779SMasatake YAMATO return -ERANGE;
584600e1779SMasatake YAMATO buffer += len;
585600e1779SMasatake YAMATO }
586600e1779SMasatake YAMATO
587600e1779SMasatake YAMATO len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
588600e1779SMasatake YAMATO used += len;
589600e1779SMasatake YAMATO if (buffer) {
590600e1779SMasatake YAMATO if (size < used)
591600e1779SMasatake YAMATO return -ERANGE;
592600e1779SMasatake YAMATO memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
593600e1779SMasatake YAMATO buffer += len;
594600e1779SMasatake YAMATO }
595600e1779SMasatake YAMATO
596600e1779SMasatake YAMATO return used;
597600e1779SMasatake YAMATO }
598600e1779SMasatake YAMATO
sockfs_setattr(struct mnt_idmap * idmap,struct dentry * dentry,struct iattr * iattr)599c1632a0fSChristian Brauner static int sockfs_setattr(struct mnt_idmap *idmap,
600549c7297SChristian Brauner struct dentry *dentry, struct iattr *iattr)
60186741ec2SLorenzo Colitti {
602c1632a0fSChristian Brauner int err = simple_setattr(&nop_mnt_idmap, dentry, iattr);
60386741ec2SLorenzo Colitti
604e1a3a60aSEric Biggers if (!err && (iattr->ia_valid & ATTR_UID)) {
60586741ec2SLorenzo Colitti struct socket *sock = SOCKET_I(d_inode(dentry));
60686741ec2SLorenzo Colitti
6076d8c50dcSCong Wang if (sock->sk)
60886741ec2SLorenzo Colitti sock->sk->sk_uid = iattr->ia_uid;
6096d8c50dcSCong Wang else
6106d8c50dcSCong Wang err = -ENOENT;
61186741ec2SLorenzo Colitti }
61286741ec2SLorenzo Colitti
61386741ec2SLorenzo Colitti return err;
61486741ec2SLorenzo Colitti }
61586741ec2SLorenzo Colitti
616600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = {
617600e1779SMasatake YAMATO .listxattr = sockfs_listxattr,
61886741ec2SLorenzo Colitti .setattr = sockfs_setattr,
619600e1779SMasatake YAMATO };
620600e1779SMasatake YAMATO
6211da177e4SLinus Torvalds /**
6221da177e4SLinus Torvalds * sock_alloc - allocate a socket
6231da177e4SLinus Torvalds *
6241da177e4SLinus Torvalds * Allocate a new inode and socket object. The two are bound together
6251da177e4SLinus Torvalds * and initialised. The socket is then returned. If we are out of inodes
6268a3c245cSPedro Tammela * NULL is returned. This functions uses GFP_KERNEL internally.
6271da177e4SLinus Torvalds */
6281da177e4SLinus Torvalds
sock_alloc(void)629f4a00aacSTom Herbert struct socket *sock_alloc(void)
6301da177e4SLinus Torvalds {
6311da177e4SLinus Torvalds struct inode *inode;
6321da177e4SLinus Torvalds struct socket *sock;
6331da177e4SLinus Torvalds
634a209dfc7SEric Dumazet inode = new_inode_pseudo(sock_mnt->mnt_sb);
6351da177e4SLinus Torvalds if (!inode)
6361da177e4SLinus Torvalds return NULL;
6371da177e4SLinus Torvalds
6381da177e4SLinus Torvalds sock = SOCKET_I(inode);
6391da177e4SLinus Torvalds
64085fe4025SChristoph Hellwig inode->i_ino = get_next_ino();
6411da177e4SLinus Torvalds inode->i_mode = S_IFSOCK | S_IRWXUGO;
6428192b0c4SDavid Howells inode->i_uid = current_fsuid();
6438192b0c4SDavid Howells inode->i_gid = current_fsgid();
644600e1779SMasatake YAMATO inode->i_op = &sockfs_inode_ops;
6451da177e4SLinus Torvalds
6461da177e4SLinus Torvalds return sock;
6471da177e4SLinus Torvalds }
648f4a00aacSTom Herbert EXPORT_SYMBOL(sock_alloc);
6491da177e4SLinus Torvalds
__sock_release(struct socket * sock,struct inode * inode)6506d8c50dcSCong Wang static void __sock_release(struct socket *sock, struct inode *inode)
6511da177e4SLinus Torvalds {
6521ded5e5aSEric Dumazet const struct proto_ops *ops = READ_ONCE(sock->ops);
6531ded5e5aSEric Dumazet
6541ded5e5aSEric Dumazet if (ops) {
6551ded5e5aSEric Dumazet struct module *owner = ops->owner;
6561da177e4SLinus Torvalds
6576d8c50dcSCong Wang if (inode)
6586d8c50dcSCong Wang inode_lock(inode);
6591ded5e5aSEric Dumazet ops->release(sock);
660ff7b11aaSEric Biggers sock->sk = NULL;
6616d8c50dcSCong Wang if (inode)
6626d8c50dcSCong Wang inode_unlock(inode);
6631da177e4SLinus Torvalds sock->ops = NULL;
6641da177e4SLinus Torvalds module_put(owner);
6651da177e4SLinus Torvalds }
6661da177e4SLinus Torvalds
667333f7909SAl Viro if (sock->wq.fasync_list)
6683410f22eSYang Yingliang pr_err("%s: fasync list not empty!\n", __func__);
6691da177e4SLinus Torvalds
6701da177e4SLinus Torvalds if (!sock->file) {
6711da177e4SLinus Torvalds iput(SOCK_INODE(sock));
6721da177e4SLinus Torvalds return;
6731da177e4SLinus Torvalds }
6741da177e4SLinus Torvalds sock->file = NULL;
6751da177e4SLinus Torvalds }
6766d8c50dcSCong Wang
6779a8ad9acSAndrew Lunn /**
6789a8ad9acSAndrew Lunn * sock_release - close a socket
6799a8ad9acSAndrew Lunn * @sock: socket to close
6809a8ad9acSAndrew Lunn *
6819a8ad9acSAndrew Lunn * The socket is released from the protocol stack if it has a release
6829a8ad9acSAndrew Lunn * callback, and the inode is then released if the socket is bound to
6839a8ad9acSAndrew Lunn * an inode not a file.
6849a8ad9acSAndrew Lunn */
sock_release(struct socket * sock)6856d8c50dcSCong Wang void sock_release(struct socket *sock)
6866d8c50dcSCong Wang {
6876d8c50dcSCong Wang __sock_release(sock, NULL);
6886d8c50dcSCong Wang }
689c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
6901da177e4SLinus Torvalds
__sock_tx_timestamp(__u16 tsflags,__u8 * tx_flags)691c14ac945SSoheil Hassas Yeganeh void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags)
69220d49473SPatrick Ohly {
693140c55d4SEric Dumazet u8 flags = *tx_flags;
694140c55d4SEric Dumazet
69551eb7492SGerhard Engleder if (tsflags & SOF_TIMESTAMPING_TX_HARDWARE) {
696140c55d4SEric Dumazet flags |= SKBTX_HW_TSTAMP;
697140c55d4SEric Dumazet
69851eb7492SGerhard Engleder /* PTP hardware clocks can provide a free running cycle counter
69951eb7492SGerhard Engleder * as a time base for virtual clocks. Tell driver to use the
70051eb7492SGerhard Engleder * free running cycle counter for timestamp if socket is bound
70151eb7492SGerhard Engleder * to virtual clock.
70251eb7492SGerhard Engleder */
70351eb7492SGerhard Engleder if (tsflags & SOF_TIMESTAMPING_BIND_PHC)
70451eb7492SGerhard Engleder flags |= SKBTX_HW_TSTAMP_USE_CYCLES;
70551eb7492SGerhard Engleder }
70651eb7492SGerhard Engleder
707c14ac945SSoheil Hassas Yeganeh if (tsflags & SOF_TIMESTAMPING_TX_SOFTWARE)
708140c55d4SEric Dumazet flags |= SKBTX_SW_TSTAMP;
709140c55d4SEric Dumazet
710c14ac945SSoheil Hassas Yeganeh if (tsflags & SOF_TIMESTAMPING_TX_SCHED)
711140c55d4SEric Dumazet flags |= SKBTX_SCHED_TSTAMP;
712140c55d4SEric Dumazet
713140c55d4SEric Dumazet *tx_flags = flags;
71420d49473SPatrick Ohly }
71567cc0d40SWillem de Bruijn EXPORT_SYMBOL(__sock_tx_timestamp);
71620d49473SPatrick Ohly
7178c3c447bSPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet_sendmsg(struct socket *, struct msghdr *,
7188c3c447bSPaolo Abeni size_t));
719a648a592SPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet6_sendmsg(struct socket *, struct msghdr *,
720a648a592SPaolo Abeni size_t));
7216e6eda44SYunhui Cui
call_trace_sock_send_length(struct sock * sk,int ret,int flags)7226e6eda44SYunhui Cui static noinline void call_trace_sock_send_length(struct sock *sk, int ret,
7236e6eda44SYunhui Cui int flags)
7246e6eda44SYunhui Cui {
7256e6eda44SYunhui Cui trace_sock_send_length(sk, ret, 0);
7266e6eda44SYunhui Cui }
7276e6eda44SYunhui Cui
sock_sendmsg_nosec(struct socket * sock,struct msghdr * msg)728d8725c86SAl Viro static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
7291da177e4SLinus Torvalds {
7301ded5e5aSEric Dumazet int ret = INDIRECT_CALL_INET(READ_ONCE(sock->ops)->sendmsg, inet6_sendmsg,
731a648a592SPaolo Abeni inet_sendmsg, sock, msg,
732a648a592SPaolo Abeni msg_data_left(msg));
733d8725c86SAl Viro BUG_ON(ret == -EIOCBQUEUED);
7346e6eda44SYunhui Cui
7356e6eda44SYunhui Cui if (trace_sock_send_length_enabled())
7366e6eda44SYunhui Cui call_trace_sock_send_length(sock->sk, ret, 0);
737d8725c86SAl Viro return ret;
7381da177e4SLinus Torvalds }
7390cf00c6fSGu Zheng
__sock_sendmsg(struct socket * sock,struct msghdr * msg)74086a7e0b6SJordan Rife static int __sock_sendmsg(struct socket *sock, struct msghdr *msg)
74186a7e0b6SJordan Rife {
74286a7e0b6SJordan Rife int err = security_socket_sendmsg(sock, msg,
74386a7e0b6SJordan Rife msg_data_left(msg));
74486a7e0b6SJordan Rife
74586a7e0b6SJordan Rife return err ?: sock_sendmsg_nosec(sock, msg);
74686a7e0b6SJordan Rife }
74786a7e0b6SJordan Rife
74885806af0SRandy Dunlap /**
74985806af0SRandy Dunlap * sock_sendmsg - send a message through @sock
75085806af0SRandy Dunlap * @sock: socket
75185806af0SRandy Dunlap * @msg: message to send
75285806af0SRandy Dunlap *
75385806af0SRandy Dunlap * Sends @msg through @sock, passing through LSM.
75485806af0SRandy Dunlap * Returns the number of bytes sent, or an error code.
75585806af0SRandy Dunlap */
sock_sendmsg(struct socket * sock,struct msghdr * msg)756d8725c86SAl Viro int sock_sendmsg(struct socket *sock, struct msghdr *msg)
7570cf00c6fSGu Zheng {
75886a7e0b6SJordan Rife struct sockaddr_storage *save_addr = (struct sockaddr_storage *)msg->msg_name;
75986a7e0b6SJordan Rife struct sockaddr_storage address;
760d5e0bb03SMarc Dionne int save_len = msg->msg_namelen;
76186a7e0b6SJordan Rife int ret;
7621b784140SYing Xue
76386a7e0b6SJordan Rife if (msg->msg_name) {
76486a7e0b6SJordan Rife memcpy(&address, msg->msg_name, msg->msg_namelen);
76586a7e0b6SJordan Rife msg->msg_name = &address;
76686a7e0b6SJordan Rife }
76786a7e0b6SJordan Rife
76886a7e0b6SJordan Rife ret = __sock_sendmsg(sock, msg);
76986a7e0b6SJordan Rife msg->msg_name = save_addr;
770d5e0bb03SMarc Dionne msg->msg_namelen = save_len;
77186a7e0b6SJordan Rife
77286a7e0b6SJordan Rife return ret;
7730cf00c6fSGu Zheng }
774c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
7751da177e4SLinus Torvalds
7768a3c245cSPedro Tammela /**
7778a3c245cSPedro Tammela * kernel_sendmsg - send a message through @sock (kernel-space)
7788a3c245cSPedro Tammela * @sock: socket
7798a3c245cSPedro Tammela * @msg: message header
7808a3c245cSPedro Tammela * @vec: kernel vec
7818a3c245cSPedro Tammela * @num: vec array length
7828a3c245cSPedro Tammela * @size: total message data size
7838a3c245cSPedro Tammela *
7848a3c245cSPedro Tammela * Builds the message data with @vec and sends it through @sock.
7858a3c245cSPedro Tammela * Returns the number of bytes sent, or an error code.
7868a3c245cSPedro Tammela */
7878a3c245cSPedro Tammela
kernel_sendmsg(struct socket * sock,struct msghdr * msg,struct kvec * vec,size_t num,size_t size)7881da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
7891da177e4SLinus Torvalds struct kvec *vec, size_t num, size_t size)
7901da177e4SLinus Torvalds {
791de4eda9dSAl Viro iov_iter_kvec(&msg->msg_iter, ITER_SOURCE, vec, num, size);
792d8725c86SAl Viro return sock_sendmsg(sock, msg);
7931da177e4SLinus Torvalds }
794c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
7951da177e4SLinus Torvalds
7968a3c245cSPedro Tammela /**
7978a3c245cSPedro Tammela * kernel_sendmsg_locked - send a message through @sock (kernel-space)
7988a3c245cSPedro Tammela * @sk: sock
7998a3c245cSPedro Tammela * @msg: message header
8008a3c245cSPedro Tammela * @vec: output s/g array
8018a3c245cSPedro Tammela * @num: output s/g array length
8028a3c245cSPedro Tammela * @size: total message data size
8038a3c245cSPedro Tammela *
8048a3c245cSPedro Tammela * Builds the message data with @vec and sends it through @sock.
8058a3c245cSPedro Tammela * Returns the number of bytes sent, or an error code.
8068a3c245cSPedro Tammela * Caller must hold @sk.
8078a3c245cSPedro Tammela */
8088a3c245cSPedro Tammela
kernel_sendmsg_locked(struct sock * sk,struct msghdr * msg,struct kvec * vec,size_t num,size_t size)809306b13ebSTom Herbert int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg,
810306b13ebSTom Herbert struct kvec *vec, size_t num, size_t size)
811306b13ebSTom Herbert {
812306b13ebSTom Herbert struct socket *sock = sk->sk_socket;
8131ded5e5aSEric Dumazet const struct proto_ops *ops = READ_ONCE(sock->ops);
814306b13ebSTom Herbert
8151ded5e5aSEric Dumazet if (!ops->sendmsg_locked)
816db5980d8SJohn Fastabend return sock_no_sendmsg_locked(sk, msg, size);
817306b13ebSTom Herbert
818de4eda9dSAl Viro iov_iter_kvec(&msg->msg_iter, ITER_SOURCE, vec, num, size);
819306b13ebSTom Herbert
8201ded5e5aSEric Dumazet return ops->sendmsg_locked(sk, msg, msg_data_left(msg));
821306b13ebSTom Herbert }
822306b13ebSTom Herbert EXPORT_SYMBOL(kernel_sendmsg_locked);
823306b13ebSTom Herbert
skb_is_err_queue(const struct sk_buff * skb)8248605330aSSoheil Hassas Yeganeh static bool skb_is_err_queue(const struct sk_buff *skb)
8258605330aSSoheil Hassas Yeganeh {
8268605330aSSoheil Hassas Yeganeh /* pkt_type of skbs enqueued on the error queue are set to
8278605330aSSoheil Hassas Yeganeh * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do
8288605330aSSoheil Hassas Yeganeh * in recvmsg, since skbs received on a local socket will never
8298605330aSSoheil Hassas Yeganeh * have a pkt_type of PACKET_OUTGOING.
8308605330aSSoheil Hassas Yeganeh */
8318605330aSSoheil Hassas Yeganeh return skb->pkt_type == PACKET_OUTGOING;
8328605330aSSoheil Hassas Yeganeh }
8338605330aSSoheil Hassas Yeganeh
834b50a5c70SMiroslav Lichvar /* On transmit, software and hardware timestamps are returned independently.
835b50a5c70SMiroslav Lichvar * As the two skb clones share the hardware timestamp, which may be updated
836b50a5c70SMiroslav Lichvar * before the software timestamp is received, a hardware TX timestamp may be
837b50a5c70SMiroslav Lichvar * returned only if there is no software TX timestamp. Ignore false software
838b50a5c70SMiroslav Lichvar * timestamps, which may be made in the __sock_recv_timestamp() call when the
8397f1bc6e9SDeepa Dinamani * option SO_TIMESTAMP_OLD(NS) is enabled on the socket, even when the skb has a
840b50a5c70SMiroslav Lichvar * hardware timestamp.
841b50a5c70SMiroslav Lichvar */
skb_is_swtx_tstamp(const struct sk_buff * skb,int false_tstamp)842b50a5c70SMiroslav Lichvar static bool skb_is_swtx_tstamp(const struct sk_buff *skb, int false_tstamp)
843b50a5c70SMiroslav Lichvar {
844b50a5c70SMiroslav Lichvar return skb->tstamp && !false_tstamp && skb_is_err_queue(skb);
845b50a5c70SMiroslav Lichvar }
846b50a5c70SMiroslav Lichvar
get_timestamp(struct sock * sk,struct sk_buff * skb,int * if_index)84797dc7cd9SGerhard Engleder static ktime_t get_timestamp(struct sock *sk, struct sk_buff *skb, int *if_index)
84897dc7cd9SGerhard Engleder {
849e3390b30SEric Dumazet bool cycles = READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_BIND_PHC;
85097dc7cd9SGerhard Engleder struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
85197dc7cd9SGerhard Engleder struct net_device *orig_dev;
85297dc7cd9SGerhard Engleder ktime_t hwtstamp;
85397dc7cd9SGerhard Engleder
85497dc7cd9SGerhard Engleder rcu_read_lock();
85597dc7cd9SGerhard Engleder orig_dev = dev_get_by_napi_id(skb_napi_id(skb));
85697dc7cd9SGerhard Engleder if (orig_dev) {
85797dc7cd9SGerhard Engleder *if_index = orig_dev->ifindex;
85897dc7cd9SGerhard Engleder hwtstamp = netdev_get_tstamp(orig_dev, shhwtstamps, cycles);
85997dc7cd9SGerhard Engleder } else {
86097dc7cd9SGerhard Engleder hwtstamp = shhwtstamps->hwtstamp;
86197dc7cd9SGerhard Engleder }
86297dc7cd9SGerhard Engleder rcu_read_unlock();
86397dc7cd9SGerhard Engleder
86497dc7cd9SGerhard Engleder return hwtstamp;
86597dc7cd9SGerhard Engleder }
86697dc7cd9SGerhard Engleder
put_ts_pktinfo(struct msghdr * msg,struct sk_buff * skb,int if_index)86797dc7cd9SGerhard Engleder static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb,
86897dc7cd9SGerhard Engleder int if_index)
869aad9c8c4SMiroslav Lichvar {
870aad9c8c4SMiroslav Lichvar struct scm_ts_pktinfo ts_pktinfo;
871aad9c8c4SMiroslav Lichvar struct net_device *orig_dev;
872aad9c8c4SMiroslav Lichvar
873aad9c8c4SMiroslav Lichvar if (!skb_mac_header_was_set(skb))
874aad9c8c4SMiroslav Lichvar return;
875aad9c8c4SMiroslav Lichvar
876aad9c8c4SMiroslav Lichvar memset(&ts_pktinfo, 0, sizeof(ts_pktinfo));
877aad9c8c4SMiroslav Lichvar
87897dc7cd9SGerhard Engleder if (!if_index) {
879aad9c8c4SMiroslav Lichvar rcu_read_lock();
880aad9c8c4SMiroslav Lichvar orig_dev = dev_get_by_napi_id(skb_napi_id(skb));
881aad9c8c4SMiroslav Lichvar if (orig_dev)
88297dc7cd9SGerhard Engleder if_index = orig_dev->ifindex;
883aad9c8c4SMiroslav Lichvar rcu_read_unlock();
88497dc7cd9SGerhard Engleder }
88597dc7cd9SGerhard Engleder ts_pktinfo.if_index = if_index;
886aad9c8c4SMiroslav Lichvar
887aad9c8c4SMiroslav Lichvar ts_pktinfo.pkt_length = skb->len - skb_mac_offset(skb);
888aad9c8c4SMiroslav Lichvar put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO,
889aad9c8c4SMiroslav Lichvar sizeof(ts_pktinfo), &ts_pktinfo);
890aad9c8c4SMiroslav Lichvar }
891aad9c8c4SMiroslav Lichvar
89292f37fd2SEric Dumazet /*
89392f37fd2SEric Dumazet * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
89492f37fd2SEric Dumazet */
__sock_recv_timestamp(struct msghdr * msg,struct sock * sk,struct sk_buff * skb)89592f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
89692f37fd2SEric Dumazet struct sk_buff *skb)
89792f37fd2SEric Dumazet {
89820d49473SPatrick Ohly int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
899887feae3SDeepa Dinamani int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW);
9009718475eSDeepa Dinamani struct scm_timestamping_internal tss;
901b50a5c70SMiroslav Lichvar int empty = 1, false_tstamp = 0;
90220d49473SPatrick Ohly struct skb_shared_hwtstamps *shhwtstamps =
90320d49473SPatrick Ohly skb_hwtstamps(skb);
90497dc7cd9SGerhard Engleder int if_index;
905007747a9SMiroslav Lichvar ktime_t hwtstamp;
906e3390b30SEric Dumazet u32 tsflags;
90792f37fd2SEric Dumazet
90820d49473SPatrick Ohly /* Race occurred between timestamp enabling and packet
90920d49473SPatrick Ohly receiving. Fill in the current time for now. */
910b50a5c70SMiroslav Lichvar if (need_software_tstamp && skb->tstamp == 0) {
91120d49473SPatrick Ohly __net_timestamp(skb);
912b50a5c70SMiroslav Lichvar false_tstamp = 1;
913b50a5c70SMiroslav Lichvar }
91420d49473SPatrick Ohly
91520d49473SPatrick Ohly if (need_software_tstamp) {
91692f37fd2SEric Dumazet if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
917887feae3SDeepa Dinamani if (new_tstamp) {
918887feae3SDeepa Dinamani struct __kernel_sock_timeval tv;
919887feae3SDeepa Dinamani
920887feae3SDeepa Dinamani skb_get_new_timestamp(skb, &tv);
921887feae3SDeepa Dinamani put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_NEW,
922887feae3SDeepa Dinamani sizeof(tv), &tv);
923887feae3SDeepa Dinamani } else {
92413c6ee2aSDeepa Dinamani struct __kernel_old_timeval tv;
925887feae3SDeepa Dinamani
92620d49473SPatrick Ohly skb_get_timestamp(skb, &tv);
9277f1bc6e9SDeepa Dinamani put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD,
92820d49473SPatrick Ohly sizeof(tv), &tv);
929887feae3SDeepa Dinamani }
930887feae3SDeepa Dinamani } else {
931887feae3SDeepa Dinamani if (new_tstamp) {
932887feae3SDeepa Dinamani struct __kernel_timespec ts;
933887feae3SDeepa Dinamani
934887feae3SDeepa Dinamani skb_get_new_timestampns(skb, &ts);
935887feae3SDeepa Dinamani put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW,
936887feae3SDeepa Dinamani sizeof(ts), &ts);
93792f37fd2SEric Dumazet } else {
938df1b4ba9SArnd Bergmann struct __kernel_old_timespec ts;
939887feae3SDeepa Dinamani
940f24b9be5SWillem de Bruijn skb_get_timestampns(skb, &ts);
9417f1bc6e9SDeepa Dinamani put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
942f24b9be5SWillem de Bruijn sizeof(ts), &ts);
94392f37fd2SEric Dumazet }
94492f37fd2SEric Dumazet }
945887feae3SDeepa Dinamani }
94692f37fd2SEric Dumazet
947f24b9be5SWillem de Bruijn memset(&tss, 0, sizeof(tss));
948e3390b30SEric Dumazet tsflags = READ_ONCE(sk->sk_tsflags);
949e3390b30SEric Dumazet if ((tsflags & SOF_TIMESTAMPING_SOFTWARE) &&
9509718475eSDeepa Dinamani ktime_to_timespec64_cond(skb->tstamp, tss.ts + 0))
95120d49473SPatrick Ohly empty = 0;
9524d276eb6SWillem de Bruijn if (shhwtstamps &&
953e3390b30SEric Dumazet (tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
954d7c08826SYangbo Lu !skb_is_swtx_tstamp(skb, false_tstamp)) {
95597dc7cd9SGerhard Engleder if_index = 0;
95697dc7cd9SGerhard Engleder if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP_NETDEV)
95797dc7cd9SGerhard Engleder hwtstamp = get_timestamp(sk, skb, &if_index);
958007747a9SMiroslav Lichvar else
959007747a9SMiroslav Lichvar hwtstamp = shhwtstamps->hwtstamp;
960d7c08826SYangbo Lu
961e3390b30SEric Dumazet if (tsflags & SOF_TIMESTAMPING_BIND_PHC)
96297dc7cd9SGerhard Engleder hwtstamp = ptp_convert_timestamp(&hwtstamp,
963251cd405SEric Dumazet READ_ONCE(sk->sk_bind_phc));
96497dc7cd9SGerhard Engleder
965007747a9SMiroslav Lichvar if (ktime_to_timespec64_cond(hwtstamp, tss.ts + 2)) {
96620d49473SPatrick Ohly empty = 0;
967d7c08826SYangbo Lu
968e3390b30SEric Dumazet if ((tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&
969aad9c8c4SMiroslav Lichvar !skb_is_err_queue(skb))
97097dc7cd9SGerhard Engleder put_ts_pktinfo(msg, skb, if_index);
971aad9c8c4SMiroslav Lichvar }
972d7c08826SYangbo Lu }
9731c885808SFrancis Yan if (!empty) {
9749718475eSDeepa Dinamani if (sock_flag(sk, SOCK_TSTAMP_NEW))
9759718475eSDeepa Dinamani put_cmsg_scm_timestamping64(msg, &tss);
9769718475eSDeepa Dinamani else
9779718475eSDeepa Dinamani put_cmsg_scm_timestamping(msg, &tss);
9781c885808SFrancis Yan
9798605330aSSoheil Hassas Yeganeh if (skb_is_err_queue(skb) && skb->len &&
9804ef1b286SSoheil Hassas Yeganeh SKB_EXT_ERR(skb)->opt_stats)
9811c885808SFrancis Yan put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS,
9821c885808SFrancis Yan skb->len, skb->data);
9831c885808SFrancis Yan }
98420d49473SPatrick Ohly }
9857c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
9867c81fd8bSArnaldo Carvalho de Melo
987eb6fba75SJakub Kicinski #ifdef CONFIG_WIRELESS
__sock_recv_wifi_status(struct msghdr * msg,struct sock * sk,struct sk_buff * skb)9886e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
9896e3e939fSJohannes Berg struct sk_buff *skb)
9906e3e939fSJohannes Berg {
9916e3e939fSJohannes Berg int ack;
9926e3e939fSJohannes Berg
9936e3e939fSJohannes Berg if (!sock_flag(sk, SOCK_WIFI_STATUS))
9946e3e939fSJohannes Berg return;
9956e3e939fSJohannes Berg if (!skb->wifi_acked_valid)
9966e3e939fSJohannes Berg return;
9976e3e939fSJohannes Berg
9986e3e939fSJohannes Berg ack = skb->wifi_acked;
9996e3e939fSJohannes Berg
10006e3e939fSJohannes Berg put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
10016e3e939fSJohannes Berg }
10026e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
1003eb6fba75SJakub Kicinski #endif
10046e3e939fSJohannes Berg
sock_recv_drops(struct msghdr * msg,struct sock * sk,struct sk_buff * skb)100511165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
100611165f14Sstephen hemminger struct sk_buff *skb)
10073b885787SNeil Horman {
1008744d5a3eSEyal Birger if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && SOCK_SKB_CB(skb)->dropcount)
10093b885787SNeil Horman put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
1010744d5a3eSEyal Birger sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount);
10113b885787SNeil Horman }
10123b885787SNeil Horman
sock_recv_mark(struct msghdr * msg,struct sock * sk,struct sk_buff * skb)10136fd1d51cSErin MacNeil static void sock_recv_mark(struct msghdr *msg, struct sock *sk,
10146fd1d51cSErin MacNeil struct sk_buff *skb)
10156fd1d51cSErin MacNeil {
10162558b803SEric Dumazet if (sock_flag(sk, SOCK_RCVMARK) && skb) {
10172558b803SEric Dumazet /* We must use a bounce buffer for CONFIG_HARDENED_USERCOPY=y */
10182558b803SEric Dumazet __u32 mark = skb->mark;
10192558b803SEric Dumazet
10202558b803SEric Dumazet put_cmsg(msg, SOL_SOCKET, SO_MARK, sizeof(__u32), &mark);
10212558b803SEric Dumazet }
10226fd1d51cSErin MacNeil }
10236fd1d51cSErin MacNeil
__sock_recv_cmsgs(struct msghdr * msg,struct sock * sk,struct sk_buff * skb)10246fd1d51cSErin MacNeil void __sock_recv_cmsgs(struct msghdr *msg, struct sock *sk,
10253b885787SNeil Horman struct sk_buff *skb)
10263b885787SNeil Horman {
10273b885787SNeil Horman sock_recv_timestamp(msg, sk, skb);
10283b885787SNeil Horman sock_recv_drops(msg, sk, skb);
10296fd1d51cSErin MacNeil sock_recv_mark(msg, sk, skb);
10303b885787SNeil Horman }
10316fd1d51cSErin MacNeil EXPORT_SYMBOL_GPL(__sock_recv_cmsgs);
10323b885787SNeil Horman
10338c3c447bSPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet_recvmsg(struct socket *, struct msghdr *,
10348c3c447bSPaolo Abeni size_t, int));
1035a648a592SPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet6_recvmsg(struct socket *, struct msghdr *,
1036a648a592SPaolo Abeni size_t, int));
10376e6eda44SYunhui Cui
call_trace_sock_recv_length(struct sock * sk,int ret,int flags)10386e6eda44SYunhui Cui static noinline void call_trace_sock_recv_length(struct sock *sk, int ret, int flags)
10396e6eda44SYunhui Cui {
10406e6eda44SYunhui Cui trace_sock_recv_length(sk, ret, flags);
10416e6eda44SYunhui Cui }
10426e6eda44SYunhui Cui
sock_recvmsg_nosec(struct socket * sock,struct msghdr * msg,int flags)10431b784140SYing Xue static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
10441b784140SYing Xue int flags)
1045a2e27255SArnaldo Carvalho de Melo {
10461ded5e5aSEric Dumazet int ret = INDIRECT_CALL_INET(READ_ONCE(sock->ops)->recvmsg,
10471ded5e5aSEric Dumazet inet6_recvmsg,
10486e6eda44SYunhui Cui inet_recvmsg, sock, msg,
10496e6eda44SYunhui Cui msg_data_left(msg), flags);
10506e6eda44SYunhui Cui if (trace_sock_recv_length_enabled())
10516e6eda44SYunhui Cui call_trace_sock_recv_length(sock->sk, ret, flags);
10526e6eda44SYunhui Cui return ret;
10532da62906SAl Viro }
1054a2e27255SArnaldo Carvalho de Melo
105585806af0SRandy Dunlap /**
105685806af0SRandy Dunlap * sock_recvmsg - receive a message from @sock
105785806af0SRandy Dunlap * @sock: socket
105885806af0SRandy Dunlap * @msg: message to receive
105985806af0SRandy Dunlap * @flags: message flags
106085806af0SRandy Dunlap *
106185806af0SRandy Dunlap * Receives @msg from @sock, passing through LSM. Returns the total number
106285806af0SRandy Dunlap * of bytes received, or an error.
106385806af0SRandy Dunlap */
sock_recvmsg(struct socket * sock,struct msghdr * msg,int flags)10642da62906SAl Viro int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags)
10652da62906SAl Viro {
10662da62906SAl Viro int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags);
10672da62906SAl Viro
10682da62906SAl Viro return err ?: sock_recvmsg_nosec(sock, msg, flags);
10691da177e4SLinus Torvalds }
1070c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
10711da177e4SLinus Torvalds
1072c1249c0aSMartin Lucina /**
1073c1249c0aSMartin Lucina * kernel_recvmsg - Receive a message from a socket (kernel space)
1074c1249c0aSMartin Lucina * @sock: The socket to receive the message from
1075c1249c0aSMartin Lucina * @msg: Received message
1076c1249c0aSMartin Lucina * @vec: Input s/g array for message data
1077c1249c0aSMartin Lucina * @num: Size of input s/g array
1078c1249c0aSMartin Lucina * @size: Number of bytes to read
1079c1249c0aSMartin Lucina * @flags: Message flags (MSG_DONTWAIT, etc...)
1080c1249c0aSMartin Lucina *
1081c1249c0aSMartin Lucina * On return the msg structure contains the scatter/gather array passed in the
1082c1249c0aSMartin Lucina * vec argument. The array is modified so that it consists of the unfilled
1083c1249c0aSMartin Lucina * portion of the original array.
1084c1249c0aSMartin Lucina *
1085c1249c0aSMartin Lucina * The returned value is the total number of bytes received, or an error.
1086c1249c0aSMartin Lucina */
10878a3c245cSPedro Tammela
kernel_recvmsg(struct socket * sock,struct msghdr * msg,struct kvec * vec,size_t num,size_t size,int flags)10881da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
108989bddce5SStephen Hemminger struct kvec *vec, size_t num, size_t size, int flags)
10901da177e4SLinus Torvalds {
10911f466e1fSChristoph Hellwig msg->msg_control_is_user = false;
1092de4eda9dSAl Viro iov_iter_kvec(&msg->msg_iter, ITER_DEST, vec, num, size);
10931f466e1fSChristoph Hellwig return sock_recvmsg(sock, msg, flags);
10941da177e4SLinus Torvalds }
1095c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
10961da177e4SLinus Torvalds
sock_splice_read(struct file * file,loff_t * ppos,struct pipe_inode_info * pipe,size_t len,unsigned int flags)10979c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
10989c55e01cSJens Axboe struct pipe_inode_info *pipe, size_t len,
10999c55e01cSJens Axboe unsigned int flags)
11009c55e01cSJens Axboe {
11019c55e01cSJens Axboe struct socket *sock = file->private_data;
11021ded5e5aSEric Dumazet const struct proto_ops *ops;
11039c55e01cSJens Axboe
11041ded5e5aSEric Dumazet ops = READ_ONCE(sock->ops);
11051ded5e5aSEric Dumazet if (unlikely(!ops->splice_read))
110667178fd0SDavid Howells return copy_splice_read(file, ppos, pipe, len, flags);
1107997b37daSRémi Denis-Courmont
11081ded5e5aSEric Dumazet return ops->splice_read(sock, ppos, pipe, len, flags);
11099c55e01cSJens Axboe }
11109c55e01cSJens Axboe
sock_splice_eof(struct file * file)11112bfc6685SDavid Howells static void sock_splice_eof(struct file *file)
11122bfc6685SDavid Howells {
11132bfc6685SDavid Howells struct socket *sock = file->private_data;
11141ded5e5aSEric Dumazet const struct proto_ops *ops;
11152bfc6685SDavid Howells
11161ded5e5aSEric Dumazet ops = READ_ONCE(sock->ops);
11171ded5e5aSEric Dumazet if (ops->splice_eof)
11181ded5e5aSEric Dumazet ops->splice_eof(sock);
11192bfc6685SDavid Howells }
11202bfc6685SDavid Howells
sock_read_iter(struct kiocb * iocb,struct iov_iter * to)11218ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
1122ce1d4d3eSChristoph Hellwig {
11236d652330SAl Viro struct file *file = iocb->ki_filp;
11246d652330SAl Viro struct socket *sock = file->private_data;
11250345f931Stadeusz.struk@intel.com struct msghdr msg = {.msg_iter = *to,
11260345f931Stadeusz.struk@intel.com .msg_iocb = iocb};
11278ae5e030SAl Viro ssize_t res;
1128ce1d4d3eSChristoph Hellwig
1129ebfcd895SJens Axboe if (file->f_flags & O_NONBLOCK || (iocb->ki_flags & IOCB_NOWAIT))
11308ae5e030SAl Viro msg.msg_flags = MSG_DONTWAIT;
11318ae5e030SAl Viro
11328ae5e030SAl Viro if (iocb->ki_pos != 0)
1133ce1d4d3eSChristoph Hellwig return -ESPIPE;
1134027445c3SBadari Pulavarty
113566ee59afSChristoph Hellwig if (!iov_iter_count(to)) /* Match SYS5 behaviour */
1136ce1d4d3eSChristoph Hellwig return 0;
1137ce1d4d3eSChristoph Hellwig
11382da62906SAl Viro res = sock_recvmsg(sock, &msg, msg.msg_flags);
11398ae5e030SAl Viro *to = msg.msg_iter;
11408ae5e030SAl Viro return res;
1141ce1d4d3eSChristoph Hellwig }
1142ce1d4d3eSChristoph Hellwig
sock_write_iter(struct kiocb * iocb,struct iov_iter * from)11438ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
11441da177e4SLinus Torvalds {
11456d652330SAl Viro struct file *file = iocb->ki_filp;
11466d652330SAl Viro struct socket *sock = file->private_data;
11470345f931Stadeusz.struk@intel.com struct msghdr msg = {.msg_iter = *from,
11480345f931Stadeusz.struk@intel.com .msg_iocb = iocb};
11498ae5e030SAl Viro ssize_t res;
11501da177e4SLinus Torvalds
11518ae5e030SAl Viro if (iocb->ki_pos != 0)
1152ce1d4d3eSChristoph Hellwig return -ESPIPE;
1153027445c3SBadari Pulavarty
1154ebfcd895SJens Axboe if (file->f_flags & O_NONBLOCK || (iocb->ki_flags & IOCB_NOWAIT))
11558ae5e030SAl Viro msg.msg_flags = MSG_DONTWAIT;
11568ae5e030SAl Viro
11576d652330SAl Viro if (sock->type == SOCK_SEQPACKET)
11586d652330SAl Viro msg.msg_flags |= MSG_EOR;
11596d652330SAl Viro
116086a7e0b6SJordan Rife res = __sock_sendmsg(sock, &msg);
11618ae5e030SAl Viro *from = msg.msg_iter;
11628ae5e030SAl Viro return res;
11631da177e4SLinus Torvalds }
11641da177e4SLinus Torvalds
11651da177e4SLinus Torvalds /*
11661da177e4SLinus Torvalds * Atomic setting of ioctl hooks to avoid race
11671da177e4SLinus Torvalds * with module unload.
11681da177e4SLinus Torvalds */
11691da177e4SLinus Torvalds
11704a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
1171ad2f99aeSArnd Bergmann static int (*br_ioctl_hook)(struct net *net, struct net_bridge *br,
1172ad2f99aeSArnd Bergmann unsigned int cmd, struct ifreq *ifr,
1173ad2f99aeSArnd Bergmann void __user *uarg);
11741da177e4SLinus Torvalds
brioctl_set(int (* hook)(struct net * net,struct net_bridge * br,unsigned int cmd,struct ifreq * ifr,void __user * uarg))1175ad2f99aeSArnd Bergmann void brioctl_set(int (*hook)(struct net *net, struct net_bridge *br,
1176ad2f99aeSArnd Bergmann unsigned int cmd, struct ifreq *ifr,
1177ad2f99aeSArnd Bergmann void __user *uarg))
11781da177e4SLinus Torvalds {
11794a3e2f71SArjan van de Ven mutex_lock(&br_ioctl_mutex);
11801da177e4SLinus Torvalds br_ioctl_hook = hook;
11814a3e2f71SArjan van de Ven mutex_unlock(&br_ioctl_mutex);
11821da177e4SLinus Torvalds }
11831da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
11841da177e4SLinus Torvalds
br_ioctl_call(struct net * net,struct net_bridge * br,unsigned int cmd,struct ifreq * ifr,void __user * uarg)1185ad2f99aeSArnd Bergmann int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd,
1186ad2f99aeSArnd Bergmann struct ifreq *ifr, void __user *uarg)
1187ad2f99aeSArnd Bergmann {
1188ad2f99aeSArnd Bergmann int err = -ENOPKG;
1189ad2f99aeSArnd Bergmann
1190ad2f99aeSArnd Bergmann if (!br_ioctl_hook)
1191ad2f99aeSArnd Bergmann request_module("bridge");
1192ad2f99aeSArnd Bergmann
1193ad2f99aeSArnd Bergmann mutex_lock(&br_ioctl_mutex);
1194ad2f99aeSArnd Bergmann if (br_ioctl_hook)
1195ad2f99aeSArnd Bergmann err = br_ioctl_hook(net, br, cmd, ifr, uarg);
1196ad2f99aeSArnd Bergmann mutex_unlock(&br_ioctl_mutex);
1197ad2f99aeSArnd Bergmann
1198ad2f99aeSArnd Bergmann return err;
1199ad2f99aeSArnd Bergmann }
1200ad2f99aeSArnd Bergmann
12014a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
1202881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
12031da177e4SLinus Torvalds
vlan_ioctl_set(int (* hook)(struct net *,void __user *))1204881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
12051da177e4SLinus Torvalds {
12064a3e2f71SArjan van de Ven mutex_lock(&vlan_ioctl_mutex);
12071da177e4SLinus Torvalds vlan_ioctl_hook = hook;
12084a3e2f71SArjan van de Ven mutex_unlock(&vlan_ioctl_mutex);
12091da177e4SLinus Torvalds }
12101da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
12111da177e4SLinus Torvalds
sock_do_ioctl(struct net * net,struct socket * sock,unsigned int cmd,unsigned long arg)12126b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
121363ff03abSJohannes Berg unsigned int cmd, unsigned long arg)
12146b96018bSArnd Bergmann {
12151ded5e5aSEric Dumazet const struct proto_ops *ops = READ_ONCE(sock->ops);
1216876f0bf9SArnd Bergmann struct ifreq ifr;
1217876f0bf9SArnd Bergmann bool need_copyout;
12186b96018bSArnd Bergmann int err;
12196b96018bSArnd Bergmann void __user *argp = (void __user *)arg;
1220a554bf96SArnd Bergmann void __user *data;
12216b96018bSArnd Bergmann
12221ded5e5aSEric Dumazet err = ops->ioctl(sock, cmd, arg);
12236b96018bSArnd Bergmann
12246b96018bSArnd Bergmann /*
12256b96018bSArnd Bergmann * If this ioctl is unknown try to hand it down
12266b96018bSArnd Bergmann * to the NIC driver.
12276b96018bSArnd Bergmann */
122836fd633eSAl Viro if (err != -ENOIOCTLCMD)
12296b96018bSArnd Bergmann return err;
12306b96018bSArnd Bergmann
123129ce8f97SJakub Kicinski if (!is_socket_ioctl_cmd(cmd))
123229ce8f97SJakub Kicinski return -ENOTTY;
123329ce8f97SJakub Kicinski
1234a554bf96SArnd Bergmann if (get_user_ifreq(&ifr, &data, argp))
123536fd633eSAl Viro return -EFAULT;
1236a554bf96SArnd Bergmann err = dev_ioctl(net, cmd, &ifr, data, &need_copyout);
123744c02a2cSAl Viro if (!err && need_copyout)
1238a554bf96SArnd Bergmann if (put_user_ifreq(&ifr, argp))
123944c02a2cSAl Viro return -EFAULT;
1240876f0bf9SArnd Bergmann
12416b96018bSArnd Bergmann return err;
12426b96018bSArnd Bergmann }
12436b96018bSArnd Bergmann
12441da177e4SLinus Torvalds /*
12451da177e4SLinus Torvalds * With an ioctl, arg may well be a user mode pointer, but we don't know
12461da177e4SLinus Torvalds * what to do with it - that's up to the protocol still.
12471da177e4SLinus Torvalds */
12481da177e4SLinus Torvalds
sock_ioctl(struct file * file,unsigned cmd,unsigned long arg)12491da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
12501da177e4SLinus Torvalds {
12511ded5e5aSEric Dumazet const struct proto_ops *ops;
12521da177e4SLinus Torvalds struct socket *sock;
1253881d966bSEric W. Biederman struct sock *sk;
12541da177e4SLinus Torvalds void __user *argp = (void __user *)arg;
12551da177e4SLinus Torvalds int pid, err;
1256881d966bSEric W. Biederman struct net *net;
12571da177e4SLinus Torvalds
1258b69aee04SEric Dumazet sock = file->private_data;
12591ded5e5aSEric Dumazet ops = READ_ONCE(sock->ops);
1260881d966bSEric W. Biederman sk = sock->sk;
12613b1e0a65SYOSHIFUJI Hideaki net = sock_net(sk);
126244c02a2cSAl Viro if (unlikely(cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))) {
126344c02a2cSAl Viro struct ifreq ifr;
1264a554bf96SArnd Bergmann void __user *data;
126544c02a2cSAl Viro bool need_copyout;
1266a554bf96SArnd Bergmann if (get_user_ifreq(&ifr, &data, argp))
126744c02a2cSAl Viro return -EFAULT;
1268a554bf96SArnd Bergmann err = dev_ioctl(net, cmd, &ifr, data, &need_copyout);
126944c02a2cSAl Viro if (!err && need_copyout)
1270a554bf96SArnd Bergmann if (put_user_ifreq(&ifr, argp))
127144c02a2cSAl Viro return -EFAULT;
12721da177e4SLinus Torvalds } else
12733d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
12741da177e4SLinus Torvalds if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
1275b1b0c245SAl Viro err = wext_handle_ioctl(net, cmd, argp);
12761da177e4SLinus Torvalds } else
12773d23e349SJohannes Berg #endif
12781da177e4SLinus Torvalds switch (cmd) {
12791da177e4SLinus Torvalds case FIOSETOWN:
12801da177e4SLinus Torvalds case SIOCSPGRP:
12811da177e4SLinus Torvalds err = -EFAULT;
12821da177e4SLinus Torvalds if (get_user(pid, (int __user *)argp))
12831da177e4SLinus Torvalds break;
1284393cc3f5SJiri Slaby err = f_setown(sock->file, pid, 1);
12851da177e4SLinus Torvalds break;
12861da177e4SLinus Torvalds case FIOGETOWN:
12871da177e4SLinus Torvalds case SIOCGPGRP:
1288609d7fa9SEric W. Biederman err = put_user(f_getown(sock->file),
128989bddce5SStephen Hemminger (int __user *)argp);
12901da177e4SLinus Torvalds break;
12911da177e4SLinus Torvalds case SIOCGIFBR:
12921da177e4SLinus Torvalds case SIOCSIFBR:
12931da177e4SLinus Torvalds case SIOCBRADDBR:
12941da177e4SLinus Torvalds case SIOCBRDELBR:
1295ad2f99aeSArnd Bergmann err = br_ioctl_call(net, NULL, cmd, NULL, argp);
12961da177e4SLinus Torvalds break;
12971da177e4SLinus Torvalds case SIOCGIFVLAN:
12981da177e4SLinus Torvalds case SIOCSIFVLAN:
12991da177e4SLinus Torvalds err = -ENOPKG;
13001da177e4SLinus Torvalds if (!vlan_ioctl_hook)
13011da177e4SLinus Torvalds request_module("8021q");
13021da177e4SLinus Torvalds
13034a3e2f71SArjan van de Ven mutex_lock(&vlan_ioctl_mutex);
13041da177e4SLinus Torvalds if (vlan_ioctl_hook)
1305881d966bSEric W. Biederman err = vlan_ioctl_hook(net, argp);
13064a3e2f71SArjan van de Ven mutex_unlock(&vlan_ioctl_mutex);
13071da177e4SLinus Torvalds break;
1308c62cce2cSAndrey Vagin case SIOCGSKNS:
1309c62cce2cSAndrey Vagin err = -EPERM;
1310c62cce2cSAndrey Vagin if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1311c62cce2cSAndrey Vagin break;
1312c62cce2cSAndrey Vagin
1313c62cce2cSAndrey Vagin err = open_related_ns(&net->ns, get_net_ns);
1314c62cce2cSAndrey Vagin break;
13150768e170SArnd Bergmann case SIOCGSTAMP_OLD:
13160768e170SArnd Bergmann case SIOCGSTAMPNS_OLD:
13171ded5e5aSEric Dumazet if (!ops->gettstamp) {
1318c7cbdbf2SArnd Bergmann err = -ENOIOCTLCMD;
1319c7cbdbf2SArnd Bergmann break;
1320c7cbdbf2SArnd Bergmann }
13211ded5e5aSEric Dumazet err = ops->gettstamp(sock, argp,
13220768e170SArnd Bergmann cmd == SIOCGSTAMP_OLD,
13230768e170SArnd Bergmann !IS_ENABLED(CONFIG_64BIT));
132460747828SGustavo A. R. Silva break;
13250768e170SArnd Bergmann case SIOCGSTAMP_NEW:
13260768e170SArnd Bergmann case SIOCGSTAMPNS_NEW:
13271ded5e5aSEric Dumazet if (!ops->gettstamp) {
13280768e170SArnd Bergmann err = -ENOIOCTLCMD;
13290768e170SArnd Bergmann break;
13300768e170SArnd Bergmann }
13311ded5e5aSEric Dumazet err = ops->gettstamp(sock, argp,
13320768e170SArnd Bergmann cmd == SIOCGSTAMP_NEW,
13330768e170SArnd Bergmann false);
1334c7cbdbf2SArnd Bergmann break;
1335876f0bf9SArnd Bergmann
1336876f0bf9SArnd Bergmann case SIOCGIFCONF:
1337876f0bf9SArnd Bergmann err = dev_ifconf(net, argp);
1338876f0bf9SArnd Bergmann break;
1339876f0bf9SArnd Bergmann
13401da177e4SLinus Torvalds default:
134163ff03abSJohannes Berg err = sock_do_ioctl(net, sock, cmd, arg);
13421da177e4SLinus Torvalds break;
13431da177e4SLinus Torvalds }
13441da177e4SLinus Torvalds return err;
13451da177e4SLinus Torvalds }
13461da177e4SLinus Torvalds
13478a3c245cSPedro Tammela /**
13488a3c245cSPedro Tammela * sock_create_lite - creates a socket
13498a3c245cSPedro Tammela * @family: protocol family (AF_INET, ...)
13508a3c245cSPedro Tammela * @type: communication type (SOCK_STREAM, ...)
13518a3c245cSPedro Tammela * @protocol: protocol (0, ...)
13528a3c245cSPedro Tammela * @res: new socket
13538a3c245cSPedro Tammela *
13548a3c245cSPedro Tammela * Creates a new socket and assigns it to @res, passing through LSM.
13558a3c245cSPedro Tammela * The new socket initialization is not complete, see kernel_accept().
13568a3c245cSPedro Tammela * Returns 0 or an error. On failure @res is set to %NULL.
13578a3c245cSPedro Tammela * This function internally uses GFP_KERNEL.
13588a3c245cSPedro Tammela */
13598a3c245cSPedro Tammela
sock_create_lite(int family,int type,int protocol,struct socket ** res)13601da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
13611da177e4SLinus Torvalds {
13621da177e4SLinus Torvalds int err;
13631da177e4SLinus Torvalds struct socket *sock = NULL;
13641da177e4SLinus Torvalds
13651da177e4SLinus Torvalds err = security_socket_create(family, type, protocol, 1);
13661da177e4SLinus Torvalds if (err)
13671da177e4SLinus Torvalds goto out;
13681da177e4SLinus Torvalds
13691da177e4SLinus Torvalds sock = sock_alloc();
13701da177e4SLinus Torvalds if (!sock) {
13711da177e4SLinus Torvalds err = -ENOMEM;
13721da177e4SLinus Torvalds goto out;
13731da177e4SLinus Torvalds }
13741da177e4SLinus Torvalds
13751da177e4SLinus Torvalds sock->type = type;
13767420ed23SVenkat Yekkirala err = security_socket_post_create(sock, family, type, protocol, 1);
13777420ed23SVenkat Yekkirala if (err)
13787420ed23SVenkat Yekkirala goto out_release;
13797420ed23SVenkat Yekkirala
13801da177e4SLinus Torvalds out:
13811da177e4SLinus Torvalds *res = sock;
13821da177e4SLinus Torvalds return err;
13837420ed23SVenkat Yekkirala out_release:
13847420ed23SVenkat Yekkirala sock_release(sock);
13857420ed23SVenkat Yekkirala sock = NULL;
13867420ed23SVenkat Yekkirala goto out;
13871da177e4SLinus Torvalds }
1388c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
13891da177e4SLinus Torvalds
13901da177e4SLinus Torvalds /* No kernel lock held - perfect */
sock_poll(struct file * file,poll_table * wait)1391ade994f4SAl Viro static __poll_t sock_poll(struct file *file, poll_table *wait)
13921da177e4SLinus Torvalds {
13933cafb376SChristoph Hellwig struct socket *sock = file->private_data;
13941ded5e5aSEric Dumazet const struct proto_ops *ops = READ_ONCE(sock->ops);
1395a331de3bSChristoph Hellwig __poll_t events = poll_requested_events(wait), flag = 0;
13961da177e4SLinus Torvalds
13971ded5e5aSEric Dumazet if (!ops->poll)
1398e88958e6SChristoph Hellwig return 0;
1399f641f13bSChristoph Hellwig
1400a331de3bSChristoph Hellwig if (sk_can_busy_loop(sock->sk)) {
1401f641f13bSChristoph Hellwig /* poll once if requested by the syscall */
1402a331de3bSChristoph Hellwig if (events & POLL_BUSY_LOOP)
1403f641f13bSChristoph Hellwig sk_busy_loop(sock->sk, 1);
1404a331de3bSChristoph Hellwig
1405a331de3bSChristoph Hellwig /* if this socket can poll_ll, tell the system call */
1406a331de3bSChristoph Hellwig flag = POLL_BUSY_LOOP;
1407a331de3bSChristoph Hellwig }
1408a331de3bSChristoph Hellwig
14091ded5e5aSEric Dumazet return ops->poll(file, sock, wait) | flag;
14101da177e4SLinus Torvalds }
14111da177e4SLinus Torvalds
sock_mmap(struct file * file,struct vm_area_struct * vma)14121da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
14131da177e4SLinus Torvalds {
1414b69aee04SEric Dumazet struct socket *sock = file->private_data;
14151da177e4SLinus Torvalds
14161ded5e5aSEric Dumazet return READ_ONCE(sock->ops)->mmap(file, sock, vma);
14171da177e4SLinus Torvalds }
14181da177e4SLinus Torvalds
sock_close(struct inode * inode,struct file * filp)141920380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
14201da177e4SLinus Torvalds {
14216d8c50dcSCong Wang __sock_release(SOCKET_I(inode), inode);
14221da177e4SLinus Torvalds return 0;
14231da177e4SLinus Torvalds }
14241da177e4SLinus Torvalds
14251da177e4SLinus Torvalds /*
14261da177e4SLinus Torvalds * Update the socket async list
14271da177e4SLinus Torvalds *
14281da177e4SLinus Torvalds * Fasync_list locking strategy.
14291da177e4SLinus Torvalds *
14301da177e4SLinus Torvalds * 1. fasync_list is modified only under process context socket lock
14311da177e4SLinus Torvalds * i.e. under semaphore.
14321da177e4SLinus Torvalds * 2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1433989a2979SEric Dumazet * or under socket lock
14341da177e4SLinus Torvalds */
14351da177e4SLinus Torvalds
sock_fasync(int fd,struct file * filp,int on)14361da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
14371da177e4SLinus Torvalds {
1438989a2979SEric Dumazet struct socket *sock = filp->private_data;
1439989a2979SEric Dumazet struct sock *sk = sock->sk;
1440333f7909SAl Viro struct socket_wq *wq = &sock->wq;
14411da177e4SLinus Torvalds
1442989a2979SEric Dumazet if (sk == NULL)
14431da177e4SLinus Torvalds return -EINVAL;
14441da177e4SLinus Torvalds
14451da177e4SLinus Torvalds lock_sock(sk);
1446eaefd110SEric Dumazet fasync_helper(fd, filp, on, &wq->fasync_list);
14471da177e4SLinus Torvalds
1448eaefd110SEric Dumazet if (!wq->fasync_list)
1449bcdce719SEric Dumazet sock_reset_flag(sk, SOCK_FASYNC);
1450989a2979SEric Dumazet else
1451989a2979SEric Dumazet sock_set_flag(sk, SOCK_FASYNC);
14521da177e4SLinus Torvalds
1453989a2979SEric Dumazet release_sock(sk);
14541da177e4SLinus Torvalds return 0;
14551da177e4SLinus Torvalds }
14561da177e4SLinus Torvalds
1457ceb5d58bSEric Dumazet /* This function may be called only under rcu_lock */
14581da177e4SLinus Torvalds
sock_wake_async(struct socket_wq * wq,int how,int band)1459ceb5d58bSEric Dumazet int sock_wake_async(struct socket_wq *wq, int how, int band)
14601da177e4SLinus Torvalds {
1461ceb5d58bSEric Dumazet if (!wq || !wq->fasync_list)
1462ceb5d58bSEric Dumazet return -1;
146343815482SEric Dumazet
146489bddce5SStephen Hemminger switch (how) {
14658d8ad9d7SPavel Emelyanov case SOCK_WAKE_WAITD:
1466ceb5d58bSEric Dumazet if (test_bit(SOCKWQ_ASYNC_WAITDATA, &wq->flags))
14671da177e4SLinus Torvalds break;
14681da177e4SLinus Torvalds goto call_kill;
14698d8ad9d7SPavel Emelyanov case SOCK_WAKE_SPACE:
1470ceb5d58bSEric Dumazet if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags))
14711da177e4SLinus Torvalds break;
14727c7ab580SMiaohe Lin fallthrough;
14738d8ad9d7SPavel Emelyanov case SOCK_WAKE_IO:
14741da177e4SLinus Torvalds call_kill:
147543815482SEric Dumazet kill_fasync(&wq->fasync_list, SIGIO, band);
14761da177e4SLinus Torvalds break;
14778d8ad9d7SPavel Emelyanov case SOCK_WAKE_URG:
147843815482SEric Dumazet kill_fasync(&wq->fasync_list, SIGURG, band);
14791da177e4SLinus Torvalds }
1480ceb5d58bSEric Dumazet
14811da177e4SLinus Torvalds return 0;
14821da177e4SLinus Torvalds }
1483c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
14841da177e4SLinus Torvalds
14858a3c245cSPedro Tammela /**
14868a3c245cSPedro Tammela * __sock_create - creates a socket
14878a3c245cSPedro Tammela * @net: net namespace
14888a3c245cSPedro Tammela * @family: protocol family (AF_INET, ...)
14898a3c245cSPedro Tammela * @type: communication type (SOCK_STREAM, ...)
14908a3c245cSPedro Tammela * @protocol: protocol (0, ...)
14918a3c245cSPedro Tammela * @res: new socket
14928a3c245cSPedro Tammela * @kern: boolean for kernel space sockets
14938a3c245cSPedro Tammela *
14948a3c245cSPedro Tammela * Creates a new socket and assigns it to @res, passing through LSM.
14958a3c245cSPedro Tammela * Returns 0 or an error. On failure @res is set to %NULL. @kern must
14968a3c245cSPedro Tammela * be set to true if the socket resides in kernel space.
14978a3c245cSPedro Tammela * This function internally uses GFP_KERNEL.
14988a3c245cSPedro Tammela */
14998a3c245cSPedro Tammela
__sock_create(struct net * net,int family,int type,int protocol,struct socket ** res,int kern)1500721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
150189bddce5SStephen Hemminger struct socket **res, int kern)
15021da177e4SLinus Torvalds {
15031da177e4SLinus Torvalds int err;
15041da177e4SLinus Torvalds struct socket *sock;
150555737fdaSStephen Hemminger const struct net_proto_family *pf;
15061da177e4SLinus Torvalds
15071da177e4SLinus Torvalds /*
15081da177e4SLinus Torvalds * Check protocol is in range
15091da177e4SLinus Torvalds */
15101da177e4SLinus Torvalds if (family < 0 || family >= NPROTO)
15111da177e4SLinus Torvalds return -EAFNOSUPPORT;
15121da177e4SLinus Torvalds if (type < 0 || type >= SOCK_MAX)
15131da177e4SLinus Torvalds return -EINVAL;
15141da177e4SLinus Torvalds
15151da177e4SLinus Torvalds /* Compatibility.
15161da177e4SLinus Torvalds
15171da177e4SLinus Torvalds This uglymoron is moved from INET layer to here to avoid
15181da177e4SLinus Torvalds deadlock in module load.
15191da177e4SLinus Torvalds */
15201da177e4SLinus Torvalds if (family == PF_INET && type == SOCK_PACKET) {
1521f3c98690Sliping.zhang pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n",
152289bddce5SStephen Hemminger current->comm);
15231da177e4SLinus Torvalds family = PF_PACKET;
15241da177e4SLinus Torvalds }
15251da177e4SLinus Torvalds
15261da177e4SLinus Torvalds err = security_socket_create(family, type, protocol, kern);
15271da177e4SLinus Torvalds if (err)
15281da177e4SLinus Torvalds return err;
15291da177e4SLinus Torvalds
153055737fdaSStephen Hemminger /*
153155737fdaSStephen Hemminger * Allocate the socket and allow the family to set things up. if
153255737fdaSStephen Hemminger * the protocol is 0, the family is instructed to select an appropriate
153355737fdaSStephen Hemminger * default.
153455737fdaSStephen Hemminger */
153555737fdaSStephen Hemminger sock = sock_alloc();
153655737fdaSStephen Hemminger if (!sock) {
1537e87cc472SJoe Perches net_warn_ratelimited("socket: no more sockets\n");
153855737fdaSStephen Hemminger return -ENFILE; /* Not exactly a match, but its the
153955737fdaSStephen Hemminger closest posix thing */
154055737fdaSStephen Hemminger }
154155737fdaSStephen Hemminger
154255737fdaSStephen Hemminger sock->type = type;
154355737fdaSStephen Hemminger
154495a5afcaSJohannes Berg #ifdef CONFIG_MODULES
15451da177e4SLinus Torvalds /* Attempt to load a protocol module if the find failed.
15461da177e4SLinus Torvalds *
15471da177e4SLinus Torvalds * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
15481da177e4SLinus Torvalds * requested real, full-featured networking support upon configuration.
15491da177e4SLinus Torvalds * Otherwise module support will break!
15501da177e4SLinus Torvalds */
1551190683a9SEric Dumazet if (rcu_access_pointer(net_families[family]) == NULL)
15521da177e4SLinus Torvalds request_module("net-pf-%d", family);
15531da177e4SLinus Torvalds #endif
15541da177e4SLinus Torvalds
155555737fdaSStephen Hemminger rcu_read_lock();
155655737fdaSStephen Hemminger pf = rcu_dereference(net_families[family]);
15571da177e4SLinus Torvalds err = -EAFNOSUPPORT;
155855737fdaSStephen Hemminger if (!pf)
155955737fdaSStephen Hemminger goto out_release;
15601da177e4SLinus Torvalds
15611da177e4SLinus Torvalds /*
15621da177e4SLinus Torvalds * We will call the ->create function, that possibly is in a loadable
15631da177e4SLinus Torvalds * module, so we have to bump that loadable module refcnt first.
15641da177e4SLinus Torvalds */
156555737fdaSStephen Hemminger if (!try_module_get(pf->owner))
15661da177e4SLinus Torvalds goto out_release;
15671da177e4SLinus Torvalds
156855737fdaSStephen Hemminger /* Now protected by module ref count */
156955737fdaSStephen Hemminger rcu_read_unlock();
157055737fdaSStephen Hemminger
15713f378b68SEric Paris err = pf->create(net, sock, protocol, kern);
1572*563e6892SIgnat Korchagin if (err < 0) {
1573*563e6892SIgnat Korchagin /* ->create should release the allocated sock->sk object on error
1574*563e6892SIgnat Korchagin * but it may leave the dangling pointer
1575*563e6892SIgnat Korchagin */
1576*563e6892SIgnat Korchagin sock->sk = NULL;
15771da177e4SLinus Torvalds goto out_module_put;
1578*563e6892SIgnat Korchagin }
1579a79af59eSFrank Filz
15801da177e4SLinus Torvalds /*
15811da177e4SLinus Torvalds * Now to bump the refcnt of the [loadable] module that owns this
15821da177e4SLinus Torvalds * socket at sock_release time we decrement its refcnt.
15831da177e4SLinus Torvalds */
158455737fdaSStephen Hemminger if (!try_module_get(sock->ops->owner))
158555737fdaSStephen Hemminger goto out_module_busy;
158655737fdaSStephen Hemminger
15871da177e4SLinus Torvalds /*
15881da177e4SLinus Torvalds * Now that we're done with the ->create function, the [loadable]
15891da177e4SLinus Torvalds * module can have its refcnt decremented
15901da177e4SLinus Torvalds */
159155737fdaSStephen Hemminger module_put(pf->owner);
15927420ed23SVenkat Yekkirala err = security_socket_post_create(sock, family, type, protocol, kern);
15937420ed23SVenkat Yekkirala if (err)
15943b185525SHerbert Xu goto out_sock_release;
159555737fdaSStephen Hemminger *res = sock;
15961da177e4SLinus Torvalds
159755737fdaSStephen Hemminger return 0;
159855737fdaSStephen Hemminger
159955737fdaSStephen Hemminger out_module_busy:
160055737fdaSStephen Hemminger err = -EAFNOSUPPORT;
16011da177e4SLinus Torvalds out_module_put:
160255737fdaSStephen Hemminger sock->ops = NULL;
160355737fdaSStephen Hemminger module_put(pf->owner);
160455737fdaSStephen Hemminger out_sock_release:
16051da177e4SLinus Torvalds sock_release(sock);
160655737fdaSStephen Hemminger return err;
160755737fdaSStephen Hemminger
160855737fdaSStephen Hemminger out_release:
160955737fdaSStephen Hemminger rcu_read_unlock();
161055737fdaSStephen Hemminger goto out_sock_release;
16111da177e4SLinus Torvalds }
1612721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
16131da177e4SLinus Torvalds
16148a3c245cSPedro Tammela /**
16158a3c245cSPedro Tammela * sock_create - creates a socket
16168a3c245cSPedro Tammela * @family: protocol family (AF_INET, ...)
16178a3c245cSPedro Tammela * @type: communication type (SOCK_STREAM, ...)
16188a3c245cSPedro Tammela * @protocol: protocol (0, ...)
16198a3c245cSPedro Tammela * @res: new socket
16208a3c245cSPedro Tammela *
16218a3c245cSPedro Tammela * A wrapper around __sock_create().
16228a3c245cSPedro Tammela * Returns 0 or an error. This function internally uses GFP_KERNEL.
16238a3c245cSPedro Tammela */
16248a3c245cSPedro Tammela
sock_create(int family,int type,int protocol,struct socket ** res)16251da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
16261da177e4SLinus Torvalds {
16271b8d7ae4SEric W. Biederman return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
16281da177e4SLinus Torvalds }
1629c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
16301da177e4SLinus Torvalds
16318a3c245cSPedro Tammela /**
16328a3c245cSPedro Tammela * sock_create_kern - creates a socket (kernel space)
16338a3c245cSPedro Tammela * @net: net namespace
16348a3c245cSPedro Tammela * @family: protocol family (AF_INET, ...)
16358a3c245cSPedro Tammela * @type: communication type (SOCK_STREAM, ...)
16368a3c245cSPedro Tammela * @protocol: protocol (0, ...)
16378a3c245cSPedro Tammela * @res: new socket
16388a3c245cSPedro Tammela *
16398a3c245cSPedro Tammela * A wrapper around __sock_create().
16408a3c245cSPedro Tammela * Returns 0 or an error. This function internally uses GFP_KERNEL.
16418a3c245cSPedro Tammela */
16428a3c245cSPedro Tammela
sock_create_kern(struct net * net,int family,int type,int protocol,struct socket ** res)1643eeb1bd5cSEric W. Biederman int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res)
16441da177e4SLinus Torvalds {
1645eeb1bd5cSEric W. Biederman return __sock_create(net, family, type, protocol, res, 1);
16461da177e4SLinus Torvalds }
1647c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
16481da177e4SLinus Torvalds
__sys_socket_create(int family,int type,int protocol)1649da214a47SJens Axboe static struct socket *__sys_socket_create(int family, int type, int protocol)
16501da177e4SLinus Torvalds {
16511da177e4SLinus Torvalds struct socket *sock;
1652da214a47SJens Axboe int retval;
1653a677a039SUlrich Drepper
1654e38b36f3SUlrich Drepper /* Check the SOCK_* constants for consistency. */
1655e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1656e38b36f3SUlrich Drepper BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1657e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1658e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1659e38b36f3SUlrich Drepper
1660da214a47SJens Axboe if ((type & ~SOCK_TYPE_MASK) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1661da214a47SJens Axboe return ERR_PTR(-EINVAL);
1662a677a039SUlrich Drepper type &= SOCK_TYPE_MASK;
16631da177e4SLinus Torvalds
16641da177e4SLinus Torvalds retval = sock_create(family, type, protocol, &sock);
16651da177e4SLinus Torvalds if (retval < 0)
1666da214a47SJens Axboe return ERR_PTR(retval);
1667da214a47SJens Axboe
1668da214a47SJens Axboe return sock;
1669da214a47SJens Axboe }
1670da214a47SJens Axboe
__sys_socket_file(int family,int type,int protocol)1671da214a47SJens Axboe struct file *__sys_socket_file(int family, int type, int protocol)
1672da214a47SJens Axboe {
1673da214a47SJens Axboe struct socket *sock;
1674da214a47SJens Axboe int flags;
1675da214a47SJens Axboe
1676da214a47SJens Axboe sock = __sys_socket_create(family, type, protocol);
1677da214a47SJens Axboe if (IS_ERR(sock))
1678da214a47SJens Axboe return ERR_CAST(sock);
1679da214a47SJens Axboe
1680da214a47SJens Axboe flags = type & ~SOCK_TYPE_MASK;
1681da214a47SJens Axboe if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1682da214a47SJens Axboe flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1683da214a47SJens Axboe
1684649c15c7SThadeu Lima de Souza Cascardo return sock_alloc_file(sock, flags, NULL);
1685da214a47SJens Axboe }
1686da214a47SJens Axboe
16870dd061a6SGeliang Tang /* A hook for bpf progs to attach to and update socket protocol.
16880dd061a6SGeliang Tang *
16890dd061a6SGeliang Tang * A static noinline declaration here could cause the compiler to
16900dd061a6SGeliang Tang * optimize away the function. A global noinline declaration will
16910dd061a6SGeliang Tang * keep the definition, but may optimize away the callsite.
16920dd061a6SGeliang Tang * Therefore, __weak is needed to ensure that the call is still
16930dd061a6SGeliang Tang * emitted, by telling the compiler that we don't know what the
16940dd061a6SGeliang Tang * function might eventually be.
16950dd061a6SGeliang Tang *
16960dd061a6SGeliang Tang * __diag_* below are needed to dismiss the missing prototype warning.
16970dd061a6SGeliang Tang */
16980dd061a6SGeliang Tang
16990dd061a6SGeliang Tang __diag_push();
17000dd061a6SGeliang Tang __diag_ignore_all("-Wmissing-prototypes",
17010dd061a6SGeliang Tang "A fmod_ret entry point for BPF programs");
17020dd061a6SGeliang Tang
update_socket_protocol(int family,int type,int protocol)17030dd061a6SGeliang Tang __weak noinline int update_socket_protocol(int family, int type, int protocol)
17040dd061a6SGeliang Tang {
17050dd061a6SGeliang Tang return protocol;
17060dd061a6SGeliang Tang }
17070dd061a6SGeliang Tang
17080dd061a6SGeliang Tang __diag_pop();
17090dd061a6SGeliang Tang
__sys_socket(int family,int type,int protocol)1710da214a47SJens Axboe int __sys_socket(int family, int type, int protocol)
1711da214a47SJens Axboe {
1712da214a47SJens Axboe struct socket *sock;
1713da214a47SJens Axboe int flags;
1714da214a47SJens Axboe
17150dd061a6SGeliang Tang sock = __sys_socket_create(family, type,
17160dd061a6SGeliang Tang update_socket_protocol(family, type, protocol));
1717da214a47SJens Axboe if (IS_ERR(sock))
1718da214a47SJens Axboe return PTR_ERR(sock);
1719da214a47SJens Axboe
1720da214a47SJens Axboe flags = type & ~SOCK_TYPE_MASK;
1721da214a47SJens Axboe if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1722da214a47SJens Axboe flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
17231da177e4SLinus Torvalds
17248e1611e2SAl Viro return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
17251da177e4SLinus Torvalds }
17261da177e4SLinus Torvalds
SYSCALL_DEFINE3(socket,int,family,int,type,int,protocol)17279d6a15c3SDominik Brodowski SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
17289d6a15c3SDominik Brodowski {
17299d6a15c3SDominik Brodowski return __sys_socket(family, type, protocol);
17309d6a15c3SDominik Brodowski }
17319d6a15c3SDominik Brodowski
17321da177e4SLinus Torvalds /*
17331da177e4SLinus Torvalds * Create a pair of connected sockets.
17341da177e4SLinus Torvalds */
17351da177e4SLinus Torvalds
__sys_socketpair(int family,int type,int protocol,int __user * usockvec)17366debc8d8SDominik Brodowski int __sys_socketpair(int family, int type, int protocol, int __user *usockvec)
17371da177e4SLinus Torvalds {
17381da177e4SLinus Torvalds struct socket *sock1, *sock2;
17391da177e4SLinus Torvalds int fd1, fd2, err;
1740db349509SAl Viro struct file *newfile1, *newfile2;
1741a677a039SUlrich Drepper int flags;
1742a677a039SUlrich Drepper
1743a677a039SUlrich Drepper flags = type & ~SOCK_TYPE_MASK;
174477d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1745a677a039SUlrich Drepper return -EINVAL;
1746a677a039SUlrich Drepper type &= SOCK_TYPE_MASK;
17471da177e4SLinus Torvalds
1748aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1749aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1750aaca0bdcSUlrich Drepper
17511da177e4SLinus Torvalds /*
1752016a266bSAl Viro * reserve descriptors and make sure we won't fail
1753016a266bSAl Viro * to return them to userland.
1754016a266bSAl Viro */
1755016a266bSAl Viro fd1 = get_unused_fd_flags(flags);
1756016a266bSAl Viro if (unlikely(fd1 < 0))
1757016a266bSAl Viro return fd1;
1758016a266bSAl Viro
1759016a266bSAl Viro fd2 = get_unused_fd_flags(flags);
1760016a266bSAl Viro if (unlikely(fd2 < 0)) {
1761016a266bSAl Viro put_unused_fd(fd1);
1762016a266bSAl Viro return fd2;
1763016a266bSAl Viro }
1764016a266bSAl Viro
1765016a266bSAl Viro err = put_user(fd1, &usockvec[0]);
1766016a266bSAl Viro if (err)
1767016a266bSAl Viro goto out;
1768016a266bSAl Viro
1769016a266bSAl Viro err = put_user(fd2, &usockvec[1]);
1770016a266bSAl Viro if (err)
1771016a266bSAl Viro goto out;
1772016a266bSAl Viro
1773016a266bSAl Viro /*
17741da177e4SLinus Torvalds * Obtain the first socket and check if the underlying protocol
17751da177e4SLinus Torvalds * supports the socketpair call.
17761da177e4SLinus Torvalds */
17771da177e4SLinus Torvalds
17781da177e4SLinus Torvalds err = sock_create(family, type, protocol, &sock1);
1779016a266bSAl Viro if (unlikely(err < 0))
17801da177e4SLinus Torvalds goto out;
17811da177e4SLinus Torvalds
17821da177e4SLinus Torvalds err = sock_create(family, type, protocol, &sock2);
1783016a266bSAl Viro if (unlikely(err < 0)) {
1784016a266bSAl Viro sock_release(sock1);
1785016a266bSAl Viro goto out;
1786bf3c23d1SDavid S. Miller }
1787d73aa286SYann Droneaud
1788d47cd945SDavid Herrmann err = security_socket_socketpair(sock1, sock2);
1789d47cd945SDavid Herrmann if (unlikely(err)) {
1790d47cd945SDavid Herrmann sock_release(sock2);
1791d47cd945SDavid Herrmann sock_release(sock1);
1792d47cd945SDavid Herrmann goto out;
1793d47cd945SDavid Herrmann }
1794d47cd945SDavid Herrmann
17951ded5e5aSEric Dumazet err = READ_ONCE(sock1->ops)->socketpair(sock1, sock2);
1796016a266bSAl Viro if (unlikely(err < 0)) {
1797016a266bSAl Viro sock_release(sock2);
1798016a266bSAl Viro sock_release(sock1);
1799016a266bSAl Viro goto out;
180028407630SAl Viro }
180128407630SAl Viro
1802aab174f0SLinus Torvalds newfile1 = sock_alloc_file(sock1, flags, NULL);
1803b5ffe634SViresh Kumar if (IS_ERR(newfile1)) {
180428407630SAl Viro err = PTR_ERR(newfile1);
1805016a266bSAl Viro sock_release(sock2);
1806016a266bSAl Viro goto out;
180728407630SAl Viro }
180828407630SAl Viro
1809aab174f0SLinus Torvalds newfile2 = sock_alloc_file(sock2, flags, NULL);
181028407630SAl Viro if (IS_ERR(newfile2)) {
181128407630SAl Viro err = PTR_ERR(newfile2);
1812016a266bSAl Viro fput(newfile1);
1813016a266bSAl Viro goto out;
1814db349509SAl Viro }
1815db349509SAl Viro
1816157cf649SAl Viro audit_fd_pair(fd1, fd2);
1817d73aa286SYann Droneaud
1818db349509SAl Viro fd_install(fd1, newfile1);
1819db349509SAl Viro fd_install(fd2, newfile2);
18201da177e4SLinus Torvalds return 0;
18211da177e4SLinus Torvalds
18221da177e4SLinus Torvalds out:
1823016a266bSAl Viro put_unused_fd(fd2);
1824016a266bSAl Viro put_unused_fd(fd1);
18251da177e4SLinus Torvalds return err;
18261da177e4SLinus Torvalds }
18271da177e4SLinus Torvalds
SYSCALL_DEFINE4(socketpair,int,family,int,type,int,protocol,int __user *,usockvec)18286debc8d8SDominik Brodowski SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
18296debc8d8SDominik Brodowski int __user *, usockvec)
18306debc8d8SDominik Brodowski {
18316debc8d8SDominik Brodowski return __sys_socketpair(family, type, protocol, usockvec);
18326debc8d8SDominik Brodowski }
18336debc8d8SDominik Brodowski
18341da177e4SLinus Torvalds /*
18351da177e4SLinus Torvalds * Bind a name to a socket. Nothing much to do here since it's
18361da177e4SLinus Torvalds * the protocol's responsibility to handle the local address.
18371da177e4SLinus Torvalds *
18381da177e4SLinus Torvalds * We move the socket address to kernel space before we call
18391da177e4SLinus Torvalds * the protocol layer (having also checked the address is ok).
18401da177e4SLinus Torvalds */
18411da177e4SLinus Torvalds
__sys_bind(int fd,struct sockaddr __user * umyaddr,int addrlen)1842a87d35d8SDominik Brodowski int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
18431da177e4SLinus Torvalds {
18441da177e4SLinus Torvalds struct socket *sock;
1845230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address;
18466cb153caSBenjamin LaHaise int err, fput_needed;
18471da177e4SLinus Torvalds
184889bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed);
184989bddce5SStephen Hemminger if (sock) {
185043db362dSMaciej Żenczykowski err = move_addr_to_kernel(umyaddr, addrlen, &address);
1851068b88ccSJakub Sitnicki if (!err) {
185289bddce5SStephen Hemminger err = security_socket_bind(sock,
1853230b1839SYOSHIFUJI Hideaki (struct sockaddr *)&address,
185489bddce5SStephen Hemminger addrlen);
18556cb153caSBenjamin LaHaise if (!err)
18561ded5e5aSEric Dumazet err = READ_ONCE(sock->ops)->bind(sock,
185789bddce5SStephen Hemminger (struct sockaddr *)
1858230b1839SYOSHIFUJI Hideaki &address, addrlen);
18591da177e4SLinus Torvalds }
18606cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed);
18611da177e4SLinus Torvalds }
18621da177e4SLinus Torvalds return err;
18631da177e4SLinus Torvalds }
18641da177e4SLinus Torvalds
SYSCALL_DEFINE3(bind,int,fd,struct sockaddr __user *,umyaddr,int,addrlen)1865a87d35d8SDominik Brodowski SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
1866a87d35d8SDominik Brodowski {
1867a87d35d8SDominik Brodowski return __sys_bind(fd, umyaddr, addrlen);
1868a87d35d8SDominik Brodowski }
1869a87d35d8SDominik Brodowski
18701da177e4SLinus Torvalds /*
18711da177e4SLinus Torvalds * Perform a listen. Basically, we allow the protocol to do anything
18721da177e4SLinus Torvalds * necessary for a listen, and if that works, we mark the socket as
18731da177e4SLinus Torvalds * ready for listening.
18741da177e4SLinus Torvalds */
18751da177e4SLinus Torvalds
__sys_listen(int fd,int backlog)187625e290eeSDominik Brodowski int __sys_listen(int fd, int backlog)
18771da177e4SLinus Torvalds {
18781da177e4SLinus Torvalds struct socket *sock;
18796cb153caSBenjamin LaHaise int err, fput_needed;
1880b8e1f9b5SPavel Emelyanov int somaxconn;
18811da177e4SLinus Torvalds
188289bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed);
188389bddce5SStephen Hemminger if (sock) {
18843c9ba81dSKuniyuki Iwashima somaxconn = READ_ONCE(sock_net(sock->sk)->core.sysctl_somaxconn);
188595c96174SEric Dumazet if ((unsigned int)backlog > somaxconn)
1886b8e1f9b5SPavel Emelyanov backlog = somaxconn;
18871da177e4SLinus Torvalds
18881da177e4SLinus Torvalds err = security_socket_listen(sock, backlog);
18896cb153caSBenjamin LaHaise if (!err)
18901ded5e5aSEric Dumazet err = READ_ONCE(sock->ops)->listen(sock, backlog);
18916cb153caSBenjamin LaHaise
18926cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed);
18931da177e4SLinus Torvalds }
18941da177e4SLinus Torvalds return err;
18951da177e4SLinus Torvalds }
18961da177e4SLinus Torvalds
SYSCALL_DEFINE2(listen,int,fd,int,backlog)189725e290eeSDominik Brodowski SYSCALL_DEFINE2(listen, int, fd, int, backlog)
189825e290eeSDominik Brodowski {
189925e290eeSDominik Brodowski return __sys_listen(fd, backlog);
190025e290eeSDominik Brodowski }
190125e290eeSDominik Brodowski
do_accept(struct file * file,unsigned file_flags,struct sockaddr __user * upeer_sockaddr,int __user * upeer_addrlen,int flags)1902d32f89daSPavel Begunkov struct file *do_accept(struct file *file, unsigned file_flags,
1903de2ea4b6SJens Axboe struct sockaddr __user *upeer_sockaddr,
1904d32f89daSPavel Begunkov int __user *upeer_addrlen, int flags)
19051da177e4SLinus Torvalds {
19061da177e4SLinus Torvalds struct socket *sock, *newsock;
190739d8c1b6SDavid S. Miller struct file *newfile;
1908d32f89daSPavel Begunkov int err, len;
1909230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address;
19101ded5e5aSEric Dumazet const struct proto_ops *ops;
19111da177e4SLinus Torvalds
1912dba4a925SFlorent Revest sock = sock_from_file(file);
1913d32f89daSPavel Begunkov if (!sock)
1914d32f89daSPavel Begunkov return ERR_PTR(-ENOTSOCK);
19151da177e4SLinus Torvalds
1916c6d409cfSEric Dumazet newsock = sock_alloc();
1917c6d409cfSEric Dumazet if (!newsock)
1918d32f89daSPavel Begunkov return ERR_PTR(-ENFILE);
19191ded5e5aSEric Dumazet ops = READ_ONCE(sock->ops);
19201da177e4SLinus Torvalds
19211da177e4SLinus Torvalds newsock->type = sock->type;
19221ded5e5aSEric Dumazet newsock->ops = ops;
19231da177e4SLinus Torvalds
19241da177e4SLinus Torvalds /*
19251da177e4SLinus Torvalds * We don't need try_module_get here, as the listening socket (sock)
19261da177e4SLinus Torvalds * has the protocol module (sock->ops->owner) held.
19271da177e4SLinus Torvalds */
19281ded5e5aSEric Dumazet __module_get(ops->owner);
19291da177e4SLinus Torvalds
1930aab174f0SLinus Torvalds newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
1931d32f89daSPavel Begunkov if (IS_ERR(newfile))
1932d32f89daSPavel Begunkov return newfile;
193339d8c1b6SDavid S. Miller
1934a79af59eSFrank Filz err = security_socket_accept(sock, newsock);
1935a79af59eSFrank Filz if (err)
193639d8c1b6SDavid S. Miller goto out_fd;
1937a79af59eSFrank Filz
19381ded5e5aSEric Dumazet err = ops->accept(sock, newsock, sock->file->f_flags | file_flags,
1939de2ea4b6SJens Axboe false);
19401da177e4SLinus Torvalds if (err < 0)
194139d8c1b6SDavid S. Miller goto out_fd;
19421da177e4SLinus Torvalds
19431da177e4SLinus Torvalds if (upeer_sockaddr) {
19441ded5e5aSEric Dumazet len = ops->getname(newsock, (struct sockaddr *)&address, 2);
19459b2c45d4SDenys Vlasenko if (len < 0) {
19461da177e4SLinus Torvalds err = -ECONNABORTED;
194739d8c1b6SDavid S. Miller goto out_fd;
19481da177e4SLinus Torvalds }
194943db362dSMaciej Żenczykowski err = move_addr_to_user(&address,
1950230b1839SYOSHIFUJI Hideaki len, upeer_sockaddr, upeer_addrlen);
19511da177e4SLinus Torvalds if (err < 0)
195239d8c1b6SDavid S. Miller goto out_fd;
19531da177e4SLinus Torvalds }
19541da177e4SLinus Torvalds
19551da177e4SLinus Torvalds /* File flags are not inherited via accept() unlike another OSes. */
1956d32f89daSPavel Begunkov return newfile;
195739d8c1b6SDavid S. Miller out_fd:
19589606a216SDavid S. Miller fput(newfile);
1959d32f89daSPavel Begunkov return ERR_PTR(err);
1960d32f89daSPavel Begunkov }
1961de2ea4b6SJens Axboe
__sys_accept4_file(struct file * file,struct sockaddr __user * upeer_sockaddr,int __user * upeer_addrlen,int flags)1962c0424532SYajun Deng static int __sys_accept4_file(struct file *file, struct sockaddr __user *upeer_sockaddr,
1963c0424532SYajun Deng int __user *upeer_addrlen, int flags)
1964d32f89daSPavel Begunkov {
1965d32f89daSPavel Begunkov struct file *newfile;
1966d32f89daSPavel Begunkov int newfd;
1967d32f89daSPavel Begunkov
1968d32f89daSPavel Begunkov if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1969d32f89daSPavel Begunkov return -EINVAL;
1970d32f89daSPavel Begunkov
1971d32f89daSPavel Begunkov if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1972d32f89daSPavel Begunkov flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1973d32f89daSPavel Begunkov
1974c0424532SYajun Deng newfd = get_unused_fd_flags(flags);
1975d32f89daSPavel Begunkov if (unlikely(newfd < 0))
1976d32f89daSPavel Begunkov return newfd;
1977d32f89daSPavel Begunkov
1978c0424532SYajun Deng newfile = do_accept(file, 0, upeer_sockaddr, upeer_addrlen,
1979d32f89daSPavel Begunkov flags);
1980d32f89daSPavel Begunkov if (IS_ERR(newfile)) {
1981d32f89daSPavel Begunkov put_unused_fd(newfd);
1982d32f89daSPavel Begunkov return PTR_ERR(newfile);
1983d32f89daSPavel Begunkov }
1984d32f89daSPavel Begunkov fd_install(newfd, newfile);
1985d32f89daSPavel Begunkov return newfd;
1986de2ea4b6SJens Axboe }
1987de2ea4b6SJens Axboe
1988de2ea4b6SJens Axboe /*
1989de2ea4b6SJens Axboe * For accept, we attempt to create a new socket, set up the link
1990de2ea4b6SJens Axboe * with the client, wake up the client, then return the new
1991de2ea4b6SJens Axboe * connected fd. We collect the address of the connector in kernel
1992de2ea4b6SJens Axboe * space and move it to user at the very end. This is unclean because
1993de2ea4b6SJens Axboe * we open the socket then return an error.
1994de2ea4b6SJens Axboe *
1995de2ea4b6SJens Axboe * 1003.1g adds the ability to recvmsg() to query connection pending
1996de2ea4b6SJens Axboe * status to recvmsg. We need to add that support in a way thats
1997de2ea4b6SJens Axboe * clean when we restructure accept also.
1998de2ea4b6SJens Axboe */
1999de2ea4b6SJens Axboe
__sys_accept4(int fd,struct sockaddr __user * upeer_sockaddr,int __user * upeer_addrlen,int flags)2000de2ea4b6SJens Axboe int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
2001de2ea4b6SJens Axboe int __user *upeer_addrlen, int flags)
2002de2ea4b6SJens Axboe {
2003de2ea4b6SJens Axboe int ret = -EBADF;
2004de2ea4b6SJens Axboe struct fd f;
2005de2ea4b6SJens Axboe
2006de2ea4b6SJens Axboe f = fdget(fd);
2007de2ea4b6SJens Axboe if (f.file) {
2008c0424532SYajun Deng ret = __sys_accept4_file(f.file, upeer_sockaddr,
2009c0424532SYajun Deng upeer_addrlen, flags);
20106b07edebSMiaohe Lin fdput(f);
2011de2ea4b6SJens Axboe }
2012de2ea4b6SJens Axboe
2013de2ea4b6SJens Axboe return ret;
20141da177e4SLinus Torvalds }
20151da177e4SLinus Torvalds
SYSCALL_DEFINE4(accept4,int,fd,struct sockaddr __user *,upeer_sockaddr,int __user *,upeer_addrlen,int,flags)20164541e805SDominik Brodowski SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
20174541e805SDominik Brodowski int __user *, upeer_addrlen, int, flags)
20184541e805SDominik Brodowski {
20194541e805SDominik Brodowski return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, flags);
20204541e805SDominik Brodowski }
20214541e805SDominik Brodowski
SYSCALL_DEFINE3(accept,int,fd,struct sockaddr __user *,upeer_sockaddr,int __user *,upeer_addrlen)202220f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
202320f37034SHeiko Carstens int __user *, upeer_addrlen)
2024aaca0bdcSUlrich Drepper {
20254541e805SDominik Brodowski return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
2026aaca0bdcSUlrich Drepper }
2027aaca0bdcSUlrich Drepper
20281da177e4SLinus Torvalds /*
20291da177e4SLinus Torvalds * Attempt to connect to a socket with the server address. The address
20301da177e4SLinus Torvalds * is in user space so we verify it is OK and move it to kernel space.
20311da177e4SLinus Torvalds *
20321da177e4SLinus Torvalds * For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
20331da177e4SLinus Torvalds * break bindings
20341da177e4SLinus Torvalds *
20351da177e4SLinus Torvalds * NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
20361da177e4SLinus Torvalds * other SEQPACKET protocols that take time to connect() as it doesn't
20371da177e4SLinus Torvalds * include the -EINPROGRESS status for such sockets.
20381da177e4SLinus Torvalds */
20391da177e4SLinus Torvalds
__sys_connect_file(struct file * file,struct sockaddr_storage * address,int addrlen,int file_flags)2040f499a021SJens Axboe int __sys_connect_file(struct file *file, struct sockaddr_storage *address,
2041bd3ded31SJens Axboe int addrlen, int file_flags)
20421da177e4SLinus Torvalds {
20431da177e4SLinus Torvalds struct socket *sock;
2044bd3ded31SJens Axboe int err;
20451da177e4SLinus Torvalds
2046dba4a925SFlorent Revest sock = sock_from_file(file);
2047dba4a925SFlorent Revest if (!sock) {
2048dba4a925SFlorent Revest err = -ENOTSOCK;
20491da177e4SLinus Torvalds goto out;
2050dba4a925SFlorent Revest }
20511da177e4SLinus Torvalds
205289bddce5SStephen Hemminger err =
2053f499a021SJens Axboe security_socket_connect(sock, (struct sockaddr *)address, addrlen);
20541da177e4SLinus Torvalds if (err)
2055bd3ded31SJens Axboe goto out;
20561da177e4SLinus Torvalds
20571ded5e5aSEric Dumazet err = READ_ONCE(sock->ops)->connect(sock, (struct sockaddr *)address,
20581ded5e5aSEric Dumazet addrlen, sock->file->f_flags | file_flags);
20591da177e4SLinus Torvalds out:
20601da177e4SLinus Torvalds return err;
20611da177e4SLinus Torvalds }
20621da177e4SLinus Torvalds
__sys_connect(int fd,struct sockaddr __user * uservaddr,int addrlen)2063bd3ded31SJens Axboe int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
2064bd3ded31SJens Axboe {
2065bd3ded31SJens Axboe int ret = -EBADF;
2066bd3ded31SJens Axboe struct fd f;
2067bd3ded31SJens Axboe
2068bd3ded31SJens Axboe f = fdget(fd);
2069bd3ded31SJens Axboe if (f.file) {
2070f499a021SJens Axboe struct sockaddr_storage address;
2071f499a021SJens Axboe
2072f499a021SJens Axboe ret = move_addr_to_kernel(uservaddr, addrlen, &address);
2073f499a021SJens Axboe if (!ret)
2074f499a021SJens Axboe ret = __sys_connect_file(f.file, &address, addrlen, 0);
20756b07edebSMiaohe Lin fdput(f);
2076bd3ded31SJens Axboe }
2077bd3ded31SJens Axboe
2078bd3ded31SJens Axboe return ret;
2079bd3ded31SJens Axboe }
2080bd3ded31SJens Axboe
SYSCALL_DEFINE3(connect,int,fd,struct sockaddr __user *,uservaddr,int,addrlen)20811387c2c2SDominik Brodowski SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
20821387c2c2SDominik Brodowski int, addrlen)
20831387c2c2SDominik Brodowski {
20841387c2c2SDominik Brodowski return __sys_connect(fd, uservaddr, addrlen);
20851387c2c2SDominik Brodowski }
20861387c2c2SDominik Brodowski
20871da177e4SLinus Torvalds /*
20881da177e4SLinus Torvalds * Get the local address ('name') of a socket object. Move the obtained
20891da177e4SLinus Torvalds * name to user space.
20901da177e4SLinus Torvalds */
20911da177e4SLinus Torvalds
__sys_getsockname(int fd,struct sockaddr __user * usockaddr,int __user * usockaddr_len)20928882a107SDominik Brodowski int __sys_getsockname(int fd, struct sockaddr __user *usockaddr,
20938882a107SDominik Brodowski int __user *usockaddr_len)
20941da177e4SLinus Torvalds {
20951da177e4SLinus Torvalds struct socket *sock;
2096230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address;
20979b2c45d4SDenys Vlasenko int err, fput_needed;
20981da177e4SLinus Torvalds
20996cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed);
21001da177e4SLinus Torvalds if (!sock)
21011da177e4SLinus Torvalds goto out;
21021da177e4SLinus Torvalds
21031da177e4SLinus Torvalds err = security_socket_getsockname(sock);
21041da177e4SLinus Torvalds if (err)
21051da177e4SLinus Torvalds goto out_put;
21061da177e4SLinus Torvalds
21071ded5e5aSEric Dumazet err = READ_ONCE(sock->ops)->getname(sock, (struct sockaddr *)&address, 0);
21089b2c45d4SDenys Vlasenko if (err < 0)
21091da177e4SLinus Torvalds goto out_put;
21109b2c45d4SDenys Vlasenko /* "err" is actually length in this case */
21119b2c45d4SDenys Vlasenko err = move_addr_to_user(&address, err, usockaddr, usockaddr_len);
21121da177e4SLinus Torvalds
21131da177e4SLinus Torvalds out_put:
21146cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed);
21151da177e4SLinus Torvalds out:
21161da177e4SLinus Torvalds return err;
21171da177e4SLinus Torvalds }
21181da177e4SLinus Torvalds
SYSCALL_DEFINE3(getsockname,int,fd,struct sockaddr __user *,usockaddr,int __user *,usockaddr_len)21198882a107SDominik Brodowski SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
21208882a107SDominik Brodowski int __user *, usockaddr_len)
21218882a107SDominik Brodowski {
21228882a107SDominik Brodowski return __sys_getsockname(fd, usockaddr, usockaddr_len);
21238882a107SDominik Brodowski }
21248882a107SDominik Brodowski
21251da177e4SLinus Torvalds /*
21261da177e4SLinus Torvalds * Get the remote address ('name') of a socket object. Move the obtained
21271da177e4SLinus Torvalds * name to user space.
21281da177e4SLinus Torvalds */
21291da177e4SLinus Torvalds
__sys_getpeername(int fd,struct sockaddr __user * usockaddr,int __user * usockaddr_len)2130b21c8f83SDominik Brodowski int __sys_getpeername(int fd, struct sockaddr __user *usockaddr,
2131b21c8f83SDominik Brodowski int __user *usockaddr_len)
21321da177e4SLinus Torvalds {
21331da177e4SLinus Torvalds struct socket *sock;
2134230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address;
21359b2c45d4SDenys Vlasenko int err, fput_needed;
21361da177e4SLinus Torvalds
213789bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed);
213889bddce5SStephen Hemminger if (sock != NULL) {
21391ded5e5aSEric Dumazet const struct proto_ops *ops = READ_ONCE(sock->ops);
21401ded5e5aSEric Dumazet
21411da177e4SLinus Torvalds err = security_socket_getpeername(sock);
21421da177e4SLinus Torvalds if (err) {
21436cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed);
21441da177e4SLinus Torvalds return err;
21451da177e4SLinus Torvalds }
21461da177e4SLinus Torvalds
21471ded5e5aSEric Dumazet err = ops->getname(sock, (struct sockaddr *)&address, 1);
21489b2c45d4SDenys Vlasenko if (err >= 0)
21499b2c45d4SDenys Vlasenko /* "err" is actually length in this case */
21509b2c45d4SDenys Vlasenko err = move_addr_to_user(&address, err, usockaddr,
215189bddce5SStephen Hemminger usockaddr_len);
21526cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed);
21531da177e4SLinus Torvalds }
21541da177e4SLinus Torvalds return err;
21551da177e4SLinus Torvalds }
21561da177e4SLinus Torvalds
SYSCALL_DEFINE3(getpeername,int,fd,struct sockaddr __user *,usockaddr,int __user *,usockaddr_len)2157b21c8f83SDominik Brodowski SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
2158b21c8f83SDominik Brodowski int __user *, usockaddr_len)
2159b21c8f83SDominik Brodowski {
2160b21c8f83SDominik Brodowski return __sys_getpeername(fd, usockaddr, usockaddr_len);
2161b21c8f83SDominik Brodowski }
2162b21c8f83SDominik Brodowski
21631da177e4SLinus Torvalds /*
21641da177e4SLinus Torvalds * Send a datagram to a given address. We move the address into kernel
21651da177e4SLinus Torvalds * space and check the user space data area is readable before invoking
21661da177e4SLinus Torvalds * the protocol.
21671da177e4SLinus Torvalds */
__sys_sendto(int fd,void __user * buff,size_t len,unsigned int flags,struct sockaddr __user * addr,int addr_len)2168211b634bSDominik Brodowski int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags,
2169211b634bSDominik Brodowski struct sockaddr __user *addr, int addr_len)
21701da177e4SLinus Torvalds {
21711da177e4SLinus Torvalds struct socket *sock;
2172230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address;
21731da177e4SLinus Torvalds int err;
21741da177e4SLinus Torvalds struct msghdr msg;
21751da177e4SLinus Torvalds struct iovec iov;
21766cb153caSBenjamin LaHaise int fput_needed;
21771da177e4SLinus Torvalds
2178de4eda9dSAl Viro err = import_single_range(ITER_SOURCE, buff, len, &iov, &msg.msg_iter);
2179602bd0e9SAl Viro if (unlikely(err))
2180602bd0e9SAl Viro return err;
2181de0fa95cSPavel Emelyanov sock = sockfd_lookup_light(fd, &err, &fput_needed);
2182de0fa95cSPavel Emelyanov if (!sock)
21834387ff75SDavid S. Miller goto out;
21846cb153caSBenjamin LaHaise
21851da177e4SLinus Torvalds msg.msg_name = NULL;
21861da177e4SLinus Torvalds msg.msg_control = NULL;
21871da177e4SLinus Torvalds msg.msg_controllen = 0;
21881da177e4SLinus Torvalds msg.msg_namelen = 0;
21897c701d92SPavel Begunkov msg.msg_ubuf = NULL;
21906cb153caSBenjamin LaHaise if (addr) {
219143db362dSMaciej Żenczykowski err = move_addr_to_kernel(addr, addr_len, &address);
21921da177e4SLinus Torvalds if (err < 0)
21931da177e4SLinus Torvalds goto out_put;
2194230b1839SYOSHIFUJI Hideaki msg.msg_name = (struct sockaddr *)&address;
21951da177e4SLinus Torvalds msg.msg_namelen = addr_len;
21961da177e4SLinus Torvalds }
2197b841b901SDavid Howells flags &= ~MSG_INTERNAL_SENDMSG_FLAGS;
21981da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK)
21991da177e4SLinus Torvalds flags |= MSG_DONTWAIT;
22001da177e4SLinus Torvalds msg.msg_flags = flags;
220186a7e0b6SJordan Rife err = __sock_sendmsg(sock, &msg);
22021da177e4SLinus Torvalds
22031da177e4SLinus Torvalds out_put:
2204de0fa95cSPavel Emelyanov fput_light(sock->file, fput_needed);
22054387ff75SDavid S. Miller out:
22061da177e4SLinus Torvalds return err;
22071da177e4SLinus Torvalds }
22081da177e4SLinus Torvalds
SYSCALL_DEFINE6(sendto,int,fd,void __user *,buff,size_t,len,unsigned int,flags,struct sockaddr __user *,addr,int,addr_len)2209211b634bSDominik Brodowski SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
2210211b634bSDominik Brodowski unsigned int, flags, struct sockaddr __user *, addr,
2211211b634bSDominik Brodowski int, addr_len)
2212211b634bSDominik Brodowski {
2213211b634bSDominik Brodowski return __sys_sendto(fd, buff, len, flags, addr, addr_len);
2214211b634bSDominik Brodowski }
2215211b634bSDominik Brodowski
22161da177e4SLinus Torvalds /*
22171da177e4SLinus Torvalds * Send a datagram down a socket.
22181da177e4SLinus Torvalds */
22191da177e4SLinus Torvalds
SYSCALL_DEFINE4(send,int,fd,void __user *,buff,size_t,len,unsigned int,flags)22203e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
222195c96174SEric Dumazet unsigned int, flags)
22221da177e4SLinus Torvalds {
2223211b634bSDominik Brodowski return __sys_sendto(fd, buff, len, flags, NULL, 0);
22241da177e4SLinus Torvalds }
22251da177e4SLinus Torvalds
22261da177e4SLinus Torvalds /*
22271da177e4SLinus Torvalds * Receive a frame from the socket and optionally record the address of the
22281da177e4SLinus Torvalds * sender. We verify the buffers are writable and if needed move the
22291da177e4SLinus Torvalds * sender address from kernel to user space.
22301da177e4SLinus Torvalds */
__sys_recvfrom(int fd,void __user * ubuf,size_t size,unsigned int flags,struct sockaddr __user * addr,int __user * addr_len)22317a09e1ebSDominik Brodowski int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags,
22327a09e1ebSDominik Brodowski struct sockaddr __user *addr, int __user *addr_len)
22331da177e4SLinus Torvalds {
22341228b34cSEric Dumazet struct sockaddr_storage address;
22351228b34cSEric Dumazet struct msghdr msg = {
22361228b34cSEric Dumazet /* Save some cycles and don't copy the address if not needed */
22371228b34cSEric Dumazet .msg_name = addr ? (struct sockaddr *)&address : NULL,
22381228b34cSEric Dumazet };
22391da177e4SLinus Torvalds struct socket *sock;
22401da177e4SLinus Torvalds struct iovec iov;
22411da177e4SLinus Torvalds int err, err2;
22426cb153caSBenjamin LaHaise int fput_needed;
22431da177e4SLinus Torvalds
2244de4eda9dSAl Viro err = import_single_range(ITER_DEST, ubuf, size, &iov, &msg.msg_iter);
2245602bd0e9SAl Viro if (unlikely(err))
2246602bd0e9SAl Viro return err;
2247de0fa95cSPavel Emelyanov sock = sockfd_lookup_light(fd, &err, &fput_needed);
22481da177e4SLinus Torvalds if (!sock)
2249de0fa95cSPavel Emelyanov goto out;
22501da177e4SLinus Torvalds
22511da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK)
22521da177e4SLinus Torvalds flags |= MSG_DONTWAIT;
22532da62906SAl Viro err = sock_recvmsg(sock, &msg, flags);
22541da177e4SLinus Torvalds
225589bddce5SStephen Hemminger if (err >= 0 && addr != NULL) {
225643db362dSMaciej Żenczykowski err2 = move_addr_to_user(&address,
2257230b1839SYOSHIFUJI Hideaki msg.msg_namelen, addr, addr_len);
22581da177e4SLinus Torvalds if (err2 < 0)
22591da177e4SLinus Torvalds err = err2;
22601da177e4SLinus Torvalds }
2261de0fa95cSPavel Emelyanov
2262de0fa95cSPavel Emelyanov fput_light(sock->file, fput_needed);
22634387ff75SDavid S. Miller out:
22641da177e4SLinus Torvalds return err;
22651da177e4SLinus Torvalds }
22661da177e4SLinus Torvalds
SYSCALL_DEFINE6(recvfrom,int,fd,void __user *,ubuf,size_t,size,unsigned int,flags,struct sockaddr __user *,addr,int __user *,addr_len)22677a09e1ebSDominik Brodowski SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
22687a09e1ebSDominik Brodowski unsigned int, flags, struct sockaddr __user *, addr,
22697a09e1ebSDominik Brodowski int __user *, addr_len)
22707a09e1ebSDominik Brodowski {
22717a09e1ebSDominik Brodowski return __sys_recvfrom(fd, ubuf, size, flags, addr, addr_len);
22727a09e1ebSDominik Brodowski }
22737a09e1ebSDominik Brodowski
22741da177e4SLinus Torvalds /*
22751da177e4SLinus Torvalds * Receive a datagram from a socket.
22761da177e4SLinus Torvalds */
22771da177e4SLinus Torvalds
SYSCALL_DEFINE4(recv,int,fd,void __user *,ubuf,size_t,size,unsigned int,flags)2278b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
2279b7c0ddf5SJan Glauber unsigned int, flags)
22801da177e4SLinus Torvalds {
22817a09e1ebSDominik Brodowski return __sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
22821da177e4SLinus Torvalds }
22831da177e4SLinus Torvalds
sock_use_custom_sol_socket(const struct socket * sock)228483f0c10bSFlorian Westphal static bool sock_use_custom_sol_socket(const struct socket *sock)
228583f0c10bSFlorian Westphal {
2286a5ef058dSPaolo Abeni return test_bit(SOCK_CUSTOM_SOCKOPT, &sock->flags);
228783f0c10bSFlorian Westphal }
228883f0c10bSFlorian Westphal
do_sock_setsockopt(struct socket * sock,bool compat,int level,int optname,sockptr_t optval,int optlen)2289e88c16a4SBreno Leitao int do_sock_setsockopt(struct socket *sock, bool compat, int level,
2290e88c16a4SBreno Leitao int optname, sockptr_t optval, int optlen)
22911da177e4SLinus Torvalds {
22921ded5e5aSEric Dumazet const struct proto_ops *ops;
22930d01da6aSStanislav Fomichev char *kernel_optval = NULL;
2294e88c16a4SBreno Leitao int err;
22951da177e4SLinus Torvalds
22961da177e4SLinus Torvalds if (optlen < 0)
22971da177e4SLinus Torvalds return -EINVAL;
22981da177e4SLinus Torvalds
22991da177e4SLinus Torvalds err = security_socket_setsockopt(sock, level, optname);
23006cb153caSBenjamin LaHaise if (err)
23016cb153caSBenjamin LaHaise goto out_put;
23021da177e4SLinus Torvalds
2303e88c16a4SBreno Leitao if (!compat)
23044a367299SChristoph Hellwig err = BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock->sk, &level, &optname,
230509fba016SBreno Leitao optval, &optlen,
230655db9c0eSChristoph Hellwig &kernel_optval);
23074a367299SChristoph Hellwig if (err < 0)
23080d01da6aSStanislav Fomichev goto out_put;
23094a367299SChristoph Hellwig if (err > 0) {
23100d01da6aSStanislav Fomichev err = 0;
23110d01da6aSStanislav Fomichev goto out_put;
23120d01da6aSStanislav Fomichev }
23130d01da6aSStanislav Fomichev
2314a7b75c5aSChristoph Hellwig if (kernel_optval)
2315a7b75c5aSChristoph Hellwig optval = KERNEL_SOCKPTR(kernel_optval);
23161ded5e5aSEric Dumazet ops = READ_ONCE(sock->ops);
231783f0c10bSFlorian Westphal if (level == SOL_SOCKET && !sock_use_custom_sol_socket(sock))
2318a7b75c5aSChristoph Hellwig err = sock_setsockopt(sock, level, optname, optval, optlen);
23191ded5e5aSEric Dumazet else if (unlikely(!ops->setsockopt))
2320a44d9e72SChristoph Hellwig err = -EOPNOTSUPP;
23211da177e4SLinus Torvalds else
23221ded5e5aSEric Dumazet err = ops->setsockopt(sock, level, optname, optval,
232389bddce5SStephen Hemminger optlen);
23240d01da6aSStanislav Fomichev kfree(kernel_optval);
23256cb153caSBenjamin LaHaise out_put:
2326e88c16a4SBreno Leitao return err;
2327e88c16a4SBreno Leitao }
2328e88c16a4SBreno Leitao EXPORT_SYMBOL(do_sock_setsockopt);
2329e88c16a4SBreno Leitao
2330e88c16a4SBreno Leitao /* Set a socket option. Because we don't know the option lengths we have
2331e88c16a4SBreno Leitao * to pass the user mode parameter for the protocols to sort out.
2332e88c16a4SBreno Leitao */
__sys_setsockopt(int fd,int level,int optname,char __user * user_optval,int optlen)2333e88c16a4SBreno Leitao int __sys_setsockopt(int fd, int level, int optname, char __user *user_optval,
2334e88c16a4SBreno Leitao int optlen)
2335e88c16a4SBreno Leitao {
2336e88c16a4SBreno Leitao sockptr_t optval = USER_SOCKPTR(user_optval);
2337e88c16a4SBreno Leitao bool compat = in_compat_syscall();
2338e88c16a4SBreno Leitao int err, fput_needed;
2339e88c16a4SBreno Leitao struct socket *sock;
2340e88c16a4SBreno Leitao
2341e88c16a4SBreno Leitao sock = sockfd_lookup_light(fd, &err, &fput_needed);
2342e88c16a4SBreno Leitao if (!sock)
2343e88c16a4SBreno Leitao return err;
2344e88c16a4SBreno Leitao
2345e88c16a4SBreno Leitao err = do_sock_setsockopt(sock, compat, level, optname, optval, optlen);
2346e88c16a4SBreno Leitao
23476cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed);
23481da177e4SLinus Torvalds return err;
23491da177e4SLinus Torvalds }
23501da177e4SLinus Torvalds
SYSCALL_DEFINE5(setsockopt,int,fd,int,level,int,optname,char __user *,optval,int,optlen)2351cc36dca0SDominik Brodowski SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
2352cc36dca0SDominik Brodowski char __user *, optval, int, optlen)
2353cc36dca0SDominik Brodowski {
2354cc36dca0SDominik Brodowski return __sys_setsockopt(fd, level, optname, optval, optlen);
2355cc36dca0SDominik Brodowski }
2356cc36dca0SDominik Brodowski
23579cacf81fSStanislav Fomichev INDIRECT_CALLABLE_DECLARE(bool tcp_bpf_bypass_getsockopt(int level,
23589cacf81fSStanislav Fomichev int optname));
23599cacf81fSStanislav Fomichev
do_sock_getsockopt(struct socket * sock,bool compat,int level,int optname,sockptr_t optval,sockptr_t optlen)23602174a3c3SBreno Leitao int do_sock_getsockopt(struct socket *sock, bool compat, int level,
23612174a3c3SBreno Leitao int optname, sockptr_t optval, sockptr_t optlen)
23622174a3c3SBreno Leitao {
2363f8d6acb1STze-nan Wu int max_optlen __maybe_unused = 0;
23642174a3c3SBreno Leitao const struct proto_ops *ops;
23652174a3c3SBreno Leitao int err;
23662174a3c3SBreno Leitao
23672174a3c3SBreno Leitao err = security_socket_getsockopt(sock, level, optname);
23682174a3c3SBreno Leitao if (err)
23692174a3c3SBreno Leitao return err;
23702174a3c3SBreno Leitao
23712174a3c3SBreno Leitao if (!compat)
2372f8d6acb1STze-nan Wu copy_from_sockptr(&max_optlen, optlen, sizeof(int));
23732174a3c3SBreno Leitao
23742174a3c3SBreno Leitao ops = READ_ONCE(sock->ops);
23752174a3c3SBreno Leitao if (level == SOL_SOCKET) {
23762174a3c3SBreno Leitao err = sk_getsockopt(sock->sk, level, optname, optval, optlen);
23772174a3c3SBreno Leitao } else if (unlikely(!ops->getsockopt)) {
23782174a3c3SBreno Leitao err = -EOPNOTSUPP;
23792174a3c3SBreno Leitao } else {
23802174a3c3SBreno Leitao if (WARN_ONCE(optval.is_kernel || optlen.is_kernel,
23812174a3c3SBreno Leitao "Invalid argument type"))
23822174a3c3SBreno Leitao return -EOPNOTSUPP;
23832174a3c3SBreno Leitao
23842174a3c3SBreno Leitao err = ops->getsockopt(sock, level, optname, optval.user,
23852174a3c3SBreno Leitao optlen.user);
23862174a3c3SBreno Leitao }
23872174a3c3SBreno Leitao
23882174a3c3SBreno Leitao if (!compat)
23892174a3c3SBreno Leitao err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level, optname,
23902174a3c3SBreno Leitao optval, optlen, max_optlen,
23912174a3c3SBreno Leitao err);
23922174a3c3SBreno Leitao
23932174a3c3SBreno Leitao return err;
23942174a3c3SBreno Leitao }
23952174a3c3SBreno Leitao EXPORT_SYMBOL(do_sock_getsockopt);
23962174a3c3SBreno Leitao
23971da177e4SLinus Torvalds /*
23981da177e4SLinus Torvalds * Get a socket option. Because we don't know the option lengths we have
23991da177e4SLinus Torvalds * to pass a user mode parameter for the protocols to sort out.
24001da177e4SLinus Torvalds */
__sys_getsockopt(int fd,int level,int optname,char __user * optval,int __user * optlen)240155db9c0eSChristoph Hellwig int __sys_getsockopt(int fd, int level, int optname, char __user *optval,
240255db9c0eSChristoph Hellwig int __user *optlen)
24031da177e4SLinus Torvalds {
24046cb153caSBenjamin LaHaise int err, fput_needed;
24051da177e4SLinus Torvalds struct socket *sock;
24062174a3c3SBreno Leitao bool compat;
24071da177e4SLinus Torvalds
240889bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed);
2409d8a9b38fSChristoph Hellwig if (!sock)
2410d8a9b38fSChristoph Hellwig return err;
2411d8a9b38fSChristoph Hellwig
24122174a3c3SBreno Leitao compat = in_compat_syscall();
24132174a3c3SBreno Leitao err = do_sock_getsockopt(sock, compat, level, optname,
24142174a3c3SBreno Leitao USER_SOCKPTR(optval), USER_SOCKPTR(optlen));
24151da177e4SLinus Torvalds
24166cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed);
24171da177e4SLinus Torvalds return err;
24181da177e4SLinus Torvalds }
24191da177e4SLinus Torvalds
SYSCALL_DEFINE5(getsockopt,int,fd,int,level,int,optname,char __user *,optval,int __user *,optlen)242013a2d70eSDominik Brodowski SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
242113a2d70eSDominik Brodowski char __user *, optval, int __user *, optlen)
242213a2d70eSDominik Brodowski {
242313a2d70eSDominik Brodowski return __sys_getsockopt(fd, level, optname, optval, optlen);
242413a2d70eSDominik Brodowski }
242513a2d70eSDominik Brodowski
24261da177e4SLinus Torvalds /*
24271da177e4SLinus Torvalds * Shutdown a socket.
24281da177e4SLinus Torvalds */
24291da177e4SLinus Torvalds
__sys_shutdown_sock(struct socket * sock,int how)2430b713c195SJens Axboe int __sys_shutdown_sock(struct socket *sock, int how)
2431b713c195SJens Axboe {
2432b713c195SJens Axboe int err;
2433b713c195SJens Axboe
2434b713c195SJens Axboe err = security_socket_shutdown(sock, how);
2435b713c195SJens Axboe if (!err)
24361ded5e5aSEric Dumazet err = READ_ONCE(sock->ops)->shutdown(sock, how);
2437b713c195SJens Axboe
2438b713c195SJens Axboe return err;
2439b713c195SJens Axboe }
2440b713c195SJens Axboe
__sys_shutdown(int fd,int how)2441005a1aeaSDominik Brodowski int __sys_shutdown(int fd, int how)
24421da177e4SLinus Torvalds {
24436cb153caSBenjamin LaHaise int err, fput_needed;
24441da177e4SLinus Torvalds struct socket *sock;
24451da177e4SLinus Torvalds
244689bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed);
244789bddce5SStephen Hemminger if (sock != NULL) {
2448b713c195SJens Axboe err = __sys_shutdown_sock(sock, how);
24496cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed);
24501da177e4SLinus Torvalds }
24511da177e4SLinus Torvalds return err;
24521da177e4SLinus Torvalds }
24531da177e4SLinus Torvalds
SYSCALL_DEFINE2(shutdown,int,fd,int,how)2454005a1aeaSDominik Brodowski SYSCALL_DEFINE2(shutdown, int, fd, int, how)
2455005a1aeaSDominik Brodowski {
2456005a1aeaSDominik Brodowski return __sys_shutdown(fd, how);
2457005a1aeaSDominik Brodowski }
2458005a1aeaSDominik Brodowski
24591da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
24601da177e4SLinus Torvalds * fields which are the same type (int / unsigned) on our platforms.
24611da177e4SLinus Torvalds */
24621da177e4SLinus Torvalds #define COMPAT_MSG(msg, member) ((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
24631da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen)
24641da177e4SLinus Torvalds #define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags)
24651da177e4SLinus Torvalds
2466c71d8ebeSTetsuo Handa struct used_address {
2467c71d8ebeSTetsuo Handa struct sockaddr_storage name;
2468c71d8ebeSTetsuo Handa unsigned int name_len;
2469c71d8ebeSTetsuo Handa };
2470c71d8ebeSTetsuo Handa
__copy_msghdr(struct msghdr * kmsg,struct user_msghdr * msg,struct sockaddr __user ** save_addr)24717fa875b8SDylan Yudaken int __copy_msghdr(struct msghdr *kmsg,
24727fa875b8SDylan Yudaken struct user_msghdr *msg,
24737fa875b8SDylan Yudaken struct sockaddr __user **save_addr)
24741661bf36SDan Carpenter {
247508adb7daSAl Viro ssize_t err;
247608adb7daSAl Viro
24771f466e1fSChristoph Hellwig kmsg->msg_control_is_user = true;
24781228b34cSEric Dumazet kmsg->msg_get_inq = 0;
24797fa875b8SDylan Yudaken kmsg->msg_control_user = msg->msg_control;
24807fa875b8SDylan Yudaken kmsg->msg_controllen = msg->msg_controllen;
24817fa875b8SDylan Yudaken kmsg->msg_flags = msg->msg_flags;
2482ffb07550SAl Viro
24837fa875b8SDylan Yudaken kmsg->msg_namelen = msg->msg_namelen;
24847fa875b8SDylan Yudaken if (!msg->msg_name)
24856a2a2b3aSAni Sinha kmsg->msg_namelen = 0;
24866a2a2b3aSAni Sinha
2487dbb490b9SMatthew Leach if (kmsg->msg_namelen < 0)
2488dbb490b9SMatthew Leach return -EINVAL;
2489dbb490b9SMatthew Leach
24901661bf36SDan Carpenter if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
2491db31c55aSDan Carpenter kmsg->msg_namelen = sizeof(struct sockaddr_storage);
249208adb7daSAl Viro
249308adb7daSAl Viro if (save_addr)
24947fa875b8SDylan Yudaken *save_addr = msg->msg_name;
249508adb7daSAl Viro
24967fa875b8SDylan Yudaken if (msg->msg_name && kmsg->msg_namelen) {
249708adb7daSAl Viro if (!save_addr) {
24987fa875b8SDylan Yudaken err = move_addr_to_kernel(msg->msg_name,
2499864d9664SPaolo Abeni kmsg->msg_namelen,
250008adb7daSAl Viro kmsg->msg_name);
250108adb7daSAl Viro if (err < 0)
250208adb7daSAl Viro return err;
250308adb7daSAl Viro }
250408adb7daSAl Viro } else {
250508adb7daSAl Viro kmsg->msg_name = NULL;
250608adb7daSAl Viro kmsg->msg_namelen = 0;
250708adb7daSAl Viro }
250808adb7daSAl Viro
25097fa875b8SDylan Yudaken if (msg->msg_iovlen > UIO_MAXIOV)
251008adb7daSAl Viro return -EMSGSIZE;
251108adb7daSAl Viro
25120345f931Stadeusz.struk@intel.com kmsg->msg_iocb = NULL;
25137c701d92SPavel Begunkov kmsg->msg_ubuf = NULL;
25140a384abfSJens Axboe return 0;
25150a384abfSJens Axboe }
25160a384abfSJens Axboe
copy_msghdr_from_user(struct msghdr * kmsg,struct user_msghdr __user * umsg,struct sockaddr __user ** save_addr,struct iovec ** iov)25170a384abfSJens Axboe static int copy_msghdr_from_user(struct msghdr *kmsg,
25180a384abfSJens Axboe struct user_msghdr __user *umsg,
25190a384abfSJens Axboe struct sockaddr __user **save_addr,
25200a384abfSJens Axboe struct iovec **iov)
25210a384abfSJens Axboe {
25220a384abfSJens Axboe struct user_msghdr msg;
25230a384abfSJens Axboe ssize_t err;
25240a384abfSJens Axboe
25257fa875b8SDylan Yudaken if (copy_from_user(&msg, umsg, sizeof(*umsg)))
25267fa875b8SDylan Yudaken return -EFAULT;
25277fa875b8SDylan Yudaken
25287fa875b8SDylan Yudaken err = __copy_msghdr(kmsg, &msg, save_addr);
25290a384abfSJens Axboe if (err)
25300a384abfSJens Axboe return err;
25310345f931Stadeusz.struk@intel.com
2532de4eda9dSAl Viro err = import_iovec(save_addr ? ITER_DEST : ITER_SOURCE,
2533ffb07550SAl Viro msg.msg_iov, msg.msg_iovlen,
2534da184284SAl Viro UIO_FASTIOV, iov, &kmsg->msg_iter);
253587e5e6daSJens Axboe return err < 0 ? err : 0;
25361661bf36SDan Carpenter }
25371661bf36SDan Carpenter
____sys_sendmsg(struct socket * sock,struct msghdr * msg_sys,unsigned int flags,struct used_address * used_address,unsigned int allowed_msghdr_flags)25384257c8caSJens Axboe static int ____sys_sendmsg(struct socket *sock, struct msghdr *msg_sys,
25394257c8caSJens Axboe unsigned int flags, struct used_address *used_address,
254028a94d8fSTom Herbert unsigned int allowed_msghdr_flags)
25411da177e4SLinus Torvalds {
2542b9d717a7SAlex Williamson unsigned char ctl[sizeof(struct cmsghdr) + 20]
2543846cc123SAmit Kushwaha __aligned(sizeof(__kernel_size_t));
2544b9d717a7SAlex Williamson /* 20 is size of ipv6_pktinfo */
25451da177e4SLinus Torvalds unsigned char *ctl_buf = ctl;
2546d8725c86SAl Viro int ctl_len;
254708adb7daSAl Viro ssize_t err;
25481da177e4SLinus Torvalds
25491da177e4SLinus Torvalds err = -ENOBUFS;
25501da177e4SLinus Torvalds
2551228e548eSAnton Blanchard if (msg_sys->msg_controllen > INT_MAX)
25524257c8caSJens Axboe goto out;
255328a94d8fSTom Herbert flags |= (msg_sys->msg_flags & allowed_msghdr_flags);
2554228e548eSAnton Blanchard ctl_len = msg_sys->msg_controllen;
25551da177e4SLinus Torvalds if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
255689bddce5SStephen Hemminger err =
2557228e548eSAnton Blanchard cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
255889bddce5SStephen Hemminger sizeof(ctl));
25591da177e4SLinus Torvalds if (err)
25604257c8caSJens Axboe goto out;
2561228e548eSAnton Blanchard ctl_buf = msg_sys->msg_control;
2562228e548eSAnton Blanchard ctl_len = msg_sys->msg_controllen;
25631da177e4SLinus Torvalds } else if (ctl_len) {
2564ac4340fcSDavid S. Miller BUILD_BUG_ON(sizeof(struct cmsghdr) !=
2565ac4340fcSDavid S. Miller CMSG_ALIGN(sizeof(struct cmsghdr)));
256689bddce5SStephen Hemminger if (ctl_len > sizeof(ctl)) {
25671da177e4SLinus Torvalds ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
25681da177e4SLinus Torvalds if (ctl_buf == NULL)
25694257c8caSJens Axboe goto out;
25701da177e4SLinus Torvalds }
25711da177e4SLinus Torvalds err = -EFAULT;
25721f466e1fSChristoph Hellwig if (copy_from_user(ctl_buf, msg_sys->msg_control_user, ctl_len))
25731da177e4SLinus Torvalds goto out_freectl;
2574228e548eSAnton Blanchard msg_sys->msg_control = ctl_buf;
25751f466e1fSChristoph Hellwig msg_sys->msg_control_is_user = false;
25761da177e4SLinus Torvalds }
2577b841b901SDavid Howells flags &= ~MSG_INTERNAL_SENDMSG_FLAGS;
2578228e548eSAnton Blanchard msg_sys->msg_flags = flags;
25791da177e4SLinus Torvalds
25801da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK)
2581228e548eSAnton Blanchard msg_sys->msg_flags |= MSG_DONTWAIT;
2582c71d8ebeSTetsuo Handa /*
2583c71d8ebeSTetsuo Handa * If this is sendmmsg() and current destination address is same as
2584c71d8ebeSTetsuo Handa * previously succeeded address, omit asking LSM's decision.
2585c71d8ebeSTetsuo Handa * used_address->name_len is initialized to UINT_MAX so that the first
2586c71d8ebeSTetsuo Handa * destination address never matches.
2587c71d8ebeSTetsuo Handa */
2588bc909d9dSMathieu Desnoyers if (used_address && msg_sys->msg_name &&
2589bc909d9dSMathieu Desnoyers used_address->name_len == msg_sys->msg_namelen &&
2590bc909d9dSMathieu Desnoyers !memcmp(&used_address->name, msg_sys->msg_name,
2591c71d8ebeSTetsuo Handa used_address->name_len)) {
2592d8725c86SAl Viro err = sock_sendmsg_nosec(sock, msg_sys);
2593c71d8ebeSTetsuo Handa goto out_freectl;
2594c71d8ebeSTetsuo Handa }
259586a7e0b6SJordan Rife err = __sock_sendmsg(sock, msg_sys);
2596c71d8ebeSTetsuo Handa /*
2597c71d8ebeSTetsuo Handa * If this is sendmmsg() and sending to current destination address was
2598c71d8ebeSTetsuo Handa * successful, remember it.
2599c71d8ebeSTetsuo Handa */
2600c71d8ebeSTetsuo Handa if (used_address && err >= 0) {
2601c71d8ebeSTetsuo Handa used_address->name_len = msg_sys->msg_namelen;
2602bc909d9dSMathieu Desnoyers if (msg_sys->msg_name)
2603bc909d9dSMathieu Desnoyers memcpy(&used_address->name, msg_sys->msg_name,
2604c71d8ebeSTetsuo Handa used_address->name_len);
2605c71d8ebeSTetsuo Handa }
26061da177e4SLinus Torvalds
26071da177e4SLinus Torvalds out_freectl:
26081da177e4SLinus Torvalds if (ctl_buf != ctl)
26091da177e4SLinus Torvalds sock_kfree_s(sock->sk, ctl_buf, ctl_len);
26104257c8caSJens Axboe out:
26114257c8caSJens Axboe return err;
26124257c8caSJens Axboe }
26134257c8caSJens Axboe
sendmsg_copy_msghdr(struct msghdr * msg,struct user_msghdr __user * umsg,unsigned flags,struct iovec ** iov)261403b1230cSJens Axboe int sendmsg_copy_msghdr(struct msghdr *msg,
26154257c8caSJens Axboe struct user_msghdr __user *umsg, unsigned flags,
26164257c8caSJens Axboe struct iovec **iov)
26174257c8caSJens Axboe {
26184257c8caSJens Axboe int err;
26194257c8caSJens Axboe
26204257c8caSJens Axboe if (flags & MSG_CMSG_COMPAT) {
26214257c8caSJens Axboe struct compat_msghdr __user *msg_compat;
26224257c8caSJens Axboe
26234257c8caSJens Axboe msg_compat = (struct compat_msghdr __user *) umsg;
26244257c8caSJens Axboe err = get_compat_msghdr(msg, msg_compat, NULL, iov);
26254257c8caSJens Axboe } else {
26264257c8caSJens Axboe err = copy_msghdr_from_user(msg, umsg, NULL, iov);
26274257c8caSJens Axboe }
26284257c8caSJens Axboe if (err < 0)
26294257c8caSJens Axboe return err;
26304257c8caSJens Axboe
26314257c8caSJens Axboe return 0;
26324257c8caSJens Axboe }
26334257c8caSJens Axboe
___sys_sendmsg(struct socket * sock,struct user_msghdr __user * msg,struct msghdr * msg_sys,unsigned int flags,struct used_address * used_address,unsigned int allowed_msghdr_flags)26344257c8caSJens Axboe static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
26354257c8caSJens Axboe struct msghdr *msg_sys, unsigned int flags,
26364257c8caSJens Axboe struct used_address *used_address,
26374257c8caSJens Axboe unsigned int allowed_msghdr_flags)
26384257c8caSJens Axboe {
26394257c8caSJens Axboe struct sockaddr_storage address;
26404257c8caSJens Axboe struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
26414257c8caSJens Axboe ssize_t err;
26424257c8caSJens Axboe
26434257c8caSJens Axboe msg_sys->msg_name = &address;
26444257c8caSJens Axboe
26454257c8caSJens Axboe err = sendmsg_copy_msghdr(msg_sys, msg, flags, &iov);
26464257c8caSJens Axboe if (err < 0)
26474257c8caSJens Axboe return err;
26484257c8caSJens Axboe
26494257c8caSJens Axboe err = ____sys_sendmsg(sock, msg_sys, flags, used_address,
26504257c8caSJens Axboe allowed_msghdr_flags);
2651a74e9106SEric Dumazet kfree(iov);
2652228e548eSAnton Blanchard return err;
2653228e548eSAnton Blanchard }
2654228e548eSAnton Blanchard
2655228e548eSAnton Blanchard /*
2656228e548eSAnton Blanchard * BSD sendmsg interface
2657228e548eSAnton Blanchard */
__sys_sendmsg_sock(struct socket * sock,struct msghdr * msg,unsigned int flags)265803b1230cSJens Axboe long __sys_sendmsg_sock(struct socket *sock, struct msghdr *msg,
26590fa03c62SJens Axboe unsigned int flags)
26600fa03c62SJens Axboe {
266103b1230cSJens Axboe return ____sys_sendmsg(sock, msg, flags, NULL, 0);
26620fa03c62SJens Axboe }
2663228e548eSAnton Blanchard
__sys_sendmsg(int fd,struct user_msghdr __user * msg,unsigned int flags,bool forbid_cmsg_compat)2664e1834a32SDominik Brodowski long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
2665e1834a32SDominik Brodowski bool forbid_cmsg_compat)
2666228e548eSAnton Blanchard {
2667228e548eSAnton Blanchard int fput_needed, err;
2668228e548eSAnton Blanchard struct msghdr msg_sys;
26691be374a0SAndy Lutomirski struct socket *sock;
2670228e548eSAnton Blanchard
2671e1834a32SDominik Brodowski if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
2672e1834a32SDominik Brodowski return -EINVAL;
2673e1834a32SDominik Brodowski
26741be374a0SAndy Lutomirski sock = sockfd_lookup_light(fd, &err, &fput_needed);
2675228e548eSAnton Blanchard if (!sock)
2676228e548eSAnton Blanchard goto out;
2677228e548eSAnton Blanchard
267828a94d8fSTom Herbert err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
2679228e548eSAnton Blanchard
26806cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed);
26811da177e4SLinus Torvalds out:
26821da177e4SLinus Torvalds return err;
26831da177e4SLinus Torvalds }
26841da177e4SLinus Torvalds
SYSCALL_DEFINE3(sendmsg,int,fd,struct user_msghdr __user *,msg,unsigned int,flags)2685666547ffSAl Viro SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
2686a7526eb5SAndy Lutomirski {
2687e1834a32SDominik Brodowski return __sys_sendmsg(fd, msg, flags, true);
2688a7526eb5SAndy Lutomirski }
2689a7526eb5SAndy Lutomirski
2690228e548eSAnton Blanchard /*
2691228e548eSAnton Blanchard * Linux sendmmsg interface
2692228e548eSAnton Blanchard */
2693228e548eSAnton Blanchard
__sys_sendmmsg(int fd,struct mmsghdr __user * mmsg,unsigned int vlen,unsigned int flags,bool forbid_cmsg_compat)2694228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2695e1834a32SDominik Brodowski unsigned int flags, bool forbid_cmsg_compat)
2696228e548eSAnton Blanchard {
2697228e548eSAnton Blanchard int fput_needed, err, datagrams;
2698228e548eSAnton Blanchard struct socket *sock;
2699228e548eSAnton Blanchard struct mmsghdr __user *entry;
2700228e548eSAnton Blanchard struct compat_mmsghdr __user *compat_entry;
2701228e548eSAnton Blanchard struct msghdr msg_sys;
2702c71d8ebeSTetsuo Handa struct used_address used_address;
2703f092276dSTom Herbert unsigned int oflags = flags;
2704228e548eSAnton Blanchard
2705e1834a32SDominik Brodowski if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
2706e1834a32SDominik Brodowski return -EINVAL;
2707e1834a32SDominik Brodowski
270898382f41SAnton Blanchard if (vlen > UIO_MAXIOV)
270998382f41SAnton Blanchard vlen = UIO_MAXIOV;
2710228e548eSAnton Blanchard
2711228e548eSAnton Blanchard datagrams = 0;
2712228e548eSAnton Blanchard
2713228e548eSAnton Blanchard sock = sockfd_lookup_light(fd, &err, &fput_needed);
2714228e548eSAnton Blanchard if (!sock)
2715228e548eSAnton Blanchard return err;
2716228e548eSAnton Blanchard
2717c71d8ebeSTetsuo Handa used_address.name_len = UINT_MAX;
2718228e548eSAnton Blanchard entry = mmsg;
2719228e548eSAnton Blanchard compat_entry = (struct compat_mmsghdr __user *)mmsg;
2720728ffb86SAnton Blanchard err = 0;
2721f092276dSTom Herbert flags |= MSG_BATCH;
2722228e548eSAnton Blanchard
2723228e548eSAnton Blanchard while (datagrams < vlen) {
2724f092276dSTom Herbert if (datagrams == vlen - 1)
2725f092276dSTom Herbert flags = oflags;
2726f092276dSTom Herbert
2727228e548eSAnton Blanchard if (MSG_CMSG_COMPAT & flags) {
2728666547ffSAl Viro err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry,
272928a94d8fSTom Herbert &msg_sys, flags, &used_address, MSG_EOR);
2730228e548eSAnton Blanchard if (err < 0)
2731228e548eSAnton Blanchard break;
2732228e548eSAnton Blanchard err = __put_user(err, &compat_entry->msg_len);
2733228e548eSAnton Blanchard ++compat_entry;
2734228e548eSAnton Blanchard } else {
2735a7526eb5SAndy Lutomirski err = ___sys_sendmsg(sock,
2736666547ffSAl Viro (struct user_msghdr __user *)entry,
273728a94d8fSTom Herbert &msg_sys, flags, &used_address, MSG_EOR);
2738228e548eSAnton Blanchard if (err < 0)
2739228e548eSAnton Blanchard break;
2740228e548eSAnton Blanchard err = put_user(err, &entry->msg_len);
2741228e548eSAnton Blanchard ++entry;
2742228e548eSAnton Blanchard }
2743228e548eSAnton Blanchard
2744228e548eSAnton Blanchard if (err)
2745228e548eSAnton Blanchard break;
2746228e548eSAnton Blanchard ++datagrams;
27473023898bSSoheil Hassas Yeganeh if (msg_data_left(&msg_sys))
27483023898bSSoheil Hassas Yeganeh break;
2749a78cb84cSEric Dumazet cond_resched();
2750228e548eSAnton Blanchard }
2751228e548eSAnton Blanchard
2752228e548eSAnton Blanchard fput_light(sock->file, fput_needed);
2753228e548eSAnton Blanchard
2754728ffb86SAnton Blanchard /* We only return an error if no datagrams were able to be sent */
2755728ffb86SAnton Blanchard if (datagrams != 0)
2756228e548eSAnton Blanchard return datagrams;
2757228e548eSAnton Blanchard
2758228e548eSAnton Blanchard return err;
2759228e548eSAnton Blanchard }
2760228e548eSAnton Blanchard
SYSCALL_DEFINE4(sendmmsg,int,fd,struct mmsghdr __user *,mmsg,unsigned int,vlen,unsigned int,flags)2761228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2762228e548eSAnton Blanchard unsigned int, vlen, unsigned int, flags)
2763228e548eSAnton Blanchard {
2764e1834a32SDominik Brodowski return __sys_sendmmsg(fd, mmsg, vlen, flags, true);
2765228e548eSAnton Blanchard }
2766228e548eSAnton Blanchard
recvmsg_copy_msghdr(struct msghdr * msg,struct user_msghdr __user * umsg,unsigned flags,struct sockaddr __user ** uaddr,struct iovec ** iov)276703b1230cSJens Axboe int recvmsg_copy_msghdr(struct msghdr *msg,
27684257c8caSJens Axboe struct user_msghdr __user *umsg, unsigned flags,
27694257c8caSJens Axboe struct sockaddr __user **uaddr,
27704257c8caSJens Axboe struct iovec **iov)
27714257c8caSJens Axboe {
27724257c8caSJens Axboe ssize_t err;
27734257c8caSJens Axboe
27744257c8caSJens Axboe if (MSG_CMSG_COMPAT & flags) {
27754257c8caSJens Axboe struct compat_msghdr __user *msg_compat;
27764257c8caSJens Axboe
27774257c8caSJens Axboe msg_compat = (struct compat_msghdr __user *) umsg;
27784257c8caSJens Axboe err = get_compat_msghdr(msg, msg_compat, uaddr, iov);
27794257c8caSJens Axboe } else {
27804257c8caSJens Axboe err = copy_msghdr_from_user(msg, umsg, uaddr, iov);
27814257c8caSJens Axboe }
27824257c8caSJens Axboe if (err < 0)
27834257c8caSJens Axboe return err;
27844257c8caSJens Axboe
27854257c8caSJens Axboe return 0;
27864257c8caSJens Axboe }
27874257c8caSJens Axboe
____sys_recvmsg(struct socket * sock,struct msghdr * msg_sys,struct user_msghdr __user * msg,struct sockaddr __user * uaddr,unsigned int flags,int nosec)27884257c8caSJens Axboe static int ____sys_recvmsg(struct socket *sock, struct msghdr *msg_sys,
27894257c8caSJens Axboe struct user_msghdr __user *msg,
27904257c8caSJens Axboe struct sockaddr __user *uaddr,
27914257c8caSJens Axboe unsigned int flags, int nosec)
27921da177e4SLinus Torvalds {
279389bddce5SStephen Hemminger struct compat_msghdr __user *msg_compat =
279489bddce5SStephen Hemminger (struct compat_msghdr __user *) msg;
27954257c8caSJens Axboe int __user *uaddr_len = COMPAT_NAMELEN(msg);
27964257c8caSJens Axboe struct sockaddr_storage addr;
27971da177e4SLinus Torvalds unsigned long cmsg_ptr;
27982da62906SAl Viro int len;
279908adb7daSAl Viro ssize_t err;
28001da177e4SLinus Torvalds
280108adb7daSAl Viro msg_sys->msg_name = &addr;
2802a2e27255SArnaldo Carvalho de Melo cmsg_ptr = (unsigned long)msg_sys->msg_control;
2803a2e27255SArnaldo Carvalho de Melo msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
28041da177e4SLinus Torvalds
2805f3d33426SHannes Frederic Sowa /* We assume all kernel code knows the size of sockaddr_storage */
2806f3d33426SHannes Frederic Sowa msg_sys->msg_namelen = 0;
2807f3d33426SHannes Frederic Sowa
28081da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK)
28091da177e4SLinus Torvalds flags |= MSG_DONTWAIT;
28101af66221SEric Dumazet
28111af66221SEric Dumazet if (unlikely(nosec))
28121af66221SEric Dumazet err = sock_recvmsg_nosec(sock, msg_sys, flags);
28131af66221SEric Dumazet else
28141af66221SEric Dumazet err = sock_recvmsg(sock, msg_sys, flags);
28151af66221SEric Dumazet
28161da177e4SLinus Torvalds if (err < 0)
28174257c8caSJens Axboe goto out;
28181da177e4SLinus Torvalds len = err;
28191da177e4SLinus Torvalds
28201da177e4SLinus Torvalds if (uaddr != NULL) {
282143db362dSMaciej Żenczykowski err = move_addr_to_user(&addr,
2822a2e27255SArnaldo Carvalho de Melo msg_sys->msg_namelen, uaddr,
282389bddce5SStephen Hemminger uaddr_len);
28241da177e4SLinus Torvalds if (err < 0)
28254257c8caSJens Axboe goto out;
28261da177e4SLinus Torvalds }
2827a2e27255SArnaldo Carvalho de Melo err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
282837f7f421SDavid S. Miller COMPAT_FLAGS(msg));
28291da177e4SLinus Torvalds if (err)
28304257c8caSJens Axboe goto out;
28311da177e4SLinus Torvalds if (MSG_CMSG_COMPAT & flags)
2832a2e27255SArnaldo Carvalho de Melo err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
28331da177e4SLinus Torvalds &msg_compat->msg_controllen);
28341da177e4SLinus Torvalds else
2835a2e27255SArnaldo Carvalho de Melo err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
28361da177e4SLinus Torvalds &msg->msg_controllen);
28371da177e4SLinus Torvalds if (err)
28384257c8caSJens Axboe goto out;
28391da177e4SLinus Torvalds err = len;
28404257c8caSJens Axboe out:
28414257c8caSJens Axboe return err;
28424257c8caSJens Axboe }
28431da177e4SLinus Torvalds
___sys_recvmsg(struct socket * sock,struct user_msghdr __user * msg,struct msghdr * msg_sys,unsigned int flags,int nosec)28444257c8caSJens Axboe static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
28454257c8caSJens Axboe struct msghdr *msg_sys, unsigned int flags, int nosec)
28464257c8caSJens Axboe {
28474257c8caSJens Axboe struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
28484257c8caSJens Axboe /* user mode address pointers */
28494257c8caSJens Axboe struct sockaddr __user *uaddr;
28504257c8caSJens Axboe ssize_t err;
28514257c8caSJens Axboe
28524257c8caSJens Axboe err = recvmsg_copy_msghdr(msg_sys, msg, flags, &uaddr, &iov);
28534257c8caSJens Axboe if (err < 0)
28544257c8caSJens Axboe return err;
28554257c8caSJens Axboe
28564257c8caSJens Axboe err = ____sys_recvmsg(sock, msg_sys, msg, uaddr, flags, nosec);
2857a74e9106SEric Dumazet kfree(iov);
2858a2e27255SArnaldo Carvalho de Melo return err;
2859a2e27255SArnaldo Carvalho de Melo }
2860a2e27255SArnaldo Carvalho de Melo
2861a2e27255SArnaldo Carvalho de Melo /*
2862a2e27255SArnaldo Carvalho de Melo * BSD recvmsg interface
2863a2e27255SArnaldo Carvalho de Melo */
2864a2e27255SArnaldo Carvalho de Melo
__sys_recvmsg_sock(struct socket * sock,struct msghdr * msg,struct user_msghdr __user * umsg,struct sockaddr __user * uaddr,unsigned int flags)286503b1230cSJens Axboe long __sys_recvmsg_sock(struct socket *sock, struct msghdr *msg,
286603b1230cSJens Axboe struct user_msghdr __user *umsg,
286703b1230cSJens Axboe struct sockaddr __user *uaddr, unsigned int flags)
2868aa1fa28fSJens Axboe {
286903b1230cSJens Axboe return ____sys_recvmsg(sock, msg, umsg, uaddr, flags, 0);
2870aa1fa28fSJens Axboe }
2871aa1fa28fSJens Axboe
__sys_recvmsg(int fd,struct user_msghdr __user * msg,unsigned int flags,bool forbid_cmsg_compat)2872e1834a32SDominik Brodowski long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
2873e1834a32SDominik Brodowski bool forbid_cmsg_compat)
2874a2e27255SArnaldo Carvalho de Melo {
2875a2e27255SArnaldo Carvalho de Melo int fput_needed, err;
2876a2e27255SArnaldo Carvalho de Melo struct msghdr msg_sys;
28771be374a0SAndy Lutomirski struct socket *sock;
2878a2e27255SArnaldo Carvalho de Melo
2879e1834a32SDominik Brodowski if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
2880e1834a32SDominik Brodowski return -EINVAL;
2881e1834a32SDominik Brodowski
28821be374a0SAndy Lutomirski sock = sockfd_lookup_light(fd, &err, &fput_needed);
2883a2e27255SArnaldo Carvalho de Melo if (!sock)
2884a2e27255SArnaldo Carvalho de Melo goto out;
2885a2e27255SArnaldo Carvalho de Melo
2886a7526eb5SAndy Lutomirski err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2887a2e27255SArnaldo Carvalho de Melo
28886cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed);
28891da177e4SLinus Torvalds out:
28901da177e4SLinus Torvalds return err;
28911da177e4SLinus Torvalds }
28921da177e4SLinus Torvalds
SYSCALL_DEFINE3(recvmsg,int,fd,struct user_msghdr __user *,msg,unsigned int,flags)2893666547ffSAl Viro SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
2894a7526eb5SAndy Lutomirski unsigned int, flags)
2895a7526eb5SAndy Lutomirski {
2896e1834a32SDominik Brodowski return __sys_recvmsg(fd, msg, flags, true);
2897a7526eb5SAndy Lutomirski }
2898a7526eb5SAndy Lutomirski
2899a2e27255SArnaldo Carvalho de Melo /*
2900a2e27255SArnaldo Carvalho de Melo * Linux recvmmsg interface
2901a2e27255SArnaldo Carvalho de Melo */
29021da177e4SLinus Torvalds
do_recvmmsg(int fd,struct mmsghdr __user * mmsg,unsigned int vlen,unsigned int flags,struct timespec64 * timeout)2903e11d4284SArnd Bergmann static int do_recvmmsg(int fd, struct mmsghdr __user *mmsg,
2904e11d4284SArnd Bergmann unsigned int vlen, unsigned int flags,
2905e11d4284SArnd Bergmann struct timespec64 *timeout)
2906a2e27255SArnaldo Carvalho de Melo {
2907a2e27255SArnaldo Carvalho de Melo int fput_needed, err, datagrams;
2908a2e27255SArnaldo Carvalho de Melo struct socket *sock;
2909a2e27255SArnaldo Carvalho de Melo struct mmsghdr __user *entry;
2910d7256d0eSJean-Mickael Guerin struct compat_mmsghdr __user *compat_entry;
2911a2e27255SArnaldo Carvalho de Melo struct msghdr msg_sys;
2912766b9f92SDeepa Dinamani struct timespec64 end_time;
2913766b9f92SDeepa Dinamani struct timespec64 timeout64;
2914a2e27255SArnaldo Carvalho de Melo
2915a2e27255SArnaldo Carvalho de Melo if (timeout &&
2916a2e27255SArnaldo Carvalho de Melo poll_select_set_timeout(&end_time, timeout->tv_sec,
2917a2e27255SArnaldo Carvalho de Melo timeout->tv_nsec))
2918a2e27255SArnaldo Carvalho de Melo return -EINVAL;
2919a2e27255SArnaldo Carvalho de Melo
2920a2e27255SArnaldo Carvalho de Melo datagrams = 0;
2921a2e27255SArnaldo Carvalho de Melo
2922a2e27255SArnaldo Carvalho de Melo sock = sockfd_lookup_light(fd, &err, &fput_needed);
2923a2e27255SArnaldo Carvalho de Melo if (!sock)
2924a2e27255SArnaldo Carvalho de Melo return err;
2925a2e27255SArnaldo Carvalho de Melo
29267797dc41SSoheil Hassas Yeganeh if (likely(!(flags & MSG_ERRQUEUE))) {
2927a2e27255SArnaldo Carvalho de Melo err = sock_error(sock->sk);
2928e623a9e9SMaxime Jayat if (err) {
2929e623a9e9SMaxime Jayat datagrams = err;
2930a2e27255SArnaldo Carvalho de Melo goto out_put;
2931e623a9e9SMaxime Jayat }
29327797dc41SSoheil Hassas Yeganeh }
2933a2e27255SArnaldo Carvalho de Melo
2934a2e27255SArnaldo Carvalho de Melo entry = mmsg;
2935d7256d0eSJean-Mickael Guerin compat_entry = (struct compat_mmsghdr __user *)mmsg;
2936a2e27255SArnaldo Carvalho de Melo
2937a2e27255SArnaldo Carvalho de Melo while (datagrams < vlen) {
2938a2e27255SArnaldo Carvalho de Melo /*
2939a2e27255SArnaldo Carvalho de Melo * No need to ask LSM for more than the first datagram.
2940a2e27255SArnaldo Carvalho de Melo */
2941d7256d0eSJean-Mickael Guerin if (MSG_CMSG_COMPAT & flags) {
2942666547ffSAl Viro err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry,
2943b9eb8b87SAnton Blanchard &msg_sys, flags & ~MSG_WAITFORONE,
2944b9eb8b87SAnton Blanchard datagrams);
2945d7256d0eSJean-Mickael Guerin if (err < 0)
2946d7256d0eSJean-Mickael Guerin break;
2947d7256d0eSJean-Mickael Guerin err = __put_user(err, &compat_entry->msg_len);
2948d7256d0eSJean-Mickael Guerin ++compat_entry;
2949d7256d0eSJean-Mickael Guerin } else {
2950a7526eb5SAndy Lutomirski err = ___sys_recvmsg(sock,
2951666547ffSAl Viro (struct user_msghdr __user *)entry,
2952b9eb8b87SAnton Blanchard &msg_sys, flags & ~MSG_WAITFORONE,
2953b9eb8b87SAnton Blanchard datagrams);
2954a2e27255SArnaldo Carvalho de Melo if (err < 0)
2955a2e27255SArnaldo Carvalho de Melo break;
2956a2e27255SArnaldo Carvalho de Melo err = put_user(err, &entry->msg_len);
2957d7256d0eSJean-Mickael Guerin ++entry;
2958d7256d0eSJean-Mickael Guerin }
2959d7256d0eSJean-Mickael Guerin
2960a2e27255SArnaldo Carvalho de Melo if (err)
2961a2e27255SArnaldo Carvalho de Melo break;
2962a2e27255SArnaldo Carvalho de Melo ++datagrams;
2963a2e27255SArnaldo Carvalho de Melo
296471c5c159SBrandon L Black /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
296571c5c159SBrandon L Black if (flags & MSG_WAITFORONE)
296671c5c159SBrandon L Black flags |= MSG_DONTWAIT;
296771c5c159SBrandon L Black
2968a2e27255SArnaldo Carvalho de Melo if (timeout) {
2969766b9f92SDeepa Dinamani ktime_get_ts64(&timeout64);
2970c2e6c856SArnd Bergmann *timeout = timespec64_sub(end_time, timeout64);
2971a2e27255SArnaldo Carvalho de Melo if (timeout->tv_sec < 0) {
2972a2e27255SArnaldo Carvalho de Melo timeout->tv_sec = timeout->tv_nsec = 0;
2973a2e27255SArnaldo Carvalho de Melo break;
2974a2e27255SArnaldo Carvalho de Melo }
2975a2e27255SArnaldo Carvalho de Melo
2976a2e27255SArnaldo Carvalho de Melo /* Timeout, return less than vlen datagrams */
2977a2e27255SArnaldo Carvalho de Melo if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2978a2e27255SArnaldo Carvalho de Melo break;
2979a2e27255SArnaldo Carvalho de Melo }
2980a2e27255SArnaldo Carvalho de Melo
2981a2e27255SArnaldo Carvalho de Melo /* Out of band data, return right away */
2982a2e27255SArnaldo Carvalho de Melo if (msg_sys.msg_flags & MSG_OOB)
2983a2e27255SArnaldo Carvalho de Melo break;
2984a78cb84cSEric Dumazet cond_resched();
2985a2e27255SArnaldo Carvalho de Melo }
2986a2e27255SArnaldo Carvalho de Melo
2987a2e27255SArnaldo Carvalho de Melo if (err == 0)
298834b88a68SArnaldo Carvalho de Melo goto out_put;
2989a2e27255SArnaldo Carvalho de Melo
299034b88a68SArnaldo Carvalho de Melo if (datagrams == 0) {
299134b88a68SArnaldo Carvalho de Melo datagrams = err;
299234b88a68SArnaldo Carvalho de Melo goto out_put;
299334b88a68SArnaldo Carvalho de Melo }
299434b88a68SArnaldo Carvalho de Melo
2995a2e27255SArnaldo Carvalho de Melo /*
2996a2e27255SArnaldo Carvalho de Melo * We may return less entries than requested (vlen) if the
2997a2e27255SArnaldo Carvalho de Melo * sock is non block and there aren't enough datagrams...
2998a2e27255SArnaldo Carvalho de Melo */
2999a2e27255SArnaldo Carvalho de Melo if (err != -EAGAIN) {
3000a2e27255SArnaldo Carvalho de Melo /*
3001a2e27255SArnaldo Carvalho de Melo * ... or if recvmsg returns an error after we
3002a2e27255SArnaldo Carvalho de Melo * received some datagrams, where we record the
3003a2e27255SArnaldo Carvalho de Melo * error to return on the next call or if the
3004a2e27255SArnaldo Carvalho de Melo * app asks about it using getsockopt(SO_ERROR).
3005a2e27255SArnaldo Carvalho de Melo */
3006e05a5f51SEric Dumazet WRITE_ONCE(sock->sk->sk_err, -err);
3007a2e27255SArnaldo Carvalho de Melo }
300834b88a68SArnaldo Carvalho de Melo out_put:
300934b88a68SArnaldo Carvalho de Melo fput_light(sock->file, fput_needed);
3010a2e27255SArnaldo Carvalho de Melo
3011a2e27255SArnaldo Carvalho de Melo return datagrams;
3012a2e27255SArnaldo Carvalho de Melo }
3013a2e27255SArnaldo Carvalho de Melo
__sys_recvmmsg(int fd,struct mmsghdr __user * mmsg,unsigned int vlen,unsigned int flags,struct __kernel_timespec __user * timeout,struct old_timespec32 __user * timeout32)3014e11d4284SArnd Bergmann int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg,
30151255e269SDominik Brodowski unsigned int vlen, unsigned int flags,
3016e11d4284SArnd Bergmann struct __kernel_timespec __user *timeout,
3017e11d4284SArnd Bergmann struct old_timespec32 __user *timeout32)
3018a2e27255SArnaldo Carvalho de Melo {
3019a2e27255SArnaldo Carvalho de Melo int datagrams;
3020c2e6c856SArnd Bergmann struct timespec64 timeout_sys;
3021a2e27255SArnaldo Carvalho de Melo
3022e11d4284SArnd Bergmann if (timeout && get_timespec64(&timeout_sys, timeout))
3023a2e27255SArnaldo Carvalho de Melo return -EFAULT;
3024a2e27255SArnaldo Carvalho de Melo
3025e11d4284SArnd Bergmann if (timeout32 && get_old_timespec32(&timeout_sys, timeout32))
3026e11d4284SArnd Bergmann return -EFAULT;
3027a2e27255SArnaldo Carvalho de Melo
3028e11d4284SArnd Bergmann if (!timeout && !timeout32)
3029e11d4284SArnd Bergmann return do_recvmmsg(fd, mmsg, vlen, flags, NULL);
3030e11d4284SArnd Bergmann
3031e11d4284SArnd Bergmann datagrams = do_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
3032e11d4284SArnd Bergmann
3033e11d4284SArnd Bergmann if (datagrams <= 0)
3034e11d4284SArnd Bergmann return datagrams;
3035e11d4284SArnd Bergmann
3036e11d4284SArnd Bergmann if (timeout && put_timespec64(&timeout_sys, timeout))
3037e11d4284SArnd Bergmann datagrams = -EFAULT;
3038e11d4284SArnd Bergmann
3039e11d4284SArnd Bergmann if (timeout32 && put_old_timespec32(&timeout_sys, timeout32))
3040a2e27255SArnaldo Carvalho de Melo datagrams = -EFAULT;
3041a2e27255SArnaldo Carvalho de Melo
3042a2e27255SArnaldo Carvalho de Melo return datagrams;
3043a2e27255SArnaldo Carvalho de Melo }
3044a2e27255SArnaldo Carvalho de Melo
SYSCALL_DEFINE5(recvmmsg,int,fd,struct mmsghdr __user *,mmsg,unsigned int,vlen,unsigned int,flags,struct __kernel_timespec __user *,timeout)30451255e269SDominik Brodowski SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
30461255e269SDominik Brodowski unsigned int, vlen, unsigned int, flags,
3047c2e6c856SArnd Bergmann struct __kernel_timespec __user *, timeout)
30481255e269SDominik Brodowski {
3049e11d4284SArnd Bergmann if (flags & MSG_CMSG_COMPAT)
3050e11d4284SArnd Bergmann return -EINVAL;
3051e11d4284SArnd Bergmann
3052e11d4284SArnd Bergmann return __sys_recvmmsg(fd, mmsg, vlen, flags, timeout, NULL);
30531255e269SDominik Brodowski }
30541255e269SDominik Brodowski
3055e11d4284SArnd Bergmann #ifdef CONFIG_COMPAT_32BIT_TIME
SYSCALL_DEFINE5(recvmmsg_time32,int,fd,struct mmsghdr __user *,mmsg,unsigned int,vlen,unsigned int,flags,struct old_timespec32 __user *,timeout)3056e11d4284SArnd Bergmann SYSCALL_DEFINE5(recvmmsg_time32, int, fd, struct mmsghdr __user *, mmsg,
3057e11d4284SArnd Bergmann unsigned int, vlen, unsigned int, flags,
3058e11d4284SArnd Bergmann struct old_timespec32 __user *, timeout)
3059e11d4284SArnd Bergmann {
3060e11d4284SArnd Bergmann if (flags & MSG_CMSG_COMPAT)
3061e11d4284SArnd Bergmann return -EINVAL;
3062e11d4284SArnd Bergmann
3063e11d4284SArnd Bergmann return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL, timeout);
3064e11d4284SArnd Bergmann }
3065e11d4284SArnd Bergmann #endif
3066e11d4284SArnd Bergmann
3067a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
30681da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
30691da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
3070228e548eSAnton Blanchard static const unsigned char nargs[21] = {
307189bddce5SStephen Hemminger AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
30721da177e4SLinus Torvalds AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
3073aaca0bdcSUlrich Drepper AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
3074228e548eSAnton Blanchard AL(4), AL(5), AL(4)
307589bddce5SStephen Hemminger };
307689bddce5SStephen Hemminger
30771da177e4SLinus Torvalds #undef AL
30781da177e4SLinus Torvalds
30791da177e4SLinus Torvalds /*
30801da177e4SLinus Torvalds * System call vectors.
30811da177e4SLinus Torvalds *
30821da177e4SLinus Torvalds * Argument checking cleaned up. Saved 20% in size.
30831da177e4SLinus Torvalds * This function doesn't need to set the kernel lock because
30841da177e4SLinus Torvalds * it is set by the callees.
30851da177e4SLinus Torvalds */
30861da177e4SLinus Torvalds
SYSCALL_DEFINE2(socketcall,int,call,unsigned long __user *,args)30873e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
30881da177e4SLinus Torvalds {
30892950fa9dSChen Gang unsigned long a[AUDITSC_ARGS];
30901da177e4SLinus Torvalds unsigned long a0, a1;
30911da177e4SLinus Torvalds int err;
309247379052SArjan van de Ven unsigned int len;
30931da177e4SLinus Torvalds
3094228e548eSAnton Blanchard if (call < 1 || call > SYS_SENDMMSG)
30951da177e4SLinus Torvalds return -EINVAL;
3096c8e8cd57SJeremy Cline call = array_index_nospec(call, SYS_SENDMMSG + 1);
30971da177e4SLinus Torvalds
309847379052SArjan van de Ven len = nargs[call];
309947379052SArjan van de Ven if (len > sizeof(a))
310047379052SArjan van de Ven return -EINVAL;
310147379052SArjan van de Ven
31021da177e4SLinus Torvalds /* copy_from_user should be SMP safe. */
310347379052SArjan van de Ven if (copy_from_user(a, args, len))
31041da177e4SLinus Torvalds return -EFAULT;
31051da177e4SLinus Torvalds
31062950fa9dSChen Gang err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
31072950fa9dSChen Gang if (err)
31082950fa9dSChen Gang return err;
31093ec3b2fbSDavid Woodhouse
31101da177e4SLinus Torvalds a0 = a[0];
31111da177e4SLinus Torvalds a1 = a[1];
31121da177e4SLinus Torvalds
311389bddce5SStephen Hemminger switch (call) {
31141da177e4SLinus Torvalds case SYS_SOCKET:
31159d6a15c3SDominik Brodowski err = __sys_socket(a0, a1, a[2]);
31161da177e4SLinus Torvalds break;
31171da177e4SLinus Torvalds case SYS_BIND:
3118a87d35d8SDominik Brodowski err = __sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
31191da177e4SLinus Torvalds break;
31201da177e4SLinus Torvalds case SYS_CONNECT:
31211387c2c2SDominik Brodowski err = __sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
31221da177e4SLinus Torvalds break;
31231da177e4SLinus Torvalds case SYS_LISTEN:
312425e290eeSDominik Brodowski err = __sys_listen(a0, a1);
31251da177e4SLinus Torvalds break;
31261da177e4SLinus Torvalds case SYS_ACCEPT:
31274541e805SDominik Brodowski err = __sys_accept4(a0, (struct sockaddr __user *)a1,
3128aaca0bdcSUlrich Drepper (int __user *)a[2], 0);
31291da177e4SLinus Torvalds break;
31301da177e4SLinus Torvalds case SYS_GETSOCKNAME:
313189bddce5SStephen Hemminger err =
31328882a107SDominik Brodowski __sys_getsockname(a0, (struct sockaddr __user *)a1,
313389bddce5SStephen Hemminger (int __user *)a[2]);
31341da177e4SLinus Torvalds break;
31351da177e4SLinus Torvalds case SYS_GETPEERNAME:
313689bddce5SStephen Hemminger err =
3137b21c8f83SDominik Brodowski __sys_getpeername(a0, (struct sockaddr __user *)a1,
313889bddce5SStephen Hemminger (int __user *)a[2]);
31391da177e4SLinus Torvalds break;
31401da177e4SLinus Torvalds case SYS_SOCKETPAIR:
31416debc8d8SDominik Brodowski err = __sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
31421da177e4SLinus Torvalds break;
31431da177e4SLinus Torvalds case SYS_SEND:
3144f3bf896bSDominik Brodowski err = __sys_sendto(a0, (void __user *)a1, a[2], a[3],
3145f3bf896bSDominik Brodowski NULL, 0);
31461da177e4SLinus Torvalds break;
31471da177e4SLinus Torvalds case SYS_SENDTO:
3148211b634bSDominik Brodowski err = __sys_sendto(a0, (void __user *)a1, a[2], a[3],
31491da177e4SLinus Torvalds (struct sockaddr __user *)a[4], a[5]);
31501da177e4SLinus Torvalds break;
31511da177e4SLinus Torvalds case SYS_RECV:
3152d27e9afcSDominik Brodowski err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
3153d27e9afcSDominik Brodowski NULL, NULL);
31541da177e4SLinus Torvalds break;
31551da177e4SLinus Torvalds case SYS_RECVFROM:
31567a09e1ebSDominik Brodowski err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
315789bddce5SStephen Hemminger (struct sockaddr __user *)a[4],
315889bddce5SStephen Hemminger (int __user *)a[5]);
31591da177e4SLinus Torvalds break;
31601da177e4SLinus Torvalds case SYS_SHUTDOWN:
3161005a1aeaSDominik Brodowski err = __sys_shutdown(a0, a1);
31621da177e4SLinus Torvalds break;
31631da177e4SLinus Torvalds case SYS_SETSOCKOPT:
3164cc36dca0SDominik Brodowski err = __sys_setsockopt(a0, a1, a[2], (char __user *)a[3],
3165cc36dca0SDominik Brodowski a[4]);
31661da177e4SLinus Torvalds break;
31671da177e4SLinus Torvalds case SYS_GETSOCKOPT:
316889bddce5SStephen Hemminger err =
316913a2d70eSDominik Brodowski __sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
317089bddce5SStephen Hemminger (int __user *)a[4]);
31711da177e4SLinus Torvalds break;
31721da177e4SLinus Torvalds case SYS_SENDMSG:
3173e1834a32SDominik Brodowski err = __sys_sendmsg(a0, (struct user_msghdr __user *)a1,
3174e1834a32SDominik Brodowski a[2], true);
31751da177e4SLinus Torvalds break;
3176228e548eSAnton Blanchard case SYS_SENDMMSG:
3177e1834a32SDominik Brodowski err = __sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2],
3178e1834a32SDominik Brodowski a[3], true);
3179228e548eSAnton Blanchard break;
31801da177e4SLinus Torvalds case SYS_RECVMSG:
3181e1834a32SDominik Brodowski err = __sys_recvmsg(a0, (struct user_msghdr __user *)a1,
3182e1834a32SDominik Brodowski a[2], true);
31831da177e4SLinus Torvalds break;
3184a2e27255SArnaldo Carvalho de Melo case SYS_RECVMMSG:
31853ca47e95SArnd Bergmann if (IS_ENABLED(CONFIG_64BIT))
3186e11d4284SArnd Bergmann err = __sys_recvmmsg(a0, (struct mmsghdr __user *)a1,
3187e11d4284SArnd Bergmann a[2], a[3],
3188e11d4284SArnd Bergmann (struct __kernel_timespec __user *)a[4],
3189e11d4284SArnd Bergmann NULL);
3190e11d4284SArnd Bergmann else
3191e11d4284SArnd Bergmann err = __sys_recvmmsg(a0, (struct mmsghdr __user *)a1,
3192e11d4284SArnd Bergmann a[2], a[3], NULL,
3193e11d4284SArnd Bergmann (struct old_timespec32 __user *)a[4]);
3194a2e27255SArnaldo Carvalho de Melo break;
3195de11defeSUlrich Drepper case SYS_ACCEPT4:
31964541e805SDominik Brodowski err = __sys_accept4(a0, (struct sockaddr __user *)a1,
3197de11defeSUlrich Drepper (int __user *)a[2], a[3]);
3198aaca0bdcSUlrich Drepper break;
31991da177e4SLinus Torvalds default:
32001da177e4SLinus Torvalds err = -EINVAL;
32011da177e4SLinus Torvalds break;
32021da177e4SLinus Torvalds }
32031da177e4SLinus Torvalds return err;
32041da177e4SLinus Torvalds }
32051da177e4SLinus Torvalds
32061da177e4SLinus Torvalds #endif /* __ARCH_WANT_SYS_SOCKETCALL */
32071da177e4SLinus Torvalds
320855737fdaSStephen Hemminger /**
320955737fdaSStephen Hemminger * sock_register - add a socket protocol handler
321055737fdaSStephen Hemminger * @ops: description of protocol
321155737fdaSStephen Hemminger *
32121da177e4SLinus Torvalds * This function is called by a protocol handler that wants to
32131da177e4SLinus Torvalds * advertise its address family, and have it linked into the
3214e793c0f7SMasanari Iida * socket interface. The value ops->family corresponds to the
321555737fdaSStephen Hemminger * socket system call protocol family.
32161da177e4SLinus Torvalds */
sock_register(const struct net_proto_family * ops)3217f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
32181da177e4SLinus Torvalds {
32191da177e4SLinus Torvalds int err;
32201da177e4SLinus Torvalds
32211da177e4SLinus Torvalds if (ops->family >= NPROTO) {
32223410f22eSYang Yingliang pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO);
32231da177e4SLinus Torvalds return -ENOBUFS;
32241da177e4SLinus Torvalds }
322555737fdaSStephen Hemminger
322655737fdaSStephen Hemminger spin_lock(&net_family_lock);
3227190683a9SEric Dumazet if (rcu_dereference_protected(net_families[ops->family],
3228190683a9SEric Dumazet lockdep_is_held(&net_family_lock)))
32291da177e4SLinus Torvalds err = -EEXIST;
323055737fdaSStephen Hemminger else {
3231cf778b00SEric Dumazet rcu_assign_pointer(net_families[ops->family], ops);
32321da177e4SLinus Torvalds err = 0;
32331da177e4SLinus Torvalds }
323455737fdaSStephen Hemminger spin_unlock(&net_family_lock);
323555737fdaSStephen Hemminger
3236fe0bdbdeSYejune Deng pr_info("NET: Registered %s protocol family\n", pf_family_names[ops->family]);
32371da177e4SLinus Torvalds return err;
32381da177e4SLinus Torvalds }
3239c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
32401da177e4SLinus Torvalds
324155737fdaSStephen Hemminger /**
324255737fdaSStephen Hemminger * sock_unregister - remove a protocol handler
324355737fdaSStephen Hemminger * @family: protocol family to remove
324455737fdaSStephen Hemminger *
32451da177e4SLinus Torvalds * This function is called by a protocol handler that wants to
32461da177e4SLinus Torvalds * remove its address family, and have it unlinked from the
324755737fdaSStephen Hemminger * new socket creation.
324855737fdaSStephen Hemminger *
324955737fdaSStephen Hemminger * If protocol handler is a module, then it can use module reference
325055737fdaSStephen Hemminger * counts to protect against new references. If protocol handler is not
325155737fdaSStephen Hemminger * a module then it needs to provide its own protection in
325255737fdaSStephen Hemminger * the ops->create routine.
32531da177e4SLinus Torvalds */
sock_unregister(int family)3254f0fd27d4SStephen Hemminger void sock_unregister(int family)
32551da177e4SLinus Torvalds {
3256f0fd27d4SStephen Hemminger BUG_ON(family < 0 || family >= NPROTO);
32571da177e4SLinus Torvalds
325855737fdaSStephen Hemminger spin_lock(&net_family_lock);
3259a9b3cd7fSStephen Hemminger RCU_INIT_POINTER(net_families[family], NULL);
326055737fdaSStephen Hemminger spin_unlock(&net_family_lock);
326155737fdaSStephen Hemminger
326255737fdaSStephen Hemminger synchronize_rcu();
326355737fdaSStephen Hemminger
3264fe0bdbdeSYejune Deng pr_info("NET: Unregistered %s protocol family\n", pf_family_names[family]);
32651da177e4SLinus Torvalds }
3266c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
32671da177e4SLinus Torvalds
sock_is_registered(int family)3268bf2ae2e4SXin Long bool sock_is_registered(int family)
3269bf2ae2e4SXin Long {
327066b51b0aSJeremy Cline return family < NPROTO && rcu_access_pointer(net_families[family]);
3271bf2ae2e4SXin Long }
3272bf2ae2e4SXin Long
sock_init(void)327377d76ea3SAndi Kleen static int __init sock_init(void)
32741da177e4SLinus Torvalds {
3275b3e19d92SNick Piggin int err;
32762ca794e5SEric W. Biederman /*
32772ca794e5SEric W. Biederman * Initialize the network sysctl infrastructure.
32782ca794e5SEric W. Biederman */
32792ca794e5SEric W. Biederman err = net_sysctl_init();
32802ca794e5SEric W. Biederman if (err)
32812ca794e5SEric W. Biederman goto out;
3282b3e19d92SNick Piggin
32831da177e4SLinus Torvalds /*
32841da177e4SLinus Torvalds * Initialize skbuff SLAB cache
32851da177e4SLinus Torvalds */
32861da177e4SLinus Torvalds skb_init();
32871da177e4SLinus Torvalds
32881da177e4SLinus Torvalds /*
32891da177e4SLinus Torvalds * Initialize the protocols module.
32901da177e4SLinus Torvalds */
32911da177e4SLinus Torvalds
32921da177e4SLinus Torvalds init_inodecache();
3293b3e19d92SNick Piggin
3294b3e19d92SNick Piggin err = register_filesystem(&sock_fs_type);
3295b3e19d92SNick Piggin if (err)
329647260ba9SMiaohe Lin goto out;
32971da177e4SLinus Torvalds sock_mnt = kern_mount(&sock_fs_type);
3298b3e19d92SNick Piggin if (IS_ERR(sock_mnt)) {
3299b3e19d92SNick Piggin err = PTR_ERR(sock_mnt);
3300b3e19d92SNick Piggin goto out_mount;
3301b3e19d92SNick Piggin }
330277d76ea3SAndi Kleen
330377d76ea3SAndi Kleen /* The real protocol initialization is performed in later initcalls.
33041da177e4SLinus Torvalds */
33051da177e4SLinus Torvalds
33061da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
33076d11cfdbSPablo Neira Ayuso err = netfilter_init();
33086d11cfdbSPablo Neira Ayuso if (err)
33096d11cfdbSPablo Neira Ayuso goto out;
33101da177e4SLinus Torvalds #endif
3311cbeb321aSDavid S. Miller
3312408eccceSDaniel Borkmann ptp_classifier_init();
3313c1f19b51SRichard Cochran
3314b3e19d92SNick Piggin out:
3315b3e19d92SNick Piggin return err;
3316b3e19d92SNick Piggin
3317b3e19d92SNick Piggin out_mount:
3318b3e19d92SNick Piggin unregister_filesystem(&sock_fs_type);
3319b3e19d92SNick Piggin goto out;
33201da177e4SLinus Torvalds }
33211da177e4SLinus Torvalds
332277d76ea3SAndi Kleen core_initcall(sock_init); /* early initcall */
332377d76ea3SAndi Kleen
33241da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
socket_seq_show(struct seq_file * seq)33251da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
33261da177e4SLinus Torvalds {
3327648845abSTonghao Zhang seq_printf(seq, "sockets: used %d\n",
3328648845abSTonghao Zhang sock_inuse_get(seq->private));
33291da177e4SLinus Torvalds }
33301da177e4SLinus Torvalds #endif /* CONFIG_PROC_FS */
33311da177e4SLinus Torvalds
333229c49648SArnd Bergmann /* Handle the fact that while struct ifreq has the same *layout* on
333329c49648SArnd Bergmann * 32/64 for everything but ifreq::ifru_ifmap and ifreq::ifru_data,
333429c49648SArnd Bergmann * which are handled elsewhere, it still has different *size* due to
333529c49648SArnd Bergmann * ifreq::ifru_ifmap (which is 16 bytes on 32 bit, 24 bytes on 64-bit,
333629c49648SArnd Bergmann * resulting in struct ifreq being 32 and 40 bytes respectively).
333729c49648SArnd Bergmann * As a result, if the struct happens to be at the end of a page and
333829c49648SArnd Bergmann * the next page isn't readable/writable, we get a fault. To prevent
333929c49648SArnd Bergmann * that, copy back and forth to the full size.
334029c49648SArnd Bergmann */
get_user_ifreq(struct ifreq * ifr,void __user ** ifrdata,void __user * arg)334129c49648SArnd Bergmann int get_user_ifreq(struct ifreq *ifr, void __user **ifrdata, void __user *arg)
334229c49648SArnd Bergmann {
334329c49648SArnd Bergmann if (in_compat_syscall()) {
334429c49648SArnd Bergmann struct compat_ifreq *ifr32 = (struct compat_ifreq *)ifr;
334529c49648SArnd Bergmann
334629c49648SArnd Bergmann memset(ifr, 0, sizeof(*ifr));
334729c49648SArnd Bergmann if (copy_from_user(ifr32, arg, sizeof(*ifr32)))
334829c49648SArnd Bergmann return -EFAULT;
334929c49648SArnd Bergmann
335029c49648SArnd Bergmann if (ifrdata)
335129c49648SArnd Bergmann *ifrdata = compat_ptr(ifr32->ifr_data);
335229c49648SArnd Bergmann
335329c49648SArnd Bergmann return 0;
335429c49648SArnd Bergmann }
335529c49648SArnd Bergmann
335629c49648SArnd Bergmann if (copy_from_user(ifr, arg, sizeof(*ifr)))
335729c49648SArnd Bergmann return -EFAULT;
335829c49648SArnd Bergmann
335929c49648SArnd Bergmann if (ifrdata)
336029c49648SArnd Bergmann *ifrdata = ifr->ifr_data;
336129c49648SArnd Bergmann
336229c49648SArnd Bergmann return 0;
336329c49648SArnd Bergmann }
336429c49648SArnd Bergmann EXPORT_SYMBOL(get_user_ifreq);
336529c49648SArnd Bergmann
put_user_ifreq(struct ifreq * ifr,void __user * arg)336629c49648SArnd Bergmann int put_user_ifreq(struct ifreq *ifr, void __user *arg)
336729c49648SArnd Bergmann {
336829c49648SArnd Bergmann size_t size = sizeof(*ifr);
336929c49648SArnd Bergmann
337029c49648SArnd Bergmann if (in_compat_syscall())
337129c49648SArnd Bergmann size = sizeof(struct compat_ifreq);
337229c49648SArnd Bergmann
337329c49648SArnd Bergmann if (copy_to_user(arg, ifr, size))
337429c49648SArnd Bergmann return -EFAULT;
337529c49648SArnd Bergmann
337629c49648SArnd Bergmann return 0;
337729c49648SArnd Bergmann }
337829c49648SArnd Bergmann EXPORT_SYMBOL(put_user_ifreq);
337929c49648SArnd Bergmann
338089bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
compat_siocwandev(struct net * net,struct compat_ifreq __user * uifr32)33817a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
33827a50a240SArnd Bergmann {
33837a50a240SArnd Bergmann compat_uptr_t uptr32;
338444c02a2cSAl Viro struct ifreq ifr;
338544c02a2cSAl Viro void __user *saved;
338644c02a2cSAl Viro int err;
33877a50a240SArnd Bergmann
338829c49648SArnd Bergmann if (get_user_ifreq(&ifr, NULL, uifr32))
33897a50a240SArnd Bergmann return -EFAULT;
33907a50a240SArnd Bergmann
33917a50a240SArnd Bergmann if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
33927a50a240SArnd Bergmann return -EFAULT;
33937a50a240SArnd Bergmann
339444c02a2cSAl Viro saved = ifr.ifr_settings.ifs_ifsu.raw_hdlc;
339544c02a2cSAl Viro ifr.ifr_settings.ifs_ifsu.raw_hdlc = compat_ptr(uptr32);
33967a50a240SArnd Bergmann
3397a554bf96SArnd Bergmann err = dev_ioctl(net, SIOCWANDEV, &ifr, NULL, NULL);
339844c02a2cSAl Viro if (!err) {
339944c02a2cSAl Viro ifr.ifr_settings.ifs_ifsu.raw_hdlc = saved;
340029c49648SArnd Bergmann if (put_user_ifreq(&ifr, uifr32))
340144c02a2cSAl Viro err = -EFAULT;
34027a50a240SArnd Bergmann }
34037a229387SArnd Bergmann return err;
34047a229387SArnd Bergmann }
34057a229387SArnd Bergmann
3406590d4693SBen Hutchings /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
compat_ifr_data_ioctl(struct net * net,unsigned int cmd,struct compat_ifreq __user * u_ifreq32)3407590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
34086b96018bSArnd Bergmann struct compat_ifreq __user *u_ifreq32)
34097a229387SArnd Bergmann {
341044c02a2cSAl Viro struct ifreq ifreq;
3411a554bf96SArnd Bergmann void __user *data;
34127a229387SArnd Bergmann
3413d0efb162SPeter Collingbourne if (!is_socket_ioctl_cmd(cmd))
3414d0efb162SPeter Collingbourne return -ENOTTY;
3415a554bf96SArnd Bergmann if (get_user_ifreq(&ifreq, &data, u_ifreq32))
34167a229387SArnd Bergmann return -EFAULT;
3417a554bf96SArnd Bergmann ifreq.ifr_data = data;
34187a229387SArnd Bergmann
3419a554bf96SArnd Bergmann return dev_ioctl(net, cmd, &ifreq, data, NULL);
34207a229387SArnd Bergmann }
34217a229387SArnd Bergmann
compat_sock_ioctl_trans(struct file * file,struct socket * sock,unsigned int cmd,unsigned long arg)34226b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
34236b96018bSArnd Bergmann unsigned int cmd, unsigned long arg)
34246b96018bSArnd Bergmann {
34256b96018bSArnd Bergmann void __user *argp = compat_ptr(arg);
34266b96018bSArnd Bergmann struct sock *sk = sock->sk;
34276b96018bSArnd Bergmann struct net *net = sock_net(sk);
34281ded5e5aSEric Dumazet const struct proto_ops *ops;
34297a229387SArnd Bergmann
34306b96018bSArnd Bergmann if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
343188fc023fSArnd Bergmann return sock_ioctl(file, cmd, (unsigned long)argp);
34327a229387SArnd Bergmann
34336b96018bSArnd Bergmann switch (cmd) {
34347a50a240SArnd Bergmann case SIOCWANDEV:
34357a50a240SArnd Bergmann return compat_siocwandev(net, argp);
34360768e170SArnd Bergmann case SIOCGSTAMP_OLD:
34370768e170SArnd Bergmann case SIOCGSTAMPNS_OLD:
34381ded5e5aSEric Dumazet ops = READ_ONCE(sock->ops);
34391ded5e5aSEric Dumazet if (!ops->gettstamp)
3440c7cbdbf2SArnd Bergmann return -ENOIOCTLCMD;
34411ded5e5aSEric Dumazet return ops->gettstamp(sock, argp, cmd == SIOCGSTAMP_OLD,
3442c7cbdbf2SArnd Bergmann !COMPAT_USE_64BIT_TIME);
3443c7cbdbf2SArnd Bergmann
3444dd98d289SArnd Bergmann case SIOCETHTOOL:
3445590d4693SBen Hutchings case SIOCBONDSLAVEINFOQUERY:
3446590d4693SBen Hutchings case SIOCBONDINFOQUERY:
3447a2116ed2SArnd Bergmann case SIOCSHWTSTAMP:
3448fd468c74SBen Hutchings case SIOCGHWTSTAMP:
3449590d4693SBen Hutchings return compat_ifr_data_ioctl(net, cmd, argp);
34507a229387SArnd Bergmann
34516b96018bSArnd Bergmann case FIOSETOWN:
34526b96018bSArnd Bergmann case SIOCSPGRP:
34536b96018bSArnd Bergmann case FIOGETOWN:
34546b96018bSArnd Bergmann case SIOCGPGRP:
34556b96018bSArnd Bergmann case SIOCBRADDBR:
34566b96018bSArnd Bergmann case SIOCBRDELBR:
34576b96018bSArnd Bergmann case SIOCGIFVLAN:
34586b96018bSArnd Bergmann case SIOCSIFVLAN:
3459c62cce2cSAndrey Vagin case SIOCGSKNS:
34600768e170SArnd Bergmann case SIOCGSTAMP_NEW:
34610768e170SArnd Bergmann case SIOCGSTAMPNS_NEW:
3462876f0bf9SArnd Bergmann case SIOCGIFCONF:
3463fd3a4590SRemi Pommarel case SIOCSIFBR:
3464fd3a4590SRemi Pommarel case SIOCGIFBR:
34656b96018bSArnd Bergmann return sock_ioctl(file, cmd, arg);
34666b96018bSArnd Bergmann
34676b96018bSArnd Bergmann case SIOCGIFFLAGS:
34686b96018bSArnd Bergmann case SIOCSIFFLAGS:
3469709566d7SArnd Bergmann case SIOCGIFMAP:
3470709566d7SArnd Bergmann case SIOCSIFMAP:
34716b96018bSArnd Bergmann case SIOCGIFMETRIC:
34726b96018bSArnd Bergmann case SIOCSIFMETRIC:
34736b96018bSArnd Bergmann case SIOCGIFMTU:
34746b96018bSArnd Bergmann case SIOCSIFMTU:
34756b96018bSArnd Bergmann case SIOCGIFMEM:
34766b96018bSArnd Bergmann case SIOCSIFMEM:
34776b96018bSArnd Bergmann case SIOCGIFHWADDR:
34786b96018bSArnd Bergmann case SIOCSIFHWADDR:
34796b96018bSArnd Bergmann case SIOCADDMULTI:
34806b96018bSArnd Bergmann case SIOCDELMULTI:
34816b96018bSArnd Bergmann case SIOCGIFINDEX:
34826b96018bSArnd Bergmann case SIOCGIFADDR:
34836b96018bSArnd Bergmann case SIOCSIFADDR:
34846b96018bSArnd Bergmann case SIOCSIFHWBROADCAST:
34856b96018bSArnd Bergmann case SIOCDIFADDR:
34866b96018bSArnd Bergmann case SIOCGIFBRDADDR:
34876b96018bSArnd Bergmann case SIOCSIFBRDADDR:
34886b96018bSArnd Bergmann case SIOCGIFDSTADDR:
34896b96018bSArnd Bergmann case SIOCSIFDSTADDR:
34906b96018bSArnd Bergmann case SIOCGIFNETMASK:
34916b96018bSArnd Bergmann case SIOCSIFNETMASK:
34926b96018bSArnd Bergmann case SIOCSIFPFLAGS:
34936b96018bSArnd Bergmann case SIOCGIFPFLAGS:
34946b96018bSArnd Bergmann case SIOCGIFTXQLEN:
34956b96018bSArnd Bergmann case SIOCSIFTXQLEN:
34966b96018bSArnd Bergmann case SIOCBRADDIF:
34976b96018bSArnd Bergmann case SIOCBRDELIF:
3498c6c9fee3SJohannes Berg case SIOCGIFNAME:
34999177efd3SArnd Bergmann case SIOCSIFNAME:
35009177efd3SArnd Bergmann case SIOCGMIIPHY:
35019177efd3SArnd Bergmann case SIOCGMIIREG:
35029177efd3SArnd Bergmann case SIOCSMIIREG:
3503f92d4fc9SAl Viro case SIOCBONDENSLAVE:
3504f92d4fc9SAl Viro case SIOCBONDRELEASE:
3505f92d4fc9SAl Viro case SIOCBONDSETHWADDR:
3506f92d4fc9SAl Viro case SIOCBONDCHANGEACTIVE:
35076b96018bSArnd Bergmann case SIOCSARP:
35086b96018bSArnd Bergmann case SIOCGARP:
35096b96018bSArnd Bergmann case SIOCDARP:
3510c7dc504eSArnd Bergmann case SIOCOUTQ:
35119d7bf41fSArnd Bergmann case SIOCOUTQNSD:
35126b96018bSArnd Bergmann case SIOCATMARK:
351363ff03abSJohannes Berg return sock_do_ioctl(net, sock, cmd, arg);
35149177efd3SArnd Bergmann }
35159177efd3SArnd Bergmann
35166b96018bSArnd Bergmann return -ENOIOCTLCMD;
35176b96018bSArnd Bergmann }
35187a229387SArnd Bergmann
compat_sock_ioctl(struct file * file,unsigned int cmd,unsigned long arg)351995c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
352089bbfc95SShaun Pereira unsigned long arg)
352189bbfc95SShaun Pereira {
352289bbfc95SShaun Pereira struct socket *sock = file->private_data;
35231ded5e5aSEric Dumazet const struct proto_ops *ops = READ_ONCE(sock->ops);
352489bbfc95SShaun Pereira int ret = -ENOIOCTLCMD;
352587de87d5SDavid S. Miller struct sock *sk;
352687de87d5SDavid S. Miller struct net *net;
352787de87d5SDavid S. Miller
352887de87d5SDavid S. Miller sk = sock->sk;
352987de87d5SDavid S. Miller net = sock_net(sk);
353089bbfc95SShaun Pereira
35311ded5e5aSEric Dumazet if (ops->compat_ioctl)
35321ded5e5aSEric Dumazet ret = ops->compat_ioctl(sock, cmd, arg);
353389bbfc95SShaun Pereira
353487de87d5SDavid S. Miller if (ret == -ENOIOCTLCMD &&
353587de87d5SDavid S. Miller (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
353687de87d5SDavid S. Miller ret = compat_wext_handle_ioctl(net, cmd, arg);
353787de87d5SDavid S. Miller
35386b96018bSArnd Bergmann if (ret == -ENOIOCTLCMD)
35396b96018bSArnd Bergmann ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
35406b96018bSArnd Bergmann
354189bbfc95SShaun Pereira return ret;
354289bbfc95SShaun Pereira }
354389bbfc95SShaun Pereira #endif
354489bbfc95SShaun Pereira
35458a3c245cSPedro Tammela /**
35468a3c245cSPedro Tammela * kernel_bind - bind an address to a socket (kernel space)
35478a3c245cSPedro Tammela * @sock: socket
35488a3c245cSPedro Tammela * @addr: address
35498a3c245cSPedro Tammela * @addrlen: length of address
35508a3c245cSPedro Tammela *
35518a3c245cSPedro Tammela * Returns 0 or an error.
35528a3c245cSPedro Tammela */
35538a3c245cSPedro Tammela
kernel_bind(struct socket * sock,struct sockaddr * addr,int addrlen)3554ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3555ac5a488eSSridhar Samudrala {
3556c889a99aSJordan Rife struct sockaddr_storage address;
3557c889a99aSJordan Rife
3558c889a99aSJordan Rife memcpy(&address, addr, addrlen);
3559c889a99aSJordan Rife
3560c889a99aSJordan Rife return READ_ONCE(sock->ops)->bind(sock, (struct sockaddr *)&address,
3561c889a99aSJordan Rife addrlen);
3562ac5a488eSSridhar Samudrala }
3563c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3564ac5a488eSSridhar Samudrala
35658a3c245cSPedro Tammela /**
35668a3c245cSPedro Tammela * kernel_listen - move socket to listening state (kernel space)
35678a3c245cSPedro Tammela * @sock: socket
35688a3c245cSPedro Tammela * @backlog: pending connections queue size
35698a3c245cSPedro Tammela *
35708a3c245cSPedro Tammela * Returns 0 or an error.
35718a3c245cSPedro Tammela */
35728a3c245cSPedro Tammela
kernel_listen(struct socket * sock,int backlog)3573ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3574ac5a488eSSridhar Samudrala {
35751ded5e5aSEric Dumazet return READ_ONCE(sock->ops)->listen(sock, backlog);
3576ac5a488eSSridhar Samudrala }
3577c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3578ac5a488eSSridhar Samudrala
35798a3c245cSPedro Tammela /**
35808a3c245cSPedro Tammela * kernel_accept - accept a connection (kernel space)
35818a3c245cSPedro Tammela * @sock: listening socket
35828a3c245cSPedro Tammela * @newsock: new connected socket
35838a3c245cSPedro Tammela * @flags: flags
35848a3c245cSPedro Tammela *
35858a3c245cSPedro Tammela * @flags must be SOCK_CLOEXEC, SOCK_NONBLOCK or 0.
35868a3c245cSPedro Tammela * If it fails, @newsock is guaranteed to be %NULL.
35878a3c245cSPedro Tammela * Returns 0 or an error.
35888a3c245cSPedro Tammela */
35898a3c245cSPedro Tammela
kernel_accept(struct socket * sock,struct socket ** newsock,int flags)3590ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3591ac5a488eSSridhar Samudrala {
3592ac5a488eSSridhar Samudrala struct sock *sk = sock->sk;
35931ded5e5aSEric Dumazet const struct proto_ops *ops = READ_ONCE(sock->ops);
3594ac5a488eSSridhar Samudrala int err;
3595ac5a488eSSridhar Samudrala
3596ac5a488eSSridhar Samudrala err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3597ac5a488eSSridhar Samudrala newsock);
3598ac5a488eSSridhar Samudrala if (err < 0)
3599ac5a488eSSridhar Samudrala goto done;
3600ac5a488eSSridhar Samudrala
36011ded5e5aSEric Dumazet err = ops->accept(sock, *newsock, flags, true);
3602ac5a488eSSridhar Samudrala if (err < 0) {
3603ac5a488eSSridhar Samudrala sock_release(*newsock);
3604fa8705b0STony Battersby *newsock = NULL;
3605ac5a488eSSridhar Samudrala goto done;
3606ac5a488eSSridhar Samudrala }
3607ac5a488eSSridhar Samudrala
36081ded5e5aSEric Dumazet (*newsock)->ops = ops;
36091ded5e5aSEric Dumazet __module_get(ops->owner);
3610ac5a488eSSridhar Samudrala
3611ac5a488eSSridhar Samudrala done:
3612ac5a488eSSridhar Samudrala return err;
3613ac5a488eSSridhar Samudrala }
3614c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3615ac5a488eSSridhar Samudrala
36168a3c245cSPedro Tammela /**
36178a3c245cSPedro Tammela * kernel_connect - connect a socket (kernel space)
36188a3c245cSPedro Tammela * @sock: socket
36198a3c245cSPedro Tammela * @addr: address
36208a3c245cSPedro Tammela * @addrlen: address length
36218a3c245cSPedro Tammela * @flags: flags (O_NONBLOCK, ...)
36228a3c245cSPedro Tammela *
3623f1dcffccSLu Wei * For datagram sockets, @addr is the address to which datagrams are sent
36248a3c245cSPedro Tammela * by default, and the only address from which datagrams are received.
36258a3c245cSPedro Tammela * For stream sockets, attempts to connect to @addr.
36268a3c245cSPedro Tammela * Returns 0 or an error code.
36278a3c245cSPedro Tammela */
36288a3c245cSPedro Tammela
kernel_connect(struct socket * sock,struct sockaddr * addr,int addrlen,int flags)3629ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3630ac5a488eSSridhar Samudrala int flags)
3631ac5a488eSSridhar Samudrala {
36320bdf3993SJordan Rife struct sockaddr_storage address;
36330bdf3993SJordan Rife
36340bdf3993SJordan Rife memcpy(&address, addr, addrlen);
36350bdf3993SJordan Rife
36360bdf3993SJordan Rife return READ_ONCE(sock->ops)->connect(sock, (struct sockaddr *)&address,
36370bdf3993SJordan Rife addrlen, flags);
3638ac5a488eSSridhar Samudrala }
3639c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3640ac5a488eSSridhar Samudrala
36418a3c245cSPedro Tammela /**
36428a3c245cSPedro Tammela * kernel_getsockname - get the address which the socket is bound (kernel space)
36438a3c245cSPedro Tammela * @sock: socket
36448a3c245cSPedro Tammela * @addr: address holder
36458a3c245cSPedro Tammela *
36468a3c245cSPedro Tammela * Fills the @addr pointer with the address which the socket is bound.
36470fc95decSAlex Maydanik * Returns the length of the address in bytes or an error code.
36488a3c245cSPedro Tammela */
36498a3c245cSPedro Tammela
kernel_getsockname(struct socket * sock,struct sockaddr * addr)36509b2c45d4SDenys Vlasenko int kernel_getsockname(struct socket *sock, struct sockaddr *addr)
3651ac5a488eSSridhar Samudrala {
36521ded5e5aSEric Dumazet return READ_ONCE(sock->ops)->getname(sock, addr, 0);
3653ac5a488eSSridhar Samudrala }
3654c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3655ac5a488eSSridhar Samudrala
36568a3c245cSPedro Tammela /**
3657645f0897SMiaohe Lin * kernel_getpeername - get the address which the socket is connected (kernel space)
36588a3c245cSPedro Tammela * @sock: socket
36598a3c245cSPedro Tammela * @addr: address holder
36608a3c245cSPedro Tammela *
36618a3c245cSPedro Tammela * Fills the @addr pointer with the address which the socket is connected.
36620fc95decSAlex Maydanik * Returns the length of the address in bytes or an error code.
36638a3c245cSPedro Tammela */
36648a3c245cSPedro Tammela
kernel_getpeername(struct socket * sock,struct sockaddr * addr)36659b2c45d4SDenys Vlasenko int kernel_getpeername(struct socket *sock, struct sockaddr *addr)
3666ac5a488eSSridhar Samudrala {
36671ded5e5aSEric Dumazet return READ_ONCE(sock->ops)->getname(sock, addr, 1);
3668ac5a488eSSridhar Samudrala }
3669c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3670ac5a488eSSridhar Samudrala
36718a3c245cSPedro Tammela /**
3672645f0897SMiaohe Lin * kernel_sock_shutdown - shut down part of a full-duplex connection (kernel space)
36738a3c245cSPedro Tammela * @sock: socket
36748a3c245cSPedro Tammela * @how: connection part
36758a3c245cSPedro Tammela *
36768a3c245cSPedro Tammela * Returns 0 or an error.
36778a3c245cSPedro Tammela */
36788a3c245cSPedro Tammela
kernel_sock_shutdown(struct socket * sock,enum sock_shutdown_cmd how)367991cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
368091cf45f0STrond Myklebust {
36811ded5e5aSEric Dumazet return READ_ONCE(sock->ops)->shutdown(sock, how);
368291cf45f0STrond Myklebust }
368391cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3684113c3075SR. Parameswaran
36858a3c245cSPedro Tammela /**
36868a3c245cSPedro Tammela * kernel_sock_ip_overhead - returns the IP overhead imposed by a socket
36878a3c245cSPedro Tammela * @sk: socket
36888a3c245cSPedro Tammela *
36898a3c245cSPedro Tammela * This routine returns the IP overhead imposed by a socket i.e.
3690113c3075SR. Parameswaran * the length of the underlying IP header, depending on whether
3691113c3075SR. Parameswaran * this is an IPv4 or IPv6 socket and the length from IP options turned
369257240d00SR. Parameswaran * on at the socket. Assumes that the caller has a lock on the socket.
3693113c3075SR. Parameswaran */
36948a3c245cSPedro Tammela
kernel_sock_ip_overhead(struct sock * sk)3695113c3075SR. Parameswaran u32 kernel_sock_ip_overhead(struct sock *sk)
3696113c3075SR. Parameswaran {
3697113c3075SR. Parameswaran struct inet_sock *inet;
3698113c3075SR. Parameswaran struct ip_options_rcu *opt;
3699113c3075SR. Parameswaran u32 overhead = 0;
3700113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6)
3701113c3075SR. Parameswaran struct ipv6_pinfo *np;
3702113c3075SR. Parameswaran struct ipv6_txoptions *optv6 = NULL;
3703113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */
3704113c3075SR. Parameswaran
3705113c3075SR. Parameswaran if (!sk)
3706113c3075SR. Parameswaran return overhead;
3707113c3075SR. Parameswaran
3708113c3075SR. Parameswaran switch (sk->sk_family) {
3709113c3075SR. Parameswaran case AF_INET:
3710113c3075SR. Parameswaran inet = inet_sk(sk);
3711113c3075SR. Parameswaran overhead += sizeof(struct iphdr);
3712113c3075SR. Parameswaran opt = rcu_dereference_protected(inet->inet_opt,
3713614d79c0Sstephen hemminger sock_owned_by_user(sk));
3714113c3075SR. Parameswaran if (opt)
3715113c3075SR. Parameswaran overhead += opt->opt.optlen;
3716113c3075SR. Parameswaran return overhead;
3717113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6)
3718113c3075SR. Parameswaran case AF_INET6:
3719113c3075SR. Parameswaran np = inet6_sk(sk);
3720113c3075SR. Parameswaran overhead += sizeof(struct ipv6hdr);
3721113c3075SR. Parameswaran if (np)
3722113c3075SR. Parameswaran optv6 = rcu_dereference_protected(np->opt,
3723614d79c0Sstephen hemminger sock_owned_by_user(sk));
3724113c3075SR. Parameswaran if (optv6)
3725113c3075SR. Parameswaran overhead += (optv6->opt_flen + optv6->opt_nflen);
3726113c3075SR. Parameswaran return overhead;
3727113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */
3728113c3075SR. Parameswaran default: /* Returns 0 overhead if the socket is not ipv4 or ipv6 */
3729113c3075SR. Parameswaran return overhead;
3730113c3075SR. Parameswaran }
3731113c3075SR. Parameswaran }
3732113c3075SR. Parameswaran EXPORT_SYMBOL(kernel_sock_ip_overhead);
3733