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 551da177e4SLinus Torvalds #include <linux/mm.h> 561da177e4SLinus Torvalds #include <linux/socket.h> 571da177e4SLinus Torvalds #include <linux/file.h> 581da177e4SLinus Torvalds #include <linux/net.h> 591da177e4SLinus Torvalds #include <linux/interrupt.h> 60aaca0bdcSUlrich Drepper #include <linux/thread_info.h> 6155737fdaSStephen Hemminger #include <linux/rcupdate.h> 621da177e4SLinus Torvalds #include <linux/netdevice.h> 631da177e4SLinus Torvalds #include <linux/proc_fs.h> 641da177e4SLinus Torvalds #include <linux/seq_file.h> 654a3e2f71SArjan van de Ven #include <linux/mutex.h> 661da177e4SLinus Torvalds #include <linux/if_bridge.h> 6720380731SArnaldo Carvalho de Melo #include <linux/if_frad.h> 6820380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h> 69408eccceSDaniel Borkmann #include <linux/ptp_classify.h> 701da177e4SLinus Torvalds #include <linux/init.h> 711da177e4SLinus Torvalds #include <linux/poll.h> 721da177e4SLinus Torvalds #include <linux/cache.h> 731da177e4SLinus Torvalds #include <linux/module.h> 741da177e4SLinus Torvalds #include <linux/highmem.h> 751da177e4SLinus Torvalds #include <linux/mount.h> 76fba9be49SDavid Howells #include <linux/pseudo_fs.h> 771da177e4SLinus Torvalds #include <linux/security.h> 781da177e4SLinus Torvalds #include <linux/syscalls.h> 791da177e4SLinus Torvalds #include <linux/compat.h> 801da177e4SLinus Torvalds #include <linux/kmod.h> 813ec3b2fbSDavid Woodhouse #include <linux/audit.h> 82d86b5e0eSAdrian Bunk #include <linux/wireless.h> 831b8d7ae4SEric W. Biederman #include <linux/nsproxy.h> 841fd7317dSNick Black #include <linux/magic.h> 855a0e3ad6STejun Heo #include <linux/slab.h> 86600e1779SMasatake YAMATO #include <linux/xattr.h> 87c8e8cd57SJeremy Cline #include <linux/nospec.h> 888c3c447bSPaolo Abeni #include <linux/indirect_call_wrapper.h> 891da177e4SLinus Torvalds 907c0f6ba6SLinus Torvalds #include <linux/uaccess.h> 911da177e4SLinus Torvalds #include <asm/unistd.h> 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds #include <net/compat.h> 9487de87d5SDavid S. Miller #include <net/wext.h> 95f8451725SHerbert Xu #include <net/cls_cgroup.h> 961da177e4SLinus Torvalds 971da177e4SLinus Torvalds #include <net/sock.h> 981da177e4SLinus Torvalds #include <linux/netfilter.h> 991da177e4SLinus Torvalds 1006b96018bSArnd Bergmann #include <linux/if_tun.h> 1016b96018bSArnd Bergmann #include <linux/ipv6_route.h> 1026b96018bSArnd Bergmann #include <linux/route.h> 103c7dc504eSArnd Bergmann #include <linux/termios.h> 1046b96018bSArnd Bergmann #include <linux/sockios.h> 105076bb0c8SEliezer Tamir #include <net/busy_poll.h> 106f24b9be5SWillem de Bruijn #include <linux/errqueue.h> 10706021292SEliezer Tamir 108e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL 10964b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly; 11064b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly; 11106021292SEliezer Tamir #endif 1126b96018bSArnd Bergmann 1138ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to); 1148ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from); 1151da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma); 1161da177e4SLinus Torvalds 1171da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file); 118a11e1d43SLinus Torvalds static __poll_t sock_poll(struct file *file, 119a11e1d43SLinus Torvalds struct poll_table_struct *wait); 12089bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 12189bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 12289bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file, 12389bbfc95SShaun Pereira unsigned int cmd, unsigned long arg); 12489bbfc95SShaun Pereira #endif 1251da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on); 1261da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page, 1271da177e4SLinus Torvalds int offset, size_t size, loff_t *ppos, int more); 1289c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos, 1299c55e01cSJens Axboe struct pipe_inode_info *pipe, size_t len, 1309c55e01cSJens Axboe unsigned int flags); 131542d3065SArnd Bergmann 132542d3065SArnd Bergmann #ifdef CONFIG_PROC_FS 133542d3065SArnd Bergmann static void sock_show_fdinfo(struct seq_file *m, struct file *f) 134542d3065SArnd Bergmann { 135542d3065SArnd Bergmann struct socket *sock = f->private_data; 136542d3065SArnd Bergmann 137542d3065SArnd Bergmann if (sock->ops->show_fdinfo) 138542d3065SArnd Bergmann sock->ops->show_fdinfo(m, sock); 139542d3065SArnd Bergmann } 140542d3065SArnd Bergmann #else 141542d3065SArnd Bergmann #define sock_show_fdinfo NULL 142542d3065SArnd Bergmann #endif 1431da177e4SLinus Torvalds 1441da177e4SLinus Torvalds /* 1451da177e4SLinus Torvalds * Socket files have a set of 'special' operations as well as the generic file ones. These don't appear 1461da177e4SLinus Torvalds * in the operation structures but are done directly via the socketcall() multiplexor. 1471da177e4SLinus Torvalds */ 1481da177e4SLinus Torvalds 149da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = { 1501da177e4SLinus Torvalds .owner = THIS_MODULE, 1511da177e4SLinus Torvalds .llseek = no_llseek, 1528ae5e030SAl Viro .read_iter = sock_read_iter, 1538ae5e030SAl Viro .write_iter = sock_write_iter, 1541da177e4SLinus Torvalds .poll = sock_poll, 1551da177e4SLinus Torvalds .unlocked_ioctl = sock_ioctl, 15689bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 15789bbfc95SShaun Pereira .compat_ioctl = compat_sock_ioctl, 15889bbfc95SShaun Pereira #endif 1591da177e4SLinus Torvalds .mmap = sock_mmap, 1601da177e4SLinus Torvalds .release = sock_close, 1611da177e4SLinus Torvalds .fasync = sock_fasync, 1625274f052SJens Axboe .sendpage = sock_sendpage, 1635274f052SJens Axboe .splice_write = generic_splice_sendpage, 1649c55e01cSJens Axboe .splice_read = sock_splice_read, 165b4653342SKirill Tkhai .show_fdinfo = sock_show_fdinfo, 1661da177e4SLinus Torvalds }; 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds /* 1691da177e4SLinus Torvalds * The protocol list. Each protocol is registered in here. 1701da177e4SLinus Torvalds */ 1711da177e4SLinus Torvalds 1721da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock); 173190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly; 1741da177e4SLinus Torvalds 1751da177e4SLinus Torvalds /* 17689bddce5SStephen Hemminger * Support routines. 17789bddce5SStephen Hemminger * Move socket addresses back and forth across the kernel/user 1781da177e4SLinus Torvalds * divide and look after the messy bits. 1791da177e4SLinus Torvalds */ 1801da177e4SLinus Torvalds 1811da177e4SLinus Torvalds /** 1821da177e4SLinus Torvalds * move_addr_to_kernel - copy a socket address into kernel space 1831da177e4SLinus Torvalds * @uaddr: Address in user space 1841da177e4SLinus Torvalds * @kaddr: Address in kernel space 1851da177e4SLinus Torvalds * @ulen: Length in user space 1861da177e4SLinus Torvalds * 1871da177e4SLinus Torvalds * The address is copied into kernel space. If the provided address is 1881da177e4SLinus Torvalds * too long an error code of -EINVAL is returned. If the copy gives 1891da177e4SLinus Torvalds * invalid addresses -EFAULT is returned. On a success 0 is returned. 1901da177e4SLinus Torvalds */ 1911da177e4SLinus Torvalds 19243db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr) 1931da177e4SLinus Torvalds { 194230b1839SYOSHIFUJI Hideaki if (ulen < 0 || ulen > sizeof(struct sockaddr_storage)) 1951da177e4SLinus Torvalds return -EINVAL; 1961da177e4SLinus Torvalds if (ulen == 0) 1971da177e4SLinus Torvalds return 0; 1981da177e4SLinus Torvalds if (copy_from_user(kaddr, uaddr, ulen)) 1991da177e4SLinus Torvalds return -EFAULT; 2003ec3b2fbSDavid Woodhouse return audit_sockaddr(ulen, kaddr); 2011da177e4SLinus Torvalds } 2021da177e4SLinus Torvalds 2031da177e4SLinus Torvalds /** 2041da177e4SLinus Torvalds * move_addr_to_user - copy an address to user space 2051da177e4SLinus Torvalds * @kaddr: kernel space address 2061da177e4SLinus Torvalds * @klen: length of address in kernel 2071da177e4SLinus Torvalds * @uaddr: user space address 2081da177e4SLinus Torvalds * @ulen: pointer to user length field 2091da177e4SLinus Torvalds * 2101da177e4SLinus Torvalds * The value pointed to by ulen on entry is the buffer length available. 2111da177e4SLinus Torvalds * This is overwritten with the buffer space used. -EINVAL is returned 2121da177e4SLinus Torvalds * if an overlong buffer is specified or a negative buffer size. -EFAULT 2131da177e4SLinus Torvalds * is returned if either the buffer or the length field are not 2141da177e4SLinus Torvalds * accessible. 2151da177e4SLinus Torvalds * After copying the data up to the limit the user specifies, the true 2161da177e4SLinus Torvalds * length of the data is written over the length limit the user 2171da177e4SLinus Torvalds * specified. Zero is returned for a success. 2181da177e4SLinus Torvalds */ 2191da177e4SLinus Torvalds 22043db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen, 22111165f14Sstephen hemminger void __user *uaddr, int __user *ulen) 2221da177e4SLinus Torvalds { 2231da177e4SLinus Torvalds int err; 2241da177e4SLinus Torvalds int len; 2251da177e4SLinus Torvalds 22668c6beb3SHannes Frederic Sowa BUG_ON(klen > sizeof(struct sockaddr_storage)); 22789bddce5SStephen Hemminger err = get_user(len, ulen); 22889bddce5SStephen Hemminger if (err) 2291da177e4SLinus Torvalds return err; 2301da177e4SLinus Torvalds if (len > klen) 2311da177e4SLinus Torvalds len = klen; 23268c6beb3SHannes Frederic Sowa if (len < 0) 2331da177e4SLinus Torvalds return -EINVAL; 23489bddce5SStephen Hemminger if (len) { 235d6fe3945SSteve Grubb if (audit_sockaddr(klen, kaddr)) 236d6fe3945SSteve Grubb return -ENOMEM; 2371da177e4SLinus Torvalds if (copy_to_user(uaddr, kaddr, len)) 2381da177e4SLinus Torvalds return -EFAULT; 2391da177e4SLinus Torvalds } 2401da177e4SLinus Torvalds /* 2411da177e4SLinus Torvalds * "fromlen shall refer to the value before truncation.." 2421da177e4SLinus Torvalds * 1003.1g 2431da177e4SLinus Torvalds */ 2441da177e4SLinus Torvalds return __put_user(klen, ulen); 2451da177e4SLinus Torvalds } 2461da177e4SLinus Torvalds 24708009a76SAlexey Dobriyan static struct kmem_cache *sock_inode_cachep __ro_after_init; 2481da177e4SLinus Torvalds 2491da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb) 2501da177e4SLinus Torvalds { 2511da177e4SLinus Torvalds struct socket_alloc *ei; 25289bddce5SStephen Hemminger 253e94b1766SChristoph Lameter ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL); 2541da177e4SLinus Torvalds if (!ei) 2551da177e4SLinus Torvalds return NULL; 256333f7909SAl Viro init_waitqueue_head(&ei->socket.wq.wait); 257333f7909SAl Viro ei->socket.wq.fasync_list = NULL; 258333f7909SAl Viro ei->socket.wq.flags = 0; 2591da177e4SLinus Torvalds 2601da177e4SLinus Torvalds ei->socket.state = SS_UNCONNECTED; 2611da177e4SLinus Torvalds ei->socket.flags = 0; 2621da177e4SLinus Torvalds ei->socket.ops = NULL; 2631da177e4SLinus Torvalds ei->socket.sk = NULL; 2641da177e4SLinus Torvalds ei->socket.file = NULL; 2651da177e4SLinus Torvalds 2661da177e4SLinus Torvalds return &ei->vfs_inode; 2671da177e4SLinus Torvalds } 2681da177e4SLinus Torvalds 2696d7855c5SAl Viro static void sock_free_inode(struct inode *inode) 2701da177e4SLinus Torvalds { 27143815482SEric Dumazet struct socket_alloc *ei; 27243815482SEric Dumazet 27343815482SEric Dumazet ei = container_of(inode, struct socket_alloc, vfs_inode); 27443815482SEric Dumazet kmem_cache_free(sock_inode_cachep, ei); 2751da177e4SLinus Torvalds } 2761da177e4SLinus Torvalds 27751cc5068SAlexey Dobriyan static void init_once(void *foo) 2781da177e4SLinus Torvalds { 2791da177e4SLinus Torvalds struct socket_alloc *ei = (struct socket_alloc *)foo; 2801da177e4SLinus Torvalds 2811da177e4SLinus Torvalds inode_init_once(&ei->vfs_inode); 2821da177e4SLinus Torvalds } 2831da177e4SLinus Torvalds 2841e911632Syuan linyu static void init_inodecache(void) 2851da177e4SLinus Torvalds { 2861da177e4SLinus Torvalds sock_inode_cachep = kmem_cache_create("sock_inode_cache", 2871da177e4SLinus Torvalds sizeof(struct socket_alloc), 28889bddce5SStephen Hemminger 0, 28989bddce5SStephen Hemminger (SLAB_HWCACHE_ALIGN | 29089bddce5SStephen Hemminger SLAB_RECLAIM_ACCOUNT | 2915d097056SVladimir Davydov SLAB_MEM_SPREAD | SLAB_ACCOUNT), 29220c2df83SPaul Mundt init_once); 2931e911632Syuan linyu BUG_ON(sock_inode_cachep == NULL); 2941da177e4SLinus Torvalds } 2951da177e4SLinus Torvalds 296b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = { 2971da177e4SLinus Torvalds .alloc_inode = sock_alloc_inode, 2986d7855c5SAl Viro .free_inode = sock_free_inode, 2991da177e4SLinus Torvalds .statfs = simple_statfs, 3001da177e4SLinus Torvalds }; 3011da177e4SLinus Torvalds 302c23fbb6bSEric Dumazet /* 303c23fbb6bSEric Dumazet * sockfs_dname() is called from d_path(). 304c23fbb6bSEric Dumazet */ 305c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen) 306c23fbb6bSEric Dumazet { 307c23fbb6bSEric Dumazet return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]", 308c5ef6035SDavid Howells d_inode(dentry)->i_ino); 309c23fbb6bSEric Dumazet } 310c23fbb6bSEric Dumazet 3113ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = { 312c23fbb6bSEric Dumazet .d_dname = sockfs_dname, 3131da177e4SLinus Torvalds }; 3141da177e4SLinus Torvalds 315bba0bd31SAndreas Gruenbacher static int sockfs_xattr_get(const struct xattr_handler *handler, 316bba0bd31SAndreas Gruenbacher struct dentry *dentry, struct inode *inode, 317bba0bd31SAndreas Gruenbacher const char *suffix, void *value, size_t size) 318bba0bd31SAndreas Gruenbacher { 319bba0bd31SAndreas Gruenbacher if (value) { 320bba0bd31SAndreas Gruenbacher if (dentry->d_name.len + 1 > size) 321bba0bd31SAndreas Gruenbacher return -ERANGE; 322bba0bd31SAndreas Gruenbacher memcpy(value, dentry->d_name.name, dentry->d_name.len + 1); 323bba0bd31SAndreas Gruenbacher } 324bba0bd31SAndreas Gruenbacher return dentry->d_name.len + 1; 325bba0bd31SAndreas Gruenbacher } 326bba0bd31SAndreas Gruenbacher 327bba0bd31SAndreas Gruenbacher #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname" 328bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX) 329bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1) 330bba0bd31SAndreas Gruenbacher 331bba0bd31SAndreas Gruenbacher static const struct xattr_handler sockfs_xattr_handler = { 332bba0bd31SAndreas Gruenbacher .name = XATTR_NAME_SOCKPROTONAME, 333bba0bd31SAndreas Gruenbacher .get = sockfs_xattr_get, 334bba0bd31SAndreas Gruenbacher }; 335bba0bd31SAndreas Gruenbacher 3364a590153SAndreas Gruenbacher static int sockfs_security_xattr_set(const struct xattr_handler *handler, 3374a590153SAndreas Gruenbacher struct dentry *dentry, struct inode *inode, 3384a590153SAndreas Gruenbacher const char *suffix, const void *value, 3394a590153SAndreas Gruenbacher size_t size, int flags) 3404a590153SAndreas Gruenbacher { 3414a590153SAndreas Gruenbacher /* Handled by LSM. */ 3424a590153SAndreas Gruenbacher return -EAGAIN; 3434a590153SAndreas Gruenbacher } 3444a590153SAndreas Gruenbacher 3454a590153SAndreas Gruenbacher static const struct xattr_handler sockfs_security_xattr_handler = { 3464a590153SAndreas Gruenbacher .prefix = XATTR_SECURITY_PREFIX, 3474a590153SAndreas Gruenbacher .set = sockfs_security_xattr_set, 3484a590153SAndreas Gruenbacher }; 3494a590153SAndreas Gruenbacher 350bba0bd31SAndreas Gruenbacher static const struct xattr_handler *sockfs_xattr_handlers[] = { 351bba0bd31SAndreas Gruenbacher &sockfs_xattr_handler, 3524a590153SAndreas Gruenbacher &sockfs_security_xattr_handler, 353bba0bd31SAndreas Gruenbacher NULL 354bba0bd31SAndreas Gruenbacher }; 355bba0bd31SAndreas Gruenbacher 356fba9be49SDavid Howells static int sockfs_init_fs_context(struct fs_context *fc) 357c74a1cbbSAl Viro { 358fba9be49SDavid Howells struct pseudo_fs_context *ctx = init_pseudo(fc, SOCKFS_MAGIC); 359fba9be49SDavid Howells if (!ctx) 360fba9be49SDavid Howells return -ENOMEM; 361fba9be49SDavid Howells ctx->ops = &sockfs_ops; 362fba9be49SDavid Howells ctx->dops = &sockfs_dentry_operations; 363fba9be49SDavid Howells ctx->xattr = sockfs_xattr_handlers; 364fba9be49SDavid Howells return 0; 365c74a1cbbSAl Viro } 366c74a1cbbSAl Viro 367c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly; 368c74a1cbbSAl Viro 369c74a1cbbSAl Viro static struct file_system_type sock_fs_type = { 370c74a1cbbSAl Viro .name = "sockfs", 371fba9be49SDavid Howells .init_fs_context = sockfs_init_fs_context, 372c74a1cbbSAl Viro .kill_sb = kill_anon_super, 373c74a1cbbSAl Viro }; 374c74a1cbbSAl Viro 3751da177e4SLinus Torvalds /* 3761da177e4SLinus Torvalds * Obtains the first available file descriptor and sets it up for use. 3771da177e4SLinus Torvalds * 37839d8c1b6SDavid S. Miller * These functions create file structures and maps them to fd space 37939d8c1b6SDavid S. Miller * of the current process. On success it returns file descriptor 3801da177e4SLinus Torvalds * and file struct implicitly stored in sock->file. 3811da177e4SLinus Torvalds * Note that another thread may close file descriptor before we return 3821da177e4SLinus Torvalds * from this function. We use the fact that now we do not refer 3831da177e4SLinus Torvalds * to socket after mapping. If one day we will need it, this 3841da177e4SLinus Torvalds * function will increment ref. count on file by 1. 3851da177e4SLinus Torvalds * 3861da177e4SLinus Torvalds * In any case returned fd MAY BE not valid! 3871da177e4SLinus Torvalds * This race condition is unavoidable 3881da177e4SLinus Torvalds * with shared fd spaces, we cannot solve it inside kernel, 3891da177e4SLinus Torvalds * but we take care of internal coherence yet. 3901da177e4SLinus Torvalds */ 3911da177e4SLinus Torvalds 3928a3c245cSPedro Tammela /** 3938a3c245cSPedro Tammela * sock_alloc_file - Bind a &socket to a &file 3948a3c245cSPedro Tammela * @sock: socket 3958a3c245cSPedro Tammela * @flags: file status flags 3968a3c245cSPedro Tammela * @dname: protocol name 3978a3c245cSPedro Tammela * 3988a3c245cSPedro Tammela * Returns the &file bound with @sock, implicitly storing it 3998a3c245cSPedro Tammela * in sock->file. If dname is %NULL, sets to "". 4008a3c245cSPedro Tammela * On failure the return is a ERR pointer (see linux/err.h). 4018a3c245cSPedro Tammela * This function uses GFP_KERNEL internally. 4028a3c245cSPedro Tammela */ 4038a3c245cSPedro Tammela 404aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) 4051da177e4SLinus Torvalds { 4067cbe66b6SAl Viro struct file *file; 4071da177e4SLinus Torvalds 408d93aa9d8SAl Viro if (!dname) 409d93aa9d8SAl Viro dname = sock->sk ? sock->sk->sk_prot_creator->name : ""; 41039d8c1b6SDavid S. Miller 411d93aa9d8SAl Viro file = alloc_file_pseudo(SOCK_INODE(sock), sock_mnt, dname, 412d93aa9d8SAl Viro O_RDWR | (flags & O_NONBLOCK), 413cc3808f8SAl Viro &socket_file_ops); 414b5ffe634SViresh Kumar if (IS_ERR(file)) { 4158e1611e2SAl Viro sock_release(sock); 41639b65252SAnatol Pomozov return file; 417cc3808f8SAl Viro } 4181da177e4SLinus Torvalds 4191da177e4SLinus Torvalds sock->file = file; 42007dc3f07SBenjamin LaHaise file->private_data = sock; 421d8e464ecSLinus Torvalds stream_open(SOCK_INODE(sock), file); 42228407630SAl Viro return file; 4231da177e4SLinus Torvalds } 42456b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file); 4251da177e4SLinus Torvalds 42656b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags) 42739d8c1b6SDavid S. Miller { 42839d8c1b6SDavid S. Miller struct file *newfile; 42928407630SAl Viro int fd = get_unused_fd_flags(flags); 430ce4bb04cSAl Viro if (unlikely(fd < 0)) { 431ce4bb04cSAl Viro sock_release(sock); 4321da177e4SLinus Torvalds return fd; 433ce4bb04cSAl Viro } 4341da177e4SLinus Torvalds 435aab174f0SLinus Torvalds newfile = sock_alloc_file(sock, flags, NULL); 4364546e44cSEnrico Weigelt if (!IS_ERR(newfile)) { 4371da177e4SLinus Torvalds fd_install(fd, newfile); 4381da177e4SLinus Torvalds return fd; 4391da177e4SLinus Torvalds } 44028407630SAl Viro 44128407630SAl Viro put_unused_fd(fd); 44228407630SAl Viro return PTR_ERR(newfile); 4431da177e4SLinus Torvalds } 4441da177e4SLinus Torvalds 4458a3c245cSPedro Tammela /** 4468a3c245cSPedro Tammela * sock_from_file - Return the &socket bounded to @file. 4478a3c245cSPedro Tammela * @file: file 4488a3c245cSPedro Tammela * @err: pointer to an error code return 4498a3c245cSPedro Tammela * 4508a3c245cSPedro Tammela * On failure returns %NULL and assigns -ENOTSOCK to @err. 4518a3c245cSPedro Tammela */ 4528a3c245cSPedro Tammela 453406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err) 4546cb153caSBenjamin LaHaise { 4556cb153caSBenjamin LaHaise if (file->f_op == &socket_file_ops) 4566cb153caSBenjamin LaHaise return file->private_data; /* set in sock_map_fd */ 4576cb153caSBenjamin LaHaise 4586cb153caSBenjamin LaHaise *err = -ENOTSOCK; 4596cb153caSBenjamin LaHaise return NULL; 4606cb153caSBenjamin LaHaise } 461406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file); 4626cb153caSBenjamin LaHaise 4631da177e4SLinus Torvalds /** 4641da177e4SLinus Torvalds * sockfd_lookup - Go from a file number to its socket slot 4651da177e4SLinus Torvalds * @fd: file handle 4661da177e4SLinus Torvalds * @err: pointer to an error code return 4671da177e4SLinus Torvalds * 4681da177e4SLinus Torvalds * The file handle passed in is locked and the socket it is bound 469241c4667SRosen, Rami * to is returned. If an error occurs the err pointer is overwritten 4701da177e4SLinus Torvalds * with a negative errno code and NULL is returned. The function checks 4711da177e4SLinus Torvalds * for both invalid handles and passing a handle which is not a socket. 4721da177e4SLinus Torvalds * 4731da177e4SLinus Torvalds * On a success the socket object pointer is returned. 4741da177e4SLinus Torvalds */ 4751da177e4SLinus Torvalds 4761da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err) 4771da177e4SLinus Torvalds { 4781da177e4SLinus Torvalds struct file *file; 4791da177e4SLinus Torvalds struct socket *sock; 4801da177e4SLinus Torvalds 48189bddce5SStephen Hemminger file = fget(fd); 48289bddce5SStephen Hemminger if (!file) { 4831da177e4SLinus Torvalds *err = -EBADF; 4841da177e4SLinus Torvalds return NULL; 4851da177e4SLinus Torvalds } 48689bddce5SStephen Hemminger 4876cb153caSBenjamin LaHaise sock = sock_from_file(file, err); 4886cb153caSBenjamin LaHaise if (!sock) 4891da177e4SLinus Torvalds fput(file); 4906cb153caSBenjamin LaHaise return sock; 4911da177e4SLinus Torvalds } 492c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup); 4931da177e4SLinus Torvalds 4946cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) 4956cb153caSBenjamin LaHaise { 49600e188efSAl Viro struct fd f = fdget(fd); 4976cb153caSBenjamin LaHaise struct socket *sock; 4986cb153caSBenjamin LaHaise 4993672558cSHua Zhong *err = -EBADF; 50000e188efSAl Viro if (f.file) { 50100e188efSAl Viro sock = sock_from_file(f.file, err); 50200e188efSAl Viro if (likely(sock)) { 50300e188efSAl Viro *fput_needed = f.flags; 5041da177e4SLinus Torvalds return sock; 50500e188efSAl Viro } 50600e188efSAl Viro fdput(f); 5076cb153caSBenjamin LaHaise } 5086cb153caSBenjamin LaHaise return NULL; 5091da177e4SLinus Torvalds } 5101da177e4SLinus Torvalds 511600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer, 512600e1779SMasatake YAMATO size_t size) 513600e1779SMasatake YAMATO { 514600e1779SMasatake YAMATO ssize_t len; 515600e1779SMasatake YAMATO ssize_t used = 0; 516600e1779SMasatake YAMATO 517c5ef6035SDavid Howells len = security_inode_listsecurity(d_inode(dentry), buffer, size); 518600e1779SMasatake YAMATO if (len < 0) 519600e1779SMasatake YAMATO return len; 520600e1779SMasatake YAMATO used += len; 521600e1779SMasatake YAMATO if (buffer) { 522600e1779SMasatake YAMATO if (size < used) 523600e1779SMasatake YAMATO return -ERANGE; 524600e1779SMasatake YAMATO buffer += len; 525600e1779SMasatake YAMATO } 526600e1779SMasatake YAMATO 527600e1779SMasatake YAMATO len = (XATTR_NAME_SOCKPROTONAME_LEN + 1); 528600e1779SMasatake YAMATO used += len; 529600e1779SMasatake YAMATO if (buffer) { 530600e1779SMasatake YAMATO if (size < used) 531600e1779SMasatake YAMATO return -ERANGE; 532600e1779SMasatake YAMATO memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len); 533600e1779SMasatake YAMATO buffer += len; 534600e1779SMasatake YAMATO } 535600e1779SMasatake YAMATO 536600e1779SMasatake YAMATO return used; 537600e1779SMasatake YAMATO } 538600e1779SMasatake YAMATO 539dc647ec8STobias Klauser static int sockfs_setattr(struct dentry *dentry, struct iattr *iattr) 54086741ec2SLorenzo Colitti { 54186741ec2SLorenzo Colitti int err = simple_setattr(dentry, iattr); 54286741ec2SLorenzo Colitti 543e1a3a60aSEric Biggers if (!err && (iattr->ia_valid & ATTR_UID)) { 54486741ec2SLorenzo Colitti struct socket *sock = SOCKET_I(d_inode(dentry)); 54586741ec2SLorenzo Colitti 5466d8c50dcSCong Wang if (sock->sk) 54786741ec2SLorenzo Colitti sock->sk->sk_uid = iattr->ia_uid; 5486d8c50dcSCong Wang else 5496d8c50dcSCong Wang err = -ENOENT; 55086741ec2SLorenzo Colitti } 55186741ec2SLorenzo Colitti 55286741ec2SLorenzo Colitti return err; 55386741ec2SLorenzo Colitti } 55486741ec2SLorenzo Colitti 555600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = { 556600e1779SMasatake YAMATO .listxattr = sockfs_listxattr, 55786741ec2SLorenzo Colitti .setattr = sockfs_setattr, 558600e1779SMasatake YAMATO }; 559600e1779SMasatake YAMATO 5601da177e4SLinus Torvalds /** 5611da177e4SLinus Torvalds * sock_alloc - allocate a socket 5621da177e4SLinus Torvalds * 5631da177e4SLinus Torvalds * Allocate a new inode and socket object. The two are bound together 5641da177e4SLinus Torvalds * and initialised. The socket is then returned. If we are out of inodes 5658a3c245cSPedro Tammela * NULL is returned. This functions uses GFP_KERNEL internally. 5661da177e4SLinus Torvalds */ 5671da177e4SLinus Torvalds 568f4a00aacSTom Herbert struct socket *sock_alloc(void) 5691da177e4SLinus Torvalds { 5701da177e4SLinus Torvalds struct inode *inode; 5711da177e4SLinus Torvalds struct socket *sock; 5721da177e4SLinus Torvalds 573a209dfc7SEric Dumazet inode = new_inode_pseudo(sock_mnt->mnt_sb); 5741da177e4SLinus Torvalds if (!inode) 5751da177e4SLinus Torvalds return NULL; 5761da177e4SLinus Torvalds 5771da177e4SLinus Torvalds sock = SOCKET_I(inode); 5781da177e4SLinus Torvalds 57985fe4025SChristoph Hellwig inode->i_ino = get_next_ino(); 5801da177e4SLinus Torvalds inode->i_mode = S_IFSOCK | S_IRWXUGO; 5818192b0c4SDavid Howells inode->i_uid = current_fsuid(); 5828192b0c4SDavid Howells inode->i_gid = current_fsgid(); 583600e1779SMasatake YAMATO inode->i_op = &sockfs_inode_ops; 5841da177e4SLinus Torvalds 5851da177e4SLinus Torvalds return sock; 5861da177e4SLinus Torvalds } 587f4a00aacSTom Herbert EXPORT_SYMBOL(sock_alloc); 5881da177e4SLinus Torvalds 5896d8c50dcSCong Wang static void __sock_release(struct socket *sock, struct inode *inode) 5901da177e4SLinus Torvalds { 5911da177e4SLinus Torvalds if (sock->ops) { 5921da177e4SLinus Torvalds struct module *owner = sock->ops->owner; 5931da177e4SLinus Torvalds 5946d8c50dcSCong Wang if (inode) 5956d8c50dcSCong Wang inode_lock(inode); 5961da177e4SLinus Torvalds sock->ops->release(sock); 597ff7b11aaSEric Biggers sock->sk = NULL; 5986d8c50dcSCong Wang if (inode) 5996d8c50dcSCong Wang inode_unlock(inode); 6001da177e4SLinus Torvalds sock->ops = NULL; 6011da177e4SLinus Torvalds module_put(owner); 6021da177e4SLinus Torvalds } 6031da177e4SLinus Torvalds 604333f7909SAl Viro if (sock->wq.fasync_list) 6053410f22eSYang Yingliang pr_err("%s: fasync list not empty!\n", __func__); 6061da177e4SLinus Torvalds 6071da177e4SLinus Torvalds if (!sock->file) { 6081da177e4SLinus Torvalds iput(SOCK_INODE(sock)); 6091da177e4SLinus Torvalds return; 6101da177e4SLinus Torvalds } 6111da177e4SLinus Torvalds sock->file = NULL; 6121da177e4SLinus Torvalds } 6136d8c50dcSCong Wang 6149a8ad9acSAndrew Lunn /** 6159a8ad9acSAndrew Lunn * sock_release - close a socket 6169a8ad9acSAndrew Lunn * @sock: socket to close 6179a8ad9acSAndrew Lunn * 6189a8ad9acSAndrew Lunn * The socket is released from the protocol stack if it has a release 6199a8ad9acSAndrew Lunn * callback, and the inode is then released if the socket is bound to 6209a8ad9acSAndrew Lunn * an inode not a file. 6219a8ad9acSAndrew Lunn */ 6226d8c50dcSCong Wang void sock_release(struct socket *sock) 6236d8c50dcSCong Wang { 6246d8c50dcSCong Wang __sock_release(sock, NULL); 6256d8c50dcSCong Wang } 626c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release); 6271da177e4SLinus Torvalds 628c14ac945SSoheil Hassas Yeganeh void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags) 62920d49473SPatrick Ohly { 630140c55d4SEric Dumazet u8 flags = *tx_flags; 631140c55d4SEric Dumazet 632c14ac945SSoheil Hassas Yeganeh if (tsflags & SOF_TIMESTAMPING_TX_HARDWARE) 633140c55d4SEric Dumazet flags |= SKBTX_HW_TSTAMP; 634140c55d4SEric Dumazet 635c14ac945SSoheil Hassas Yeganeh if (tsflags & SOF_TIMESTAMPING_TX_SOFTWARE) 636140c55d4SEric Dumazet flags |= SKBTX_SW_TSTAMP; 637140c55d4SEric Dumazet 638c14ac945SSoheil Hassas Yeganeh if (tsflags & SOF_TIMESTAMPING_TX_SCHED) 639140c55d4SEric Dumazet flags |= SKBTX_SCHED_TSTAMP; 640140c55d4SEric Dumazet 641140c55d4SEric Dumazet *tx_flags = flags; 64220d49473SPatrick Ohly } 64367cc0d40SWillem de Bruijn EXPORT_SYMBOL(__sock_tx_timestamp); 64420d49473SPatrick Ohly 6458c3c447bSPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet_sendmsg(struct socket *, struct msghdr *, 6468c3c447bSPaolo Abeni size_t)); 647a648a592SPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet6_sendmsg(struct socket *, struct msghdr *, 648a648a592SPaolo Abeni size_t)); 649d8725c86SAl Viro static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg) 6501da177e4SLinus Torvalds { 651a648a592SPaolo Abeni int ret = INDIRECT_CALL_INET(sock->ops->sendmsg, inet6_sendmsg, 652a648a592SPaolo Abeni inet_sendmsg, sock, msg, 653a648a592SPaolo Abeni msg_data_left(msg)); 654d8725c86SAl Viro BUG_ON(ret == -EIOCBQUEUED); 655d8725c86SAl Viro return ret; 6561da177e4SLinus Torvalds } 6570cf00c6fSGu Zheng 65885806af0SRandy Dunlap /** 65985806af0SRandy Dunlap * sock_sendmsg - send a message through @sock 66085806af0SRandy Dunlap * @sock: socket 66185806af0SRandy Dunlap * @msg: message to send 66285806af0SRandy Dunlap * 66385806af0SRandy Dunlap * Sends @msg through @sock, passing through LSM. 66485806af0SRandy Dunlap * Returns the number of bytes sent, or an error code. 66585806af0SRandy Dunlap */ 666d8725c86SAl Viro int sock_sendmsg(struct socket *sock, struct msghdr *msg) 6670cf00c6fSGu Zheng { 668d8725c86SAl Viro int err = security_socket_sendmsg(sock, msg, 66901e97e65SAl Viro msg_data_left(msg)); 6701b784140SYing Xue 671d8725c86SAl Viro return err ?: sock_sendmsg_nosec(sock, msg); 6720cf00c6fSGu Zheng } 673c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg); 6741da177e4SLinus Torvalds 6758a3c245cSPedro Tammela /** 6768a3c245cSPedro Tammela * kernel_sendmsg - send a message through @sock (kernel-space) 6778a3c245cSPedro Tammela * @sock: socket 6788a3c245cSPedro Tammela * @msg: message header 6798a3c245cSPedro Tammela * @vec: kernel vec 6808a3c245cSPedro Tammela * @num: vec array length 6818a3c245cSPedro Tammela * @size: total message data size 6828a3c245cSPedro Tammela * 6838a3c245cSPedro Tammela * Builds the message data with @vec and sends it through @sock. 6848a3c245cSPedro Tammela * Returns the number of bytes sent, or an error code. 6858a3c245cSPedro Tammela */ 6868a3c245cSPedro Tammela 6871da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg, 6881da177e4SLinus Torvalds struct kvec *vec, size_t num, size_t size) 6891da177e4SLinus Torvalds { 690aa563d7bSDavid Howells iov_iter_kvec(&msg->msg_iter, WRITE, vec, num, size); 691d8725c86SAl Viro return sock_sendmsg(sock, msg); 6921da177e4SLinus Torvalds } 693c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg); 6941da177e4SLinus Torvalds 6958a3c245cSPedro Tammela /** 6968a3c245cSPedro Tammela * kernel_sendmsg_locked - send a message through @sock (kernel-space) 6978a3c245cSPedro Tammela * @sk: sock 6988a3c245cSPedro Tammela * @msg: message header 6998a3c245cSPedro Tammela * @vec: output s/g array 7008a3c245cSPedro Tammela * @num: output s/g array length 7018a3c245cSPedro Tammela * @size: total message data size 7028a3c245cSPedro Tammela * 7038a3c245cSPedro Tammela * Builds the message data with @vec and sends it through @sock. 7048a3c245cSPedro Tammela * Returns the number of bytes sent, or an error code. 7058a3c245cSPedro Tammela * Caller must hold @sk. 7068a3c245cSPedro Tammela */ 7078a3c245cSPedro Tammela 708306b13ebSTom Herbert int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg, 709306b13ebSTom Herbert struct kvec *vec, size_t num, size_t size) 710306b13ebSTom Herbert { 711306b13ebSTom Herbert struct socket *sock = sk->sk_socket; 712306b13ebSTom Herbert 713306b13ebSTom Herbert if (!sock->ops->sendmsg_locked) 714db5980d8SJohn Fastabend return sock_no_sendmsg_locked(sk, msg, size); 715306b13ebSTom Herbert 716aa563d7bSDavid Howells iov_iter_kvec(&msg->msg_iter, WRITE, vec, num, size); 717306b13ebSTom Herbert 718306b13ebSTom Herbert return sock->ops->sendmsg_locked(sk, msg, msg_data_left(msg)); 719306b13ebSTom Herbert } 720306b13ebSTom Herbert EXPORT_SYMBOL(kernel_sendmsg_locked); 721306b13ebSTom Herbert 7228605330aSSoheil Hassas Yeganeh static bool skb_is_err_queue(const struct sk_buff *skb) 7238605330aSSoheil Hassas Yeganeh { 7248605330aSSoheil Hassas Yeganeh /* pkt_type of skbs enqueued on the error queue are set to 7258605330aSSoheil Hassas Yeganeh * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do 7268605330aSSoheil Hassas Yeganeh * in recvmsg, since skbs received on a local socket will never 7278605330aSSoheil Hassas Yeganeh * have a pkt_type of PACKET_OUTGOING. 7288605330aSSoheil Hassas Yeganeh */ 7298605330aSSoheil Hassas Yeganeh return skb->pkt_type == PACKET_OUTGOING; 7308605330aSSoheil Hassas Yeganeh } 7318605330aSSoheil Hassas Yeganeh 732b50a5c70SMiroslav Lichvar /* On transmit, software and hardware timestamps are returned independently. 733b50a5c70SMiroslav Lichvar * As the two skb clones share the hardware timestamp, which may be updated 734b50a5c70SMiroslav Lichvar * before the software timestamp is received, a hardware TX timestamp may be 735b50a5c70SMiroslav Lichvar * returned only if there is no software TX timestamp. Ignore false software 736b50a5c70SMiroslav Lichvar * timestamps, which may be made in the __sock_recv_timestamp() call when the 7377f1bc6e9SDeepa Dinamani * option SO_TIMESTAMP_OLD(NS) is enabled on the socket, even when the skb has a 738b50a5c70SMiroslav Lichvar * hardware timestamp. 739b50a5c70SMiroslav Lichvar */ 740b50a5c70SMiroslav Lichvar static bool skb_is_swtx_tstamp(const struct sk_buff *skb, int false_tstamp) 741b50a5c70SMiroslav Lichvar { 742b50a5c70SMiroslav Lichvar return skb->tstamp && !false_tstamp && skb_is_err_queue(skb); 743b50a5c70SMiroslav Lichvar } 744b50a5c70SMiroslav Lichvar 745aad9c8c4SMiroslav Lichvar static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb) 746aad9c8c4SMiroslav Lichvar { 747aad9c8c4SMiroslav Lichvar struct scm_ts_pktinfo ts_pktinfo; 748aad9c8c4SMiroslav Lichvar struct net_device *orig_dev; 749aad9c8c4SMiroslav Lichvar 750aad9c8c4SMiroslav Lichvar if (!skb_mac_header_was_set(skb)) 751aad9c8c4SMiroslav Lichvar return; 752aad9c8c4SMiroslav Lichvar 753aad9c8c4SMiroslav Lichvar memset(&ts_pktinfo, 0, sizeof(ts_pktinfo)); 754aad9c8c4SMiroslav Lichvar 755aad9c8c4SMiroslav Lichvar rcu_read_lock(); 756aad9c8c4SMiroslav Lichvar orig_dev = dev_get_by_napi_id(skb_napi_id(skb)); 757aad9c8c4SMiroslav Lichvar if (orig_dev) 758aad9c8c4SMiroslav Lichvar ts_pktinfo.if_index = orig_dev->ifindex; 759aad9c8c4SMiroslav Lichvar rcu_read_unlock(); 760aad9c8c4SMiroslav Lichvar 761aad9c8c4SMiroslav Lichvar ts_pktinfo.pkt_length = skb->len - skb_mac_offset(skb); 762aad9c8c4SMiroslav Lichvar put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO, 763aad9c8c4SMiroslav Lichvar sizeof(ts_pktinfo), &ts_pktinfo); 764aad9c8c4SMiroslav Lichvar } 765aad9c8c4SMiroslav Lichvar 76692f37fd2SEric Dumazet /* 76792f37fd2SEric Dumazet * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) 76892f37fd2SEric Dumazet */ 76992f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, 77092f37fd2SEric Dumazet struct sk_buff *skb) 77192f37fd2SEric Dumazet { 77220d49473SPatrick Ohly int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); 773887feae3SDeepa Dinamani int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW); 7749718475eSDeepa Dinamani struct scm_timestamping_internal tss; 7759718475eSDeepa Dinamani 776b50a5c70SMiroslav Lichvar int empty = 1, false_tstamp = 0; 77720d49473SPatrick Ohly struct skb_shared_hwtstamps *shhwtstamps = 77820d49473SPatrick Ohly skb_hwtstamps(skb); 77992f37fd2SEric Dumazet 78020d49473SPatrick Ohly /* Race occurred between timestamp enabling and packet 78120d49473SPatrick Ohly receiving. Fill in the current time for now. */ 782b50a5c70SMiroslav Lichvar if (need_software_tstamp && skb->tstamp == 0) { 78320d49473SPatrick Ohly __net_timestamp(skb); 784b50a5c70SMiroslav Lichvar false_tstamp = 1; 785b50a5c70SMiroslav Lichvar } 78620d49473SPatrick Ohly 78720d49473SPatrick Ohly if (need_software_tstamp) { 78892f37fd2SEric Dumazet if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { 789887feae3SDeepa Dinamani if (new_tstamp) { 790887feae3SDeepa Dinamani struct __kernel_sock_timeval tv; 791887feae3SDeepa Dinamani 792887feae3SDeepa Dinamani skb_get_new_timestamp(skb, &tv); 793887feae3SDeepa Dinamani put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_NEW, 794887feae3SDeepa Dinamani sizeof(tv), &tv); 795887feae3SDeepa Dinamani } else { 79613c6ee2aSDeepa Dinamani struct __kernel_old_timeval tv; 797887feae3SDeepa Dinamani 79820d49473SPatrick Ohly skb_get_timestamp(skb, &tv); 7997f1bc6e9SDeepa Dinamani put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD, 80020d49473SPatrick Ohly sizeof(tv), &tv); 801887feae3SDeepa Dinamani } 802887feae3SDeepa Dinamani } else { 803887feae3SDeepa Dinamani if (new_tstamp) { 804887feae3SDeepa Dinamani struct __kernel_timespec ts; 805887feae3SDeepa Dinamani 806887feae3SDeepa Dinamani skb_get_new_timestampns(skb, &ts); 807887feae3SDeepa Dinamani put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW, 808887feae3SDeepa Dinamani sizeof(ts), &ts); 80992f37fd2SEric Dumazet } else { 810df1b4ba9SArnd Bergmann struct __kernel_old_timespec ts; 811887feae3SDeepa Dinamani 812f24b9be5SWillem de Bruijn skb_get_timestampns(skb, &ts); 8137f1bc6e9SDeepa Dinamani put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD, 814f24b9be5SWillem de Bruijn sizeof(ts), &ts); 81592f37fd2SEric Dumazet } 81692f37fd2SEric Dumazet } 817887feae3SDeepa Dinamani } 81892f37fd2SEric Dumazet 819f24b9be5SWillem de Bruijn memset(&tss, 0, sizeof(tss)); 820c199105dSWillem de Bruijn if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) && 8219718475eSDeepa Dinamani ktime_to_timespec64_cond(skb->tstamp, tss.ts + 0)) 82220d49473SPatrick Ohly empty = 0; 8234d276eb6SWillem de Bruijn if (shhwtstamps && 824b9f40e21SWillem de Bruijn (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && 825b50a5c70SMiroslav Lichvar !skb_is_swtx_tstamp(skb, false_tstamp) && 8269718475eSDeepa Dinamani ktime_to_timespec64_cond(shhwtstamps->hwtstamp, tss.ts + 2)) { 82720d49473SPatrick Ohly empty = 0; 828aad9c8c4SMiroslav Lichvar if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) && 829aad9c8c4SMiroslav Lichvar !skb_is_err_queue(skb)) 830aad9c8c4SMiroslav Lichvar put_ts_pktinfo(msg, skb); 831aad9c8c4SMiroslav Lichvar } 8321c885808SFrancis Yan if (!empty) { 8339718475eSDeepa Dinamani if (sock_flag(sk, SOCK_TSTAMP_NEW)) 8349718475eSDeepa Dinamani put_cmsg_scm_timestamping64(msg, &tss); 8359718475eSDeepa Dinamani else 8369718475eSDeepa Dinamani put_cmsg_scm_timestamping(msg, &tss); 8371c885808SFrancis Yan 8388605330aSSoheil Hassas Yeganeh if (skb_is_err_queue(skb) && skb->len && 8394ef1b286SSoheil Hassas Yeganeh SKB_EXT_ERR(skb)->opt_stats) 8401c885808SFrancis Yan put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS, 8411c885808SFrancis Yan skb->len, skb->data); 8421c885808SFrancis Yan } 84320d49473SPatrick Ohly } 8447c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp); 8457c81fd8bSArnaldo Carvalho de Melo 8466e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk, 8476e3e939fSJohannes Berg struct sk_buff *skb) 8486e3e939fSJohannes Berg { 8496e3e939fSJohannes Berg int ack; 8506e3e939fSJohannes Berg 8516e3e939fSJohannes Berg if (!sock_flag(sk, SOCK_WIFI_STATUS)) 8526e3e939fSJohannes Berg return; 8536e3e939fSJohannes Berg if (!skb->wifi_acked_valid) 8546e3e939fSJohannes Berg return; 8556e3e939fSJohannes Berg 8566e3e939fSJohannes Berg ack = skb->wifi_acked; 8576e3e939fSJohannes Berg 8586e3e939fSJohannes Berg put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack); 8596e3e939fSJohannes Berg } 8606e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status); 8616e3e939fSJohannes Berg 86211165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, 86311165f14Sstephen hemminger struct sk_buff *skb) 8643b885787SNeil Horman { 865744d5a3eSEyal Birger if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && SOCK_SKB_CB(skb)->dropcount) 8663b885787SNeil Horman put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL, 867744d5a3eSEyal Birger sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount); 8683b885787SNeil Horman } 8693b885787SNeil Horman 870767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, 8713b885787SNeil Horman struct sk_buff *skb) 8723b885787SNeil Horman { 8733b885787SNeil Horman sock_recv_timestamp(msg, sk, skb); 8743b885787SNeil Horman sock_recv_drops(msg, sk, skb); 8753b885787SNeil Horman } 876767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops); 8773b885787SNeil Horman 8788c3c447bSPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet_recvmsg(struct socket *, struct msghdr *, 8798c3c447bSPaolo Abeni size_t, int)); 880a648a592SPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet6_recvmsg(struct socket *, struct msghdr *, 881a648a592SPaolo Abeni size_t, int)); 8821b784140SYing Xue static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg, 8831b784140SYing Xue int flags) 884a2e27255SArnaldo Carvalho de Melo { 885a648a592SPaolo Abeni return INDIRECT_CALL_INET(sock->ops->recvmsg, inet6_recvmsg, 886a648a592SPaolo Abeni inet_recvmsg, sock, msg, msg_data_left(msg), 887a648a592SPaolo Abeni flags); 8882da62906SAl Viro } 889a2e27255SArnaldo Carvalho de Melo 89085806af0SRandy Dunlap /** 89185806af0SRandy Dunlap * sock_recvmsg - receive a message from @sock 89285806af0SRandy Dunlap * @sock: socket 89385806af0SRandy Dunlap * @msg: message to receive 89485806af0SRandy Dunlap * @flags: message flags 89585806af0SRandy Dunlap * 89685806af0SRandy Dunlap * Receives @msg from @sock, passing through LSM. Returns the total number 89785806af0SRandy Dunlap * of bytes received, or an error. 89885806af0SRandy Dunlap */ 8992da62906SAl Viro int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags) 9002da62906SAl Viro { 9012da62906SAl Viro int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags); 9022da62906SAl Viro 9032da62906SAl Viro return err ?: sock_recvmsg_nosec(sock, msg, flags); 9041da177e4SLinus Torvalds } 905c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg); 9061da177e4SLinus Torvalds 907c1249c0aSMartin Lucina /** 908c1249c0aSMartin Lucina * kernel_recvmsg - Receive a message from a socket (kernel space) 909c1249c0aSMartin Lucina * @sock: The socket to receive the message from 910c1249c0aSMartin Lucina * @msg: Received message 911c1249c0aSMartin Lucina * @vec: Input s/g array for message data 912c1249c0aSMartin Lucina * @num: Size of input s/g array 913c1249c0aSMartin Lucina * @size: Number of bytes to read 914c1249c0aSMartin Lucina * @flags: Message flags (MSG_DONTWAIT, etc...) 915c1249c0aSMartin Lucina * 916c1249c0aSMartin Lucina * On return the msg structure contains the scatter/gather array passed in the 917c1249c0aSMartin Lucina * vec argument. The array is modified so that it consists of the unfilled 918c1249c0aSMartin Lucina * portion of the original array. 919c1249c0aSMartin Lucina * 920c1249c0aSMartin Lucina * The returned value is the total number of bytes received, or an error. 921c1249c0aSMartin Lucina */ 9228a3c245cSPedro Tammela 9231da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg, 92489bddce5SStephen Hemminger struct kvec *vec, size_t num, size_t size, int flags) 9251da177e4SLinus Torvalds { 9261f466e1fSChristoph Hellwig msg->msg_control_is_user = false; 927aa563d7bSDavid Howells iov_iter_kvec(&msg->msg_iter, READ, vec, num, size); 9281f466e1fSChristoph Hellwig return sock_recvmsg(sock, msg, flags); 9291da177e4SLinus Torvalds } 930c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg); 9311da177e4SLinus Torvalds 93220380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page, 9331da177e4SLinus Torvalds int offset, size_t size, loff_t *ppos, int more) 9341da177e4SLinus Torvalds { 9351da177e4SLinus Torvalds struct socket *sock; 9361da177e4SLinus Torvalds int flags; 9371da177e4SLinus Torvalds 938b69aee04SEric Dumazet sock = file->private_data; 9391da177e4SLinus Torvalds 94035f9c09fSEric Dumazet flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; 94135f9c09fSEric Dumazet /* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */ 94235f9c09fSEric Dumazet flags |= more; 9431da177e4SLinus Torvalds 944e6949583SLinus Torvalds return kernel_sendpage(sock, page, offset, size, flags); 9451da177e4SLinus Torvalds } 9461da177e4SLinus Torvalds 9479c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos, 9489c55e01cSJens Axboe struct pipe_inode_info *pipe, size_t len, 9499c55e01cSJens Axboe unsigned int flags) 9509c55e01cSJens Axboe { 9519c55e01cSJens Axboe struct socket *sock = file->private_data; 9529c55e01cSJens Axboe 953997b37daSRémi Denis-Courmont if (unlikely(!sock->ops->splice_read)) 95495506588SSlavomir Kaslev return generic_file_splice_read(file, ppos, pipe, len, flags); 955997b37daSRémi Denis-Courmont 9569c55e01cSJens Axboe return sock->ops->splice_read(sock, ppos, pipe, len, flags); 9579c55e01cSJens Axboe } 9589c55e01cSJens Axboe 9598ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to) 960ce1d4d3eSChristoph Hellwig { 9616d652330SAl Viro struct file *file = iocb->ki_filp; 9626d652330SAl Viro struct socket *sock = file->private_data; 9630345f931Stadeusz.struk@intel.com struct msghdr msg = {.msg_iter = *to, 9640345f931Stadeusz.struk@intel.com .msg_iocb = iocb}; 9658ae5e030SAl Viro ssize_t res; 966ce1d4d3eSChristoph Hellwig 967ebfcd895SJens Axboe if (file->f_flags & O_NONBLOCK || (iocb->ki_flags & IOCB_NOWAIT)) 9688ae5e030SAl Viro msg.msg_flags = MSG_DONTWAIT; 9698ae5e030SAl Viro 9708ae5e030SAl Viro if (iocb->ki_pos != 0) 971ce1d4d3eSChristoph Hellwig return -ESPIPE; 972027445c3SBadari Pulavarty 97366ee59afSChristoph Hellwig if (!iov_iter_count(to)) /* Match SYS5 behaviour */ 974ce1d4d3eSChristoph Hellwig return 0; 975ce1d4d3eSChristoph Hellwig 9762da62906SAl Viro res = sock_recvmsg(sock, &msg, msg.msg_flags); 9778ae5e030SAl Viro *to = msg.msg_iter; 9788ae5e030SAl Viro return res; 979ce1d4d3eSChristoph Hellwig } 980ce1d4d3eSChristoph Hellwig 9818ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from) 9821da177e4SLinus Torvalds { 9836d652330SAl Viro struct file *file = iocb->ki_filp; 9846d652330SAl Viro struct socket *sock = file->private_data; 9850345f931Stadeusz.struk@intel.com struct msghdr msg = {.msg_iter = *from, 9860345f931Stadeusz.struk@intel.com .msg_iocb = iocb}; 9878ae5e030SAl Viro ssize_t res; 9881da177e4SLinus Torvalds 9898ae5e030SAl Viro if (iocb->ki_pos != 0) 990ce1d4d3eSChristoph Hellwig return -ESPIPE; 991027445c3SBadari Pulavarty 992ebfcd895SJens Axboe if (file->f_flags & O_NONBLOCK || (iocb->ki_flags & IOCB_NOWAIT)) 9938ae5e030SAl Viro msg.msg_flags = MSG_DONTWAIT; 9948ae5e030SAl Viro 9956d652330SAl Viro if (sock->type == SOCK_SEQPACKET) 9966d652330SAl Viro msg.msg_flags |= MSG_EOR; 9976d652330SAl Viro 998d8725c86SAl Viro res = sock_sendmsg(sock, &msg); 9998ae5e030SAl Viro *from = msg.msg_iter; 10008ae5e030SAl Viro return res; 10011da177e4SLinus Torvalds } 10021da177e4SLinus Torvalds 10031da177e4SLinus Torvalds /* 10041da177e4SLinus Torvalds * Atomic setting of ioctl hooks to avoid race 10051da177e4SLinus Torvalds * with module unload. 10061da177e4SLinus Torvalds */ 10071da177e4SLinus Torvalds 10084a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex); 1009c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg); 10101da177e4SLinus Torvalds 1011881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *)) 10121da177e4SLinus Torvalds { 10134a3e2f71SArjan van de Ven mutex_lock(&br_ioctl_mutex); 10141da177e4SLinus Torvalds br_ioctl_hook = hook; 10154a3e2f71SArjan van de Ven mutex_unlock(&br_ioctl_mutex); 10161da177e4SLinus Torvalds } 10171da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set); 10181da177e4SLinus Torvalds 10194a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex); 1020881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg); 10211da177e4SLinus Torvalds 1022881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *)) 10231da177e4SLinus Torvalds { 10244a3e2f71SArjan van de Ven mutex_lock(&vlan_ioctl_mutex); 10251da177e4SLinus Torvalds vlan_ioctl_hook = hook; 10264a3e2f71SArjan van de Ven mutex_unlock(&vlan_ioctl_mutex); 10271da177e4SLinus Torvalds } 10281da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set); 10291da177e4SLinus Torvalds 10304a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex); 10311da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *); 10321da177e4SLinus Torvalds 10331da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *)) 10341da177e4SLinus Torvalds { 10354a3e2f71SArjan van de Ven mutex_lock(&dlci_ioctl_mutex); 10361da177e4SLinus Torvalds dlci_ioctl_hook = hook; 10374a3e2f71SArjan van de Ven mutex_unlock(&dlci_ioctl_mutex); 10381da177e4SLinus Torvalds } 10391da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set); 10401da177e4SLinus Torvalds 10416b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock, 104263ff03abSJohannes Berg unsigned int cmd, unsigned long arg) 10436b96018bSArnd Bergmann { 10446b96018bSArnd Bergmann int err; 10456b96018bSArnd Bergmann void __user *argp = (void __user *)arg; 10466b96018bSArnd Bergmann 10476b96018bSArnd Bergmann err = sock->ops->ioctl(sock, cmd, arg); 10486b96018bSArnd Bergmann 10496b96018bSArnd Bergmann /* 10506b96018bSArnd Bergmann * If this ioctl is unknown try to hand it down 10516b96018bSArnd Bergmann * to the NIC driver. 10526b96018bSArnd Bergmann */ 105336fd633eSAl Viro if (err != -ENOIOCTLCMD) 10546b96018bSArnd Bergmann return err; 10556b96018bSArnd Bergmann 105636fd633eSAl Viro if (cmd == SIOCGIFCONF) { 105736fd633eSAl Viro struct ifconf ifc; 105836fd633eSAl Viro if (copy_from_user(&ifc, argp, sizeof(struct ifconf))) 105936fd633eSAl Viro return -EFAULT; 106036fd633eSAl Viro rtnl_lock(); 106136fd633eSAl Viro err = dev_ifconf(net, &ifc, sizeof(struct ifreq)); 106236fd633eSAl Viro rtnl_unlock(); 106336fd633eSAl Viro if (!err && copy_to_user(argp, &ifc, sizeof(struct ifconf))) 106436fd633eSAl Viro err = -EFAULT; 106544c02a2cSAl Viro } else { 106644c02a2cSAl Viro struct ifreq ifr; 106744c02a2cSAl Viro bool need_copyout; 106863ff03abSJohannes Berg if (copy_from_user(&ifr, argp, sizeof(struct ifreq))) 106944c02a2cSAl Viro return -EFAULT; 107044c02a2cSAl Viro err = dev_ioctl(net, cmd, &ifr, &need_copyout); 107144c02a2cSAl Viro if (!err && need_copyout) 107263ff03abSJohannes Berg if (copy_to_user(argp, &ifr, sizeof(struct ifreq))) 107344c02a2cSAl Viro return -EFAULT; 107436fd633eSAl Viro } 10756b96018bSArnd Bergmann return err; 10766b96018bSArnd Bergmann } 10776b96018bSArnd Bergmann 10781da177e4SLinus Torvalds /* 10791da177e4SLinus Torvalds * With an ioctl, arg may well be a user mode pointer, but we don't know 10801da177e4SLinus Torvalds * what to do with it - that's up to the protocol still. 10811da177e4SLinus Torvalds */ 10821da177e4SLinus Torvalds 10838a3c245cSPedro Tammela /** 10848a3c245cSPedro Tammela * get_net_ns - increment the refcount of the network namespace 10858a3c245cSPedro Tammela * @ns: common namespace (net) 10868a3c245cSPedro Tammela * 10878a3c245cSPedro Tammela * Returns the net's common namespace. 10888a3c245cSPedro Tammela */ 10898a3c245cSPedro Tammela 1090d8d211a2SKirill Tkhai struct ns_common *get_net_ns(struct ns_common *ns) 1091c62cce2cSAndrey Vagin { 1092c62cce2cSAndrey Vagin return &get_net(container_of(ns, struct net, ns))->ns; 1093c62cce2cSAndrey Vagin } 1094d8d211a2SKirill Tkhai EXPORT_SYMBOL_GPL(get_net_ns); 1095c62cce2cSAndrey Vagin 10961da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) 10971da177e4SLinus Torvalds { 10981da177e4SLinus Torvalds struct socket *sock; 1099881d966bSEric W. Biederman struct sock *sk; 11001da177e4SLinus Torvalds void __user *argp = (void __user *)arg; 11011da177e4SLinus Torvalds int pid, err; 1102881d966bSEric W. Biederman struct net *net; 11031da177e4SLinus Torvalds 1104b69aee04SEric Dumazet sock = file->private_data; 1105881d966bSEric W. Biederman sk = sock->sk; 11063b1e0a65SYOSHIFUJI Hideaki net = sock_net(sk); 110744c02a2cSAl Viro if (unlikely(cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))) { 110844c02a2cSAl Viro struct ifreq ifr; 110944c02a2cSAl Viro bool need_copyout; 111044c02a2cSAl Viro if (copy_from_user(&ifr, argp, sizeof(struct ifreq))) 111144c02a2cSAl Viro return -EFAULT; 111244c02a2cSAl Viro err = dev_ioctl(net, cmd, &ifr, &need_copyout); 111344c02a2cSAl Viro if (!err && need_copyout) 111444c02a2cSAl Viro if (copy_to_user(argp, &ifr, sizeof(struct ifreq))) 111544c02a2cSAl Viro return -EFAULT; 11161da177e4SLinus Torvalds } else 11173d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE 11181da177e4SLinus Torvalds if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { 1119b1b0c245SAl Viro err = wext_handle_ioctl(net, cmd, argp); 11201da177e4SLinus Torvalds } else 11213d23e349SJohannes Berg #endif 11221da177e4SLinus Torvalds switch (cmd) { 11231da177e4SLinus Torvalds case FIOSETOWN: 11241da177e4SLinus Torvalds case SIOCSPGRP: 11251da177e4SLinus Torvalds err = -EFAULT; 11261da177e4SLinus Torvalds if (get_user(pid, (int __user *)argp)) 11271da177e4SLinus Torvalds break; 1128393cc3f5SJiri Slaby err = f_setown(sock->file, pid, 1); 11291da177e4SLinus Torvalds break; 11301da177e4SLinus Torvalds case FIOGETOWN: 11311da177e4SLinus Torvalds case SIOCGPGRP: 1132609d7fa9SEric W. Biederman err = put_user(f_getown(sock->file), 113389bddce5SStephen Hemminger (int __user *)argp); 11341da177e4SLinus Torvalds break; 11351da177e4SLinus Torvalds case SIOCGIFBR: 11361da177e4SLinus Torvalds case SIOCSIFBR: 11371da177e4SLinus Torvalds case SIOCBRADDBR: 11381da177e4SLinus Torvalds case SIOCBRDELBR: 11391da177e4SLinus Torvalds err = -ENOPKG; 11401da177e4SLinus Torvalds if (!br_ioctl_hook) 11411da177e4SLinus Torvalds request_module("bridge"); 11421da177e4SLinus Torvalds 11434a3e2f71SArjan van de Ven mutex_lock(&br_ioctl_mutex); 11441da177e4SLinus Torvalds if (br_ioctl_hook) 1145881d966bSEric W. Biederman err = br_ioctl_hook(net, cmd, argp); 11464a3e2f71SArjan van de Ven mutex_unlock(&br_ioctl_mutex); 11471da177e4SLinus Torvalds break; 11481da177e4SLinus Torvalds case SIOCGIFVLAN: 11491da177e4SLinus Torvalds case SIOCSIFVLAN: 11501da177e4SLinus Torvalds err = -ENOPKG; 11511da177e4SLinus Torvalds if (!vlan_ioctl_hook) 11521da177e4SLinus Torvalds request_module("8021q"); 11531da177e4SLinus Torvalds 11544a3e2f71SArjan van de Ven mutex_lock(&vlan_ioctl_mutex); 11551da177e4SLinus Torvalds if (vlan_ioctl_hook) 1156881d966bSEric W. Biederman err = vlan_ioctl_hook(net, argp); 11574a3e2f71SArjan van de Ven mutex_unlock(&vlan_ioctl_mutex); 11581da177e4SLinus Torvalds break; 11591da177e4SLinus Torvalds case SIOCADDDLCI: 11601da177e4SLinus Torvalds case SIOCDELDLCI: 11611da177e4SLinus Torvalds err = -ENOPKG; 11621da177e4SLinus Torvalds if (!dlci_ioctl_hook) 11631da177e4SLinus Torvalds request_module("dlci"); 11641da177e4SLinus Torvalds 11654a3e2f71SArjan van de Ven mutex_lock(&dlci_ioctl_mutex); 11667512cbf6SPavel Emelyanov if (dlci_ioctl_hook) 11671da177e4SLinus Torvalds err = dlci_ioctl_hook(cmd, argp); 11684a3e2f71SArjan van de Ven mutex_unlock(&dlci_ioctl_mutex); 11691da177e4SLinus Torvalds break; 1170c62cce2cSAndrey Vagin case SIOCGSKNS: 1171c62cce2cSAndrey Vagin err = -EPERM; 1172c62cce2cSAndrey Vagin if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) 1173c62cce2cSAndrey Vagin break; 1174c62cce2cSAndrey Vagin 1175c62cce2cSAndrey Vagin err = open_related_ns(&net->ns, get_net_ns); 1176c62cce2cSAndrey Vagin break; 11770768e170SArnd Bergmann case SIOCGSTAMP_OLD: 11780768e170SArnd Bergmann case SIOCGSTAMPNS_OLD: 1179c7cbdbf2SArnd Bergmann if (!sock->ops->gettstamp) { 1180c7cbdbf2SArnd Bergmann err = -ENOIOCTLCMD; 1181c7cbdbf2SArnd Bergmann break; 1182c7cbdbf2SArnd Bergmann } 1183c7cbdbf2SArnd Bergmann err = sock->ops->gettstamp(sock, argp, 11840768e170SArnd Bergmann cmd == SIOCGSTAMP_OLD, 11850768e170SArnd Bergmann !IS_ENABLED(CONFIG_64BIT)); 118660747828SGustavo A. R. Silva break; 11870768e170SArnd Bergmann case SIOCGSTAMP_NEW: 11880768e170SArnd Bergmann case SIOCGSTAMPNS_NEW: 11890768e170SArnd Bergmann if (!sock->ops->gettstamp) { 11900768e170SArnd Bergmann err = -ENOIOCTLCMD; 11910768e170SArnd Bergmann break; 11920768e170SArnd Bergmann } 11930768e170SArnd Bergmann err = sock->ops->gettstamp(sock, argp, 11940768e170SArnd Bergmann cmd == SIOCGSTAMP_NEW, 11950768e170SArnd Bergmann false); 1196c7cbdbf2SArnd Bergmann break; 11971da177e4SLinus Torvalds default: 119863ff03abSJohannes Berg err = sock_do_ioctl(net, sock, cmd, arg); 11991da177e4SLinus Torvalds break; 12001da177e4SLinus Torvalds } 12011da177e4SLinus Torvalds return err; 12021da177e4SLinus Torvalds } 12031da177e4SLinus Torvalds 12048a3c245cSPedro Tammela /** 12058a3c245cSPedro Tammela * sock_create_lite - creates a socket 12068a3c245cSPedro Tammela * @family: protocol family (AF_INET, ...) 12078a3c245cSPedro Tammela * @type: communication type (SOCK_STREAM, ...) 12088a3c245cSPedro Tammela * @protocol: protocol (0, ...) 12098a3c245cSPedro Tammela * @res: new socket 12108a3c245cSPedro Tammela * 12118a3c245cSPedro Tammela * Creates a new socket and assigns it to @res, passing through LSM. 12128a3c245cSPedro Tammela * The new socket initialization is not complete, see kernel_accept(). 12138a3c245cSPedro Tammela * Returns 0 or an error. On failure @res is set to %NULL. 12148a3c245cSPedro Tammela * This function internally uses GFP_KERNEL. 12158a3c245cSPedro Tammela */ 12168a3c245cSPedro Tammela 12171da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res) 12181da177e4SLinus Torvalds { 12191da177e4SLinus Torvalds int err; 12201da177e4SLinus Torvalds struct socket *sock = NULL; 12211da177e4SLinus Torvalds 12221da177e4SLinus Torvalds err = security_socket_create(family, type, protocol, 1); 12231da177e4SLinus Torvalds if (err) 12241da177e4SLinus Torvalds goto out; 12251da177e4SLinus Torvalds 12261da177e4SLinus Torvalds sock = sock_alloc(); 12271da177e4SLinus Torvalds if (!sock) { 12281da177e4SLinus Torvalds err = -ENOMEM; 12291da177e4SLinus Torvalds goto out; 12301da177e4SLinus Torvalds } 12311da177e4SLinus Torvalds 12321da177e4SLinus Torvalds sock->type = type; 12337420ed23SVenkat Yekkirala err = security_socket_post_create(sock, family, type, protocol, 1); 12347420ed23SVenkat Yekkirala if (err) 12357420ed23SVenkat Yekkirala goto out_release; 12367420ed23SVenkat Yekkirala 12371da177e4SLinus Torvalds out: 12381da177e4SLinus Torvalds *res = sock; 12391da177e4SLinus Torvalds return err; 12407420ed23SVenkat Yekkirala out_release: 12417420ed23SVenkat Yekkirala sock_release(sock); 12427420ed23SVenkat Yekkirala sock = NULL; 12437420ed23SVenkat Yekkirala goto out; 12441da177e4SLinus Torvalds } 1245c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite); 12461da177e4SLinus Torvalds 12471da177e4SLinus Torvalds /* No kernel lock held - perfect */ 1248ade994f4SAl Viro static __poll_t sock_poll(struct file *file, poll_table *wait) 12491da177e4SLinus Torvalds { 12503cafb376SChristoph Hellwig struct socket *sock = file->private_data; 1251a331de3bSChristoph Hellwig __poll_t events = poll_requested_events(wait), flag = 0; 12521da177e4SLinus Torvalds 1253e88958e6SChristoph Hellwig if (!sock->ops->poll) 1254e88958e6SChristoph Hellwig return 0; 1255f641f13bSChristoph Hellwig 1256a331de3bSChristoph Hellwig if (sk_can_busy_loop(sock->sk)) { 1257f641f13bSChristoph Hellwig /* poll once if requested by the syscall */ 1258a331de3bSChristoph Hellwig if (events & POLL_BUSY_LOOP) 1259f641f13bSChristoph Hellwig sk_busy_loop(sock->sk, 1); 1260a331de3bSChristoph Hellwig 1261a331de3bSChristoph Hellwig /* if this socket can poll_ll, tell the system call */ 1262a331de3bSChristoph Hellwig flag = POLL_BUSY_LOOP; 1263a331de3bSChristoph Hellwig } 1264a331de3bSChristoph Hellwig 1265a331de3bSChristoph Hellwig return sock->ops->poll(file, sock, wait) | flag; 12661da177e4SLinus Torvalds } 12671da177e4SLinus Torvalds 12681da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma) 12691da177e4SLinus Torvalds { 1270b69aee04SEric Dumazet struct socket *sock = file->private_data; 12711da177e4SLinus Torvalds 12721da177e4SLinus Torvalds return sock->ops->mmap(file, sock, vma); 12731da177e4SLinus Torvalds } 12741da177e4SLinus Torvalds 127520380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp) 12761da177e4SLinus Torvalds { 12776d8c50dcSCong Wang __sock_release(SOCKET_I(inode), inode); 12781da177e4SLinus Torvalds return 0; 12791da177e4SLinus Torvalds } 12801da177e4SLinus Torvalds 12811da177e4SLinus Torvalds /* 12821da177e4SLinus Torvalds * Update the socket async list 12831da177e4SLinus Torvalds * 12841da177e4SLinus Torvalds * Fasync_list locking strategy. 12851da177e4SLinus Torvalds * 12861da177e4SLinus Torvalds * 1. fasync_list is modified only under process context socket lock 12871da177e4SLinus Torvalds * i.e. under semaphore. 12881da177e4SLinus Torvalds * 2. fasync_list is used under read_lock(&sk->sk_callback_lock) 1289989a2979SEric Dumazet * or under socket lock 12901da177e4SLinus Torvalds */ 12911da177e4SLinus Torvalds 12921da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on) 12931da177e4SLinus Torvalds { 1294989a2979SEric Dumazet struct socket *sock = filp->private_data; 1295989a2979SEric Dumazet struct sock *sk = sock->sk; 1296333f7909SAl Viro struct socket_wq *wq = &sock->wq; 12971da177e4SLinus Torvalds 1298989a2979SEric Dumazet if (sk == NULL) 12991da177e4SLinus Torvalds return -EINVAL; 13001da177e4SLinus Torvalds 13011da177e4SLinus Torvalds lock_sock(sk); 1302eaefd110SEric Dumazet fasync_helper(fd, filp, on, &wq->fasync_list); 13031da177e4SLinus Torvalds 1304eaefd110SEric Dumazet if (!wq->fasync_list) 1305bcdce719SEric Dumazet sock_reset_flag(sk, SOCK_FASYNC); 1306989a2979SEric Dumazet else 1307989a2979SEric Dumazet sock_set_flag(sk, SOCK_FASYNC); 13081da177e4SLinus Torvalds 1309989a2979SEric Dumazet release_sock(sk); 13101da177e4SLinus Torvalds return 0; 13111da177e4SLinus Torvalds } 13121da177e4SLinus Torvalds 1313ceb5d58bSEric Dumazet /* This function may be called only under rcu_lock */ 13141da177e4SLinus Torvalds 1315ceb5d58bSEric Dumazet int sock_wake_async(struct socket_wq *wq, int how, int band) 13161da177e4SLinus Torvalds { 1317ceb5d58bSEric Dumazet if (!wq || !wq->fasync_list) 1318ceb5d58bSEric Dumazet return -1; 131943815482SEric Dumazet 132089bddce5SStephen Hemminger switch (how) { 13218d8ad9d7SPavel Emelyanov case SOCK_WAKE_WAITD: 1322ceb5d58bSEric Dumazet if (test_bit(SOCKWQ_ASYNC_WAITDATA, &wq->flags)) 13231da177e4SLinus Torvalds break; 13241da177e4SLinus Torvalds goto call_kill; 13258d8ad9d7SPavel Emelyanov case SOCK_WAKE_SPACE: 1326ceb5d58bSEric Dumazet if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags)) 13271da177e4SLinus Torvalds break; 13281da177e4SLinus Torvalds /* fall through */ 13298d8ad9d7SPavel Emelyanov case SOCK_WAKE_IO: 13301da177e4SLinus Torvalds call_kill: 133143815482SEric Dumazet kill_fasync(&wq->fasync_list, SIGIO, band); 13321da177e4SLinus Torvalds break; 13338d8ad9d7SPavel Emelyanov case SOCK_WAKE_URG: 133443815482SEric Dumazet kill_fasync(&wq->fasync_list, SIGURG, band); 13351da177e4SLinus Torvalds } 1336ceb5d58bSEric Dumazet 13371da177e4SLinus Torvalds return 0; 13381da177e4SLinus Torvalds } 1339c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async); 13401da177e4SLinus Torvalds 13418a3c245cSPedro Tammela /** 13428a3c245cSPedro Tammela * __sock_create - creates a socket 13438a3c245cSPedro Tammela * @net: net namespace 13448a3c245cSPedro Tammela * @family: protocol family (AF_INET, ...) 13458a3c245cSPedro Tammela * @type: communication type (SOCK_STREAM, ...) 13468a3c245cSPedro Tammela * @protocol: protocol (0, ...) 13478a3c245cSPedro Tammela * @res: new socket 13488a3c245cSPedro Tammela * @kern: boolean for kernel space sockets 13498a3c245cSPedro Tammela * 13508a3c245cSPedro Tammela * Creates a new socket and assigns it to @res, passing through LSM. 13518a3c245cSPedro Tammela * Returns 0 or an error. On failure @res is set to %NULL. @kern must 13528a3c245cSPedro Tammela * be set to true if the socket resides in kernel space. 13538a3c245cSPedro Tammela * This function internally uses GFP_KERNEL. 13548a3c245cSPedro Tammela */ 13558a3c245cSPedro Tammela 1356721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol, 135789bddce5SStephen Hemminger struct socket **res, int kern) 13581da177e4SLinus Torvalds { 13591da177e4SLinus Torvalds int err; 13601da177e4SLinus Torvalds struct socket *sock; 136155737fdaSStephen Hemminger const struct net_proto_family *pf; 13621da177e4SLinus Torvalds 13631da177e4SLinus Torvalds /* 13641da177e4SLinus Torvalds * Check protocol is in range 13651da177e4SLinus Torvalds */ 13661da177e4SLinus Torvalds if (family < 0 || family >= NPROTO) 13671da177e4SLinus Torvalds return -EAFNOSUPPORT; 13681da177e4SLinus Torvalds if (type < 0 || type >= SOCK_MAX) 13691da177e4SLinus Torvalds return -EINVAL; 13701da177e4SLinus Torvalds 13711da177e4SLinus Torvalds /* Compatibility. 13721da177e4SLinus Torvalds 13731da177e4SLinus Torvalds This uglymoron is moved from INET layer to here to avoid 13741da177e4SLinus Torvalds deadlock in module load. 13751da177e4SLinus Torvalds */ 13761da177e4SLinus Torvalds if (family == PF_INET && type == SOCK_PACKET) { 1377f3c98690Sliping.zhang pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n", 137889bddce5SStephen Hemminger current->comm); 13791da177e4SLinus Torvalds family = PF_PACKET; 13801da177e4SLinus Torvalds } 13811da177e4SLinus Torvalds 13821da177e4SLinus Torvalds err = security_socket_create(family, type, protocol, kern); 13831da177e4SLinus Torvalds if (err) 13841da177e4SLinus Torvalds return err; 13851da177e4SLinus Torvalds 138655737fdaSStephen Hemminger /* 138755737fdaSStephen Hemminger * Allocate the socket and allow the family to set things up. if 138855737fdaSStephen Hemminger * the protocol is 0, the family is instructed to select an appropriate 138955737fdaSStephen Hemminger * default. 139055737fdaSStephen Hemminger */ 139155737fdaSStephen Hemminger sock = sock_alloc(); 139255737fdaSStephen Hemminger if (!sock) { 1393e87cc472SJoe Perches net_warn_ratelimited("socket: no more sockets\n"); 139455737fdaSStephen Hemminger return -ENFILE; /* Not exactly a match, but its the 139555737fdaSStephen Hemminger closest posix thing */ 139655737fdaSStephen Hemminger } 139755737fdaSStephen Hemminger 139855737fdaSStephen Hemminger sock->type = type; 139955737fdaSStephen Hemminger 140095a5afcaSJohannes Berg #ifdef CONFIG_MODULES 14011da177e4SLinus Torvalds /* Attempt to load a protocol module if the find failed. 14021da177e4SLinus Torvalds * 14031da177e4SLinus Torvalds * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user 14041da177e4SLinus Torvalds * requested real, full-featured networking support upon configuration. 14051da177e4SLinus Torvalds * Otherwise module support will break! 14061da177e4SLinus Torvalds */ 1407190683a9SEric Dumazet if (rcu_access_pointer(net_families[family]) == NULL) 14081da177e4SLinus Torvalds request_module("net-pf-%d", family); 14091da177e4SLinus Torvalds #endif 14101da177e4SLinus Torvalds 141155737fdaSStephen Hemminger rcu_read_lock(); 141255737fdaSStephen Hemminger pf = rcu_dereference(net_families[family]); 14131da177e4SLinus Torvalds err = -EAFNOSUPPORT; 141455737fdaSStephen Hemminger if (!pf) 141555737fdaSStephen Hemminger goto out_release; 14161da177e4SLinus Torvalds 14171da177e4SLinus Torvalds /* 14181da177e4SLinus Torvalds * We will call the ->create function, that possibly is in a loadable 14191da177e4SLinus Torvalds * module, so we have to bump that loadable module refcnt first. 14201da177e4SLinus Torvalds */ 142155737fdaSStephen Hemminger if (!try_module_get(pf->owner)) 14221da177e4SLinus Torvalds goto out_release; 14231da177e4SLinus Torvalds 142455737fdaSStephen Hemminger /* Now protected by module ref count */ 142555737fdaSStephen Hemminger rcu_read_unlock(); 142655737fdaSStephen Hemminger 14273f378b68SEric Paris err = pf->create(net, sock, protocol, kern); 142855737fdaSStephen Hemminger if (err < 0) 14291da177e4SLinus Torvalds goto out_module_put; 1430a79af59eSFrank Filz 14311da177e4SLinus Torvalds /* 14321da177e4SLinus Torvalds * Now to bump the refcnt of the [loadable] module that owns this 14331da177e4SLinus Torvalds * socket at sock_release time we decrement its refcnt. 14341da177e4SLinus Torvalds */ 143555737fdaSStephen Hemminger if (!try_module_get(sock->ops->owner)) 143655737fdaSStephen Hemminger goto out_module_busy; 143755737fdaSStephen Hemminger 14381da177e4SLinus Torvalds /* 14391da177e4SLinus Torvalds * Now that we're done with the ->create function, the [loadable] 14401da177e4SLinus Torvalds * module can have its refcnt decremented 14411da177e4SLinus Torvalds */ 144255737fdaSStephen Hemminger module_put(pf->owner); 14437420ed23SVenkat Yekkirala err = security_socket_post_create(sock, family, type, protocol, kern); 14447420ed23SVenkat Yekkirala if (err) 14453b185525SHerbert Xu goto out_sock_release; 144655737fdaSStephen Hemminger *res = sock; 14471da177e4SLinus Torvalds 144855737fdaSStephen Hemminger return 0; 144955737fdaSStephen Hemminger 145055737fdaSStephen Hemminger out_module_busy: 145155737fdaSStephen Hemminger err = -EAFNOSUPPORT; 14521da177e4SLinus Torvalds out_module_put: 145355737fdaSStephen Hemminger sock->ops = NULL; 145455737fdaSStephen Hemminger module_put(pf->owner); 145555737fdaSStephen Hemminger out_sock_release: 14561da177e4SLinus Torvalds sock_release(sock); 145755737fdaSStephen Hemminger return err; 145855737fdaSStephen Hemminger 145955737fdaSStephen Hemminger out_release: 146055737fdaSStephen Hemminger rcu_read_unlock(); 146155737fdaSStephen Hemminger goto out_sock_release; 14621da177e4SLinus Torvalds } 1463721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create); 14641da177e4SLinus Torvalds 14658a3c245cSPedro Tammela /** 14668a3c245cSPedro Tammela * sock_create - creates a socket 14678a3c245cSPedro Tammela * @family: protocol family (AF_INET, ...) 14688a3c245cSPedro Tammela * @type: communication type (SOCK_STREAM, ...) 14698a3c245cSPedro Tammela * @protocol: protocol (0, ...) 14708a3c245cSPedro Tammela * @res: new socket 14718a3c245cSPedro Tammela * 14728a3c245cSPedro Tammela * A wrapper around __sock_create(). 14738a3c245cSPedro Tammela * Returns 0 or an error. This function internally uses GFP_KERNEL. 14748a3c245cSPedro Tammela */ 14758a3c245cSPedro Tammela 14761da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res) 14771da177e4SLinus Torvalds { 14781b8d7ae4SEric W. Biederman return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0); 14791da177e4SLinus Torvalds } 1480c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create); 14811da177e4SLinus Torvalds 14828a3c245cSPedro Tammela /** 14838a3c245cSPedro Tammela * sock_create_kern - creates a socket (kernel space) 14848a3c245cSPedro Tammela * @net: net namespace 14858a3c245cSPedro Tammela * @family: protocol family (AF_INET, ...) 14868a3c245cSPedro Tammela * @type: communication type (SOCK_STREAM, ...) 14878a3c245cSPedro Tammela * @protocol: protocol (0, ...) 14888a3c245cSPedro Tammela * @res: new socket 14898a3c245cSPedro Tammela * 14908a3c245cSPedro Tammela * A wrapper around __sock_create(). 14918a3c245cSPedro Tammela * Returns 0 or an error. This function internally uses GFP_KERNEL. 14928a3c245cSPedro Tammela */ 14938a3c245cSPedro Tammela 1494eeb1bd5cSEric W. Biederman int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res) 14951da177e4SLinus Torvalds { 1496eeb1bd5cSEric W. Biederman return __sock_create(net, family, type, protocol, res, 1); 14971da177e4SLinus Torvalds } 1498c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern); 14991da177e4SLinus Torvalds 15009d6a15c3SDominik Brodowski int __sys_socket(int family, int type, int protocol) 15011da177e4SLinus Torvalds { 15021da177e4SLinus Torvalds int retval; 15031da177e4SLinus Torvalds struct socket *sock; 1504a677a039SUlrich Drepper int flags; 1505a677a039SUlrich Drepper 1506e38b36f3SUlrich Drepper /* Check the SOCK_* constants for consistency. */ 1507e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC); 1508e38b36f3SUlrich Drepper BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK); 1509e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK); 1510e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK); 1511e38b36f3SUlrich Drepper 1512a677a039SUlrich Drepper flags = type & ~SOCK_TYPE_MASK; 151377d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1514a677a039SUlrich Drepper return -EINVAL; 1515a677a039SUlrich Drepper type &= SOCK_TYPE_MASK; 15161da177e4SLinus Torvalds 1517aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1518aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1519aaca0bdcSUlrich Drepper 15201da177e4SLinus Torvalds retval = sock_create(family, type, protocol, &sock); 15211da177e4SLinus Torvalds if (retval < 0) 15221da177e4SLinus Torvalds return retval; 15231da177e4SLinus Torvalds 15248e1611e2SAl Viro return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); 15251da177e4SLinus Torvalds } 15261da177e4SLinus Torvalds 15279d6a15c3SDominik Brodowski SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) 15289d6a15c3SDominik Brodowski { 15299d6a15c3SDominik Brodowski return __sys_socket(family, type, protocol); 15309d6a15c3SDominik Brodowski } 15319d6a15c3SDominik Brodowski 15321da177e4SLinus Torvalds /* 15331da177e4SLinus Torvalds * Create a pair of connected sockets. 15341da177e4SLinus Torvalds */ 15351da177e4SLinus Torvalds 15366debc8d8SDominik Brodowski int __sys_socketpair(int family, int type, int protocol, int __user *usockvec) 15371da177e4SLinus Torvalds { 15381da177e4SLinus Torvalds struct socket *sock1, *sock2; 15391da177e4SLinus Torvalds int fd1, fd2, err; 1540db349509SAl Viro struct file *newfile1, *newfile2; 1541a677a039SUlrich Drepper int flags; 1542a677a039SUlrich Drepper 1543a677a039SUlrich Drepper flags = type & ~SOCK_TYPE_MASK; 154477d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1545a677a039SUlrich Drepper return -EINVAL; 1546a677a039SUlrich Drepper type &= SOCK_TYPE_MASK; 15471da177e4SLinus Torvalds 1548aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1549aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1550aaca0bdcSUlrich Drepper 15511da177e4SLinus Torvalds /* 1552016a266bSAl Viro * reserve descriptors and make sure we won't fail 1553016a266bSAl Viro * to return them to userland. 1554016a266bSAl Viro */ 1555016a266bSAl Viro fd1 = get_unused_fd_flags(flags); 1556016a266bSAl Viro if (unlikely(fd1 < 0)) 1557016a266bSAl Viro return fd1; 1558016a266bSAl Viro 1559016a266bSAl Viro fd2 = get_unused_fd_flags(flags); 1560016a266bSAl Viro if (unlikely(fd2 < 0)) { 1561016a266bSAl Viro put_unused_fd(fd1); 1562016a266bSAl Viro return fd2; 1563016a266bSAl Viro } 1564016a266bSAl Viro 1565016a266bSAl Viro err = put_user(fd1, &usockvec[0]); 1566016a266bSAl Viro if (err) 1567016a266bSAl Viro goto out; 1568016a266bSAl Viro 1569016a266bSAl Viro err = put_user(fd2, &usockvec[1]); 1570016a266bSAl Viro if (err) 1571016a266bSAl Viro goto out; 1572016a266bSAl Viro 1573016a266bSAl Viro /* 15741da177e4SLinus Torvalds * Obtain the first socket and check if the underlying protocol 15751da177e4SLinus Torvalds * supports the socketpair call. 15761da177e4SLinus Torvalds */ 15771da177e4SLinus Torvalds 15781da177e4SLinus Torvalds err = sock_create(family, type, protocol, &sock1); 1579016a266bSAl Viro if (unlikely(err < 0)) 15801da177e4SLinus Torvalds goto out; 15811da177e4SLinus Torvalds 15821da177e4SLinus Torvalds err = sock_create(family, type, protocol, &sock2); 1583016a266bSAl Viro if (unlikely(err < 0)) { 1584016a266bSAl Viro sock_release(sock1); 1585016a266bSAl Viro goto out; 1586bf3c23d1SDavid S. Miller } 1587d73aa286SYann Droneaud 1588d47cd945SDavid Herrmann err = security_socket_socketpair(sock1, sock2); 1589d47cd945SDavid Herrmann if (unlikely(err)) { 1590d47cd945SDavid Herrmann sock_release(sock2); 1591d47cd945SDavid Herrmann sock_release(sock1); 1592d47cd945SDavid Herrmann goto out; 1593d47cd945SDavid Herrmann } 1594d47cd945SDavid Herrmann 1595016a266bSAl Viro err = sock1->ops->socketpair(sock1, sock2); 1596016a266bSAl Viro if (unlikely(err < 0)) { 1597016a266bSAl Viro sock_release(sock2); 1598016a266bSAl Viro sock_release(sock1); 1599016a266bSAl Viro goto out; 160028407630SAl Viro } 160128407630SAl Viro 1602aab174f0SLinus Torvalds newfile1 = sock_alloc_file(sock1, flags, NULL); 1603b5ffe634SViresh Kumar if (IS_ERR(newfile1)) { 160428407630SAl Viro err = PTR_ERR(newfile1); 1605016a266bSAl Viro sock_release(sock2); 1606016a266bSAl Viro goto out; 160728407630SAl Viro } 160828407630SAl Viro 1609aab174f0SLinus Torvalds newfile2 = sock_alloc_file(sock2, flags, NULL); 161028407630SAl Viro if (IS_ERR(newfile2)) { 161128407630SAl Viro err = PTR_ERR(newfile2); 1612016a266bSAl Viro fput(newfile1); 1613016a266bSAl Viro goto out; 1614db349509SAl Viro } 1615db349509SAl Viro 1616157cf649SAl Viro audit_fd_pair(fd1, fd2); 1617d73aa286SYann Droneaud 1618db349509SAl Viro fd_install(fd1, newfile1); 1619db349509SAl Viro fd_install(fd2, newfile2); 16201da177e4SLinus Torvalds return 0; 16211da177e4SLinus Torvalds 16221da177e4SLinus Torvalds out: 1623016a266bSAl Viro put_unused_fd(fd2); 1624016a266bSAl Viro put_unused_fd(fd1); 16251da177e4SLinus Torvalds return err; 16261da177e4SLinus Torvalds } 16271da177e4SLinus Torvalds 16286debc8d8SDominik Brodowski SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, 16296debc8d8SDominik Brodowski int __user *, usockvec) 16306debc8d8SDominik Brodowski { 16316debc8d8SDominik Brodowski return __sys_socketpair(family, type, protocol, usockvec); 16326debc8d8SDominik Brodowski } 16336debc8d8SDominik Brodowski 16341da177e4SLinus Torvalds /* 16351da177e4SLinus Torvalds * Bind a name to a socket. Nothing much to do here since it's 16361da177e4SLinus Torvalds * the protocol's responsibility to handle the local address. 16371da177e4SLinus Torvalds * 16381da177e4SLinus Torvalds * We move the socket address to kernel space before we call 16391da177e4SLinus Torvalds * the protocol layer (having also checked the address is ok). 16401da177e4SLinus Torvalds */ 16411da177e4SLinus Torvalds 1642a87d35d8SDominik Brodowski int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) 16431da177e4SLinus Torvalds { 16441da177e4SLinus Torvalds struct socket *sock; 1645230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 16466cb153caSBenjamin LaHaise int err, fput_needed; 16471da177e4SLinus Torvalds 164889bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 164989bddce5SStephen Hemminger if (sock) { 165043db362dSMaciej Żenczykowski err = move_addr_to_kernel(umyaddr, addrlen, &address); 1651068b88ccSJakub Sitnicki if (!err) { 165289bddce5SStephen Hemminger err = security_socket_bind(sock, 1653230b1839SYOSHIFUJI Hideaki (struct sockaddr *)&address, 165489bddce5SStephen Hemminger addrlen); 16556cb153caSBenjamin LaHaise if (!err) 16566cb153caSBenjamin LaHaise err = sock->ops->bind(sock, 165789bddce5SStephen Hemminger (struct sockaddr *) 1658230b1839SYOSHIFUJI Hideaki &address, addrlen); 16591da177e4SLinus Torvalds } 16606cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16611da177e4SLinus Torvalds } 16621da177e4SLinus Torvalds return err; 16631da177e4SLinus Torvalds } 16641da177e4SLinus Torvalds 1665a87d35d8SDominik Brodowski SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen) 1666a87d35d8SDominik Brodowski { 1667a87d35d8SDominik Brodowski return __sys_bind(fd, umyaddr, addrlen); 1668a87d35d8SDominik Brodowski } 1669a87d35d8SDominik Brodowski 16701da177e4SLinus Torvalds /* 16711da177e4SLinus Torvalds * Perform a listen. Basically, we allow the protocol to do anything 16721da177e4SLinus Torvalds * necessary for a listen, and if that works, we mark the socket as 16731da177e4SLinus Torvalds * ready for listening. 16741da177e4SLinus Torvalds */ 16751da177e4SLinus Torvalds 167625e290eeSDominik Brodowski int __sys_listen(int fd, int backlog) 16771da177e4SLinus Torvalds { 16781da177e4SLinus Torvalds struct socket *sock; 16796cb153caSBenjamin LaHaise int err, fput_needed; 1680b8e1f9b5SPavel Emelyanov int somaxconn; 16811da177e4SLinus Torvalds 168289bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 168389bddce5SStephen Hemminger if (sock) { 16848efa6e93SPavel Emelyanov somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn; 168595c96174SEric Dumazet if ((unsigned int)backlog > somaxconn) 1686b8e1f9b5SPavel Emelyanov backlog = somaxconn; 16871da177e4SLinus Torvalds 16881da177e4SLinus Torvalds err = security_socket_listen(sock, backlog); 16896cb153caSBenjamin LaHaise if (!err) 16901da177e4SLinus Torvalds err = sock->ops->listen(sock, backlog); 16916cb153caSBenjamin LaHaise 16926cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16931da177e4SLinus Torvalds } 16941da177e4SLinus Torvalds return err; 16951da177e4SLinus Torvalds } 16961da177e4SLinus Torvalds 169725e290eeSDominik Brodowski SYSCALL_DEFINE2(listen, int, fd, int, backlog) 169825e290eeSDominik Brodowski { 169925e290eeSDominik Brodowski return __sys_listen(fd, backlog); 170025e290eeSDominik Brodowski } 170125e290eeSDominik Brodowski 1702de2ea4b6SJens Axboe int __sys_accept4_file(struct file *file, unsigned file_flags, 1703de2ea4b6SJens Axboe struct sockaddr __user *upeer_sockaddr, 170409952e3eSJens Axboe int __user *upeer_addrlen, int flags, 170509952e3eSJens Axboe unsigned long nofile) 17061da177e4SLinus Torvalds { 17071da177e4SLinus Torvalds struct socket *sock, *newsock; 170839d8c1b6SDavid S. Miller struct file *newfile; 1709de2ea4b6SJens Axboe int err, len, newfd; 1710230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 17111da177e4SLinus Torvalds 171277d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1713aaca0bdcSUlrich Drepper return -EINVAL; 1714aaca0bdcSUlrich Drepper 1715aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1716aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1717aaca0bdcSUlrich Drepper 1718de2ea4b6SJens Axboe sock = sock_from_file(file, &err); 17191da177e4SLinus Torvalds if (!sock) 17201da177e4SLinus Torvalds goto out; 17211da177e4SLinus Torvalds 17221da177e4SLinus Torvalds err = -ENFILE; 1723c6d409cfSEric Dumazet newsock = sock_alloc(); 1724c6d409cfSEric Dumazet if (!newsock) 1725de2ea4b6SJens Axboe goto out; 17261da177e4SLinus Torvalds 17271da177e4SLinus Torvalds newsock->type = sock->type; 17281da177e4SLinus Torvalds newsock->ops = sock->ops; 17291da177e4SLinus Torvalds 17301da177e4SLinus Torvalds /* 17311da177e4SLinus Torvalds * We don't need try_module_get here, as the listening socket (sock) 17321da177e4SLinus Torvalds * has the protocol module (sock->ops->owner) held. 17331da177e4SLinus Torvalds */ 17341da177e4SLinus Torvalds __module_get(newsock->ops->owner); 17351da177e4SLinus Torvalds 173609952e3eSJens Axboe newfd = __get_unused_fd_flags(flags, nofile); 173739d8c1b6SDavid S. Miller if (unlikely(newfd < 0)) { 173839d8c1b6SDavid S. Miller err = newfd; 17399a1875e6SDavid S. Miller sock_release(newsock); 1740de2ea4b6SJens Axboe goto out; 174139d8c1b6SDavid S. Miller } 1742aab174f0SLinus Torvalds newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name); 1743b5ffe634SViresh Kumar if (IS_ERR(newfile)) { 174428407630SAl Viro err = PTR_ERR(newfile); 174528407630SAl Viro put_unused_fd(newfd); 1746de2ea4b6SJens Axboe goto out; 174728407630SAl Viro } 174839d8c1b6SDavid S. Miller 1749a79af59eSFrank Filz err = security_socket_accept(sock, newsock); 1750a79af59eSFrank Filz if (err) 175139d8c1b6SDavid S. Miller goto out_fd; 1752a79af59eSFrank Filz 1753de2ea4b6SJens Axboe err = sock->ops->accept(sock, newsock, sock->file->f_flags | file_flags, 1754de2ea4b6SJens Axboe false); 17551da177e4SLinus Torvalds if (err < 0) 175639d8c1b6SDavid S. Miller goto out_fd; 17571da177e4SLinus Torvalds 17581da177e4SLinus Torvalds if (upeer_sockaddr) { 17599b2c45d4SDenys Vlasenko len = newsock->ops->getname(newsock, 17609b2c45d4SDenys Vlasenko (struct sockaddr *)&address, 2); 17619b2c45d4SDenys Vlasenko if (len < 0) { 17621da177e4SLinus Torvalds err = -ECONNABORTED; 176339d8c1b6SDavid S. Miller goto out_fd; 17641da177e4SLinus Torvalds } 176543db362dSMaciej Żenczykowski err = move_addr_to_user(&address, 1766230b1839SYOSHIFUJI Hideaki len, upeer_sockaddr, upeer_addrlen); 17671da177e4SLinus Torvalds if (err < 0) 176839d8c1b6SDavid S. Miller goto out_fd; 17691da177e4SLinus Torvalds } 17701da177e4SLinus Torvalds 17711da177e4SLinus Torvalds /* File flags are not inherited via accept() unlike another OSes. */ 17721da177e4SLinus Torvalds 177339d8c1b6SDavid S. Miller fd_install(newfd, newfile); 177439d8c1b6SDavid S. Miller err = newfd; 17751da177e4SLinus Torvalds out: 17761da177e4SLinus Torvalds return err; 177739d8c1b6SDavid S. Miller out_fd: 17789606a216SDavid S. Miller fput(newfile); 177939d8c1b6SDavid S. Miller put_unused_fd(newfd); 1780de2ea4b6SJens Axboe goto out; 1781de2ea4b6SJens Axboe 1782de2ea4b6SJens Axboe } 1783de2ea4b6SJens Axboe 1784de2ea4b6SJens Axboe /* 1785de2ea4b6SJens Axboe * For accept, we attempt to create a new socket, set up the link 1786de2ea4b6SJens Axboe * with the client, wake up the client, then return the new 1787de2ea4b6SJens Axboe * connected fd. We collect the address of the connector in kernel 1788de2ea4b6SJens Axboe * space and move it to user at the very end. This is unclean because 1789de2ea4b6SJens Axboe * we open the socket then return an error. 1790de2ea4b6SJens Axboe * 1791de2ea4b6SJens Axboe * 1003.1g adds the ability to recvmsg() to query connection pending 1792de2ea4b6SJens Axboe * status to recvmsg. We need to add that support in a way thats 1793de2ea4b6SJens Axboe * clean when we restructure accept also. 1794de2ea4b6SJens Axboe */ 1795de2ea4b6SJens Axboe 1796de2ea4b6SJens Axboe int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, 1797de2ea4b6SJens Axboe int __user *upeer_addrlen, int flags) 1798de2ea4b6SJens Axboe { 1799de2ea4b6SJens Axboe int ret = -EBADF; 1800de2ea4b6SJens Axboe struct fd f; 1801de2ea4b6SJens Axboe 1802de2ea4b6SJens Axboe f = fdget(fd); 1803de2ea4b6SJens Axboe if (f.file) { 1804de2ea4b6SJens Axboe ret = __sys_accept4_file(f.file, 0, upeer_sockaddr, 180509952e3eSJens Axboe upeer_addrlen, flags, 180609952e3eSJens Axboe rlimit(RLIMIT_NOFILE)); 1807de2ea4b6SJens Axboe if (f.flags) 1808de2ea4b6SJens Axboe fput(f.file); 1809de2ea4b6SJens Axboe } 1810de2ea4b6SJens Axboe 1811de2ea4b6SJens Axboe return ret; 18121da177e4SLinus Torvalds } 18131da177e4SLinus Torvalds 18144541e805SDominik Brodowski SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, 18154541e805SDominik Brodowski int __user *, upeer_addrlen, int, flags) 18164541e805SDominik Brodowski { 18174541e805SDominik Brodowski return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, flags); 18184541e805SDominik Brodowski } 18194541e805SDominik Brodowski 182020f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr, 182120f37034SHeiko Carstens int __user *, upeer_addrlen) 1822aaca0bdcSUlrich Drepper { 18234541e805SDominik Brodowski return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0); 1824aaca0bdcSUlrich Drepper } 1825aaca0bdcSUlrich Drepper 18261da177e4SLinus Torvalds /* 18271da177e4SLinus Torvalds * Attempt to connect to a socket with the server address. The address 18281da177e4SLinus Torvalds * is in user space so we verify it is OK and move it to kernel space. 18291da177e4SLinus Torvalds * 18301da177e4SLinus Torvalds * For 1003.1g we need to add clean support for a bind to AF_UNSPEC to 18311da177e4SLinus Torvalds * break bindings 18321da177e4SLinus Torvalds * 18331da177e4SLinus Torvalds * NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and 18341da177e4SLinus Torvalds * other SEQPACKET protocols that take time to connect() as it doesn't 18351da177e4SLinus Torvalds * include the -EINPROGRESS status for such sockets. 18361da177e4SLinus Torvalds */ 18371da177e4SLinus Torvalds 1838f499a021SJens Axboe int __sys_connect_file(struct file *file, struct sockaddr_storage *address, 1839bd3ded31SJens Axboe int addrlen, int file_flags) 18401da177e4SLinus Torvalds { 18411da177e4SLinus Torvalds struct socket *sock; 1842bd3ded31SJens Axboe int err; 18431da177e4SLinus Torvalds 1844bd3ded31SJens Axboe sock = sock_from_file(file, &err); 18451da177e4SLinus Torvalds if (!sock) 18461da177e4SLinus Torvalds goto out; 18471da177e4SLinus Torvalds 184889bddce5SStephen Hemminger err = 1849f499a021SJens Axboe security_socket_connect(sock, (struct sockaddr *)address, addrlen); 18501da177e4SLinus Torvalds if (err) 1851bd3ded31SJens Axboe goto out; 18521da177e4SLinus Torvalds 1853f499a021SJens Axboe err = sock->ops->connect(sock, (struct sockaddr *)address, addrlen, 1854bd3ded31SJens Axboe sock->file->f_flags | file_flags); 18551da177e4SLinus Torvalds out: 18561da177e4SLinus Torvalds return err; 18571da177e4SLinus Torvalds } 18581da177e4SLinus Torvalds 1859bd3ded31SJens Axboe int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen) 1860bd3ded31SJens Axboe { 1861bd3ded31SJens Axboe int ret = -EBADF; 1862bd3ded31SJens Axboe struct fd f; 1863bd3ded31SJens Axboe 1864bd3ded31SJens Axboe f = fdget(fd); 1865bd3ded31SJens Axboe if (f.file) { 1866f499a021SJens Axboe struct sockaddr_storage address; 1867f499a021SJens Axboe 1868f499a021SJens Axboe ret = move_addr_to_kernel(uservaddr, addrlen, &address); 1869f499a021SJens Axboe if (!ret) 1870f499a021SJens Axboe ret = __sys_connect_file(f.file, &address, addrlen, 0); 1871bd3ded31SJens Axboe if (f.flags) 1872bd3ded31SJens Axboe fput(f.file); 1873bd3ded31SJens Axboe } 1874bd3ded31SJens Axboe 1875bd3ded31SJens Axboe return ret; 1876bd3ded31SJens Axboe } 1877bd3ded31SJens Axboe 18781387c2c2SDominik Brodowski SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr, 18791387c2c2SDominik Brodowski int, addrlen) 18801387c2c2SDominik Brodowski { 18811387c2c2SDominik Brodowski return __sys_connect(fd, uservaddr, addrlen); 18821387c2c2SDominik Brodowski } 18831387c2c2SDominik Brodowski 18841da177e4SLinus Torvalds /* 18851da177e4SLinus Torvalds * Get the local address ('name') of a socket object. Move the obtained 18861da177e4SLinus Torvalds * name to user space. 18871da177e4SLinus Torvalds */ 18881da177e4SLinus Torvalds 18898882a107SDominik Brodowski int __sys_getsockname(int fd, struct sockaddr __user *usockaddr, 18908882a107SDominik Brodowski int __user *usockaddr_len) 18911da177e4SLinus Torvalds { 18921da177e4SLinus Torvalds struct socket *sock; 1893230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 18949b2c45d4SDenys Vlasenko int err, fput_needed; 18951da177e4SLinus Torvalds 18966cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 18971da177e4SLinus Torvalds if (!sock) 18981da177e4SLinus Torvalds goto out; 18991da177e4SLinus Torvalds 19001da177e4SLinus Torvalds err = security_socket_getsockname(sock); 19011da177e4SLinus Torvalds if (err) 19021da177e4SLinus Torvalds goto out_put; 19031da177e4SLinus Torvalds 19049b2c45d4SDenys Vlasenko err = sock->ops->getname(sock, (struct sockaddr *)&address, 0); 19059b2c45d4SDenys Vlasenko if (err < 0) 19061da177e4SLinus Torvalds goto out_put; 19079b2c45d4SDenys Vlasenko /* "err" is actually length in this case */ 19089b2c45d4SDenys Vlasenko err = move_addr_to_user(&address, err, usockaddr, usockaddr_len); 19091da177e4SLinus Torvalds 19101da177e4SLinus Torvalds out_put: 19116cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 19121da177e4SLinus Torvalds out: 19131da177e4SLinus Torvalds return err; 19141da177e4SLinus Torvalds } 19151da177e4SLinus Torvalds 19168882a107SDominik Brodowski SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr, 19178882a107SDominik Brodowski int __user *, usockaddr_len) 19188882a107SDominik Brodowski { 19198882a107SDominik Brodowski return __sys_getsockname(fd, usockaddr, usockaddr_len); 19208882a107SDominik Brodowski } 19218882a107SDominik Brodowski 19221da177e4SLinus Torvalds /* 19231da177e4SLinus Torvalds * Get the remote address ('name') of a socket object. Move the obtained 19241da177e4SLinus Torvalds * name to user space. 19251da177e4SLinus Torvalds */ 19261da177e4SLinus Torvalds 1927b21c8f83SDominik Brodowski int __sys_getpeername(int fd, struct sockaddr __user *usockaddr, 1928b21c8f83SDominik Brodowski int __user *usockaddr_len) 19291da177e4SLinus Torvalds { 19301da177e4SLinus Torvalds struct socket *sock; 1931230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 19329b2c45d4SDenys Vlasenko int err, fput_needed; 19331da177e4SLinus Torvalds 193489bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 193589bddce5SStephen Hemminger if (sock != NULL) { 19361da177e4SLinus Torvalds err = security_socket_getpeername(sock); 19371da177e4SLinus Torvalds if (err) { 19386cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 19391da177e4SLinus Torvalds return err; 19401da177e4SLinus Torvalds } 19411da177e4SLinus Torvalds 19429b2c45d4SDenys Vlasenko err = sock->ops->getname(sock, (struct sockaddr *)&address, 1); 19439b2c45d4SDenys Vlasenko if (err >= 0) 19449b2c45d4SDenys Vlasenko /* "err" is actually length in this case */ 19459b2c45d4SDenys Vlasenko err = move_addr_to_user(&address, err, usockaddr, 194689bddce5SStephen Hemminger usockaddr_len); 19476cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 19481da177e4SLinus Torvalds } 19491da177e4SLinus Torvalds return err; 19501da177e4SLinus Torvalds } 19511da177e4SLinus Torvalds 1952b21c8f83SDominik Brodowski SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr, 1953b21c8f83SDominik Brodowski int __user *, usockaddr_len) 1954b21c8f83SDominik Brodowski { 1955b21c8f83SDominik Brodowski return __sys_getpeername(fd, usockaddr, usockaddr_len); 1956b21c8f83SDominik Brodowski } 1957b21c8f83SDominik Brodowski 19581da177e4SLinus Torvalds /* 19591da177e4SLinus Torvalds * Send a datagram to a given address. We move the address into kernel 19601da177e4SLinus Torvalds * space and check the user space data area is readable before invoking 19611da177e4SLinus Torvalds * the protocol. 19621da177e4SLinus Torvalds */ 1963211b634bSDominik Brodowski int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags, 1964211b634bSDominik Brodowski struct sockaddr __user *addr, int addr_len) 19651da177e4SLinus Torvalds { 19661da177e4SLinus Torvalds struct socket *sock; 1967230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 19681da177e4SLinus Torvalds int err; 19691da177e4SLinus Torvalds struct msghdr msg; 19701da177e4SLinus Torvalds struct iovec iov; 19716cb153caSBenjamin LaHaise int fput_needed; 19721da177e4SLinus Torvalds 1973602bd0e9SAl Viro err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter); 1974602bd0e9SAl Viro if (unlikely(err)) 1975602bd0e9SAl Viro return err; 1976de0fa95cSPavel Emelyanov sock = sockfd_lookup_light(fd, &err, &fput_needed); 1977de0fa95cSPavel Emelyanov if (!sock) 19784387ff75SDavid S. Miller goto out; 19796cb153caSBenjamin LaHaise 19801da177e4SLinus Torvalds msg.msg_name = NULL; 19811da177e4SLinus Torvalds msg.msg_control = NULL; 19821da177e4SLinus Torvalds msg.msg_controllen = 0; 19831da177e4SLinus Torvalds msg.msg_namelen = 0; 19846cb153caSBenjamin LaHaise if (addr) { 198543db362dSMaciej Żenczykowski err = move_addr_to_kernel(addr, addr_len, &address); 19861da177e4SLinus Torvalds if (err < 0) 19871da177e4SLinus Torvalds goto out_put; 1988230b1839SYOSHIFUJI Hideaki msg.msg_name = (struct sockaddr *)&address; 19891da177e4SLinus Torvalds msg.msg_namelen = addr_len; 19901da177e4SLinus Torvalds } 19911da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 19921da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 19931da177e4SLinus Torvalds msg.msg_flags = flags; 1994d8725c86SAl Viro err = sock_sendmsg(sock, &msg); 19951da177e4SLinus Torvalds 19961da177e4SLinus Torvalds out_put: 1997de0fa95cSPavel Emelyanov fput_light(sock->file, fput_needed); 19984387ff75SDavid S. Miller out: 19991da177e4SLinus Torvalds return err; 20001da177e4SLinus Torvalds } 20011da177e4SLinus Torvalds 2002211b634bSDominik Brodowski SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len, 2003211b634bSDominik Brodowski unsigned int, flags, struct sockaddr __user *, addr, 2004211b634bSDominik Brodowski int, addr_len) 2005211b634bSDominik Brodowski { 2006211b634bSDominik Brodowski return __sys_sendto(fd, buff, len, flags, addr, addr_len); 2007211b634bSDominik Brodowski } 2008211b634bSDominik Brodowski 20091da177e4SLinus Torvalds /* 20101da177e4SLinus Torvalds * Send a datagram down a socket. 20111da177e4SLinus Torvalds */ 20121da177e4SLinus Torvalds 20133e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len, 201495c96174SEric Dumazet unsigned int, flags) 20151da177e4SLinus Torvalds { 2016211b634bSDominik Brodowski return __sys_sendto(fd, buff, len, flags, NULL, 0); 20171da177e4SLinus Torvalds } 20181da177e4SLinus Torvalds 20191da177e4SLinus Torvalds /* 20201da177e4SLinus Torvalds * Receive a frame from the socket and optionally record the address of the 20211da177e4SLinus Torvalds * sender. We verify the buffers are writable and if needed move the 20221da177e4SLinus Torvalds * sender address from kernel to user space. 20231da177e4SLinus Torvalds */ 20247a09e1ebSDominik Brodowski int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags, 20257a09e1ebSDominik Brodowski struct sockaddr __user *addr, int __user *addr_len) 20261da177e4SLinus Torvalds { 20271da177e4SLinus Torvalds struct socket *sock; 20281da177e4SLinus Torvalds struct iovec iov; 20291da177e4SLinus Torvalds struct msghdr msg; 2030230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 20311da177e4SLinus Torvalds int err, err2; 20326cb153caSBenjamin LaHaise int fput_needed; 20331da177e4SLinus Torvalds 2034602bd0e9SAl Viro err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter); 2035602bd0e9SAl Viro if (unlikely(err)) 2036602bd0e9SAl Viro return err; 2037de0fa95cSPavel Emelyanov sock = sockfd_lookup_light(fd, &err, &fput_needed); 20381da177e4SLinus Torvalds if (!sock) 2039de0fa95cSPavel Emelyanov goto out; 20401da177e4SLinus Torvalds 20411da177e4SLinus Torvalds msg.msg_control = NULL; 20421da177e4SLinus Torvalds msg.msg_controllen = 0; 2043f3d33426SHannes Frederic Sowa /* Save some cycles and don't copy the address if not needed */ 2044f3d33426SHannes Frederic Sowa msg.msg_name = addr ? (struct sockaddr *)&address : NULL; 2045f3d33426SHannes Frederic Sowa /* We assume all kernel code knows the size of sockaddr_storage */ 2046f3d33426SHannes Frederic Sowa msg.msg_namelen = 0; 2047130ed5d1Stadeusz.struk@intel.com msg.msg_iocb = NULL; 20489f138fa6SAlexander Potapenko msg.msg_flags = 0; 20491da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 20501da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 20512da62906SAl Viro err = sock_recvmsg(sock, &msg, flags); 20521da177e4SLinus Torvalds 205389bddce5SStephen Hemminger if (err >= 0 && addr != NULL) { 205443db362dSMaciej Żenczykowski err2 = move_addr_to_user(&address, 2055230b1839SYOSHIFUJI Hideaki msg.msg_namelen, addr, addr_len); 20561da177e4SLinus Torvalds if (err2 < 0) 20571da177e4SLinus Torvalds err = err2; 20581da177e4SLinus Torvalds } 2059de0fa95cSPavel Emelyanov 2060de0fa95cSPavel Emelyanov fput_light(sock->file, fput_needed); 20614387ff75SDavid S. Miller out: 20621da177e4SLinus Torvalds return err; 20631da177e4SLinus Torvalds } 20641da177e4SLinus Torvalds 20657a09e1ebSDominik Brodowski SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, 20667a09e1ebSDominik Brodowski unsigned int, flags, struct sockaddr __user *, addr, 20677a09e1ebSDominik Brodowski int __user *, addr_len) 20687a09e1ebSDominik Brodowski { 20697a09e1ebSDominik Brodowski return __sys_recvfrom(fd, ubuf, size, flags, addr, addr_len); 20707a09e1ebSDominik Brodowski } 20717a09e1ebSDominik Brodowski 20721da177e4SLinus Torvalds /* 20731da177e4SLinus Torvalds * Receive a datagram from a socket. 20741da177e4SLinus Torvalds */ 20751da177e4SLinus Torvalds 2076b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size, 2077b7c0ddf5SJan Glauber unsigned int, flags) 20781da177e4SLinus Torvalds { 20797a09e1ebSDominik Brodowski return __sys_recvfrom(fd, ubuf, size, flags, NULL, NULL); 20801da177e4SLinus Torvalds } 20811da177e4SLinus Torvalds 208283f0c10bSFlorian Westphal static bool sock_use_custom_sol_socket(const struct socket *sock) 208383f0c10bSFlorian Westphal { 208483f0c10bSFlorian Westphal const struct sock *sk = sock->sk; 208583f0c10bSFlorian Westphal 208683f0c10bSFlorian Westphal /* Use sock->ops->setsockopt() for MPTCP */ 208783f0c10bSFlorian Westphal return IS_ENABLED(CONFIG_MPTCP) && 208883f0c10bSFlorian Westphal sk->sk_protocol == IPPROTO_MPTCP && 208983f0c10bSFlorian Westphal sk->sk_type == SOCK_STREAM && 209083f0c10bSFlorian Westphal (sk->sk_family == AF_INET || sk->sk_family == AF_INET6); 209183f0c10bSFlorian Westphal } 209283f0c10bSFlorian Westphal 20931da177e4SLinus Torvalds /* 20941da177e4SLinus Torvalds * Set a socket option. Because we don't know the option lengths we have 20951da177e4SLinus Torvalds * to pass the user mode parameter for the protocols to sort out. 20961da177e4SLinus Torvalds */ 20971da177e4SLinus Torvalds 2098cc36dca0SDominik Brodowski static int __sys_setsockopt(int fd, int level, int optname, 2099cc36dca0SDominik Brodowski char __user *optval, int optlen) 21001da177e4SLinus Torvalds { 21010d01da6aSStanislav Fomichev mm_segment_t oldfs = get_fs(); 21020d01da6aSStanislav Fomichev char *kernel_optval = NULL; 21036cb153caSBenjamin LaHaise int err, fput_needed; 21041da177e4SLinus Torvalds struct socket *sock; 21051da177e4SLinus Torvalds 21061da177e4SLinus Torvalds if (optlen < 0) 21071da177e4SLinus Torvalds return -EINVAL; 21081da177e4SLinus Torvalds 210989bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 211089bddce5SStephen Hemminger if (sock != NULL) { 21111da177e4SLinus Torvalds err = security_socket_setsockopt(sock, level, optname); 21126cb153caSBenjamin LaHaise if (err) 21136cb153caSBenjamin LaHaise goto out_put; 21141da177e4SLinus Torvalds 21150d01da6aSStanislav Fomichev err = BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock->sk, &level, 21160d01da6aSStanislav Fomichev &optname, optval, &optlen, 21170d01da6aSStanislav Fomichev &kernel_optval); 21180d01da6aSStanislav Fomichev 21190d01da6aSStanislav Fomichev if (err < 0) { 21200d01da6aSStanislav Fomichev goto out_put; 21210d01da6aSStanislav Fomichev } else if (err > 0) { 21220d01da6aSStanislav Fomichev err = 0; 21230d01da6aSStanislav Fomichev goto out_put; 21240d01da6aSStanislav Fomichev } 21250d01da6aSStanislav Fomichev 21260d01da6aSStanislav Fomichev if (kernel_optval) { 21270d01da6aSStanislav Fomichev set_fs(KERNEL_DS); 21280d01da6aSStanislav Fomichev optval = (char __user __force *)kernel_optval; 21290d01da6aSStanislav Fomichev } 21300d01da6aSStanislav Fomichev 213183f0c10bSFlorian Westphal if (level == SOL_SOCKET && !sock_use_custom_sol_socket(sock)) 213289bddce5SStephen Hemminger err = 213389bddce5SStephen Hemminger sock_setsockopt(sock, level, optname, optval, 213489bddce5SStephen Hemminger optlen); 21351da177e4SLinus Torvalds else 213689bddce5SStephen Hemminger err = 213789bddce5SStephen Hemminger sock->ops->setsockopt(sock, level, optname, optval, 213889bddce5SStephen Hemminger optlen); 21390d01da6aSStanislav Fomichev 21400d01da6aSStanislav Fomichev if (kernel_optval) { 21410d01da6aSStanislav Fomichev set_fs(oldfs); 21420d01da6aSStanislav Fomichev kfree(kernel_optval); 21430d01da6aSStanislav Fomichev } 21446cb153caSBenjamin LaHaise out_put: 21456cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 21461da177e4SLinus Torvalds } 21471da177e4SLinus Torvalds return err; 21481da177e4SLinus Torvalds } 21491da177e4SLinus Torvalds 2150cc36dca0SDominik Brodowski SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname, 2151cc36dca0SDominik Brodowski char __user *, optval, int, optlen) 2152cc36dca0SDominik Brodowski { 2153cc36dca0SDominik Brodowski return __sys_setsockopt(fd, level, optname, optval, optlen); 2154cc36dca0SDominik Brodowski } 2155cc36dca0SDominik Brodowski 21561da177e4SLinus Torvalds /* 21571da177e4SLinus Torvalds * Get a socket option. Because we don't know the option lengths we have 21581da177e4SLinus Torvalds * to pass a user mode parameter for the protocols to sort out. 21591da177e4SLinus Torvalds */ 21601da177e4SLinus Torvalds 216113a2d70eSDominik Brodowski static int __sys_getsockopt(int fd, int level, int optname, 216213a2d70eSDominik Brodowski char __user *optval, int __user *optlen) 21631da177e4SLinus Torvalds { 21646cb153caSBenjamin LaHaise int err, fput_needed; 21651da177e4SLinus Torvalds struct socket *sock; 21660d01da6aSStanislav Fomichev int max_optlen; 21671da177e4SLinus Torvalds 216889bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 216989bddce5SStephen Hemminger if (sock != NULL) { 21706cb153caSBenjamin LaHaise err = security_socket_getsockopt(sock, level, optname); 21716cb153caSBenjamin LaHaise if (err) 21726cb153caSBenjamin LaHaise goto out_put; 21731da177e4SLinus Torvalds 21740d01da6aSStanislav Fomichev max_optlen = BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN(optlen); 21750d01da6aSStanislav Fomichev 21761da177e4SLinus Torvalds if (level == SOL_SOCKET) 217789bddce5SStephen Hemminger err = 217889bddce5SStephen Hemminger sock_getsockopt(sock, level, optname, optval, 217989bddce5SStephen Hemminger optlen); 21801da177e4SLinus Torvalds else 218189bddce5SStephen Hemminger err = 218289bddce5SStephen Hemminger sock->ops->getsockopt(sock, level, optname, optval, 218389bddce5SStephen Hemminger optlen); 21840d01da6aSStanislav Fomichev 21850d01da6aSStanislav Fomichev err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level, optname, 21860d01da6aSStanislav Fomichev optval, optlen, 21870d01da6aSStanislav Fomichev max_optlen, err); 21886cb153caSBenjamin LaHaise out_put: 21896cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 21901da177e4SLinus Torvalds } 21911da177e4SLinus Torvalds return err; 21921da177e4SLinus Torvalds } 21931da177e4SLinus Torvalds 219413a2d70eSDominik Brodowski SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname, 219513a2d70eSDominik Brodowski char __user *, optval, int __user *, optlen) 219613a2d70eSDominik Brodowski { 219713a2d70eSDominik Brodowski return __sys_getsockopt(fd, level, optname, optval, optlen); 219813a2d70eSDominik Brodowski } 219913a2d70eSDominik Brodowski 22001da177e4SLinus Torvalds /* 22011da177e4SLinus Torvalds * Shutdown a socket. 22021da177e4SLinus Torvalds */ 22031da177e4SLinus Torvalds 2204005a1aeaSDominik Brodowski int __sys_shutdown(int fd, int how) 22051da177e4SLinus Torvalds { 22066cb153caSBenjamin LaHaise int err, fput_needed; 22071da177e4SLinus Torvalds struct socket *sock; 22081da177e4SLinus Torvalds 220989bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 221089bddce5SStephen Hemminger if (sock != NULL) { 22111da177e4SLinus Torvalds err = security_socket_shutdown(sock, how); 22126cb153caSBenjamin LaHaise if (!err) 22131da177e4SLinus Torvalds err = sock->ops->shutdown(sock, how); 22146cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 22151da177e4SLinus Torvalds } 22161da177e4SLinus Torvalds return err; 22171da177e4SLinus Torvalds } 22181da177e4SLinus Torvalds 2219005a1aeaSDominik Brodowski SYSCALL_DEFINE2(shutdown, int, fd, int, how) 2220005a1aeaSDominik Brodowski { 2221005a1aeaSDominik Brodowski return __sys_shutdown(fd, how); 2222005a1aeaSDominik Brodowski } 2223005a1aeaSDominik Brodowski 22241da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit 22251da177e4SLinus Torvalds * fields which are the same type (int / unsigned) on our platforms. 22261da177e4SLinus Torvalds */ 22271da177e4SLinus Torvalds #define COMPAT_MSG(msg, member) ((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member) 22281da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen) 22291da177e4SLinus Torvalds #define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags) 22301da177e4SLinus Torvalds 2231c71d8ebeSTetsuo Handa struct used_address { 2232c71d8ebeSTetsuo Handa struct sockaddr_storage name; 2233c71d8ebeSTetsuo Handa unsigned int name_len; 2234c71d8ebeSTetsuo Handa }; 2235c71d8ebeSTetsuo Handa 22360a384abfSJens Axboe int __copy_msghdr_from_user(struct msghdr *kmsg, 223708adb7daSAl Viro struct user_msghdr __user *umsg, 223808adb7daSAl Viro struct sockaddr __user **save_addr, 22390a384abfSJens Axboe struct iovec __user **uiov, size_t *nsegs) 22401661bf36SDan Carpenter { 2241ffb07550SAl Viro struct user_msghdr msg; 224208adb7daSAl Viro ssize_t err; 224308adb7daSAl Viro 2244ffb07550SAl Viro if (copy_from_user(&msg, umsg, sizeof(*umsg))) 22451661bf36SDan Carpenter return -EFAULT; 2246dbb490b9SMatthew Leach 22471f466e1fSChristoph Hellwig kmsg->msg_control_is_user = true; 22481f466e1fSChristoph Hellwig kmsg->msg_control_user = msg.msg_control; 2249ffb07550SAl Viro kmsg->msg_controllen = msg.msg_controllen; 2250ffb07550SAl Viro kmsg->msg_flags = msg.msg_flags; 2251ffb07550SAl Viro 2252ffb07550SAl Viro kmsg->msg_namelen = msg.msg_namelen; 2253ffb07550SAl Viro if (!msg.msg_name) 22546a2a2b3aSAni Sinha kmsg->msg_namelen = 0; 22556a2a2b3aSAni Sinha 2256dbb490b9SMatthew Leach if (kmsg->msg_namelen < 0) 2257dbb490b9SMatthew Leach return -EINVAL; 2258dbb490b9SMatthew Leach 22591661bf36SDan Carpenter if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) 2260db31c55aSDan Carpenter kmsg->msg_namelen = sizeof(struct sockaddr_storage); 226108adb7daSAl Viro 226208adb7daSAl Viro if (save_addr) 2263ffb07550SAl Viro *save_addr = msg.msg_name; 226408adb7daSAl Viro 2265ffb07550SAl Viro if (msg.msg_name && kmsg->msg_namelen) { 226608adb7daSAl Viro if (!save_addr) { 2267864d9664SPaolo Abeni err = move_addr_to_kernel(msg.msg_name, 2268864d9664SPaolo Abeni kmsg->msg_namelen, 226908adb7daSAl Viro kmsg->msg_name); 227008adb7daSAl Viro if (err < 0) 227108adb7daSAl Viro return err; 227208adb7daSAl Viro } 227308adb7daSAl Viro } else { 227408adb7daSAl Viro kmsg->msg_name = NULL; 227508adb7daSAl Viro kmsg->msg_namelen = 0; 227608adb7daSAl Viro } 227708adb7daSAl Viro 2278ffb07550SAl Viro if (msg.msg_iovlen > UIO_MAXIOV) 227908adb7daSAl Viro return -EMSGSIZE; 228008adb7daSAl Viro 22810345f931Stadeusz.struk@intel.com kmsg->msg_iocb = NULL; 22820a384abfSJens Axboe *uiov = msg.msg_iov; 22830a384abfSJens Axboe *nsegs = msg.msg_iovlen; 22840a384abfSJens Axboe return 0; 22850a384abfSJens Axboe } 22860a384abfSJens Axboe 22870a384abfSJens Axboe static int copy_msghdr_from_user(struct msghdr *kmsg, 22880a384abfSJens Axboe struct user_msghdr __user *umsg, 22890a384abfSJens Axboe struct sockaddr __user **save_addr, 22900a384abfSJens Axboe struct iovec **iov) 22910a384abfSJens Axboe { 22920a384abfSJens Axboe struct user_msghdr msg; 22930a384abfSJens Axboe ssize_t err; 22940a384abfSJens Axboe 22950a384abfSJens Axboe err = __copy_msghdr_from_user(kmsg, umsg, save_addr, &msg.msg_iov, 22960a384abfSJens Axboe &msg.msg_iovlen); 22970a384abfSJens Axboe if (err) 22980a384abfSJens Axboe return err; 22990345f931Stadeusz.struk@intel.com 230087e5e6daSJens Axboe err = import_iovec(save_addr ? READ : WRITE, 2301ffb07550SAl Viro msg.msg_iov, msg.msg_iovlen, 2302da184284SAl Viro UIO_FASTIOV, iov, &kmsg->msg_iter); 230387e5e6daSJens Axboe return err < 0 ? err : 0; 23041661bf36SDan Carpenter } 23051661bf36SDan Carpenter 23064257c8caSJens Axboe static int ____sys_sendmsg(struct socket *sock, struct msghdr *msg_sys, 23074257c8caSJens Axboe unsigned int flags, struct used_address *used_address, 230828a94d8fSTom Herbert unsigned int allowed_msghdr_flags) 23091da177e4SLinus Torvalds { 2310b9d717a7SAlex Williamson unsigned char ctl[sizeof(struct cmsghdr) + 20] 2311846cc123SAmit Kushwaha __aligned(sizeof(__kernel_size_t)); 2312b9d717a7SAlex Williamson /* 20 is size of ipv6_pktinfo */ 23131da177e4SLinus Torvalds unsigned char *ctl_buf = ctl; 2314d8725c86SAl Viro int ctl_len; 231508adb7daSAl Viro ssize_t err; 23161da177e4SLinus Torvalds 23171da177e4SLinus Torvalds err = -ENOBUFS; 23181da177e4SLinus Torvalds 2319228e548eSAnton Blanchard if (msg_sys->msg_controllen > INT_MAX) 23204257c8caSJens Axboe goto out; 232128a94d8fSTom Herbert flags |= (msg_sys->msg_flags & allowed_msghdr_flags); 2322228e548eSAnton Blanchard ctl_len = msg_sys->msg_controllen; 23231da177e4SLinus Torvalds if ((MSG_CMSG_COMPAT & flags) && ctl_len) { 232489bddce5SStephen Hemminger err = 2325228e548eSAnton Blanchard cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl, 232689bddce5SStephen Hemminger sizeof(ctl)); 23271da177e4SLinus Torvalds if (err) 23284257c8caSJens Axboe goto out; 2329228e548eSAnton Blanchard ctl_buf = msg_sys->msg_control; 2330228e548eSAnton Blanchard ctl_len = msg_sys->msg_controllen; 23311da177e4SLinus Torvalds } else if (ctl_len) { 2332ac4340fcSDavid S. Miller BUILD_BUG_ON(sizeof(struct cmsghdr) != 2333ac4340fcSDavid S. Miller CMSG_ALIGN(sizeof(struct cmsghdr))); 233489bddce5SStephen Hemminger if (ctl_len > sizeof(ctl)) { 23351da177e4SLinus Torvalds ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); 23361da177e4SLinus Torvalds if (ctl_buf == NULL) 23374257c8caSJens Axboe goto out; 23381da177e4SLinus Torvalds } 23391da177e4SLinus Torvalds err = -EFAULT; 23401f466e1fSChristoph Hellwig if (copy_from_user(ctl_buf, msg_sys->msg_control_user, ctl_len)) 23411da177e4SLinus Torvalds goto out_freectl; 2342228e548eSAnton Blanchard msg_sys->msg_control = ctl_buf; 23431f466e1fSChristoph Hellwig msg_sys->msg_control_is_user = false; 23441da177e4SLinus Torvalds } 2345228e548eSAnton Blanchard msg_sys->msg_flags = flags; 23461da177e4SLinus Torvalds 23471da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 2348228e548eSAnton Blanchard msg_sys->msg_flags |= MSG_DONTWAIT; 2349c71d8ebeSTetsuo Handa /* 2350c71d8ebeSTetsuo Handa * If this is sendmmsg() and current destination address is same as 2351c71d8ebeSTetsuo Handa * previously succeeded address, omit asking LSM's decision. 2352c71d8ebeSTetsuo Handa * used_address->name_len is initialized to UINT_MAX so that the first 2353c71d8ebeSTetsuo Handa * destination address never matches. 2354c71d8ebeSTetsuo Handa */ 2355bc909d9dSMathieu Desnoyers if (used_address && msg_sys->msg_name && 2356bc909d9dSMathieu Desnoyers used_address->name_len == msg_sys->msg_namelen && 2357bc909d9dSMathieu Desnoyers !memcmp(&used_address->name, msg_sys->msg_name, 2358c71d8ebeSTetsuo Handa used_address->name_len)) { 2359d8725c86SAl Viro err = sock_sendmsg_nosec(sock, msg_sys); 2360c71d8ebeSTetsuo Handa goto out_freectl; 2361c71d8ebeSTetsuo Handa } 2362d8725c86SAl Viro err = sock_sendmsg(sock, msg_sys); 2363c71d8ebeSTetsuo Handa /* 2364c71d8ebeSTetsuo Handa * If this is sendmmsg() and sending to current destination address was 2365c71d8ebeSTetsuo Handa * successful, remember it. 2366c71d8ebeSTetsuo Handa */ 2367c71d8ebeSTetsuo Handa if (used_address && err >= 0) { 2368c71d8ebeSTetsuo Handa used_address->name_len = msg_sys->msg_namelen; 2369bc909d9dSMathieu Desnoyers if (msg_sys->msg_name) 2370bc909d9dSMathieu Desnoyers memcpy(&used_address->name, msg_sys->msg_name, 2371c71d8ebeSTetsuo Handa used_address->name_len); 2372c71d8ebeSTetsuo Handa } 23731da177e4SLinus Torvalds 23741da177e4SLinus Torvalds out_freectl: 23751da177e4SLinus Torvalds if (ctl_buf != ctl) 23761da177e4SLinus Torvalds sock_kfree_s(sock->sk, ctl_buf, ctl_len); 23774257c8caSJens Axboe out: 23784257c8caSJens Axboe return err; 23794257c8caSJens Axboe } 23804257c8caSJens Axboe 238103b1230cSJens Axboe int sendmsg_copy_msghdr(struct msghdr *msg, 23824257c8caSJens Axboe struct user_msghdr __user *umsg, unsigned flags, 23834257c8caSJens Axboe struct iovec **iov) 23844257c8caSJens Axboe { 23854257c8caSJens Axboe int err; 23864257c8caSJens Axboe 23874257c8caSJens Axboe if (flags & MSG_CMSG_COMPAT) { 23884257c8caSJens Axboe struct compat_msghdr __user *msg_compat; 23894257c8caSJens Axboe 23904257c8caSJens Axboe msg_compat = (struct compat_msghdr __user *) umsg; 23914257c8caSJens Axboe err = get_compat_msghdr(msg, msg_compat, NULL, iov); 23924257c8caSJens Axboe } else { 23934257c8caSJens Axboe err = copy_msghdr_from_user(msg, umsg, NULL, iov); 23944257c8caSJens Axboe } 23954257c8caSJens Axboe if (err < 0) 23964257c8caSJens Axboe return err; 23974257c8caSJens Axboe 23984257c8caSJens Axboe return 0; 23994257c8caSJens Axboe } 24004257c8caSJens Axboe 24014257c8caSJens Axboe static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg, 24024257c8caSJens Axboe struct msghdr *msg_sys, unsigned int flags, 24034257c8caSJens Axboe struct used_address *used_address, 24044257c8caSJens Axboe unsigned int allowed_msghdr_flags) 24054257c8caSJens Axboe { 24064257c8caSJens Axboe struct sockaddr_storage address; 24074257c8caSJens Axboe struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; 24084257c8caSJens Axboe ssize_t err; 24094257c8caSJens Axboe 24104257c8caSJens Axboe msg_sys->msg_name = &address; 24114257c8caSJens Axboe 24124257c8caSJens Axboe err = sendmsg_copy_msghdr(msg_sys, msg, flags, &iov); 24134257c8caSJens Axboe if (err < 0) 24144257c8caSJens Axboe return err; 24154257c8caSJens Axboe 24164257c8caSJens Axboe err = ____sys_sendmsg(sock, msg_sys, flags, used_address, 24174257c8caSJens Axboe allowed_msghdr_flags); 2418a74e9106SEric Dumazet kfree(iov); 2419228e548eSAnton Blanchard return err; 2420228e548eSAnton Blanchard } 2421228e548eSAnton Blanchard 2422228e548eSAnton Blanchard /* 2423228e548eSAnton Blanchard * BSD sendmsg interface 2424228e548eSAnton Blanchard */ 242503b1230cSJens Axboe long __sys_sendmsg_sock(struct socket *sock, struct msghdr *msg, 24260fa03c62SJens Axboe unsigned int flags) 24270fa03c62SJens Axboe { 2428d69e0779SJens Axboe /* disallow ancillary data requests from this path */ 242903b1230cSJens Axboe if (msg->msg_control || msg->msg_controllen) 243003b1230cSJens Axboe return -EINVAL; 2431d69e0779SJens Axboe 243203b1230cSJens Axboe return ____sys_sendmsg(sock, msg, flags, NULL, 0); 24330fa03c62SJens Axboe } 2434228e548eSAnton Blanchard 2435e1834a32SDominik Brodowski long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags, 2436e1834a32SDominik Brodowski bool forbid_cmsg_compat) 2437228e548eSAnton Blanchard { 2438228e548eSAnton Blanchard int fput_needed, err; 2439228e548eSAnton Blanchard struct msghdr msg_sys; 24401be374a0SAndy Lutomirski struct socket *sock; 2441228e548eSAnton Blanchard 2442e1834a32SDominik Brodowski if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT)) 2443e1834a32SDominik Brodowski return -EINVAL; 2444e1834a32SDominik Brodowski 24451be374a0SAndy Lutomirski sock = sockfd_lookup_light(fd, &err, &fput_needed); 2446228e548eSAnton Blanchard if (!sock) 2447228e548eSAnton Blanchard goto out; 2448228e548eSAnton Blanchard 244928a94d8fSTom Herbert err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0); 2450228e548eSAnton Blanchard 24516cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 24521da177e4SLinus Torvalds out: 24531da177e4SLinus Torvalds return err; 24541da177e4SLinus Torvalds } 24551da177e4SLinus Torvalds 2456666547ffSAl Viro SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags) 2457a7526eb5SAndy Lutomirski { 2458e1834a32SDominik Brodowski return __sys_sendmsg(fd, msg, flags, true); 2459a7526eb5SAndy Lutomirski } 2460a7526eb5SAndy Lutomirski 2461228e548eSAnton Blanchard /* 2462228e548eSAnton Blanchard * Linux sendmmsg interface 2463228e548eSAnton Blanchard */ 2464228e548eSAnton Blanchard 2465228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, 2466e1834a32SDominik Brodowski unsigned int flags, bool forbid_cmsg_compat) 2467228e548eSAnton Blanchard { 2468228e548eSAnton Blanchard int fput_needed, err, datagrams; 2469228e548eSAnton Blanchard struct socket *sock; 2470228e548eSAnton Blanchard struct mmsghdr __user *entry; 2471228e548eSAnton Blanchard struct compat_mmsghdr __user *compat_entry; 2472228e548eSAnton Blanchard struct msghdr msg_sys; 2473c71d8ebeSTetsuo Handa struct used_address used_address; 2474f092276dSTom Herbert unsigned int oflags = flags; 2475228e548eSAnton Blanchard 2476e1834a32SDominik Brodowski if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT)) 2477e1834a32SDominik Brodowski return -EINVAL; 2478e1834a32SDominik Brodowski 247998382f41SAnton Blanchard if (vlen > UIO_MAXIOV) 248098382f41SAnton Blanchard vlen = UIO_MAXIOV; 2481228e548eSAnton Blanchard 2482228e548eSAnton Blanchard datagrams = 0; 2483228e548eSAnton Blanchard 2484228e548eSAnton Blanchard sock = sockfd_lookup_light(fd, &err, &fput_needed); 2485228e548eSAnton Blanchard if (!sock) 2486228e548eSAnton Blanchard return err; 2487228e548eSAnton Blanchard 2488c71d8ebeSTetsuo Handa used_address.name_len = UINT_MAX; 2489228e548eSAnton Blanchard entry = mmsg; 2490228e548eSAnton Blanchard compat_entry = (struct compat_mmsghdr __user *)mmsg; 2491728ffb86SAnton Blanchard err = 0; 2492f092276dSTom Herbert flags |= MSG_BATCH; 2493228e548eSAnton Blanchard 2494228e548eSAnton Blanchard while (datagrams < vlen) { 2495f092276dSTom Herbert if (datagrams == vlen - 1) 2496f092276dSTom Herbert flags = oflags; 2497f092276dSTom Herbert 2498228e548eSAnton Blanchard if (MSG_CMSG_COMPAT & flags) { 2499666547ffSAl Viro err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry, 250028a94d8fSTom Herbert &msg_sys, flags, &used_address, MSG_EOR); 2501228e548eSAnton Blanchard if (err < 0) 2502228e548eSAnton Blanchard break; 2503228e548eSAnton Blanchard err = __put_user(err, &compat_entry->msg_len); 2504228e548eSAnton Blanchard ++compat_entry; 2505228e548eSAnton Blanchard } else { 2506a7526eb5SAndy Lutomirski err = ___sys_sendmsg(sock, 2507666547ffSAl Viro (struct user_msghdr __user *)entry, 250828a94d8fSTom Herbert &msg_sys, flags, &used_address, MSG_EOR); 2509228e548eSAnton Blanchard if (err < 0) 2510228e548eSAnton Blanchard break; 2511228e548eSAnton Blanchard err = put_user(err, &entry->msg_len); 2512228e548eSAnton Blanchard ++entry; 2513228e548eSAnton Blanchard } 2514228e548eSAnton Blanchard 2515228e548eSAnton Blanchard if (err) 2516228e548eSAnton Blanchard break; 2517228e548eSAnton Blanchard ++datagrams; 25183023898bSSoheil Hassas Yeganeh if (msg_data_left(&msg_sys)) 25193023898bSSoheil Hassas Yeganeh break; 2520a78cb84cSEric Dumazet cond_resched(); 2521228e548eSAnton Blanchard } 2522228e548eSAnton Blanchard 2523228e548eSAnton Blanchard fput_light(sock->file, fput_needed); 2524228e548eSAnton Blanchard 2525728ffb86SAnton Blanchard /* We only return an error if no datagrams were able to be sent */ 2526728ffb86SAnton Blanchard if (datagrams != 0) 2527228e548eSAnton Blanchard return datagrams; 2528228e548eSAnton Blanchard 2529228e548eSAnton Blanchard return err; 2530228e548eSAnton Blanchard } 2531228e548eSAnton Blanchard 2532228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, 2533228e548eSAnton Blanchard unsigned int, vlen, unsigned int, flags) 2534228e548eSAnton Blanchard { 2535e1834a32SDominik Brodowski return __sys_sendmmsg(fd, mmsg, vlen, flags, true); 2536228e548eSAnton Blanchard } 2537228e548eSAnton Blanchard 253803b1230cSJens Axboe int recvmsg_copy_msghdr(struct msghdr *msg, 25394257c8caSJens Axboe struct user_msghdr __user *umsg, unsigned flags, 25404257c8caSJens Axboe struct sockaddr __user **uaddr, 25414257c8caSJens Axboe struct iovec **iov) 25424257c8caSJens Axboe { 25434257c8caSJens Axboe ssize_t err; 25444257c8caSJens Axboe 25454257c8caSJens Axboe if (MSG_CMSG_COMPAT & flags) { 25464257c8caSJens Axboe struct compat_msghdr __user *msg_compat; 25474257c8caSJens Axboe 25484257c8caSJens Axboe msg_compat = (struct compat_msghdr __user *) umsg; 25494257c8caSJens Axboe err = get_compat_msghdr(msg, msg_compat, uaddr, iov); 25504257c8caSJens Axboe } else { 25514257c8caSJens Axboe err = copy_msghdr_from_user(msg, umsg, uaddr, iov); 25524257c8caSJens Axboe } 25534257c8caSJens Axboe if (err < 0) 25544257c8caSJens Axboe return err; 25554257c8caSJens Axboe 25564257c8caSJens Axboe return 0; 25574257c8caSJens Axboe } 25584257c8caSJens Axboe 25594257c8caSJens Axboe static int ____sys_recvmsg(struct socket *sock, struct msghdr *msg_sys, 25604257c8caSJens Axboe struct user_msghdr __user *msg, 25614257c8caSJens Axboe struct sockaddr __user *uaddr, 25624257c8caSJens Axboe unsigned int flags, int nosec) 25631da177e4SLinus Torvalds { 256489bddce5SStephen Hemminger struct compat_msghdr __user *msg_compat = 256589bddce5SStephen Hemminger (struct compat_msghdr __user *) msg; 25664257c8caSJens Axboe int __user *uaddr_len = COMPAT_NAMELEN(msg); 25674257c8caSJens Axboe struct sockaddr_storage addr; 25681da177e4SLinus Torvalds unsigned long cmsg_ptr; 25692da62906SAl Viro int len; 257008adb7daSAl Viro ssize_t err; 25711da177e4SLinus Torvalds 257208adb7daSAl Viro msg_sys->msg_name = &addr; 2573a2e27255SArnaldo Carvalho de Melo cmsg_ptr = (unsigned long)msg_sys->msg_control; 2574a2e27255SArnaldo Carvalho de Melo msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); 25751da177e4SLinus Torvalds 2576f3d33426SHannes Frederic Sowa /* We assume all kernel code knows the size of sockaddr_storage */ 2577f3d33426SHannes Frederic Sowa msg_sys->msg_namelen = 0; 2578f3d33426SHannes Frederic Sowa 25791da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 25801da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 25811af66221SEric Dumazet 25821af66221SEric Dumazet if (unlikely(nosec)) 25831af66221SEric Dumazet err = sock_recvmsg_nosec(sock, msg_sys, flags); 25841af66221SEric Dumazet else 25851af66221SEric Dumazet err = sock_recvmsg(sock, msg_sys, flags); 25861af66221SEric Dumazet 25871da177e4SLinus Torvalds if (err < 0) 25884257c8caSJens Axboe goto out; 25891da177e4SLinus Torvalds len = err; 25901da177e4SLinus Torvalds 25911da177e4SLinus Torvalds if (uaddr != NULL) { 259243db362dSMaciej Żenczykowski err = move_addr_to_user(&addr, 2593a2e27255SArnaldo Carvalho de Melo msg_sys->msg_namelen, uaddr, 259489bddce5SStephen Hemminger uaddr_len); 25951da177e4SLinus Torvalds if (err < 0) 25964257c8caSJens Axboe goto out; 25971da177e4SLinus Torvalds } 2598a2e27255SArnaldo Carvalho de Melo err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT), 259937f7f421SDavid S. Miller COMPAT_FLAGS(msg)); 26001da177e4SLinus Torvalds if (err) 26014257c8caSJens Axboe goto out; 26021da177e4SLinus Torvalds if (MSG_CMSG_COMPAT & flags) 2603a2e27255SArnaldo Carvalho de Melo err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr, 26041da177e4SLinus Torvalds &msg_compat->msg_controllen); 26051da177e4SLinus Torvalds else 2606a2e27255SArnaldo Carvalho de Melo err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr, 26071da177e4SLinus Torvalds &msg->msg_controllen); 26081da177e4SLinus Torvalds if (err) 26094257c8caSJens Axboe goto out; 26101da177e4SLinus Torvalds err = len; 26114257c8caSJens Axboe out: 26124257c8caSJens Axboe return err; 26134257c8caSJens Axboe } 26141da177e4SLinus Torvalds 26154257c8caSJens Axboe static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg, 26164257c8caSJens Axboe struct msghdr *msg_sys, unsigned int flags, int nosec) 26174257c8caSJens Axboe { 26184257c8caSJens Axboe struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; 26194257c8caSJens Axboe /* user mode address pointers */ 26204257c8caSJens Axboe struct sockaddr __user *uaddr; 26214257c8caSJens Axboe ssize_t err; 26224257c8caSJens Axboe 26234257c8caSJens Axboe err = recvmsg_copy_msghdr(msg_sys, msg, flags, &uaddr, &iov); 26244257c8caSJens Axboe if (err < 0) 26254257c8caSJens Axboe return err; 26264257c8caSJens Axboe 26274257c8caSJens Axboe err = ____sys_recvmsg(sock, msg_sys, msg, uaddr, flags, nosec); 2628a74e9106SEric Dumazet kfree(iov); 2629a2e27255SArnaldo Carvalho de Melo return err; 2630a2e27255SArnaldo Carvalho de Melo } 2631a2e27255SArnaldo Carvalho de Melo 2632a2e27255SArnaldo Carvalho de Melo /* 2633a2e27255SArnaldo Carvalho de Melo * BSD recvmsg interface 2634a2e27255SArnaldo Carvalho de Melo */ 2635a2e27255SArnaldo Carvalho de Melo 263603b1230cSJens Axboe long __sys_recvmsg_sock(struct socket *sock, struct msghdr *msg, 263703b1230cSJens Axboe struct user_msghdr __user *umsg, 263803b1230cSJens Axboe struct sockaddr __user *uaddr, unsigned int flags) 2639aa1fa28fSJens Axboe { 2640d69e0779SJens Axboe /* disallow ancillary data requests from this path */ 264103b1230cSJens Axboe if (msg->msg_control || msg->msg_controllen) 264203b1230cSJens Axboe return -EINVAL; 2643d69e0779SJens Axboe 264403b1230cSJens Axboe return ____sys_recvmsg(sock, msg, umsg, uaddr, flags, 0); 2645aa1fa28fSJens Axboe } 2646aa1fa28fSJens Axboe 2647e1834a32SDominik Brodowski long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags, 2648e1834a32SDominik Brodowski bool forbid_cmsg_compat) 2649a2e27255SArnaldo Carvalho de Melo { 2650a2e27255SArnaldo Carvalho de Melo int fput_needed, err; 2651a2e27255SArnaldo Carvalho de Melo struct msghdr msg_sys; 26521be374a0SAndy Lutomirski struct socket *sock; 2653a2e27255SArnaldo Carvalho de Melo 2654e1834a32SDominik Brodowski if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT)) 2655e1834a32SDominik Brodowski return -EINVAL; 2656e1834a32SDominik Brodowski 26571be374a0SAndy Lutomirski sock = sockfd_lookup_light(fd, &err, &fput_needed); 2658a2e27255SArnaldo Carvalho de Melo if (!sock) 2659a2e27255SArnaldo Carvalho de Melo goto out; 2660a2e27255SArnaldo Carvalho de Melo 2661a7526eb5SAndy Lutomirski err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0); 2662a2e27255SArnaldo Carvalho de Melo 26636cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 26641da177e4SLinus Torvalds out: 26651da177e4SLinus Torvalds return err; 26661da177e4SLinus Torvalds } 26671da177e4SLinus Torvalds 2668666547ffSAl Viro SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg, 2669a7526eb5SAndy Lutomirski unsigned int, flags) 2670a7526eb5SAndy Lutomirski { 2671e1834a32SDominik Brodowski return __sys_recvmsg(fd, msg, flags, true); 2672a7526eb5SAndy Lutomirski } 2673a7526eb5SAndy Lutomirski 2674a2e27255SArnaldo Carvalho de Melo /* 2675a2e27255SArnaldo Carvalho de Melo * Linux recvmmsg interface 2676a2e27255SArnaldo Carvalho de Melo */ 26771da177e4SLinus Torvalds 2678e11d4284SArnd Bergmann static int do_recvmmsg(int fd, struct mmsghdr __user *mmsg, 2679e11d4284SArnd Bergmann unsigned int vlen, unsigned int flags, 2680e11d4284SArnd Bergmann struct timespec64 *timeout) 2681a2e27255SArnaldo Carvalho de Melo { 2682a2e27255SArnaldo Carvalho de Melo int fput_needed, err, datagrams; 2683a2e27255SArnaldo Carvalho de Melo struct socket *sock; 2684a2e27255SArnaldo Carvalho de Melo struct mmsghdr __user *entry; 2685d7256d0eSJean-Mickael Guerin struct compat_mmsghdr __user *compat_entry; 2686a2e27255SArnaldo Carvalho de Melo struct msghdr msg_sys; 2687766b9f92SDeepa Dinamani struct timespec64 end_time; 2688766b9f92SDeepa Dinamani struct timespec64 timeout64; 2689a2e27255SArnaldo Carvalho de Melo 2690a2e27255SArnaldo Carvalho de Melo if (timeout && 2691a2e27255SArnaldo Carvalho de Melo poll_select_set_timeout(&end_time, timeout->tv_sec, 2692a2e27255SArnaldo Carvalho de Melo timeout->tv_nsec)) 2693a2e27255SArnaldo Carvalho de Melo return -EINVAL; 2694a2e27255SArnaldo Carvalho de Melo 2695a2e27255SArnaldo Carvalho de Melo datagrams = 0; 2696a2e27255SArnaldo Carvalho de Melo 2697a2e27255SArnaldo Carvalho de Melo sock = sockfd_lookup_light(fd, &err, &fput_needed); 2698a2e27255SArnaldo Carvalho de Melo if (!sock) 2699a2e27255SArnaldo Carvalho de Melo return err; 2700a2e27255SArnaldo Carvalho de Melo 27017797dc41SSoheil Hassas Yeganeh if (likely(!(flags & MSG_ERRQUEUE))) { 2702a2e27255SArnaldo Carvalho de Melo err = sock_error(sock->sk); 2703e623a9e9SMaxime Jayat if (err) { 2704e623a9e9SMaxime Jayat datagrams = err; 2705a2e27255SArnaldo Carvalho de Melo goto out_put; 2706e623a9e9SMaxime Jayat } 27077797dc41SSoheil Hassas Yeganeh } 2708a2e27255SArnaldo Carvalho de Melo 2709a2e27255SArnaldo Carvalho de Melo entry = mmsg; 2710d7256d0eSJean-Mickael Guerin compat_entry = (struct compat_mmsghdr __user *)mmsg; 2711a2e27255SArnaldo Carvalho de Melo 2712a2e27255SArnaldo Carvalho de Melo while (datagrams < vlen) { 2713a2e27255SArnaldo Carvalho de Melo /* 2714a2e27255SArnaldo Carvalho de Melo * No need to ask LSM for more than the first datagram. 2715a2e27255SArnaldo Carvalho de Melo */ 2716d7256d0eSJean-Mickael Guerin if (MSG_CMSG_COMPAT & flags) { 2717666547ffSAl Viro err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry, 2718b9eb8b87SAnton Blanchard &msg_sys, flags & ~MSG_WAITFORONE, 2719b9eb8b87SAnton Blanchard datagrams); 2720d7256d0eSJean-Mickael Guerin if (err < 0) 2721d7256d0eSJean-Mickael Guerin break; 2722d7256d0eSJean-Mickael Guerin err = __put_user(err, &compat_entry->msg_len); 2723d7256d0eSJean-Mickael Guerin ++compat_entry; 2724d7256d0eSJean-Mickael Guerin } else { 2725a7526eb5SAndy Lutomirski err = ___sys_recvmsg(sock, 2726666547ffSAl Viro (struct user_msghdr __user *)entry, 2727b9eb8b87SAnton Blanchard &msg_sys, flags & ~MSG_WAITFORONE, 2728b9eb8b87SAnton Blanchard datagrams); 2729a2e27255SArnaldo Carvalho de Melo if (err < 0) 2730a2e27255SArnaldo Carvalho de Melo break; 2731a2e27255SArnaldo Carvalho de Melo err = put_user(err, &entry->msg_len); 2732d7256d0eSJean-Mickael Guerin ++entry; 2733d7256d0eSJean-Mickael Guerin } 2734d7256d0eSJean-Mickael Guerin 2735a2e27255SArnaldo Carvalho de Melo if (err) 2736a2e27255SArnaldo Carvalho de Melo break; 2737a2e27255SArnaldo Carvalho de Melo ++datagrams; 2738a2e27255SArnaldo Carvalho de Melo 273971c5c159SBrandon L Black /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */ 274071c5c159SBrandon L Black if (flags & MSG_WAITFORONE) 274171c5c159SBrandon L Black flags |= MSG_DONTWAIT; 274271c5c159SBrandon L Black 2743a2e27255SArnaldo Carvalho de Melo if (timeout) { 2744766b9f92SDeepa Dinamani ktime_get_ts64(&timeout64); 2745c2e6c856SArnd Bergmann *timeout = timespec64_sub(end_time, timeout64); 2746a2e27255SArnaldo Carvalho de Melo if (timeout->tv_sec < 0) { 2747a2e27255SArnaldo Carvalho de Melo timeout->tv_sec = timeout->tv_nsec = 0; 2748a2e27255SArnaldo Carvalho de Melo break; 2749a2e27255SArnaldo Carvalho de Melo } 2750a2e27255SArnaldo Carvalho de Melo 2751a2e27255SArnaldo Carvalho de Melo /* Timeout, return less than vlen datagrams */ 2752a2e27255SArnaldo Carvalho de Melo if (timeout->tv_nsec == 0 && timeout->tv_sec == 0) 2753a2e27255SArnaldo Carvalho de Melo break; 2754a2e27255SArnaldo Carvalho de Melo } 2755a2e27255SArnaldo Carvalho de Melo 2756a2e27255SArnaldo Carvalho de Melo /* Out of band data, return right away */ 2757a2e27255SArnaldo Carvalho de Melo if (msg_sys.msg_flags & MSG_OOB) 2758a2e27255SArnaldo Carvalho de Melo break; 2759a78cb84cSEric Dumazet cond_resched(); 2760a2e27255SArnaldo Carvalho de Melo } 2761a2e27255SArnaldo Carvalho de Melo 2762a2e27255SArnaldo Carvalho de Melo if (err == 0) 276334b88a68SArnaldo Carvalho de Melo goto out_put; 2764a2e27255SArnaldo Carvalho de Melo 276534b88a68SArnaldo Carvalho de Melo if (datagrams == 0) { 276634b88a68SArnaldo Carvalho de Melo datagrams = err; 276734b88a68SArnaldo Carvalho de Melo goto out_put; 276834b88a68SArnaldo Carvalho de Melo } 276934b88a68SArnaldo Carvalho de Melo 2770a2e27255SArnaldo Carvalho de Melo /* 2771a2e27255SArnaldo Carvalho de Melo * We may return less entries than requested (vlen) if the 2772a2e27255SArnaldo Carvalho de Melo * sock is non block and there aren't enough datagrams... 2773a2e27255SArnaldo Carvalho de Melo */ 2774a2e27255SArnaldo Carvalho de Melo if (err != -EAGAIN) { 2775a2e27255SArnaldo Carvalho de Melo /* 2776a2e27255SArnaldo Carvalho de Melo * ... or if recvmsg returns an error after we 2777a2e27255SArnaldo Carvalho de Melo * received some datagrams, where we record the 2778a2e27255SArnaldo Carvalho de Melo * error to return on the next call or if the 2779a2e27255SArnaldo Carvalho de Melo * app asks about it using getsockopt(SO_ERROR). 2780a2e27255SArnaldo Carvalho de Melo */ 2781a2e27255SArnaldo Carvalho de Melo sock->sk->sk_err = -err; 2782a2e27255SArnaldo Carvalho de Melo } 278334b88a68SArnaldo Carvalho de Melo out_put: 278434b88a68SArnaldo Carvalho de Melo fput_light(sock->file, fput_needed); 2785a2e27255SArnaldo Carvalho de Melo 2786a2e27255SArnaldo Carvalho de Melo return datagrams; 2787a2e27255SArnaldo Carvalho de Melo } 2788a2e27255SArnaldo Carvalho de Melo 2789e11d4284SArnd Bergmann int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, 27901255e269SDominik Brodowski unsigned int vlen, unsigned int flags, 2791e11d4284SArnd Bergmann struct __kernel_timespec __user *timeout, 2792e11d4284SArnd Bergmann struct old_timespec32 __user *timeout32) 2793a2e27255SArnaldo Carvalho de Melo { 2794a2e27255SArnaldo Carvalho de Melo int datagrams; 2795c2e6c856SArnd Bergmann struct timespec64 timeout_sys; 2796a2e27255SArnaldo Carvalho de Melo 2797e11d4284SArnd Bergmann if (timeout && get_timespec64(&timeout_sys, timeout)) 2798a2e27255SArnaldo Carvalho de Melo return -EFAULT; 2799a2e27255SArnaldo Carvalho de Melo 2800e11d4284SArnd Bergmann if (timeout32 && get_old_timespec32(&timeout_sys, timeout32)) 2801e11d4284SArnd Bergmann return -EFAULT; 2802a2e27255SArnaldo Carvalho de Melo 2803e11d4284SArnd Bergmann if (!timeout && !timeout32) 2804e11d4284SArnd Bergmann return do_recvmmsg(fd, mmsg, vlen, flags, NULL); 2805e11d4284SArnd Bergmann 2806e11d4284SArnd Bergmann datagrams = do_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys); 2807e11d4284SArnd Bergmann 2808e11d4284SArnd Bergmann if (datagrams <= 0) 2809e11d4284SArnd Bergmann return datagrams; 2810e11d4284SArnd Bergmann 2811e11d4284SArnd Bergmann if (timeout && put_timespec64(&timeout_sys, timeout)) 2812e11d4284SArnd Bergmann datagrams = -EFAULT; 2813e11d4284SArnd Bergmann 2814e11d4284SArnd Bergmann if (timeout32 && put_old_timespec32(&timeout_sys, timeout32)) 2815a2e27255SArnaldo Carvalho de Melo datagrams = -EFAULT; 2816a2e27255SArnaldo Carvalho de Melo 2817a2e27255SArnaldo Carvalho de Melo return datagrams; 2818a2e27255SArnaldo Carvalho de Melo } 2819a2e27255SArnaldo Carvalho de Melo 28201255e269SDominik Brodowski SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, 28211255e269SDominik Brodowski unsigned int, vlen, unsigned int, flags, 2822c2e6c856SArnd Bergmann struct __kernel_timespec __user *, timeout) 28231255e269SDominik Brodowski { 2824e11d4284SArnd Bergmann if (flags & MSG_CMSG_COMPAT) 2825e11d4284SArnd Bergmann return -EINVAL; 2826e11d4284SArnd Bergmann 2827e11d4284SArnd Bergmann return __sys_recvmmsg(fd, mmsg, vlen, flags, timeout, NULL); 28281255e269SDominik Brodowski } 28291255e269SDominik Brodowski 2830e11d4284SArnd Bergmann #ifdef CONFIG_COMPAT_32BIT_TIME 2831e11d4284SArnd Bergmann SYSCALL_DEFINE5(recvmmsg_time32, int, fd, struct mmsghdr __user *, mmsg, 2832e11d4284SArnd Bergmann unsigned int, vlen, unsigned int, flags, 2833e11d4284SArnd Bergmann struct old_timespec32 __user *, timeout) 2834e11d4284SArnd Bergmann { 2835e11d4284SArnd Bergmann if (flags & MSG_CMSG_COMPAT) 2836e11d4284SArnd Bergmann return -EINVAL; 2837e11d4284SArnd Bergmann 2838e11d4284SArnd Bergmann return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL, timeout); 2839e11d4284SArnd Bergmann } 2840e11d4284SArnd Bergmann #endif 2841e11d4284SArnd Bergmann 2842a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL 28431da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */ 28441da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long)) 2845228e548eSAnton Blanchard static const unsigned char nargs[21] = { 284689bddce5SStephen Hemminger AL(0), AL(3), AL(3), AL(3), AL(2), AL(3), 28471da177e4SLinus Torvalds AL(3), AL(3), AL(4), AL(4), AL(4), AL(6), 2848aaca0bdcSUlrich Drepper AL(6), AL(2), AL(5), AL(5), AL(3), AL(3), 2849228e548eSAnton Blanchard AL(4), AL(5), AL(4) 285089bddce5SStephen Hemminger }; 285189bddce5SStephen Hemminger 28521da177e4SLinus Torvalds #undef AL 28531da177e4SLinus Torvalds 28541da177e4SLinus Torvalds /* 28551da177e4SLinus Torvalds * System call vectors. 28561da177e4SLinus Torvalds * 28571da177e4SLinus Torvalds * Argument checking cleaned up. Saved 20% in size. 28581da177e4SLinus Torvalds * This function doesn't need to set the kernel lock because 28591da177e4SLinus Torvalds * it is set by the callees. 28601da177e4SLinus Torvalds */ 28611da177e4SLinus Torvalds 28623e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) 28631da177e4SLinus Torvalds { 28642950fa9dSChen Gang unsigned long a[AUDITSC_ARGS]; 28651da177e4SLinus Torvalds unsigned long a0, a1; 28661da177e4SLinus Torvalds int err; 286747379052SArjan van de Ven unsigned int len; 28681da177e4SLinus Torvalds 2869228e548eSAnton Blanchard if (call < 1 || call > SYS_SENDMMSG) 28701da177e4SLinus Torvalds return -EINVAL; 2871c8e8cd57SJeremy Cline call = array_index_nospec(call, SYS_SENDMMSG + 1); 28721da177e4SLinus Torvalds 287347379052SArjan van de Ven len = nargs[call]; 287447379052SArjan van de Ven if (len > sizeof(a)) 287547379052SArjan van de Ven return -EINVAL; 287647379052SArjan van de Ven 28771da177e4SLinus Torvalds /* copy_from_user should be SMP safe. */ 287847379052SArjan van de Ven if (copy_from_user(a, args, len)) 28791da177e4SLinus Torvalds return -EFAULT; 28801da177e4SLinus Torvalds 28812950fa9dSChen Gang err = audit_socketcall(nargs[call] / sizeof(unsigned long), a); 28822950fa9dSChen Gang if (err) 28832950fa9dSChen Gang return err; 28843ec3b2fbSDavid Woodhouse 28851da177e4SLinus Torvalds a0 = a[0]; 28861da177e4SLinus Torvalds a1 = a[1]; 28871da177e4SLinus Torvalds 288889bddce5SStephen Hemminger switch (call) { 28891da177e4SLinus Torvalds case SYS_SOCKET: 28909d6a15c3SDominik Brodowski err = __sys_socket(a0, a1, a[2]); 28911da177e4SLinus Torvalds break; 28921da177e4SLinus Torvalds case SYS_BIND: 2893a87d35d8SDominik Brodowski err = __sys_bind(a0, (struct sockaddr __user *)a1, a[2]); 28941da177e4SLinus Torvalds break; 28951da177e4SLinus Torvalds case SYS_CONNECT: 28961387c2c2SDominik Brodowski err = __sys_connect(a0, (struct sockaddr __user *)a1, a[2]); 28971da177e4SLinus Torvalds break; 28981da177e4SLinus Torvalds case SYS_LISTEN: 289925e290eeSDominik Brodowski err = __sys_listen(a0, a1); 29001da177e4SLinus Torvalds break; 29011da177e4SLinus Torvalds case SYS_ACCEPT: 29024541e805SDominik Brodowski err = __sys_accept4(a0, (struct sockaddr __user *)a1, 2903aaca0bdcSUlrich Drepper (int __user *)a[2], 0); 29041da177e4SLinus Torvalds break; 29051da177e4SLinus Torvalds case SYS_GETSOCKNAME: 290689bddce5SStephen Hemminger err = 29078882a107SDominik Brodowski __sys_getsockname(a0, (struct sockaddr __user *)a1, 290889bddce5SStephen Hemminger (int __user *)a[2]); 29091da177e4SLinus Torvalds break; 29101da177e4SLinus Torvalds case SYS_GETPEERNAME: 291189bddce5SStephen Hemminger err = 2912b21c8f83SDominik Brodowski __sys_getpeername(a0, (struct sockaddr __user *)a1, 291389bddce5SStephen Hemminger (int __user *)a[2]); 29141da177e4SLinus Torvalds break; 29151da177e4SLinus Torvalds case SYS_SOCKETPAIR: 29166debc8d8SDominik Brodowski err = __sys_socketpair(a0, a1, a[2], (int __user *)a[3]); 29171da177e4SLinus Torvalds break; 29181da177e4SLinus Torvalds case SYS_SEND: 2919f3bf896bSDominik Brodowski err = __sys_sendto(a0, (void __user *)a1, a[2], a[3], 2920f3bf896bSDominik Brodowski NULL, 0); 29211da177e4SLinus Torvalds break; 29221da177e4SLinus Torvalds case SYS_SENDTO: 2923211b634bSDominik Brodowski err = __sys_sendto(a0, (void __user *)a1, a[2], a[3], 29241da177e4SLinus Torvalds (struct sockaddr __user *)a[4], a[5]); 29251da177e4SLinus Torvalds break; 29261da177e4SLinus Torvalds case SYS_RECV: 2927d27e9afcSDominik Brodowski err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3], 2928d27e9afcSDominik Brodowski NULL, NULL); 29291da177e4SLinus Torvalds break; 29301da177e4SLinus Torvalds case SYS_RECVFROM: 29317a09e1ebSDominik Brodowski err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3], 293289bddce5SStephen Hemminger (struct sockaddr __user *)a[4], 293389bddce5SStephen Hemminger (int __user *)a[5]); 29341da177e4SLinus Torvalds break; 29351da177e4SLinus Torvalds case SYS_SHUTDOWN: 2936005a1aeaSDominik Brodowski err = __sys_shutdown(a0, a1); 29371da177e4SLinus Torvalds break; 29381da177e4SLinus Torvalds case SYS_SETSOCKOPT: 2939cc36dca0SDominik Brodowski err = __sys_setsockopt(a0, a1, a[2], (char __user *)a[3], 2940cc36dca0SDominik Brodowski a[4]); 29411da177e4SLinus Torvalds break; 29421da177e4SLinus Torvalds case SYS_GETSOCKOPT: 294389bddce5SStephen Hemminger err = 294413a2d70eSDominik Brodowski __sys_getsockopt(a0, a1, a[2], (char __user *)a[3], 294589bddce5SStephen Hemminger (int __user *)a[4]); 29461da177e4SLinus Torvalds break; 29471da177e4SLinus Torvalds case SYS_SENDMSG: 2948e1834a32SDominik Brodowski err = __sys_sendmsg(a0, (struct user_msghdr __user *)a1, 2949e1834a32SDominik Brodowski a[2], true); 29501da177e4SLinus Torvalds break; 2951228e548eSAnton Blanchard case SYS_SENDMMSG: 2952e1834a32SDominik Brodowski err = __sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], 2953e1834a32SDominik Brodowski a[3], true); 2954228e548eSAnton Blanchard break; 29551da177e4SLinus Torvalds case SYS_RECVMSG: 2956e1834a32SDominik Brodowski err = __sys_recvmsg(a0, (struct user_msghdr __user *)a1, 2957e1834a32SDominik Brodowski a[2], true); 29581da177e4SLinus Torvalds break; 2959a2e27255SArnaldo Carvalho de Melo case SYS_RECVMMSG: 29603ca47e95SArnd Bergmann if (IS_ENABLED(CONFIG_64BIT)) 2961e11d4284SArnd Bergmann err = __sys_recvmmsg(a0, (struct mmsghdr __user *)a1, 2962e11d4284SArnd Bergmann a[2], a[3], 2963e11d4284SArnd Bergmann (struct __kernel_timespec __user *)a[4], 2964e11d4284SArnd Bergmann NULL); 2965e11d4284SArnd Bergmann else 2966e11d4284SArnd Bergmann err = __sys_recvmmsg(a0, (struct mmsghdr __user *)a1, 2967e11d4284SArnd Bergmann a[2], a[3], NULL, 2968e11d4284SArnd Bergmann (struct old_timespec32 __user *)a[4]); 2969a2e27255SArnaldo Carvalho de Melo break; 2970de11defeSUlrich Drepper case SYS_ACCEPT4: 29714541e805SDominik Brodowski err = __sys_accept4(a0, (struct sockaddr __user *)a1, 2972de11defeSUlrich Drepper (int __user *)a[2], a[3]); 2973aaca0bdcSUlrich Drepper break; 29741da177e4SLinus Torvalds default: 29751da177e4SLinus Torvalds err = -EINVAL; 29761da177e4SLinus Torvalds break; 29771da177e4SLinus Torvalds } 29781da177e4SLinus Torvalds return err; 29791da177e4SLinus Torvalds } 29801da177e4SLinus Torvalds 29811da177e4SLinus Torvalds #endif /* __ARCH_WANT_SYS_SOCKETCALL */ 29821da177e4SLinus Torvalds 298355737fdaSStephen Hemminger /** 298455737fdaSStephen Hemminger * sock_register - add a socket protocol handler 298555737fdaSStephen Hemminger * @ops: description of protocol 298655737fdaSStephen Hemminger * 29871da177e4SLinus Torvalds * This function is called by a protocol handler that wants to 29881da177e4SLinus Torvalds * advertise its address family, and have it linked into the 2989e793c0f7SMasanari Iida * socket interface. The value ops->family corresponds to the 299055737fdaSStephen Hemminger * socket system call protocol family. 29911da177e4SLinus Torvalds */ 2992f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops) 29931da177e4SLinus Torvalds { 29941da177e4SLinus Torvalds int err; 29951da177e4SLinus Torvalds 29961da177e4SLinus Torvalds if (ops->family >= NPROTO) { 29973410f22eSYang Yingliang pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO); 29981da177e4SLinus Torvalds return -ENOBUFS; 29991da177e4SLinus Torvalds } 300055737fdaSStephen Hemminger 300155737fdaSStephen Hemminger spin_lock(&net_family_lock); 3002190683a9SEric Dumazet if (rcu_dereference_protected(net_families[ops->family], 3003190683a9SEric Dumazet lockdep_is_held(&net_family_lock))) 30041da177e4SLinus Torvalds err = -EEXIST; 300555737fdaSStephen Hemminger else { 3006cf778b00SEric Dumazet rcu_assign_pointer(net_families[ops->family], ops); 30071da177e4SLinus Torvalds err = 0; 30081da177e4SLinus Torvalds } 300955737fdaSStephen Hemminger spin_unlock(&net_family_lock); 301055737fdaSStephen Hemminger 30113410f22eSYang Yingliang pr_info("NET: Registered protocol family %d\n", ops->family); 30121da177e4SLinus Torvalds return err; 30131da177e4SLinus Torvalds } 3014c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register); 30151da177e4SLinus Torvalds 301655737fdaSStephen Hemminger /** 301755737fdaSStephen Hemminger * sock_unregister - remove a protocol handler 301855737fdaSStephen Hemminger * @family: protocol family to remove 301955737fdaSStephen Hemminger * 30201da177e4SLinus Torvalds * This function is called by a protocol handler that wants to 30211da177e4SLinus Torvalds * remove its address family, and have it unlinked from the 302255737fdaSStephen Hemminger * new socket creation. 302355737fdaSStephen Hemminger * 302455737fdaSStephen Hemminger * If protocol handler is a module, then it can use module reference 302555737fdaSStephen Hemminger * counts to protect against new references. If protocol handler is not 302655737fdaSStephen Hemminger * a module then it needs to provide its own protection in 302755737fdaSStephen Hemminger * the ops->create routine. 30281da177e4SLinus Torvalds */ 3029f0fd27d4SStephen Hemminger void sock_unregister(int family) 30301da177e4SLinus Torvalds { 3031f0fd27d4SStephen Hemminger BUG_ON(family < 0 || family >= NPROTO); 30321da177e4SLinus Torvalds 303355737fdaSStephen Hemminger spin_lock(&net_family_lock); 3034a9b3cd7fSStephen Hemminger RCU_INIT_POINTER(net_families[family], NULL); 303555737fdaSStephen Hemminger spin_unlock(&net_family_lock); 303655737fdaSStephen Hemminger 303755737fdaSStephen Hemminger synchronize_rcu(); 303855737fdaSStephen Hemminger 30393410f22eSYang Yingliang pr_info("NET: Unregistered protocol family %d\n", family); 30401da177e4SLinus Torvalds } 3041c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister); 30421da177e4SLinus Torvalds 3043bf2ae2e4SXin Long bool sock_is_registered(int family) 3044bf2ae2e4SXin Long { 304566b51b0aSJeremy Cline return family < NPROTO && rcu_access_pointer(net_families[family]); 3046bf2ae2e4SXin Long } 3047bf2ae2e4SXin Long 304877d76ea3SAndi Kleen static int __init sock_init(void) 30491da177e4SLinus Torvalds { 3050b3e19d92SNick Piggin int err; 30512ca794e5SEric W. Biederman /* 30522ca794e5SEric W. Biederman * Initialize the network sysctl infrastructure. 30532ca794e5SEric W. Biederman */ 30542ca794e5SEric W. Biederman err = net_sysctl_init(); 30552ca794e5SEric W. Biederman if (err) 30562ca794e5SEric W. Biederman goto out; 3057b3e19d92SNick Piggin 30581da177e4SLinus Torvalds /* 30591da177e4SLinus Torvalds * Initialize skbuff SLAB cache 30601da177e4SLinus Torvalds */ 30611da177e4SLinus Torvalds skb_init(); 30621da177e4SLinus Torvalds 30631da177e4SLinus Torvalds /* 30641da177e4SLinus Torvalds * Initialize the protocols module. 30651da177e4SLinus Torvalds */ 30661da177e4SLinus Torvalds 30671da177e4SLinus Torvalds init_inodecache(); 3068b3e19d92SNick Piggin 3069b3e19d92SNick Piggin err = register_filesystem(&sock_fs_type); 3070b3e19d92SNick Piggin if (err) 3071b3e19d92SNick Piggin goto out_fs; 30721da177e4SLinus Torvalds sock_mnt = kern_mount(&sock_fs_type); 3073b3e19d92SNick Piggin if (IS_ERR(sock_mnt)) { 3074b3e19d92SNick Piggin err = PTR_ERR(sock_mnt); 3075b3e19d92SNick Piggin goto out_mount; 3076b3e19d92SNick Piggin } 307777d76ea3SAndi Kleen 307877d76ea3SAndi Kleen /* The real protocol initialization is performed in later initcalls. 30791da177e4SLinus Torvalds */ 30801da177e4SLinus Torvalds 30811da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER 30826d11cfdbSPablo Neira Ayuso err = netfilter_init(); 30836d11cfdbSPablo Neira Ayuso if (err) 30846d11cfdbSPablo Neira Ayuso goto out; 30851da177e4SLinus Torvalds #endif 3086cbeb321aSDavid S. Miller 3087408eccceSDaniel Borkmann ptp_classifier_init(); 3088c1f19b51SRichard Cochran 3089b3e19d92SNick Piggin out: 3090b3e19d92SNick Piggin return err; 3091b3e19d92SNick Piggin 3092b3e19d92SNick Piggin out_mount: 3093b3e19d92SNick Piggin unregister_filesystem(&sock_fs_type); 3094b3e19d92SNick Piggin out_fs: 3095b3e19d92SNick Piggin goto out; 30961da177e4SLinus Torvalds } 30971da177e4SLinus Torvalds 309877d76ea3SAndi Kleen core_initcall(sock_init); /* early initcall */ 309977d76ea3SAndi Kleen 31001da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS 31011da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq) 31021da177e4SLinus Torvalds { 3103648845abSTonghao Zhang seq_printf(seq, "sockets: used %d\n", 3104648845abSTonghao Zhang sock_inuse_get(seq->private)); 31051da177e4SLinus Torvalds } 31061da177e4SLinus Torvalds #endif /* CONFIG_PROC_FS */ 31071da177e4SLinus Torvalds 310889bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 310936fd633eSAl Viro static int compat_dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) 31107a229387SArnd Bergmann { 31116b96018bSArnd Bergmann struct compat_ifconf ifc32; 31127a229387SArnd Bergmann struct ifconf ifc; 31137a229387SArnd Bergmann int err; 31147a229387SArnd Bergmann 31156b96018bSArnd Bergmann if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf))) 31167a229387SArnd Bergmann return -EFAULT; 31177a229387SArnd Bergmann 311836fd633eSAl Viro ifc.ifc_len = ifc32.ifc_len; 311936fd633eSAl Viro ifc.ifc_req = compat_ptr(ifc32.ifcbuf); 31207a229387SArnd Bergmann 312136fd633eSAl Viro rtnl_lock(); 312236fd633eSAl Viro err = dev_ifconf(net, &ifc, sizeof(struct compat_ifreq)); 312336fd633eSAl Viro rtnl_unlock(); 31247a229387SArnd Bergmann if (err) 31257a229387SArnd Bergmann return err; 31267a229387SArnd Bergmann 312736fd633eSAl Viro ifc32.ifc_len = ifc.ifc_len; 31286b96018bSArnd Bergmann if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf))) 31297a229387SArnd Bergmann return -EFAULT; 31307a229387SArnd Bergmann 31317a229387SArnd Bergmann return 0; 31327a229387SArnd Bergmann } 31337a229387SArnd Bergmann 31346b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) 31357a229387SArnd Bergmann { 31363a7da39dSBen Hutchings struct compat_ethtool_rxnfc __user *compat_rxnfc; 31373a7da39dSBen Hutchings bool convert_in = false, convert_out = false; 313844c02a2cSAl Viro size_t buf_size = 0; 313944c02a2cSAl Viro struct ethtool_rxnfc __user *rxnfc = NULL; 314044c02a2cSAl Viro struct ifreq ifr; 31413a7da39dSBen Hutchings u32 rule_cnt = 0, actual_rule_cnt; 31423a7da39dSBen Hutchings u32 ethcmd; 31437a229387SArnd Bergmann u32 data; 31443a7da39dSBen Hutchings int ret; 31457a229387SArnd Bergmann 31467a229387SArnd Bergmann if (get_user(data, &ifr32->ifr_ifru.ifru_data)) 31477a229387SArnd Bergmann return -EFAULT; 31487a229387SArnd Bergmann 31493a7da39dSBen Hutchings compat_rxnfc = compat_ptr(data); 31503a7da39dSBen Hutchings 31513a7da39dSBen Hutchings if (get_user(ethcmd, &compat_rxnfc->cmd)) 31527a229387SArnd Bergmann return -EFAULT; 31537a229387SArnd Bergmann 31543a7da39dSBen Hutchings /* Most ethtool structures are defined without padding. 31553a7da39dSBen Hutchings * Unfortunately struct ethtool_rxnfc is an exception. 31563a7da39dSBen Hutchings */ 31573a7da39dSBen Hutchings switch (ethcmd) { 31583a7da39dSBen Hutchings default: 31593a7da39dSBen Hutchings break; 31603a7da39dSBen Hutchings case ETHTOOL_GRXCLSRLALL: 31613a7da39dSBen Hutchings /* Buffer size is variable */ 31623a7da39dSBen Hutchings if (get_user(rule_cnt, &compat_rxnfc->rule_cnt)) 31633a7da39dSBen Hutchings return -EFAULT; 31643a7da39dSBen Hutchings if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32)) 31653a7da39dSBen Hutchings return -ENOMEM; 31663a7da39dSBen Hutchings buf_size += rule_cnt * sizeof(u32); 31673a7da39dSBen Hutchings /* fall through */ 31683a7da39dSBen Hutchings case ETHTOOL_GRXRINGS: 31693a7da39dSBen Hutchings case ETHTOOL_GRXCLSRLCNT: 31703a7da39dSBen Hutchings case ETHTOOL_GRXCLSRULE: 317155664f32SBen Hutchings case ETHTOOL_SRXCLSRLINS: 31723a7da39dSBen Hutchings convert_out = true; 31733a7da39dSBen Hutchings /* fall through */ 31743a7da39dSBen Hutchings case ETHTOOL_SRXCLSRLDEL: 31753a7da39dSBen Hutchings buf_size += sizeof(struct ethtool_rxnfc); 31763a7da39dSBen Hutchings convert_in = true; 317744c02a2cSAl Viro rxnfc = compat_alloc_user_space(buf_size); 31783a7da39dSBen Hutchings break; 31793a7da39dSBen Hutchings } 31803a7da39dSBen Hutchings 318144c02a2cSAl Viro if (copy_from_user(&ifr.ifr_name, &ifr32->ifr_name, IFNAMSIZ)) 31823a7da39dSBen Hutchings return -EFAULT; 31833a7da39dSBen Hutchings 318444c02a2cSAl Viro ifr.ifr_data = convert_in ? rxnfc : (void __user *)compat_rxnfc; 31853a7da39dSBen Hutchings 31863a7da39dSBen Hutchings if (convert_in) { 3187127fe533SAlexander Duyck /* We expect there to be holes between fs.m_ext and 31883a7da39dSBen Hutchings * fs.ring_cookie and at the end of fs, but nowhere else. 31893a7da39dSBen Hutchings */ 3190127fe533SAlexander Duyck BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) + 3191127fe533SAlexander Duyck sizeof(compat_rxnfc->fs.m_ext) != 3192127fe533SAlexander Duyck offsetof(struct ethtool_rxnfc, fs.m_ext) + 3193127fe533SAlexander Duyck sizeof(rxnfc->fs.m_ext)); 31943a7da39dSBen Hutchings BUILD_BUG_ON( 31953a7da39dSBen Hutchings offsetof(struct compat_ethtool_rxnfc, fs.location) - 31963a7da39dSBen Hutchings offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) != 31973a7da39dSBen Hutchings offsetof(struct ethtool_rxnfc, fs.location) - 31983a7da39dSBen Hutchings offsetof(struct ethtool_rxnfc, fs.ring_cookie)); 31993a7da39dSBen Hutchings 32003a7da39dSBen Hutchings if (copy_in_user(rxnfc, compat_rxnfc, 3201954b1244SStephen Hemminger (void __user *)(&rxnfc->fs.m_ext + 1) - 3202954b1244SStephen Hemminger (void __user *)rxnfc) || 32033a7da39dSBen Hutchings copy_in_user(&rxnfc->fs.ring_cookie, 32043a7da39dSBen Hutchings &compat_rxnfc->fs.ring_cookie, 3205954b1244SStephen Hemminger (void __user *)(&rxnfc->fs.location + 1) - 3206b6168562SWenwen Wang (void __user *)&rxnfc->fs.ring_cookie)) 3207b6168562SWenwen Wang return -EFAULT; 3208b6168562SWenwen Wang if (ethcmd == ETHTOOL_GRXCLSRLALL) { 3209b6168562SWenwen Wang if (put_user(rule_cnt, &rxnfc->rule_cnt)) 3210b6168562SWenwen Wang return -EFAULT; 3211b6168562SWenwen Wang } else if (copy_in_user(&rxnfc->rule_cnt, 3212b6168562SWenwen Wang &compat_rxnfc->rule_cnt, 32133a7da39dSBen Hutchings sizeof(rxnfc->rule_cnt))) 32143a7da39dSBen Hutchings return -EFAULT; 32153a7da39dSBen Hutchings } 32163a7da39dSBen Hutchings 321744c02a2cSAl Viro ret = dev_ioctl(net, SIOCETHTOOL, &ifr, NULL); 32183a7da39dSBen Hutchings if (ret) 32193a7da39dSBen Hutchings return ret; 32203a7da39dSBen Hutchings 32213a7da39dSBen Hutchings if (convert_out) { 32223a7da39dSBen Hutchings if (copy_in_user(compat_rxnfc, rxnfc, 3223954b1244SStephen Hemminger (const void __user *)(&rxnfc->fs.m_ext + 1) - 3224954b1244SStephen Hemminger (const void __user *)rxnfc) || 32253a7da39dSBen Hutchings copy_in_user(&compat_rxnfc->fs.ring_cookie, 32263a7da39dSBen Hutchings &rxnfc->fs.ring_cookie, 3227954b1244SStephen Hemminger (const void __user *)(&rxnfc->fs.location + 1) - 3228954b1244SStephen Hemminger (const void __user *)&rxnfc->fs.ring_cookie) || 32293a7da39dSBen Hutchings copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt, 32303a7da39dSBen Hutchings sizeof(rxnfc->rule_cnt))) 32313a7da39dSBen Hutchings return -EFAULT; 32323a7da39dSBen Hutchings 32333a7da39dSBen Hutchings if (ethcmd == ETHTOOL_GRXCLSRLALL) { 32343a7da39dSBen Hutchings /* As an optimisation, we only copy the actual 32353a7da39dSBen Hutchings * number of rules that the underlying 32363a7da39dSBen Hutchings * function returned. Since Mallory might 32373a7da39dSBen Hutchings * change the rule count in user memory, we 32383a7da39dSBen Hutchings * check that it is less than the rule count 32393a7da39dSBen Hutchings * originally given (as the user buffer size), 32403a7da39dSBen Hutchings * which has been range-checked. 32413a7da39dSBen Hutchings */ 32423a7da39dSBen Hutchings if (get_user(actual_rule_cnt, &rxnfc->rule_cnt)) 32433a7da39dSBen Hutchings return -EFAULT; 32443a7da39dSBen Hutchings if (actual_rule_cnt < rule_cnt) 32453a7da39dSBen Hutchings rule_cnt = actual_rule_cnt; 32463a7da39dSBen Hutchings if (copy_in_user(&compat_rxnfc->rule_locs[0], 32473a7da39dSBen Hutchings &rxnfc->rule_locs[0], 32483a7da39dSBen Hutchings rule_cnt * sizeof(u32))) 32493a7da39dSBen Hutchings return -EFAULT; 32503a7da39dSBen Hutchings } 32513a7da39dSBen Hutchings } 32523a7da39dSBen Hutchings 32533a7da39dSBen Hutchings return 0; 32547a229387SArnd Bergmann } 32557a229387SArnd Bergmann 32567a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32) 32577a50a240SArnd Bergmann { 32587a50a240SArnd Bergmann compat_uptr_t uptr32; 325944c02a2cSAl Viro struct ifreq ifr; 326044c02a2cSAl Viro void __user *saved; 326144c02a2cSAl Viro int err; 32627a50a240SArnd Bergmann 326344c02a2cSAl Viro if (copy_from_user(&ifr, uifr32, sizeof(struct compat_ifreq))) 32647a50a240SArnd Bergmann return -EFAULT; 32657a50a240SArnd Bergmann 32667a50a240SArnd Bergmann if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu)) 32677a50a240SArnd Bergmann return -EFAULT; 32687a50a240SArnd Bergmann 326944c02a2cSAl Viro saved = ifr.ifr_settings.ifs_ifsu.raw_hdlc; 327044c02a2cSAl Viro ifr.ifr_settings.ifs_ifsu.raw_hdlc = compat_ptr(uptr32); 32717a50a240SArnd Bergmann 327244c02a2cSAl Viro err = dev_ioctl(net, SIOCWANDEV, &ifr, NULL); 327344c02a2cSAl Viro if (!err) { 327444c02a2cSAl Viro ifr.ifr_settings.ifs_ifsu.raw_hdlc = saved; 327544c02a2cSAl Viro if (copy_to_user(uifr32, &ifr, sizeof(struct compat_ifreq))) 327644c02a2cSAl Viro err = -EFAULT; 32777a50a240SArnd Bergmann } 32787a229387SArnd Bergmann return err; 32797a229387SArnd Bergmann } 32807a229387SArnd Bergmann 3281590d4693SBen Hutchings /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */ 3282590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd, 32836b96018bSArnd Bergmann struct compat_ifreq __user *u_ifreq32) 32847a229387SArnd Bergmann { 328544c02a2cSAl Viro struct ifreq ifreq; 32867a229387SArnd Bergmann u32 data32; 32877a229387SArnd Bergmann 328844c02a2cSAl Viro if (copy_from_user(ifreq.ifr_name, u_ifreq32->ifr_name, IFNAMSIZ)) 32897a229387SArnd Bergmann return -EFAULT; 329044c02a2cSAl Viro if (get_user(data32, &u_ifreq32->ifr_data)) 32917a229387SArnd Bergmann return -EFAULT; 329244c02a2cSAl Viro ifreq.ifr_data = compat_ptr(data32); 32937a229387SArnd Bergmann 329444c02a2cSAl Viro return dev_ioctl(net, cmd, &ifreq, NULL); 3295a2116ed2SArnd Bergmann } 3296a2116ed2SArnd Bergmann 329737ac39bdSJohannes Berg static int compat_ifreq_ioctl(struct net *net, struct socket *sock, 329837ac39bdSJohannes Berg unsigned int cmd, 329937ac39bdSJohannes Berg struct compat_ifreq __user *uifr32) 330037ac39bdSJohannes Berg { 330137ac39bdSJohannes Berg struct ifreq __user *uifr; 330237ac39bdSJohannes Berg int err; 330337ac39bdSJohannes Berg 330437ac39bdSJohannes Berg /* Handle the fact that while struct ifreq has the same *layout* on 330537ac39bdSJohannes Berg * 32/64 for everything but ifreq::ifru_ifmap and ifreq::ifru_data, 330637ac39bdSJohannes Berg * which are handled elsewhere, it still has different *size* due to 330737ac39bdSJohannes Berg * ifreq::ifru_ifmap (which is 16 bytes on 32 bit, 24 bytes on 64-bit, 330837ac39bdSJohannes Berg * resulting in struct ifreq being 32 and 40 bytes respectively). 330937ac39bdSJohannes Berg * As a result, if the struct happens to be at the end of a page and 331037ac39bdSJohannes Berg * the next page isn't readable/writable, we get a fault. To prevent 331137ac39bdSJohannes Berg * that, copy back and forth to the full size. 331237ac39bdSJohannes Berg */ 331337ac39bdSJohannes Berg 331437ac39bdSJohannes Berg uifr = compat_alloc_user_space(sizeof(*uifr)); 331537ac39bdSJohannes Berg if (copy_in_user(uifr, uifr32, sizeof(*uifr32))) 331637ac39bdSJohannes Berg return -EFAULT; 331737ac39bdSJohannes Berg 331837ac39bdSJohannes Berg err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr); 331937ac39bdSJohannes Berg 332037ac39bdSJohannes Berg if (!err) { 332137ac39bdSJohannes Berg switch (cmd) { 332237ac39bdSJohannes Berg case SIOCGIFFLAGS: 332337ac39bdSJohannes Berg case SIOCGIFMETRIC: 332437ac39bdSJohannes Berg case SIOCGIFMTU: 332537ac39bdSJohannes Berg case SIOCGIFMEM: 332637ac39bdSJohannes Berg case SIOCGIFHWADDR: 332737ac39bdSJohannes Berg case SIOCGIFINDEX: 332837ac39bdSJohannes Berg case SIOCGIFADDR: 332937ac39bdSJohannes Berg case SIOCGIFBRDADDR: 333037ac39bdSJohannes Berg case SIOCGIFDSTADDR: 333137ac39bdSJohannes Berg case SIOCGIFNETMASK: 333237ac39bdSJohannes Berg case SIOCGIFPFLAGS: 333337ac39bdSJohannes Berg case SIOCGIFTXQLEN: 333437ac39bdSJohannes Berg case SIOCGMIIPHY: 333537ac39bdSJohannes Berg case SIOCGMIIREG: 3336c6c9fee3SJohannes Berg case SIOCGIFNAME: 333737ac39bdSJohannes Berg if (copy_in_user(uifr32, uifr, sizeof(*uifr32))) 333837ac39bdSJohannes Berg err = -EFAULT; 333937ac39bdSJohannes Berg break; 334037ac39bdSJohannes Berg } 334137ac39bdSJohannes Berg } 334237ac39bdSJohannes Berg return err; 334337ac39bdSJohannes Berg } 334437ac39bdSJohannes Berg 3345a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd, 3346a2116ed2SArnd Bergmann struct compat_ifreq __user *uifr32) 3347a2116ed2SArnd Bergmann { 3348a2116ed2SArnd Bergmann struct ifreq ifr; 3349a2116ed2SArnd Bergmann struct compat_ifmap __user *uifmap32; 3350a2116ed2SArnd Bergmann int err; 3351a2116ed2SArnd Bergmann 3352a2116ed2SArnd Bergmann uifmap32 = &uifr32->ifr_ifru.ifru_map; 3353a2116ed2SArnd Bergmann err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name)); 33543ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); 33553ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); 33563ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); 33573ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.irq, &uifmap32->irq); 33583ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.dma, &uifmap32->dma); 33593ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.port, &uifmap32->port); 3360a2116ed2SArnd Bergmann if (err) 3361a2116ed2SArnd Bergmann return -EFAULT; 3362a2116ed2SArnd Bergmann 336344c02a2cSAl Viro err = dev_ioctl(net, cmd, &ifr, NULL); 3364a2116ed2SArnd Bergmann 3365a2116ed2SArnd Bergmann if (cmd == SIOCGIFMAP && !err) { 33667a229387SArnd Bergmann err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name)); 33673ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); 33683ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); 33693ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); 33703ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.irq, &uifmap32->irq); 33713ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.dma, &uifmap32->dma); 33723ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.port, &uifmap32->port); 33737a229387SArnd Bergmann if (err) 33747a229387SArnd Bergmann err = -EFAULT; 33757a229387SArnd Bergmann } 33767a229387SArnd Bergmann return err; 33777a229387SArnd Bergmann } 33787a229387SArnd Bergmann 33797a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE 33807a229387SArnd Bergmann * for some operations; this forces use of the newer bridge-utils that 338125985edcSLucas De Marchi * use compatible ioctls 33827a229387SArnd Bergmann */ 33836b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp) 33847a229387SArnd Bergmann { 33856b96018bSArnd Bergmann compat_ulong_t tmp; 33867a229387SArnd Bergmann 33876b96018bSArnd Bergmann if (get_user(tmp, argp)) 33887a229387SArnd Bergmann return -EFAULT; 33897a229387SArnd Bergmann if (tmp == BRCTL_GET_VERSION) 33907a229387SArnd Bergmann return BRCTL_VERSION + 1; 33917a229387SArnd Bergmann return -EINVAL; 33927a229387SArnd Bergmann } 33937a229387SArnd Bergmann 33946b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, 33956b96018bSArnd Bergmann unsigned int cmd, unsigned long arg) 33966b96018bSArnd Bergmann { 33976b96018bSArnd Bergmann void __user *argp = compat_ptr(arg); 33986b96018bSArnd Bergmann struct sock *sk = sock->sk; 33996b96018bSArnd Bergmann struct net *net = sock_net(sk); 34007a229387SArnd Bergmann 34016b96018bSArnd Bergmann if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) 3402590d4693SBen Hutchings return compat_ifr_data_ioctl(net, cmd, argp); 34037a229387SArnd Bergmann 34046b96018bSArnd Bergmann switch (cmd) { 34056b96018bSArnd Bergmann case SIOCSIFBR: 34066b96018bSArnd Bergmann case SIOCGIFBR: 34076b96018bSArnd Bergmann return old_bridge_ioctl(argp); 34086b96018bSArnd Bergmann case SIOCGIFCONF: 340936fd633eSAl Viro return compat_dev_ifconf(net, argp); 34106b96018bSArnd Bergmann case SIOCETHTOOL: 34116b96018bSArnd Bergmann return ethtool_ioctl(net, argp); 34127a50a240SArnd Bergmann case SIOCWANDEV: 34137a50a240SArnd Bergmann return compat_siocwandev(net, argp); 3414a2116ed2SArnd Bergmann case SIOCGIFMAP: 3415a2116ed2SArnd Bergmann case SIOCSIFMAP: 3416a2116ed2SArnd Bergmann return compat_sioc_ifmap(net, cmd, argp); 34170768e170SArnd Bergmann case SIOCGSTAMP_OLD: 34180768e170SArnd Bergmann case SIOCGSTAMPNS_OLD: 3419c7cbdbf2SArnd Bergmann if (!sock->ops->gettstamp) 3420c7cbdbf2SArnd Bergmann return -ENOIOCTLCMD; 34210768e170SArnd Bergmann return sock->ops->gettstamp(sock, argp, cmd == SIOCGSTAMP_OLD, 3422c7cbdbf2SArnd Bergmann !COMPAT_USE_64BIT_TIME); 3423c7cbdbf2SArnd Bergmann 3424590d4693SBen Hutchings case SIOCBONDSLAVEINFOQUERY: 3425590d4693SBen Hutchings case SIOCBONDINFOQUERY: 3426a2116ed2SArnd Bergmann case SIOCSHWTSTAMP: 3427fd468c74SBen Hutchings case SIOCGHWTSTAMP: 3428590d4693SBen Hutchings return compat_ifr_data_ioctl(net, cmd, argp); 34297a229387SArnd Bergmann 34306b96018bSArnd Bergmann case FIOSETOWN: 34316b96018bSArnd Bergmann case SIOCSPGRP: 34326b96018bSArnd Bergmann case FIOGETOWN: 34336b96018bSArnd Bergmann case SIOCGPGRP: 34346b96018bSArnd Bergmann case SIOCBRADDBR: 34356b96018bSArnd Bergmann case SIOCBRDELBR: 34366b96018bSArnd Bergmann case SIOCGIFVLAN: 34376b96018bSArnd Bergmann case SIOCSIFVLAN: 34386b96018bSArnd Bergmann case SIOCADDDLCI: 34396b96018bSArnd Bergmann case SIOCDELDLCI: 3440c62cce2cSAndrey Vagin case SIOCGSKNS: 34410768e170SArnd Bergmann case SIOCGSTAMP_NEW: 34420768e170SArnd Bergmann case SIOCGSTAMPNS_NEW: 34436b96018bSArnd Bergmann return sock_ioctl(file, cmd, arg); 34446b96018bSArnd Bergmann 34456b96018bSArnd Bergmann case SIOCGIFFLAGS: 34466b96018bSArnd Bergmann case SIOCSIFFLAGS: 34476b96018bSArnd Bergmann case SIOCGIFMETRIC: 34486b96018bSArnd Bergmann case SIOCSIFMETRIC: 34496b96018bSArnd Bergmann case SIOCGIFMTU: 34506b96018bSArnd Bergmann case SIOCSIFMTU: 34516b96018bSArnd Bergmann case SIOCGIFMEM: 34526b96018bSArnd Bergmann case SIOCSIFMEM: 34536b96018bSArnd Bergmann case SIOCGIFHWADDR: 34546b96018bSArnd Bergmann case SIOCSIFHWADDR: 34556b96018bSArnd Bergmann case SIOCADDMULTI: 34566b96018bSArnd Bergmann case SIOCDELMULTI: 34576b96018bSArnd Bergmann case SIOCGIFINDEX: 34586b96018bSArnd Bergmann case SIOCGIFADDR: 34596b96018bSArnd Bergmann case SIOCSIFADDR: 34606b96018bSArnd Bergmann case SIOCSIFHWBROADCAST: 34616b96018bSArnd Bergmann case SIOCDIFADDR: 34626b96018bSArnd Bergmann case SIOCGIFBRDADDR: 34636b96018bSArnd Bergmann case SIOCSIFBRDADDR: 34646b96018bSArnd Bergmann case SIOCGIFDSTADDR: 34656b96018bSArnd Bergmann case SIOCSIFDSTADDR: 34666b96018bSArnd Bergmann case SIOCGIFNETMASK: 34676b96018bSArnd Bergmann case SIOCSIFNETMASK: 34686b96018bSArnd Bergmann case SIOCSIFPFLAGS: 34696b96018bSArnd Bergmann case SIOCGIFPFLAGS: 34706b96018bSArnd Bergmann case SIOCGIFTXQLEN: 34716b96018bSArnd Bergmann case SIOCSIFTXQLEN: 34726b96018bSArnd Bergmann case SIOCBRADDIF: 34736b96018bSArnd Bergmann case SIOCBRDELIF: 3474c6c9fee3SJohannes Berg case SIOCGIFNAME: 34759177efd3SArnd Bergmann case SIOCSIFNAME: 34769177efd3SArnd Bergmann case SIOCGMIIPHY: 34779177efd3SArnd Bergmann case SIOCGMIIREG: 34789177efd3SArnd Bergmann case SIOCSMIIREG: 3479f92d4fc9SAl Viro case SIOCBONDENSLAVE: 3480f92d4fc9SAl Viro case SIOCBONDRELEASE: 3481f92d4fc9SAl Viro case SIOCBONDSETHWADDR: 3482f92d4fc9SAl Viro case SIOCBONDCHANGEACTIVE: 348337ac39bdSJohannes Berg return compat_ifreq_ioctl(net, sock, cmd, argp); 348437ac39bdSJohannes Berg 34856b96018bSArnd Bergmann case SIOCSARP: 34866b96018bSArnd Bergmann case SIOCGARP: 34876b96018bSArnd Bergmann case SIOCDARP: 3488c7dc504eSArnd Bergmann case SIOCOUTQ: 34899d7bf41fSArnd Bergmann case SIOCOUTQNSD: 34906b96018bSArnd Bergmann case SIOCATMARK: 349163ff03abSJohannes Berg return sock_do_ioctl(net, sock, cmd, arg); 34929177efd3SArnd Bergmann } 34939177efd3SArnd Bergmann 34946b96018bSArnd Bergmann return -ENOIOCTLCMD; 34956b96018bSArnd Bergmann } 34967a229387SArnd Bergmann 349795c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd, 349889bbfc95SShaun Pereira unsigned long arg) 349989bbfc95SShaun Pereira { 350089bbfc95SShaun Pereira struct socket *sock = file->private_data; 350189bbfc95SShaun Pereira int ret = -ENOIOCTLCMD; 350287de87d5SDavid S. Miller struct sock *sk; 350387de87d5SDavid S. Miller struct net *net; 350487de87d5SDavid S. Miller 350587de87d5SDavid S. Miller sk = sock->sk; 350687de87d5SDavid S. Miller net = sock_net(sk); 350789bbfc95SShaun Pereira 350889bbfc95SShaun Pereira if (sock->ops->compat_ioctl) 350989bbfc95SShaun Pereira ret = sock->ops->compat_ioctl(sock, cmd, arg); 351089bbfc95SShaun Pereira 351187de87d5SDavid S. Miller if (ret == -ENOIOCTLCMD && 351287de87d5SDavid S. Miller (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)) 351387de87d5SDavid S. Miller ret = compat_wext_handle_ioctl(net, cmd, arg); 351487de87d5SDavid S. Miller 35156b96018bSArnd Bergmann if (ret == -ENOIOCTLCMD) 35166b96018bSArnd Bergmann ret = compat_sock_ioctl_trans(file, sock, cmd, arg); 35176b96018bSArnd Bergmann 351889bbfc95SShaun Pereira return ret; 351989bbfc95SShaun Pereira } 352089bbfc95SShaun Pereira #endif 352189bbfc95SShaun Pereira 35228a3c245cSPedro Tammela /** 35238a3c245cSPedro Tammela * kernel_bind - bind an address to a socket (kernel space) 35248a3c245cSPedro Tammela * @sock: socket 35258a3c245cSPedro Tammela * @addr: address 35268a3c245cSPedro Tammela * @addrlen: length of address 35278a3c245cSPedro Tammela * 35288a3c245cSPedro Tammela * Returns 0 or an error. 35298a3c245cSPedro Tammela */ 35308a3c245cSPedro Tammela 3531ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen) 3532ac5a488eSSridhar Samudrala { 3533ac5a488eSSridhar Samudrala return sock->ops->bind(sock, addr, addrlen); 3534ac5a488eSSridhar Samudrala } 3535c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind); 3536ac5a488eSSridhar Samudrala 35378a3c245cSPedro Tammela /** 35388a3c245cSPedro Tammela * kernel_listen - move socket to listening state (kernel space) 35398a3c245cSPedro Tammela * @sock: socket 35408a3c245cSPedro Tammela * @backlog: pending connections queue size 35418a3c245cSPedro Tammela * 35428a3c245cSPedro Tammela * Returns 0 or an error. 35438a3c245cSPedro Tammela */ 35448a3c245cSPedro Tammela 3545ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog) 3546ac5a488eSSridhar Samudrala { 3547ac5a488eSSridhar Samudrala return sock->ops->listen(sock, backlog); 3548ac5a488eSSridhar Samudrala } 3549c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen); 3550ac5a488eSSridhar Samudrala 35518a3c245cSPedro Tammela /** 35528a3c245cSPedro Tammela * kernel_accept - accept a connection (kernel space) 35538a3c245cSPedro Tammela * @sock: listening socket 35548a3c245cSPedro Tammela * @newsock: new connected socket 35558a3c245cSPedro Tammela * @flags: flags 35568a3c245cSPedro Tammela * 35578a3c245cSPedro Tammela * @flags must be SOCK_CLOEXEC, SOCK_NONBLOCK or 0. 35588a3c245cSPedro Tammela * If it fails, @newsock is guaranteed to be %NULL. 35598a3c245cSPedro Tammela * Returns 0 or an error. 35608a3c245cSPedro Tammela */ 35618a3c245cSPedro Tammela 3562ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags) 3563ac5a488eSSridhar Samudrala { 3564ac5a488eSSridhar Samudrala struct sock *sk = sock->sk; 3565ac5a488eSSridhar Samudrala int err; 3566ac5a488eSSridhar Samudrala 3567ac5a488eSSridhar Samudrala err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol, 3568ac5a488eSSridhar Samudrala newsock); 3569ac5a488eSSridhar Samudrala if (err < 0) 3570ac5a488eSSridhar Samudrala goto done; 3571ac5a488eSSridhar Samudrala 3572cdfbabfbSDavid Howells err = sock->ops->accept(sock, *newsock, flags, true); 3573ac5a488eSSridhar Samudrala if (err < 0) { 3574ac5a488eSSridhar Samudrala sock_release(*newsock); 3575fa8705b0STony Battersby *newsock = NULL; 3576ac5a488eSSridhar Samudrala goto done; 3577ac5a488eSSridhar Samudrala } 3578ac5a488eSSridhar Samudrala 3579ac5a488eSSridhar Samudrala (*newsock)->ops = sock->ops; 35801b08534eSWei Yongjun __module_get((*newsock)->ops->owner); 3581ac5a488eSSridhar Samudrala 3582ac5a488eSSridhar Samudrala done: 3583ac5a488eSSridhar Samudrala return err; 3584ac5a488eSSridhar Samudrala } 3585c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept); 3586ac5a488eSSridhar Samudrala 35878a3c245cSPedro Tammela /** 35888a3c245cSPedro Tammela * kernel_connect - connect a socket (kernel space) 35898a3c245cSPedro Tammela * @sock: socket 35908a3c245cSPedro Tammela * @addr: address 35918a3c245cSPedro Tammela * @addrlen: address length 35928a3c245cSPedro Tammela * @flags: flags (O_NONBLOCK, ...) 35938a3c245cSPedro Tammela * 35948a3c245cSPedro Tammela * For datagram sockets, @addr is the addres to which datagrams are sent 35958a3c245cSPedro Tammela * by default, and the only address from which datagrams are received. 35968a3c245cSPedro Tammela * For stream sockets, attempts to connect to @addr. 35978a3c245cSPedro Tammela * Returns 0 or an error code. 35988a3c245cSPedro Tammela */ 35998a3c245cSPedro Tammela 3600ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen, 3601ac5a488eSSridhar Samudrala int flags) 3602ac5a488eSSridhar Samudrala { 3603ac5a488eSSridhar Samudrala return sock->ops->connect(sock, addr, addrlen, flags); 3604ac5a488eSSridhar Samudrala } 3605c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect); 3606ac5a488eSSridhar Samudrala 36078a3c245cSPedro Tammela /** 36088a3c245cSPedro Tammela * kernel_getsockname - get the address which the socket is bound (kernel space) 36098a3c245cSPedro Tammela * @sock: socket 36108a3c245cSPedro Tammela * @addr: address holder 36118a3c245cSPedro Tammela * 36128a3c245cSPedro Tammela * Fills the @addr pointer with the address which the socket is bound. 36138a3c245cSPedro Tammela * Returns 0 or an error code. 36148a3c245cSPedro Tammela */ 36158a3c245cSPedro Tammela 36169b2c45d4SDenys Vlasenko int kernel_getsockname(struct socket *sock, struct sockaddr *addr) 3617ac5a488eSSridhar Samudrala { 36189b2c45d4SDenys Vlasenko return sock->ops->getname(sock, addr, 0); 3619ac5a488eSSridhar Samudrala } 3620c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname); 3621ac5a488eSSridhar Samudrala 36228a3c245cSPedro Tammela /** 36238a3c245cSPedro Tammela * kernel_peername - get the address which the socket is connected (kernel space) 36248a3c245cSPedro Tammela * @sock: socket 36258a3c245cSPedro Tammela * @addr: address holder 36268a3c245cSPedro Tammela * 36278a3c245cSPedro Tammela * Fills the @addr pointer with the address which the socket is connected. 36288a3c245cSPedro Tammela * Returns 0 or an error code. 36298a3c245cSPedro Tammela */ 36308a3c245cSPedro Tammela 36319b2c45d4SDenys Vlasenko int kernel_getpeername(struct socket *sock, struct sockaddr *addr) 3632ac5a488eSSridhar Samudrala { 36339b2c45d4SDenys Vlasenko return sock->ops->getname(sock, addr, 1); 3634ac5a488eSSridhar Samudrala } 3635c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername); 3636ac5a488eSSridhar Samudrala 36378a3c245cSPedro Tammela /** 36388a3c245cSPedro Tammela * kernel_sendpage - send a &page through a socket (kernel space) 36398a3c245cSPedro Tammela * @sock: socket 36408a3c245cSPedro Tammela * @page: page 36418a3c245cSPedro Tammela * @offset: page offset 36428a3c245cSPedro Tammela * @size: total size in bytes 36438a3c245cSPedro Tammela * @flags: flags (MSG_DONTWAIT, ...) 36448a3c245cSPedro Tammela * 36458a3c245cSPedro Tammela * Returns the total amount sent in bytes or an error. 36468a3c245cSPedro Tammela */ 36478a3c245cSPedro Tammela 3648ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset, 3649ac5a488eSSridhar Samudrala size_t size, int flags) 3650ac5a488eSSridhar Samudrala { 3651ac5a488eSSridhar Samudrala if (sock->ops->sendpage) 3652ac5a488eSSridhar Samudrala return sock->ops->sendpage(sock, page, offset, size, flags); 3653ac5a488eSSridhar Samudrala 3654ac5a488eSSridhar Samudrala return sock_no_sendpage(sock, page, offset, size, flags); 3655ac5a488eSSridhar Samudrala } 3656c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage); 3657ac5a488eSSridhar Samudrala 36588a3c245cSPedro Tammela /** 36598a3c245cSPedro Tammela * kernel_sendpage_locked - send a &page through the locked sock (kernel space) 36608a3c245cSPedro Tammela * @sk: sock 36618a3c245cSPedro Tammela * @page: page 36628a3c245cSPedro Tammela * @offset: page offset 36638a3c245cSPedro Tammela * @size: total size in bytes 36648a3c245cSPedro Tammela * @flags: flags (MSG_DONTWAIT, ...) 36658a3c245cSPedro Tammela * 36668a3c245cSPedro Tammela * Returns the total amount sent in bytes or an error. 36678a3c245cSPedro Tammela * Caller must hold @sk. 36688a3c245cSPedro Tammela */ 36698a3c245cSPedro Tammela 3670306b13ebSTom Herbert int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset, 3671306b13ebSTom Herbert size_t size, int flags) 3672306b13ebSTom Herbert { 3673306b13ebSTom Herbert struct socket *sock = sk->sk_socket; 3674306b13ebSTom Herbert 3675306b13ebSTom Herbert if (sock->ops->sendpage_locked) 3676306b13ebSTom Herbert return sock->ops->sendpage_locked(sk, page, offset, size, 3677306b13ebSTom Herbert flags); 3678306b13ebSTom Herbert 3679306b13ebSTom Herbert return sock_no_sendpage_locked(sk, page, offset, size, flags); 3680306b13ebSTom Herbert } 3681306b13ebSTom Herbert EXPORT_SYMBOL(kernel_sendpage_locked); 3682306b13ebSTom Herbert 36838a3c245cSPedro Tammela /** 36848a3c245cSPedro Tammela * kernel_shutdown - shut down part of a full-duplex connection (kernel space) 36858a3c245cSPedro Tammela * @sock: socket 36868a3c245cSPedro Tammela * @how: connection part 36878a3c245cSPedro Tammela * 36888a3c245cSPedro Tammela * Returns 0 or an error. 36898a3c245cSPedro Tammela */ 36908a3c245cSPedro Tammela 369191cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how) 369291cf45f0STrond Myklebust { 369391cf45f0STrond Myklebust return sock->ops->shutdown(sock, how); 369491cf45f0STrond Myklebust } 369591cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown); 3696113c3075SR. Parameswaran 36978a3c245cSPedro Tammela /** 36988a3c245cSPedro Tammela * kernel_sock_ip_overhead - returns the IP overhead imposed by a socket 36998a3c245cSPedro Tammela * @sk: socket 37008a3c245cSPedro Tammela * 37018a3c245cSPedro Tammela * This routine returns the IP overhead imposed by a socket i.e. 3702113c3075SR. Parameswaran * the length of the underlying IP header, depending on whether 3703113c3075SR. Parameswaran * this is an IPv4 or IPv6 socket and the length from IP options turned 370457240d00SR. Parameswaran * on at the socket. Assumes that the caller has a lock on the socket. 3705113c3075SR. Parameswaran */ 37068a3c245cSPedro Tammela 3707113c3075SR. Parameswaran u32 kernel_sock_ip_overhead(struct sock *sk) 3708113c3075SR. Parameswaran { 3709113c3075SR. Parameswaran struct inet_sock *inet; 3710113c3075SR. Parameswaran struct ip_options_rcu *opt; 3711113c3075SR. Parameswaran u32 overhead = 0; 3712113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6) 3713113c3075SR. Parameswaran struct ipv6_pinfo *np; 3714113c3075SR. Parameswaran struct ipv6_txoptions *optv6 = NULL; 3715113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */ 3716113c3075SR. Parameswaran 3717113c3075SR. Parameswaran if (!sk) 3718113c3075SR. Parameswaran return overhead; 3719113c3075SR. Parameswaran 3720113c3075SR. Parameswaran switch (sk->sk_family) { 3721113c3075SR. Parameswaran case AF_INET: 3722113c3075SR. Parameswaran inet = inet_sk(sk); 3723113c3075SR. Parameswaran overhead += sizeof(struct iphdr); 3724113c3075SR. Parameswaran opt = rcu_dereference_protected(inet->inet_opt, 3725614d79c0Sstephen hemminger sock_owned_by_user(sk)); 3726113c3075SR. Parameswaran if (opt) 3727113c3075SR. Parameswaran overhead += opt->opt.optlen; 3728113c3075SR. Parameswaran return overhead; 3729113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6) 3730113c3075SR. Parameswaran case AF_INET6: 3731113c3075SR. Parameswaran np = inet6_sk(sk); 3732113c3075SR. Parameswaran overhead += sizeof(struct ipv6hdr); 3733113c3075SR. Parameswaran if (np) 3734113c3075SR. Parameswaran optv6 = rcu_dereference_protected(np->opt, 3735614d79c0Sstephen hemminger sock_owned_by_user(sk)); 3736113c3075SR. Parameswaran if (optv6) 3737113c3075SR. Parameswaran overhead += (optv6->opt_flen + optv6->opt_nflen); 3738113c3075SR. Parameswaran return overhead; 3739113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */ 3740113c3075SR. Parameswaran default: /* Returns 0 overhead if the socket is not ipv4 or ipv6 */ 3741113c3075SR. Parameswaran return overhead; 3742113c3075SR. Parameswaran } 3743113c3075SR. Parameswaran } 3744113c3075SR. Parameswaran EXPORT_SYMBOL(kernel_sock_ip_overhead); 3745