11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * NET An implementation of the SOCKET network access protocol. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Version: @(#)socket.c 1.1.93 18/02/95 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Authors: Orest Zborowski, <obz@Kodak.COM> 702c30a84SJesper Juhl * Ross Biro 81da177e4SLinus Torvalds * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * Fixes: 111da177e4SLinus Torvalds * Anonymous : NOTSOCK/BADF cleanup. Error fix in 121da177e4SLinus Torvalds * shutdown() 131da177e4SLinus Torvalds * Alan Cox : verify_area() fixes 141da177e4SLinus Torvalds * Alan Cox : Removed DDI 151da177e4SLinus Torvalds * Jonathan Kamens : SOCK_DGRAM reconnect bug 161da177e4SLinus Torvalds * Alan Cox : Moved a load of checks to the very 171da177e4SLinus Torvalds * top level. 181da177e4SLinus Torvalds * Alan Cox : Move address structures to/from user 191da177e4SLinus Torvalds * mode above the protocol layers. 201da177e4SLinus Torvalds * Rob Janssen : Allow 0 length sends. 211da177e4SLinus Torvalds * Alan Cox : Asynchronous I/O support (cribbed from the 221da177e4SLinus Torvalds * tty drivers). 231da177e4SLinus Torvalds * Niibe Yutaka : Asynchronous I/O for writes (4.4BSD style) 241da177e4SLinus Torvalds * Jeff Uphoff : Made max number of sockets command-line 251da177e4SLinus Torvalds * configurable. 261da177e4SLinus Torvalds * Matti Aarnio : Made the number of sockets dynamic, 271da177e4SLinus Torvalds * to be allocated when needed, and mr. 281da177e4SLinus Torvalds * Uphoff's max is used as max to be 291da177e4SLinus Torvalds * allowed to allocate. 301da177e4SLinus Torvalds * Linus : Argh. removed all the socket allocation 311da177e4SLinus Torvalds * altogether: it's in the inode now. 321da177e4SLinus Torvalds * Alan Cox : Made sock_alloc()/sock_release() public 331da177e4SLinus Torvalds * for NetROM and future kernel nfsd type 341da177e4SLinus Torvalds * stuff. 351da177e4SLinus Torvalds * Alan Cox : sendmsg/recvmsg basics. 361da177e4SLinus Torvalds * Tom Dyas : Export net symbols. 371da177e4SLinus Torvalds * Marcin Dalecki : Fixed problems with CONFIG_NET="n". 381da177e4SLinus Torvalds * Alan Cox : Added thread locking to sys_* calls 391da177e4SLinus Torvalds * for sockets. May have errors at the 401da177e4SLinus Torvalds * moment. 411da177e4SLinus Torvalds * Kevin Buhr : Fixed the dumb errors in the above. 421da177e4SLinus Torvalds * Andi Kleen : Some small cleanups, optimizations, 431da177e4SLinus Torvalds * and fixed a copy_from_user() bug. 441da177e4SLinus Torvalds * Tigran Aivazian : sys_send(args) calls sys_sendto(args, NULL, 0) 451da177e4SLinus Torvalds * Tigran Aivazian : Made listen(2) backlog sanity checks 461da177e4SLinus Torvalds * protocol-independent 471da177e4SLinus Torvalds * 481da177e4SLinus Torvalds * 491da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 501da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 511da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 521da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 531da177e4SLinus Torvalds * 541da177e4SLinus Torvalds * 551da177e4SLinus Torvalds * This module is effectively the top level interface to the BSD socket 561da177e4SLinus Torvalds * paradigm. 571da177e4SLinus Torvalds * 581da177e4SLinus Torvalds * Based upon Swansea University Computer Society NET3.039 591da177e4SLinus Torvalds */ 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds #include <linux/mm.h> 621da177e4SLinus Torvalds #include <linux/socket.h> 631da177e4SLinus Torvalds #include <linux/file.h> 641da177e4SLinus Torvalds #include <linux/net.h> 651da177e4SLinus Torvalds #include <linux/interrupt.h> 66aaca0bdcSUlrich Drepper #include <linux/thread_info.h> 6755737fdaSStephen Hemminger #include <linux/rcupdate.h> 681da177e4SLinus Torvalds #include <linux/netdevice.h> 691da177e4SLinus Torvalds #include <linux/proc_fs.h> 701da177e4SLinus Torvalds #include <linux/seq_file.h> 714a3e2f71SArjan van de Ven #include <linux/mutex.h> 721da177e4SLinus Torvalds #include <linux/if_bridge.h> 7320380731SArnaldo Carvalho de Melo #include <linux/if_frad.h> 7420380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h> 75408eccceSDaniel Borkmann #include <linux/ptp_classify.h> 761da177e4SLinus Torvalds #include <linux/init.h> 771da177e4SLinus Torvalds #include <linux/poll.h> 781da177e4SLinus Torvalds #include <linux/cache.h> 791da177e4SLinus Torvalds #include <linux/module.h> 801da177e4SLinus Torvalds #include <linux/highmem.h> 811da177e4SLinus Torvalds #include <linux/mount.h> 821da177e4SLinus Torvalds #include <linux/security.h> 831da177e4SLinus Torvalds #include <linux/syscalls.h> 841da177e4SLinus Torvalds #include <linux/compat.h> 851da177e4SLinus Torvalds #include <linux/kmod.h> 863ec3b2fbSDavid Woodhouse #include <linux/audit.h> 87d86b5e0eSAdrian Bunk #include <linux/wireless.h> 881b8d7ae4SEric W. Biederman #include <linux/nsproxy.h> 891fd7317dSNick Black #include <linux/magic.h> 905a0e3ad6STejun Heo #include <linux/slab.h> 91600e1779SMasatake YAMATO #include <linux/xattr.h> 921da177e4SLinus Torvalds 937c0f6ba6SLinus Torvalds #include <linux/uaccess.h> 941da177e4SLinus Torvalds #include <asm/unistd.h> 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds #include <net/compat.h> 9787de87d5SDavid S. Miller #include <net/wext.h> 98f8451725SHerbert Xu #include <net/cls_cgroup.h> 991da177e4SLinus Torvalds 1001da177e4SLinus Torvalds #include <net/sock.h> 1011da177e4SLinus Torvalds #include <linux/netfilter.h> 1021da177e4SLinus Torvalds 1036b96018bSArnd Bergmann #include <linux/if_tun.h> 1046b96018bSArnd Bergmann #include <linux/ipv6_route.h> 1056b96018bSArnd Bergmann #include <linux/route.h> 1066b96018bSArnd Bergmann #include <linux/sockios.h> 107076bb0c8SEliezer Tamir #include <net/busy_poll.h> 108f24b9be5SWillem de Bruijn #include <linux/errqueue.h> 10906021292SEliezer Tamir 110e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL 11164b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly; 11264b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly; 11306021292SEliezer Tamir #endif 1146b96018bSArnd Bergmann 1158ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to); 1168ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from); 1171da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma); 1181da177e4SLinus Torvalds 1191da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file); 12015252423SChristoph Hellwig static struct wait_queue_head *sock_get_poll_head(struct file *file, 12115252423SChristoph Hellwig __poll_t events); 12215252423SChristoph Hellwig static __poll_t sock_poll_mask(struct file *file, __poll_t); 12315252423SChristoph Hellwig static __poll_t sock_poll(struct file *file, struct poll_table_struct *wait); 12489bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 12589bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 12689bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file, 12789bbfc95SShaun Pereira unsigned int cmd, unsigned long arg); 12889bbfc95SShaun Pereira #endif 1291da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on); 1301da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page, 1311da177e4SLinus Torvalds int offset, size_t size, loff_t *ppos, int more); 1329c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos, 1339c55e01cSJens Axboe struct pipe_inode_info *pipe, size_t len, 1349c55e01cSJens Axboe unsigned int flags); 1351da177e4SLinus Torvalds 1361da177e4SLinus Torvalds /* 1371da177e4SLinus Torvalds * Socket files have a set of 'special' operations as well as the generic file ones. These don't appear 1381da177e4SLinus Torvalds * in the operation structures but are done directly via the socketcall() multiplexor. 1391da177e4SLinus Torvalds */ 1401da177e4SLinus Torvalds 141da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = { 1421da177e4SLinus Torvalds .owner = THIS_MODULE, 1431da177e4SLinus Torvalds .llseek = no_llseek, 1448ae5e030SAl Viro .read_iter = sock_read_iter, 1458ae5e030SAl Viro .write_iter = sock_write_iter, 14615252423SChristoph Hellwig .get_poll_head = sock_get_poll_head, 14715252423SChristoph Hellwig .poll_mask = sock_poll_mask, 1481da177e4SLinus Torvalds .poll = sock_poll, 1491da177e4SLinus Torvalds .unlocked_ioctl = sock_ioctl, 15089bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 15189bbfc95SShaun Pereira .compat_ioctl = compat_sock_ioctl, 15289bbfc95SShaun Pereira #endif 1531da177e4SLinus Torvalds .mmap = sock_mmap, 1541da177e4SLinus Torvalds .release = sock_close, 1551da177e4SLinus Torvalds .fasync = sock_fasync, 1565274f052SJens Axboe .sendpage = sock_sendpage, 1575274f052SJens Axboe .splice_write = generic_splice_sendpage, 1589c55e01cSJens Axboe .splice_read = sock_splice_read, 1591da177e4SLinus Torvalds }; 1601da177e4SLinus Torvalds 1611da177e4SLinus Torvalds /* 1621da177e4SLinus Torvalds * The protocol list. Each protocol is registered in here. 1631da177e4SLinus Torvalds */ 1641da177e4SLinus Torvalds 1651da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock); 166190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly; 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds /* 16989bddce5SStephen Hemminger * Support routines. 17089bddce5SStephen Hemminger * Move socket addresses back and forth across the kernel/user 1711da177e4SLinus Torvalds * divide and look after the messy bits. 1721da177e4SLinus Torvalds */ 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds /** 1751da177e4SLinus Torvalds * move_addr_to_kernel - copy a socket address into kernel space 1761da177e4SLinus Torvalds * @uaddr: Address in user space 1771da177e4SLinus Torvalds * @kaddr: Address in kernel space 1781da177e4SLinus Torvalds * @ulen: Length in user space 1791da177e4SLinus Torvalds * 1801da177e4SLinus Torvalds * The address is copied into kernel space. If the provided address is 1811da177e4SLinus Torvalds * too long an error code of -EINVAL is returned. If the copy gives 1821da177e4SLinus Torvalds * invalid addresses -EFAULT is returned. On a success 0 is returned. 1831da177e4SLinus Torvalds */ 1841da177e4SLinus Torvalds 18543db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr) 1861da177e4SLinus Torvalds { 187230b1839SYOSHIFUJI Hideaki if (ulen < 0 || ulen > sizeof(struct sockaddr_storage)) 1881da177e4SLinus Torvalds return -EINVAL; 1891da177e4SLinus Torvalds if (ulen == 0) 1901da177e4SLinus Torvalds return 0; 1911da177e4SLinus Torvalds if (copy_from_user(kaddr, uaddr, ulen)) 1921da177e4SLinus Torvalds return -EFAULT; 1933ec3b2fbSDavid Woodhouse return audit_sockaddr(ulen, kaddr); 1941da177e4SLinus Torvalds } 1951da177e4SLinus Torvalds 1961da177e4SLinus Torvalds /** 1971da177e4SLinus Torvalds * move_addr_to_user - copy an address to user space 1981da177e4SLinus Torvalds * @kaddr: kernel space address 1991da177e4SLinus Torvalds * @klen: length of address in kernel 2001da177e4SLinus Torvalds * @uaddr: user space address 2011da177e4SLinus Torvalds * @ulen: pointer to user length field 2021da177e4SLinus Torvalds * 2031da177e4SLinus Torvalds * The value pointed to by ulen on entry is the buffer length available. 2041da177e4SLinus Torvalds * This is overwritten with the buffer space used. -EINVAL is returned 2051da177e4SLinus Torvalds * if an overlong buffer is specified or a negative buffer size. -EFAULT 2061da177e4SLinus Torvalds * is returned if either the buffer or the length field are not 2071da177e4SLinus Torvalds * accessible. 2081da177e4SLinus Torvalds * After copying the data up to the limit the user specifies, the true 2091da177e4SLinus Torvalds * length of the data is written over the length limit the user 2101da177e4SLinus Torvalds * specified. Zero is returned for a success. 2111da177e4SLinus Torvalds */ 2121da177e4SLinus Torvalds 21343db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen, 21411165f14Sstephen hemminger void __user *uaddr, int __user *ulen) 2151da177e4SLinus Torvalds { 2161da177e4SLinus Torvalds int err; 2171da177e4SLinus Torvalds int len; 2181da177e4SLinus Torvalds 21968c6beb3SHannes Frederic Sowa BUG_ON(klen > sizeof(struct sockaddr_storage)); 22089bddce5SStephen Hemminger err = get_user(len, ulen); 22189bddce5SStephen Hemminger if (err) 2221da177e4SLinus Torvalds return err; 2231da177e4SLinus Torvalds if (len > klen) 2241da177e4SLinus Torvalds len = klen; 22568c6beb3SHannes Frederic Sowa if (len < 0) 2261da177e4SLinus Torvalds return -EINVAL; 22789bddce5SStephen Hemminger if (len) { 228d6fe3945SSteve Grubb if (audit_sockaddr(klen, kaddr)) 229d6fe3945SSteve Grubb return -ENOMEM; 2301da177e4SLinus Torvalds if (copy_to_user(uaddr, kaddr, len)) 2311da177e4SLinus Torvalds return -EFAULT; 2321da177e4SLinus Torvalds } 2331da177e4SLinus Torvalds /* 2341da177e4SLinus Torvalds * "fromlen shall refer to the value before truncation.." 2351da177e4SLinus Torvalds * 1003.1g 2361da177e4SLinus Torvalds */ 2371da177e4SLinus Torvalds return __put_user(klen, ulen); 2381da177e4SLinus Torvalds } 2391da177e4SLinus Torvalds 24008009a76SAlexey Dobriyan static struct kmem_cache *sock_inode_cachep __ro_after_init; 2411da177e4SLinus Torvalds 2421da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb) 2431da177e4SLinus Torvalds { 2441da177e4SLinus Torvalds struct socket_alloc *ei; 245eaefd110SEric Dumazet struct socket_wq *wq; 24689bddce5SStephen Hemminger 247e94b1766SChristoph Lameter ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL); 2481da177e4SLinus Torvalds if (!ei) 2491da177e4SLinus Torvalds return NULL; 250eaefd110SEric Dumazet wq = kmalloc(sizeof(*wq), GFP_KERNEL); 251eaefd110SEric Dumazet if (!wq) { 25243815482SEric Dumazet kmem_cache_free(sock_inode_cachep, ei); 25343815482SEric Dumazet return NULL; 25443815482SEric Dumazet } 255eaefd110SEric Dumazet init_waitqueue_head(&wq->wait); 256eaefd110SEric Dumazet wq->fasync_list = NULL; 257574aab1eSNicolai Stange wq->flags = 0; 258eaefd110SEric Dumazet RCU_INIT_POINTER(ei->socket.wq, wq); 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 2691da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode) 2701da177e4SLinus Torvalds { 27143815482SEric Dumazet struct socket_alloc *ei; 272eaefd110SEric Dumazet struct socket_wq *wq; 27343815482SEric Dumazet 27443815482SEric Dumazet ei = container_of(inode, struct socket_alloc, vfs_inode); 275eaefd110SEric Dumazet wq = rcu_dereference_protected(ei->socket.wq, 1); 27661845220SLai Jiangshan kfree_rcu(wq, rcu); 27743815482SEric Dumazet kmem_cache_free(sock_inode_cachep, ei); 2781da177e4SLinus Torvalds } 2791da177e4SLinus Torvalds 28051cc5068SAlexey Dobriyan static void init_once(void *foo) 2811da177e4SLinus Torvalds { 2821da177e4SLinus Torvalds struct socket_alloc *ei = (struct socket_alloc *)foo; 2831da177e4SLinus Torvalds 2841da177e4SLinus Torvalds inode_init_once(&ei->vfs_inode); 2851da177e4SLinus Torvalds } 2861da177e4SLinus Torvalds 2871e911632Syuan linyu static void init_inodecache(void) 2881da177e4SLinus Torvalds { 2891da177e4SLinus Torvalds sock_inode_cachep = kmem_cache_create("sock_inode_cache", 2901da177e4SLinus Torvalds sizeof(struct socket_alloc), 29189bddce5SStephen Hemminger 0, 29289bddce5SStephen Hemminger (SLAB_HWCACHE_ALIGN | 29389bddce5SStephen Hemminger SLAB_RECLAIM_ACCOUNT | 2945d097056SVladimir Davydov SLAB_MEM_SPREAD | SLAB_ACCOUNT), 29520c2df83SPaul Mundt init_once); 2961e911632Syuan linyu BUG_ON(sock_inode_cachep == NULL); 2971da177e4SLinus Torvalds } 2981da177e4SLinus Torvalds 299b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = { 3001da177e4SLinus Torvalds .alloc_inode = sock_alloc_inode, 3011da177e4SLinus Torvalds .destroy_inode = sock_destroy_inode, 3021da177e4SLinus Torvalds .statfs = simple_statfs, 3031da177e4SLinus Torvalds }; 3041da177e4SLinus Torvalds 305c23fbb6bSEric Dumazet /* 306c23fbb6bSEric Dumazet * sockfs_dname() is called from d_path(). 307c23fbb6bSEric Dumazet */ 308c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen) 309c23fbb6bSEric Dumazet { 310c23fbb6bSEric Dumazet return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]", 311c5ef6035SDavid Howells d_inode(dentry)->i_ino); 312c23fbb6bSEric Dumazet } 313c23fbb6bSEric Dumazet 3143ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = { 315c23fbb6bSEric Dumazet .d_dname = sockfs_dname, 3161da177e4SLinus Torvalds }; 3171da177e4SLinus Torvalds 318bba0bd31SAndreas Gruenbacher static int sockfs_xattr_get(const struct xattr_handler *handler, 319bba0bd31SAndreas Gruenbacher struct dentry *dentry, struct inode *inode, 320bba0bd31SAndreas Gruenbacher const char *suffix, void *value, size_t size) 321bba0bd31SAndreas Gruenbacher { 322bba0bd31SAndreas Gruenbacher if (value) { 323bba0bd31SAndreas Gruenbacher if (dentry->d_name.len + 1 > size) 324bba0bd31SAndreas Gruenbacher return -ERANGE; 325bba0bd31SAndreas Gruenbacher memcpy(value, dentry->d_name.name, dentry->d_name.len + 1); 326bba0bd31SAndreas Gruenbacher } 327bba0bd31SAndreas Gruenbacher return dentry->d_name.len + 1; 328bba0bd31SAndreas Gruenbacher } 329bba0bd31SAndreas Gruenbacher 330bba0bd31SAndreas Gruenbacher #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname" 331bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX) 332bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1) 333bba0bd31SAndreas Gruenbacher 334bba0bd31SAndreas Gruenbacher static const struct xattr_handler sockfs_xattr_handler = { 335bba0bd31SAndreas Gruenbacher .name = XATTR_NAME_SOCKPROTONAME, 336bba0bd31SAndreas Gruenbacher .get = sockfs_xattr_get, 337bba0bd31SAndreas Gruenbacher }; 338bba0bd31SAndreas Gruenbacher 3394a590153SAndreas Gruenbacher static int sockfs_security_xattr_set(const struct xattr_handler *handler, 3404a590153SAndreas Gruenbacher struct dentry *dentry, struct inode *inode, 3414a590153SAndreas Gruenbacher const char *suffix, const void *value, 3424a590153SAndreas Gruenbacher size_t size, int flags) 3434a590153SAndreas Gruenbacher { 3444a590153SAndreas Gruenbacher /* Handled by LSM. */ 3454a590153SAndreas Gruenbacher return -EAGAIN; 3464a590153SAndreas Gruenbacher } 3474a590153SAndreas Gruenbacher 3484a590153SAndreas Gruenbacher static const struct xattr_handler sockfs_security_xattr_handler = { 3494a590153SAndreas Gruenbacher .prefix = XATTR_SECURITY_PREFIX, 3504a590153SAndreas Gruenbacher .set = sockfs_security_xattr_set, 3514a590153SAndreas Gruenbacher }; 3524a590153SAndreas Gruenbacher 353bba0bd31SAndreas Gruenbacher static const struct xattr_handler *sockfs_xattr_handlers[] = { 354bba0bd31SAndreas Gruenbacher &sockfs_xattr_handler, 3554a590153SAndreas Gruenbacher &sockfs_security_xattr_handler, 356bba0bd31SAndreas Gruenbacher NULL 357bba0bd31SAndreas Gruenbacher }; 358bba0bd31SAndreas Gruenbacher 359c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type, 360c74a1cbbSAl Viro int flags, const char *dev_name, void *data) 361c74a1cbbSAl Viro { 362bba0bd31SAndreas Gruenbacher return mount_pseudo_xattr(fs_type, "socket:", &sockfs_ops, 363bba0bd31SAndreas Gruenbacher sockfs_xattr_handlers, 364c74a1cbbSAl Viro &sockfs_dentry_operations, SOCKFS_MAGIC); 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", 371c74a1cbbSAl Viro .mount = sockfs_mount, 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 392aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) 3931da177e4SLinus Torvalds { 3947cbe66b6SAl Viro struct qstr name = { .name = "" }; 3952c48b9c4SAl Viro struct path path; 3967cbe66b6SAl Viro struct file *file; 3971da177e4SLinus Torvalds 398600e1779SMasatake YAMATO if (dname) { 399600e1779SMasatake YAMATO name.name = dname; 400600e1779SMasatake YAMATO name.len = strlen(name.name); 401600e1779SMasatake YAMATO } else if (sock->sk) { 402600e1779SMasatake YAMATO name.name = sock->sk->sk_prot_creator->name; 403600e1779SMasatake YAMATO name.len = strlen(name.name); 404600e1779SMasatake YAMATO } 4054b936885SNick Piggin path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name); 4068e1611e2SAl Viro if (unlikely(!path.dentry)) { 4078e1611e2SAl Viro sock_release(sock); 40828407630SAl Viro return ERR_PTR(-ENOMEM); 4098e1611e2SAl Viro } 4102c48b9c4SAl Viro path.mnt = mntget(sock_mnt); 41139d8c1b6SDavid S. Miller 4122c48b9c4SAl Viro d_instantiate(path.dentry, SOCK_INODE(sock)); 413cc3808f8SAl Viro 4142c48b9c4SAl Viro file = alloc_file(&path, FMODE_READ | FMODE_WRITE, 415cc3808f8SAl Viro &socket_file_ops); 416b5ffe634SViresh Kumar if (IS_ERR(file)) { 4178e1611e2SAl Viro /* drop dentry, keep inode for a bit */ 418c5ef6035SDavid Howells ihold(d_inode(path.dentry)); 4192c48b9c4SAl Viro path_put(&path); 4208e1611e2SAl Viro /* ... and now kill it properly */ 4218e1611e2SAl Viro sock_release(sock); 42239b65252SAnatol Pomozov return file; 423cc3808f8SAl Viro } 4241da177e4SLinus Torvalds 4251da177e4SLinus Torvalds sock->file = file; 42677d27200SUlrich Drepper file->f_flags = O_RDWR | (flags & O_NONBLOCK); 42707dc3f07SBenjamin LaHaise file->private_data = sock; 42828407630SAl Viro return file; 4291da177e4SLinus Torvalds } 43056b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file); 4311da177e4SLinus Torvalds 43256b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags) 43339d8c1b6SDavid S. Miller { 43439d8c1b6SDavid S. Miller struct file *newfile; 43528407630SAl Viro int fd = get_unused_fd_flags(flags); 436ce4bb04cSAl Viro if (unlikely(fd < 0)) { 437ce4bb04cSAl Viro sock_release(sock); 4381da177e4SLinus Torvalds return fd; 439ce4bb04cSAl Viro } 4401da177e4SLinus Torvalds 441aab174f0SLinus Torvalds newfile = sock_alloc_file(sock, flags, NULL); 44228407630SAl Viro if (likely(!IS_ERR(newfile))) { 4431da177e4SLinus Torvalds fd_install(fd, newfile); 4441da177e4SLinus Torvalds return fd; 4451da177e4SLinus Torvalds } 44628407630SAl Viro 44728407630SAl Viro put_unused_fd(fd); 44828407630SAl Viro return PTR_ERR(newfile); 4491da177e4SLinus Torvalds } 4501da177e4SLinus Torvalds 451406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err) 4526cb153caSBenjamin LaHaise { 4536cb153caSBenjamin LaHaise if (file->f_op == &socket_file_ops) 4546cb153caSBenjamin LaHaise return file->private_data; /* set in sock_map_fd */ 4556cb153caSBenjamin LaHaise 4566cb153caSBenjamin LaHaise *err = -ENOTSOCK; 4576cb153caSBenjamin LaHaise return NULL; 4586cb153caSBenjamin LaHaise } 459406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file); 4606cb153caSBenjamin LaHaise 4611da177e4SLinus Torvalds /** 4621da177e4SLinus Torvalds * sockfd_lookup - Go from a file number to its socket slot 4631da177e4SLinus Torvalds * @fd: file handle 4641da177e4SLinus Torvalds * @err: pointer to an error code return 4651da177e4SLinus Torvalds * 4661da177e4SLinus Torvalds * The file handle passed in is locked and the socket it is bound 467241c4667SRosen, Rami * to is returned. If an error occurs the err pointer is overwritten 4681da177e4SLinus Torvalds * with a negative errno code and NULL is returned. The function checks 4691da177e4SLinus Torvalds * for both invalid handles and passing a handle which is not a socket. 4701da177e4SLinus Torvalds * 4711da177e4SLinus Torvalds * On a success the socket object pointer is returned. 4721da177e4SLinus Torvalds */ 4731da177e4SLinus Torvalds 4741da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err) 4751da177e4SLinus Torvalds { 4761da177e4SLinus Torvalds struct file *file; 4771da177e4SLinus Torvalds struct socket *sock; 4781da177e4SLinus Torvalds 47989bddce5SStephen Hemminger file = fget(fd); 48089bddce5SStephen Hemminger if (!file) { 4811da177e4SLinus Torvalds *err = -EBADF; 4821da177e4SLinus Torvalds return NULL; 4831da177e4SLinus Torvalds } 48489bddce5SStephen Hemminger 4856cb153caSBenjamin LaHaise sock = sock_from_file(file, err); 4866cb153caSBenjamin LaHaise if (!sock) 4871da177e4SLinus Torvalds fput(file); 4886cb153caSBenjamin LaHaise return sock; 4891da177e4SLinus Torvalds } 490c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup); 4911da177e4SLinus Torvalds 4926cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) 4936cb153caSBenjamin LaHaise { 49400e188efSAl Viro struct fd f = fdget(fd); 4956cb153caSBenjamin LaHaise struct socket *sock; 4966cb153caSBenjamin LaHaise 4973672558cSHua Zhong *err = -EBADF; 49800e188efSAl Viro if (f.file) { 49900e188efSAl Viro sock = sock_from_file(f.file, err); 50000e188efSAl Viro if (likely(sock)) { 50100e188efSAl Viro *fput_needed = f.flags; 5021da177e4SLinus Torvalds return sock; 50300e188efSAl Viro } 50400e188efSAl Viro fdput(f); 5056cb153caSBenjamin LaHaise } 5066cb153caSBenjamin LaHaise return NULL; 5071da177e4SLinus Torvalds } 5081da177e4SLinus Torvalds 509600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer, 510600e1779SMasatake YAMATO size_t size) 511600e1779SMasatake YAMATO { 512600e1779SMasatake YAMATO ssize_t len; 513600e1779SMasatake YAMATO ssize_t used = 0; 514600e1779SMasatake YAMATO 515c5ef6035SDavid Howells len = security_inode_listsecurity(d_inode(dentry), buffer, size); 516600e1779SMasatake YAMATO if (len < 0) 517600e1779SMasatake YAMATO return len; 518600e1779SMasatake YAMATO used += len; 519600e1779SMasatake YAMATO if (buffer) { 520600e1779SMasatake YAMATO if (size < used) 521600e1779SMasatake YAMATO return -ERANGE; 522600e1779SMasatake YAMATO buffer += len; 523600e1779SMasatake YAMATO } 524600e1779SMasatake YAMATO 525600e1779SMasatake YAMATO len = (XATTR_NAME_SOCKPROTONAME_LEN + 1); 526600e1779SMasatake YAMATO used += len; 527600e1779SMasatake YAMATO if (buffer) { 528600e1779SMasatake YAMATO if (size < used) 529600e1779SMasatake YAMATO return -ERANGE; 530600e1779SMasatake YAMATO memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len); 531600e1779SMasatake YAMATO buffer += len; 532600e1779SMasatake YAMATO } 533600e1779SMasatake YAMATO 534600e1779SMasatake YAMATO return used; 535600e1779SMasatake YAMATO } 536600e1779SMasatake YAMATO 537dc647ec8STobias Klauser static int sockfs_setattr(struct dentry *dentry, struct iattr *iattr) 53886741ec2SLorenzo Colitti { 53986741ec2SLorenzo Colitti int err = simple_setattr(dentry, iattr); 54086741ec2SLorenzo Colitti 541e1a3a60aSEric Biggers if (!err && (iattr->ia_valid & ATTR_UID)) { 54286741ec2SLorenzo Colitti struct socket *sock = SOCKET_I(d_inode(dentry)); 54386741ec2SLorenzo Colitti 5446d8c50dcSCong Wang if (sock->sk) 54586741ec2SLorenzo Colitti sock->sk->sk_uid = iattr->ia_uid; 5466d8c50dcSCong Wang else 5476d8c50dcSCong Wang err = -ENOENT; 54886741ec2SLorenzo Colitti } 54986741ec2SLorenzo Colitti 55086741ec2SLorenzo Colitti return err; 55186741ec2SLorenzo Colitti } 55286741ec2SLorenzo Colitti 553600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = { 554600e1779SMasatake YAMATO .listxattr = sockfs_listxattr, 55586741ec2SLorenzo Colitti .setattr = sockfs_setattr, 556600e1779SMasatake YAMATO }; 557600e1779SMasatake YAMATO 5581da177e4SLinus Torvalds /** 5591da177e4SLinus Torvalds * sock_alloc - allocate a socket 5601da177e4SLinus Torvalds * 5611da177e4SLinus Torvalds * Allocate a new inode and socket object. The two are bound together 5621da177e4SLinus Torvalds * and initialised. The socket is then returned. If we are out of inodes 5631da177e4SLinus Torvalds * NULL is returned. 5641da177e4SLinus Torvalds */ 5651da177e4SLinus Torvalds 566f4a00aacSTom Herbert struct socket *sock_alloc(void) 5671da177e4SLinus Torvalds { 5681da177e4SLinus Torvalds struct inode *inode; 5691da177e4SLinus Torvalds struct socket *sock; 5701da177e4SLinus Torvalds 571a209dfc7SEric Dumazet inode = new_inode_pseudo(sock_mnt->mnt_sb); 5721da177e4SLinus Torvalds if (!inode) 5731da177e4SLinus Torvalds return NULL; 5741da177e4SLinus Torvalds 5751da177e4SLinus Torvalds sock = SOCKET_I(inode); 5761da177e4SLinus Torvalds 57785fe4025SChristoph Hellwig inode->i_ino = get_next_ino(); 5781da177e4SLinus Torvalds inode->i_mode = S_IFSOCK | S_IRWXUGO; 5798192b0c4SDavid Howells inode->i_uid = current_fsuid(); 5808192b0c4SDavid Howells inode->i_gid = current_fsgid(); 581600e1779SMasatake YAMATO inode->i_op = &sockfs_inode_ops; 5821da177e4SLinus Torvalds 5831da177e4SLinus Torvalds return sock; 5841da177e4SLinus Torvalds } 585f4a00aacSTom Herbert EXPORT_SYMBOL(sock_alloc); 5861da177e4SLinus Torvalds 5871da177e4SLinus Torvalds /** 5881da177e4SLinus Torvalds * sock_release - close a socket 5891da177e4SLinus Torvalds * @sock: socket to close 5901da177e4SLinus Torvalds * 5911da177e4SLinus Torvalds * The socket is released from the protocol stack if it has a release 5921da177e4SLinus Torvalds * callback, and the inode is then released if the socket is bound to 5931da177e4SLinus Torvalds * an inode not a file. 5941da177e4SLinus Torvalds */ 5951da177e4SLinus Torvalds 5966d8c50dcSCong Wang static void __sock_release(struct socket *sock, struct inode *inode) 5971da177e4SLinus Torvalds { 5981da177e4SLinus Torvalds if (sock->ops) { 5991da177e4SLinus Torvalds struct module *owner = sock->ops->owner; 6001da177e4SLinus Torvalds 6016d8c50dcSCong Wang if (inode) 6026d8c50dcSCong Wang inode_lock(inode); 6031da177e4SLinus Torvalds sock->ops->release(sock); 6046d8c50dcSCong Wang if (inode) 6056d8c50dcSCong Wang inode_unlock(inode); 6061da177e4SLinus Torvalds sock->ops = NULL; 6071da177e4SLinus Torvalds module_put(owner); 6081da177e4SLinus Torvalds } 6091da177e4SLinus Torvalds 610eaefd110SEric Dumazet if (rcu_dereference_protected(sock->wq, 1)->fasync_list) 6113410f22eSYang Yingliang pr_err("%s: fasync list not empty!\n", __func__); 6121da177e4SLinus Torvalds 6131da177e4SLinus Torvalds if (!sock->file) { 6141da177e4SLinus Torvalds iput(SOCK_INODE(sock)); 6151da177e4SLinus Torvalds return; 6161da177e4SLinus Torvalds } 6171da177e4SLinus Torvalds sock->file = NULL; 6181da177e4SLinus Torvalds } 6196d8c50dcSCong Wang 6206d8c50dcSCong Wang void sock_release(struct socket *sock) 6216d8c50dcSCong Wang { 6226d8c50dcSCong Wang __sock_release(sock, NULL); 6236d8c50dcSCong Wang } 624c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release); 6251da177e4SLinus Torvalds 626c14ac945SSoheil Hassas Yeganeh void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags) 62720d49473SPatrick Ohly { 628140c55d4SEric Dumazet u8 flags = *tx_flags; 629140c55d4SEric Dumazet 630c14ac945SSoheil Hassas Yeganeh if (tsflags & SOF_TIMESTAMPING_TX_HARDWARE) 631140c55d4SEric Dumazet flags |= SKBTX_HW_TSTAMP; 632140c55d4SEric Dumazet 633c14ac945SSoheil Hassas Yeganeh if (tsflags & SOF_TIMESTAMPING_TX_SOFTWARE) 634140c55d4SEric Dumazet flags |= SKBTX_SW_TSTAMP; 635140c55d4SEric Dumazet 636c14ac945SSoheil Hassas Yeganeh if (tsflags & SOF_TIMESTAMPING_TX_SCHED) 637140c55d4SEric Dumazet flags |= SKBTX_SCHED_TSTAMP; 638140c55d4SEric Dumazet 639140c55d4SEric Dumazet *tx_flags = flags; 64020d49473SPatrick Ohly } 64167cc0d40SWillem de Bruijn EXPORT_SYMBOL(__sock_tx_timestamp); 64220d49473SPatrick Ohly 643d8725c86SAl Viro static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg) 6441da177e4SLinus Torvalds { 64501e97e65SAl Viro int ret = sock->ops->sendmsg(sock, msg, msg_data_left(msg)); 646d8725c86SAl Viro BUG_ON(ret == -EIOCBQUEUED); 647d8725c86SAl Viro return ret; 6481da177e4SLinus Torvalds } 6490cf00c6fSGu Zheng 650d8725c86SAl Viro int sock_sendmsg(struct socket *sock, struct msghdr *msg) 6510cf00c6fSGu Zheng { 652d8725c86SAl Viro int err = security_socket_sendmsg(sock, msg, 65301e97e65SAl Viro msg_data_left(msg)); 6541b784140SYing Xue 655d8725c86SAl Viro return err ?: sock_sendmsg_nosec(sock, msg); 6560cf00c6fSGu Zheng } 657c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg); 6581da177e4SLinus Torvalds 6591da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg, 6601da177e4SLinus Torvalds struct kvec *vec, size_t num, size_t size) 6611da177e4SLinus Torvalds { 6626aa24814SAl Viro iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size); 663d8725c86SAl Viro return sock_sendmsg(sock, msg); 6641da177e4SLinus Torvalds } 665c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg); 6661da177e4SLinus Torvalds 667306b13ebSTom Herbert int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg, 668306b13ebSTom Herbert struct kvec *vec, size_t num, size_t size) 669306b13ebSTom Herbert { 670306b13ebSTom Herbert struct socket *sock = sk->sk_socket; 671306b13ebSTom Herbert 672306b13ebSTom Herbert if (!sock->ops->sendmsg_locked) 673db5980d8SJohn Fastabend return sock_no_sendmsg_locked(sk, msg, size); 674306b13ebSTom Herbert 675306b13ebSTom Herbert iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size); 676306b13ebSTom Herbert 677306b13ebSTom Herbert return sock->ops->sendmsg_locked(sk, msg, msg_data_left(msg)); 678306b13ebSTom Herbert } 679306b13ebSTom Herbert EXPORT_SYMBOL(kernel_sendmsg_locked); 680306b13ebSTom Herbert 6818605330aSSoheil Hassas Yeganeh static bool skb_is_err_queue(const struct sk_buff *skb) 6828605330aSSoheil Hassas Yeganeh { 6838605330aSSoheil Hassas Yeganeh /* pkt_type of skbs enqueued on the error queue are set to 6848605330aSSoheil Hassas Yeganeh * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do 6858605330aSSoheil Hassas Yeganeh * in recvmsg, since skbs received on a local socket will never 6868605330aSSoheil Hassas Yeganeh * have a pkt_type of PACKET_OUTGOING. 6878605330aSSoheil Hassas Yeganeh */ 6888605330aSSoheil Hassas Yeganeh return skb->pkt_type == PACKET_OUTGOING; 6898605330aSSoheil Hassas Yeganeh } 6908605330aSSoheil Hassas Yeganeh 691b50a5c70SMiroslav Lichvar /* On transmit, software and hardware timestamps are returned independently. 692b50a5c70SMiroslav Lichvar * As the two skb clones share the hardware timestamp, which may be updated 693b50a5c70SMiroslav Lichvar * before the software timestamp is received, a hardware TX timestamp may be 694b50a5c70SMiroslav Lichvar * returned only if there is no software TX timestamp. Ignore false software 695b50a5c70SMiroslav Lichvar * timestamps, which may be made in the __sock_recv_timestamp() call when the 696b50a5c70SMiroslav Lichvar * option SO_TIMESTAMP(NS) is enabled on the socket, even when the skb has a 697b50a5c70SMiroslav Lichvar * hardware timestamp. 698b50a5c70SMiroslav Lichvar */ 699b50a5c70SMiroslav Lichvar static bool skb_is_swtx_tstamp(const struct sk_buff *skb, int false_tstamp) 700b50a5c70SMiroslav Lichvar { 701b50a5c70SMiroslav Lichvar return skb->tstamp && !false_tstamp && skb_is_err_queue(skb); 702b50a5c70SMiroslav Lichvar } 703b50a5c70SMiroslav Lichvar 704aad9c8c4SMiroslav Lichvar static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb) 705aad9c8c4SMiroslav Lichvar { 706aad9c8c4SMiroslav Lichvar struct scm_ts_pktinfo ts_pktinfo; 707aad9c8c4SMiroslav Lichvar struct net_device *orig_dev; 708aad9c8c4SMiroslav Lichvar 709aad9c8c4SMiroslav Lichvar if (!skb_mac_header_was_set(skb)) 710aad9c8c4SMiroslav Lichvar return; 711aad9c8c4SMiroslav Lichvar 712aad9c8c4SMiroslav Lichvar memset(&ts_pktinfo, 0, sizeof(ts_pktinfo)); 713aad9c8c4SMiroslav Lichvar 714aad9c8c4SMiroslav Lichvar rcu_read_lock(); 715aad9c8c4SMiroslav Lichvar orig_dev = dev_get_by_napi_id(skb_napi_id(skb)); 716aad9c8c4SMiroslav Lichvar if (orig_dev) 717aad9c8c4SMiroslav Lichvar ts_pktinfo.if_index = orig_dev->ifindex; 718aad9c8c4SMiroslav Lichvar rcu_read_unlock(); 719aad9c8c4SMiroslav Lichvar 720aad9c8c4SMiroslav Lichvar ts_pktinfo.pkt_length = skb->len - skb_mac_offset(skb); 721aad9c8c4SMiroslav Lichvar put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO, 722aad9c8c4SMiroslav Lichvar sizeof(ts_pktinfo), &ts_pktinfo); 723aad9c8c4SMiroslav Lichvar } 724aad9c8c4SMiroslav Lichvar 72592f37fd2SEric Dumazet /* 72692f37fd2SEric Dumazet * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) 72792f37fd2SEric Dumazet */ 72892f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, 72992f37fd2SEric Dumazet struct sk_buff *skb) 73092f37fd2SEric Dumazet { 73120d49473SPatrick Ohly int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); 732f24b9be5SWillem de Bruijn struct scm_timestamping tss; 733b50a5c70SMiroslav Lichvar int empty = 1, false_tstamp = 0; 73420d49473SPatrick Ohly struct skb_shared_hwtstamps *shhwtstamps = 73520d49473SPatrick Ohly skb_hwtstamps(skb); 73692f37fd2SEric Dumazet 73720d49473SPatrick Ohly /* Race occurred between timestamp enabling and packet 73820d49473SPatrick Ohly receiving. Fill in the current time for now. */ 739b50a5c70SMiroslav Lichvar if (need_software_tstamp && skb->tstamp == 0) { 74020d49473SPatrick Ohly __net_timestamp(skb); 741b50a5c70SMiroslav Lichvar false_tstamp = 1; 742b50a5c70SMiroslav Lichvar } 74320d49473SPatrick Ohly 74420d49473SPatrick Ohly if (need_software_tstamp) { 74592f37fd2SEric Dumazet if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { 74692f37fd2SEric Dumazet struct timeval tv; 74720d49473SPatrick Ohly skb_get_timestamp(skb, &tv); 74820d49473SPatrick Ohly put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, 74920d49473SPatrick Ohly sizeof(tv), &tv); 75092f37fd2SEric Dumazet } else { 751f24b9be5SWillem de Bruijn struct timespec ts; 752f24b9be5SWillem de Bruijn skb_get_timestampns(skb, &ts); 75320d49473SPatrick Ohly put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, 754f24b9be5SWillem de Bruijn sizeof(ts), &ts); 75592f37fd2SEric Dumazet } 75692f37fd2SEric Dumazet } 75792f37fd2SEric Dumazet 758f24b9be5SWillem de Bruijn memset(&tss, 0, sizeof(tss)); 759c199105dSWillem de Bruijn if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) && 760f24b9be5SWillem de Bruijn ktime_to_timespec_cond(skb->tstamp, tss.ts + 0)) 76120d49473SPatrick Ohly empty = 0; 7624d276eb6SWillem de Bruijn if (shhwtstamps && 763b9f40e21SWillem de Bruijn (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && 764b50a5c70SMiroslav Lichvar !skb_is_swtx_tstamp(skb, false_tstamp) && 765aad9c8c4SMiroslav Lichvar ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) { 76620d49473SPatrick Ohly empty = 0; 767aad9c8c4SMiroslav Lichvar if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) && 768aad9c8c4SMiroslav Lichvar !skb_is_err_queue(skb)) 769aad9c8c4SMiroslav Lichvar put_ts_pktinfo(msg, skb); 770aad9c8c4SMiroslav Lichvar } 7711c885808SFrancis Yan if (!empty) { 77220d49473SPatrick Ohly put_cmsg(msg, SOL_SOCKET, 773f24b9be5SWillem de Bruijn SCM_TIMESTAMPING, sizeof(tss), &tss); 7741c885808SFrancis Yan 7758605330aSSoheil Hassas Yeganeh if (skb_is_err_queue(skb) && skb->len && 7764ef1b286SSoheil Hassas Yeganeh SKB_EXT_ERR(skb)->opt_stats) 7771c885808SFrancis Yan put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS, 7781c885808SFrancis Yan skb->len, skb->data); 7791c885808SFrancis Yan } 78020d49473SPatrick Ohly } 7817c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp); 7827c81fd8bSArnaldo Carvalho de Melo 7836e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk, 7846e3e939fSJohannes Berg struct sk_buff *skb) 7856e3e939fSJohannes Berg { 7866e3e939fSJohannes Berg int ack; 7876e3e939fSJohannes Berg 7886e3e939fSJohannes Berg if (!sock_flag(sk, SOCK_WIFI_STATUS)) 7896e3e939fSJohannes Berg return; 7906e3e939fSJohannes Berg if (!skb->wifi_acked_valid) 7916e3e939fSJohannes Berg return; 7926e3e939fSJohannes Berg 7936e3e939fSJohannes Berg ack = skb->wifi_acked; 7946e3e939fSJohannes Berg 7956e3e939fSJohannes Berg put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack); 7966e3e939fSJohannes Berg } 7976e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status); 7986e3e939fSJohannes Berg 79911165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, 80011165f14Sstephen hemminger struct sk_buff *skb) 8013b885787SNeil Horman { 802744d5a3eSEyal Birger if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && SOCK_SKB_CB(skb)->dropcount) 8033b885787SNeil Horman put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL, 804744d5a3eSEyal Birger sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount); 8053b885787SNeil Horman } 8063b885787SNeil Horman 807767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, 8083b885787SNeil Horman struct sk_buff *skb) 8093b885787SNeil Horman { 8103b885787SNeil Horman sock_recv_timestamp(msg, sk, skb); 8113b885787SNeil Horman sock_recv_drops(msg, sk, skb); 8123b885787SNeil Horman } 813767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops); 8143b885787SNeil Horman 8151b784140SYing Xue static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg, 8161b784140SYing Xue int flags) 817a2e27255SArnaldo Carvalho de Melo { 8182da62906SAl Viro return sock->ops->recvmsg(sock, msg, msg_data_left(msg), flags); 8192da62906SAl Viro } 820a2e27255SArnaldo Carvalho de Melo 8212da62906SAl Viro int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags) 8222da62906SAl Viro { 8232da62906SAl Viro int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags); 8242da62906SAl Viro 8252da62906SAl Viro return err ?: sock_recvmsg_nosec(sock, msg, flags); 8261da177e4SLinus Torvalds } 827c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg); 8281da177e4SLinus Torvalds 829c1249c0aSMartin Lucina /** 830c1249c0aSMartin Lucina * kernel_recvmsg - Receive a message from a socket (kernel space) 831c1249c0aSMartin Lucina * @sock: The socket to receive the message from 832c1249c0aSMartin Lucina * @msg: Received message 833c1249c0aSMartin Lucina * @vec: Input s/g array for message data 834c1249c0aSMartin Lucina * @num: Size of input s/g array 835c1249c0aSMartin Lucina * @size: Number of bytes to read 836c1249c0aSMartin Lucina * @flags: Message flags (MSG_DONTWAIT, etc...) 837c1249c0aSMartin Lucina * 838c1249c0aSMartin Lucina * On return the msg structure contains the scatter/gather array passed in the 839c1249c0aSMartin Lucina * vec argument. The array is modified so that it consists of the unfilled 840c1249c0aSMartin Lucina * portion of the original array. 841c1249c0aSMartin Lucina * 842c1249c0aSMartin Lucina * The returned value is the total number of bytes received, or an error. 843c1249c0aSMartin Lucina */ 8441da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg, 84589bddce5SStephen Hemminger struct kvec *vec, size_t num, size_t size, int flags) 8461da177e4SLinus Torvalds { 8471da177e4SLinus Torvalds mm_segment_t oldfs = get_fs(); 8481da177e4SLinus Torvalds int result; 8491da177e4SLinus Torvalds 8506aa24814SAl Viro iov_iter_kvec(&msg->msg_iter, READ | ITER_KVEC, vec, num, size); 8511da177e4SLinus Torvalds set_fs(KERNEL_DS); 8522da62906SAl Viro result = sock_recvmsg(sock, msg, flags); 8531da177e4SLinus Torvalds set_fs(oldfs); 8541da177e4SLinus Torvalds return result; 8551da177e4SLinus Torvalds } 856c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg); 8571da177e4SLinus Torvalds 85820380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page, 8591da177e4SLinus Torvalds int offset, size_t size, loff_t *ppos, int more) 8601da177e4SLinus Torvalds { 8611da177e4SLinus Torvalds struct socket *sock; 8621da177e4SLinus Torvalds int flags; 8631da177e4SLinus Torvalds 864b69aee04SEric Dumazet sock = file->private_data; 8651da177e4SLinus Torvalds 86635f9c09fSEric Dumazet flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; 86735f9c09fSEric Dumazet /* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */ 86835f9c09fSEric Dumazet flags |= more; 8691da177e4SLinus Torvalds 870e6949583SLinus Torvalds return kernel_sendpage(sock, page, offset, size, flags); 8711da177e4SLinus Torvalds } 8721da177e4SLinus Torvalds 8739c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos, 8749c55e01cSJens Axboe struct pipe_inode_info *pipe, size_t len, 8759c55e01cSJens Axboe unsigned int flags) 8769c55e01cSJens Axboe { 8779c55e01cSJens Axboe struct socket *sock = file->private_data; 8789c55e01cSJens Axboe 879997b37daSRémi Denis-Courmont if (unlikely(!sock->ops->splice_read)) 880997b37daSRémi Denis-Courmont return -EINVAL; 881997b37daSRémi Denis-Courmont 8829c55e01cSJens Axboe return sock->ops->splice_read(sock, ppos, pipe, len, flags); 8839c55e01cSJens Axboe } 8849c55e01cSJens Axboe 8858ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to) 886ce1d4d3eSChristoph Hellwig { 8876d652330SAl Viro struct file *file = iocb->ki_filp; 8886d652330SAl Viro struct socket *sock = file->private_data; 8890345f931Stadeusz.struk@intel.com struct msghdr msg = {.msg_iter = *to, 8900345f931Stadeusz.struk@intel.com .msg_iocb = iocb}; 8918ae5e030SAl Viro ssize_t res; 892ce1d4d3eSChristoph Hellwig 8938ae5e030SAl Viro if (file->f_flags & O_NONBLOCK) 8948ae5e030SAl Viro msg.msg_flags = MSG_DONTWAIT; 8958ae5e030SAl Viro 8968ae5e030SAl Viro if (iocb->ki_pos != 0) 897ce1d4d3eSChristoph Hellwig return -ESPIPE; 898027445c3SBadari Pulavarty 89966ee59afSChristoph Hellwig if (!iov_iter_count(to)) /* Match SYS5 behaviour */ 900ce1d4d3eSChristoph Hellwig return 0; 901ce1d4d3eSChristoph Hellwig 9022da62906SAl Viro res = sock_recvmsg(sock, &msg, msg.msg_flags); 9038ae5e030SAl Viro *to = msg.msg_iter; 9048ae5e030SAl Viro return res; 905ce1d4d3eSChristoph Hellwig } 906ce1d4d3eSChristoph Hellwig 9078ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from) 9081da177e4SLinus Torvalds { 9096d652330SAl Viro struct file *file = iocb->ki_filp; 9106d652330SAl Viro struct socket *sock = file->private_data; 9110345f931Stadeusz.struk@intel.com struct msghdr msg = {.msg_iter = *from, 9120345f931Stadeusz.struk@intel.com .msg_iocb = iocb}; 9138ae5e030SAl Viro ssize_t res; 9141da177e4SLinus Torvalds 9158ae5e030SAl Viro if (iocb->ki_pos != 0) 916ce1d4d3eSChristoph Hellwig return -ESPIPE; 917027445c3SBadari Pulavarty 9188ae5e030SAl Viro if (file->f_flags & O_NONBLOCK) 9198ae5e030SAl Viro msg.msg_flags = MSG_DONTWAIT; 9208ae5e030SAl Viro 9216d652330SAl Viro if (sock->type == SOCK_SEQPACKET) 9226d652330SAl Viro msg.msg_flags |= MSG_EOR; 9236d652330SAl Viro 924d8725c86SAl Viro res = sock_sendmsg(sock, &msg); 9258ae5e030SAl Viro *from = msg.msg_iter; 9268ae5e030SAl Viro return res; 9271da177e4SLinus Torvalds } 9281da177e4SLinus Torvalds 9291da177e4SLinus Torvalds /* 9301da177e4SLinus Torvalds * Atomic setting of ioctl hooks to avoid race 9311da177e4SLinus Torvalds * with module unload. 9321da177e4SLinus Torvalds */ 9331da177e4SLinus Torvalds 9344a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex); 935c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg); 9361da177e4SLinus Torvalds 937881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *)) 9381da177e4SLinus Torvalds { 9394a3e2f71SArjan van de Ven mutex_lock(&br_ioctl_mutex); 9401da177e4SLinus Torvalds br_ioctl_hook = hook; 9414a3e2f71SArjan van de Ven mutex_unlock(&br_ioctl_mutex); 9421da177e4SLinus Torvalds } 9431da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set); 9441da177e4SLinus Torvalds 9454a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex); 946881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg); 9471da177e4SLinus Torvalds 948881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *)) 9491da177e4SLinus Torvalds { 9504a3e2f71SArjan van de Ven mutex_lock(&vlan_ioctl_mutex); 9511da177e4SLinus Torvalds vlan_ioctl_hook = hook; 9524a3e2f71SArjan van de Ven mutex_unlock(&vlan_ioctl_mutex); 9531da177e4SLinus Torvalds } 9541da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set); 9551da177e4SLinus Torvalds 9564a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex); 9571da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *); 9581da177e4SLinus Torvalds 9591da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *)) 9601da177e4SLinus Torvalds { 9614a3e2f71SArjan van de Ven mutex_lock(&dlci_ioctl_mutex); 9621da177e4SLinus Torvalds dlci_ioctl_hook = hook; 9634a3e2f71SArjan van de Ven mutex_unlock(&dlci_ioctl_mutex); 9641da177e4SLinus Torvalds } 9651da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set); 9661da177e4SLinus Torvalds 9676b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock, 9686b96018bSArnd Bergmann unsigned int cmd, unsigned long arg) 9696b96018bSArnd Bergmann { 9706b96018bSArnd Bergmann int err; 9716b96018bSArnd Bergmann void __user *argp = (void __user *)arg; 9726b96018bSArnd Bergmann 9736b96018bSArnd Bergmann err = sock->ops->ioctl(sock, cmd, arg); 9746b96018bSArnd Bergmann 9756b96018bSArnd Bergmann /* 9766b96018bSArnd Bergmann * If this ioctl is unknown try to hand it down 9776b96018bSArnd Bergmann * to the NIC driver. 9786b96018bSArnd Bergmann */ 97936fd633eSAl Viro if (err != -ENOIOCTLCMD) 9806b96018bSArnd Bergmann return err; 9816b96018bSArnd Bergmann 98236fd633eSAl Viro if (cmd == SIOCGIFCONF) { 98336fd633eSAl Viro struct ifconf ifc; 98436fd633eSAl Viro if (copy_from_user(&ifc, argp, sizeof(struct ifconf))) 98536fd633eSAl Viro return -EFAULT; 98636fd633eSAl Viro rtnl_lock(); 98736fd633eSAl Viro err = dev_ifconf(net, &ifc, sizeof(struct ifreq)); 98836fd633eSAl Viro rtnl_unlock(); 98936fd633eSAl Viro if (!err && copy_to_user(argp, &ifc, sizeof(struct ifconf))) 99036fd633eSAl Viro err = -EFAULT; 99144c02a2cSAl Viro } else { 99244c02a2cSAl Viro struct ifreq ifr; 99344c02a2cSAl Viro bool need_copyout; 99444c02a2cSAl Viro if (copy_from_user(&ifr, argp, sizeof(struct ifreq))) 99544c02a2cSAl Viro return -EFAULT; 99644c02a2cSAl Viro err = dev_ioctl(net, cmd, &ifr, &need_copyout); 99744c02a2cSAl Viro if (!err && need_copyout) 99844c02a2cSAl Viro if (copy_to_user(argp, &ifr, sizeof(struct ifreq))) 99944c02a2cSAl Viro return -EFAULT; 100036fd633eSAl Viro } 10016b96018bSArnd Bergmann return err; 10026b96018bSArnd Bergmann } 10036b96018bSArnd Bergmann 10041da177e4SLinus Torvalds /* 10051da177e4SLinus Torvalds * With an ioctl, arg may well be a user mode pointer, but we don't know 10061da177e4SLinus Torvalds * what to do with it - that's up to the protocol still. 10071da177e4SLinus Torvalds */ 10081da177e4SLinus Torvalds 1009d8d211a2SKirill Tkhai struct ns_common *get_net_ns(struct ns_common *ns) 1010c62cce2cSAndrey Vagin { 1011c62cce2cSAndrey Vagin return &get_net(container_of(ns, struct net, ns))->ns; 1012c62cce2cSAndrey Vagin } 1013d8d211a2SKirill Tkhai EXPORT_SYMBOL_GPL(get_net_ns); 1014c62cce2cSAndrey Vagin 10151da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) 10161da177e4SLinus Torvalds { 10171da177e4SLinus Torvalds struct socket *sock; 1018881d966bSEric W. Biederman struct sock *sk; 10191da177e4SLinus Torvalds void __user *argp = (void __user *)arg; 10201da177e4SLinus Torvalds int pid, err; 1021881d966bSEric W. Biederman struct net *net; 10221da177e4SLinus Torvalds 1023b69aee04SEric Dumazet sock = file->private_data; 1024881d966bSEric W. Biederman sk = sock->sk; 10253b1e0a65SYOSHIFUJI Hideaki net = sock_net(sk); 102644c02a2cSAl Viro if (unlikely(cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))) { 102744c02a2cSAl Viro struct ifreq ifr; 102844c02a2cSAl Viro bool need_copyout; 102944c02a2cSAl Viro if (copy_from_user(&ifr, argp, sizeof(struct ifreq))) 103044c02a2cSAl Viro return -EFAULT; 103144c02a2cSAl Viro err = dev_ioctl(net, cmd, &ifr, &need_copyout); 103244c02a2cSAl Viro if (!err && need_copyout) 103344c02a2cSAl Viro if (copy_to_user(argp, &ifr, sizeof(struct ifreq))) 103444c02a2cSAl Viro return -EFAULT; 10351da177e4SLinus Torvalds } else 10363d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE 10371da177e4SLinus Torvalds if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { 1038b1b0c245SAl Viro err = wext_handle_ioctl(net, cmd, argp); 10391da177e4SLinus Torvalds } else 10403d23e349SJohannes Berg #endif 10411da177e4SLinus Torvalds switch (cmd) { 10421da177e4SLinus Torvalds case FIOSETOWN: 10431da177e4SLinus Torvalds case SIOCSPGRP: 10441da177e4SLinus Torvalds err = -EFAULT; 10451da177e4SLinus Torvalds if (get_user(pid, (int __user *)argp)) 10461da177e4SLinus Torvalds break; 1047393cc3f5SJiri Slaby err = f_setown(sock->file, pid, 1); 10481da177e4SLinus Torvalds break; 10491da177e4SLinus Torvalds case FIOGETOWN: 10501da177e4SLinus Torvalds case SIOCGPGRP: 1051609d7fa9SEric W. Biederman err = put_user(f_getown(sock->file), 105289bddce5SStephen Hemminger (int __user *)argp); 10531da177e4SLinus Torvalds break; 10541da177e4SLinus Torvalds case SIOCGIFBR: 10551da177e4SLinus Torvalds case SIOCSIFBR: 10561da177e4SLinus Torvalds case SIOCBRADDBR: 10571da177e4SLinus Torvalds case SIOCBRDELBR: 10581da177e4SLinus Torvalds err = -ENOPKG; 10591da177e4SLinus Torvalds if (!br_ioctl_hook) 10601da177e4SLinus Torvalds request_module("bridge"); 10611da177e4SLinus Torvalds 10624a3e2f71SArjan van de Ven mutex_lock(&br_ioctl_mutex); 10631da177e4SLinus Torvalds if (br_ioctl_hook) 1064881d966bSEric W. Biederman err = br_ioctl_hook(net, cmd, argp); 10654a3e2f71SArjan van de Ven mutex_unlock(&br_ioctl_mutex); 10661da177e4SLinus Torvalds break; 10671da177e4SLinus Torvalds case SIOCGIFVLAN: 10681da177e4SLinus Torvalds case SIOCSIFVLAN: 10691da177e4SLinus Torvalds err = -ENOPKG; 10701da177e4SLinus Torvalds if (!vlan_ioctl_hook) 10711da177e4SLinus Torvalds request_module("8021q"); 10721da177e4SLinus Torvalds 10734a3e2f71SArjan van de Ven mutex_lock(&vlan_ioctl_mutex); 10741da177e4SLinus Torvalds if (vlan_ioctl_hook) 1075881d966bSEric W. Biederman err = vlan_ioctl_hook(net, argp); 10764a3e2f71SArjan van de Ven mutex_unlock(&vlan_ioctl_mutex); 10771da177e4SLinus Torvalds break; 10781da177e4SLinus Torvalds case SIOCADDDLCI: 10791da177e4SLinus Torvalds case SIOCDELDLCI: 10801da177e4SLinus Torvalds err = -ENOPKG; 10811da177e4SLinus Torvalds if (!dlci_ioctl_hook) 10821da177e4SLinus Torvalds request_module("dlci"); 10831da177e4SLinus Torvalds 10844a3e2f71SArjan van de Ven mutex_lock(&dlci_ioctl_mutex); 10857512cbf6SPavel Emelyanov if (dlci_ioctl_hook) 10861da177e4SLinus Torvalds err = dlci_ioctl_hook(cmd, argp); 10874a3e2f71SArjan van de Ven mutex_unlock(&dlci_ioctl_mutex); 10881da177e4SLinus Torvalds break; 1089c62cce2cSAndrey Vagin case SIOCGSKNS: 1090c62cce2cSAndrey Vagin err = -EPERM; 1091c62cce2cSAndrey Vagin if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) 1092c62cce2cSAndrey Vagin break; 1093c62cce2cSAndrey Vagin 1094c62cce2cSAndrey Vagin err = open_related_ns(&net->ns, get_net_ns); 1095c62cce2cSAndrey Vagin break; 10961da177e4SLinus Torvalds default: 10976b96018bSArnd Bergmann err = sock_do_ioctl(net, sock, cmd, arg); 10981da177e4SLinus Torvalds break; 10991da177e4SLinus Torvalds } 11001da177e4SLinus Torvalds return err; 11011da177e4SLinus Torvalds } 11021da177e4SLinus Torvalds 11031da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res) 11041da177e4SLinus Torvalds { 11051da177e4SLinus Torvalds int err; 11061da177e4SLinus Torvalds struct socket *sock = NULL; 11071da177e4SLinus Torvalds 11081da177e4SLinus Torvalds err = security_socket_create(family, type, protocol, 1); 11091da177e4SLinus Torvalds if (err) 11101da177e4SLinus Torvalds goto out; 11111da177e4SLinus Torvalds 11121da177e4SLinus Torvalds sock = sock_alloc(); 11131da177e4SLinus Torvalds if (!sock) { 11141da177e4SLinus Torvalds err = -ENOMEM; 11151da177e4SLinus Torvalds goto out; 11161da177e4SLinus Torvalds } 11171da177e4SLinus Torvalds 11181da177e4SLinus Torvalds sock->type = type; 11197420ed23SVenkat Yekkirala err = security_socket_post_create(sock, family, type, protocol, 1); 11207420ed23SVenkat Yekkirala if (err) 11217420ed23SVenkat Yekkirala goto out_release; 11227420ed23SVenkat Yekkirala 11231da177e4SLinus Torvalds out: 11241da177e4SLinus Torvalds *res = sock; 11251da177e4SLinus Torvalds return err; 11267420ed23SVenkat Yekkirala out_release: 11277420ed23SVenkat Yekkirala sock_release(sock); 11287420ed23SVenkat Yekkirala sock = NULL; 11297420ed23SVenkat Yekkirala goto out; 11301da177e4SLinus Torvalds } 1131c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite); 11321da177e4SLinus Torvalds 113315252423SChristoph Hellwig static struct wait_queue_head *sock_get_poll_head(struct file *file, 113415252423SChristoph Hellwig __poll_t events) 113515252423SChristoph Hellwig { 113615252423SChristoph Hellwig struct socket *sock = file->private_data; 113715252423SChristoph Hellwig 113815252423SChristoph Hellwig if (!sock->ops->poll_mask) 113915252423SChristoph Hellwig return NULL; 114015252423SChristoph Hellwig sock_poll_busy_loop(sock, events); 114115252423SChristoph Hellwig return sk_sleep(sock->sk); 114215252423SChristoph Hellwig } 114315252423SChristoph Hellwig 114415252423SChristoph Hellwig static __poll_t sock_poll_mask(struct file *file, __poll_t events) 114515252423SChristoph Hellwig { 114615252423SChristoph Hellwig struct socket *sock = file->private_data; 114715252423SChristoph Hellwig 114815252423SChristoph Hellwig /* 114915252423SChristoph Hellwig * We need to be sure we are in sync with the socket flags modification. 115015252423SChristoph Hellwig * 115115252423SChristoph Hellwig * This memory barrier is paired in the wq_has_sleeper. 115215252423SChristoph Hellwig */ 115315252423SChristoph Hellwig smp_mb(); 115415252423SChristoph Hellwig 115515252423SChristoph Hellwig /* this socket can poll_ll so tell the system call */ 115615252423SChristoph Hellwig return sock->ops->poll_mask(sock, events) | 115715252423SChristoph Hellwig (sk_can_busy_loop(sock->sk) ? POLL_BUSY_LOOP : 0); 115815252423SChristoph Hellwig } 115915252423SChristoph Hellwig 11601da177e4SLinus Torvalds /* No kernel lock held - perfect */ 1161ade994f4SAl Viro static __poll_t sock_poll(struct file *file, poll_table *wait) 11621da177e4SLinus Torvalds { 11633cafb376SChristoph Hellwig struct socket *sock = file->private_data; 116415252423SChristoph Hellwig __poll_t events = poll_requested_events(wait), mask = 0; 11651da177e4SLinus Torvalds 116615252423SChristoph Hellwig if (sock->ops->poll) { 11673cafb376SChristoph Hellwig sock_poll_busy_loop(sock, events); 116815252423SChristoph Hellwig mask = sock->ops->poll(file, sock, wait); 116915252423SChristoph Hellwig } else if (sock->ops->poll_mask) { 117015252423SChristoph Hellwig sock_poll_wait(file, sock_get_poll_head(file, events), wait); 117115252423SChristoph Hellwig mask = sock->ops->poll_mask(sock, events); 117215252423SChristoph Hellwig } 117315252423SChristoph Hellwig 117415252423SChristoph Hellwig return mask | sock_poll_busy_flag(sock); 11751da177e4SLinus Torvalds } 11761da177e4SLinus Torvalds 11771da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma) 11781da177e4SLinus Torvalds { 1179b69aee04SEric Dumazet struct socket *sock = file->private_data; 11801da177e4SLinus Torvalds 11811da177e4SLinus Torvalds return sock->ops->mmap(file, sock, vma); 11821da177e4SLinus Torvalds } 11831da177e4SLinus Torvalds 118420380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp) 11851da177e4SLinus Torvalds { 11866d8c50dcSCong Wang __sock_release(SOCKET_I(inode), inode); 11871da177e4SLinus Torvalds return 0; 11881da177e4SLinus Torvalds } 11891da177e4SLinus Torvalds 11901da177e4SLinus Torvalds /* 11911da177e4SLinus Torvalds * Update the socket async list 11921da177e4SLinus Torvalds * 11931da177e4SLinus Torvalds * Fasync_list locking strategy. 11941da177e4SLinus Torvalds * 11951da177e4SLinus Torvalds * 1. fasync_list is modified only under process context socket lock 11961da177e4SLinus Torvalds * i.e. under semaphore. 11971da177e4SLinus Torvalds * 2. fasync_list is used under read_lock(&sk->sk_callback_lock) 1198989a2979SEric Dumazet * or under socket lock 11991da177e4SLinus Torvalds */ 12001da177e4SLinus Torvalds 12011da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on) 12021da177e4SLinus Torvalds { 1203989a2979SEric Dumazet struct socket *sock = filp->private_data; 1204989a2979SEric Dumazet struct sock *sk = sock->sk; 1205eaefd110SEric Dumazet struct socket_wq *wq; 12061da177e4SLinus Torvalds 1207989a2979SEric Dumazet if (sk == NULL) 12081da177e4SLinus Torvalds return -EINVAL; 12091da177e4SLinus Torvalds 12101da177e4SLinus Torvalds lock_sock(sk); 12111e1d04e6SHannes Frederic Sowa wq = rcu_dereference_protected(sock->wq, lockdep_sock_is_held(sk)); 1212eaefd110SEric Dumazet fasync_helper(fd, filp, on, &wq->fasync_list); 12131da177e4SLinus Torvalds 1214eaefd110SEric Dumazet if (!wq->fasync_list) 1215bcdce719SEric Dumazet sock_reset_flag(sk, SOCK_FASYNC); 1216989a2979SEric Dumazet else 1217989a2979SEric Dumazet sock_set_flag(sk, SOCK_FASYNC); 12181da177e4SLinus Torvalds 1219989a2979SEric Dumazet release_sock(sk); 12201da177e4SLinus Torvalds return 0; 12211da177e4SLinus Torvalds } 12221da177e4SLinus Torvalds 1223ceb5d58bSEric Dumazet /* This function may be called only under rcu_lock */ 12241da177e4SLinus Torvalds 1225ceb5d58bSEric Dumazet int sock_wake_async(struct socket_wq *wq, int how, int band) 12261da177e4SLinus Torvalds { 1227ceb5d58bSEric Dumazet if (!wq || !wq->fasync_list) 1228ceb5d58bSEric Dumazet return -1; 122943815482SEric Dumazet 123089bddce5SStephen Hemminger switch (how) { 12318d8ad9d7SPavel Emelyanov case SOCK_WAKE_WAITD: 1232ceb5d58bSEric Dumazet if (test_bit(SOCKWQ_ASYNC_WAITDATA, &wq->flags)) 12331da177e4SLinus Torvalds break; 12341da177e4SLinus Torvalds goto call_kill; 12358d8ad9d7SPavel Emelyanov case SOCK_WAKE_SPACE: 1236ceb5d58bSEric Dumazet if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags)) 12371da177e4SLinus Torvalds break; 12381da177e4SLinus Torvalds /* fall through */ 12398d8ad9d7SPavel Emelyanov case SOCK_WAKE_IO: 12401da177e4SLinus Torvalds call_kill: 124143815482SEric Dumazet kill_fasync(&wq->fasync_list, SIGIO, band); 12421da177e4SLinus Torvalds break; 12438d8ad9d7SPavel Emelyanov case SOCK_WAKE_URG: 124443815482SEric Dumazet kill_fasync(&wq->fasync_list, SIGURG, band); 12451da177e4SLinus Torvalds } 1246ceb5d58bSEric Dumazet 12471da177e4SLinus Torvalds return 0; 12481da177e4SLinus Torvalds } 1249c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async); 12501da177e4SLinus Torvalds 1251721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol, 125289bddce5SStephen Hemminger struct socket **res, int kern) 12531da177e4SLinus Torvalds { 12541da177e4SLinus Torvalds int err; 12551da177e4SLinus Torvalds struct socket *sock; 125655737fdaSStephen Hemminger const struct net_proto_family *pf; 12571da177e4SLinus Torvalds 12581da177e4SLinus Torvalds /* 12591da177e4SLinus Torvalds * Check protocol is in range 12601da177e4SLinus Torvalds */ 12611da177e4SLinus Torvalds if (family < 0 || family >= NPROTO) 12621da177e4SLinus Torvalds return -EAFNOSUPPORT; 12631da177e4SLinus Torvalds if (type < 0 || type >= SOCK_MAX) 12641da177e4SLinus Torvalds return -EINVAL; 12651da177e4SLinus Torvalds 12661da177e4SLinus Torvalds /* Compatibility. 12671da177e4SLinus Torvalds 12681da177e4SLinus Torvalds This uglymoron is moved from INET layer to here to avoid 12691da177e4SLinus Torvalds deadlock in module load. 12701da177e4SLinus Torvalds */ 12711da177e4SLinus Torvalds if (family == PF_INET && type == SOCK_PACKET) { 1272f3c98690Sliping.zhang pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n", 127389bddce5SStephen Hemminger current->comm); 12741da177e4SLinus Torvalds family = PF_PACKET; 12751da177e4SLinus Torvalds } 12761da177e4SLinus Torvalds 12771da177e4SLinus Torvalds err = security_socket_create(family, type, protocol, kern); 12781da177e4SLinus Torvalds if (err) 12791da177e4SLinus Torvalds return err; 12801da177e4SLinus Torvalds 128155737fdaSStephen Hemminger /* 128255737fdaSStephen Hemminger * Allocate the socket and allow the family to set things up. if 128355737fdaSStephen Hemminger * the protocol is 0, the family is instructed to select an appropriate 128455737fdaSStephen Hemminger * default. 128555737fdaSStephen Hemminger */ 128655737fdaSStephen Hemminger sock = sock_alloc(); 128755737fdaSStephen Hemminger if (!sock) { 1288e87cc472SJoe Perches net_warn_ratelimited("socket: no more sockets\n"); 128955737fdaSStephen Hemminger return -ENFILE; /* Not exactly a match, but its the 129055737fdaSStephen Hemminger closest posix thing */ 129155737fdaSStephen Hemminger } 129255737fdaSStephen Hemminger 129355737fdaSStephen Hemminger sock->type = type; 129455737fdaSStephen Hemminger 129595a5afcaSJohannes Berg #ifdef CONFIG_MODULES 12961da177e4SLinus Torvalds /* Attempt to load a protocol module if the find failed. 12971da177e4SLinus Torvalds * 12981da177e4SLinus Torvalds * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user 12991da177e4SLinus Torvalds * requested real, full-featured networking support upon configuration. 13001da177e4SLinus Torvalds * Otherwise module support will break! 13011da177e4SLinus Torvalds */ 1302190683a9SEric Dumazet if (rcu_access_pointer(net_families[family]) == NULL) 13031da177e4SLinus Torvalds request_module("net-pf-%d", family); 13041da177e4SLinus Torvalds #endif 13051da177e4SLinus Torvalds 130655737fdaSStephen Hemminger rcu_read_lock(); 130755737fdaSStephen Hemminger pf = rcu_dereference(net_families[family]); 13081da177e4SLinus Torvalds err = -EAFNOSUPPORT; 130955737fdaSStephen Hemminger if (!pf) 131055737fdaSStephen Hemminger goto out_release; 13111da177e4SLinus Torvalds 13121da177e4SLinus Torvalds /* 13131da177e4SLinus Torvalds * We will call the ->create function, that possibly is in a loadable 13141da177e4SLinus Torvalds * module, so we have to bump that loadable module refcnt first. 13151da177e4SLinus Torvalds */ 131655737fdaSStephen Hemminger if (!try_module_get(pf->owner)) 13171da177e4SLinus Torvalds goto out_release; 13181da177e4SLinus Torvalds 131955737fdaSStephen Hemminger /* Now protected by module ref count */ 132055737fdaSStephen Hemminger rcu_read_unlock(); 132155737fdaSStephen Hemminger 13223f378b68SEric Paris err = pf->create(net, sock, protocol, kern); 132355737fdaSStephen Hemminger if (err < 0) 13241da177e4SLinus Torvalds goto out_module_put; 1325a79af59eSFrank Filz 13261da177e4SLinus Torvalds /* 13271da177e4SLinus Torvalds * Now to bump the refcnt of the [loadable] module that owns this 13281da177e4SLinus Torvalds * socket at sock_release time we decrement its refcnt. 13291da177e4SLinus Torvalds */ 133055737fdaSStephen Hemminger if (!try_module_get(sock->ops->owner)) 133155737fdaSStephen Hemminger goto out_module_busy; 133255737fdaSStephen Hemminger 13331da177e4SLinus Torvalds /* 13341da177e4SLinus Torvalds * Now that we're done with the ->create function, the [loadable] 13351da177e4SLinus Torvalds * module can have its refcnt decremented 13361da177e4SLinus Torvalds */ 133755737fdaSStephen Hemminger module_put(pf->owner); 13387420ed23SVenkat Yekkirala err = security_socket_post_create(sock, family, type, protocol, kern); 13397420ed23SVenkat Yekkirala if (err) 13403b185525SHerbert Xu goto out_sock_release; 134155737fdaSStephen Hemminger *res = sock; 13421da177e4SLinus Torvalds 134355737fdaSStephen Hemminger return 0; 134455737fdaSStephen Hemminger 134555737fdaSStephen Hemminger out_module_busy: 134655737fdaSStephen Hemminger err = -EAFNOSUPPORT; 13471da177e4SLinus Torvalds out_module_put: 134855737fdaSStephen Hemminger sock->ops = NULL; 134955737fdaSStephen Hemminger module_put(pf->owner); 135055737fdaSStephen Hemminger out_sock_release: 13511da177e4SLinus Torvalds sock_release(sock); 135255737fdaSStephen Hemminger return err; 135355737fdaSStephen Hemminger 135455737fdaSStephen Hemminger out_release: 135555737fdaSStephen Hemminger rcu_read_unlock(); 135655737fdaSStephen Hemminger goto out_sock_release; 13571da177e4SLinus Torvalds } 1358721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create); 13591da177e4SLinus Torvalds 13601da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res) 13611da177e4SLinus Torvalds { 13621b8d7ae4SEric W. Biederman return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0); 13631da177e4SLinus Torvalds } 1364c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create); 13651da177e4SLinus Torvalds 1366eeb1bd5cSEric W. Biederman int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res) 13671da177e4SLinus Torvalds { 1368eeb1bd5cSEric W. Biederman return __sock_create(net, family, type, protocol, res, 1); 13691da177e4SLinus Torvalds } 1370c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern); 13711da177e4SLinus Torvalds 13729d6a15c3SDominik Brodowski int __sys_socket(int family, int type, int protocol) 13731da177e4SLinus Torvalds { 13741da177e4SLinus Torvalds int retval; 13751da177e4SLinus Torvalds struct socket *sock; 1376a677a039SUlrich Drepper int flags; 1377a677a039SUlrich Drepper 1378e38b36f3SUlrich Drepper /* Check the SOCK_* constants for consistency. */ 1379e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC); 1380e38b36f3SUlrich Drepper BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK); 1381e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK); 1382e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK); 1383e38b36f3SUlrich Drepper 1384a677a039SUlrich Drepper flags = type & ~SOCK_TYPE_MASK; 138577d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1386a677a039SUlrich Drepper return -EINVAL; 1387a677a039SUlrich Drepper type &= SOCK_TYPE_MASK; 13881da177e4SLinus Torvalds 1389aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1390aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1391aaca0bdcSUlrich Drepper 13921da177e4SLinus Torvalds retval = sock_create(family, type, protocol, &sock); 13931da177e4SLinus Torvalds if (retval < 0) 13941da177e4SLinus Torvalds return retval; 13951da177e4SLinus Torvalds 13968e1611e2SAl Viro return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); 13971da177e4SLinus Torvalds } 13981da177e4SLinus Torvalds 13999d6a15c3SDominik Brodowski SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) 14009d6a15c3SDominik Brodowski { 14019d6a15c3SDominik Brodowski return __sys_socket(family, type, protocol); 14029d6a15c3SDominik Brodowski } 14039d6a15c3SDominik Brodowski 14041da177e4SLinus Torvalds /* 14051da177e4SLinus Torvalds * Create a pair of connected sockets. 14061da177e4SLinus Torvalds */ 14071da177e4SLinus Torvalds 14086debc8d8SDominik Brodowski int __sys_socketpair(int family, int type, int protocol, int __user *usockvec) 14091da177e4SLinus Torvalds { 14101da177e4SLinus Torvalds struct socket *sock1, *sock2; 14111da177e4SLinus Torvalds int fd1, fd2, err; 1412db349509SAl Viro struct file *newfile1, *newfile2; 1413a677a039SUlrich Drepper int flags; 1414a677a039SUlrich Drepper 1415a677a039SUlrich Drepper flags = type & ~SOCK_TYPE_MASK; 141677d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1417a677a039SUlrich Drepper return -EINVAL; 1418a677a039SUlrich Drepper type &= SOCK_TYPE_MASK; 14191da177e4SLinus Torvalds 1420aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1421aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1422aaca0bdcSUlrich Drepper 14231da177e4SLinus Torvalds /* 1424016a266bSAl Viro * reserve descriptors and make sure we won't fail 1425016a266bSAl Viro * to return them to userland. 1426016a266bSAl Viro */ 1427016a266bSAl Viro fd1 = get_unused_fd_flags(flags); 1428016a266bSAl Viro if (unlikely(fd1 < 0)) 1429016a266bSAl Viro return fd1; 1430016a266bSAl Viro 1431016a266bSAl Viro fd2 = get_unused_fd_flags(flags); 1432016a266bSAl Viro if (unlikely(fd2 < 0)) { 1433016a266bSAl Viro put_unused_fd(fd1); 1434016a266bSAl Viro return fd2; 1435016a266bSAl Viro } 1436016a266bSAl Viro 1437016a266bSAl Viro err = put_user(fd1, &usockvec[0]); 1438016a266bSAl Viro if (err) 1439016a266bSAl Viro goto out; 1440016a266bSAl Viro 1441016a266bSAl Viro err = put_user(fd2, &usockvec[1]); 1442016a266bSAl Viro if (err) 1443016a266bSAl Viro goto out; 1444016a266bSAl Viro 1445016a266bSAl Viro /* 14461da177e4SLinus Torvalds * Obtain the first socket and check if the underlying protocol 14471da177e4SLinus Torvalds * supports the socketpair call. 14481da177e4SLinus Torvalds */ 14491da177e4SLinus Torvalds 14501da177e4SLinus Torvalds err = sock_create(family, type, protocol, &sock1); 1451016a266bSAl Viro if (unlikely(err < 0)) 14521da177e4SLinus Torvalds goto out; 14531da177e4SLinus Torvalds 14541da177e4SLinus Torvalds err = sock_create(family, type, protocol, &sock2); 1455016a266bSAl Viro if (unlikely(err < 0)) { 1456016a266bSAl Viro sock_release(sock1); 1457016a266bSAl Viro goto out; 1458bf3c23d1SDavid S. Miller } 1459d73aa286SYann Droneaud 1460d47cd945SDavid Herrmann err = security_socket_socketpair(sock1, sock2); 1461d47cd945SDavid Herrmann if (unlikely(err)) { 1462d47cd945SDavid Herrmann sock_release(sock2); 1463d47cd945SDavid Herrmann sock_release(sock1); 1464d47cd945SDavid Herrmann goto out; 1465d47cd945SDavid Herrmann } 1466d47cd945SDavid Herrmann 1467016a266bSAl Viro err = sock1->ops->socketpair(sock1, sock2); 1468016a266bSAl Viro if (unlikely(err < 0)) { 1469016a266bSAl Viro sock_release(sock2); 1470016a266bSAl Viro sock_release(sock1); 1471016a266bSAl Viro goto out; 147228407630SAl Viro } 147328407630SAl Viro 1474aab174f0SLinus Torvalds newfile1 = sock_alloc_file(sock1, flags, NULL); 1475b5ffe634SViresh Kumar if (IS_ERR(newfile1)) { 147628407630SAl Viro err = PTR_ERR(newfile1); 1477016a266bSAl Viro sock_release(sock2); 1478016a266bSAl Viro goto out; 147928407630SAl Viro } 148028407630SAl Viro 1481aab174f0SLinus Torvalds newfile2 = sock_alloc_file(sock2, flags, NULL); 148228407630SAl Viro if (IS_ERR(newfile2)) { 148328407630SAl Viro err = PTR_ERR(newfile2); 1484016a266bSAl Viro fput(newfile1); 1485016a266bSAl Viro goto out; 1486db349509SAl Viro } 1487db349509SAl Viro 1488157cf649SAl Viro audit_fd_pair(fd1, fd2); 1489d73aa286SYann Droneaud 1490db349509SAl Viro fd_install(fd1, newfile1); 1491db349509SAl Viro fd_install(fd2, newfile2); 14921da177e4SLinus Torvalds return 0; 14931da177e4SLinus Torvalds 14941da177e4SLinus Torvalds out: 1495016a266bSAl Viro put_unused_fd(fd2); 1496016a266bSAl Viro put_unused_fd(fd1); 14971da177e4SLinus Torvalds return err; 14981da177e4SLinus Torvalds } 14991da177e4SLinus Torvalds 15006debc8d8SDominik Brodowski SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, 15016debc8d8SDominik Brodowski int __user *, usockvec) 15026debc8d8SDominik Brodowski { 15036debc8d8SDominik Brodowski return __sys_socketpair(family, type, protocol, usockvec); 15046debc8d8SDominik Brodowski } 15056debc8d8SDominik Brodowski 15061da177e4SLinus Torvalds /* 15071da177e4SLinus Torvalds * Bind a name to a socket. Nothing much to do here since it's 15081da177e4SLinus Torvalds * the protocol's responsibility to handle the local address. 15091da177e4SLinus Torvalds * 15101da177e4SLinus Torvalds * We move the socket address to kernel space before we call 15111da177e4SLinus Torvalds * the protocol layer (having also checked the address is ok). 15121da177e4SLinus Torvalds */ 15131da177e4SLinus Torvalds 1514a87d35d8SDominik Brodowski int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) 15151da177e4SLinus Torvalds { 15161da177e4SLinus Torvalds struct socket *sock; 1517230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 15186cb153caSBenjamin LaHaise int err, fput_needed; 15191da177e4SLinus Torvalds 152089bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 152189bddce5SStephen Hemminger if (sock) { 152243db362dSMaciej Żenczykowski err = move_addr_to_kernel(umyaddr, addrlen, &address); 152389bddce5SStephen Hemminger if (err >= 0) { 152489bddce5SStephen Hemminger err = security_socket_bind(sock, 1525230b1839SYOSHIFUJI Hideaki (struct sockaddr *)&address, 152689bddce5SStephen Hemminger addrlen); 15276cb153caSBenjamin LaHaise if (!err) 15286cb153caSBenjamin LaHaise err = sock->ops->bind(sock, 152989bddce5SStephen Hemminger (struct sockaddr *) 1530230b1839SYOSHIFUJI Hideaki &address, addrlen); 15311da177e4SLinus Torvalds } 15326cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 15331da177e4SLinus Torvalds } 15341da177e4SLinus Torvalds return err; 15351da177e4SLinus Torvalds } 15361da177e4SLinus Torvalds 1537a87d35d8SDominik Brodowski SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen) 1538a87d35d8SDominik Brodowski { 1539a87d35d8SDominik Brodowski return __sys_bind(fd, umyaddr, addrlen); 1540a87d35d8SDominik Brodowski } 1541a87d35d8SDominik Brodowski 15421da177e4SLinus Torvalds /* 15431da177e4SLinus Torvalds * Perform a listen. Basically, we allow the protocol to do anything 15441da177e4SLinus Torvalds * necessary for a listen, and if that works, we mark the socket as 15451da177e4SLinus Torvalds * ready for listening. 15461da177e4SLinus Torvalds */ 15471da177e4SLinus Torvalds 154825e290eeSDominik Brodowski int __sys_listen(int fd, int backlog) 15491da177e4SLinus Torvalds { 15501da177e4SLinus Torvalds struct socket *sock; 15516cb153caSBenjamin LaHaise int err, fput_needed; 1552b8e1f9b5SPavel Emelyanov int somaxconn; 15531da177e4SLinus Torvalds 155489bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 155589bddce5SStephen Hemminger if (sock) { 15568efa6e93SPavel Emelyanov somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn; 155795c96174SEric Dumazet if ((unsigned int)backlog > somaxconn) 1558b8e1f9b5SPavel Emelyanov backlog = somaxconn; 15591da177e4SLinus Torvalds 15601da177e4SLinus Torvalds err = security_socket_listen(sock, backlog); 15616cb153caSBenjamin LaHaise if (!err) 15621da177e4SLinus Torvalds err = sock->ops->listen(sock, backlog); 15636cb153caSBenjamin LaHaise 15646cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 15651da177e4SLinus Torvalds } 15661da177e4SLinus Torvalds return err; 15671da177e4SLinus Torvalds } 15681da177e4SLinus Torvalds 156925e290eeSDominik Brodowski SYSCALL_DEFINE2(listen, int, fd, int, backlog) 157025e290eeSDominik Brodowski { 157125e290eeSDominik Brodowski return __sys_listen(fd, backlog); 157225e290eeSDominik Brodowski } 157325e290eeSDominik Brodowski 15741da177e4SLinus Torvalds /* 15751da177e4SLinus Torvalds * For accept, we attempt to create a new socket, set up the link 15761da177e4SLinus Torvalds * with the client, wake up the client, then return the new 15771da177e4SLinus Torvalds * connected fd. We collect the address of the connector in kernel 15781da177e4SLinus Torvalds * space and move it to user at the very end. This is unclean because 15791da177e4SLinus Torvalds * we open the socket then return an error. 15801da177e4SLinus Torvalds * 15811da177e4SLinus Torvalds * 1003.1g adds the ability to recvmsg() to query connection pending 15821da177e4SLinus Torvalds * status to recvmsg. We need to add that support in a way thats 1583b903036aSGeert Uytterhoeven * clean when we restructure accept also. 15841da177e4SLinus Torvalds */ 15851da177e4SLinus Torvalds 15864541e805SDominik Brodowski int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, 15874541e805SDominik Brodowski int __user *upeer_addrlen, int flags) 15881da177e4SLinus Torvalds { 15891da177e4SLinus Torvalds struct socket *sock, *newsock; 159039d8c1b6SDavid S. Miller struct file *newfile; 15916cb153caSBenjamin LaHaise int err, len, newfd, fput_needed; 1592230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 15931da177e4SLinus Torvalds 159477d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1595aaca0bdcSUlrich Drepper return -EINVAL; 1596aaca0bdcSUlrich Drepper 1597aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1598aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1599aaca0bdcSUlrich Drepper 16006cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 16011da177e4SLinus Torvalds if (!sock) 16021da177e4SLinus Torvalds goto out; 16031da177e4SLinus Torvalds 16041da177e4SLinus Torvalds err = -ENFILE; 1605c6d409cfSEric Dumazet newsock = sock_alloc(); 1606c6d409cfSEric Dumazet if (!newsock) 16071da177e4SLinus Torvalds goto out_put; 16081da177e4SLinus Torvalds 16091da177e4SLinus Torvalds newsock->type = sock->type; 16101da177e4SLinus Torvalds newsock->ops = sock->ops; 16111da177e4SLinus Torvalds 16121da177e4SLinus Torvalds /* 16131da177e4SLinus Torvalds * We don't need try_module_get here, as the listening socket (sock) 16141da177e4SLinus Torvalds * has the protocol module (sock->ops->owner) held. 16151da177e4SLinus Torvalds */ 16161da177e4SLinus Torvalds __module_get(newsock->ops->owner); 16171da177e4SLinus Torvalds 161828407630SAl Viro newfd = get_unused_fd_flags(flags); 161939d8c1b6SDavid S. Miller if (unlikely(newfd < 0)) { 162039d8c1b6SDavid S. Miller err = newfd; 16219a1875e6SDavid S. Miller sock_release(newsock); 16229a1875e6SDavid S. Miller goto out_put; 162339d8c1b6SDavid S. Miller } 1624aab174f0SLinus Torvalds newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name); 1625b5ffe634SViresh Kumar if (IS_ERR(newfile)) { 162628407630SAl Viro err = PTR_ERR(newfile); 162728407630SAl Viro put_unused_fd(newfd); 162828407630SAl Viro goto out_put; 162928407630SAl Viro } 163039d8c1b6SDavid S. Miller 1631a79af59eSFrank Filz err = security_socket_accept(sock, newsock); 1632a79af59eSFrank Filz if (err) 163339d8c1b6SDavid S. Miller goto out_fd; 1634a79af59eSFrank Filz 1635cdfbabfbSDavid Howells err = sock->ops->accept(sock, newsock, sock->file->f_flags, false); 16361da177e4SLinus Torvalds if (err < 0) 163739d8c1b6SDavid S. Miller goto out_fd; 16381da177e4SLinus Torvalds 16391da177e4SLinus Torvalds if (upeer_sockaddr) { 16409b2c45d4SDenys Vlasenko len = newsock->ops->getname(newsock, 16419b2c45d4SDenys Vlasenko (struct sockaddr *)&address, 2); 16429b2c45d4SDenys Vlasenko if (len < 0) { 16431da177e4SLinus Torvalds err = -ECONNABORTED; 164439d8c1b6SDavid S. Miller goto out_fd; 16451da177e4SLinus Torvalds } 164643db362dSMaciej Żenczykowski err = move_addr_to_user(&address, 1647230b1839SYOSHIFUJI Hideaki len, upeer_sockaddr, upeer_addrlen); 16481da177e4SLinus Torvalds if (err < 0) 164939d8c1b6SDavid S. Miller goto out_fd; 16501da177e4SLinus Torvalds } 16511da177e4SLinus Torvalds 16521da177e4SLinus Torvalds /* File flags are not inherited via accept() unlike another OSes. */ 16531da177e4SLinus Torvalds 165439d8c1b6SDavid S. Miller fd_install(newfd, newfile); 165539d8c1b6SDavid S. Miller err = newfd; 16561da177e4SLinus Torvalds 16571da177e4SLinus Torvalds out_put: 16586cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16591da177e4SLinus Torvalds out: 16601da177e4SLinus Torvalds return err; 166139d8c1b6SDavid S. Miller out_fd: 16629606a216SDavid S. Miller fput(newfile); 166339d8c1b6SDavid S. Miller put_unused_fd(newfd); 16641da177e4SLinus Torvalds goto out_put; 16651da177e4SLinus Torvalds } 16661da177e4SLinus Torvalds 16674541e805SDominik Brodowski SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, 16684541e805SDominik Brodowski int __user *, upeer_addrlen, int, flags) 16694541e805SDominik Brodowski { 16704541e805SDominik Brodowski return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, flags); 16714541e805SDominik Brodowski } 16724541e805SDominik Brodowski 167320f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr, 167420f37034SHeiko Carstens int __user *, upeer_addrlen) 1675aaca0bdcSUlrich Drepper { 16764541e805SDominik Brodowski return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0); 1677aaca0bdcSUlrich Drepper } 1678aaca0bdcSUlrich Drepper 16791da177e4SLinus Torvalds /* 16801da177e4SLinus Torvalds * Attempt to connect to a socket with the server address. The address 16811da177e4SLinus Torvalds * is in user space so we verify it is OK and move it to kernel space. 16821da177e4SLinus Torvalds * 16831da177e4SLinus Torvalds * For 1003.1g we need to add clean support for a bind to AF_UNSPEC to 16841da177e4SLinus Torvalds * break bindings 16851da177e4SLinus Torvalds * 16861da177e4SLinus Torvalds * NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and 16871da177e4SLinus Torvalds * other SEQPACKET protocols that take time to connect() as it doesn't 16881da177e4SLinus Torvalds * include the -EINPROGRESS status for such sockets. 16891da177e4SLinus Torvalds */ 16901da177e4SLinus Torvalds 16911387c2c2SDominik Brodowski int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen) 16921da177e4SLinus Torvalds { 16931da177e4SLinus Torvalds struct socket *sock; 1694230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 16956cb153caSBenjamin LaHaise int err, fput_needed; 16961da177e4SLinus Torvalds 16976cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 16981da177e4SLinus Torvalds if (!sock) 16991da177e4SLinus Torvalds goto out; 170043db362dSMaciej Żenczykowski err = move_addr_to_kernel(uservaddr, addrlen, &address); 17011da177e4SLinus Torvalds if (err < 0) 17021da177e4SLinus Torvalds goto out_put; 17031da177e4SLinus Torvalds 170489bddce5SStephen Hemminger err = 1705230b1839SYOSHIFUJI Hideaki security_socket_connect(sock, (struct sockaddr *)&address, addrlen); 17061da177e4SLinus Torvalds if (err) 17071da177e4SLinus Torvalds goto out_put; 17081da177e4SLinus Torvalds 1709230b1839SYOSHIFUJI Hideaki err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen, 17101da177e4SLinus Torvalds sock->file->f_flags); 17111da177e4SLinus Torvalds out_put: 17126cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 17131da177e4SLinus Torvalds out: 17141da177e4SLinus Torvalds return err; 17151da177e4SLinus Torvalds } 17161da177e4SLinus Torvalds 17171387c2c2SDominik Brodowski SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr, 17181387c2c2SDominik Brodowski int, addrlen) 17191387c2c2SDominik Brodowski { 17201387c2c2SDominik Brodowski return __sys_connect(fd, uservaddr, addrlen); 17211387c2c2SDominik Brodowski } 17221387c2c2SDominik Brodowski 17231da177e4SLinus Torvalds /* 17241da177e4SLinus Torvalds * Get the local address ('name') of a socket object. Move the obtained 17251da177e4SLinus Torvalds * name to user space. 17261da177e4SLinus Torvalds */ 17271da177e4SLinus Torvalds 17288882a107SDominik Brodowski int __sys_getsockname(int fd, struct sockaddr __user *usockaddr, 17298882a107SDominik Brodowski int __user *usockaddr_len) 17301da177e4SLinus Torvalds { 17311da177e4SLinus Torvalds struct socket *sock; 1732230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 17339b2c45d4SDenys Vlasenko int err, fput_needed; 17341da177e4SLinus Torvalds 17356cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 17361da177e4SLinus Torvalds if (!sock) 17371da177e4SLinus Torvalds goto out; 17381da177e4SLinus Torvalds 17391da177e4SLinus Torvalds err = security_socket_getsockname(sock); 17401da177e4SLinus Torvalds if (err) 17411da177e4SLinus Torvalds goto out_put; 17421da177e4SLinus Torvalds 17439b2c45d4SDenys Vlasenko err = sock->ops->getname(sock, (struct sockaddr *)&address, 0); 17449b2c45d4SDenys Vlasenko if (err < 0) 17451da177e4SLinus Torvalds goto out_put; 17469b2c45d4SDenys Vlasenko /* "err" is actually length in this case */ 17479b2c45d4SDenys Vlasenko err = move_addr_to_user(&address, err, usockaddr, usockaddr_len); 17481da177e4SLinus Torvalds 17491da177e4SLinus Torvalds out_put: 17506cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 17511da177e4SLinus Torvalds out: 17521da177e4SLinus Torvalds return err; 17531da177e4SLinus Torvalds } 17541da177e4SLinus Torvalds 17558882a107SDominik Brodowski SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr, 17568882a107SDominik Brodowski int __user *, usockaddr_len) 17578882a107SDominik Brodowski { 17588882a107SDominik Brodowski return __sys_getsockname(fd, usockaddr, usockaddr_len); 17598882a107SDominik Brodowski } 17608882a107SDominik Brodowski 17611da177e4SLinus Torvalds /* 17621da177e4SLinus Torvalds * Get the remote address ('name') of a socket object. Move the obtained 17631da177e4SLinus Torvalds * name to user space. 17641da177e4SLinus Torvalds */ 17651da177e4SLinus Torvalds 1766b21c8f83SDominik Brodowski int __sys_getpeername(int fd, struct sockaddr __user *usockaddr, 1767b21c8f83SDominik Brodowski int __user *usockaddr_len) 17681da177e4SLinus Torvalds { 17691da177e4SLinus Torvalds struct socket *sock; 1770230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 17719b2c45d4SDenys Vlasenko int err, fput_needed; 17721da177e4SLinus Torvalds 177389bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 177489bddce5SStephen Hemminger if (sock != NULL) { 17751da177e4SLinus Torvalds err = security_socket_getpeername(sock); 17761da177e4SLinus Torvalds if (err) { 17776cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 17781da177e4SLinus Torvalds return err; 17791da177e4SLinus Torvalds } 17801da177e4SLinus Torvalds 17819b2c45d4SDenys Vlasenko err = sock->ops->getname(sock, (struct sockaddr *)&address, 1); 17829b2c45d4SDenys Vlasenko if (err >= 0) 17839b2c45d4SDenys Vlasenko /* "err" is actually length in this case */ 17849b2c45d4SDenys Vlasenko err = move_addr_to_user(&address, err, usockaddr, 178589bddce5SStephen Hemminger usockaddr_len); 17866cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 17871da177e4SLinus Torvalds } 17881da177e4SLinus Torvalds return err; 17891da177e4SLinus Torvalds } 17901da177e4SLinus Torvalds 1791b21c8f83SDominik Brodowski SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr, 1792b21c8f83SDominik Brodowski int __user *, usockaddr_len) 1793b21c8f83SDominik Brodowski { 1794b21c8f83SDominik Brodowski return __sys_getpeername(fd, usockaddr, usockaddr_len); 1795b21c8f83SDominik Brodowski } 1796b21c8f83SDominik Brodowski 17971da177e4SLinus Torvalds /* 17981da177e4SLinus Torvalds * Send a datagram to a given address. We move the address into kernel 17991da177e4SLinus Torvalds * space and check the user space data area is readable before invoking 18001da177e4SLinus Torvalds * the protocol. 18011da177e4SLinus Torvalds */ 1802211b634bSDominik Brodowski int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags, 1803211b634bSDominik Brodowski struct sockaddr __user *addr, int addr_len) 18041da177e4SLinus Torvalds { 18051da177e4SLinus Torvalds struct socket *sock; 1806230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 18071da177e4SLinus Torvalds int err; 18081da177e4SLinus Torvalds struct msghdr msg; 18091da177e4SLinus Torvalds struct iovec iov; 18106cb153caSBenjamin LaHaise int fput_needed; 18111da177e4SLinus Torvalds 1812602bd0e9SAl Viro err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter); 1813602bd0e9SAl Viro if (unlikely(err)) 1814602bd0e9SAl Viro return err; 1815de0fa95cSPavel Emelyanov sock = sockfd_lookup_light(fd, &err, &fput_needed); 1816de0fa95cSPavel Emelyanov if (!sock) 18174387ff75SDavid S. Miller goto out; 18186cb153caSBenjamin LaHaise 18191da177e4SLinus Torvalds msg.msg_name = NULL; 18201da177e4SLinus Torvalds msg.msg_control = NULL; 18211da177e4SLinus Torvalds msg.msg_controllen = 0; 18221da177e4SLinus Torvalds msg.msg_namelen = 0; 18236cb153caSBenjamin LaHaise if (addr) { 182443db362dSMaciej Żenczykowski err = move_addr_to_kernel(addr, addr_len, &address); 18251da177e4SLinus Torvalds if (err < 0) 18261da177e4SLinus Torvalds goto out_put; 1827230b1839SYOSHIFUJI Hideaki msg.msg_name = (struct sockaddr *)&address; 18281da177e4SLinus Torvalds msg.msg_namelen = addr_len; 18291da177e4SLinus Torvalds } 18301da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 18311da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 18321da177e4SLinus Torvalds msg.msg_flags = flags; 1833d8725c86SAl Viro err = sock_sendmsg(sock, &msg); 18341da177e4SLinus Torvalds 18351da177e4SLinus Torvalds out_put: 1836de0fa95cSPavel Emelyanov fput_light(sock->file, fput_needed); 18374387ff75SDavid S. Miller out: 18381da177e4SLinus Torvalds return err; 18391da177e4SLinus Torvalds } 18401da177e4SLinus Torvalds 1841211b634bSDominik Brodowski SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len, 1842211b634bSDominik Brodowski unsigned int, flags, struct sockaddr __user *, addr, 1843211b634bSDominik Brodowski int, addr_len) 1844211b634bSDominik Brodowski { 1845211b634bSDominik Brodowski return __sys_sendto(fd, buff, len, flags, addr, addr_len); 1846211b634bSDominik Brodowski } 1847211b634bSDominik Brodowski 18481da177e4SLinus Torvalds /* 18491da177e4SLinus Torvalds * Send a datagram down a socket. 18501da177e4SLinus Torvalds */ 18511da177e4SLinus Torvalds 18523e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len, 185395c96174SEric Dumazet unsigned int, flags) 18541da177e4SLinus Torvalds { 1855211b634bSDominik Brodowski return __sys_sendto(fd, buff, len, flags, NULL, 0); 18561da177e4SLinus Torvalds } 18571da177e4SLinus Torvalds 18581da177e4SLinus Torvalds /* 18591da177e4SLinus Torvalds * Receive a frame from the socket and optionally record the address of the 18601da177e4SLinus Torvalds * sender. We verify the buffers are writable and if needed move the 18611da177e4SLinus Torvalds * sender address from kernel to user space. 18621da177e4SLinus Torvalds */ 18637a09e1ebSDominik Brodowski int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags, 18647a09e1ebSDominik Brodowski struct sockaddr __user *addr, int __user *addr_len) 18651da177e4SLinus Torvalds { 18661da177e4SLinus Torvalds struct socket *sock; 18671da177e4SLinus Torvalds struct iovec iov; 18681da177e4SLinus Torvalds struct msghdr msg; 1869230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 18701da177e4SLinus Torvalds int err, err2; 18716cb153caSBenjamin LaHaise int fput_needed; 18721da177e4SLinus Torvalds 1873602bd0e9SAl Viro err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter); 1874602bd0e9SAl Viro if (unlikely(err)) 1875602bd0e9SAl Viro return err; 1876de0fa95cSPavel Emelyanov sock = sockfd_lookup_light(fd, &err, &fput_needed); 18771da177e4SLinus Torvalds if (!sock) 1878de0fa95cSPavel Emelyanov goto out; 18791da177e4SLinus Torvalds 18801da177e4SLinus Torvalds msg.msg_control = NULL; 18811da177e4SLinus Torvalds msg.msg_controllen = 0; 1882f3d33426SHannes Frederic Sowa /* Save some cycles and don't copy the address if not needed */ 1883f3d33426SHannes Frederic Sowa msg.msg_name = addr ? (struct sockaddr *)&address : NULL; 1884f3d33426SHannes Frederic Sowa /* We assume all kernel code knows the size of sockaddr_storage */ 1885f3d33426SHannes Frederic Sowa msg.msg_namelen = 0; 1886130ed5d1Stadeusz.struk@intel.com msg.msg_iocb = NULL; 18879f138fa6SAlexander Potapenko msg.msg_flags = 0; 18881da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 18891da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 18902da62906SAl Viro err = sock_recvmsg(sock, &msg, flags); 18911da177e4SLinus Torvalds 189289bddce5SStephen Hemminger if (err >= 0 && addr != NULL) { 189343db362dSMaciej Żenczykowski err2 = move_addr_to_user(&address, 1894230b1839SYOSHIFUJI Hideaki msg.msg_namelen, addr, addr_len); 18951da177e4SLinus Torvalds if (err2 < 0) 18961da177e4SLinus Torvalds err = err2; 18971da177e4SLinus Torvalds } 1898de0fa95cSPavel Emelyanov 1899de0fa95cSPavel Emelyanov fput_light(sock->file, fput_needed); 19004387ff75SDavid S. Miller out: 19011da177e4SLinus Torvalds return err; 19021da177e4SLinus Torvalds } 19031da177e4SLinus Torvalds 19047a09e1ebSDominik Brodowski SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, 19057a09e1ebSDominik Brodowski unsigned int, flags, struct sockaddr __user *, addr, 19067a09e1ebSDominik Brodowski int __user *, addr_len) 19077a09e1ebSDominik Brodowski { 19087a09e1ebSDominik Brodowski return __sys_recvfrom(fd, ubuf, size, flags, addr, addr_len); 19097a09e1ebSDominik Brodowski } 19107a09e1ebSDominik Brodowski 19111da177e4SLinus Torvalds /* 19121da177e4SLinus Torvalds * Receive a datagram from a socket. 19131da177e4SLinus Torvalds */ 19141da177e4SLinus Torvalds 1915b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size, 1916b7c0ddf5SJan Glauber unsigned int, flags) 19171da177e4SLinus Torvalds { 19187a09e1ebSDominik Brodowski return __sys_recvfrom(fd, ubuf, size, flags, NULL, NULL); 19191da177e4SLinus Torvalds } 19201da177e4SLinus Torvalds 19211da177e4SLinus Torvalds /* 19221da177e4SLinus Torvalds * Set a socket option. Because we don't know the option lengths we have 19231da177e4SLinus Torvalds * to pass the user mode parameter for the protocols to sort out. 19241da177e4SLinus Torvalds */ 19251da177e4SLinus Torvalds 1926cc36dca0SDominik Brodowski static int __sys_setsockopt(int fd, int level, int optname, 1927cc36dca0SDominik Brodowski char __user *optval, int optlen) 19281da177e4SLinus Torvalds { 19296cb153caSBenjamin LaHaise int err, fput_needed; 19301da177e4SLinus Torvalds struct socket *sock; 19311da177e4SLinus Torvalds 19321da177e4SLinus Torvalds if (optlen < 0) 19331da177e4SLinus Torvalds return -EINVAL; 19341da177e4SLinus Torvalds 193589bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 193689bddce5SStephen Hemminger if (sock != NULL) { 19371da177e4SLinus Torvalds err = security_socket_setsockopt(sock, level, optname); 19386cb153caSBenjamin LaHaise if (err) 19396cb153caSBenjamin LaHaise goto out_put; 19401da177e4SLinus Torvalds 19411da177e4SLinus Torvalds if (level == SOL_SOCKET) 194289bddce5SStephen Hemminger err = 194389bddce5SStephen Hemminger sock_setsockopt(sock, level, optname, optval, 194489bddce5SStephen Hemminger optlen); 19451da177e4SLinus Torvalds else 194689bddce5SStephen Hemminger err = 194789bddce5SStephen Hemminger sock->ops->setsockopt(sock, level, optname, optval, 194889bddce5SStephen Hemminger optlen); 19496cb153caSBenjamin LaHaise out_put: 19506cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 19511da177e4SLinus Torvalds } 19521da177e4SLinus Torvalds return err; 19531da177e4SLinus Torvalds } 19541da177e4SLinus Torvalds 1955cc36dca0SDominik Brodowski SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname, 1956cc36dca0SDominik Brodowski char __user *, optval, int, optlen) 1957cc36dca0SDominik Brodowski { 1958cc36dca0SDominik Brodowski return __sys_setsockopt(fd, level, optname, optval, optlen); 1959cc36dca0SDominik Brodowski } 1960cc36dca0SDominik Brodowski 19611da177e4SLinus Torvalds /* 19621da177e4SLinus Torvalds * Get a socket option. Because we don't know the option lengths we have 19631da177e4SLinus Torvalds * to pass a user mode parameter for the protocols to sort out. 19641da177e4SLinus Torvalds */ 19651da177e4SLinus Torvalds 196613a2d70eSDominik Brodowski static int __sys_getsockopt(int fd, int level, int optname, 196713a2d70eSDominik Brodowski char __user *optval, int __user *optlen) 19681da177e4SLinus Torvalds { 19696cb153caSBenjamin LaHaise int err, fput_needed; 19701da177e4SLinus Torvalds struct socket *sock; 19711da177e4SLinus Torvalds 197289bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 197389bddce5SStephen Hemminger if (sock != NULL) { 19746cb153caSBenjamin LaHaise err = security_socket_getsockopt(sock, level, optname); 19756cb153caSBenjamin LaHaise if (err) 19766cb153caSBenjamin LaHaise goto out_put; 19771da177e4SLinus Torvalds 19781da177e4SLinus Torvalds if (level == SOL_SOCKET) 197989bddce5SStephen Hemminger err = 198089bddce5SStephen Hemminger sock_getsockopt(sock, level, optname, optval, 198189bddce5SStephen Hemminger optlen); 19821da177e4SLinus Torvalds else 198389bddce5SStephen Hemminger err = 198489bddce5SStephen Hemminger sock->ops->getsockopt(sock, level, optname, optval, 198589bddce5SStephen Hemminger optlen); 19866cb153caSBenjamin LaHaise out_put: 19876cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 19881da177e4SLinus Torvalds } 19891da177e4SLinus Torvalds return err; 19901da177e4SLinus Torvalds } 19911da177e4SLinus Torvalds 199213a2d70eSDominik Brodowski SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname, 199313a2d70eSDominik Brodowski char __user *, optval, int __user *, optlen) 199413a2d70eSDominik Brodowski { 199513a2d70eSDominik Brodowski return __sys_getsockopt(fd, level, optname, optval, optlen); 199613a2d70eSDominik Brodowski } 199713a2d70eSDominik Brodowski 19981da177e4SLinus Torvalds /* 19991da177e4SLinus Torvalds * Shutdown a socket. 20001da177e4SLinus Torvalds */ 20011da177e4SLinus Torvalds 2002005a1aeaSDominik Brodowski int __sys_shutdown(int fd, int how) 20031da177e4SLinus Torvalds { 20046cb153caSBenjamin LaHaise int err, fput_needed; 20051da177e4SLinus Torvalds struct socket *sock; 20061da177e4SLinus Torvalds 200789bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 200889bddce5SStephen Hemminger if (sock != NULL) { 20091da177e4SLinus Torvalds err = security_socket_shutdown(sock, how); 20106cb153caSBenjamin LaHaise if (!err) 20111da177e4SLinus Torvalds err = sock->ops->shutdown(sock, how); 20126cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 20131da177e4SLinus Torvalds } 20141da177e4SLinus Torvalds return err; 20151da177e4SLinus Torvalds } 20161da177e4SLinus Torvalds 2017005a1aeaSDominik Brodowski SYSCALL_DEFINE2(shutdown, int, fd, int, how) 2018005a1aeaSDominik Brodowski { 2019005a1aeaSDominik Brodowski return __sys_shutdown(fd, how); 2020005a1aeaSDominik Brodowski } 2021005a1aeaSDominik Brodowski 20221da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit 20231da177e4SLinus Torvalds * fields which are the same type (int / unsigned) on our platforms. 20241da177e4SLinus Torvalds */ 20251da177e4SLinus Torvalds #define COMPAT_MSG(msg, member) ((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member) 20261da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen) 20271da177e4SLinus Torvalds #define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags) 20281da177e4SLinus Torvalds 2029c71d8ebeSTetsuo Handa struct used_address { 2030c71d8ebeSTetsuo Handa struct sockaddr_storage name; 2031c71d8ebeSTetsuo Handa unsigned int name_len; 2032c71d8ebeSTetsuo Handa }; 2033c71d8ebeSTetsuo Handa 2034da184284SAl Viro static int copy_msghdr_from_user(struct msghdr *kmsg, 203508adb7daSAl Viro struct user_msghdr __user *umsg, 203608adb7daSAl Viro struct sockaddr __user **save_addr, 203708adb7daSAl Viro struct iovec **iov) 20381661bf36SDan Carpenter { 2039ffb07550SAl Viro struct user_msghdr msg; 204008adb7daSAl Viro ssize_t err; 204108adb7daSAl Viro 2042ffb07550SAl Viro if (copy_from_user(&msg, umsg, sizeof(*umsg))) 20431661bf36SDan Carpenter return -EFAULT; 2044dbb490b9SMatthew Leach 2045864d9664SPaolo Abeni kmsg->msg_control = (void __force *)msg.msg_control; 2046ffb07550SAl Viro kmsg->msg_controllen = msg.msg_controllen; 2047ffb07550SAl Viro kmsg->msg_flags = msg.msg_flags; 2048ffb07550SAl Viro 2049ffb07550SAl Viro kmsg->msg_namelen = msg.msg_namelen; 2050ffb07550SAl Viro if (!msg.msg_name) 20516a2a2b3aSAni Sinha kmsg->msg_namelen = 0; 20526a2a2b3aSAni Sinha 2053dbb490b9SMatthew Leach if (kmsg->msg_namelen < 0) 2054dbb490b9SMatthew Leach return -EINVAL; 2055dbb490b9SMatthew Leach 20561661bf36SDan Carpenter if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) 2057db31c55aSDan Carpenter kmsg->msg_namelen = sizeof(struct sockaddr_storage); 205808adb7daSAl Viro 205908adb7daSAl Viro if (save_addr) 2060ffb07550SAl Viro *save_addr = msg.msg_name; 206108adb7daSAl Viro 2062ffb07550SAl Viro if (msg.msg_name && kmsg->msg_namelen) { 206308adb7daSAl Viro if (!save_addr) { 2064864d9664SPaolo Abeni err = move_addr_to_kernel(msg.msg_name, 2065864d9664SPaolo Abeni kmsg->msg_namelen, 206608adb7daSAl Viro kmsg->msg_name); 206708adb7daSAl Viro if (err < 0) 206808adb7daSAl Viro return err; 206908adb7daSAl Viro } 207008adb7daSAl Viro } else { 207108adb7daSAl Viro kmsg->msg_name = NULL; 207208adb7daSAl Viro kmsg->msg_namelen = 0; 207308adb7daSAl Viro } 207408adb7daSAl Viro 2075ffb07550SAl Viro if (msg.msg_iovlen > UIO_MAXIOV) 207608adb7daSAl Viro return -EMSGSIZE; 207708adb7daSAl Viro 20780345f931Stadeusz.struk@intel.com kmsg->msg_iocb = NULL; 20790345f931Stadeusz.struk@intel.com 2080ffb07550SAl Viro return import_iovec(save_addr ? READ : WRITE, 2081ffb07550SAl Viro msg.msg_iov, msg.msg_iovlen, 2082da184284SAl Viro UIO_FASTIOV, iov, &kmsg->msg_iter); 20831661bf36SDan Carpenter } 20841661bf36SDan Carpenter 2085666547ffSAl Viro static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg, 208695c96174SEric Dumazet struct msghdr *msg_sys, unsigned int flags, 208728a94d8fSTom Herbert struct used_address *used_address, 208828a94d8fSTom Herbert unsigned int allowed_msghdr_flags) 20891da177e4SLinus Torvalds { 209089bddce5SStephen Hemminger struct compat_msghdr __user *msg_compat = 209189bddce5SStephen Hemminger (struct compat_msghdr __user *)msg; 2092230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 20931da177e4SLinus Torvalds struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; 2094b9d717a7SAlex Williamson unsigned char ctl[sizeof(struct cmsghdr) + 20] 2095846cc123SAmit Kushwaha __aligned(sizeof(__kernel_size_t)); 2096b9d717a7SAlex Williamson /* 20 is size of ipv6_pktinfo */ 20971da177e4SLinus Torvalds unsigned char *ctl_buf = ctl; 2098d8725c86SAl Viro int ctl_len; 209908adb7daSAl Viro ssize_t err; 21001da177e4SLinus Torvalds 210108adb7daSAl Viro msg_sys->msg_name = &address; 21021da177e4SLinus Torvalds 210308449320SAl Viro if (MSG_CMSG_COMPAT & flags) 210408adb7daSAl Viro err = get_compat_msghdr(msg_sys, msg_compat, NULL, &iov); 210508449320SAl Viro else 210608adb7daSAl Viro err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov); 21071da177e4SLinus Torvalds if (err < 0) 2108da184284SAl Viro return err; 21091da177e4SLinus Torvalds 21101da177e4SLinus Torvalds err = -ENOBUFS; 21111da177e4SLinus Torvalds 2112228e548eSAnton Blanchard if (msg_sys->msg_controllen > INT_MAX) 21131da177e4SLinus Torvalds goto out_freeiov; 211428a94d8fSTom Herbert flags |= (msg_sys->msg_flags & allowed_msghdr_flags); 2115228e548eSAnton Blanchard ctl_len = msg_sys->msg_controllen; 21161da177e4SLinus Torvalds if ((MSG_CMSG_COMPAT & flags) && ctl_len) { 211789bddce5SStephen Hemminger err = 2118228e548eSAnton Blanchard cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl, 211989bddce5SStephen Hemminger sizeof(ctl)); 21201da177e4SLinus Torvalds if (err) 21211da177e4SLinus Torvalds goto out_freeiov; 2122228e548eSAnton Blanchard ctl_buf = msg_sys->msg_control; 2123228e548eSAnton Blanchard ctl_len = msg_sys->msg_controllen; 21241da177e4SLinus Torvalds } else if (ctl_len) { 2125ac4340fcSDavid S. Miller BUILD_BUG_ON(sizeof(struct cmsghdr) != 2126ac4340fcSDavid S. Miller CMSG_ALIGN(sizeof(struct cmsghdr))); 212789bddce5SStephen Hemminger if (ctl_len > sizeof(ctl)) { 21281da177e4SLinus Torvalds ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); 21291da177e4SLinus Torvalds if (ctl_buf == NULL) 21301da177e4SLinus Torvalds goto out_freeiov; 21311da177e4SLinus Torvalds } 21321da177e4SLinus Torvalds err = -EFAULT; 21331da177e4SLinus Torvalds /* 2134228e548eSAnton Blanchard * Careful! Before this, msg_sys->msg_control contains a user pointer. 21351da177e4SLinus Torvalds * Afterwards, it will be a kernel pointer. Thus the compiler-assisted 21361da177e4SLinus Torvalds * checking falls down on this. 21371da177e4SLinus Torvalds */ 2138fb8621bbSNamhyung Kim if (copy_from_user(ctl_buf, 2139228e548eSAnton Blanchard (void __user __force *)msg_sys->msg_control, 214089bddce5SStephen Hemminger ctl_len)) 21411da177e4SLinus Torvalds goto out_freectl; 2142228e548eSAnton Blanchard msg_sys->msg_control = ctl_buf; 21431da177e4SLinus Torvalds } 2144228e548eSAnton Blanchard msg_sys->msg_flags = flags; 21451da177e4SLinus Torvalds 21461da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 2147228e548eSAnton Blanchard msg_sys->msg_flags |= MSG_DONTWAIT; 2148c71d8ebeSTetsuo Handa /* 2149c71d8ebeSTetsuo Handa * If this is sendmmsg() and current destination address is same as 2150c71d8ebeSTetsuo Handa * previously succeeded address, omit asking LSM's decision. 2151c71d8ebeSTetsuo Handa * used_address->name_len is initialized to UINT_MAX so that the first 2152c71d8ebeSTetsuo Handa * destination address never matches. 2153c71d8ebeSTetsuo Handa */ 2154bc909d9dSMathieu Desnoyers if (used_address && msg_sys->msg_name && 2155bc909d9dSMathieu Desnoyers used_address->name_len == msg_sys->msg_namelen && 2156bc909d9dSMathieu Desnoyers !memcmp(&used_address->name, msg_sys->msg_name, 2157c71d8ebeSTetsuo Handa used_address->name_len)) { 2158d8725c86SAl Viro err = sock_sendmsg_nosec(sock, msg_sys); 2159c71d8ebeSTetsuo Handa goto out_freectl; 2160c71d8ebeSTetsuo Handa } 2161d8725c86SAl Viro err = sock_sendmsg(sock, msg_sys); 2162c71d8ebeSTetsuo Handa /* 2163c71d8ebeSTetsuo Handa * If this is sendmmsg() and sending to current destination address was 2164c71d8ebeSTetsuo Handa * successful, remember it. 2165c71d8ebeSTetsuo Handa */ 2166c71d8ebeSTetsuo Handa if (used_address && err >= 0) { 2167c71d8ebeSTetsuo Handa used_address->name_len = msg_sys->msg_namelen; 2168bc909d9dSMathieu Desnoyers if (msg_sys->msg_name) 2169bc909d9dSMathieu Desnoyers memcpy(&used_address->name, msg_sys->msg_name, 2170c71d8ebeSTetsuo Handa used_address->name_len); 2171c71d8ebeSTetsuo Handa } 21721da177e4SLinus Torvalds 21731da177e4SLinus Torvalds out_freectl: 21741da177e4SLinus Torvalds if (ctl_buf != ctl) 21751da177e4SLinus Torvalds sock_kfree_s(sock->sk, ctl_buf, ctl_len); 21761da177e4SLinus Torvalds out_freeiov: 2177a74e9106SEric Dumazet kfree(iov); 2178228e548eSAnton Blanchard return err; 2179228e548eSAnton Blanchard } 2180228e548eSAnton Blanchard 2181228e548eSAnton Blanchard /* 2182228e548eSAnton Blanchard * BSD sendmsg interface 2183228e548eSAnton Blanchard */ 2184228e548eSAnton Blanchard 2185e1834a32SDominik Brodowski long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags, 2186e1834a32SDominik Brodowski bool forbid_cmsg_compat) 2187228e548eSAnton Blanchard { 2188228e548eSAnton Blanchard int fput_needed, err; 2189228e548eSAnton Blanchard struct msghdr msg_sys; 21901be374a0SAndy Lutomirski struct socket *sock; 2191228e548eSAnton Blanchard 2192e1834a32SDominik Brodowski if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT)) 2193e1834a32SDominik Brodowski return -EINVAL; 2194e1834a32SDominik Brodowski 21951be374a0SAndy Lutomirski sock = sockfd_lookup_light(fd, &err, &fput_needed); 2196228e548eSAnton Blanchard if (!sock) 2197228e548eSAnton Blanchard goto out; 2198228e548eSAnton Blanchard 219928a94d8fSTom Herbert err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0); 2200228e548eSAnton Blanchard 22016cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 22021da177e4SLinus Torvalds out: 22031da177e4SLinus Torvalds return err; 22041da177e4SLinus Torvalds } 22051da177e4SLinus Torvalds 2206666547ffSAl Viro SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags) 2207a7526eb5SAndy Lutomirski { 2208e1834a32SDominik Brodowski return __sys_sendmsg(fd, msg, flags, true); 2209a7526eb5SAndy Lutomirski } 2210a7526eb5SAndy Lutomirski 2211228e548eSAnton Blanchard /* 2212228e548eSAnton Blanchard * Linux sendmmsg interface 2213228e548eSAnton Blanchard */ 2214228e548eSAnton Blanchard 2215228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, 2216e1834a32SDominik Brodowski unsigned int flags, bool forbid_cmsg_compat) 2217228e548eSAnton Blanchard { 2218228e548eSAnton Blanchard int fput_needed, err, datagrams; 2219228e548eSAnton Blanchard struct socket *sock; 2220228e548eSAnton Blanchard struct mmsghdr __user *entry; 2221228e548eSAnton Blanchard struct compat_mmsghdr __user *compat_entry; 2222228e548eSAnton Blanchard struct msghdr msg_sys; 2223c71d8ebeSTetsuo Handa struct used_address used_address; 2224f092276dSTom Herbert unsigned int oflags = flags; 2225228e548eSAnton Blanchard 2226e1834a32SDominik Brodowski if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT)) 2227e1834a32SDominik Brodowski return -EINVAL; 2228e1834a32SDominik Brodowski 222998382f41SAnton Blanchard if (vlen > UIO_MAXIOV) 223098382f41SAnton Blanchard vlen = UIO_MAXIOV; 2231228e548eSAnton Blanchard 2232228e548eSAnton Blanchard datagrams = 0; 2233228e548eSAnton Blanchard 2234228e548eSAnton Blanchard sock = sockfd_lookup_light(fd, &err, &fput_needed); 2235228e548eSAnton Blanchard if (!sock) 2236228e548eSAnton Blanchard return err; 2237228e548eSAnton Blanchard 2238c71d8ebeSTetsuo Handa used_address.name_len = UINT_MAX; 2239228e548eSAnton Blanchard entry = mmsg; 2240228e548eSAnton Blanchard compat_entry = (struct compat_mmsghdr __user *)mmsg; 2241728ffb86SAnton Blanchard err = 0; 2242f092276dSTom Herbert flags |= MSG_BATCH; 2243228e548eSAnton Blanchard 2244228e548eSAnton Blanchard while (datagrams < vlen) { 2245f092276dSTom Herbert if (datagrams == vlen - 1) 2246f092276dSTom Herbert flags = oflags; 2247f092276dSTom Herbert 2248228e548eSAnton Blanchard if (MSG_CMSG_COMPAT & flags) { 2249666547ffSAl Viro err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry, 225028a94d8fSTom Herbert &msg_sys, flags, &used_address, MSG_EOR); 2251228e548eSAnton Blanchard if (err < 0) 2252228e548eSAnton Blanchard break; 2253228e548eSAnton Blanchard err = __put_user(err, &compat_entry->msg_len); 2254228e548eSAnton Blanchard ++compat_entry; 2255228e548eSAnton Blanchard } else { 2256a7526eb5SAndy Lutomirski err = ___sys_sendmsg(sock, 2257666547ffSAl Viro (struct user_msghdr __user *)entry, 225828a94d8fSTom Herbert &msg_sys, flags, &used_address, MSG_EOR); 2259228e548eSAnton Blanchard if (err < 0) 2260228e548eSAnton Blanchard break; 2261228e548eSAnton Blanchard err = put_user(err, &entry->msg_len); 2262228e548eSAnton Blanchard ++entry; 2263228e548eSAnton Blanchard } 2264228e548eSAnton Blanchard 2265228e548eSAnton Blanchard if (err) 2266228e548eSAnton Blanchard break; 2267228e548eSAnton Blanchard ++datagrams; 22683023898bSSoheil Hassas Yeganeh if (msg_data_left(&msg_sys)) 22693023898bSSoheil Hassas Yeganeh break; 2270a78cb84cSEric Dumazet cond_resched(); 2271228e548eSAnton Blanchard } 2272228e548eSAnton Blanchard 2273228e548eSAnton Blanchard fput_light(sock->file, fput_needed); 2274228e548eSAnton Blanchard 2275728ffb86SAnton Blanchard /* We only return an error if no datagrams were able to be sent */ 2276728ffb86SAnton Blanchard if (datagrams != 0) 2277228e548eSAnton Blanchard return datagrams; 2278228e548eSAnton Blanchard 2279228e548eSAnton Blanchard return err; 2280228e548eSAnton Blanchard } 2281228e548eSAnton Blanchard 2282228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, 2283228e548eSAnton Blanchard unsigned int, vlen, unsigned int, flags) 2284228e548eSAnton Blanchard { 2285e1834a32SDominik Brodowski return __sys_sendmmsg(fd, mmsg, vlen, flags, true); 2286228e548eSAnton Blanchard } 2287228e548eSAnton Blanchard 2288666547ffSAl Viro static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg, 228995c96174SEric Dumazet struct msghdr *msg_sys, unsigned int flags, int nosec) 22901da177e4SLinus Torvalds { 229189bddce5SStephen Hemminger struct compat_msghdr __user *msg_compat = 229289bddce5SStephen Hemminger (struct compat_msghdr __user *)msg; 22931da177e4SLinus Torvalds struct iovec iovstack[UIO_FASTIOV]; 22941da177e4SLinus Torvalds struct iovec *iov = iovstack; 22951da177e4SLinus Torvalds unsigned long cmsg_ptr; 22962da62906SAl Viro int len; 229708adb7daSAl Viro ssize_t err; 22981da177e4SLinus Torvalds 22991da177e4SLinus Torvalds /* kernel mode address */ 2300230b1839SYOSHIFUJI Hideaki struct sockaddr_storage addr; 23011da177e4SLinus Torvalds 23021da177e4SLinus Torvalds /* user mode address pointers */ 23031da177e4SLinus Torvalds struct sockaddr __user *uaddr; 230408adb7daSAl Viro int __user *uaddr_len = COMPAT_NAMELEN(msg); 23051da177e4SLinus Torvalds 230608adb7daSAl Viro msg_sys->msg_name = &addr; 23071da177e4SLinus Torvalds 2308f3d33426SHannes Frederic Sowa if (MSG_CMSG_COMPAT & flags) 230908adb7daSAl Viro err = get_compat_msghdr(msg_sys, msg_compat, &uaddr, &iov); 2310f3d33426SHannes Frederic Sowa else 231108adb7daSAl Viro err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov); 23121da177e4SLinus Torvalds if (err < 0) 2313da184284SAl Viro return err; 23141da177e4SLinus Torvalds 2315a2e27255SArnaldo Carvalho de Melo cmsg_ptr = (unsigned long)msg_sys->msg_control; 2316a2e27255SArnaldo Carvalho de Melo msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); 23171da177e4SLinus Torvalds 2318f3d33426SHannes Frederic Sowa /* We assume all kernel code knows the size of sockaddr_storage */ 2319f3d33426SHannes Frederic Sowa msg_sys->msg_namelen = 0; 2320f3d33426SHannes Frederic Sowa 23211da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 23221da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 23232da62906SAl Viro err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, flags); 23241da177e4SLinus Torvalds if (err < 0) 23251da177e4SLinus Torvalds goto out_freeiov; 23261da177e4SLinus Torvalds len = err; 23271da177e4SLinus Torvalds 23281da177e4SLinus Torvalds if (uaddr != NULL) { 232943db362dSMaciej Żenczykowski err = move_addr_to_user(&addr, 2330a2e27255SArnaldo Carvalho de Melo msg_sys->msg_namelen, uaddr, 233189bddce5SStephen Hemminger uaddr_len); 23321da177e4SLinus Torvalds if (err < 0) 23331da177e4SLinus Torvalds goto out_freeiov; 23341da177e4SLinus Torvalds } 2335a2e27255SArnaldo Carvalho de Melo err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT), 233637f7f421SDavid S. Miller COMPAT_FLAGS(msg)); 23371da177e4SLinus Torvalds if (err) 23381da177e4SLinus Torvalds goto out_freeiov; 23391da177e4SLinus Torvalds if (MSG_CMSG_COMPAT & flags) 2340a2e27255SArnaldo Carvalho de Melo err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr, 23411da177e4SLinus Torvalds &msg_compat->msg_controllen); 23421da177e4SLinus Torvalds else 2343a2e27255SArnaldo Carvalho de Melo err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr, 23441da177e4SLinus Torvalds &msg->msg_controllen); 23451da177e4SLinus Torvalds if (err) 23461da177e4SLinus Torvalds goto out_freeiov; 23471da177e4SLinus Torvalds err = len; 23481da177e4SLinus Torvalds 23491da177e4SLinus Torvalds out_freeiov: 2350a74e9106SEric Dumazet kfree(iov); 2351a2e27255SArnaldo Carvalho de Melo return err; 2352a2e27255SArnaldo Carvalho de Melo } 2353a2e27255SArnaldo Carvalho de Melo 2354a2e27255SArnaldo Carvalho de Melo /* 2355a2e27255SArnaldo Carvalho de Melo * BSD recvmsg interface 2356a2e27255SArnaldo Carvalho de Melo */ 2357a2e27255SArnaldo Carvalho de Melo 2358e1834a32SDominik Brodowski long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags, 2359e1834a32SDominik Brodowski bool forbid_cmsg_compat) 2360a2e27255SArnaldo Carvalho de Melo { 2361a2e27255SArnaldo Carvalho de Melo int fput_needed, err; 2362a2e27255SArnaldo Carvalho de Melo struct msghdr msg_sys; 23631be374a0SAndy Lutomirski struct socket *sock; 2364a2e27255SArnaldo Carvalho de Melo 2365e1834a32SDominik Brodowski if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT)) 2366e1834a32SDominik Brodowski return -EINVAL; 2367e1834a32SDominik Brodowski 23681be374a0SAndy Lutomirski sock = sockfd_lookup_light(fd, &err, &fput_needed); 2369a2e27255SArnaldo Carvalho de Melo if (!sock) 2370a2e27255SArnaldo Carvalho de Melo goto out; 2371a2e27255SArnaldo Carvalho de Melo 2372a7526eb5SAndy Lutomirski err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0); 2373a2e27255SArnaldo Carvalho de Melo 23746cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 23751da177e4SLinus Torvalds out: 23761da177e4SLinus Torvalds return err; 23771da177e4SLinus Torvalds } 23781da177e4SLinus Torvalds 2379666547ffSAl Viro SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg, 2380a7526eb5SAndy Lutomirski unsigned int, flags) 2381a7526eb5SAndy Lutomirski { 2382e1834a32SDominik Brodowski return __sys_recvmsg(fd, msg, flags, true); 2383a7526eb5SAndy Lutomirski } 2384a7526eb5SAndy Lutomirski 2385a2e27255SArnaldo Carvalho de Melo /* 2386a2e27255SArnaldo Carvalho de Melo * Linux recvmmsg interface 2387a2e27255SArnaldo Carvalho de Melo */ 23881da177e4SLinus Torvalds 2389a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, 2390a2e27255SArnaldo Carvalho de Melo unsigned int flags, struct timespec *timeout) 2391a2e27255SArnaldo Carvalho de Melo { 2392a2e27255SArnaldo Carvalho de Melo int fput_needed, err, datagrams; 2393a2e27255SArnaldo Carvalho de Melo struct socket *sock; 2394a2e27255SArnaldo Carvalho de Melo struct mmsghdr __user *entry; 2395d7256d0eSJean-Mickael Guerin struct compat_mmsghdr __user *compat_entry; 2396a2e27255SArnaldo Carvalho de Melo struct msghdr msg_sys; 2397766b9f92SDeepa Dinamani struct timespec64 end_time; 2398766b9f92SDeepa Dinamani struct timespec64 timeout64; 2399a2e27255SArnaldo Carvalho de Melo 2400a2e27255SArnaldo Carvalho de Melo if (timeout && 2401a2e27255SArnaldo Carvalho de Melo poll_select_set_timeout(&end_time, timeout->tv_sec, 2402a2e27255SArnaldo Carvalho de Melo timeout->tv_nsec)) 2403a2e27255SArnaldo Carvalho de Melo return -EINVAL; 2404a2e27255SArnaldo Carvalho de Melo 2405a2e27255SArnaldo Carvalho de Melo datagrams = 0; 2406a2e27255SArnaldo Carvalho de Melo 2407a2e27255SArnaldo Carvalho de Melo sock = sockfd_lookup_light(fd, &err, &fput_needed); 2408a2e27255SArnaldo Carvalho de Melo if (!sock) 2409a2e27255SArnaldo Carvalho de Melo return err; 2410a2e27255SArnaldo Carvalho de Melo 24117797dc41SSoheil Hassas Yeganeh if (likely(!(flags & MSG_ERRQUEUE))) { 2412a2e27255SArnaldo Carvalho de Melo err = sock_error(sock->sk); 2413e623a9e9SMaxime Jayat if (err) { 2414e623a9e9SMaxime Jayat datagrams = err; 2415a2e27255SArnaldo Carvalho de Melo goto out_put; 2416e623a9e9SMaxime Jayat } 24177797dc41SSoheil Hassas Yeganeh } 2418a2e27255SArnaldo Carvalho de Melo 2419a2e27255SArnaldo Carvalho de Melo entry = mmsg; 2420d7256d0eSJean-Mickael Guerin compat_entry = (struct compat_mmsghdr __user *)mmsg; 2421a2e27255SArnaldo Carvalho de Melo 2422a2e27255SArnaldo Carvalho de Melo while (datagrams < vlen) { 2423a2e27255SArnaldo Carvalho de Melo /* 2424a2e27255SArnaldo Carvalho de Melo * No need to ask LSM for more than the first datagram. 2425a2e27255SArnaldo Carvalho de Melo */ 2426d7256d0eSJean-Mickael Guerin if (MSG_CMSG_COMPAT & flags) { 2427666547ffSAl Viro err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry, 2428b9eb8b87SAnton Blanchard &msg_sys, flags & ~MSG_WAITFORONE, 2429b9eb8b87SAnton Blanchard datagrams); 2430d7256d0eSJean-Mickael Guerin if (err < 0) 2431d7256d0eSJean-Mickael Guerin break; 2432d7256d0eSJean-Mickael Guerin err = __put_user(err, &compat_entry->msg_len); 2433d7256d0eSJean-Mickael Guerin ++compat_entry; 2434d7256d0eSJean-Mickael Guerin } else { 2435a7526eb5SAndy Lutomirski err = ___sys_recvmsg(sock, 2436666547ffSAl Viro (struct user_msghdr __user *)entry, 2437b9eb8b87SAnton Blanchard &msg_sys, flags & ~MSG_WAITFORONE, 2438b9eb8b87SAnton Blanchard datagrams); 2439a2e27255SArnaldo Carvalho de Melo if (err < 0) 2440a2e27255SArnaldo Carvalho de Melo break; 2441a2e27255SArnaldo Carvalho de Melo err = put_user(err, &entry->msg_len); 2442d7256d0eSJean-Mickael Guerin ++entry; 2443d7256d0eSJean-Mickael Guerin } 2444d7256d0eSJean-Mickael Guerin 2445a2e27255SArnaldo Carvalho de Melo if (err) 2446a2e27255SArnaldo Carvalho de Melo break; 2447a2e27255SArnaldo Carvalho de Melo ++datagrams; 2448a2e27255SArnaldo Carvalho de Melo 244971c5c159SBrandon L Black /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */ 245071c5c159SBrandon L Black if (flags & MSG_WAITFORONE) 245171c5c159SBrandon L Black flags |= MSG_DONTWAIT; 245271c5c159SBrandon L Black 2453a2e27255SArnaldo Carvalho de Melo if (timeout) { 2454766b9f92SDeepa Dinamani ktime_get_ts64(&timeout64); 2455766b9f92SDeepa Dinamani *timeout = timespec64_to_timespec( 2456766b9f92SDeepa Dinamani timespec64_sub(end_time, timeout64)); 2457a2e27255SArnaldo Carvalho de Melo if (timeout->tv_sec < 0) { 2458a2e27255SArnaldo Carvalho de Melo timeout->tv_sec = timeout->tv_nsec = 0; 2459a2e27255SArnaldo Carvalho de Melo break; 2460a2e27255SArnaldo Carvalho de Melo } 2461a2e27255SArnaldo Carvalho de Melo 2462a2e27255SArnaldo Carvalho de Melo /* Timeout, return less than vlen datagrams */ 2463a2e27255SArnaldo Carvalho de Melo if (timeout->tv_nsec == 0 && timeout->tv_sec == 0) 2464a2e27255SArnaldo Carvalho de Melo break; 2465a2e27255SArnaldo Carvalho de Melo } 2466a2e27255SArnaldo Carvalho de Melo 2467a2e27255SArnaldo Carvalho de Melo /* Out of band data, return right away */ 2468a2e27255SArnaldo Carvalho de Melo if (msg_sys.msg_flags & MSG_OOB) 2469a2e27255SArnaldo Carvalho de Melo break; 2470a78cb84cSEric Dumazet cond_resched(); 2471a2e27255SArnaldo Carvalho de Melo } 2472a2e27255SArnaldo Carvalho de Melo 2473a2e27255SArnaldo Carvalho de Melo if (err == 0) 247434b88a68SArnaldo Carvalho de Melo goto out_put; 2475a2e27255SArnaldo Carvalho de Melo 247634b88a68SArnaldo Carvalho de Melo if (datagrams == 0) { 247734b88a68SArnaldo Carvalho de Melo datagrams = err; 247834b88a68SArnaldo Carvalho de Melo goto out_put; 247934b88a68SArnaldo Carvalho de Melo } 248034b88a68SArnaldo Carvalho de Melo 2481a2e27255SArnaldo Carvalho de Melo /* 2482a2e27255SArnaldo Carvalho de Melo * We may return less entries than requested (vlen) if the 2483a2e27255SArnaldo Carvalho de Melo * sock is non block and there aren't enough datagrams... 2484a2e27255SArnaldo Carvalho de Melo */ 2485a2e27255SArnaldo Carvalho de Melo if (err != -EAGAIN) { 2486a2e27255SArnaldo Carvalho de Melo /* 2487a2e27255SArnaldo Carvalho de Melo * ... or if recvmsg returns an error after we 2488a2e27255SArnaldo Carvalho de Melo * received some datagrams, where we record the 2489a2e27255SArnaldo Carvalho de Melo * error to return on the next call or if the 2490a2e27255SArnaldo Carvalho de Melo * app asks about it using getsockopt(SO_ERROR). 2491a2e27255SArnaldo Carvalho de Melo */ 2492a2e27255SArnaldo Carvalho de Melo sock->sk->sk_err = -err; 2493a2e27255SArnaldo Carvalho de Melo } 249434b88a68SArnaldo Carvalho de Melo out_put: 249534b88a68SArnaldo Carvalho de Melo fput_light(sock->file, fput_needed); 2496a2e27255SArnaldo Carvalho de Melo 2497a2e27255SArnaldo Carvalho de Melo return datagrams; 2498a2e27255SArnaldo Carvalho de Melo } 2499a2e27255SArnaldo Carvalho de Melo 25001255e269SDominik Brodowski static int do_sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, 25011255e269SDominik Brodowski unsigned int vlen, unsigned int flags, 25021255e269SDominik Brodowski struct timespec __user *timeout) 2503a2e27255SArnaldo Carvalho de Melo { 2504a2e27255SArnaldo Carvalho de Melo int datagrams; 2505a2e27255SArnaldo Carvalho de Melo struct timespec timeout_sys; 2506a2e27255SArnaldo Carvalho de Melo 25071be374a0SAndy Lutomirski if (flags & MSG_CMSG_COMPAT) 25081be374a0SAndy Lutomirski return -EINVAL; 25091be374a0SAndy Lutomirski 2510a2e27255SArnaldo Carvalho de Melo if (!timeout) 2511a2e27255SArnaldo Carvalho de Melo return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL); 2512a2e27255SArnaldo Carvalho de Melo 2513a2e27255SArnaldo Carvalho de Melo if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys))) 2514a2e27255SArnaldo Carvalho de Melo return -EFAULT; 2515a2e27255SArnaldo Carvalho de Melo 2516a2e27255SArnaldo Carvalho de Melo datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys); 2517a2e27255SArnaldo Carvalho de Melo 2518a2e27255SArnaldo Carvalho de Melo if (datagrams > 0 && 2519a2e27255SArnaldo Carvalho de Melo copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys))) 2520a2e27255SArnaldo Carvalho de Melo datagrams = -EFAULT; 2521a2e27255SArnaldo Carvalho de Melo 2522a2e27255SArnaldo Carvalho de Melo return datagrams; 2523a2e27255SArnaldo Carvalho de Melo } 2524a2e27255SArnaldo Carvalho de Melo 25251255e269SDominik Brodowski SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, 25261255e269SDominik Brodowski unsigned int, vlen, unsigned int, flags, 25271255e269SDominik Brodowski struct timespec __user *, timeout) 25281255e269SDominik Brodowski { 25291255e269SDominik Brodowski return do_sys_recvmmsg(fd, mmsg, vlen, flags, timeout); 25301255e269SDominik Brodowski } 25311255e269SDominik Brodowski 2532a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL 25331da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */ 25341da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long)) 2535228e548eSAnton Blanchard static const unsigned char nargs[21] = { 253689bddce5SStephen Hemminger AL(0), AL(3), AL(3), AL(3), AL(2), AL(3), 25371da177e4SLinus Torvalds AL(3), AL(3), AL(4), AL(4), AL(4), AL(6), 2538aaca0bdcSUlrich Drepper AL(6), AL(2), AL(5), AL(5), AL(3), AL(3), 2539228e548eSAnton Blanchard AL(4), AL(5), AL(4) 254089bddce5SStephen Hemminger }; 254189bddce5SStephen Hemminger 25421da177e4SLinus Torvalds #undef AL 25431da177e4SLinus Torvalds 25441da177e4SLinus Torvalds /* 25451da177e4SLinus Torvalds * System call vectors. 25461da177e4SLinus Torvalds * 25471da177e4SLinus Torvalds * Argument checking cleaned up. Saved 20% in size. 25481da177e4SLinus Torvalds * This function doesn't need to set the kernel lock because 25491da177e4SLinus Torvalds * it is set by the callees. 25501da177e4SLinus Torvalds */ 25511da177e4SLinus Torvalds 25523e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) 25531da177e4SLinus Torvalds { 25542950fa9dSChen Gang unsigned long a[AUDITSC_ARGS]; 25551da177e4SLinus Torvalds unsigned long a0, a1; 25561da177e4SLinus Torvalds int err; 255747379052SArjan van de Ven unsigned int len; 25581da177e4SLinus Torvalds 2559228e548eSAnton Blanchard if (call < 1 || call > SYS_SENDMMSG) 25601da177e4SLinus Torvalds return -EINVAL; 25611da177e4SLinus Torvalds 256247379052SArjan van de Ven len = nargs[call]; 256347379052SArjan van de Ven if (len > sizeof(a)) 256447379052SArjan van de Ven return -EINVAL; 256547379052SArjan van de Ven 25661da177e4SLinus Torvalds /* copy_from_user should be SMP safe. */ 256747379052SArjan van de Ven if (copy_from_user(a, args, len)) 25681da177e4SLinus Torvalds return -EFAULT; 25691da177e4SLinus Torvalds 25702950fa9dSChen Gang err = audit_socketcall(nargs[call] / sizeof(unsigned long), a); 25712950fa9dSChen Gang if (err) 25722950fa9dSChen Gang return err; 25733ec3b2fbSDavid Woodhouse 25741da177e4SLinus Torvalds a0 = a[0]; 25751da177e4SLinus Torvalds a1 = a[1]; 25761da177e4SLinus Torvalds 257789bddce5SStephen Hemminger switch (call) { 25781da177e4SLinus Torvalds case SYS_SOCKET: 25799d6a15c3SDominik Brodowski err = __sys_socket(a0, a1, a[2]); 25801da177e4SLinus Torvalds break; 25811da177e4SLinus Torvalds case SYS_BIND: 2582a87d35d8SDominik Brodowski err = __sys_bind(a0, (struct sockaddr __user *)a1, a[2]); 25831da177e4SLinus Torvalds break; 25841da177e4SLinus Torvalds case SYS_CONNECT: 25851387c2c2SDominik Brodowski err = __sys_connect(a0, (struct sockaddr __user *)a1, a[2]); 25861da177e4SLinus Torvalds break; 25871da177e4SLinus Torvalds case SYS_LISTEN: 258825e290eeSDominik Brodowski err = __sys_listen(a0, a1); 25891da177e4SLinus Torvalds break; 25901da177e4SLinus Torvalds case SYS_ACCEPT: 25914541e805SDominik Brodowski err = __sys_accept4(a0, (struct sockaddr __user *)a1, 2592aaca0bdcSUlrich Drepper (int __user *)a[2], 0); 25931da177e4SLinus Torvalds break; 25941da177e4SLinus Torvalds case SYS_GETSOCKNAME: 259589bddce5SStephen Hemminger err = 25968882a107SDominik Brodowski __sys_getsockname(a0, (struct sockaddr __user *)a1, 259789bddce5SStephen Hemminger (int __user *)a[2]); 25981da177e4SLinus Torvalds break; 25991da177e4SLinus Torvalds case SYS_GETPEERNAME: 260089bddce5SStephen Hemminger err = 2601b21c8f83SDominik Brodowski __sys_getpeername(a0, (struct sockaddr __user *)a1, 260289bddce5SStephen Hemminger (int __user *)a[2]); 26031da177e4SLinus Torvalds break; 26041da177e4SLinus Torvalds case SYS_SOCKETPAIR: 26056debc8d8SDominik Brodowski err = __sys_socketpair(a0, a1, a[2], (int __user *)a[3]); 26061da177e4SLinus Torvalds break; 26071da177e4SLinus Torvalds case SYS_SEND: 2608f3bf896bSDominik Brodowski err = __sys_sendto(a0, (void __user *)a1, a[2], a[3], 2609f3bf896bSDominik Brodowski NULL, 0); 26101da177e4SLinus Torvalds break; 26111da177e4SLinus Torvalds case SYS_SENDTO: 2612211b634bSDominik Brodowski err = __sys_sendto(a0, (void __user *)a1, a[2], a[3], 26131da177e4SLinus Torvalds (struct sockaddr __user *)a[4], a[5]); 26141da177e4SLinus Torvalds break; 26151da177e4SLinus Torvalds case SYS_RECV: 2616d27e9afcSDominik Brodowski err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3], 2617d27e9afcSDominik Brodowski NULL, NULL); 26181da177e4SLinus Torvalds break; 26191da177e4SLinus Torvalds case SYS_RECVFROM: 26207a09e1ebSDominik Brodowski err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3], 262189bddce5SStephen Hemminger (struct sockaddr __user *)a[4], 262289bddce5SStephen Hemminger (int __user *)a[5]); 26231da177e4SLinus Torvalds break; 26241da177e4SLinus Torvalds case SYS_SHUTDOWN: 2625005a1aeaSDominik Brodowski err = __sys_shutdown(a0, a1); 26261da177e4SLinus Torvalds break; 26271da177e4SLinus Torvalds case SYS_SETSOCKOPT: 2628cc36dca0SDominik Brodowski err = __sys_setsockopt(a0, a1, a[2], (char __user *)a[3], 2629cc36dca0SDominik Brodowski a[4]); 26301da177e4SLinus Torvalds break; 26311da177e4SLinus Torvalds case SYS_GETSOCKOPT: 263289bddce5SStephen Hemminger err = 263313a2d70eSDominik Brodowski __sys_getsockopt(a0, a1, a[2], (char __user *)a[3], 263489bddce5SStephen Hemminger (int __user *)a[4]); 26351da177e4SLinus Torvalds break; 26361da177e4SLinus Torvalds case SYS_SENDMSG: 2637e1834a32SDominik Brodowski err = __sys_sendmsg(a0, (struct user_msghdr __user *)a1, 2638e1834a32SDominik Brodowski a[2], true); 26391da177e4SLinus Torvalds break; 2640228e548eSAnton Blanchard case SYS_SENDMMSG: 2641e1834a32SDominik Brodowski err = __sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], 2642e1834a32SDominik Brodowski a[3], true); 2643228e548eSAnton Blanchard break; 26441da177e4SLinus Torvalds case SYS_RECVMSG: 2645e1834a32SDominik Brodowski err = __sys_recvmsg(a0, (struct user_msghdr __user *)a1, 2646e1834a32SDominik Brodowski a[2], true); 26471da177e4SLinus Torvalds break; 2648a2e27255SArnaldo Carvalho de Melo case SYS_RECVMMSG: 26491255e269SDominik Brodowski err = do_sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], 26501255e269SDominik Brodowski a[3], (struct timespec __user *)a[4]); 2651a2e27255SArnaldo Carvalho de Melo break; 2652de11defeSUlrich Drepper case SYS_ACCEPT4: 26534541e805SDominik Brodowski err = __sys_accept4(a0, (struct sockaddr __user *)a1, 2654de11defeSUlrich Drepper (int __user *)a[2], a[3]); 2655aaca0bdcSUlrich Drepper break; 26561da177e4SLinus Torvalds default: 26571da177e4SLinus Torvalds err = -EINVAL; 26581da177e4SLinus Torvalds break; 26591da177e4SLinus Torvalds } 26601da177e4SLinus Torvalds return err; 26611da177e4SLinus Torvalds } 26621da177e4SLinus Torvalds 26631da177e4SLinus Torvalds #endif /* __ARCH_WANT_SYS_SOCKETCALL */ 26641da177e4SLinus Torvalds 266555737fdaSStephen Hemminger /** 266655737fdaSStephen Hemminger * sock_register - add a socket protocol handler 266755737fdaSStephen Hemminger * @ops: description of protocol 266855737fdaSStephen Hemminger * 26691da177e4SLinus Torvalds * This function is called by a protocol handler that wants to 26701da177e4SLinus Torvalds * advertise its address family, and have it linked into the 2671e793c0f7SMasanari Iida * socket interface. The value ops->family corresponds to the 267255737fdaSStephen Hemminger * socket system call protocol family. 26731da177e4SLinus Torvalds */ 2674f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops) 26751da177e4SLinus Torvalds { 26761da177e4SLinus Torvalds int err; 26771da177e4SLinus Torvalds 26781da177e4SLinus Torvalds if (ops->family >= NPROTO) { 26793410f22eSYang Yingliang pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO); 26801da177e4SLinus Torvalds return -ENOBUFS; 26811da177e4SLinus Torvalds } 268255737fdaSStephen Hemminger 268355737fdaSStephen Hemminger spin_lock(&net_family_lock); 2684190683a9SEric Dumazet if (rcu_dereference_protected(net_families[ops->family], 2685190683a9SEric Dumazet lockdep_is_held(&net_family_lock))) 26861da177e4SLinus Torvalds err = -EEXIST; 268755737fdaSStephen Hemminger else { 2688cf778b00SEric Dumazet rcu_assign_pointer(net_families[ops->family], ops); 26891da177e4SLinus Torvalds err = 0; 26901da177e4SLinus Torvalds } 269155737fdaSStephen Hemminger spin_unlock(&net_family_lock); 269255737fdaSStephen Hemminger 26933410f22eSYang Yingliang pr_info("NET: Registered protocol family %d\n", ops->family); 26941da177e4SLinus Torvalds return err; 26951da177e4SLinus Torvalds } 2696c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register); 26971da177e4SLinus Torvalds 269855737fdaSStephen Hemminger /** 269955737fdaSStephen Hemminger * sock_unregister - remove a protocol handler 270055737fdaSStephen Hemminger * @family: protocol family to remove 270155737fdaSStephen Hemminger * 27021da177e4SLinus Torvalds * This function is called by a protocol handler that wants to 27031da177e4SLinus Torvalds * remove its address family, and have it unlinked from the 270455737fdaSStephen Hemminger * new socket creation. 270555737fdaSStephen Hemminger * 270655737fdaSStephen Hemminger * If protocol handler is a module, then it can use module reference 270755737fdaSStephen Hemminger * counts to protect against new references. If protocol handler is not 270855737fdaSStephen Hemminger * a module then it needs to provide its own protection in 270955737fdaSStephen Hemminger * the ops->create routine. 27101da177e4SLinus Torvalds */ 2711f0fd27d4SStephen Hemminger void sock_unregister(int family) 27121da177e4SLinus Torvalds { 2713f0fd27d4SStephen Hemminger BUG_ON(family < 0 || family >= NPROTO); 27141da177e4SLinus Torvalds 271555737fdaSStephen Hemminger spin_lock(&net_family_lock); 2716a9b3cd7fSStephen Hemminger RCU_INIT_POINTER(net_families[family], NULL); 271755737fdaSStephen Hemminger spin_unlock(&net_family_lock); 271855737fdaSStephen Hemminger 271955737fdaSStephen Hemminger synchronize_rcu(); 272055737fdaSStephen Hemminger 27213410f22eSYang Yingliang pr_info("NET: Unregistered protocol family %d\n", family); 27221da177e4SLinus Torvalds } 2723c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister); 27241da177e4SLinus Torvalds 2725bf2ae2e4SXin Long bool sock_is_registered(int family) 2726bf2ae2e4SXin Long { 2727bf2ae2e4SXin Long return family < NPROTO && rcu_access_pointer(net_families[family]); 2728bf2ae2e4SXin Long } 2729bf2ae2e4SXin Long 273077d76ea3SAndi Kleen static int __init sock_init(void) 27311da177e4SLinus Torvalds { 2732b3e19d92SNick Piggin int err; 27332ca794e5SEric W. Biederman /* 27342ca794e5SEric W. Biederman * Initialize the network sysctl infrastructure. 27352ca794e5SEric W. Biederman */ 27362ca794e5SEric W. Biederman err = net_sysctl_init(); 27372ca794e5SEric W. Biederman if (err) 27382ca794e5SEric W. Biederman goto out; 2739b3e19d92SNick Piggin 27401da177e4SLinus Torvalds /* 27411da177e4SLinus Torvalds * Initialize skbuff SLAB cache 27421da177e4SLinus Torvalds */ 27431da177e4SLinus Torvalds skb_init(); 27441da177e4SLinus Torvalds 27451da177e4SLinus Torvalds /* 27461da177e4SLinus Torvalds * Initialize the protocols module. 27471da177e4SLinus Torvalds */ 27481da177e4SLinus Torvalds 27491da177e4SLinus Torvalds init_inodecache(); 2750b3e19d92SNick Piggin 2751b3e19d92SNick Piggin err = register_filesystem(&sock_fs_type); 2752b3e19d92SNick Piggin if (err) 2753b3e19d92SNick Piggin goto out_fs; 27541da177e4SLinus Torvalds sock_mnt = kern_mount(&sock_fs_type); 2755b3e19d92SNick Piggin if (IS_ERR(sock_mnt)) { 2756b3e19d92SNick Piggin err = PTR_ERR(sock_mnt); 2757b3e19d92SNick Piggin goto out_mount; 2758b3e19d92SNick Piggin } 275977d76ea3SAndi Kleen 276077d76ea3SAndi Kleen /* The real protocol initialization is performed in later initcalls. 27611da177e4SLinus Torvalds */ 27621da177e4SLinus Torvalds 27631da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER 27646d11cfdbSPablo Neira Ayuso err = netfilter_init(); 27656d11cfdbSPablo Neira Ayuso if (err) 27666d11cfdbSPablo Neira Ayuso goto out; 27671da177e4SLinus Torvalds #endif 2768cbeb321aSDavid S. Miller 2769408eccceSDaniel Borkmann ptp_classifier_init(); 2770c1f19b51SRichard Cochran 2771b3e19d92SNick Piggin out: 2772b3e19d92SNick Piggin return err; 2773b3e19d92SNick Piggin 2774b3e19d92SNick Piggin out_mount: 2775b3e19d92SNick Piggin unregister_filesystem(&sock_fs_type); 2776b3e19d92SNick Piggin out_fs: 2777b3e19d92SNick Piggin goto out; 27781da177e4SLinus Torvalds } 27791da177e4SLinus Torvalds 278077d76ea3SAndi Kleen core_initcall(sock_init); /* early initcall */ 278177d76ea3SAndi Kleen 27821da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS 27831da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq) 27841da177e4SLinus Torvalds { 2785648845abSTonghao Zhang seq_printf(seq, "sockets: used %d\n", 2786648845abSTonghao Zhang sock_inuse_get(seq->private)); 27871da177e4SLinus Torvalds } 27881da177e4SLinus Torvalds #endif /* CONFIG_PROC_FS */ 27891da177e4SLinus Torvalds 279089bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 27916b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock, 2792644595f8SH. Peter Anvin unsigned int cmd, void __user *up) 27937a229387SArnd Bergmann { 27947a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 27957a229387SArnd Bergmann struct timeval ktv; 27967a229387SArnd Bergmann int err; 27977a229387SArnd Bergmann 27987a229387SArnd Bergmann set_fs(KERNEL_DS); 27996b96018bSArnd Bergmann err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv); 28007a229387SArnd Bergmann set_fs(old_fs); 2801644595f8SH. Peter Anvin if (!err) 2802ed6fe9d6SMikulas Patocka err = compat_put_timeval(&ktv, up); 2803644595f8SH. Peter Anvin 28047a229387SArnd Bergmann return err; 28057a229387SArnd Bergmann } 28067a229387SArnd Bergmann 28076b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock, 2808644595f8SH. Peter Anvin unsigned int cmd, void __user *up) 28097a229387SArnd Bergmann { 28107a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 28117a229387SArnd Bergmann struct timespec kts; 28127a229387SArnd Bergmann int err; 28137a229387SArnd Bergmann 28147a229387SArnd Bergmann set_fs(KERNEL_DS); 28156b96018bSArnd Bergmann err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts); 28167a229387SArnd Bergmann set_fs(old_fs); 2817644595f8SH. Peter Anvin if (!err) 2818ed6fe9d6SMikulas Patocka err = compat_put_timespec(&kts, up); 2819644595f8SH. Peter Anvin 28207a229387SArnd Bergmann return err; 28217a229387SArnd Bergmann } 28227a229387SArnd Bergmann 282336fd633eSAl Viro static int compat_dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) 28247a229387SArnd Bergmann { 28256b96018bSArnd Bergmann struct compat_ifconf ifc32; 28267a229387SArnd Bergmann struct ifconf ifc; 28277a229387SArnd Bergmann int err; 28287a229387SArnd Bergmann 28296b96018bSArnd Bergmann if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf))) 28307a229387SArnd Bergmann return -EFAULT; 28317a229387SArnd Bergmann 283236fd633eSAl Viro ifc.ifc_len = ifc32.ifc_len; 283336fd633eSAl Viro ifc.ifc_req = compat_ptr(ifc32.ifcbuf); 28347a229387SArnd Bergmann 283536fd633eSAl Viro rtnl_lock(); 283636fd633eSAl Viro err = dev_ifconf(net, &ifc, sizeof(struct compat_ifreq)); 283736fd633eSAl Viro rtnl_unlock(); 28387a229387SArnd Bergmann if (err) 28397a229387SArnd Bergmann return err; 28407a229387SArnd Bergmann 284136fd633eSAl Viro ifc32.ifc_len = ifc.ifc_len; 28426b96018bSArnd Bergmann if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf))) 28437a229387SArnd Bergmann return -EFAULT; 28447a229387SArnd Bergmann 28457a229387SArnd Bergmann return 0; 28467a229387SArnd Bergmann } 28477a229387SArnd Bergmann 28486b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) 28497a229387SArnd Bergmann { 28503a7da39dSBen Hutchings struct compat_ethtool_rxnfc __user *compat_rxnfc; 28513a7da39dSBen Hutchings bool convert_in = false, convert_out = false; 285244c02a2cSAl Viro size_t buf_size = 0; 285344c02a2cSAl Viro struct ethtool_rxnfc __user *rxnfc = NULL; 285444c02a2cSAl Viro struct ifreq ifr; 28553a7da39dSBen Hutchings u32 rule_cnt = 0, actual_rule_cnt; 28563a7da39dSBen Hutchings u32 ethcmd; 28577a229387SArnd Bergmann u32 data; 28583a7da39dSBen Hutchings int ret; 28597a229387SArnd Bergmann 28607a229387SArnd Bergmann if (get_user(data, &ifr32->ifr_ifru.ifru_data)) 28617a229387SArnd Bergmann return -EFAULT; 28627a229387SArnd Bergmann 28633a7da39dSBen Hutchings compat_rxnfc = compat_ptr(data); 28643a7da39dSBen Hutchings 28653a7da39dSBen Hutchings if (get_user(ethcmd, &compat_rxnfc->cmd)) 28667a229387SArnd Bergmann return -EFAULT; 28677a229387SArnd Bergmann 28683a7da39dSBen Hutchings /* Most ethtool structures are defined without padding. 28693a7da39dSBen Hutchings * Unfortunately struct ethtool_rxnfc is an exception. 28703a7da39dSBen Hutchings */ 28713a7da39dSBen Hutchings switch (ethcmd) { 28723a7da39dSBen Hutchings default: 28733a7da39dSBen Hutchings break; 28743a7da39dSBen Hutchings case ETHTOOL_GRXCLSRLALL: 28753a7da39dSBen Hutchings /* Buffer size is variable */ 28763a7da39dSBen Hutchings if (get_user(rule_cnt, &compat_rxnfc->rule_cnt)) 28773a7da39dSBen Hutchings return -EFAULT; 28783a7da39dSBen Hutchings if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32)) 28793a7da39dSBen Hutchings return -ENOMEM; 28803a7da39dSBen Hutchings buf_size += rule_cnt * sizeof(u32); 28813a7da39dSBen Hutchings /* fall through */ 28823a7da39dSBen Hutchings case ETHTOOL_GRXRINGS: 28833a7da39dSBen Hutchings case ETHTOOL_GRXCLSRLCNT: 28843a7da39dSBen Hutchings case ETHTOOL_GRXCLSRULE: 288555664f32SBen Hutchings case ETHTOOL_SRXCLSRLINS: 28863a7da39dSBen Hutchings convert_out = true; 28873a7da39dSBen Hutchings /* fall through */ 28883a7da39dSBen Hutchings case ETHTOOL_SRXCLSRLDEL: 28893a7da39dSBen Hutchings buf_size += sizeof(struct ethtool_rxnfc); 28903a7da39dSBen Hutchings convert_in = true; 289144c02a2cSAl Viro rxnfc = compat_alloc_user_space(buf_size); 28923a7da39dSBen Hutchings break; 28933a7da39dSBen Hutchings } 28943a7da39dSBen Hutchings 289544c02a2cSAl Viro if (copy_from_user(&ifr.ifr_name, &ifr32->ifr_name, IFNAMSIZ)) 28963a7da39dSBen Hutchings return -EFAULT; 28973a7da39dSBen Hutchings 289844c02a2cSAl Viro ifr.ifr_data = convert_in ? rxnfc : (void __user *)compat_rxnfc; 28993a7da39dSBen Hutchings 29003a7da39dSBen Hutchings if (convert_in) { 2901127fe533SAlexander Duyck /* We expect there to be holes between fs.m_ext and 29023a7da39dSBen Hutchings * fs.ring_cookie and at the end of fs, but nowhere else. 29033a7da39dSBen Hutchings */ 2904127fe533SAlexander Duyck BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) + 2905127fe533SAlexander Duyck sizeof(compat_rxnfc->fs.m_ext) != 2906127fe533SAlexander Duyck offsetof(struct ethtool_rxnfc, fs.m_ext) + 2907127fe533SAlexander Duyck sizeof(rxnfc->fs.m_ext)); 29083a7da39dSBen Hutchings BUILD_BUG_ON( 29093a7da39dSBen Hutchings offsetof(struct compat_ethtool_rxnfc, fs.location) - 29103a7da39dSBen Hutchings offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) != 29113a7da39dSBen Hutchings offsetof(struct ethtool_rxnfc, fs.location) - 29123a7da39dSBen Hutchings offsetof(struct ethtool_rxnfc, fs.ring_cookie)); 29133a7da39dSBen Hutchings 29143a7da39dSBen Hutchings if (copy_in_user(rxnfc, compat_rxnfc, 2915954b1244SStephen Hemminger (void __user *)(&rxnfc->fs.m_ext + 1) - 2916954b1244SStephen Hemminger (void __user *)rxnfc) || 29173a7da39dSBen Hutchings copy_in_user(&rxnfc->fs.ring_cookie, 29183a7da39dSBen Hutchings &compat_rxnfc->fs.ring_cookie, 2919954b1244SStephen Hemminger (void __user *)(&rxnfc->fs.location + 1) - 2920954b1244SStephen Hemminger (void __user *)&rxnfc->fs.ring_cookie) || 29213a7da39dSBen Hutchings copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt, 29223a7da39dSBen Hutchings sizeof(rxnfc->rule_cnt))) 29233a7da39dSBen Hutchings return -EFAULT; 29243a7da39dSBen Hutchings } 29253a7da39dSBen Hutchings 292644c02a2cSAl Viro ret = dev_ioctl(net, SIOCETHTOOL, &ifr, NULL); 29273a7da39dSBen Hutchings if (ret) 29283a7da39dSBen Hutchings return ret; 29293a7da39dSBen Hutchings 29303a7da39dSBen Hutchings if (convert_out) { 29313a7da39dSBen Hutchings if (copy_in_user(compat_rxnfc, rxnfc, 2932954b1244SStephen Hemminger (const void __user *)(&rxnfc->fs.m_ext + 1) - 2933954b1244SStephen Hemminger (const void __user *)rxnfc) || 29343a7da39dSBen Hutchings copy_in_user(&compat_rxnfc->fs.ring_cookie, 29353a7da39dSBen Hutchings &rxnfc->fs.ring_cookie, 2936954b1244SStephen Hemminger (const void __user *)(&rxnfc->fs.location + 1) - 2937954b1244SStephen Hemminger (const void __user *)&rxnfc->fs.ring_cookie) || 29383a7da39dSBen Hutchings copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt, 29393a7da39dSBen Hutchings sizeof(rxnfc->rule_cnt))) 29403a7da39dSBen Hutchings return -EFAULT; 29413a7da39dSBen Hutchings 29423a7da39dSBen Hutchings if (ethcmd == ETHTOOL_GRXCLSRLALL) { 29433a7da39dSBen Hutchings /* As an optimisation, we only copy the actual 29443a7da39dSBen Hutchings * number of rules that the underlying 29453a7da39dSBen Hutchings * function returned. Since Mallory might 29463a7da39dSBen Hutchings * change the rule count in user memory, we 29473a7da39dSBen Hutchings * check that it is less than the rule count 29483a7da39dSBen Hutchings * originally given (as the user buffer size), 29493a7da39dSBen Hutchings * which has been range-checked. 29503a7da39dSBen Hutchings */ 29513a7da39dSBen Hutchings if (get_user(actual_rule_cnt, &rxnfc->rule_cnt)) 29523a7da39dSBen Hutchings return -EFAULT; 29533a7da39dSBen Hutchings if (actual_rule_cnt < rule_cnt) 29543a7da39dSBen Hutchings rule_cnt = actual_rule_cnt; 29553a7da39dSBen Hutchings if (copy_in_user(&compat_rxnfc->rule_locs[0], 29563a7da39dSBen Hutchings &rxnfc->rule_locs[0], 29573a7da39dSBen Hutchings rule_cnt * sizeof(u32))) 29583a7da39dSBen Hutchings return -EFAULT; 29593a7da39dSBen Hutchings } 29603a7da39dSBen Hutchings } 29613a7da39dSBen Hutchings 29623a7da39dSBen Hutchings return 0; 29637a229387SArnd Bergmann } 29647a229387SArnd Bergmann 29657a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32) 29667a50a240SArnd Bergmann { 29677a50a240SArnd Bergmann compat_uptr_t uptr32; 296844c02a2cSAl Viro struct ifreq ifr; 296944c02a2cSAl Viro void __user *saved; 297044c02a2cSAl Viro int err; 29717a50a240SArnd Bergmann 297244c02a2cSAl Viro if (copy_from_user(&ifr, uifr32, sizeof(struct compat_ifreq))) 29737a50a240SArnd Bergmann return -EFAULT; 29747a50a240SArnd Bergmann 29757a50a240SArnd Bergmann if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu)) 29767a50a240SArnd Bergmann return -EFAULT; 29777a50a240SArnd Bergmann 297844c02a2cSAl Viro saved = ifr.ifr_settings.ifs_ifsu.raw_hdlc; 297944c02a2cSAl Viro ifr.ifr_settings.ifs_ifsu.raw_hdlc = compat_ptr(uptr32); 29807a50a240SArnd Bergmann 298144c02a2cSAl Viro err = dev_ioctl(net, SIOCWANDEV, &ifr, NULL); 298244c02a2cSAl Viro if (!err) { 298344c02a2cSAl Viro ifr.ifr_settings.ifs_ifsu.raw_hdlc = saved; 298444c02a2cSAl Viro if (copy_to_user(uifr32, &ifr, sizeof(struct compat_ifreq))) 298544c02a2cSAl Viro err = -EFAULT; 29867a50a240SArnd Bergmann } 29877a229387SArnd Bergmann return err; 29887a229387SArnd Bergmann } 29897a229387SArnd Bergmann 2990590d4693SBen Hutchings /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */ 2991590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd, 29926b96018bSArnd Bergmann struct compat_ifreq __user *u_ifreq32) 29937a229387SArnd Bergmann { 299444c02a2cSAl Viro struct ifreq ifreq; 29957a229387SArnd Bergmann u32 data32; 29967a229387SArnd Bergmann 299744c02a2cSAl Viro if (copy_from_user(ifreq.ifr_name, u_ifreq32->ifr_name, IFNAMSIZ)) 29987a229387SArnd Bergmann return -EFAULT; 299944c02a2cSAl Viro if (get_user(data32, &u_ifreq32->ifr_data)) 30007a229387SArnd Bergmann return -EFAULT; 300144c02a2cSAl Viro ifreq.ifr_data = compat_ptr(data32); 30027a229387SArnd Bergmann 300344c02a2cSAl Viro return dev_ioctl(net, cmd, &ifreq, NULL); 3004a2116ed2SArnd Bergmann } 3005a2116ed2SArnd Bergmann 3006a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd, 3007a2116ed2SArnd Bergmann struct compat_ifreq __user *uifr32) 3008a2116ed2SArnd Bergmann { 3009a2116ed2SArnd Bergmann struct ifreq ifr; 3010a2116ed2SArnd Bergmann struct compat_ifmap __user *uifmap32; 3011a2116ed2SArnd Bergmann int err; 3012a2116ed2SArnd Bergmann 3013a2116ed2SArnd Bergmann uifmap32 = &uifr32->ifr_ifru.ifru_map; 3014a2116ed2SArnd Bergmann err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name)); 30153ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); 30163ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); 30173ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); 30183ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.irq, &uifmap32->irq); 30193ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.dma, &uifmap32->dma); 30203ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.port, &uifmap32->port); 3021a2116ed2SArnd Bergmann if (err) 3022a2116ed2SArnd Bergmann return -EFAULT; 3023a2116ed2SArnd Bergmann 302444c02a2cSAl Viro err = dev_ioctl(net, cmd, &ifr, NULL); 3025a2116ed2SArnd Bergmann 3026a2116ed2SArnd Bergmann if (cmd == SIOCGIFMAP && !err) { 30277a229387SArnd Bergmann err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name)); 30283ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); 30293ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); 30303ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); 30313ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.irq, &uifmap32->irq); 30323ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.dma, &uifmap32->dma); 30333ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.port, &uifmap32->port); 30347a229387SArnd Bergmann if (err) 30357a229387SArnd Bergmann err = -EFAULT; 30367a229387SArnd Bergmann } 30377a229387SArnd Bergmann return err; 30387a229387SArnd Bergmann } 30397a229387SArnd Bergmann 30407a229387SArnd Bergmann struct rtentry32 { 30417a229387SArnd Bergmann u32 rt_pad1; 30427a229387SArnd Bergmann struct sockaddr rt_dst; /* target address */ 30437a229387SArnd Bergmann struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ 30447a229387SArnd Bergmann struct sockaddr rt_genmask; /* target network mask (IP) */ 30457a229387SArnd Bergmann unsigned short rt_flags; 30467a229387SArnd Bergmann short rt_pad2; 30477a229387SArnd Bergmann u32 rt_pad3; 30487a229387SArnd Bergmann unsigned char rt_tos; 30497a229387SArnd Bergmann unsigned char rt_class; 30507a229387SArnd Bergmann short rt_pad4; 30517a229387SArnd Bergmann short rt_metric; /* +1 for binary compatibility! */ 30527a229387SArnd Bergmann /* char * */ u32 rt_dev; /* forcing the device at add */ 30537a229387SArnd Bergmann u32 rt_mtu; /* per route MTU/Window */ 30547a229387SArnd Bergmann u32 rt_window; /* Window clamping */ 30557a229387SArnd Bergmann unsigned short rt_irtt; /* Initial RTT */ 30567a229387SArnd Bergmann }; 30577a229387SArnd Bergmann 30587a229387SArnd Bergmann struct in6_rtmsg32 { 30597a229387SArnd Bergmann struct in6_addr rtmsg_dst; 30607a229387SArnd Bergmann struct in6_addr rtmsg_src; 30617a229387SArnd Bergmann struct in6_addr rtmsg_gateway; 30627a229387SArnd Bergmann u32 rtmsg_type; 30637a229387SArnd Bergmann u16 rtmsg_dst_len; 30647a229387SArnd Bergmann u16 rtmsg_src_len; 30657a229387SArnd Bergmann u32 rtmsg_metric; 30667a229387SArnd Bergmann u32 rtmsg_info; 30677a229387SArnd Bergmann u32 rtmsg_flags; 30687a229387SArnd Bergmann s32 rtmsg_ifindex; 30697a229387SArnd Bergmann }; 30707a229387SArnd Bergmann 30716b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock, 30726b96018bSArnd Bergmann unsigned int cmd, void __user *argp) 30737a229387SArnd Bergmann { 30747a229387SArnd Bergmann int ret; 30757a229387SArnd Bergmann void *r = NULL; 30767a229387SArnd Bergmann struct in6_rtmsg r6; 30777a229387SArnd Bergmann struct rtentry r4; 30787a229387SArnd Bergmann char devname[16]; 30797a229387SArnd Bergmann u32 rtdev; 30807a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 30817a229387SArnd Bergmann 30826b96018bSArnd Bergmann if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */ 30836b96018bSArnd Bergmann struct in6_rtmsg32 __user *ur6 = argp; 30847a229387SArnd Bergmann ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst), 30857a229387SArnd Bergmann 3 * sizeof(struct in6_addr)); 30863ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type)); 30873ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len)); 30883ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len)); 30893ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric)); 30903ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info)); 30913ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags)); 30923ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex)); 30937a229387SArnd Bergmann 30947a229387SArnd Bergmann r = (void *) &r6; 30957a229387SArnd Bergmann } else { /* ipv4 */ 30966b96018bSArnd Bergmann struct rtentry32 __user *ur4 = argp; 30977a229387SArnd Bergmann ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst), 30987a229387SArnd Bergmann 3 * sizeof(struct sockaddr)); 30993ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_flags, &(ur4->rt_flags)); 31003ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_metric, &(ur4->rt_metric)); 31013ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu)); 31023ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_window, &(ur4->rt_window)); 31033ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt)); 31043ddc5b46SMathieu Desnoyers ret |= get_user(rtdev, &(ur4->rt_dev)); 31057a229387SArnd Bergmann if (rtdev) { 31067a229387SArnd Bergmann ret |= copy_from_user(devname, compat_ptr(rtdev), 15); 3107c3f52ae6Sstephen hemminger r4.rt_dev = (char __user __force *)devname; 3108c3f52ae6Sstephen hemminger devname[15] = 0; 31097a229387SArnd Bergmann } else 31107a229387SArnd Bergmann r4.rt_dev = NULL; 31117a229387SArnd Bergmann 31127a229387SArnd Bergmann r = (void *) &r4; 31137a229387SArnd Bergmann } 31147a229387SArnd Bergmann 31157a229387SArnd Bergmann if (ret) { 31167a229387SArnd Bergmann ret = -EFAULT; 31177a229387SArnd Bergmann goto out; 31187a229387SArnd Bergmann } 31197a229387SArnd Bergmann 31207a229387SArnd Bergmann set_fs(KERNEL_DS); 31216b96018bSArnd Bergmann ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r); 31227a229387SArnd Bergmann set_fs(old_fs); 31237a229387SArnd Bergmann 31247a229387SArnd Bergmann out: 31257a229387SArnd Bergmann return ret; 31267a229387SArnd Bergmann } 31277a229387SArnd Bergmann 31287a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE 31297a229387SArnd Bergmann * for some operations; this forces use of the newer bridge-utils that 313025985edcSLucas De Marchi * use compatible ioctls 31317a229387SArnd Bergmann */ 31326b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp) 31337a229387SArnd Bergmann { 31346b96018bSArnd Bergmann compat_ulong_t tmp; 31357a229387SArnd Bergmann 31366b96018bSArnd Bergmann if (get_user(tmp, argp)) 31377a229387SArnd Bergmann return -EFAULT; 31387a229387SArnd Bergmann if (tmp == BRCTL_GET_VERSION) 31397a229387SArnd Bergmann return BRCTL_VERSION + 1; 31407a229387SArnd Bergmann return -EINVAL; 31417a229387SArnd Bergmann } 31427a229387SArnd Bergmann 31436b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, 31446b96018bSArnd Bergmann unsigned int cmd, unsigned long arg) 31456b96018bSArnd Bergmann { 31466b96018bSArnd Bergmann void __user *argp = compat_ptr(arg); 31476b96018bSArnd Bergmann struct sock *sk = sock->sk; 31486b96018bSArnd Bergmann struct net *net = sock_net(sk); 31497a229387SArnd Bergmann 31506b96018bSArnd Bergmann if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) 3151590d4693SBen Hutchings return compat_ifr_data_ioctl(net, cmd, argp); 31527a229387SArnd Bergmann 31536b96018bSArnd Bergmann switch (cmd) { 31546b96018bSArnd Bergmann case SIOCSIFBR: 31556b96018bSArnd Bergmann case SIOCGIFBR: 31566b96018bSArnd Bergmann return old_bridge_ioctl(argp); 31576b96018bSArnd Bergmann case SIOCGIFCONF: 315836fd633eSAl Viro return compat_dev_ifconf(net, argp); 31596b96018bSArnd Bergmann case SIOCETHTOOL: 31606b96018bSArnd Bergmann return ethtool_ioctl(net, argp); 31617a50a240SArnd Bergmann case SIOCWANDEV: 31627a50a240SArnd Bergmann return compat_siocwandev(net, argp); 3163a2116ed2SArnd Bergmann case SIOCGIFMAP: 3164a2116ed2SArnd Bergmann case SIOCSIFMAP: 3165a2116ed2SArnd Bergmann return compat_sioc_ifmap(net, cmd, argp); 31666b96018bSArnd Bergmann case SIOCADDRT: 31676b96018bSArnd Bergmann case SIOCDELRT: 31686b96018bSArnd Bergmann return routing_ioctl(net, sock, cmd, argp); 31696b96018bSArnd Bergmann case SIOCGSTAMP: 31706b96018bSArnd Bergmann return do_siocgstamp(net, sock, cmd, argp); 31716b96018bSArnd Bergmann case SIOCGSTAMPNS: 31726b96018bSArnd Bergmann return do_siocgstampns(net, sock, cmd, argp); 3173590d4693SBen Hutchings case SIOCBONDSLAVEINFOQUERY: 3174590d4693SBen Hutchings case SIOCBONDINFOQUERY: 3175a2116ed2SArnd Bergmann case SIOCSHWTSTAMP: 3176fd468c74SBen Hutchings case SIOCGHWTSTAMP: 3177590d4693SBen Hutchings return compat_ifr_data_ioctl(net, cmd, argp); 31787a229387SArnd Bergmann 31796b96018bSArnd Bergmann case FIOSETOWN: 31806b96018bSArnd Bergmann case SIOCSPGRP: 31816b96018bSArnd Bergmann case FIOGETOWN: 31826b96018bSArnd Bergmann case SIOCGPGRP: 31836b96018bSArnd Bergmann case SIOCBRADDBR: 31846b96018bSArnd Bergmann case SIOCBRDELBR: 31856b96018bSArnd Bergmann case SIOCGIFVLAN: 31866b96018bSArnd Bergmann case SIOCSIFVLAN: 31876b96018bSArnd Bergmann case SIOCADDDLCI: 31886b96018bSArnd Bergmann case SIOCDELDLCI: 3189c62cce2cSAndrey Vagin case SIOCGSKNS: 31906b96018bSArnd Bergmann return sock_ioctl(file, cmd, arg); 31916b96018bSArnd Bergmann 31926b96018bSArnd Bergmann case SIOCGIFFLAGS: 31936b96018bSArnd Bergmann case SIOCSIFFLAGS: 31946b96018bSArnd Bergmann case SIOCGIFMETRIC: 31956b96018bSArnd Bergmann case SIOCSIFMETRIC: 31966b96018bSArnd Bergmann case SIOCGIFMTU: 31976b96018bSArnd Bergmann case SIOCSIFMTU: 31986b96018bSArnd Bergmann case SIOCGIFMEM: 31996b96018bSArnd Bergmann case SIOCSIFMEM: 32006b96018bSArnd Bergmann case SIOCGIFHWADDR: 32016b96018bSArnd Bergmann case SIOCSIFHWADDR: 32026b96018bSArnd Bergmann case SIOCADDMULTI: 32036b96018bSArnd Bergmann case SIOCDELMULTI: 32046b96018bSArnd Bergmann case SIOCGIFINDEX: 32056b96018bSArnd Bergmann case SIOCGIFADDR: 32066b96018bSArnd Bergmann case SIOCSIFADDR: 32076b96018bSArnd Bergmann case SIOCSIFHWBROADCAST: 32086b96018bSArnd Bergmann case SIOCDIFADDR: 32096b96018bSArnd Bergmann case SIOCGIFBRDADDR: 32106b96018bSArnd Bergmann case SIOCSIFBRDADDR: 32116b96018bSArnd Bergmann case SIOCGIFDSTADDR: 32126b96018bSArnd Bergmann case SIOCSIFDSTADDR: 32136b96018bSArnd Bergmann case SIOCGIFNETMASK: 32146b96018bSArnd Bergmann case SIOCSIFNETMASK: 32156b96018bSArnd Bergmann case SIOCSIFPFLAGS: 32166b96018bSArnd Bergmann case SIOCGIFPFLAGS: 32176b96018bSArnd Bergmann case SIOCGIFTXQLEN: 32186b96018bSArnd Bergmann case SIOCSIFTXQLEN: 32196b96018bSArnd Bergmann case SIOCBRADDIF: 32206b96018bSArnd Bergmann case SIOCBRDELIF: 32219177efd3SArnd Bergmann case SIOCSIFNAME: 32229177efd3SArnd Bergmann case SIOCGMIIPHY: 32239177efd3SArnd Bergmann case SIOCGMIIREG: 32249177efd3SArnd Bergmann case SIOCSMIIREG: 32256b96018bSArnd Bergmann case SIOCSARP: 32266b96018bSArnd Bergmann case SIOCGARP: 32276b96018bSArnd Bergmann case SIOCDARP: 32286b96018bSArnd Bergmann case SIOCATMARK: 3229f92d4fc9SAl Viro case SIOCBONDENSLAVE: 3230f92d4fc9SAl Viro case SIOCBONDRELEASE: 3231f92d4fc9SAl Viro case SIOCBONDSETHWADDR: 3232f92d4fc9SAl Viro case SIOCBONDCHANGEACTIVE: 32334cf808e7SAl Viro case SIOCGIFNAME: 32349177efd3SArnd Bergmann return sock_do_ioctl(net, sock, cmd, arg); 32359177efd3SArnd Bergmann } 32369177efd3SArnd Bergmann 32376b96018bSArnd Bergmann return -ENOIOCTLCMD; 32386b96018bSArnd Bergmann } 32397a229387SArnd Bergmann 324095c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd, 324189bbfc95SShaun Pereira unsigned long arg) 324289bbfc95SShaun Pereira { 324389bbfc95SShaun Pereira struct socket *sock = file->private_data; 324489bbfc95SShaun Pereira int ret = -ENOIOCTLCMD; 324587de87d5SDavid S. Miller struct sock *sk; 324687de87d5SDavid S. Miller struct net *net; 324787de87d5SDavid S. Miller 324887de87d5SDavid S. Miller sk = sock->sk; 324987de87d5SDavid S. Miller net = sock_net(sk); 325089bbfc95SShaun Pereira 325189bbfc95SShaun Pereira if (sock->ops->compat_ioctl) 325289bbfc95SShaun Pereira ret = sock->ops->compat_ioctl(sock, cmd, arg); 325389bbfc95SShaun Pereira 325487de87d5SDavid S. Miller if (ret == -ENOIOCTLCMD && 325587de87d5SDavid S. Miller (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)) 325687de87d5SDavid S. Miller ret = compat_wext_handle_ioctl(net, cmd, arg); 325787de87d5SDavid S. Miller 32586b96018bSArnd Bergmann if (ret == -ENOIOCTLCMD) 32596b96018bSArnd Bergmann ret = compat_sock_ioctl_trans(file, sock, cmd, arg); 32606b96018bSArnd Bergmann 326189bbfc95SShaun Pereira return ret; 326289bbfc95SShaun Pereira } 326389bbfc95SShaun Pereira #endif 326489bbfc95SShaun Pereira 3265ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen) 3266ac5a488eSSridhar Samudrala { 3267ac5a488eSSridhar Samudrala return sock->ops->bind(sock, addr, addrlen); 3268ac5a488eSSridhar Samudrala } 3269c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind); 3270ac5a488eSSridhar Samudrala 3271ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog) 3272ac5a488eSSridhar Samudrala { 3273ac5a488eSSridhar Samudrala return sock->ops->listen(sock, backlog); 3274ac5a488eSSridhar Samudrala } 3275c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen); 3276ac5a488eSSridhar Samudrala 3277ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags) 3278ac5a488eSSridhar Samudrala { 3279ac5a488eSSridhar Samudrala struct sock *sk = sock->sk; 3280ac5a488eSSridhar Samudrala int err; 3281ac5a488eSSridhar Samudrala 3282ac5a488eSSridhar Samudrala err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol, 3283ac5a488eSSridhar Samudrala newsock); 3284ac5a488eSSridhar Samudrala if (err < 0) 3285ac5a488eSSridhar Samudrala goto done; 3286ac5a488eSSridhar Samudrala 3287cdfbabfbSDavid Howells err = sock->ops->accept(sock, *newsock, flags, true); 3288ac5a488eSSridhar Samudrala if (err < 0) { 3289ac5a488eSSridhar Samudrala sock_release(*newsock); 3290fa8705b0STony Battersby *newsock = NULL; 3291ac5a488eSSridhar Samudrala goto done; 3292ac5a488eSSridhar Samudrala } 3293ac5a488eSSridhar Samudrala 3294ac5a488eSSridhar Samudrala (*newsock)->ops = sock->ops; 32951b08534eSWei Yongjun __module_get((*newsock)->ops->owner); 3296ac5a488eSSridhar Samudrala 3297ac5a488eSSridhar Samudrala done: 3298ac5a488eSSridhar Samudrala return err; 3299ac5a488eSSridhar Samudrala } 3300c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept); 3301ac5a488eSSridhar Samudrala 3302ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen, 3303ac5a488eSSridhar Samudrala int flags) 3304ac5a488eSSridhar Samudrala { 3305ac5a488eSSridhar Samudrala return sock->ops->connect(sock, addr, addrlen, flags); 3306ac5a488eSSridhar Samudrala } 3307c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect); 3308ac5a488eSSridhar Samudrala 33099b2c45d4SDenys Vlasenko int kernel_getsockname(struct socket *sock, struct sockaddr *addr) 3310ac5a488eSSridhar Samudrala { 33119b2c45d4SDenys Vlasenko return sock->ops->getname(sock, addr, 0); 3312ac5a488eSSridhar Samudrala } 3313c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname); 3314ac5a488eSSridhar Samudrala 33159b2c45d4SDenys Vlasenko int kernel_getpeername(struct socket *sock, struct sockaddr *addr) 3316ac5a488eSSridhar Samudrala { 33179b2c45d4SDenys Vlasenko return sock->ops->getname(sock, addr, 1); 3318ac5a488eSSridhar Samudrala } 3319c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername); 3320ac5a488eSSridhar Samudrala 3321ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname, 3322ac5a488eSSridhar Samudrala char *optval, int *optlen) 3323ac5a488eSSridhar Samudrala { 3324ac5a488eSSridhar Samudrala mm_segment_t oldfs = get_fs(); 3325fb8621bbSNamhyung Kim char __user *uoptval; 3326fb8621bbSNamhyung Kim int __user *uoptlen; 3327ac5a488eSSridhar Samudrala int err; 3328ac5a488eSSridhar Samudrala 3329fb8621bbSNamhyung Kim uoptval = (char __user __force *) optval; 3330fb8621bbSNamhyung Kim uoptlen = (int __user __force *) optlen; 3331fb8621bbSNamhyung Kim 3332ac5a488eSSridhar Samudrala set_fs(KERNEL_DS); 3333ac5a488eSSridhar Samudrala if (level == SOL_SOCKET) 3334fb8621bbSNamhyung Kim err = sock_getsockopt(sock, level, optname, uoptval, uoptlen); 3335ac5a488eSSridhar Samudrala else 3336fb8621bbSNamhyung Kim err = sock->ops->getsockopt(sock, level, optname, uoptval, 3337fb8621bbSNamhyung Kim uoptlen); 3338ac5a488eSSridhar Samudrala set_fs(oldfs); 3339ac5a488eSSridhar Samudrala return err; 3340ac5a488eSSridhar Samudrala } 3341c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt); 3342ac5a488eSSridhar Samudrala 3343ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname, 3344b7058842SDavid S. Miller char *optval, unsigned int optlen) 3345ac5a488eSSridhar Samudrala { 3346ac5a488eSSridhar Samudrala mm_segment_t oldfs = get_fs(); 3347fb8621bbSNamhyung Kim char __user *uoptval; 3348ac5a488eSSridhar Samudrala int err; 3349ac5a488eSSridhar Samudrala 3350fb8621bbSNamhyung Kim uoptval = (char __user __force *) optval; 3351fb8621bbSNamhyung Kim 3352ac5a488eSSridhar Samudrala set_fs(KERNEL_DS); 3353ac5a488eSSridhar Samudrala if (level == SOL_SOCKET) 3354fb8621bbSNamhyung Kim err = sock_setsockopt(sock, level, optname, uoptval, optlen); 3355ac5a488eSSridhar Samudrala else 3356fb8621bbSNamhyung Kim err = sock->ops->setsockopt(sock, level, optname, uoptval, 3357ac5a488eSSridhar Samudrala optlen); 3358ac5a488eSSridhar Samudrala set_fs(oldfs); 3359ac5a488eSSridhar Samudrala return err; 3360ac5a488eSSridhar Samudrala } 3361c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt); 3362ac5a488eSSridhar Samudrala 3363ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset, 3364ac5a488eSSridhar Samudrala size_t size, int flags) 3365ac5a488eSSridhar Samudrala { 3366ac5a488eSSridhar Samudrala if (sock->ops->sendpage) 3367ac5a488eSSridhar Samudrala return sock->ops->sendpage(sock, page, offset, size, flags); 3368ac5a488eSSridhar Samudrala 3369ac5a488eSSridhar Samudrala return sock_no_sendpage(sock, page, offset, size, flags); 3370ac5a488eSSridhar Samudrala } 3371c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage); 3372ac5a488eSSridhar Samudrala 3373306b13ebSTom Herbert int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset, 3374306b13ebSTom Herbert size_t size, int flags) 3375306b13ebSTom Herbert { 3376306b13ebSTom Herbert struct socket *sock = sk->sk_socket; 3377306b13ebSTom Herbert 3378306b13ebSTom Herbert if (sock->ops->sendpage_locked) 3379306b13ebSTom Herbert return sock->ops->sendpage_locked(sk, page, offset, size, 3380306b13ebSTom Herbert flags); 3381306b13ebSTom Herbert 3382306b13ebSTom Herbert return sock_no_sendpage_locked(sk, page, offset, size, flags); 3383306b13ebSTom Herbert } 3384306b13ebSTom Herbert EXPORT_SYMBOL(kernel_sendpage_locked); 3385306b13ebSTom Herbert 338691cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how) 338791cf45f0STrond Myklebust { 338891cf45f0STrond Myklebust return sock->ops->shutdown(sock, how); 338991cf45f0STrond Myklebust } 339091cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown); 3391113c3075SR. Parameswaran 3392113c3075SR. Parameswaran /* This routine returns the IP overhead imposed by a socket i.e. 3393113c3075SR. Parameswaran * the length of the underlying IP header, depending on whether 3394113c3075SR. Parameswaran * this is an IPv4 or IPv6 socket and the length from IP options turned 339557240d00SR. Parameswaran * on at the socket. Assumes that the caller has a lock on the socket. 3396113c3075SR. Parameswaran */ 3397113c3075SR. Parameswaran u32 kernel_sock_ip_overhead(struct sock *sk) 3398113c3075SR. Parameswaran { 3399113c3075SR. Parameswaran struct inet_sock *inet; 3400113c3075SR. Parameswaran struct ip_options_rcu *opt; 3401113c3075SR. Parameswaran u32 overhead = 0; 3402113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6) 3403113c3075SR. Parameswaran struct ipv6_pinfo *np; 3404113c3075SR. Parameswaran struct ipv6_txoptions *optv6 = NULL; 3405113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */ 3406113c3075SR. Parameswaran 3407113c3075SR. Parameswaran if (!sk) 3408113c3075SR. Parameswaran return overhead; 3409113c3075SR. Parameswaran 3410113c3075SR. Parameswaran switch (sk->sk_family) { 3411113c3075SR. Parameswaran case AF_INET: 3412113c3075SR. Parameswaran inet = inet_sk(sk); 3413113c3075SR. Parameswaran overhead += sizeof(struct iphdr); 3414113c3075SR. Parameswaran opt = rcu_dereference_protected(inet->inet_opt, 3415614d79c0Sstephen hemminger sock_owned_by_user(sk)); 3416113c3075SR. Parameswaran if (opt) 3417113c3075SR. Parameswaran overhead += opt->opt.optlen; 3418113c3075SR. Parameswaran return overhead; 3419113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6) 3420113c3075SR. Parameswaran case AF_INET6: 3421113c3075SR. Parameswaran np = inet6_sk(sk); 3422113c3075SR. Parameswaran overhead += sizeof(struct ipv6hdr); 3423113c3075SR. Parameswaran if (np) 3424113c3075SR. Parameswaran optv6 = rcu_dereference_protected(np->opt, 3425614d79c0Sstephen hemminger sock_owned_by_user(sk)); 3426113c3075SR. Parameswaran if (optv6) 3427113c3075SR. Parameswaran overhead += (optv6->opt_flen + optv6->opt_nflen); 3428113c3075SR. Parameswaran return overhead; 3429113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */ 3430113c3075SR. Parameswaran default: /* Returns 0 overhead if the socket is not ipv4 or ipv6 */ 3431113c3075SR. Parameswaran return overhead; 3432113c3075SR. Parameswaran } 3433113c3075SR. Parameswaran } 3434113c3075SR. Parameswaran EXPORT_SYMBOL(kernel_sock_ip_overhead); 3435