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> 1076b96018bSArnd Bergmann #include <linux/atalk.h> 108076bb0c8SEliezer Tamir #include <net/busy_poll.h> 109f24b9be5SWillem de Bruijn #include <linux/errqueue.h> 11006021292SEliezer Tamir 111e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL 11264b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly; 11364b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly; 11406021292SEliezer Tamir #endif 1156b96018bSArnd Bergmann 1168ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to); 1178ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from); 1181da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma); 1191da177e4SLinus Torvalds 1201da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file); 121ade994f4SAl Viro static __poll_t sock_poll(struct file *file, 1221da177e4SLinus Torvalds struct poll_table_struct *wait); 12389bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 12489bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 12589bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file, 12689bbfc95SShaun Pereira unsigned int cmd, unsigned long arg); 12789bbfc95SShaun Pereira #endif 1281da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on); 1291da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page, 1301da177e4SLinus Torvalds int offset, size_t size, loff_t *ppos, int more); 1319c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos, 1329c55e01cSJens Axboe struct pipe_inode_info *pipe, size_t len, 1339c55e01cSJens Axboe unsigned int flags); 1341da177e4SLinus Torvalds 1351da177e4SLinus Torvalds /* 1361da177e4SLinus Torvalds * Socket files have a set of 'special' operations as well as the generic file ones. These don't appear 1371da177e4SLinus Torvalds * in the operation structures but are done directly via the socketcall() multiplexor. 1381da177e4SLinus Torvalds */ 1391da177e4SLinus Torvalds 140da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = { 1411da177e4SLinus Torvalds .owner = THIS_MODULE, 1421da177e4SLinus Torvalds .llseek = no_llseek, 1438ae5e030SAl Viro .read_iter = sock_read_iter, 1448ae5e030SAl Viro .write_iter = sock_write_iter, 1451da177e4SLinus Torvalds .poll = sock_poll, 1461da177e4SLinus Torvalds .unlocked_ioctl = sock_ioctl, 14789bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 14889bbfc95SShaun Pereira .compat_ioctl = compat_sock_ioctl, 14989bbfc95SShaun Pereira #endif 1501da177e4SLinus Torvalds .mmap = sock_mmap, 1511da177e4SLinus Torvalds .release = sock_close, 1521da177e4SLinus Torvalds .fasync = sock_fasync, 1535274f052SJens Axboe .sendpage = sock_sendpage, 1545274f052SJens Axboe .splice_write = generic_splice_sendpage, 1559c55e01cSJens Axboe .splice_read = sock_splice_read, 1561da177e4SLinus Torvalds }; 1571da177e4SLinus Torvalds 1581da177e4SLinus Torvalds /* 1591da177e4SLinus Torvalds * The protocol list. Each protocol is registered in here. 1601da177e4SLinus Torvalds */ 1611da177e4SLinus Torvalds 1621da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock); 163190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly; 1641da177e4SLinus Torvalds 1651da177e4SLinus Torvalds /* 16689bddce5SStephen Hemminger * Support routines. 16789bddce5SStephen Hemminger * Move socket addresses back and forth across the kernel/user 1681da177e4SLinus Torvalds * divide and look after the messy bits. 1691da177e4SLinus Torvalds */ 1701da177e4SLinus Torvalds 1711da177e4SLinus Torvalds /** 1721da177e4SLinus Torvalds * move_addr_to_kernel - copy a socket address into kernel space 1731da177e4SLinus Torvalds * @uaddr: Address in user space 1741da177e4SLinus Torvalds * @kaddr: Address in kernel space 1751da177e4SLinus Torvalds * @ulen: Length in user space 1761da177e4SLinus Torvalds * 1771da177e4SLinus Torvalds * The address is copied into kernel space. If the provided address is 1781da177e4SLinus Torvalds * too long an error code of -EINVAL is returned. If the copy gives 1791da177e4SLinus Torvalds * invalid addresses -EFAULT is returned. On a success 0 is returned. 1801da177e4SLinus Torvalds */ 1811da177e4SLinus Torvalds 18243db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr) 1831da177e4SLinus Torvalds { 184230b1839SYOSHIFUJI Hideaki if (ulen < 0 || ulen > sizeof(struct sockaddr_storage)) 1851da177e4SLinus Torvalds return -EINVAL; 1861da177e4SLinus Torvalds if (ulen == 0) 1871da177e4SLinus Torvalds return 0; 1881da177e4SLinus Torvalds if (copy_from_user(kaddr, uaddr, ulen)) 1891da177e4SLinus Torvalds return -EFAULT; 1903ec3b2fbSDavid Woodhouse return audit_sockaddr(ulen, kaddr); 1911da177e4SLinus Torvalds } 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds /** 1941da177e4SLinus Torvalds * move_addr_to_user - copy an address to user space 1951da177e4SLinus Torvalds * @kaddr: kernel space address 1961da177e4SLinus Torvalds * @klen: length of address in kernel 1971da177e4SLinus Torvalds * @uaddr: user space address 1981da177e4SLinus Torvalds * @ulen: pointer to user length field 1991da177e4SLinus Torvalds * 2001da177e4SLinus Torvalds * The value pointed to by ulen on entry is the buffer length available. 2011da177e4SLinus Torvalds * This is overwritten with the buffer space used. -EINVAL is returned 2021da177e4SLinus Torvalds * if an overlong buffer is specified or a negative buffer size. -EFAULT 2031da177e4SLinus Torvalds * is returned if either the buffer or the length field are not 2041da177e4SLinus Torvalds * accessible. 2051da177e4SLinus Torvalds * After copying the data up to the limit the user specifies, the true 2061da177e4SLinus Torvalds * length of the data is written over the length limit the user 2071da177e4SLinus Torvalds * specified. Zero is returned for a success. 2081da177e4SLinus Torvalds */ 2091da177e4SLinus Torvalds 21043db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen, 21111165f14Sstephen hemminger void __user *uaddr, int __user *ulen) 2121da177e4SLinus Torvalds { 2131da177e4SLinus Torvalds int err; 2141da177e4SLinus Torvalds int len; 2151da177e4SLinus Torvalds 21668c6beb3SHannes Frederic Sowa BUG_ON(klen > sizeof(struct sockaddr_storage)); 21789bddce5SStephen Hemminger err = get_user(len, ulen); 21889bddce5SStephen Hemminger if (err) 2191da177e4SLinus Torvalds return err; 2201da177e4SLinus Torvalds if (len > klen) 2211da177e4SLinus Torvalds len = klen; 22268c6beb3SHannes Frederic Sowa if (len < 0) 2231da177e4SLinus Torvalds return -EINVAL; 22489bddce5SStephen Hemminger if (len) { 225d6fe3945SSteve Grubb if (audit_sockaddr(klen, kaddr)) 226d6fe3945SSteve Grubb return -ENOMEM; 2271da177e4SLinus Torvalds if (copy_to_user(uaddr, kaddr, len)) 2281da177e4SLinus Torvalds return -EFAULT; 2291da177e4SLinus Torvalds } 2301da177e4SLinus Torvalds /* 2311da177e4SLinus Torvalds * "fromlen shall refer to the value before truncation.." 2321da177e4SLinus Torvalds * 1003.1g 2331da177e4SLinus Torvalds */ 2341da177e4SLinus Torvalds return __put_user(klen, ulen); 2351da177e4SLinus Torvalds } 2361da177e4SLinus Torvalds 237e18b890bSChristoph Lameter static struct kmem_cache *sock_inode_cachep __read_mostly; 2381da177e4SLinus Torvalds 2391da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb) 2401da177e4SLinus Torvalds { 2411da177e4SLinus Torvalds struct socket_alloc *ei; 242eaefd110SEric Dumazet struct socket_wq *wq; 24389bddce5SStephen Hemminger 244e94b1766SChristoph Lameter ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL); 2451da177e4SLinus Torvalds if (!ei) 2461da177e4SLinus Torvalds return NULL; 247eaefd110SEric Dumazet wq = kmalloc(sizeof(*wq), GFP_KERNEL); 248eaefd110SEric Dumazet if (!wq) { 24943815482SEric Dumazet kmem_cache_free(sock_inode_cachep, ei); 25043815482SEric Dumazet return NULL; 25143815482SEric Dumazet } 252eaefd110SEric Dumazet init_waitqueue_head(&wq->wait); 253eaefd110SEric Dumazet wq->fasync_list = NULL; 254574aab1eSNicolai Stange wq->flags = 0; 255eaefd110SEric Dumazet RCU_INIT_POINTER(ei->socket.wq, wq); 2561da177e4SLinus Torvalds 2571da177e4SLinus Torvalds ei->socket.state = SS_UNCONNECTED; 2581da177e4SLinus Torvalds ei->socket.flags = 0; 2591da177e4SLinus Torvalds ei->socket.ops = NULL; 2601da177e4SLinus Torvalds ei->socket.sk = NULL; 2611da177e4SLinus Torvalds ei->socket.file = NULL; 2621da177e4SLinus Torvalds 2631da177e4SLinus Torvalds return &ei->vfs_inode; 2641da177e4SLinus Torvalds } 2651da177e4SLinus Torvalds 2661da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode) 2671da177e4SLinus Torvalds { 26843815482SEric Dumazet struct socket_alloc *ei; 269eaefd110SEric Dumazet struct socket_wq *wq; 27043815482SEric Dumazet 27143815482SEric Dumazet ei = container_of(inode, struct socket_alloc, vfs_inode); 272eaefd110SEric Dumazet wq = rcu_dereference_protected(ei->socket.wq, 1); 27361845220SLai Jiangshan kfree_rcu(wq, rcu); 27443815482SEric Dumazet kmem_cache_free(sock_inode_cachep, ei); 2751da177e4SLinus Torvalds } 2761da177e4SLinus Torvalds 27751cc5068SAlexey Dobriyan static void init_once(void *foo) 2781da177e4SLinus Torvalds { 2791da177e4SLinus Torvalds struct socket_alloc *ei = (struct socket_alloc *)foo; 2801da177e4SLinus Torvalds 2811da177e4SLinus Torvalds inode_init_once(&ei->vfs_inode); 2821da177e4SLinus Torvalds } 2831da177e4SLinus Torvalds 2841e911632Syuan linyu static void init_inodecache(void) 2851da177e4SLinus Torvalds { 2861da177e4SLinus Torvalds sock_inode_cachep = kmem_cache_create("sock_inode_cache", 2871da177e4SLinus Torvalds sizeof(struct socket_alloc), 28889bddce5SStephen Hemminger 0, 28989bddce5SStephen Hemminger (SLAB_HWCACHE_ALIGN | 29089bddce5SStephen Hemminger SLAB_RECLAIM_ACCOUNT | 2915d097056SVladimir Davydov SLAB_MEM_SPREAD | SLAB_ACCOUNT), 29220c2df83SPaul Mundt init_once); 2931e911632Syuan linyu BUG_ON(sock_inode_cachep == NULL); 2941da177e4SLinus Torvalds } 2951da177e4SLinus Torvalds 296b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = { 2971da177e4SLinus Torvalds .alloc_inode = sock_alloc_inode, 2981da177e4SLinus Torvalds .destroy_inode = sock_destroy_inode, 2991da177e4SLinus Torvalds .statfs = simple_statfs, 3001da177e4SLinus Torvalds }; 3011da177e4SLinus Torvalds 302c23fbb6bSEric Dumazet /* 303c23fbb6bSEric Dumazet * sockfs_dname() is called from d_path(). 304c23fbb6bSEric Dumazet */ 305c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen) 306c23fbb6bSEric Dumazet { 307c23fbb6bSEric Dumazet return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]", 308c5ef6035SDavid Howells d_inode(dentry)->i_ino); 309c23fbb6bSEric Dumazet } 310c23fbb6bSEric Dumazet 3113ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = { 312c23fbb6bSEric Dumazet .d_dname = sockfs_dname, 3131da177e4SLinus Torvalds }; 3141da177e4SLinus Torvalds 315bba0bd31SAndreas Gruenbacher static int sockfs_xattr_get(const struct xattr_handler *handler, 316bba0bd31SAndreas Gruenbacher struct dentry *dentry, struct inode *inode, 317bba0bd31SAndreas Gruenbacher const char *suffix, void *value, size_t size) 318bba0bd31SAndreas Gruenbacher { 319bba0bd31SAndreas Gruenbacher if (value) { 320bba0bd31SAndreas Gruenbacher if (dentry->d_name.len + 1 > size) 321bba0bd31SAndreas Gruenbacher return -ERANGE; 322bba0bd31SAndreas Gruenbacher memcpy(value, dentry->d_name.name, dentry->d_name.len + 1); 323bba0bd31SAndreas Gruenbacher } 324bba0bd31SAndreas Gruenbacher return dentry->d_name.len + 1; 325bba0bd31SAndreas Gruenbacher } 326bba0bd31SAndreas Gruenbacher 327bba0bd31SAndreas Gruenbacher #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname" 328bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX) 329bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1) 330bba0bd31SAndreas Gruenbacher 331bba0bd31SAndreas Gruenbacher static const struct xattr_handler sockfs_xattr_handler = { 332bba0bd31SAndreas Gruenbacher .name = XATTR_NAME_SOCKPROTONAME, 333bba0bd31SAndreas Gruenbacher .get = sockfs_xattr_get, 334bba0bd31SAndreas Gruenbacher }; 335bba0bd31SAndreas Gruenbacher 3364a590153SAndreas Gruenbacher static int sockfs_security_xattr_set(const struct xattr_handler *handler, 3374a590153SAndreas Gruenbacher struct dentry *dentry, struct inode *inode, 3384a590153SAndreas Gruenbacher const char *suffix, const void *value, 3394a590153SAndreas Gruenbacher size_t size, int flags) 3404a590153SAndreas Gruenbacher { 3414a590153SAndreas Gruenbacher /* Handled by LSM. */ 3424a590153SAndreas Gruenbacher return -EAGAIN; 3434a590153SAndreas Gruenbacher } 3444a590153SAndreas Gruenbacher 3454a590153SAndreas Gruenbacher static const struct xattr_handler sockfs_security_xattr_handler = { 3464a590153SAndreas Gruenbacher .prefix = XATTR_SECURITY_PREFIX, 3474a590153SAndreas Gruenbacher .set = sockfs_security_xattr_set, 3484a590153SAndreas Gruenbacher }; 3494a590153SAndreas Gruenbacher 350bba0bd31SAndreas Gruenbacher static const struct xattr_handler *sockfs_xattr_handlers[] = { 351bba0bd31SAndreas Gruenbacher &sockfs_xattr_handler, 3524a590153SAndreas Gruenbacher &sockfs_security_xattr_handler, 353bba0bd31SAndreas Gruenbacher NULL 354bba0bd31SAndreas Gruenbacher }; 355bba0bd31SAndreas Gruenbacher 356c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type, 357c74a1cbbSAl Viro int flags, const char *dev_name, void *data) 358c74a1cbbSAl Viro { 359bba0bd31SAndreas Gruenbacher return mount_pseudo_xattr(fs_type, "socket:", &sockfs_ops, 360bba0bd31SAndreas Gruenbacher sockfs_xattr_handlers, 361c74a1cbbSAl Viro &sockfs_dentry_operations, SOCKFS_MAGIC); 362c74a1cbbSAl Viro } 363c74a1cbbSAl Viro 364c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly; 365c74a1cbbSAl Viro 366c74a1cbbSAl Viro static struct file_system_type sock_fs_type = { 367c74a1cbbSAl Viro .name = "sockfs", 368c74a1cbbSAl Viro .mount = sockfs_mount, 369c74a1cbbSAl Viro .kill_sb = kill_anon_super, 370c74a1cbbSAl Viro }; 371c74a1cbbSAl Viro 3721da177e4SLinus Torvalds /* 3731da177e4SLinus Torvalds * Obtains the first available file descriptor and sets it up for use. 3741da177e4SLinus Torvalds * 37539d8c1b6SDavid S. Miller * These functions create file structures and maps them to fd space 37639d8c1b6SDavid S. Miller * of the current process. On success it returns file descriptor 3771da177e4SLinus Torvalds * and file struct implicitly stored in sock->file. 3781da177e4SLinus Torvalds * Note that another thread may close file descriptor before we return 3791da177e4SLinus Torvalds * from this function. We use the fact that now we do not refer 3801da177e4SLinus Torvalds * to socket after mapping. If one day we will need it, this 3811da177e4SLinus Torvalds * function will increment ref. count on file by 1. 3821da177e4SLinus Torvalds * 3831da177e4SLinus Torvalds * In any case returned fd MAY BE not valid! 3841da177e4SLinus Torvalds * This race condition is unavoidable 3851da177e4SLinus Torvalds * with shared fd spaces, we cannot solve it inside kernel, 3861da177e4SLinus Torvalds * but we take care of internal coherence yet. 3871da177e4SLinus Torvalds */ 3881da177e4SLinus Torvalds 389aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) 3901da177e4SLinus Torvalds { 3917cbe66b6SAl Viro struct qstr name = { .name = "" }; 3922c48b9c4SAl Viro struct path path; 3937cbe66b6SAl Viro struct file *file; 3941da177e4SLinus Torvalds 395600e1779SMasatake YAMATO if (dname) { 396600e1779SMasatake YAMATO name.name = dname; 397600e1779SMasatake YAMATO name.len = strlen(name.name); 398600e1779SMasatake YAMATO } else if (sock->sk) { 399600e1779SMasatake YAMATO name.name = sock->sk->sk_prot_creator->name; 400600e1779SMasatake YAMATO name.len = strlen(name.name); 401600e1779SMasatake YAMATO } 4024b936885SNick Piggin path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name); 4038e1611e2SAl Viro if (unlikely(!path.dentry)) { 4048e1611e2SAl Viro sock_release(sock); 40528407630SAl Viro return ERR_PTR(-ENOMEM); 4068e1611e2SAl Viro } 4072c48b9c4SAl Viro path.mnt = mntget(sock_mnt); 40839d8c1b6SDavid S. Miller 4092c48b9c4SAl Viro d_instantiate(path.dentry, SOCK_INODE(sock)); 410cc3808f8SAl Viro 4112c48b9c4SAl Viro file = alloc_file(&path, FMODE_READ | FMODE_WRITE, 412cc3808f8SAl Viro &socket_file_ops); 413b5ffe634SViresh Kumar if (IS_ERR(file)) { 4148e1611e2SAl Viro /* drop dentry, keep inode for a bit */ 415c5ef6035SDavid Howells ihold(d_inode(path.dentry)); 4162c48b9c4SAl Viro path_put(&path); 4178e1611e2SAl Viro /* ... and now kill it properly */ 4188e1611e2SAl Viro sock_release(sock); 41939b65252SAnatol Pomozov return file; 420cc3808f8SAl Viro } 4211da177e4SLinus Torvalds 4221da177e4SLinus Torvalds sock->file = file; 42377d27200SUlrich Drepper file->f_flags = O_RDWR | (flags & O_NONBLOCK); 42407dc3f07SBenjamin LaHaise file->private_data = sock; 42528407630SAl Viro return file; 4261da177e4SLinus Torvalds } 42756b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file); 4281da177e4SLinus Torvalds 42956b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags) 43039d8c1b6SDavid S. Miller { 43139d8c1b6SDavid S. Miller struct file *newfile; 43228407630SAl Viro int fd = get_unused_fd_flags(flags); 433ce4bb04cSAl Viro if (unlikely(fd < 0)) { 434ce4bb04cSAl Viro sock_release(sock); 4351da177e4SLinus Torvalds return fd; 436ce4bb04cSAl Viro } 4371da177e4SLinus Torvalds 438aab174f0SLinus Torvalds newfile = sock_alloc_file(sock, flags, NULL); 43928407630SAl Viro if (likely(!IS_ERR(newfile))) { 4401da177e4SLinus Torvalds fd_install(fd, newfile); 4411da177e4SLinus Torvalds return fd; 4421da177e4SLinus Torvalds } 44328407630SAl Viro 44428407630SAl Viro put_unused_fd(fd); 44528407630SAl Viro return PTR_ERR(newfile); 4461da177e4SLinus Torvalds } 4471da177e4SLinus Torvalds 448406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err) 4496cb153caSBenjamin LaHaise { 4506cb153caSBenjamin LaHaise if (file->f_op == &socket_file_ops) 4516cb153caSBenjamin LaHaise return file->private_data; /* set in sock_map_fd */ 4526cb153caSBenjamin LaHaise 4536cb153caSBenjamin LaHaise *err = -ENOTSOCK; 4546cb153caSBenjamin LaHaise return NULL; 4556cb153caSBenjamin LaHaise } 456406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file); 4576cb153caSBenjamin LaHaise 4581da177e4SLinus Torvalds /** 4591da177e4SLinus Torvalds * sockfd_lookup - Go from a file number to its socket slot 4601da177e4SLinus Torvalds * @fd: file handle 4611da177e4SLinus Torvalds * @err: pointer to an error code return 4621da177e4SLinus Torvalds * 4631da177e4SLinus Torvalds * The file handle passed in is locked and the socket it is bound 464241c4667SRosen, Rami * to is returned. If an error occurs the err pointer is overwritten 4651da177e4SLinus Torvalds * with a negative errno code and NULL is returned. The function checks 4661da177e4SLinus Torvalds * for both invalid handles and passing a handle which is not a socket. 4671da177e4SLinus Torvalds * 4681da177e4SLinus Torvalds * On a success the socket object pointer is returned. 4691da177e4SLinus Torvalds */ 4701da177e4SLinus Torvalds 4711da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err) 4721da177e4SLinus Torvalds { 4731da177e4SLinus Torvalds struct file *file; 4741da177e4SLinus Torvalds struct socket *sock; 4751da177e4SLinus Torvalds 47689bddce5SStephen Hemminger file = fget(fd); 47789bddce5SStephen Hemminger if (!file) { 4781da177e4SLinus Torvalds *err = -EBADF; 4791da177e4SLinus Torvalds return NULL; 4801da177e4SLinus Torvalds } 48189bddce5SStephen Hemminger 4826cb153caSBenjamin LaHaise sock = sock_from_file(file, err); 4836cb153caSBenjamin LaHaise if (!sock) 4841da177e4SLinus Torvalds fput(file); 4856cb153caSBenjamin LaHaise return sock; 4861da177e4SLinus Torvalds } 487c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup); 4881da177e4SLinus Torvalds 4896cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) 4906cb153caSBenjamin LaHaise { 49100e188efSAl Viro struct fd f = fdget(fd); 4926cb153caSBenjamin LaHaise struct socket *sock; 4936cb153caSBenjamin LaHaise 4943672558cSHua Zhong *err = -EBADF; 49500e188efSAl Viro if (f.file) { 49600e188efSAl Viro sock = sock_from_file(f.file, err); 49700e188efSAl Viro if (likely(sock)) { 49800e188efSAl Viro *fput_needed = f.flags; 4991da177e4SLinus Torvalds return sock; 50000e188efSAl Viro } 50100e188efSAl Viro fdput(f); 5026cb153caSBenjamin LaHaise } 5036cb153caSBenjamin LaHaise return NULL; 5041da177e4SLinus Torvalds } 5051da177e4SLinus Torvalds 506600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer, 507600e1779SMasatake YAMATO size_t size) 508600e1779SMasatake YAMATO { 509600e1779SMasatake YAMATO ssize_t len; 510600e1779SMasatake YAMATO ssize_t used = 0; 511600e1779SMasatake YAMATO 512c5ef6035SDavid Howells len = security_inode_listsecurity(d_inode(dentry), buffer, size); 513600e1779SMasatake YAMATO if (len < 0) 514600e1779SMasatake YAMATO return len; 515600e1779SMasatake YAMATO used += len; 516600e1779SMasatake YAMATO if (buffer) { 517600e1779SMasatake YAMATO if (size < used) 518600e1779SMasatake YAMATO return -ERANGE; 519600e1779SMasatake YAMATO buffer += len; 520600e1779SMasatake YAMATO } 521600e1779SMasatake YAMATO 522600e1779SMasatake YAMATO len = (XATTR_NAME_SOCKPROTONAME_LEN + 1); 523600e1779SMasatake YAMATO used += len; 524600e1779SMasatake YAMATO if (buffer) { 525600e1779SMasatake YAMATO if (size < used) 526600e1779SMasatake YAMATO return -ERANGE; 527600e1779SMasatake YAMATO memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len); 528600e1779SMasatake YAMATO buffer += len; 529600e1779SMasatake YAMATO } 530600e1779SMasatake YAMATO 531600e1779SMasatake YAMATO return used; 532600e1779SMasatake YAMATO } 533600e1779SMasatake YAMATO 534dc647ec8STobias Klauser static int sockfs_setattr(struct dentry *dentry, struct iattr *iattr) 53586741ec2SLorenzo Colitti { 53686741ec2SLorenzo Colitti int err = simple_setattr(dentry, iattr); 53786741ec2SLorenzo Colitti 538e1a3a60aSEric Biggers if (!err && (iattr->ia_valid & ATTR_UID)) { 53986741ec2SLorenzo Colitti struct socket *sock = SOCKET_I(d_inode(dentry)); 54086741ec2SLorenzo Colitti 54186741ec2SLorenzo Colitti sock->sk->sk_uid = iattr->ia_uid; 54286741ec2SLorenzo Colitti } 54386741ec2SLorenzo Colitti 54486741ec2SLorenzo Colitti return err; 54586741ec2SLorenzo Colitti } 54686741ec2SLorenzo Colitti 547600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = { 548600e1779SMasatake YAMATO .listxattr = sockfs_listxattr, 54986741ec2SLorenzo Colitti .setattr = sockfs_setattr, 550600e1779SMasatake YAMATO }; 551600e1779SMasatake YAMATO 5521da177e4SLinus Torvalds /** 5531da177e4SLinus Torvalds * sock_alloc - allocate a socket 5541da177e4SLinus Torvalds * 5551da177e4SLinus Torvalds * Allocate a new inode and socket object. The two are bound together 5561da177e4SLinus Torvalds * and initialised. The socket is then returned. If we are out of inodes 5571da177e4SLinus Torvalds * NULL is returned. 5581da177e4SLinus Torvalds */ 5591da177e4SLinus Torvalds 560f4a00aacSTom Herbert struct socket *sock_alloc(void) 5611da177e4SLinus Torvalds { 5621da177e4SLinus Torvalds struct inode *inode; 5631da177e4SLinus Torvalds struct socket *sock; 5641da177e4SLinus Torvalds 565a209dfc7SEric Dumazet inode = new_inode_pseudo(sock_mnt->mnt_sb); 5661da177e4SLinus Torvalds if (!inode) 5671da177e4SLinus Torvalds return NULL; 5681da177e4SLinus Torvalds 5691da177e4SLinus Torvalds sock = SOCKET_I(inode); 5701da177e4SLinus Torvalds 57185fe4025SChristoph Hellwig inode->i_ino = get_next_ino(); 5721da177e4SLinus Torvalds inode->i_mode = S_IFSOCK | S_IRWXUGO; 5738192b0c4SDavid Howells inode->i_uid = current_fsuid(); 5748192b0c4SDavid Howells inode->i_gid = current_fsgid(); 575600e1779SMasatake YAMATO inode->i_op = &sockfs_inode_ops; 5761da177e4SLinus Torvalds 5771da177e4SLinus Torvalds return sock; 5781da177e4SLinus Torvalds } 579f4a00aacSTom Herbert EXPORT_SYMBOL(sock_alloc); 5801da177e4SLinus Torvalds 5811da177e4SLinus Torvalds /** 5821da177e4SLinus Torvalds * sock_release - close a socket 5831da177e4SLinus Torvalds * @sock: socket to close 5841da177e4SLinus Torvalds * 5851da177e4SLinus Torvalds * The socket is released from the protocol stack if it has a release 5861da177e4SLinus Torvalds * callback, and the inode is then released if the socket is bound to 5871da177e4SLinus Torvalds * an inode not a file. 5881da177e4SLinus Torvalds */ 5891da177e4SLinus Torvalds 5901da177e4SLinus Torvalds void sock_release(struct socket *sock) 5911da177e4SLinus Torvalds { 5921da177e4SLinus Torvalds if (sock->ops) { 5931da177e4SLinus Torvalds struct module *owner = sock->ops->owner; 5941da177e4SLinus Torvalds 5951da177e4SLinus Torvalds sock->ops->release(sock); 5961da177e4SLinus Torvalds sock->ops = NULL; 5971da177e4SLinus Torvalds module_put(owner); 5981da177e4SLinus Torvalds } 5991da177e4SLinus Torvalds 600eaefd110SEric Dumazet if (rcu_dereference_protected(sock->wq, 1)->fasync_list) 6013410f22eSYang Yingliang pr_err("%s: fasync list not empty!\n", __func__); 6021da177e4SLinus Torvalds 6031da177e4SLinus Torvalds if (!sock->file) { 6041da177e4SLinus Torvalds iput(SOCK_INODE(sock)); 6051da177e4SLinus Torvalds return; 6061da177e4SLinus Torvalds } 6071da177e4SLinus Torvalds sock->file = NULL; 6081da177e4SLinus Torvalds } 609c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release); 6101da177e4SLinus Torvalds 611c14ac945SSoheil Hassas Yeganeh void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags) 61220d49473SPatrick Ohly { 613140c55d4SEric Dumazet u8 flags = *tx_flags; 614140c55d4SEric Dumazet 615c14ac945SSoheil Hassas Yeganeh if (tsflags & SOF_TIMESTAMPING_TX_HARDWARE) 616140c55d4SEric Dumazet flags |= SKBTX_HW_TSTAMP; 617140c55d4SEric Dumazet 618c14ac945SSoheil Hassas Yeganeh if (tsflags & SOF_TIMESTAMPING_TX_SOFTWARE) 619140c55d4SEric Dumazet flags |= SKBTX_SW_TSTAMP; 620140c55d4SEric Dumazet 621c14ac945SSoheil Hassas Yeganeh if (tsflags & SOF_TIMESTAMPING_TX_SCHED) 622140c55d4SEric Dumazet flags |= SKBTX_SCHED_TSTAMP; 623140c55d4SEric Dumazet 624140c55d4SEric Dumazet *tx_flags = flags; 62520d49473SPatrick Ohly } 62667cc0d40SWillem de Bruijn EXPORT_SYMBOL(__sock_tx_timestamp); 62720d49473SPatrick Ohly 628d8725c86SAl Viro static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg) 6291da177e4SLinus Torvalds { 63001e97e65SAl Viro int ret = sock->ops->sendmsg(sock, msg, msg_data_left(msg)); 631d8725c86SAl Viro BUG_ON(ret == -EIOCBQUEUED); 632d8725c86SAl Viro return ret; 6331da177e4SLinus Torvalds } 6340cf00c6fSGu Zheng 635d8725c86SAl Viro int sock_sendmsg(struct socket *sock, struct msghdr *msg) 6360cf00c6fSGu Zheng { 637d8725c86SAl Viro int err = security_socket_sendmsg(sock, msg, 63801e97e65SAl Viro msg_data_left(msg)); 6391b784140SYing Xue 640d8725c86SAl Viro return err ?: sock_sendmsg_nosec(sock, msg); 6410cf00c6fSGu Zheng } 642c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg); 6431da177e4SLinus Torvalds 6441da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg, 6451da177e4SLinus Torvalds struct kvec *vec, size_t num, size_t size) 6461da177e4SLinus Torvalds { 6476aa24814SAl Viro iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size); 648d8725c86SAl Viro return sock_sendmsg(sock, msg); 6491da177e4SLinus Torvalds } 650c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg); 6511da177e4SLinus Torvalds 652306b13ebSTom Herbert int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg, 653306b13ebSTom Herbert struct kvec *vec, size_t num, size_t size) 654306b13ebSTom Herbert { 655306b13ebSTom Herbert struct socket *sock = sk->sk_socket; 656306b13ebSTom Herbert 657306b13ebSTom Herbert if (!sock->ops->sendmsg_locked) 658db5980d8SJohn Fastabend return sock_no_sendmsg_locked(sk, msg, size); 659306b13ebSTom Herbert 660306b13ebSTom Herbert iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size); 661306b13ebSTom Herbert 662306b13ebSTom Herbert return sock->ops->sendmsg_locked(sk, msg, msg_data_left(msg)); 663306b13ebSTom Herbert } 664306b13ebSTom Herbert EXPORT_SYMBOL(kernel_sendmsg_locked); 665306b13ebSTom Herbert 6668605330aSSoheil Hassas Yeganeh static bool skb_is_err_queue(const struct sk_buff *skb) 6678605330aSSoheil Hassas Yeganeh { 6688605330aSSoheil Hassas Yeganeh /* pkt_type of skbs enqueued on the error queue are set to 6698605330aSSoheil Hassas Yeganeh * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do 6708605330aSSoheil Hassas Yeganeh * in recvmsg, since skbs received on a local socket will never 6718605330aSSoheil Hassas Yeganeh * have a pkt_type of PACKET_OUTGOING. 6728605330aSSoheil Hassas Yeganeh */ 6738605330aSSoheil Hassas Yeganeh return skb->pkt_type == PACKET_OUTGOING; 6748605330aSSoheil Hassas Yeganeh } 6758605330aSSoheil Hassas Yeganeh 676b50a5c70SMiroslav Lichvar /* On transmit, software and hardware timestamps are returned independently. 677b50a5c70SMiroslav Lichvar * As the two skb clones share the hardware timestamp, which may be updated 678b50a5c70SMiroslav Lichvar * before the software timestamp is received, a hardware TX timestamp may be 679b50a5c70SMiroslav Lichvar * returned only if there is no software TX timestamp. Ignore false software 680b50a5c70SMiroslav Lichvar * timestamps, which may be made in the __sock_recv_timestamp() call when the 681b50a5c70SMiroslav Lichvar * option SO_TIMESTAMP(NS) is enabled on the socket, even when the skb has a 682b50a5c70SMiroslav Lichvar * hardware timestamp. 683b50a5c70SMiroslav Lichvar */ 684b50a5c70SMiroslav Lichvar static bool skb_is_swtx_tstamp(const struct sk_buff *skb, int false_tstamp) 685b50a5c70SMiroslav Lichvar { 686b50a5c70SMiroslav Lichvar return skb->tstamp && !false_tstamp && skb_is_err_queue(skb); 687b50a5c70SMiroslav Lichvar } 688b50a5c70SMiroslav Lichvar 689aad9c8c4SMiroslav Lichvar static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb) 690aad9c8c4SMiroslav Lichvar { 691aad9c8c4SMiroslav Lichvar struct scm_ts_pktinfo ts_pktinfo; 692aad9c8c4SMiroslav Lichvar struct net_device *orig_dev; 693aad9c8c4SMiroslav Lichvar 694aad9c8c4SMiroslav Lichvar if (!skb_mac_header_was_set(skb)) 695aad9c8c4SMiroslav Lichvar return; 696aad9c8c4SMiroslav Lichvar 697aad9c8c4SMiroslav Lichvar memset(&ts_pktinfo, 0, sizeof(ts_pktinfo)); 698aad9c8c4SMiroslav Lichvar 699aad9c8c4SMiroslav Lichvar rcu_read_lock(); 700aad9c8c4SMiroslav Lichvar orig_dev = dev_get_by_napi_id(skb_napi_id(skb)); 701aad9c8c4SMiroslav Lichvar if (orig_dev) 702aad9c8c4SMiroslav Lichvar ts_pktinfo.if_index = orig_dev->ifindex; 703aad9c8c4SMiroslav Lichvar rcu_read_unlock(); 704aad9c8c4SMiroslav Lichvar 705aad9c8c4SMiroslav Lichvar ts_pktinfo.pkt_length = skb->len - skb_mac_offset(skb); 706aad9c8c4SMiroslav Lichvar put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO, 707aad9c8c4SMiroslav Lichvar sizeof(ts_pktinfo), &ts_pktinfo); 708aad9c8c4SMiroslav Lichvar } 709aad9c8c4SMiroslav Lichvar 71092f37fd2SEric Dumazet /* 71192f37fd2SEric Dumazet * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) 71292f37fd2SEric Dumazet */ 71392f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, 71492f37fd2SEric Dumazet struct sk_buff *skb) 71592f37fd2SEric Dumazet { 71620d49473SPatrick Ohly int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); 717f24b9be5SWillem de Bruijn struct scm_timestamping tss; 718b50a5c70SMiroslav Lichvar int empty = 1, false_tstamp = 0; 71920d49473SPatrick Ohly struct skb_shared_hwtstamps *shhwtstamps = 72020d49473SPatrick Ohly skb_hwtstamps(skb); 72192f37fd2SEric Dumazet 72220d49473SPatrick Ohly /* Race occurred between timestamp enabling and packet 72320d49473SPatrick Ohly receiving. Fill in the current time for now. */ 724b50a5c70SMiroslav Lichvar if (need_software_tstamp && skb->tstamp == 0) { 72520d49473SPatrick Ohly __net_timestamp(skb); 726b50a5c70SMiroslav Lichvar false_tstamp = 1; 727b50a5c70SMiroslav Lichvar } 72820d49473SPatrick Ohly 72920d49473SPatrick Ohly if (need_software_tstamp) { 73092f37fd2SEric Dumazet if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { 73192f37fd2SEric Dumazet struct timeval tv; 73220d49473SPatrick Ohly skb_get_timestamp(skb, &tv); 73320d49473SPatrick Ohly put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, 73420d49473SPatrick Ohly sizeof(tv), &tv); 73592f37fd2SEric Dumazet } else { 736f24b9be5SWillem de Bruijn struct timespec ts; 737f24b9be5SWillem de Bruijn skb_get_timestampns(skb, &ts); 73820d49473SPatrick Ohly put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, 739f24b9be5SWillem de Bruijn sizeof(ts), &ts); 74092f37fd2SEric Dumazet } 74192f37fd2SEric Dumazet } 74292f37fd2SEric Dumazet 743f24b9be5SWillem de Bruijn memset(&tss, 0, sizeof(tss)); 744c199105dSWillem de Bruijn if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) && 745f24b9be5SWillem de Bruijn ktime_to_timespec_cond(skb->tstamp, tss.ts + 0)) 74620d49473SPatrick Ohly empty = 0; 7474d276eb6SWillem de Bruijn if (shhwtstamps && 748b9f40e21SWillem de Bruijn (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && 749b50a5c70SMiroslav Lichvar !skb_is_swtx_tstamp(skb, false_tstamp) && 750aad9c8c4SMiroslav Lichvar ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) { 75120d49473SPatrick Ohly empty = 0; 752aad9c8c4SMiroslav Lichvar if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) && 753aad9c8c4SMiroslav Lichvar !skb_is_err_queue(skb)) 754aad9c8c4SMiroslav Lichvar put_ts_pktinfo(msg, skb); 755aad9c8c4SMiroslav Lichvar } 7561c885808SFrancis Yan if (!empty) { 75720d49473SPatrick Ohly put_cmsg(msg, SOL_SOCKET, 758f24b9be5SWillem de Bruijn SCM_TIMESTAMPING, sizeof(tss), &tss); 7591c885808SFrancis Yan 7608605330aSSoheil Hassas Yeganeh if (skb_is_err_queue(skb) && skb->len && 7614ef1b286SSoheil Hassas Yeganeh SKB_EXT_ERR(skb)->opt_stats) 7621c885808SFrancis Yan put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS, 7631c885808SFrancis Yan skb->len, skb->data); 7641c885808SFrancis Yan } 76520d49473SPatrick Ohly } 7667c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp); 7677c81fd8bSArnaldo Carvalho de Melo 7686e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk, 7696e3e939fSJohannes Berg struct sk_buff *skb) 7706e3e939fSJohannes Berg { 7716e3e939fSJohannes Berg int ack; 7726e3e939fSJohannes Berg 7736e3e939fSJohannes Berg if (!sock_flag(sk, SOCK_WIFI_STATUS)) 7746e3e939fSJohannes Berg return; 7756e3e939fSJohannes Berg if (!skb->wifi_acked_valid) 7766e3e939fSJohannes Berg return; 7776e3e939fSJohannes Berg 7786e3e939fSJohannes Berg ack = skb->wifi_acked; 7796e3e939fSJohannes Berg 7806e3e939fSJohannes Berg put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack); 7816e3e939fSJohannes Berg } 7826e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status); 7836e3e939fSJohannes Berg 78411165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, 78511165f14Sstephen hemminger struct sk_buff *skb) 7863b885787SNeil Horman { 787744d5a3eSEyal Birger if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && SOCK_SKB_CB(skb)->dropcount) 7883b885787SNeil Horman put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL, 789744d5a3eSEyal Birger sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount); 7903b885787SNeil Horman } 7913b885787SNeil Horman 792767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, 7933b885787SNeil Horman struct sk_buff *skb) 7943b885787SNeil Horman { 7953b885787SNeil Horman sock_recv_timestamp(msg, sk, skb); 7963b885787SNeil Horman sock_recv_drops(msg, sk, skb); 7973b885787SNeil Horman } 798767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops); 7993b885787SNeil Horman 8001b784140SYing Xue static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg, 8011b784140SYing Xue int flags) 802a2e27255SArnaldo Carvalho de Melo { 8032da62906SAl Viro return sock->ops->recvmsg(sock, msg, msg_data_left(msg), flags); 8042da62906SAl Viro } 805a2e27255SArnaldo Carvalho de Melo 8062da62906SAl Viro int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags) 8072da62906SAl Viro { 8082da62906SAl Viro int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags); 8092da62906SAl Viro 8102da62906SAl Viro return err ?: sock_recvmsg_nosec(sock, msg, flags); 8111da177e4SLinus Torvalds } 812c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg); 8131da177e4SLinus Torvalds 814c1249c0aSMartin Lucina /** 815c1249c0aSMartin Lucina * kernel_recvmsg - Receive a message from a socket (kernel space) 816c1249c0aSMartin Lucina * @sock: The socket to receive the message from 817c1249c0aSMartin Lucina * @msg: Received message 818c1249c0aSMartin Lucina * @vec: Input s/g array for message data 819c1249c0aSMartin Lucina * @num: Size of input s/g array 820c1249c0aSMartin Lucina * @size: Number of bytes to read 821c1249c0aSMartin Lucina * @flags: Message flags (MSG_DONTWAIT, etc...) 822c1249c0aSMartin Lucina * 823c1249c0aSMartin Lucina * On return the msg structure contains the scatter/gather array passed in the 824c1249c0aSMartin Lucina * vec argument. The array is modified so that it consists of the unfilled 825c1249c0aSMartin Lucina * portion of the original array. 826c1249c0aSMartin Lucina * 827c1249c0aSMartin Lucina * The returned value is the total number of bytes received, or an error. 828c1249c0aSMartin Lucina */ 8291da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg, 83089bddce5SStephen Hemminger struct kvec *vec, size_t num, size_t size, int flags) 8311da177e4SLinus Torvalds { 8321da177e4SLinus Torvalds mm_segment_t oldfs = get_fs(); 8331da177e4SLinus Torvalds int result; 8341da177e4SLinus Torvalds 8356aa24814SAl Viro iov_iter_kvec(&msg->msg_iter, READ | ITER_KVEC, vec, num, size); 8361da177e4SLinus Torvalds set_fs(KERNEL_DS); 8372da62906SAl Viro result = sock_recvmsg(sock, msg, flags); 8381da177e4SLinus Torvalds set_fs(oldfs); 8391da177e4SLinus Torvalds return result; 8401da177e4SLinus Torvalds } 841c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg); 8421da177e4SLinus Torvalds 84320380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page, 8441da177e4SLinus Torvalds int offset, size_t size, loff_t *ppos, int more) 8451da177e4SLinus Torvalds { 8461da177e4SLinus Torvalds struct socket *sock; 8471da177e4SLinus Torvalds int flags; 8481da177e4SLinus Torvalds 849b69aee04SEric Dumazet sock = file->private_data; 8501da177e4SLinus Torvalds 85135f9c09fSEric Dumazet flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; 85235f9c09fSEric Dumazet /* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */ 85335f9c09fSEric Dumazet flags |= more; 8541da177e4SLinus Torvalds 855e6949583SLinus Torvalds return kernel_sendpage(sock, page, offset, size, flags); 8561da177e4SLinus Torvalds } 8571da177e4SLinus Torvalds 8589c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos, 8599c55e01cSJens Axboe struct pipe_inode_info *pipe, size_t len, 8609c55e01cSJens Axboe unsigned int flags) 8619c55e01cSJens Axboe { 8629c55e01cSJens Axboe struct socket *sock = file->private_data; 8639c55e01cSJens Axboe 864997b37daSRémi Denis-Courmont if (unlikely(!sock->ops->splice_read)) 865997b37daSRémi Denis-Courmont return -EINVAL; 866997b37daSRémi Denis-Courmont 8679c55e01cSJens Axboe return sock->ops->splice_read(sock, ppos, pipe, len, flags); 8689c55e01cSJens Axboe } 8699c55e01cSJens Axboe 8708ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to) 871ce1d4d3eSChristoph Hellwig { 8726d652330SAl Viro struct file *file = iocb->ki_filp; 8736d652330SAl Viro struct socket *sock = file->private_data; 8740345f931Stadeusz.struk@intel.com struct msghdr msg = {.msg_iter = *to, 8750345f931Stadeusz.struk@intel.com .msg_iocb = iocb}; 8768ae5e030SAl Viro ssize_t res; 877ce1d4d3eSChristoph Hellwig 8788ae5e030SAl Viro if (file->f_flags & O_NONBLOCK) 8798ae5e030SAl Viro msg.msg_flags = MSG_DONTWAIT; 8808ae5e030SAl Viro 8818ae5e030SAl Viro if (iocb->ki_pos != 0) 882ce1d4d3eSChristoph Hellwig return -ESPIPE; 883027445c3SBadari Pulavarty 88466ee59afSChristoph Hellwig if (!iov_iter_count(to)) /* Match SYS5 behaviour */ 885ce1d4d3eSChristoph Hellwig return 0; 886ce1d4d3eSChristoph Hellwig 8872da62906SAl Viro res = sock_recvmsg(sock, &msg, msg.msg_flags); 8888ae5e030SAl Viro *to = msg.msg_iter; 8898ae5e030SAl Viro return res; 890ce1d4d3eSChristoph Hellwig } 891ce1d4d3eSChristoph Hellwig 8928ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from) 8931da177e4SLinus Torvalds { 8946d652330SAl Viro struct file *file = iocb->ki_filp; 8956d652330SAl Viro struct socket *sock = file->private_data; 8960345f931Stadeusz.struk@intel.com struct msghdr msg = {.msg_iter = *from, 8970345f931Stadeusz.struk@intel.com .msg_iocb = iocb}; 8988ae5e030SAl Viro ssize_t res; 8991da177e4SLinus Torvalds 9008ae5e030SAl Viro if (iocb->ki_pos != 0) 901ce1d4d3eSChristoph Hellwig return -ESPIPE; 902027445c3SBadari Pulavarty 9038ae5e030SAl Viro if (file->f_flags & O_NONBLOCK) 9048ae5e030SAl Viro msg.msg_flags = MSG_DONTWAIT; 9058ae5e030SAl Viro 9066d652330SAl Viro if (sock->type == SOCK_SEQPACKET) 9076d652330SAl Viro msg.msg_flags |= MSG_EOR; 9086d652330SAl Viro 909d8725c86SAl Viro res = sock_sendmsg(sock, &msg); 9108ae5e030SAl Viro *from = msg.msg_iter; 9118ae5e030SAl Viro return res; 9121da177e4SLinus Torvalds } 9131da177e4SLinus Torvalds 9141da177e4SLinus Torvalds /* 9151da177e4SLinus Torvalds * Atomic setting of ioctl hooks to avoid race 9161da177e4SLinus Torvalds * with module unload. 9171da177e4SLinus Torvalds */ 9181da177e4SLinus Torvalds 9194a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex); 920c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg); 9211da177e4SLinus Torvalds 922881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *)) 9231da177e4SLinus Torvalds { 9244a3e2f71SArjan van de Ven mutex_lock(&br_ioctl_mutex); 9251da177e4SLinus Torvalds br_ioctl_hook = hook; 9264a3e2f71SArjan van de Ven mutex_unlock(&br_ioctl_mutex); 9271da177e4SLinus Torvalds } 9281da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set); 9291da177e4SLinus Torvalds 9304a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex); 931881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg); 9321da177e4SLinus Torvalds 933881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *)) 9341da177e4SLinus Torvalds { 9354a3e2f71SArjan van de Ven mutex_lock(&vlan_ioctl_mutex); 9361da177e4SLinus Torvalds vlan_ioctl_hook = hook; 9374a3e2f71SArjan van de Ven mutex_unlock(&vlan_ioctl_mutex); 9381da177e4SLinus Torvalds } 9391da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set); 9401da177e4SLinus Torvalds 9414a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex); 9421da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *); 9431da177e4SLinus Torvalds 9441da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *)) 9451da177e4SLinus Torvalds { 9464a3e2f71SArjan van de Ven mutex_lock(&dlci_ioctl_mutex); 9471da177e4SLinus Torvalds dlci_ioctl_hook = hook; 9484a3e2f71SArjan van de Ven mutex_unlock(&dlci_ioctl_mutex); 9491da177e4SLinus Torvalds } 9501da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set); 9511da177e4SLinus Torvalds 9526b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock, 9536b96018bSArnd Bergmann unsigned int cmd, unsigned long arg) 9546b96018bSArnd Bergmann { 9556b96018bSArnd Bergmann int err; 9566b96018bSArnd Bergmann void __user *argp = (void __user *)arg; 9576b96018bSArnd Bergmann 9586b96018bSArnd Bergmann err = sock->ops->ioctl(sock, cmd, arg); 9596b96018bSArnd Bergmann 9606b96018bSArnd Bergmann /* 9616b96018bSArnd Bergmann * If this ioctl is unknown try to hand it down 9626b96018bSArnd Bergmann * to the NIC driver. 9636b96018bSArnd Bergmann */ 96436fd633eSAl Viro if (err != -ENOIOCTLCMD) 9656b96018bSArnd Bergmann return err; 9666b96018bSArnd Bergmann 96736fd633eSAl Viro if (cmd == SIOCGIFCONF) { 96836fd633eSAl Viro struct ifconf ifc; 96936fd633eSAl Viro if (copy_from_user(&ifc, argp, sizeof(struct ifconf))) 97036fd633eSAl Viro return -EFAULT; 97136fd633eSAl Viro rtnl_lock(); 97236fd633eSAl Viro err = dev_ifconf(net, &ifc, sizeof(struct ifreq)); 97336fd633eSAl Viro rtnl_unlock(); 97436fd633eSAl Viro if (!err && copy_to_user(argp, &ifc, sizeof(struct ifconf))) 97536fd633eSAl Viro err = -EFAULT; 97644c02a2cSAl Viro } else { 97744c02a2cSAl Viro struct ifreq ifr; 97844c02a2cSAl Viro bool need_copyout; 97944c02a2cSAl Viro if (copy_from_user(&ifr, argp, sizeof(struct ifreq))) 98044c02a2cSAl Viro return -EFAULT; 98144c02a2cSAl Viro err = dev_ioctl(net, cmd, &ifr, &need_copyout); 98244c02a2cSAl Viro if (!err && need_copyout) 98344c02a2cSAl Viro if (copy_to_user(argp, &ifr, sizeof(struct ifreq))) 98444c02a2cSAl Viro return -EFAULT; 98536fd633eSAl Viro } 9866b96018bSArnd Bergmann return err; 9876b96018bSArnd Bergmann } 9886b96018bSArnd Bergmann 9891da177e4SLinus Torvalds /* 9901da177e4SLinus Torvalds * With an ioctl, arg may well be a user mode pointer, but we don't know 9911da177e4SLinus Torvalds * what to do with it - that's up to the protocol still. 9921da177e4SLinus Torvalds */ 9931da177e4SLinus Torvalds 994c62cce2cSAndrey Vagin static struct ns_common *get_net_ns(struct ns_common *ns) 995c62cce2cSAndrey Vagin { 996c62cce2cSAndrey Vagin return &get_net(container_of(ns, struct net, ns))->ns; 997c62cce2cSAndrey Vagin } 998c62cce2cSAndrey Vagin 9991da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) 10001da177e4SLinus Torvalds { 10011da177e4SLinus Torvalds struct socket *sock; 1002881d966bSEric W. Biederman struct sock *sk; 10031da177e4SLinus Torvalds void __user *argp = (void __user *)arg; 10041da177e4SLinus Torvalds int pid, err; 1005881d966bSEric W. Biederman struct net *net; 10061da177e4SLinus Torvalds 1007b69aee04SEric Dumazet sock = file->private_data; 1008881d966bSEric W. Biederman sk = sock->sk; 10093b1e0a65SYOSHIFUJI Hideaki net = sock_net(sk); 101044c02a2cSAl Viro if (unlikely(cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))) { 101144c02a2cSAl Viro struct ifreq ifr; 101244c02a2cSAl Viro bool need_copyout; 101344c02a2cSAl Viro if (copy_from_user(&ifr, argp, sizeof(struct ifreq))) 101444c02a2cSAl Viro return -EFAULT; 101544c02a2cSAl Viro err = dev_ioctl(net, cmd, &ifr, &need_copyout); 101644c02a2cSAl Viro if (!err && need_copyout) 101744c02a2cSAl Viro if (copy_to_user(argp, &ifr, sizeof(struct ifreq))) 101844c02a2cSAl Viro return -EFAULT; 10191da177e4SLinus Torvalds } else 10203d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE 10211da177e4SLinus Torvalds if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { 1022b1b0c245SAl Viro err = wext_handle_ioctl(net, cmd, argp); 10231da177e4SLinus Torvalds } else 10243d23e349SJohannes Berg #endif 10251da177e4SLinus Torvalds switch (cmd) { 10261da177e4SLinus Torvalds case FIOSETOWN: 10271da177e4SLinus Torvalds case SIOCSPGRP: 10281da177e4SLinus Torvalds err = -EFAULT; 10291da177e4SLinus Torvalds if (get_user(pid, (int __user *)argp)) 10301da177e4SLinus Torvalds break; 1031393cc3f5SJiri Slaby err = f_setown(sock->file, pid, 1); 10321da177e4SLinus Torvalds break; 10331da177e4SLinus Torvalds case FIOGETOWN: 10341da177e4SLinus Torvalds case SIOCGPGRP: 1035609d7fa9SEric W. Biederman err = put_user(f_getown(sock->file), 103689bddce5SStephen Hemminger (int __user *)argp); 10371da177e4SLinus Torvalds break; 10381da177e4SLinus Torvalds case SIOCGIFBR: 10391da177e4SLinus Torvalds case SIOCSIFBR: 10401da177e4SLinus Torvalds case SIOCBRADDBR: 10411da177e4SLinus Torvalds case SIOCBRDELBR: 10421da177e4SLinus Torvalds err = -ENOPKG; 10431da177e4SLinus Torvalds if (!br_ioctl_hook) 10441da177e4SLinus Torvalds request_module("bridge"); 10451da177e4SLinus Torvalds 10464a3e2f71SArjan van de Ven mutex_lock(&br_ioctl_mutex); 10471da177e4SLinus Torvalds if (br_ioctl_hook) 1048881d966bSEric W. Biederman err = br_ioctl_hook(net, cmd, argp); 10494a3e2f71SArjan van de Ven mutex_unlock(&br_ioctl_mutex); 10501da177e4SLinus Torvalds break; 10511da177e4SLinus Torvalds case SIOCGIFVLAN: 10521da177e4SLinus Torvalds case SIOCSIFVLAN: 10531da177e4SLinus Torvalds err = -ENOPKG; 10541da177e4SLinus Torvalds if (!vlan_ioctl_hook) 10551da177e4SLinus Torvalds request_module("8021q"); 10561da177e4SLinus Torvalds 10574a3e2f71SArjan van de Ven mutex_lock(&vlan_ioctl_mutex); 10581da177e4SLinus Torvalds if (vlan_ioctl_hook) 1059881d966bSEric W. Biederman err = vlan_ioctl_hook(net, argp); 10604a3e2f71SArjan van de Ven mutex_unlock(&vlan_ioctl_mutex); 10611da177e4SLinus Torvalds break; 10621da177e4SLinus Torvalds case SIOCADDDLCI: 10631da177e4SLinus Torvalds case SIOCDELDLCI: 10641da177e4SLinus Torvalds err = -ENOPKG; 10651da177e4SLinus Torvalds if (!dlci_ioctl_hook) 10661da177e4SLinus Torvalds request_module("dlci"); 10671da177e4SLinus Torvalds 10684a3e2f71SArjan van de Ven mutex_lock(&dlci_ioctl_mutex); 10697512cbf6SPavel Emelyanov if (dlci_ioctl_hook) 10701da177e4SLinus Torvalds err = dlci_ioctl_hook(cmd, argp); 10714a3e2f71SArjan van de Ven mutex_unlock(&dlci_ioctl_mutex); 10721da177e4SLinus Torvalds break; 1073c62cce2cSAndrey Vagin case SIOCGSKNS: 1074c62cce2cSAndrey Vagin err = -EPERM; 1075c62cce2cSAndrey Vagin if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) 1076c62cce2cSAndrey Vagin break; 1077c62cce2cSAndrey Vagin 1078c62cce2cSAndrey Vagin err = open_related_ns(&net->ns, get_net_ns); 1079c62cce2cSAndrey Vagin break; 10801da177e4SLinus Torvalds default: 10816b96018bSArnd Bergmann err = sock_do_ioctl(net, sock, cmd, arg); 10821da177e4SLinus Torvalds break; 10831da177e4SLinus Torvalds } 10841da177e4SLinus Torvalds return err; 10851da177e4SLinus Torvalds } 10861da177e4SLinus Torvalds 10871da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res) 10881da177e4SLinus Torvalds { 10891da177e4SLinus Torvalds int err; 10901da177e4SLinus Torvalds struct socket *sock = NULL; 10911da177e4SLinus Torvalds 10921da177e4SLinus Torvalds err = security_socket_create(family, type, protocol, 1); 10931da177e4SLinus Torvalds if (err) 10941da177e4SLinus Torvalds goto out; 10951da177e4SLinus Torvalds 10961da177e4SLinus Torvalds sock = sock_alloc(); 10971da177e4SLinus Torvalds if (!sock) { 10981da177e4SLinus Torvalds err = -ENOMEM; 10991da177e4SLinus Torvalds goto out; 11001da177e4SLinus Torvalds } 11011da177e4SLinus Torvalds 11021da177e4SLinus Torvalds sock->type = type; 11037420ed23SVenkat Yekkirala err = security_socket_post_create(sock, family, type, protocol, 1); 11047420ed23SVenkat Yekkirala if (err) 11057420ed23SVenkat Yekkirala goto out_release; 11067420ed23SVenkat Yekkirala 11071da177e4SLinus Torvalds out: 11081da177e4SLinus Torvalds *res = sock; 11091da177e4SLinus Torvalds return err; 11107420ed23SVenkat Yekkirala out_release: 11117420ed23SVenkat Yekkirala sock_release(sock); 11127420ed23SVenkat Yekkirala sock = NULL; 11137420ed23SVenkat Yekkirala goto out; 11141da177e4SLinus Torvalds } 1115c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite); 11161da177e4SLinus Torvalds 11171da177e4SLinus Torvalds /* No kernel lock held - perfect */ 1118ade994f4SAl Viro static __poll_t sock_poll(struct file *file, poll_table *wait) 11191da177e4SLinus Torvalds { 1120e6c8adcaSAl Viro __poll_t busy_flag = 0; 11211da177e4SLinus Torvalds struct socket *sock; 11221da177e4SLinus Torvalds 11231da177e4SLinus Torvalds /* 11241da177e4SLinus Torvalds * We can't return errors to poll, so it's either yes or no. 11251da177e4SLinus Torvalds */ 1126b69aee04SEric Dumazet sock = file->private_data; 11272d48d67fSEliezer Tamir 1128cbf55001SEliezer Tamir if (sk_can_busy_loop(sock->sk)) { 11292d48d67fSEliezer Tamir /* this socket can poll_ll so tell the system call */ 1130cbf55001SEliezer Tamir busy_flag = POLL_BUSY_LOOP; 11312d48d67fSEliezer Tamir 11322d48d67fSEliezer Tamir /* once, only if requested by syscall */ 1133cbf55001SEliezer Tamir if (wait && (wait->_key & POLL_BUSY_LOOP)) 1134cbf55001SEliezer Tamir sk_busy_loop(sock->sk, 1); 11352d48d67fSEliezer Tamir } 11362d48d67fSEliezer Tamir 1137cbf55001SEliezer Tamir return busy_flag | sock->ops->poll(file, sock, wait); 11381da177e4SLinus Torvalds } 11391da177e4SLinus Torvalds 11401da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma) 11411da177e4SLinus Torvalds { 1142b69aee04SEric Dumazet struct socket *sock = file->private_data; 11431da177e4SLinus Torvalds 11441da177e4SLinus Torvalds return sock->ops->mmap(file, sock, vma); 11451da177e4SLinus Torvalds } 11461da177e4SLinus Torvalds 114720380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp) 11481da177e4SLinus Torvalds { 11491da177e4SLinus Torvalds sock_release(SOCKET_I(inode)); 11501da177e4SLinus Torvalds return 0; 11511da177e4SLinus Torvalds } 11521da177e4SLinus Torvalds 11531da177e4SLinus Torvalds /* 11541da177e4SLinus Torvalds * Update the socket async list 11551da177e4SLinus Torvalds * 11561da177e4SLinus Torvalds * Fasync_list locking strategy. 11571da177e4SLinus Torvalds * 11581da177e4SLinus Torvalds * 1. fasync_list is modified only under process context socket lock 11591da177e4SLinus Torvalds * i.e. under semaphore. 11601da177e4SLinus Torvalds * 2. fasync_list is used under read_lock(&sk->sk_callback_lock) 1161989a2979SEric Dumazet * or under socket lock 11621da177e4SLinus Torvalds */ 11631da177e4SLinus Torvalds 11641da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on) 11651da177e4SLinus Torvalds { 1166989a2979SEric Dumazet struct socket *sock = filp->private_data; 1167989a2979SEric Dumazet struct sock *sk = sock->sk; 1168eaefd110SEric Dumazet struct socket_wq *wq; 11691da177e4SLinus Torvalds 1170989a2979SEric Dumazet if (sk == NULL) 11711da177e4SLinus Torvalds return -EINVAL; 11721da177e4SLinus Torvalds 11731da177e4SLinus Torvalds lock_sock(sk); 11741e1d04e6SHannes Frederic Sowa wq = rcu_dereference_protected(sock->wq, lockdep_sock_is_held(sk)); 1175eaefd110SEric Dumazet fasync_helper(fd, filp, on, &wq->fasync_list); 11761da177e4SLinus Torvalds 1177eaefd110SEric Dumazet if (!wq->fasync_list) 1178bcdce719SEric Dumazet sock_reset_flag(sk, SOCK_FASYNC); 1179989a2979SEric Dumazet else 1180989a2979SEric Dumazet sock_set_flag(sk, SOCK_FASYNC); 11811da177e4SLinus Torvalds 1182989a2979SEric Dumazet release_sock(sk); 11831da177e4SLinus Torvalds return 0; 11841da177e4SLinus Torvalds } 11851da177e4SLinus Torvalds 1186ceb5d58bSEric Dumazet /* This function may be called only under rcu_lock */ 11871da177e4SLinus Torvalds 1188ceb5d58bSEric Dumazet int sock_wake_async(struct socket_wq *wq, int how, int band) 11891da177e4SLinus Torvalds { 1190ceb5d58bSEric Dumazet if (!wq || !wq->fasync_list) 1191ceb5d58bSEric Dumazet return -1; 119243815482SEric Dumazet 119389bddce5SStephen Hemminger switch (how) { 11948d8ad9d7SPavel Emelyanov case SOCK_WAKE_WAITD: 1195ceb5d58bSEric Dumazet if (test_bit(SOCKWQ_ASYNC_WAITDATA, &wq->flags)) 11961da177e4SLinus Torvalds break; 11971da177e4SLinus Torvalds goto call_kill; 11988d8ad9d7SPavel Emelyanov case SOCK_WAKE_SPACE: 1199ceb5d58bSEric Dumazet if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags)) 12001da177e4SLinus Torvalds break; 12011da177e4SLinus Torvalds /* fall through */ 12028d8ad9d7SPavel Emelyanov case SOCK_WAKE_IO: 12031da177e4SLinus Torvalds call_kill: 120443815482SEric Dumazet kill_fasync(&wq->fasync_list, SIGIO, band); 12051da177e4SLinus Torvalds break; 12068d8ad9d7SPavel Emelyanov case SOCK_WAKE_URG: 120743815482SEric Dumazet kill_fasync(&wq->fasync_list, SIGURG, band); 12081da177e4SLinus Torvalds } 1209ceb5d58bSEric Dumazet 12101da177e4SLinus Torvalds return 0; 12111da177e4SLinus Torvalds } 1212c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async); 12131da177e4SLinus Torvalds 1214721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol, 121589bddce5SStephen Hemminger struct socket **res, int kern) 12161da177e4SLinus Torvalds { 12171da177e4SLinus Torvalds int err; 12181da177e4SLinus Torvalds struct socket *sock; 121955737fdaSStephen Hemminger const struct net_proto_family *pf; 12201da177e4SLinus Torvalds 12211da177e4SLinus Torvalds /* 12221da177e4SLinus Torvalds * Check protocol is in range 12231da177e4SLinus Torvalds */ 12241da177e4SLinus Torvalds if (family < 0 || family >= NPROTO) 12251da177e4SLinus Torvalds return -EAFNOSUPPORT; 12261da177e4SLinus Torvalds if (type < 0 || type >= SOCK_MAX) 12271da177e4SLinus Torvalds return -EINVAL; 12281da177e4SLinus Torvalds 12291da177e4SLinus Torvalds /* Compatibility. 12301da177e4SLinus Torvalds 12311da177e4SLinus Torvalds This uglymoron is moved from INET layer to here to avoid 12321da177e4SLinus Torvalds deadlock in module load. 12331da177e4SLinus Torvalds */ 12341da177e4SLinus Torvalds if (family == PF_INET && type == SOCK_PACKET) { 1235f3c98690Sliping.zhang pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n", 123689bddce5SStephen Hemminger current->comm); 12371da177e4SLinus Torvalds family = PF_PACKET; 12381da177e4SLinus Torvalds } 12391da177e4SLinus Torvalds 12401da177e4SLinus Torvalds err = security_socket_create(family, type, protocol, kern); 12411da177e4SLinus Torvalds if (err) 12421da177e4SLinus Torvalds return err; 12431da177e4SLinus Torvalds 124455737fdaSStephen Hemminger /* 124555737fdaSStephen Hemminger * Allocate the socket and allow the family to set things up. if 124655737fdaSStephen Hemminger * the protocol is 0, the family is instructed to select an appropriate 124755737fdaSStephen Hemminger * default. 124855737fdaSStephen Hemminger */ 124955737fdaSStephen Hemminger sock = sock_alloc(); 125055737fdaSStephen Hemminger if (!sock) { 1251e87cc472SJoe Perches net_warn_ratelimited("socket: no more sockets\n"); 125255737fdaSStephen Hemminger return -ENFILE; /* Not exactly a match, but its the 125355737fdaSStephen Hemminger closest posix thing */ 125455737fdaSStephen Hemminger } 125555737fdaSStephen Hemminger 125655737fdaSStephen Hemminger sock->type = type; 125755737fdaSStephen Hemminger 125895a5afcaSJohannes Berg #ifdef CONFIG_MODULES 12591da177e4SLinus Torvalds /* Attempt to load a protocol module if the find failed. 12601da177e4SLinus Torvalds * 12611da177e4SLinus Torvalds * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user 12621da177e4SLinus Torvalds * requested real, full-featured networking support upon configuration. 12631da177e4SLinus Torvalds * Otherwise module support will break! 12641da177e4SLinus Torvalds */ 1265190683a9SEric Dumazet if (rcu_access_pointer(net_families[family]) == NULL) 12661da177e4SLinus Torvalds request_module("net-pf-%d", family); 12671da177e4SLinus Torvalds #endif 12681da177e4SLinus Torvalds 126955737fdaSStephen Hemminger rcu_read_lock(); 127055737fdaSStephen Hemminger pf = rcu_dereference(net_families[family]); 12711da177e4SLinus Torvalds err = -EAFNOSUPPORT; 127255737fdaSStephen Hemminger if (!pf) 127355737fdaSStephen Hemminger goto out_release; 12741da177e4SLinus Torvalds 12751da177e4SLinus Torvalds /* 12761da177e4SLinus Torvalds * We will call the ->create function, that possibly is in a loadable 12771da177e4SLinus Torvalds * module, so we have to bump that loadable module refcnt first. 12781da177e4SLinus Torvalds */ 127955737fdaSStephen Hemminger if (!try_module_get(pf->owner)) 12801da177e4SLinus Torvalds goto out_release; 12811da177e4SLinus Torvalds 128255737fdaSStephen Hemminger /* Now protected by module ref count */ 128355737fdaSStephen Hemminger rcu_read_unlock(); 128455737fdaSStephen Hemminger 12853f378b68SEric Paris err = pf->create(net, sock, protocol, kern); 128655737fdaSStephen Hemminger if (err < 0) 12871da177e4SLinus Torvalds goto out_module_put; 1288a79af59eSFrank Filz 12891da177e4SLinus Torvalds /* 12901da177e4SLinus Torvalds * Now to bump the refcnt of the [loadable] module that owns this 12911da177e4SLinus Torvalds * socket at sock_release time we decrement its refcnt. 12921da177e4SLinus Torvalds */ 129355737fdaSStephen Hemminger if (!try_module_get(sock->ops->owner)) 129455737fdaSStephen Hemminger goto out_module_busy; 129555737fdaSStephen Hemminger 12961da177e4SLinus Torvalds /* 12971da177e4SLinus Torvalds * Now that we're done with the ->create function, the [loadable] 12981da177e4SLinus Torvalds * module can have its refcnt decremented 12991da177e4SLinus Torvalds */ 130055737fdaSStephen Hemminger module_put(pf->owner); 13017420ed23SVenkat Yekkirala err = security_socket_post_create(sock, family, type, protocol, kern); 13027420ed23SVenkat Yekkirala if (err) 13033b185525SHerbert Xu goto out_sock_release; 130455737fdaSStephen Hemminger *res = sock; 13051da177e4SLinus Torvalds 130655737fdaSStephen Hemminger return 0; 130755737fdaSStephen Hemminger 130855737fdaSStephen Hemminger out_module_busy: 130955737fdaSStephen Hemminger err = -EAFNOSUPPORT; 13101da177e4SLinus Torvalds out_module_put: 131155737fdaSStephen Hemminger sock->ops = NULL; 131255737fdaSStephen Hemminger module_put(pf->owner); 131355737fdaSStephen Hemminger out_sock_release: 13141da177e4SLinus Torvalds sock_release(sock); 131555737fdaSStephen Hemminger return err; 131655737fdaSStephen Hemminger 131755737fdaSStephen Hemminger out_release: 131855737fdaSStephen Hemminger rcu_read_unlock(); 131955737fdaSStephen Hemminger goto out_sock_release; 13201da177e4SLinus Torvalds } 1321721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create); 13221da177e4SLinus Torvalds 13231da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res) 13241da177e4SLinus Torvalds { 13251b8d7ae4SEric W. Biederman return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0); 13261da177e4SLinus Torvalds } 1327c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create); 13281da177e4SLinus Torvalds 1329eeb1bd5cSEric W. Biederman int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res) 13301da177e4SLinus Torvalds { 1331eeb1bd5cSEric W. Biederman return __sock_create(net, family, type, protocol, res, 1); 13321da177e4SLinus Torvalds } 1333c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern); 13341da177e4SLinus Torvalds 13359d6a15c3SDominik Brodowski int __sys_socket(int family, int type, int protocol) 13361da177e4SLinus Torvalds { 13371da177e4SLinus Torvalds int retval; 13381da177e4SLinus Torvalds struct socket *sock; 1339a677a039SUlrich Drepper int flags; 1340a677a039SUlrich Drepper 1341e38b36f3SUlrich Drepper /* Check the SOCK_* constants for consistency. */ 1342e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC); 1343e38b36f3SUlrich Drepper BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK); 1344e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK); 1345e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK); 1346e38b36f3SUlrich Drepper 1347a677a039SUlrich Drepper flags = type & ~SOCK_TYPE_MASK; 134877d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1349a677a039SUlrich Drepper return -EINVAL; 1350a677a039SUlrich Drepper type &= SOCK_TYPE_MASK; 13511da177e4SLinus Torvalds 1352aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1353aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1354aaca0bdcSUlrich Drepper 13551da177e4SLinus Torvalds retval = sock_create(family, type, protocol, &sock); 13561da177e4SLinus Torvalds if (retval < 0) 13571da177e4SLinus Torvalds return retval; 13581da177e4SLinus Torvalds 13598e1611e2SAl Viro return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); 13601da177e4SLinus Torvalds } 13611da177e4SLinus Torvalds 13629d6a15c3SDominik Brodowski SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) 13639d6a15c3SDominik Brodowski { 13649d6a15c3SDominik Brodowski return __sys_socket(family, type, protocol); 13659d6a15c3SDominik Brodowski } 13669d6a15c3SDominik Brodowski 13671da177e4SLinus Torvalds /* 13681da177e4SLinus Torvalds * Create a pair of connected sockets. 13691da177e4SLinus Torvalds */ 13701da177e4SLinus Torvalds 13713e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, 13723e0fa65fSHeiko Carstens int __user *, usockvec) 13731da177e4SLinus Torvalds { 13741da177e4SLinus Torvalds struct socket *sock1, *sock2; 13751da177e4SLinus Torvalds int fd1, fd2, err; 1376db349509SAl Viro struct file *newfile1, *newfile2; 1377a677a039SUlrich Drepper int flags; 1378a677a039SUlrich Drepper 1379a677a039SUlrich Drepper flags = type & ~SOCK_TYPE_MASK; 138077d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1381a677a039SUlrich Drepper return -EINVAL; 1382a677a039SUlrich Drepper type &= SOCK_TYPE_MASK; 13831da177e4SLinus Torvalds 1384aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1385aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1386aaca0bdcSUlrich Drepper 13871da177e4SLinus Torvalds /* 1388016a266bSAl Viro * reserve descriptors and make sure we won't fail 1389016a266bSAl Viro * to return them to userland. 1390016a266bSAl Viro */ 1391016a266bSAl Viro fd1 = get_unused_fd_flags(flags); 1392016a266bSAl Viro if (unlikely(fd1 < 0)) 1393016a266bSAl Viro return fd1; 1394016a266bSAl Viro 1395016a266bSAl Viro fd2 = get_unused_fd_flags(flags); 1396016a266bSAl Viro if (unlikely(fd2 < 0)) { 1397016a266bSAl Viro put_unused_fd(fd1); 1398016a266bSAl Viro return fd2; 1399016a266bSAl Viro } 1400016a266bSAl Viro 1401016a266bSAl Viro err = put_user(fd1, &usockvec[0]); 1402016a266bSAl Viro if (err) 1403016a266bSAl Viro goto out; 1404016a266bSAl Viro 1405016a266bSAl Viro err = put_user(fd2, &usockvec[1]); 1406016a266bSAl Viro if (err) 1407016a266bSAl Viro goto out; 1408016a266bSAl Viro 1409016a266bSAl Viro /* 14101da177e4SLinus Torvalds * Obtain the first socket and check if the underlying protocol 14111da177e4SLinus Torvalds * supports the socketpair call. 14121da177e4SLinus Torvalds */ 14131da177e4SLinus Torvalds 14141da177e4SLinus Torvalds err = sock_create(family, type, protocol, &sock1); 1415016a266bSAl Viro if (unlikely(err < 0)) 14161da177e4SLinus Torvalds goto out; 14171da177e4SLinus Torvalds 14181da177e4SLinus Torvalds err = sock_create(family, type, protocol, &sock2); 1419016a266bSAl Viro if (unlikely(err < 0)) { 1420016a266bSAl Viro sock_release(sock1); 1421016a266bSAl Viro goto out; 1422bf3c23d1SDavid S. Miller } 1423d73aa286SYann Droneaud 1424016a266bSAl Viro err = sock1->ops->socketpair(sock1, sock2); 1425016a266bSAl Viro if (unlikely(err < 0)) { 1426016a266bSAl Viro sock_release(sock2); 1427016a266bSAl Viro sock_release(sock1); 1428016a266bSAl Viro goto out; 142928407630SAl Viro } 143028407630SAl Viro 1431aab174f0SLinus Torvalds newfile1 = sock_alloc_file(sock1, flags, NULL); 1432b5ffe634SViresh Kumar if (IS_ERR(newfile1)) { 143328407630SAl Viro err = PTR_ERR(newfile1); 1434016a266bSAl Viro sock_release(sock2); 1435016a266bSAl Viro goto out; 143628407630SAl Viro } 143728407630SAl Viro 1438aab174f0SLinus Torvalds newfile2 = sock_alloc_file(sock2, flags, NULL); 143928407630SAl Viro if (IS_ERR(newfile2)) { 144028407630SAl Viro err = PTR_ERR(newfile2); 1441016a266bSAl Viro fput(newfile1); 1442016a266bSAl Viro goto out; 1443db349509SAl Viro } 1444db349509SAl Viro 1445157cf649SAl Viro audit_fd_pair(fd1, fd2); 1446d73aa286SYann Droneaud 1447db349509SAl Viro fd_install(fd1, newfile1); 1448db349509SAl Viro fd_install(fd2, newfile2); 14491da177e4SLinus Torvalds return 0; 14501da177e4SLinus Torvalds 14511da177e4SLinus Torvalds out: 1452016a266bSAl Viro put_unused_fd(fd2); 1453016a266bSAl Viro put_unused_fd(fd1); 14541da177e4SLinus Torvalds return err; 14551da177e4SLinus Torvalds } 14561da177e4SLinus Torvalds 14571da177e4SLinus Torvalds /* 14581da177e4SLinus Torvalds * Bind a name to a socket. Nothing much to do here since it's 14591da177e4SLinus Torvalds * the protocol's responsibility to handle the local address. 14601da177e4SLinus Torvalds * 14611da177e4SLinus Torvalds * We move the socket address to kernel space before we call 14621da177e4SLinus Torvalds * the protocol layer (having also checked the address is ok). 14631da177e4SLinus Torvalds */ 14641da177e4SLinus Torvalds 1465a87d35d8SDominik Brodowski int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) 14661da177e4SLinus Torvalds { 14671da177e4SLinus Torvalds struct socket *sock; 1468230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 14696cb153caSBenjamin LaHaise int err, fput_needed; 14701da177e4SLinus Torvalds 147189bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 147289bddce5SStephen Hemminger if (sock) { 147343db362dSMaciej Żenczykowski err = move_addr_to_kernel(umyaddr, addrlen, &address); 147489bddce5SStephen Hemminger if (err >= 0) { 147589bddce5SStephen Hemminger err = security_socket_bind(sock, 1476230b1839SYOSHIFUJI Hideaki (struct sockaddr *)&address, 147789bddce5SStephen Hemminger addrlen); 14786cb153caSBenjamin LaHaise if (!err) 14796cb153caSBenjamin LaHaise err = sock->ops->bind(sock, 148089bddce5SStephen Hemminger (struct sockaddr *) 1481230b1839SYOSHIFUJI Hideaki &address, addrlen); 14821da177e4SLinus Torvalds } 14836cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 14841da177e4SLinus Torvalds } 14851da177e4SLinus Torvalds return err; 14861da177e4SLinus Torvalds } 14871da177e4SLinus Torvalds 1488a87d35d8SDominik Brodowski SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen) 1489a87d35d8SDominik Brodowski { 1490a87d35d8SDominik Brodowski return __sys_bind(fd, umyaddr, addrlen); 1491a87d35d8SDominik Brodowski } 1492a87d35d8SDominik Brodowski 14931da177e4SLinus Torvalds /* 14941da177e4SLinus Torvalds * Perform a listen. Basically, we allow the protocol to do anything 14951da177e4SLinus Torvalds * necessary for a listen, and if that works, we mark the socket as 14961da177e4SLinus Torvalds * ready for listening. 14971da177e4SLinus Torvalds */ 14981da177e4SLinus Torvalds 149925e290eeSDominik Brodowski int __sys_listen(int fd, int backlog) 15001da177e4SLinus Torvalds { 15011da177e4SLinus Torvalds struct socket *sock; 15026cb153caSBenjamin LaHaise int err, fput_needed; 1503b8e1f9b5SPavel Emelyanov int somaxconn; 15041da177e4SLinus Torvalds 150589bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 150689bddce5SStephen Hemminger if (sock) { 15078efa6e93SPavel Emelyanov somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn; 150895c96174SEric Dumazet if ((unsigned int)backlog > somaxconn) 1509b8e1f9b5SPavel Emelyanov backlog = somaxconn; 15101da177e4SLinus Torvalds 15111da177e4SLinus Torvalds err = security_socket_listen(sock, backlog); 15126cb153caSBenjamin LaHaise if (!err) 15131da177e4SLinus Torvalds err = sock->ops->listen(sock, backlog); 15146cb153caSBenjamin LaHaise 15156cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 15161da177e4SLinus Torvalds } 15171da177e4SLinus Torvalds return err; 15181da177e4SLinus Torvalds } 15191da177e4SLinus Torvalds 152025e290eeSDominik Brodowski SYSCALL_DEFINE2(listen, int, fd, int, backlog) 152125e290eeSDominik Brodowski { 152225e290eeSDominik Brodowski return __sys_listen(fd, backlog); 152325e290eeSDominik Brodowski } 152425e290eeSDominik Brodowski 15251da177e4SLinus Torvalds /* 15261da177e4SLinus Torvalds * For accept, we attempt to create a new socket, set up the link 15271da177e4SLinus Torvalds * with the client, wake up the client, then return the new 15281da177e4SLinus Torvalds * connected fd. We collect the address of the connector in kernel 15291da177e4SLinus Torvalds * space and move it to user at the very end. This is unclean because 15301da177e4SLinus Torvalds * we open the socket then return an error. 15311da177e4SLinus Torvalds * 15321da177e4SLinus Torvalds * 1003.1g adds the ability to recvmsg() to query connection pending 15331da177e4SLinus Torvalds * status to recvmsg. We need to add that support in a way thats 15341da177e4SLinus Torvalds * clean when we restucture accept also. 15351da177e4SLinus Torvalds */ 15361da177e4SLinus Torvalds 15374541e805SDominik Brodowski int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, 15384541e805SDominik Brodowski int __user *upeer_addrlen, int flags) 15391da177e4SLinus Torvalds { 15401da177e4SLinus Torvalds struct socket *sock, *newsock; 154139d8c1b6SDavid S. Miller struct file *newfile; 15426cb153caSBenjamin LaHaise int err, len, newfd, fput_needed; 1543230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 15441da177e4SLinus Torvalds 154577d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1546aaca0bdcSUlrich Drepper return -EINVAL; 1547aaca0bdcSUlrich Drepper 1548aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1549aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1550aaca0bdcSUlrich Drepper 15516cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 15521da177e4SLinus Torvalds if (!sock) 15531da177e4SLinus Torvalds goto out; 15541da177e4SLinus Torvalds 15551da177e4SLinus Torvalds err = -ENFILE; 1556c6d409cfSEric Dumazet newsock = sock_alloc(); 1557c6d409cfSEric Dumazet if (!newsock) 15581da177e4SLinus Torvalds goto out_put; 15591da177e4SLinus Torvalds 15601da177e4SLinus Torvalds newsock->type = sock->type; 15611da177e4SLinus Torvalds newsock->ops = sock->ops; 15621da177e4SLinus Torvalds 15631da177e4SLinus Torvalds /* 15641da177e4SLinus Torvalds * We don't need try_module_get here, as the listening socket (sock) 15651da177e4SLinus Torvalds * has the protocol module (sock->ops->owner) held. 15661da177e4SLinus Torvalds */ 15671da177e4SLinus Torvalds __module_get(newsock->ops->owner); 15681da177e4SLinus Torvalds 156928407630SAl Viro newfd = get_unused_fd_flags(flags); 157039d8c1b6SDavid S. Miller if (unlikely(newfd < 0)) { 157139d8c1b6SDavid S. Miller err = newfd; 15729a1875e6SDavid S. Miller sock_release(newsock); 15739a1875e6SDavid S. Miller goto out_put; 157439d8c1b6SDavid S. Miller } 1575aab174f0SLinus Torvalds newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name); 1576b5ffe634SViresh Kumar if (IS_ERR(newfile)) { 157728407630SAl Viro err = PTR_ERR(newfile); 157828407630SAl Viro put_unused_fd(newfd); 157928407630SAl Viro goto out_put; 158028407630SAl Viro } 158139d8c1b6SDavid S. Miller 1582a79af59eSFrank Filz err = security_socket_accept(sock, newsock); 1583a79af59eSFrank Filz if (err) 158439d8c1b6SDavid S. Miller goto out_fd; 1585a79af59eSFrank Filz 1586cdfbabfbSDavid Howells err = sock->ops->accept(sock, newsock, sock->file->f_flags, false); 15871da177e4SLinus Torvalds if (err < 0) 158839d8c1b6SDavid S. Miller goto out_fd; 15891da177e4SLinus Torvalds 15901da177e4SLinus Torvalds if (upeer_sockaddr) { 1591230b1839SYOSHIFUJI Hideaki if (newsock->ops->getname(newsock, (struct sockaddr *)&address, 159289bddce5SStephen Hemminger &len, 2) < 0) { 15931da177e4SLinus Torvalds err = -ECONNABORTED; 159439d8c1b6SDavid S. Miller goto out_fd; 15951da177e4SLinus Torvalds } 159643db362dSMaciej Żenczykowski err = move_addr_to_user(&address, 1597230b1839SYOSHIFUJI Hideaki len, upeer_sockaddr, upeer_addrlen); 15981da177e4SLinus Torvalds if (err < 0) 159939d8c1b6SDavid S. Miller goto out_fd; 16001da177e4SLinus Torvalds } 16011da177e4SLinus Torvalds 16021da177e4SLinus Torvalds /* File flags are not inherited via accept() unlike another OSes. */ 16031da177e4SLinus Torvalds 160439d8c1b6SDavid S. Miller fd_install(newfd, newfile); 160539d8c1b6SDavid S. Miller err = newfd; 16061da177e4SLinus Torvalds 16071da177e4SLinus Torvalds out_put: 16086cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16091da177e4SLinus Torvalds out: 16101da177e4SLinus Torvalds return err; 161139d8c1b6SDavid S. Miller out_fd: 16129606a216SDavid S. Miller fput(newfile); 161339d8c1b6SDavid S. Miller put_unused_fd(newfd); 16141da177e4SLinus Torvalds goto out_put; 16151da177e4SLinus Torvalds } 16161da177e4SLinus Torvalds 16174541e805SDominik Brodowski SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, 16184541e805SDominik Brodowski int __user *, upeer_addrlen, int, flags) 16194541e805SDominik Brodowski { 16204541e805SDominik Brodowski return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, flags); 16214541e805SDominik Brodowski } 16224541e805SDominik Brodowski 162320f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr, 162420f37034SHeiko Carstens int __user *, upeer_addrlen) 1625aaca0bdcSUlrich Drepper { 16264541e805SDominik Brodowski return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0); 1627aaca0bdcSUlrich Drepper } 1628aaca0bdcSUlrich Drepper 16291da177e4SLinus Torvalds /* 16301da177e4SLinus Torvalds * Attempt to connect to a socket with the server address. The address 16311da177e4SLinus Torvalds * is in user space so we verify it is OK and move it to kernel space. 16321da177e4SLinus Torvalds * 16331da177e4SLinus Torvalds * For 1003.1g we need to add clean support for a bind to AF_UNSPEC to 16341da177e4SLinus Torvalds * break bindings 16351da177e4SLinus Torvalds * 16361da177e4SLinus Torvalds * NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and 16371da177e4SLinus Torvalds * other SEQPACKET protocols that take time to connect() as it doesn't 16381da177e4SLinus Torvalds * include the -EINPROGRESS status for such sockets. 16391da177e4SLinus Torvalds */ 16401da177e4SLinus Torvalds 16411387c2c2SDominik Brodowski int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen) 16421da177e4SLinus Torvalds { 16431da177e4SLinus Torvalds struct socket *sock; 1644230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 16456cb153caSBenjamin LaHaise int err, fput_needed; 16461da177e4SLinus Torvalds 16476cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 16481da177e4SLinus Torvalds if (!sock) 16491da177e4SLinus Torvalds goto out; 165043db362dSMaciej Żenczykowski err = move_addr_to_kernel(uservaddr, addrlen, &address); 16511da177e4SLinus Torvalds if (err < 0) 16521da177e4SLinus Torvalds goto out_put; 16531da177e4SLinus Torvalds 165489bddce5SStephen Hemminger err = 1655230b1839SYOSHIFUJI Hideaki security_socket_connect(sock, (struct sockaddr *)&address, addrlen); 16561da177e4SLinus Torvalds if (err) 16571da177e4SLinus Torvalds goto out_put; 16581da177e4SLinus Torvalds 1659230b1839SYOSHIFUJI Hideaki err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen, 16601da177e4SLinus Torvalds sock->file->f_flags); 16611da177e4SLinus Torvalds out_put: 16626cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16631da177e4SLinus Torvalds out: 16641da177e4SLinus Torvalds return err; 16651da177e4SLinus Torvalds } 16661da177e4SLinus Torvalds 16671387c2c2SDominik Brodowski SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr, 16681387c2c2SDominik Brodowski int, addrlen) 16691387c2c2SDominik Brodowski { 16701387c2c2SDominik Brodowski return __sys_connect(fd, uservaddr, addrlen); 16711387c2c2SDominik Brodowski } 16721387c2c2SDominik Brodowski 16731da177e4SLinus Torvalds /* 16741da177e4SLinus Torvalds * Get the local address ('name') of a socket object. Move the obtained 16751da177e4SLinus Torvalds * name to user space. 16761da177e4SLinus Torvalds */ 16771da177e4SLinus Torvalds 167820f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr, 167920f37034SHeiko Carstens int __user *, usockaddr_len) 16801da177e4SLinus Torvalds { 16811da177e4SLinus Torvalds struct socket *sock; 1682230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 16836cb153caSBenjamin LaHaise int len, err, fput_needed; 16841da177e4SLinus Torvalds 16856cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 16861da177e4SLinus Torvalds if (!sock) 16871da177e4SLinus Torvalds goto out; 16881da177e4SLinus Torvalds 16891da177e4SLinus Torvalds err = security_socket_getsockname(sock); 16901da177e4SLinus Torvalds if (err) 16911da177e4SLinus Torvalds goto out_put; 16921da177e4SLinus Torvalds 1693230b1839SYOSHIFUJI Hideaki err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0); 16941da177e4SLinus Torvalds if (err) 16951da177e4SLinus Torvalds goto out_put; 169643db362dSMaciej Żenczykowski err = move_addr_to_user(&address, len, usockaddr, usockaddr_len); 16971da177e4SLinus Torvalds 16981da177e4SLinus Torvalds out_put: 16996cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 17001da177e4SLinus Torvalds out: 17011da177e4SLinus Torvalds return err; 17021da177e4SLinus Torvalds } 17031da177e4SLinus Torvalds 17041da177e4SLinus Torvalds /* 17051da177e4SLinus Torvalds * Get the remote address ('name') of a socket object. Move the obtained 17061da177e4SLinus Torvalds * name to user space. 17071da177e4SLinus Torvalds */ 17081da177e4SLinus Torvalds 170920f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr, 171020f37034SHeiko Carstens int __user *, usockaddr_len) 17111da177e4SLinus Torvalds { 17121da177e4SLinus Torvalds struct socket *sock; 1713230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 17146cb153caSBenjamin LaHaise int len, err, fput_needed; 17151da177e4SLinus Torvalds 171689bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 171789bddce5SStephen Hemminger if (sock != NULL) { 17181da177e4SLinus Torvalds err = security_socket_getpeername(sock); 17191da177e4SLinus Torvalds if (err) { 17206cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 17211da177e4SLinus Torvalds return err; 17221da177e4SLinus Torvalds } 17231da177e4SLinus Torvalds 172489bddce5SStephen Hemminger err = 1725230b1839SYOSHIFUJI Hideaki sock->ops->getname(sock, (struct sockaddr *)&address, &len, 172689bddce5SStephen Hemminger 1); 17271da177e4SLinus Torvalds if (!err) 172843db362dSMaciej Żenczykowski err = move_addr_to_user(&address, len, usockaddr, 172989bddce5SStephen Hemminger usockaddr_len); 17306cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 17311da177e4SLinus Torvalds } 17321da177e4SLinus Torvalds return err; 17331da177e4SLinus Torvalds } 17341da177e4SLinus Torvalds 17351da177e4SLinus Torvalds /* 17361da177e4SLinus Torvalds * Send a datagram to a given address. We move the address into kernel 17371da177e4SLinus Torvalds * space and check the user space data area is readable before invoking 17381da177e4SLinus Torvalds * the protocol. 17391da177e4SLinus Torvalds */ 1740211b634bSDominik Brodowski int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags, 1741211b634bSDominik Brodowski struct sockaddr __user *addr, int addr_len) 17421da177e4SLinus Torvalds { 17431da177e4SLinus Torvalds struct socket *sock; 1744230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 17451da177e4SLinus Torvalds int err; 17461da177e4SLinus Torvalds struct msghdr msg; 17471da177e4SLinus Torvalds struct iovec iov; 17486cb153caSBenjamin LaHaise int fput_needed; 17491da177e4SLinus Torvalds 1750602bd0e9SAl Viro err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter); 1751602bd0e9SAl Viro if (unlikely(err)) 1752602bd0e9SAl Viro return err; 1753de0fa95cSPavel Emelyanov sock = sockfd_lookup_light(fd, &err, &fput_needed); 1754de0fa95cSPavel Emelyanov if (!sock) 17554387ff75SDavid S. Miller goto out; 17566cb153caSBenjamin LaHaise 17571da177e4SLinus Torvalds msg.msg_name = NULL; 17581da177e4SLinus Torvalds msg.msg_control = NULL; 17591da177e4SLinus Torvalds msg.msg_controllen = 0; 17601da177e4SLinus Torvalds msg.msg_namelen = 0; 17616cb153caSBenjamin LaHaise if (addr) { 176243db362dSMaciej Żenczykowski err = move_addr_to_kernel(addr, addr_len, &address); 17631da177e4SLinus Torvalds if (err < 0) 17641da177e4SLinus Torvalds goto out_put; 1765230b1839SYOSHIFUJI Hideaki msg.msg_name = (struct sockaddr *)&address; 17661da177e4SLinus Torvalds msg.msg_namelen = addr_len; 17671da177e4SLinus Torvalds } 17681da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 17691da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 17701da177e4SLinus Torvalds msg.msg_flags = flags; 1771d8725c86SAl Viro err = sock_sendmsg(sock, &msg); 17721da177e4SLinus Torvalds 17731da177e4SLinus Torvalds out_put: 1774de0fa95cSPavel Emelyanov fput_light(sock->file, fput_needed); 17754387ff75SDavid S. Miller out: 17761da177e4SLinus Torvalds return err; 17771da177e4SLinus Torvalds } 17781da177e4SLinus Torvalds 1779211b634bSDominik Brodowski SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len, 1780211b634bSDominik Brodowski unsigned int, flags, struct sockaddr __user *, addr, 1781211b634bSDominik Brodowski int, addr_len) 1782211b634bSDominik Brodowski { 1783211b634bSDominik Brodowski return __sys_sendto(fd, buff, len, flags, addr, addr_len); 1784211b634bSDominik Brodowski } 1785211b634bSDominik Brodowski 17861da177e4SLinus Torvalds /* 17871da177e4SLinus Torvalds * Send a datagram down a socket. 17881da177e4SLinus Torvalds */ 17891da177e4SLinus Torvalds 17903e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len, 179195c96174SEric Dumazet unsigned int, flags) 17921da177e4SLinus Torvalds { 1793211b634bSDominik Brodowski return __sys_sendto(fd, buff, len, flags, NULL, 0); 17941da177e4SLinus Torvalds } 17951da177e4SLinus Torvalds 17961da177e4SLinus Torvalds /* 17971da177e4SLinus Torvalds * Receive a frame from the socket and optionally record the address of the 17981da177e4SLinus Torvalds * sender. We verify the buffers are writable and if needed move the 17991da177e4SLinus Torvalds * sender address from kernel to user space. 18001da177e4SLinus Torvalds */ 18017a09e1ebSDominik Brodowski int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags, 18027a09e1ebSDominik Brodowski struct sockaddr __user *addr, int __user *addr_len) 18031da177e4SLinus Torvalds { 18041da177e4SLinus Torvalds struct socket *sock; 18051da177e4SLinus Torvalds struct iovec iov; 18061da177e4SLinus Torvalds struct msghdr msg; 1807230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 18081da177e4SLinus Torvalds int err, err2; 18096cb153caSBenjamin LaHaise int fput_needed; 18101da177e4SLinus Torvalds 1811602bd0e9SAl Viro err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter); 1812602bd0e9SAl Viro if (unlikely(err)) 1813602bd0e9SAl Viro return err; 1814de0fa95cSPavel Emelyanov sock = sockfd_lookup_light(fd, &err, &fput_needed); 18151da177e4SLinus Torvalds if (!sock) 1816de0fa95cSPavel Emelyanov goto out; 18171da177e4SLinus Torvalds 18181da177e4SLinus Torvalds msg.msg_control = NULL; 18191da177e4SLinus Torvalds msg.msg_controllen = 0; 1820f3d33426SHannes Frederic Sowa /* Save some cycles and don't copy the address if not needed */ 1821f3d33426SHannes Frederic Sowa msg.msg_name = addr ? (struct sockaddr *)&address : NULL; 1822f3d33426SHannes Frederic Sowa /* We assume all kernel code knows the size of sockaddr_storage */ 1823f3d33426SHannes Frederic Sowa msg.msg_namelen = 0; 1824130ed5d1Stadeusz.struk@intel.com msg.msg_iocb = NULL; 18259f138fa6SAlexander Potapenko msg.msg_flags = 0; 18261da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 18271da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 18282da62906SAl Viro err = sock_recvmsg(sock, &msg, flags); 18291da177e4SLinus Torvalds 183089bddce5SStephen Hemminger if (err >= 0 && addr != NULL) { 183143db362dSMaciej Żenczykowski err2 = move_addr_to_user(&address, 1832230b1839SYOSHIFUJI Hideaki msg.msg_namelen, addr, addr_len); 18331da177e4SLinus Torvalds if (err2 < 0) 18341da177e4SLinus Torvalds err = err2; 18351da177e4SLinus Torvalds } 1836de0fa95cSPavel Emelyanov 1837de0fa95cSPavel Emelyanov fput_light(sock->file, fput_needed); 18384387ff75SDavid S. Miller out: 18391da177e4SLinus Torvalds return err; 18401da177e4SLinus Torvalds } 18411da177e4SLinus Torvalds 18427a09e1ebSDominik Brodowski SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, 18437a09e1ebSDominik Brodowski unsigned int, flags, struct sockaddr __user *, addr, 18447a09e1ebSDominik Brodowski int __user *, addr_len) 18457a09e1ebSDominik Brodowski { 18467a09e1ebSDominik Brodowski return __sys_recvfrom(fd, ubuf, size, flags, addr, addr_len); 18477a09e1ebSDominik Brodowski } 18487a09e1ebSDominik Brodowski 18491da177e4SLinus Torvalds /* 18501da177e4SLinus Torvalds * Receive a datagram from a socket. 18511da177e4SLinus Torvalds */ 18521da177e4SLinus Torvalds 1853b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size, 1854b7c0ddf5SJan Glauber unsigned int, flags) 18551da177e4SLinus Torvalds { 18567a09e1ebSDominik Brodowski return __sys_recvfrom(fd, ubuf, size, flags, NULL, NULL); 18571da177e4SLinus Torvalds } 18581da177e4SLinus Torvalds 18591da177e4SLinus Torvalds /* 18601da177e4SLinus Torvalds * Set a socket option. Because we don't know the option lengths we have 18611da177e4SLinus Torvalds * to pass the user mode parameter for the protocols to sort out. 18621da177e4SLinus Torvalds */ 18631da177e4SLinus Torvalds 186420f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname, 186520f37034SHeiko Carstens char __user *, optval, int, optlen) 18661da177e4SLinus Torvalds { 18676cb153caSBenjamin LaHaise int err, fput_needed; 18681da177e4SLinus Torvalds struct socket *sock; 18691da177e4SLinus Torvalds 18701da177e4SLinus Torvalds if (optlen < 0) 18711da177e4SLinus Torvalds return -EINVAL; 18721da177e4SLinus Torvalds 187389bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 187489bddce5SStephen Hemminger if (sock != NULL) { 18751da177e4SLinus Torvalds err = security_socket_setsockopt(sock, level, optname); 18766cb153caSBenjamin LaHaise if (err) 18776cb153caSBenjamin LaHaise goto out_put; 18781da177e4SLinus Torvalds 18791da177e4SLinus Torvalds if (level == SOL_SOCKET) 188089bddce5SStephen Hemminger err = 188189bddce5SStephen Hemminger sock_setsockopt(sock, level, optname, optval, 188289bddce5SStephen Hemminger optlen); 18831da177e4SLinus Torvalds else 188489bddce5SStephen Hemminger err = 188589bddce5SStephen Hemminger sock->ops->setsockopt(sock, level, optname, optval, 188689bddce5SStephen Hemminger optlen); 18876cb153caSBenjamin LaHaise out_put: 18886cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 18891da177e4SLinus Torvalds } 18901da177e4SLinus Torvalds return err; 18911da177e4SLinus Torvalds } 18921da177e4SLinus Torvalds 18931da177e4SLinus Torvalds /* 18941da177e4SLinus Torvalds * Get a socket option. Because we don't know the option lengths we have 18951da177e4SLinus Torvalds * to pass a user mode parameter for the protocols to sort out. 18961da177e4SLinus Torvalds */ 18971da177e4SLinus Torvalds 189820f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname, 189920f37034SHeiko Carstens char __user *, optval, int __user *, optlen) 19001da177e4SLinus Torvalds { 19016cb153caSBenjamin LaHaise int err, fput_needed; 19021da177e4SLinus Torvalds struct socket *sock; 19031da177e4SLinus Torvalds 190489bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 190589bddce5SStephen Hemminger if (sock != NULL) { 19066cb153caSBenjamin LaHaise err = security_socket_getsockopt(sock, level, optname); 19076cb153caSBenjamin LaHaise if (err) 19086cb153caSBenjamin LaHaise goto out_put; 19091da177e4SLinus Torvalds 19101da177e4SLinus Torvalds if (level == SOL_SOCKET) 191189bddce5SStephen Hemminger err = 191289bddce5SStephen Hemminger sock_getsockopt(sock, level, optname, optval, 191389bddce5SStephen Hemminger optlen); 19141da177e4SLinus Torvalds else 191589bddce5SStephen Hemminger err = 191689bddce5SStephen Hemminger sock->ops->getsockopt(sock, level, optname, optval, 191789bddce5SStephen Hemminger optlen); 19186cb153caSBenjamin LaHaise out_put: 19196cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 19201da177e4SLinus Torvalds } 19211da177e4SLinus Torvalds return err; 19221da177e4SLinus Torvalds } 19231da177e4SLinus Torvalds 19241da177e4SLinus Torvalds /* 19251da177e4SLinus Torvalds * Shutdown a socket. 19261da177e4SLinus Torvalds */ 19271da177e4SLinus Torvalds 1928754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how) 19291da177e4SLinus Torvalds { 19306cb153caSBenjamin LaHaise int err, fput_needed; 19311da177e4SLinus Torvalds struct socket *sock; 19321da177e4SLinus Torvalds 193389bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 193489bddce5SStephen Hemminger if (sock != NULL) { 19351da177e4SLinus Torvalds err = security_socket_shutdown(sock, how); 19366cb153caSBenjamin LaHaise if (!err) 19371da177e4SLinus Torvalds err = sock->ops->shutdown(sock, how); 19386cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 19391da177e4SLinus Torvalds } 19401da177e4SLinus Torvalds return err; 19411da177e4SLinus Torvalds } 19421da177e4SLinus Torvalds 19431da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit 19441da177e4SLinus Torvalds * fields which are the same type (int / unsigned) on our platforms. 19451da177e4SLinus Torvalds */ 19461da177e4SLinus Torvalds #define COMPAT_MSG(msg, member) ((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member) 19471da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen) 19481da177e4SLinus Torvalds #define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags) 19491da177e4SLinus Torvalds 1950c71d8ebeSTetsuo Handa struct used_address { 1951c71d8ebeSTetsuo Handa struct sockaddr_storage name; 1952c71d8ebeSTetsuo Handa unsigned int name_len; 1953c71d8ebeSTetsuo Handa }; 1954c71d8ebeSTetsuo Handa 1955da184284SAl Viro static int copy_msghdr_from_user(struct msghdr *kmsg, 195608adb7daSAl Viro struct user_msghdr __user *umsg, 195708adb7daSAl Viro struct sockaddr __user **save_addr, 195808adb7daSAl Viro struct iovec **iov) 19591661bf36SDan Carpenter { 1960ffb07550SAl Viro struct user_msghdr msg; 196108adb7daSAl Viro ssize_t err; 196208adb7daSAl Viro 1963ffb07550SAl Viro if (copy_from_user(&msg, umsg, sizeof(*umsg))) 19641661bf36SDan Carpenter return -EFAULT; 1965dbb490b9SMatthew Leach 1966864d9664SPaolo Abeni kmsg->msg_control = (void __force *)msg.msg_control; 1967ffb07550SAl Viro kmsg->msg_controllen = msg.msg_controllen; 1968ffb07550SAl Viro kmsg->msg_flags = msg.msg_flags; 1969ffb07550SAl Viro 1970ffb07550SAl Viro kmsg->msg_namelen = msg.msg_namelen; 1971ffb07550SAl Viro if (!msg.msg_name) 19726a2a2b3aSAni Sinha kmsg->msg_namelen = 0; 19736a2a2b3aSAni Sinha 1974dbb490b9SMatthew Leach if (kmsg->msg_namelen < 0) 1975dbb490b9SMatthew Leach return -EINVAL; 1976dbb490b9SMatthew Leach 19771661bf36SDan Carpenter if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) 1978db31c55aSDan Carpenter kmsg->msg_namelen = sizeof(struct sockaddr_storage); 197908adb7daSAl Viro 198008adb7daSAl Viro if (save_addr) 1981ffb07550SAl Viro *save_addr = msg.msg_name; 198208adb7daSAl Viro 1983ffb07550SAl Viro if (msg.msg_name && kmsg->msg_namelen) { 198408adb7daSAl Viro if (!save_addr) { 1985864d9664SPaolo Abeni err = move_addr_to_kernel(msg.msg_name, 1986864d9664SPaolo Abeni kmsg->msg_namelen, 198708adb7daSAl Viro kmsg->msg_name); 198808adb7daSAl Viro if (err < 0) 198908adb7daSAl Viro return err; 199008adb7daSAl Viro } 199108adb7daSAl Viro } else { 199208adb7daSAl Viro kmsg->msg_name = NULL; 199308adb7daSAl Viro kmsg->msg_namelen = 0; 199408adb7daSAl Viro } 199508adb7daSAl Viro 1996ffb07550SAl Viro if (msg.msg_iovlen > UIO_MAXIOV) 199708adb7daSAl Viro return -EMSGSIZE; 199808adb7daSAl Viro 19990345f931Stadeusz.struk@intel.com kmsg->msg_iocb = NULL; 20000345f931Stadeusz.struk@intel.com 2001ffb07550SAl Viro return import_iovec(save_addr ? READ : WRITE, 2002ffb07550SAl Viro msg.msg_iov, msg.msg_iovlen, 2003da184284SAl Viro UIO_FASTIOV, iov, &kmsg->msg_iter); 20041661bf36SDan Carpenter } 20051661bf36SDan Carpenter 2006666547ffSAl Viro static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg, 200795c96174SEric Dumazet struct msghdr *msg_sys, unsigned int flags, 200828a94d8fSTom Herbert struct used_address *used_address, 200928a94d8fSTom Herbert unsigned int allowed_msghdr_flags) 20101da177e4SLinus Torvalds { 201189bddce5SStephen Hemminger struct compat_msghdr __user *msg_compat = 201289bddce5SStephen Hemminger (struct compat_msghdr __user *)msg; 2013230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 20141da177e4SLinus Torvalds struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; 2015b9d717a7SAlex Williamson unsigned char ctl[sizeof(struct cmsghdr) + 20] 2016846cc123SAmit Kushwaha __aligned(sizeof(__kernel_size_t)); 2017b9d717a7SAlex Williamson /* 20 is size of ipv6_pktinfo */ 20181da177e4SLinus Torvalds unsigned char *ctl_buf = ctl; 2019d8725c86SAl Viro int ctl_len; 202008adb7daSAl Viro ssize_t err; 20211da177e4SLinus Torvalds 202208adb7daSAl Viro msg_sys->msg_name = &address; 20231da177e4SLinus Torvalds 202408449320SAl Viro if (MSG_CMSG_COMPAT & flags) 202508adb7daSAl Viro err = get_compat_msghdr(msg_sys, msg_compat, NULL, &iov); 202608449320SAl Viro else 202708adb7daSAl Viro err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov); 20281da177e4SLinus Torvalds if (err < 0) 2029da184284SAl Viro return err; 20301da177e4SLinus Torvalds 20311da177e4SLinus Torvalds err = -ENOBUFS; 20321da177e4SLinus Torvalds 2033228e548eSAnton Blanchard if (msg_sys->msg_controllen > INT_MAX) 20341da177e4SLinus Torvalds goto out_freeiov; 203528a94d8fSTom Herbert flags |= (msg_sys->msg_flags & allowed_msghdr_flags); 2036228e548eSAnton Blanchard ctl_len = msg_sys->msg_controllen; 20371da177e4SLinus Torvalds if ((MSG_CMSG_COMPAT & flags) && ctl_len) { 203889bddce5SStephen Hemminger err = 2039228e548eSAnton Blanchard cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl, 204089bddce5SStephen Hemminger sizeof(ctl)); 20411da177e4SLinus Torvalds if (err) 20421da177e4SLinus Torvalds goto out_freeiov; 2043228e548eSAnton Blanchard ctl_buf = msg_sys->msg_control; 2044228e548eSAnton Blanchard ctl_len = msg_sys->msg_controllen; 20451da177e4SLinus Torvalds } else if (ctl_len) { 2046ac4340fcSDavid S. Miller BUILD_BUG_ON(sizeof(struct cmsghdr) != 2047ac4340fcSDavid S. Miller CMSG_ALIGN(sizeof(struct cmsghdr))); 204889bddce5SStephen Hemminger if (ctl_len > sizeof(ctl)) { 20491da177e4SLinus Torvalds ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); 20501da177e4SLinus Torvalds if (ctl_buf == NULL) 20511da177e4SLinus Torvalds goto out_freeiov; 20521da177e4SLinus Torvalds } 20531da177e4SLinus Torvalds err = -EFAULT; 20541da177e4SLinus Torvalds /* 2055228e548eSAnton Blanchard * Careful! Before this, msg_sys->msg_control contains a user pointer. 20561da177e4SLinus Torvalds * Afterwards, it will be a kernel pointer. Thus the compiler-assisted 20571da177e4SLinus Torvalds * checking falls down on this. 20581da177e4SLinus Torvalds */ 2059fb8621bbSNamhyung Kim if (copy_from_user(ctl_buf, 2060228e548eSAnton Blanchard (void __user __force *)msg_sys->msg_control, 206189bddce5SStephen Hemminger ctl_len)) 20621da177e4SLinus Torvalds goto out_freectl; 2063228e548eSAnton Blanchard msg_sys->msg_control = ctl_buf; 20641da177e4SLinus Torvalds } 2065228e548eSAnton Blanchard msg_sys->msg_flags = flags; 20661da177e4SLinus Torvalds 20671da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 2068228e548eSAnton Blanchard msg_sys->msg_flags |= MSG_DONTWAIT; 2069c71d8ebeSTetsuo Handa /* 2070c71d8ebeSTetsuo Handa * If this is sendmmsg() and current destination address is same as 2071c71d8ebeSTetsuo Handa * previously succeeded address, omit asking LSM's decision. 2072c71d8ebeSTetsuo Handa * used_address->name_len is initialized to UINT_MAX so that the first 2073c71d8ebeSTetsuo Handa * destination address never matches. 2074c71d8ebeSTetsuo Handa */ 2075bc909d9dSMathieu Desnoyers if (used_address && msg_sys->msg_name && 2076bc909d9dSMathieu Desnoyers used_address->name_len == msg_sys->msg_namelen && 2077bc909d9dSMathieu Desnoyers !memcmp(&used_address->name, msg_sys->msg_name, 2078c71d8ebeSTetsuo Handa used_address->name_len)) { 2079d8725c86SAl Viro err = sock_sendmsg_nosec(sock, msg_sys); 2080c71d8ebeSTetsuo Handa goto out_freectl; 2081c71d8ebeSTetsuo Handa } 2082d8725c86SAl Viro err = sock_sendmsg(sock, msg_sys); 2083c71d8ebeSTetsuo Handa /* 2084c71d8ebeSTetsuo Handa * If this is sendmmsg() and sending to current destination address was 2085c71d8ebeSTetsuo Handa * successful, remember it. 2086c71d8ebeSTetsuo Handa */ 2087c71d8ebeSTetsuo Handa if (used_address && err >= 0) { 2088c71d8ebeSTetsuo Handa used_address->name_len = msg_sys->msg_namelen; 2089bc909d9dSMathieu Desnoyers if (msg_sys->msg_name) 2090bc909d9dSMathieu Desnoyers memcpy(&used_address->name, msg_sys->msg_name, 2091c71d8ebeSTetsuo Handa used_address->name_len); 2092c71d8ebeSTetsuo Handa } 20931da177e4SLinus Torvalds 20941da177e4SLinus Torvalds out_freectl: 20951da177e4SLinus Torvalds if (ctl_buf != ctl) 20961da177e4SLinus Torvalds sock_kfree_s(sock->sk, ctl_buf, ctl_len); 20971da177e4SLinus Torvalds out_freeiov: 2098a74e9106SEric Dumazet kfree(iov); 2099228e548eSAnton Blanchard return err; 2100228e548eSAnton Blanchard } 2101228e548eSAnton Blanchard 2102228e548eSAnton Blanchard /* 2103228e548eSAnton Blanchard * BSD sendmsg interface 2104228e548eSAnton Blanchard */ 2105228e548eSAnton Blanchard 2106666547ffSAl Viro long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags) 2107228e548eSAnton Blanchard { 2108228e548eSAnton Blanchard int fput_needed, err; 2109228e548eSAnton Blanchard struct msghdr msg_sys; 21101be374a0SAndy Lutomirski struct socket *sock; 2111228e548eSAnton Blanchard 21121be374a0SAndy Lutomirski sock = sockfd_lookup_light(fd, &err, &fput_needed); 2113228e548eSAnton Blanchard if (!sock) 2114228e548eSAnton Blanchard goto out; 2115228e548eSAnton Blanchard 211628a94d8fSTom Herbert err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0); 2117228e548eSAnton Blanchard 21186cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 21191da177e4SLinus Torvalds out: 21201da177e4SLinus Torvalds return err; 21211da177e4SLinus Torvalds } 21221da177e4SLinus Torvalds 2123666547ffSAl Viro SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags) 2124a7526eb5SAndy Lutomirski { 2125a7526eb5SAndy Lutomirski if (flags & MSG_CMSG_COMPAT) 2126a7526eb5SAndy Lutomirski return -EINVAL; 2127a7526eb5SAndy Lutomirski return __sys_sendmsg(fd, msg, flags); 2128a7526eb5SAndy Lutomirski } 2129a7526eb5SAndy Lutomirski 2130228e548eSAnton Blanchard /* 2131228e548eSAnton Blanchard * Linux sendmmsg interface 2132228e548eSAnton Blanchard */ 2133228e548eSAnton Blanchard 2134228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, 2135228e548eSAnton Blanchard unsigned int flags) 2136228e548eSAnton Blanchard { 2137228e548eSAnton Blanchard int fput_needed, err, datagrams; 2138228e548eSAnton Blanchard struct socket *sock; 2139228e548eSAnton Blanchard struct mmsghdr __user *entry; 2140228e548eSAnton Blanchard struct compat_mmsghdr __user *compat_entry; 2141228e548eSAnton Blanchard struct msghdr msg_sys; 2142c71d8ebeSTetsuo Handa struct used_address used_address; 2143f092276dSTom Herbert unsigned int oflags = flags; 2144228e548eSAnton Blanchard 214598382f41SAnton Blanchard if (vlen > UIO_MAXIOV) 214698382f41SAnton Blanchard vlen = UIO_MAXIOV; 2147228e548eSAnton Blanchard 2148228e548eSAnton Blanchard datagrams = 0; 2149228e548eSAnton Blanchard 2150228e548eSAnton Blanchard sock = sockfd_lookup_light(fd, &err, &fput_needed); 2151228e548eSAnton Blanchard if (!sock) 2152228e548eSAnton Blanchard return err; 2153228e548eSAnton Blanchard 2154c71d8ebeSTetsuo Handa used_address.name_len = UINT_MAX; 2155228e548eSAnton Blanchard entry = mmsg; 2156228e548eSAnton Blanchard compat_entry = (struct compat_mmsghdr __user *)mmsg; 2157728ffb86SAnton Blanchard err = 0; 2158f092276dSTom Herbert flags |= MSG_BATCH; 2159228e548eSAnton Blanchard 2160228e548eSAnton Blanchard while (datagrams < vlen) { 2161f092276dSTom Herbert if (datagrams == vlen - 1) 2162f092276dSTom Herbert flags = oflags; 2163f092276dSTom Herbert 2164228e548eSAnton Blanchard if (MSG_CMSG_COMPAT & flags) { 2165666547ffSAl Viro err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry, 216628a94d8fSTom Herbert &msg_sys, flags, &used_address, MSG_EOR); 2167228e548eSAnton Blanchard if (err < 0) 2168228e548eSAnton Blanchard break; 2169228e548eSAnton Blanchard err = __put_user(err, &compat_entry->msg_len); 2170228e548eSAnton Blanchard ++compat_entry; 2171228e548eSAnton Blanchard } else { 2172a7526eb5SAndy Lutomirski err = ___sys_sendmsg(sock, 2173666547ffSAl Viro (struct user_msghdr __user *)entry, 217428a94d8fSTom Herbert &msg_sys, flags, &used_address, MSG_EOR); 2175228e548eSAnton Blanchard if (err < 0) 2176228e548eSAnton Blanchard break; 2177228e548eSAnton Blanchard err = put_user(err, &entry->msg_len); 2178228e548eSAnton Blanchard ++entry; 2179228e548eSAnton Blanchard } 2180228e548eSAnton Blanchard 2181228e548eSAnton Blanchard if (err) 2182228e548eSAnton Blanchard break; 2183228e548eSAnton Blanchard ++datagrams; 21843023898bSSoheil Hassas Yeganeh if (msg_data_left(&msg_sys)) 21853023898bSSoheil Hassas Yeganeh break; 2186a78cb84cSEric Dumazet cond_resched(); 2187228e548eSAnton Blanchard } 2188228e548eSAnton Blanchard 2189228e548eSAnton Blanchard fput_light(sock->file, fput_needed); 2190228e548eSAnton Blanchard 2191728ffb86SAnton Blanchard /* We only return an error if no datagrams were able to be sent */ 2192728ffb86SAnton Blanchard if (datagrams != 0) 2193228e548eSAnton Blanchard return datagrams; 2194228e548eSAnton Blanchard 2195228e548eSAnton Blanchard return err; 2196228e548eSAnton Blanchard } 2197228e548eSAnton Blanchard 2198228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, 2199228e548eSAnton Blanchard unsigned int, vlen, unsigned int, flags) 2200228e548eSAnton Blanchard { 22011be374a0SAndy Lutomirski if (flags & MSG_CMSG_COMPAT) 22021be374a0SAndy Lutomirski return -EINVAL; 2203228e548eSAnton Blanchard return __sys_sendmmsg(fd, mmsg, vlen, flags); 2204228e548eSAnton Blanchard } 2205228e548eSAnton Blanchard 2206666547ffSAl Viro static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg, 220795c96174SEric Dumazet struct msghdr *msg_sys, unsigned int flags, int nosec) 22081da177e4SLinus Torvalds { 220989bddce5SStephen Hemminger struct compat_msghdr __user *msg_compat = 221089bddce5SStephen Hemminger (struct compat_msghdr __user *)msg; 22111da177e4SLinus Torvalds struct iovec iovstack[UIO_FASTIOV]; 22121da177e4SLinus Torvalds struct iovec *iov = iovstack; 22131da177e4SLinus Torvalds unsigned long cmsg_ptr; 22142da62906SAl Viro int len; 221508adb7daSAl Viro ssize_t err; 22161da177e4SLinus Torvalds 22171da177e4SLinus Torvalds /* kernel mode address */ 2218230b1839SYOSHIFUJI Hideaki struct sockaddr_storage addr; 22191da177e4SLinus Torvalds 22201da177e4SLinus Torvalds /* user mode address pointers */ 22211da177e4SLinus Torvalds struct sockaddr __user *uaddr; 222208adb7daSAl Viro int __user *uaddr_len = COMPAT_NAMELEN(msg); 22231da177e4SLinus Torvalds 222408adb7daSAl Viro msg_sys->msg_name = &addr; 22251da177e4SLinus Torvalds 2226f3d33426SHannes Frederic Sowa if (MSG_CMSG_COMPAT & flags) 222708adb7daSAl Viro err = get_compat_msghdr(msg_sys, msg_compat, &uaddr, &iov); 2228f3d33426SHannes Frederic Sowa else 222908adb7daSAl Viro err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov); 22301da177e4SLinus Torvalds if (err < 0) 2231da184284SAl Viro return err; 22321da177e4SLinus Torvalds 2233a2e27255SArnaldo Carvalho de Melo cmsg_ptr = (unsigned long)msg_sys->msg_control; 2234a2e27255SArnaldo Carvalho de Melo msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); 22351da177e4SLinus Torvalds 2236f3d33426SHannes Frederic Sowa /* We assume all kernel code knows the size of sockaddr_storage */ 2237f3d33426SHannes Frederic Sowa msg_sys->msg_namelen = 0; 2238f3d33426SHannes Frederic Sowa 22391da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 22401da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 22412da62906SAl Viro err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, flags); 22421da177e4SLinus Torvalds if (err < 0) 22431da177e4SLinus Torvalds goto out_freeiov; 22441da177e4SLinus Torvalds len = err; 22451da177e4SLinus Torvalds 22461da177e4SLinus Torvalds if (uaddr != NULL) { 224743db362dSMaciej Żenczykowski err = move_addr_to_user(&addr, 2248a2e27255SArnaldo Carvalho de Melo msg_sys->msg_namelen, uaddr, 224989bddce5SStephen Hemminger uaddr_len); 22501da177e4SLinus Torvalds if (err < 0) 22511da177e4SLinus Torvalds goto out_freeiov; 22521da177e4SLinus Torvalds } 2253a2e27255SArnaldo Carvalho de Melo err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT), 225437f7f421SDavid S. Miller COMPAT_FLAGS(msg)); 22551da177e4SLinus Torvalds if (err) 22561da177e4SLinus Torvalds goto out_freeiov; 22571da177e4SLinus Torvalds if (MSG_CMSG_COMPAT & flags) 2258a2e27255SArnaldo Carvalho de Melo err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr, 22591da177e4SLinus Torvalds &msg_compat->msg_controllen); 22601da177e4SLinus Torvalds else 2261a2e27255SArnaldo Carvalho de Melo err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr, 22621da177e4SLinus Torvalds &msg->msg_controllen); 22631da177e4SLinus Torvalds if (err) 22641da177e4SLinus Torvalds goto out_freeiov; 22651da177e4SLinus Torvalds err = len; 22661da177e4SLinus Torvalds 22671da177e4SLinus Torvalds out_freeiov: 2268a74e9106SEric Dumazet kfree(iov); 2269a2e27255SArnaldo Carvalho de Melo return err; 2270a2e27255SArnaldo Carvalho de Melo } 2271a2e27255SArnaldo Carvalho de Melo 2272a2e27255SArnaldo Carvalho de Melo /* 2273a2e27255SArnaldo Carvalho de Melo * BSD recvmsg interface 2274a2e27255SArnaldo Carvalho de Melo */ 2275a2e27255SArnaldo Carvalho de Melo 2276666547ffSAl Viro long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags) 2277a2e27255SArnaldo Carvalho de Melo { 2278a2e27255SArnaldo Carvalho de Melo int fput_needed, err; 2279a2e27255SArnaldo Carvalho de Melo struct msghdr msg_sys; 22801be374a0SAndy Lutomirski struct socket *sock; 2281a2e27255SArnaldo Carvalho de Melo 22821be374a0SAndy Lutomirski sock = sockfd_lookup_light(fd, &err, &fput_needed); 2283a2e27255SArnaldo Carvalho de Melo if (!sock) 2284a2e27255SArnaldo Carvalho de Melo goto out; 2285a2e27255SArnaldo Carvalho de Melo 2286a7526eb5SAndy Lutomirski err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0); 2287a2e27255SArnaldo Carvalho de Melo 22886cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 22891da177e4SLinus Torvalds out: 22901da177e4SLinus Torvalds return err; 22911da177e4SLinus Torvalds } 22921da177e4SLinus Torvalds 2293666547ffSAl Viro SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg, 2294a7526eb5SAndy Lutomirski unsigned int, flags) 2295a7526eb5SAndy Lutomirski { 2296a7526eb5SAndy Lutomirski if (flags & MSG_CMSG_COMPAT) 2297a7526eb5SAndy Lutomirski return -EINVAL; 2298a7526eb5SAndy Lutomirski return __sys_recvmsg(fd, msg, flags); 2299a7526eb5SAndy Lutomirski } 2300a7526eb5SAndy Lutomirski 2301a2e27255SArnaldo Carvalho de Melo /* 2302a2e27255SArnaldo Carvalho de Melo * Linux recvmmsg interface 2303a2e27255SArnaldo Carvalho de Melo */ 23041da177e4SLinus Torvalds 2305a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, 2306a2e27255SArnaldo Carvalho de Melo unsigned int flags, struct timespec *timeout) 2307a2e27255SArnaldo Carvalho de Melo { 2308a2e27255SArnaldo Carvalho de Melo int fput_needed, err, datagrams; 2309a2e27255SArnaldo Carvalho de Melo struct socket *sock; 2310a2e27255SArnaldo Carvalho de Melo struct mmsghdr __user *entry; 2311d7256d0eSJean-Mickael Guerin struct compat_mmsghdr __user *compat_entry; 2312a2e27255SArnaldo Carvalho de Melo struct msghdr msg_sys; 2313766b9f92SDeepa Dinamani struct timespec64 end_time; 2314766b9f92SDeepa Dinamani struct timespec64 timeout64; 2315a2e27255SArnaldo Carvalho de Melo 2316a2e27255SArnaldo Carvalho de Melo if (timeout && 2317a2e27255SArnaldo Carvalho de Melo poll_select_set_timeout(&end_time, timeout->tv_sec, 2318a2e27255SArnaldo Carvalho de Melo timeout->tv_nsec)) 2319a2e27255SArnaldo Carvalho de Melo return -EINVAL; 2320a2e27255SArnaldo Carvalho de Melo 2321a2e27255SArnaldo Carvalho de Melo datagrams = 0; 2322a2e27255SArnaldo Carvalho de Melo 2323a2e27255SArnaldo Carvalho de Melo sock = sockfd_lookup_light(fd, &err, &fput_needed); 2324a2e27255SArnaldo Carvalho de Melo if (!sock) 2325a2e27255SArnaldo Carvalho de Melo return err; 2326a2e27255SArnaldo Carvalho de Melo 2327a2e27255SArnaldo Carvalho de Melo err = sock_error(sock->sk); 2328e623a9e9SMaxime Jayat if (err) { 2329e623a9e9SMaxime Jayat datagrams = err; 2330a2e27255SArnaldo Carvalho de Melo goto out_put; 2331e623a9e9SMaxime Jayat } 2332a2e27255SArnaldo Carvalho de Melo 2333a2e27255SArnaldo Carvalho de Melo entry = mmsg; 2334d7256d0eSJean-Mickael Guerin compat_entry = (struct compat_mmsghdr __user *)mmsg; 2335a2e27255SArnaldo Carvalho de Melo 2336a2e27255SArnaldo Carvalho de Melo while (datagrams < vlen) { 2337a2e27255SArnaldo Carvalho de Melo /* 2338a2e27255SArnaldo Carvalho de Melo * No need to ask LSM for more than the first datagram. 2339a2e27255SArnaldo Carvalho de Melo */ 2340d7256d0eSJean-Mickael Guerin if (MSG_CMSG_COMPAT & flags) { 2341666547ffSAl Viro err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry, 2342b9eb8b87SAnton Blanchard &msg_sys, flags & ~MSG_WAITFORONE, 2343b9eb8b87SAnton Blanchard datagrams); 2344d7256d0eSJean-Mickael Guerin if (err < 0) 2345d7256d0eSJean-Mickael Guerin break; 2346d7256d0eSJean-Mickael Guerin err = __put_user(err, &compat_entry->msg_len); 2347d7256d0eSJean-Mickael Guerin ++compat_entry; 2348d7256d0eSJean-Mickael Guerin } else { 2349a7526eb5SAndy Lutomirski err = ___sys_recvmsg(sock, 2350666547ffSAl Viro (struct user_msghdr __user *)entry, 2351b9eb8b87SAnton Blanchard &msg_sys, flags & ~MSG_WAITFORONE, 2352b9eb8b87SAnton Blanchard datagrams); 2353a2e27255SArnaldo Carvalho de Melo if (err < 0) 2354a2e27255SArnaldo Carvalho de Melo break; 2355a2e27255SArnaldo Carvalho de Melo err = put_user(err, &entry->msg_len); 2356d7256d0eSJean-Mickael Guerin ++entry; 2357d7256d0eSJean-Mickael Guerin } 2358d7256d0eSJean-Mickael Guerin 2359a2e27255SArnaldo Carvalho de Melo if (err) 2360a2e27255SArnaldo Carvalho de Melo break; 2361a2e27255SArnaldo Carvalho de Melo ++datagrams; 2362a2e27255SArnaldo Carvalho de Melo 236371c5c159SBrandon L Black /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */ 236471c5c159SBrandon L Black if (flags & MSG_WAITFORONE) 236571c5c159SBrandon L Black flags |= MSG_DONTWAIT; 236671c5c159SBrandon L Black 2367a2e27255SArnaldo Carvalho de Melo if (timeout) { 2368766b9f92SDeepa Dinamani ktime_get_ts64(&timeout64); 2369766b9f92SDeepa Dinamani *timeout = timespec64_to_timespec( 2370766b9f92SDeepa Dinamani timespec64_sub(end_time, timeout64)); 2371a2e27255SArnaldo Carvalho de Melo if (timeout->tv_sec < 0) { 2372a2e27255SArnaldo Carvalho de Melo timeout->tv_sec = timeout->tv_nsec = 0; 2373a2e27255SArnaldo Carvalho de Melo break; 2374a2e27255SArnaldo Carvalho de Melo } 2375a2e27255SArnaldo Carvalho de Melo 2376a2e27255SArnaldo Carvalho de Melo /* Timeout, return less than vlen datagrams */ 2377a2e27255SArnaldo Carvalho de Melo if (timeout->tv_nsec == 0 && timeout->tv_sec == 0) 2378a2e27255SArnaldo Carvalho de Melo break; 2379a2e27255SArnaldo Carvalho de Melo } 2380a2e27255SArnaldo Carvalho de Melo 2381a2e27255SArnaldo Carvalho de Melo /* Out of band data, return right away */ 2382a2e27255SArnaldo Carvalho de Melo if (msg_sys.msg_flags & MSG_OOB) 2383a2e27255SArnaldo Carvalho de Melo break; 2384a78cb84cSEric Dumazet cond_resched(); 2385a2e27255SArnaldo Carvalho de Melo } 2386a2e27255SArnaldo Carvalho de Melo 2387a2e27255SArnaldo Carvalho de Melo if (err == 0) 238834b88a68SArnaldo Carvalho de Melo goto out_put; 2389a2e27255SArnaldo Carvalho de Melo 239034b88a68SArnaldo Carvalho de Melo if (datagrams == 0) { 239134b88a68SArnaldo Carvalho de Melo datagrams = err; 239234b88a68SArnaldo Carvalho de Melo goto out_put; 239334b88a68SArnaldo Carvalho de Melo } 239434b88a68SArnaldo Carvalho de Melo 2395a2e27255SArnaldo Carvalho de Melo /* 2396a2e27255SArnaldo Carvalho de Melo * We may return less entries than requested (vlen) if the 2397a2e27255SArnaldo Carvalho de Melo * sock is non block and there aren't enough datagrams... 2398a2e27255SArnaldo Carvalho de Melo */ 2399a2e27255SArnaldo Carvalho de Melo if (err != -EAGAIN) { 2400a2e27255SArnaldo Carvalho de Melo /* 2401a2e27255SArnaldo Carvalho de Melo * ... or if recvmsg returns an error after we 2402a2e27255SArnaldo Carvalho de Melo * received some datagrams, where we record the 2403a2e27255SArnaldo Carvalho de Melo * error to return on the next call or if the 2404a2e27255SArnaldo Carvalho de Melo * app asks about it using getsockopt(SO_ERROR). 2405a2e27255SArnaldo Carvalho de Melo */ 2406a2e27255SArnaldo Carvalho de Melo sock->sk->sk_err = -err; 2407a2e27255SArnaldo Carvalho de Melo } 240834b88a68SArnaldo Carvalho de Melo out_put: 240934b88a68SArnaldo Carvalho de Melo fput_light(sock->file, fput_needed); 2410a2e27255SArnaldo Carvalho de Melo 2411a2e27255SArnaldo Carvalho de Melo return datagrams; 2412a2e27255SArnaldo Carvalho de Melo } 2413a2e27255SArnaldo Carvalho de Melo 2414a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, 2415a2e27255SArnaldo Carvalho de Melo unsigned int, vlen, unsigned int, flags, 2416a2e27255SArnaldo Carvalho de Melo struct timespec __user *, timeout) 2417a2e27255SArnaldo Carvalho de Melo { 2418a2e27255SArnaldo Carvalho de Melo int datagrams; 2419a2e27255SArnaldo Carvalho de Melo struct timespec timeout_sys; 2420a2e27255SArnaldo Carvalho de Melo 24211be374a0SAndy Lutomirski if (flags & MSG_CMSG_COMPAT) 24221be374a0SAndy Lutomirski return -EINVAL; 24231be374a0SAndy Lutomirski 2424a2e27255SArnaldo Carvalho de Melo if (!timeout) 2425a2e27255SArnaldo Carvalho de Melo return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL); 2426a2e27255SArnaldo Carvalho de Melo 2427a2e27255SArnaldo Carvalho de Melo if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys))) 2428a2e27255SArnaldo Carvalho de Melo return -EFAULT; 2429a2e27255SArnaldo Carvalho de Melo 2430a2e27255SArnaldo Carvalho de Melo datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys); 2431a2e27255SArnaldo Carvalho de Melo 2432a2e27255SArnaldo Carvalho de Melo if (datagrams > 0 && 2433a2e27255SArnaldo Carvalho de Melo copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys))) 2434a2e27255SArnaldo Carvalho de Melo datagrams = -EFAULT; 2435a2e27255SArnaldo Carvalho de Melo 2436a2e27255SArnaldo Carvalho de Melo return datagrams; 2437a2e27255SArnaldo Carvalho de Melo } 2438a2e27255SArnaldo Carvalho de Melo 2439a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL 24401da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */ 24411da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long)) 2442228e548eSAnton Blanchard static const unsigned char nargs[21] = { 244389bddce5SStephen Hemminger AL(0), AL(3), AL(3), AL(3), AL(2), AL(3), 24441da177e4SLinus Torvalds AL(3), AL(3), AL(4), AL(4), AL(4), AL(6), 2445aaca0bdcSUlrich Drepper AL(6), AL(2), AL(5), AL(5), AL(3), AL(3), 2446228e548eSAnton Blanchard AL(4), AL(5), AL(4) 244789bddce5SStephen Hemminger }; 244889bddce5SStephen Hemminger 24491da177e4SLinus Torvalds #undef AL 24501da177e4SLinus Torvalds 24511da177e4SLinus Torvalds /* 24521da177e4SLinus Torvalds * System call vectors. 24531da177e4SLinus Torvalds * 24541da177e4SLinus Torvalds * Argument checking cleaned up. Saved 20% in size. 24551da177e4SLinus Torvalds * This function doesn't need to set the kernel lock because 24561da177e4SLinus Torvalds * it is set by the callees. 24571da177e4SLinus Torvalds */ 24581da177e4SLinus Torvalds 24593e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) 24601da177e4SLinus Torvalds { 24612950fa9dSChen Gang unsigned long a[AUDITSC_ARGS]; 24621da177e4SLinus Torvalds unsigned long a0, a1; 24631da177e4SLinus Torvalds int err; 246447379052SArjan van de Ven unsigned int len; 24651da177e4SLinus Torvalds 2466228e548eSAnton Blanchard if (call < 1 || call > SYS_SENDMMSG) 24671da177e4SLinus Torvalds return -EINVAL; 24681da177e4SLinus Torvalds 246947379052SArjan van de Ven len = nargs[call]; 247047379052SArjan van de Ven if (len > sizeof(a)) 247147379052SArjan van de Ven return -EINVAL; 247247379052SArjan van de Ven 24731da177e4SLinus Torvalds /* copy_from_user should be SMP safe. */ 247447379052SArjan van de Ven if (copy_from_user(a, args, len)) 24751da177e4SLinus Torvalds return -EFAULT; 24761da177e4SLinus Torvalds 24772950fa9dSChen Gang err = audit_socketcall(nargs[call] / sizeof(unsigned long), a); 24782950fa9dSChen Gang if (err) 24792950fa9dSChen Gang return err; 24803ec3b2fbSDavid Woodhouse 24811da177e4SLinus Torvalds a0 = a[0]; 24821da177e4SLinus Torvalds a1 = a[1]; 24831da177e4SLinus Torvalds 248489bddce5SStephen Hemminger switch (call) { 24851da177e4SLinus Torvalds case SYS_SOCKET: 24869d6a15c3SDominik Brodowski err = __sys_socket(a0, a1, a[2]); 24871da177e4SLinus Torvalds break; 24881da177e4SLinus Torvalds case SYS_BIND: 2489a87d35d8SDominik Brodowski err = __sys_bind(a0, (struct sockaddr __user *)a1, a[2]); 24901da177e4SLinus Torvalds break; 24911da177e4SLinus Torvalds case SYS_CONNECT: 24921387c2c2SDominik Brodowski err = __sys_connect(a0, (struct sockaddr __user *)a1, a[2]); 24931da177e4SLinus Torvalds break; 24941da177e4SLinus Torvalds case SYS_LISTEN: 249525e290eeSDominik Brodowski err = __sys_listen(a0, a1); 24961da177e4SLinus Torvalds break; 24971da177e4SLinus Torvalds case SYS_ACCEPT: 24984541e805SDominik Brodowski err = __sys_accept4(a0, (struct sockaddr __user *)a1, 2499aaca0bdcSUlrich Drepper (int __user *)a[2], 0); 25001da177e4SLinus Torvalds break; 25011da177e4SLinus Torvalds case SYS_GETSOCKNAME: 250289bddce5SStephen Hemminger err = 250389bddce5SStephen Hemminger sys_getsockname(a0, (struct sockaddr __user *)a1, 250489bddce5SStephen Hemminger (int __user *)a[2]); 25051da177e4SLinus Torvalds break; 25061da177e4SLinus Torvalds case SYS_GETPEERNAME: 250789bddce5SStephen Hemminger err = 250889bddce5SStephen Hemminger sys_getpeername(a0, (struct sockaddr __user *)a1, 250989bddce5SStephen Hemminger (int __user *)a[2]); 25101da177e4SLinus Torvalds break; 25111da177e4SLinus Torvalds case SYS_SOCKETPAIR: 25121da177e4SLinus Torvalds err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]); 25131da177e4SLinus Torvalds break; 25141da177e4SLinus Torvalds case SYS_SEND: 25151da177e4SLinus Torvalds err = sys_send(a0, (void __user *)a1, a[2], a[3]); 25161da177e4SLinus Torvalds break; 25171da177e4SLinus Torvalds case SYS_SENDTO: 2518211b634bSDominik Brodowski err = __sys_sendto(a0, (void __user *)a1, a[2], a[3], 25191da177e4SLinus Torvalds (struct sockaddr __user *)a[4], a[5]); 25201da177e4SLinus Torvalds break; 25211da177e4SLinus Torvalds case SYS_RECV: 25221da177e4SLinus Torvalds err = sys_recv(a0, (void __user *)a1, a[2], a[3]); 25231da177e4SLinus Torvalds break; 25241da177e4SLinus Torvalds case SYS_RECVFROM: 25257a09e1ebSDominik Brodowski err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3], 252689bddce5SStephen Hemminger (struct sockaddr __user *)a[4], 252789bddce5SStephen Hemminger (int __user *)a[5]); 25281da177e4SLinus Torvalds break; 25291da177e4SLinus Torvalds case SYS_SHUTDOWN: 25301da177e4SLinus Torvalds err = sys_shutdown(a0, a1); 25311da177e4SLinus Torvalds break; 25321da177e4SLinus Torvalds case SYS_SETSOCKOPT: 25331da177e4SLinus Torvalds err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]); 25341da177e4SLinus Torvalds break; 25351da177e4SLinus Torvalds case SYS_GETSOCKOPT: 253689bddce5SStephen Hemminger err = 253789bddce5SStephen Hemminger sys_getsockopt(a0, a1, a[2], (char __user *)a[3], 253889bddce5SStephen Hemminger (int __user *)a[4]); 25391da177e4SLinus Torvalds break; 25401da177e4SLinus Torvalds case SYS_SENDMSG: 2541666547ffSAl Viro err = sys_sendmsg(a0, (struct user_msghdr __user *)a1, a[2]); 25421da177e4SLinus Torvalds break; 2543228e548eSAnton Blanchard case SYS_SENDMMSG: 2544228e548eSAnton Blanchard err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]); 2545228e548eSAnton Blanchard break; 25461da177e4SLinus Torvalds case SYS_RECVMSG: 2547666547ffSAl Viro err = sys_recvmsg(a0, (struct user_msghdr __user *)a1, a[2]); 25481da177e4SLinus Torvalds break; 2549a2e27255SArnaldo Carvalho de Melo case SYS_RECVMMSG: 2550a2e27255SArnaldo Carvalho de Melo err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3], 2551a2e27255SArnaldo Carvalho de Melo (struct timespec __user *)a[4]); 2552a2e27255SArnaldo Carvalho de Melo break; 2553de11defeSUlrich Drepper case SYS_ACCEPT4: 25544541e805SDominik Brodowski err = __sys_accept4(a0, (struct sockaddr __user *)a1, 2555de11defeSUlrich Drepper (int __user *)a[2], a[3]); 2556aaca0bdcSUlrich Drepper break; 25571da177e4SLinus Torvalds default: 25581da177e4SLinus Torvalds err = -EINVAL; 25591da177e4SLinus Torvalds break; 25601da177e4SLinus Torvalds } 25611da177e4SLinus Torvalds return err; 25621da177e4SLinus Torvalds } 25631da177e4SLinus Torvalds 25641da177e4SLinus Torvalds #endif /* __ARCH_WANT_SYS_SOCKETCALL */ 25651da177e4SLinus Torvalds 256655737fdaSStephen Hemminger /** 256755737fdaSStephen Hemminger * sock_register - add a socket protocol handler 256855737fdaSStephen Hemminger * @ops: description of protocol 256955737fdaSStephen Hemminger * 25701da177e4SLinus Torvalds * This function is called by a protocol handler that wants to 25711da177e4SLinus Torvalds * advertise its address family, and have it linked into the 2572e793c0f7SMasanari Iida * socket interface. The value ops->family corresponds to the 257355737fdaSStephen Hemminger * socket system call protocol family. 25741da177e4SLinus Torvalds */ 2575f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops) 25761da177e4SLinus Torvalds { 25771da177e4SLinus Torvalds int err; 25781da177e4SLinus Torvalds 25791da177e4SLinus Torvalds if (ops->family >= NPROTO) { 25803410f22eSYang Yingliang pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO); 25811da177e4SLinus Torvalds return -ENOBUFS; 25821da177e4SLinus Torvalds } 258355737fdaSStephen Hemminger 258455737fdaSStephen Hemminger spin_lock(&net_family_lock); 2585190683a9SEric Dumazet if (rcu_dereference_protected(net_families[ops->family], 2586190683a9SEric Dumazet lockdep_is_held(&net_family_lock))) 25871da177e4SLinus Torvalds err = -EEXIST; 258855737fdaSStephen Hemminger else { 2589cf778b00SEric Dumazet rcu_assign_pointer(net_families[ops->family], ops); 25901da177e4SLinus Torvalds err = 0; 25911da177e4SLinus Torvalds } 259255737fdaSStephen Hemminger spin_unlock(&net_family_lock); 259355737fdaSStephen Hemminger 25943410f22eSYang Yingliang pr_info("NET: Registered protocol family %d\n", ops->family); 25951da177e4SLinus Torvalds return err; 25961da177e4SLinus Torvalds } 2597c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register); 25981da177e4SLinus Torvalds 259955737fdaSStephen Hemminger /** 260055737fdaSStephen Hemminger * sock_unregister - remove a protocol handler 260155737fdaSStephen Hemminger * @family: protocol family to remove 260255737fdaSStephen Hemminger * 26031da177e4SLinus Torvalds * This function is called by a protocol handler that wants to 26041da177e4SLinus Torvalds * remove its address family, and have it unlinked from the 260555737fdaSStephen Hemminger * new socket creation. 260655737fdaSStephen Hemminger * 260755737fdaSStephen Hemminger * If protocol handler is a module, then it can use module reference 260855737fdaSStephen Hemminger * counts to protect against new references. If protocol handler is not 260955737fdaSStephen Hemminger * a module then it needs to provide its own protection in 261055737fdaSStephen Hemminger * the ops->create routine. 26111da177e4SLinus Torvalds */ 2612f0fd27d4SStephen Hemminger void sock_unregister(int family) 26131da177e4SLinus Torvalds { 2614f0fd27d4SStephen Hemminger BUG_ON(family < 0 || family >= NPROTO); 26151da177e4SLinus Torvalds 261655737fdaSStephen Hemminger spin_lock(&net_family_lock); 2617a9b3cd7fSStephen Hemminger RCU_INIT_POINTER(net_families[family], NULL); 261855737fdaSStephen Hemminger spin_unlock(&net_family_lock); 261955737fdaSStephen Hemminger 262055737fdaSStephen Hemminger synchronize_rcu(); 262155737fdaSStephen Hemminger 26223410f22eSYang Yingliang pr_info("NET: Unregistered protocol family %d\n", family); 26231da177e4SLinus Torvalds } 2624c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister); 26251da177e4SLinus Torvalds 262677d76ea3SAndi Kleen static int __init sock_init(void) 26271da177e4SLinus Torvalds { 2628b3e19d92SNick Piggin int err; 26292ca794e5SEric W. Biederman /* 26302ca794e5SEric W. Biederman * Initialize the network sysctl infrastructure. 26312ca794e5SEric W. Biederman */ 26322ca794e5SEric W. Biederman err = net_sysctl_init(); 26332ca794e5SEric W. Biederman if (err) 26342ca794e5SEric W. Biederman goto out; 2635b3e19d92SNick Piggin 26361da177e4SLinus Torvalds /* 26371da177e4SLinus Torvalds * Initialize skbuff SLAB cache 26381da177e4SLinus Torvalds */ 26391da177e4SLinus Torvalds skb_init(); 26401da177e4SLinus Torvalds 26411da177e4SLinus Torvalds /* 26421da177e4SLinus Torvalds * Initialize the protocols module. 26431da177e4SLinus Torvalds */ 26441da177e4SLinus Torvalds 26451da177e4SLinus Torvalds init_inodecache(); 2646b3e19d92SNick Piggin 2647b3e19d92SNick Piggin err = register_filesystem(&sock_fs_type); 2648b3e19d92SNick Piggin if (err) 2649b3e19d92SNick Piggin goto out_fs; 26501da177e4SLinus Torvalds sock_mnt = kern_mount(&sock_fs_type); 2651b3e19d92SNick Piggin if (IS_ERR(sock_mnt)) { 2652b3e19d92SNick Piggin err = PTR_ERR(sock_mnt); 2653b3e19d92SNick Piggin goto out_mount; 2654b3e19d92SNick Piggin } 265577d76ea3SAndi Kleen 265677d76ea3SAndi Kleen /* The real protocol initialization is performed in later initcalls. 26571da177e4SLinus Torvalds */ 26581da177e4SLinus Torvalds 26591da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER 26606d11cfdbSPablo Neira Ayuso err = netfilter_init(); 26616d11cfdbSPablo Neira Ayuso if (err) 26626d11cfdbSPablo Neira Ayuso goto out; 26631da177e4SLinus Torvalds #endif 2664cbeb321aSDavid S. Miller 2665408eccceSDaniel Borkmann ptp_classifier_init(); 2666c1f19b51SRichard Cochran 2667b3e19d92SNick Piggin out: 2668b3e19d92SNick Piggin return err; 2669b3e19d92SNick Piggin 2670b3e19d92SNick Piggin out_mount: 2671b3e19d92SNick Piggin unregister_filesystem(&sock_fs_type); 2672b3e19d92SNick Piggin out_fs: 2673b3e19d92SNick Piggin goto out; 26741da177e4SLinus Torvalds } 26751da177e4SLinus Torvalds 267677d76ea3SAndi Kleen core_initcall(sock_init); /* early initcall */ 267777d76ea3SAndi Kleen 26781da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS 26791da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq) 26801da177e4SLinus Torvalds { 2681648845abSTonghao Zhang seq_printf(seq, "sockets: used %d\n", 2682648845abSTonghao Zhang sock_inuse_get(seq->private)); 26831da177e4SLinus Torvalds } 26841da177e4SLinus Torvalds #endif /* CONFIG_PROC_FS */ 26851da177e4SLinus Torvalds 268689bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 26876b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock, 2688644595f8SH. Peter Anvin unsigned int cmd, void __user *up) 26897a229387SArnd Bergmann { 26907a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 26917a229387SArnd Bergmann struct timeval ktv; 26927a229387SArnd Bergmann int err; 26937a229387SArnd Bergmann 26947a229387SArnd Bergmann set_fs(KERNEL_DS); 26956b96018bSArnd Bergmann err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv); 26967a229387SArnd Bergmann set_fs(old_fs); 2697644595f8SH. Peter Anvin if (!err) 2698ed6fe9d6SMikulas Patocka err = compat_put_timeval(&ktv, up); 2699644595f8SH. Peter Anvin 27007a229387SArnd Bergmann return err; 27017a229387SArnd Bergmann } 27027a229387SArnd Bergmann 27036b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock, 2704644595f8SH. Peter Anvin unsigned int cmd, void __user *up) 27057a229387SArnd Bergmann { 27067a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 27077a229387SArnd Bergmann struct timespec kts; 27087a229387SArnd Bergmann int err; 27097a229387SArnd Bergmann 27107a229387SArnd Bergmann set_fs(KERNEL_DS); 27116b96018bSArnd Bergmann err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts); 27127a229387SArnd Bergmann set_fs(old_fs); 2713644595f8SH. Peter Anvin if (!err) 2714ed6fe9d6SMikulas Patocka err = compat_put_timespec(&kts, up); 2715644595f8SH. Peter Anvin 27167a229387SArnd Bergmann return err; 27177a229387SArnd Bergmann } 27187a229387SArnd Bergmann 271936fd633eSAl Viro static int compat_dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) 27207a229387SArnd Bergmann { 27216b96018bSArnd Bergmann struct compat_ifconf ifc32; 27227a229387SArnd Bergmann struct ifconf ifc; 27237a229387SArnd Bergmann int err; 27247a229387SArnd Bergmann 27256b96018bSArnd Bergmann if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf))) 27267a229387SArnd Bergmann return -EFAULT; 27277a229387SArnd Bergmann 272836fd633eSAl Viro ifc.ifc_len = ifc32.ifc_len; 272936fd633eSAl Viro ifc.ifc_req = compat_ptr(ifc32.ifcbuf); 27307a229387SArnd Bergmann 273136fd633eSAl Viro rtnl_lock(); 273236fd633eSAl Viro err = dev_ifconf(net, &ifc, sizeof(struct compat_ifreq)); 273336fd633eSAl Viro rtnl_unlock(); 27347a229387SArnd Bergmann if (err) 27357a229387SArnd Bergmann return err; 27367a229387SArnd Bergmann 273736fd633eSAl Viro ifc32.ifc_len = ifc.ifc_len; 27386b96018bSArnd Bergmann if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf))) 27397a229387SArnd Bergmann return -EFAULT; 27407a229387SArnd Bergmann 27417a229387SArnd Bergmann return 0; 27427a229387SArnd Bergmann } 27437a229387SArnd Bergmann 27446b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) 27457a229387SArnd Bergmann { 27463a7da39dSBen Hutchings struct compat_ethtool_rxnfc __user *compat_rxnfc; 27473a7da39dSBen Hutchings bool convert_in = false, convert_out = false; 274844c02a2cSAl Viro size_t buf_size = 0; 274944c02a2cSAl Viro struct ethtool_rxnfc __user *rxnfc = NULL; 275044c02a2cSAl Viro struct ifreq ifr; 27513a7da39dSBen Hutchings u32 rule_cnt = 0, actual_rule_cnt; 27523a7da39dSBen Hutchings u32 ethcmd; 27537a229387SArnd Bergmann u32 data; 27543a7da39dSBen Hutchings int ret; 27557a229387SArnd Bergmann 27567a229387SArnd Bergmann if (get_user(data, &ifr32->ifr_ifru.ifru_data)) 27577a229387SArnd Bergmann return -EFAULT; 27587a229387SArnd Bergmann 27593a7da39dSBen Hutchings compat_rxnfc = compat_ptr(data); 27603a7da39dSBen Hutchings 27613a7da39dSBen Hutchings if (get_user(ethcmd, &compat_rxnfc->cmd)) 27627a229387SArnd Bergmann return -EFAULT; 27637a229387SArnd Bergmann 27643a7da39dSBen Hutchings /* Most ethtool structures are defined without padding. 27653a7da39dSBen Hutchings * Unfortunately struct ethtool_rxnfc is an exception. 27663a7da39dSBen Hutchings */ 27673a7da39dSBen Hutchings switch (ethcmd) { 27683a7da39dSBen Hutchings default: 27693a7da39dSBen Hutchings break; 27703a7da39dSBen Hutchings case ETHTOOL_GRXCLSRLALL: 27713a7da39dSBen Hutchings /* Buffer size is variable */ 27723a7da39dSBen Hutchings if (get_user(rule_cnt, &compat_rxnfc->rule_cnt)) 27733a7da39dSBen Hutchings return -EFAULT; 27743a7da39dSBen Hutchings if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32)) 27753a7da39dSBen Hutchings return -ENOMEM; 27763a7da39dSBen Hutchings buf_size += rule_cnt * sizeof(u32); 27773a7da39dSBen Hutchings /* fall through */ 27783a7da39dSBen Hutchings case ETHTOOL_GRXRINGS: 27793a7da39dSBen Hutchings case ETHTOOL_GRXCLSRLCNT: 27803a7da39dSBen Hutchings case ETHTOOL_GRXCLSRULE: 278155664f32SBen Hutchings case ETHTOOL_SRXCLSRLINS: 27823a7da39dSBen Hutchings convert_out = true; 27833a7da39dSBen Hutchings /* fall through */ 27843a7da39dSBen Hutchings case ETHTOOL_SRXCLSRLDEL: 27853a7da39dSBen Hutchings buf_size += sizeof(struct ethtool_rxnfc); 27863a7da39dSBen Hutchings convert_in = true; 278744c02a2cSAl Viro rxnfc = compat_alloc_user_space(buf_size); 27883a7da39dSBen Hutchings break; 27893a7da39dSBen Hutchings } 27903a7da39dSBen Hutchings 279144c02a2cSAl Viro if (copy_from_user(&ifr.ifr_name, &ifr32->ifr_name, IFNAMSIZ)) 27923a7da39dSBen Hutchings return -EFAULT; 27933a7da39dSBen Hutchings 279444c02a2cSAl Viro ifr.ifr_data = convert_in ? rxnfc : (void __user *)compat_rxnfc; 27953a7da39dSBen Hutchings 27963a7da39dSBen Hutchings if (convert_in) { 2797127fe533SAlexander Duyck /* We expect there to be holes between fs.m_ext and 27983a7da39dSBen Hutchings * fs.ring_cookie and at the end of fs, but nowhere else. 27993a7da39dSBen Hutchings */ 2800127fe533SAlexander Duyck BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) + 2801127fe533SAlexander Duyck sizeof(compat_rxnfc->fs.m_ext) != 2802127fe533SAlexander Duyck offsetof(struct ethtool_rxnfc, fs.m_ext) + 2803127fe533SAlexander Duyck sizeof(rxnfc->fs.m_ext)); 28043a7da39dSBen Hutchings BUILD_BUG_ON( 28053a7da39dSBen Hutchings offsetof(struct compat_ethtool_rxnfc, fs.location) - 28063a7da39dSBen Hutchings offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) != 28073a7da39dSBen Hutchings offsetof(struct ethtool_rxnfc, fs.location) - 28083a7da39dSBen Hutchings offsetof(struct ethtool_rxnfc, fs.ring_cookie)); 28093a7da39dSBen Hutchings 28103a7da39dSBen Hutchings if (copy_in_user(rxnfc, compat_rxnfc, 2811954b1244SStephen Hemminger (void __user *)(&rxnfc->fs.m_ext + 1) - 2812954b1244SStephen Hemminger (void __user *)rxnfc) || 28133a7da39dSBen Hutchings copy_in_user(&rxnfc->fs.ring_cookie, 28143a7da39dSBen Hutchings &compat_rxnfc->fs.ring_cookie, 2815954b1244SStephen Hemminger (void __user *)(&rxnfc->fs.location + 1) - 2816954b1244SStephen Hemminger (void __user *)&rxnfc->fs.ring_cookie) || 28173a7da39dSBen Hutchings copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt, 28183a7da39dSBen Hutchings sizeof(rxnfc->rule_cnt))) 28193a7da39dSBen Hutchings return -EFAULT; 28203a7da39dSBen Hutchings } 28213a7da39dSBen Hutchings 282244c02a2cSAl Viro ret = dev_ioctl(net, SIOCETHTOOL, &ifr, NULL); 28233a7da39dSBen Hutchings if (ret) 28243a7da39dSBen Hutchings return ret; 28253a7da39dSBen Hutchings 28263a7da39dSBen Hutchings if (convert_out) { 28273a7da39dSBen Hutchings if (copy_in_user(compat_rxnfc, rxnfc, 2828954b1244SStephen Hemminger (const void __user *)(&rxnfc->fs.m_ext + 1) - 2829954b1244SStephen Hemminger (const void __user *)rxnfc) || 28303a7da39dSBen Hutchings copy_in_user(&compat_rxnfc->fs.ring_cookie, 28313a7da39dSBen Hutchings &rxnfc->fs.ring_cookie, 2832954b1244SStephen Hemminger (const void __user *)(&rxnfc->fs.location + 1) - 2833954b1244SStephen Hemminger (const void __user *)&rxnfc->fs.ring_cookie) || 28343a7da39dSBen Hutchings copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt, 28353a7da39dSBen Hutchings sizeof(rxnfc->rule_cnt))) 28363a7da39dSBen Hutchings return -EFAULT; 28373a7da39dSBen Hutchings 28383a7da39dSBen Hutchings if (ethcmd == ETHTOOL_GRXCLSRLALL) { 28393a7da39dSBen Hutchings /* As an optimisation, we only copy the actual 28403a7da39dSBen Hutchings * number of rules that the underlying 28413a7da39dSBen Hutchings * function returned. Since Mallory might 28423a7da39dSBen Hutchings * change the rule count in user memory, we 28433a7da39dSBen Hutchings * check that it is less than the rule count 28443a7da39dSBen Hutchings * originally given (as the user buffer size), 28453a7da39dSBen Hutchings * which has been range-checked. 28463a7da39dSBen Hutchings */ 28473a7da39dSBen Hutchings if (get_user(actual_rule_cnt, &rxnfc->rule_cnt)) 28483a7da39dSBen Hutchings return -EFAULT; 28493a7da39dSBen Hutchings if (actual_rule_cnt < rule_cnt) 28503a7da39dSBen Hutchings rule_cnt = actual_rule_cnt; 28513a7da39dSBen Hutchings if (copy_in_user(&compat_rxnfc->rule_locs[0], 28523a7da39dSBen Hutchings &rxnfc->rule_locs[0], 28533a7da39dSBen Hutchings rule_cnt * sizeof(u32))) 28543a7da39dSBen Hutchings return -EFAULT; 28553a7da39dSBen Hutchings } 28563a7da39dSBen Hutchings } 28573a7da39dSBen Hutchings 28583a7da39dSBen Hutchings return 0; 28597a229387SArnd Bergmann } 28607a229387SArnd Bergmann 28617a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32) 28627a50a240SArnd Bergmann { 28637a50a240SArnd Bergmann compat_uptr_t uptr32; 286444c02a2cSAl Viro struct ifreq ifr; 286544c02a2cSAl Viro void __user *saved; 286644c02a2cSAl Viro int err; 28677a50a240SArnd Bergmann 286844c02a2cSAl Viro if (copy_from_user(&ifr, uifr32, sizeof(struct compat_ifreq))) 28697a50a240SArnd Bergmann return -EFAULT; 28707a50a240SArnd Bergmann 28717a50a240SArnd Bergmann if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu)) 28727a50a240SArnd Bergmann return -EFAULT; 28737a50a240SArnd Bergmann 287444c02a2cSAl Viro saved = ifr.ifr_settings.ifs_ifsu.raw_hdlc; 287544c02a2cSAl Viro ifr.ifr_settings.ifs_ifsu.raw_hdlc = compat_ptr(uptr32); 28767a50a240SArnd Bergmann 287744c02a2cSAl Viro err = dev_ioctl(net, SIOCWANDEV, &ifr, NULL); 287844c02a2cSAl Viro if (!err) { 287944c02a2cSAl Viro ifr.ifr_settings.ifs_ifsu.raw_hdlc = saved; 288044c02a2cSAl Viro if (copy_to_user(uifr32, &ifr, sizeof(struct compat_ifreq))) 288144c02a2cSAl Viro err = -EFAULT; 28827a50a240SArnd Bergmann } 28837a229387SArnd Bergmann return err; 28847a229387SArnd Bergmann } 28857a229387SArnd Bergmann 2886590d4693SBen Hutchings /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */ 2887590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd, 28886b96018bSArnd Bergmann struct compat_ifreq __user *u_ifreq32) 28897a229387SArnd Bergmann { 289044c02a2cSAl Viro struct ifreq ifreq; 28917a229387SArnd Bergmann u32 data32; 28927a229387SArnd Bergmann 289344c02a2cSAl Viro if (copy_from_user(ifreq.ifr_name, u_ifreq32->ifr_name, IFNAMSIZ)) 28947a229387SArnd Bergmann return -EFAULT; 289544c02a2cSAl Viro if (get_user(data32, &u_ifreq32->ifr_data)) 28967a229387SArnd Bergmann return -EFAULT; 289744c02a2cSAl Viro ifreq.ifr_data = compat_ptr(data32); 28987a229387SArnd Bergmann 289944c02a2cSAl Viro return dev_ioctl(net, cmd, &ifreq, NULL); 2900a2116ed2SArnd Bergmann } 2901a2116ed2SArnd Bergmann 2902a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd, 2903a2116ed2SArnd Bergmann struct compat_ifreq __user *uifr32) 2904a2116ed2SArnd Bergmann { 2905a2116ed2SArnd Bergmann struct ifreq ifr; 2906a2116ed2SArnd Bergmann struct compat_ifmap __user *uifmap32; 2907a2116ed2SArnd Bergmann int err; 2908a2116ed2SArnd Bergmann 2909a2116ed2SArnd Bergmann uifmap32 = &uifr32->ifr_ifru.ifru_map; 2910a2116ed2SArnd Bergmann err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name)); 29113ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); 29123ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); 29133ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); 29143ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.irq, &uifmap32->irq); 29153ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.dma, &uifmap32->dma); 29163ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.port, &uifmap32->port); 2917a2116ed2SArnd Bergmann if (err) 2918a2116ed2SArnd Bergmann return -EFAULT; 2919a2116ed2SArnd Bergmann 292044c02a2cSAl Viro err = dev_ioctl(net, cmd, &ifr, NULL); 2921a2116ed2SArnd Bergmann 2922a2116ed2SArnd Bergmann if (cmd == SIOCGIFMAP && !err) { 29237a229387SArnd Bergmann err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name)); 29243ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); 29253ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); 29263ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); 29273ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.irq, &uifmap32->irq); 29283ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.dma, &uifmap32->dma); 29293ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.port, &uifmap32->port); 29307a229387SArnd Bergmann if (err) 29317a229387SArnd Bergmann err = -EFAULT; 29327a229387SArnd Bergmann } 29337a229387SArnd Bergmann return err; 29347a229387SArnd Bergmann } 29357a229387SArnd Bergmann 29367a229387SArnd Bergmann struct rtentry32 { 29377a229387SArnd Bergmann u32 rt_pad1; 29387a229387SArnd Bergmann struct sockaddr rt_dst; /* target address */ 29397a229387SArnd Bergmann struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ 29407a229387SArnd Bergmann struct sockaddr rt_genmask; /* target network mask (IP) */ 29417a229387SArnd Bergmann unsigned short rt_flags; 29427a229387SArnd Bergmann short rt_pad2; 29437a229387SArnd Bergmann u32 rt_pad3; 29447a229387SArnd Bergmann unsigned char rt_tos; 29457a229387SArnd Bergmann unsigned char rt_class; 29467a229387SArnd Bergmann short rt_pad4; 29477a229387SArnd Bergmann short rt_metric; /* +1 for binary compatibility! */ 29487a229387SArnd Bergmann /* char * */ u32 rt_dev; /* forcing the device at add */ 29497a229387SArnd Bergmann u32 rt_mtu; /* per route MTU/Window */ 29507a229387SArnd Bergmann u32 rt_window; /* Window clamping */ 29517a229387SArnd Bergmann unsigned short rt_irtt; /* Initial RTT */ 29527a229387SArnd Bergmann }; 29537a229387SArnd Bergmann 29547a229387SArnd Bergmann struct in6_rtmsg32 { 29557a229387SArnd Bergmann struct in6_addr rtmsg_dst; 29567a229387SArnd Bergmann struct in6_addr rtmsg_src; 29577a229387SArnd Bergmann struct in6_addr rtmsg_gateway; 29587a229387SArnd Bergmann u32 rtmsg_type; 29597a229387SArnd Bergmann u16 rtmsg_dst_len; 29607a229387SArnd Bergmann u16 rtmsg_src_len; 29617a229387SArnd Bergmann u32 rtmsg_metric; 29627a229387SArnd Bergmann u32 rtmsg_info; 29637a229387SArnd Bergmann u32 rtmsg_flags; 29647a229387SArnd Bergmann s32 rtmsg_ifindex; 29657a229387SArnd Bergmann }; 29667a229387SArnd Bergmann 29676b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock, 29686b96018bSArnd Bergmann unsigned int cmd, void __user *argp) 29697a229387SArnd Bergmann { 29707a229387SArnd Bergmann int ret; 29717a229387SArnd Bergmann void *r = NULL; 29727a229387SArnd Bergmann struct in6_rtmsg r6; 29737a229387SArnd Bergmann struct rtentry r4; 29747a229387SArnd Bergmann char devname[16]; 29757a229387SArnd Bergmann u32 rtdev; 29767a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 29777a229387SArnd Bergmann 29786b96018bSArnd Bergmann if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */ 29796b96018bSArnd Bergmann struct in6_rtmsg32 __user *ur6 = argp; 29807a229387SArnd Bergmann ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst), 29817a229387SArnd Bergmann 3 * sizeof(struct in6_addr)); 29823ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type)); 29833ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len)); 29843ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len)); 29853ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric)); 29863ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info)); 29873ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags)); 29883ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex)); 29897a229387SArnd Bergmann 29907a229387SArnd Bergmann r = (void *) &r6; 29917a229387SArnd Bergmann } else { /* ipv4 */ 29926b96018bSArnd Bergmann struct rtentry32 __user *ur4 = argp; 29937a229387SArnd Bergmann ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst), 29947a229387SArnd Bergmann 3 * sizeof(struct sockaddr)); 29953ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_flags, &(ur4->rt_flags)); 29963ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_metric, &(ur4->rt_metric)); 29973ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu)); 29983ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_window, &(ur4->rt_window)); 29993ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt)); 30003ddc5b46SMathieu Desnoyers ret |= get_user(rtdev, &(ur4->rt_dev)); 30017a229387SArnd Bergmann if (rtdev) { 30027a229387SArnd Bergmann ret |= copy_from_user(devname, compat_ptr(rtdev), 15); 3003c3f52ae6Sstephen hemminger r4.rt_dev = (char __user __force *)devname; 3004c3f52ae6Sstephen hemminger devname[15] = 0; 30057a229387SArnd Bergmann } else 30067a229387SArnd Bergmann r4.rt_dev = NULL; 30077a229387SArnd Bergmann 30087a229387SArnd Bergmann r = (void *) &r4; 30097a229387SArnd Bergmann } 30107a229387SArnd Bergmann 30117a229387SArnd Bergmann if (ret) { 30127a229387SArnd Bergmann ret = -EFAULT; 30137a229387SArnd Bergmann goto out; 30147a229387SArnd Bergmann } 30157a229387SArnd Bergmann 30167a229387SArnd Bergmann set_fs(KERNEL_DS); 30176b96018bSArnd Bergmann ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r); 30187a229387SArnd Bergmann set_fs(old_fs); 30197a229387SArnd Bergmann 30207a229387SArnd Bergmann out: 30217a229387SArnd Bergmann return ret; 30227a229387SArnd Bergmann } 30237a229387SArnd Bergmann 30247a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE 30257a229387SArnd Bergmann * for some operations; this forces use of the newer bridge-utils that 302625985edcSLucas De Marchi * use compatible ioctls 30277a229387SArnd Bergmann */ 30286b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp) 30297a229387SArnd Bergmann { 30306b96018bSArnd Bergmann compat_ulong_t tmp; 30317a229387SArnd Bergmann 30326b96018bSArnd Bergmann if (get_user(tmp, argp)) 30337a229387SArnd Bergmann return -EFAULT; 30347a229387SArnd Bergmann if (tmp == BRCTL_GET_VERSION) 30357a229387SArnd Bergmann return BRCTL_VERSION + 1; 30367a229387SArnd Bergmann return -EINVAL; 30377a229387SArnd Bergmann } 30387a229387SArnd Bergmann 30396b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, 30406b96018bSArnd Bergmann unsigned int cmd, unsigned long arg) 30416b96018bSArnd Bergmann { 30426b96018bSArnd Bergmann void __user *argp = compat_ptr(arg); 30436b96018bSArnd Bergmann struct sock *sk = sock->sk; 30446b96018bSArnd Bergmann struct net *net = sock_net(sk); 30457a229387SArnd Bergmann 30466b96018bSArnd Bergmann if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) 3047590d4693SBen Hutchings return compat_ifr_data_ioctl(net, cmd, argp); 30487a229387SArnd Bergmann 30496b96018bSArnd Bergmann switch (cmd) { 30506b96018bSArnd Bergmann case SIOCSIFBR: 30516b96018bSArnd Bergmann case SIOCGIFBR: 30526b96018bSArnd Bergmann return old_bridge_ioctl(argp); 30536b96018bSArnd Bergmann case SIOCGIFCONF: 305436fd633eSAl Viro return compat_dev_ifconf(net, argp); 30556b96018bSArnd Bergmann case SIOCETHTOOL: 30566b96018bSArnd Bergmann return ethtool_ioctl(net, argp); 30577a50a240SArnd Bergmann case SIOCWANDEV: 30587a50a240SArnd Bergmann return compat_siocwandev(net, argp); 3059a2116ed2SArnd Bergmann case SIOCGIFMAP: 3060a2116ed2SArnd Bergmann case SIOCSIFMAP: 3061a2116ed2SArnd Bergmann return compat_sioc_ifmap(net, cmd, argp); 30626b96018bSArnd Bergmann case SIOCADDRT: 30636b96018bSArnd Bergmann case SIOCDELRT: 30646b96018bSArnd Bergmann return routing_ioctl(net, sock, cmd, argp); 30656b96018bSArnd Bergmann case SIOCGSTAMP: 30666b96018bSArnd Bergmann return do_siocgstamp(net, sock, cmd, argp); 30676b96018bSArnd Bergmann case SIOCGSTAMPNS: 30686b96018bSArnd Bergmann return do_siocgstampns(net, sock, cmd, argp); 3069590d4693SBen Hutchings case SIOCBONDSLAVEINFOQUERY: 3070590d4693SBen Hutchings case SIOCBONDINFOQUERY: 3071a2116ed2SArnd Bergmann case SIOCSHWTSTAMP: 3072fd468c74SBen Hutchings case SIOCGHWTSTAMP: 3073590d4693SBen Hutchings return compat_ifr_data_ioctl(net, cmd, argp); 30747a229387SArnd Bergmann 30756b96018bSArnd Bergmann case FIOSETOWN: 30766b96018bSArnd Bergmann case SIOCSPGRP: 30776b96018bSArnd Bergmann case FIOGETOWN: 30786b96018bSArnd Bergmann case SIOCGPGRP: 30796b96018bSArnd Bergmann case SIOCBRADDBR: 30806b96018bSArnd Bergmann case SIOCBRDELBR: 30816b96018bSArnd Bergmann case SIOCGIFVLAN: 30826b96018bSArnd Bergmann case SIOCSIFVLAN: 30836b96018bSArnd Bergmann case SIOCADDDLCI: 30846b96018bSArnd Bergmann case SIOCDELDLCI: 3085c62cce2cSAndrey Vagin case SIOCGSKNS: 30866b96018bSArnd Bergmann return sock_ioctl(file, cmd, arg); 30876b96018bSArnd Bergmann 30886b96018bSArnd Bergmann case SIOCGIFFLAGS: 30896b96018bSArnd Bergmann case SIOCSIFFLAGS: 30906b96018bSArnd Bergmann case SIOCGIFMETRIC: 30916b96018bSArnd Bergmann case SIOCSIFMETRIC: 30926b96018bSArnd Bergmann case SIOCGIFMTU: 30936b96018bSArnd Bergmann case SIOCSIFMTU: 30946b96018bSArnd Bergmann case SIOCGIFMEM: 30956b96018bSArnd Bergmann case SIOCSIFMEM: 30966b96018bSArnd Bergmann case SIOCGIFHWADDR: 30976b96018bSArnd Bergmann case SIOCSIFHWADDR: 30986b96018bSArnd Bergmann case SIOCADDMULTI: 30996b96018bSArnd Bergmann case SIOCDELMULTI: 31006b96018bSArnd Bergmann case SIOCGIFINDEX: 31016b96018bSArnd Bergmann case SIOCGIFADDR: 31026b96018bSArnd Bergmann case SIOCSIFADDR: 31036b96018bSArnd Bergmann case SIOCSIFHWBROADCAST: 31046b96018bSArnd Bergmann case SIOCDIFADDR: 31056b96018bSArnd Bergmann case SIOCGIFBRDADDR: 31066b96018bSArnd Bergmann case SIOCSIFBRDADDR: 31076b96018bSArnd Bergmann case SIOCGIFDSTADDR: 31086b96018bSArnd Bergmann case SIOCSIFDSTADDR: 31096b96018bSArnd Bergmann case SIOCGIFNETMASK: 31106b96018bSArnd Bergmann case SIOCSIFNETMASK: 31116b96018bSArnd Bergmann case SIOCSIFPFLAGS: 31126b96018bSArnd Bergmann case SIOCGIFPFLAGS: 31136b96018bSArnd Bergmann case SIOCGIFTXQLEN: 31146b96018bSArnd Bergmann case SIOCSIFTXQLEN: 31156b96018bSArnd Bergmann case SIOCBRADDIF: 31166b96018bSArnd Bergmann case SIOCBRDELIF: 31179177efd3SArnd Bergmann case SIOCSIFNAME: 31189177efd3SArnd Bergmann case SIOCGMIIPHY: 31199177efd3SArnd Bergmann case SIOCGMIIREG: 31209177efd3SArnd Bergmann case SIOCSMIIREG: 31216b96018bSArnd Bergmann case SIOCSARP: 31226b96018bSArnd Bergmann case SIOCGARP: 31236b96018bSArnd Bergmann case SIOCDARP: 31246b96018bSArnd Bergmann case SIOCATMARK: 3125f92d4fc9SAl Viro case SIOCBONDENSLAVE: 3126f92d4fc9SAl Viro case SIOCBONDRELEASE: 3127f92d4fc9SAl Viro case SIOCBONDSETHWADDR: 3128f92d4fc9SAl Viro case SIOCBONDCHANGEACTIVE: 31294cf808e7SAl Viro case SIOCGIFNAME: 31309177efd3SArnd Bergmann return sock_do_ioctl(net, sock, cmd, arg); 31319177efd3SArnd Bergmann } 31329177efd3SArnd Bergmann 31336b96018bSArnd Bergmann return -ENOIOCTLCMD; 31346b96018bSArnd Bergmann } 31357a229387SArnd Bergmann 313695c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd, 313789bbfc95SShaun Pereira unsigned long arg) 313889bbfc95SShaun Pereira { 313989bbfc95SShaun Pereira struct socket *sock = file->private_data; 314089bbfc95SShaun Pereira int ret = -ENOIOCTLCMD; 314187de87d5SDavid S. Miller struct sock *sk; 314287de87d5SDavid S. Miller struct net *net; 314387de87d5SDavid S. Miller 314487de87d5SDavid S. Miller sk = sock->sk; 314587de87d5SDavid S. Miller net = sock_net(sk); 314689bbfc95SShaun Pereira 314789bbfc95SShaun Pereira if (sock->ops->compat_ioctl) 314889bbfc95SShaun Pereira ret = sock->ops->compat_ioctl(sock, cmd, arg); 314989bbfc95SShaun Pereira 315087de87d5SDavid S. Miller if (ret == -ENOIOCTLCMD && 315187de87d5SDavid S. Miller (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)) 315287de87d5SDavid S. Miller ret = compat_wext_handle_ioctl(net, cmd, arg); 315387de87d5SDavid S. Miller 31546b96018bSArnd Bergmann if (ret == -ENOIOCTLCMD) 31556b96018bSArnd Bergmann ret = compat_sock_ioctl_trans(file, sock, cmd, arg); 31566b96018bSArnd Bergmann 315789bbfc95SShaun Pereira return ret; 315889bbfc95SShaun Pereira } 315989bbfc95SShaun Pereira #endif 316089bbfc95SShaun Pereira 3161ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen) 3162ac5a488eSSridhar Samudrala { 3163ac5a488eSSridhar Samudrala return sock->ops->bind(sock, addr, addrlen); 3164ac5a488eSSridhar Samudrala } 3165c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind); 3166ac5a488eSSridhar Samudrala 3167ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog) 3168ac5a488eSSridhar Samudrala { 3169ac5a488eSSridhar Samudrala return sock->ops->listen(sock, backlog); 3170ac5a488eSSridhar Samudrala } 3171c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen); 3172ac5a488eSSridhar Samudrala 3173ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags) 3174ac5a488eSSridhar Samudrala { 3175ac5a488eSSridhar Samudrala struct sock *sk = sock->sk; 3176ac5a488eSSridhar Samudrala int err; 3177ac5a488eSSridhar Samudrala 3178ac5a488eSSridhar Samudrala err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol, 3179ac5a488eSSridhar Samudrala newsock); 3180ac5a488eSSridhar Samudrala if (err < 0) 3181ac5a488eSSridhar Samudrala goto done; 3182ac5a488eSSridhar Samudrala 3183cdfbabfbSDavid Howells err = sock->ops->accept(sock, *newsock, flags, true); 3184ac5a488eSSridhar Samudrala if (err < 0) { 3185ac5a488eSSridhar Samudrala sock_release(*newsock); 3186fa8705b0STony Battersby *newsock = NULL; 3187ac5a488eSSridhar Samudrala goto done; 3188ac5a488eSSridhar Samudrala } 3189ac5a488eSSridhar Samudrala 3190ac5a488eSSridhar Samudrala (*newsock)->ops = sock->ops; 31911b08534eSWei Yongjun __module_get((*newsock)->ops->owner); 3192ac5a488eSSridhar Samudrala 3193ac5a488eSSridhar Samudrala done: 3194ac5a488eSSridhar Samudrala return err; 3195ac5a488eSSridhar Samudrala } 3196c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept); 3197ac5a488eSSridhar Samudrala 3198ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen, 3199ac5a488eSSridhar Samudrala int flags) 3200ac5a488eSSridhar Samudrala { 3201ac5a488eSSridhar Samudrala return sock->ops->connect(sock, addr, addrlen, flags); 3202ac5a488eSSridhar Samudrala } 3203c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect); 3204ac5a488eSSridhar Samudrala 3205ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr, 3206ac5a488eSSridhar Samudrala int *addrlen) 3207ac5a488eSSridhar Samudrala { 3208ac5a488eSSridhar Samudrala return sock->ops->getname(sock, addr, addrlen, 0); 3209ac5a488eSSridhar Samudrala } 3210c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname); 3211ac5a488eSSridhar Samudrala 3212ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr, 3213ac5a488eSSridhar Samudrala int *addrlen) 3214ac5a488eSSridhar Samudrala { 3215ac5a488eSSridhar Samudrala return sock->ops->getname(sock, addr, addrlen, 1); 3216ac5a488eSSridhar Samudrala } 3217c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername); 3218ac5a488eSSridhar Samudrala 3219ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname, 3220ac5a488eSSridhar Samudrala char *optval, int *optlen) 3221ac5a488eSSridhar Samudrala { 3222ac5a488eSSridhar Samudrala mm_segment_t oldfs = get_fs(); 3223fb8621bbSNamhyung Kim char __user *uoptval; 3224fb8621bbSNamhyung Kim int __user *uoptlen; 3225ac5a488eSSridhar Samudrala int err; 3226ac5a488eSSridhar Samudrala 3227fb8621bbSNamhyung Kim uoptval = (char __user __force *) optval; 3228fb8621bbSNamhyung Kim uoptlen = (int __user __force *) optlen; 3229fb8621bbSNamhyung Kim 3230ac5a488eSSridhar Samudrala set_fs(KERNEL_DS); 3231ac5a488eSSridhar Samudrala if (level == SOL_SOCKET) 3232fb8621bbSNamhyung Kim err = sock_getsockopt(sock, level, optname, uoptval, uoptlen); 3233ac5a488eSSridhar Samudrala else 3234fb8621bbSNamhyung Kim err = sock->ops->getsockopt(sock, level, optname, uoptval, 3235fb8621bbSNamhyung Kim uoptlen); 3236ac5a488eSSridhar Samudrala set_fs(oldfs); 3237ac5a488eSSridhar Samudrala return err; 3238ac5a488eSSridhar Samudrala } 3239c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt); 3240ac5a488eSSridhar Samudrala 3241ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname, 3242b7058842SDavid S. Miller char *optval, unsigned int optlen) 3243ac5a488eSSridhar Samudrala { 3244ac5a488eSSridhar Samudrala mm_segment_t oldfs = get_fs(); 3245fb8621bbSNamhyung Kim char __user *uoptval; 3246ac5a488eSSridhar Samudrala int err; 3247ac5a488eSSridhar Samudrala 3248fb8621bbSNamhyung Kim uoptval = (char __user __force *) optval; 3249fb8621bbSNamhyung Kim 3250ac5a488eSSridhar Samudrala set_fs(KERNEL_DS); 3251ac5a488eSSridhar Samudrala if (level == SOL_SOCKET) 3252fb8621bbSNamhyung Kim err = sock_setsockopt(sock, level, optname, uoptval, optlen); 3253ac5a488eSSridhar Samudrala else 3254fb8621bbSNamhyung Kim err = sock->ops->setsockopt(sock, level, optname, uoptval, 3255ac5a488eSSridhar Samudrala optlen); 3256ac5a488eSSridhar Samudrala set_fs(oldfs); 3257ac5a488eSSridhar Samudrala return err; 3258ac5a488eSSridhar Samudrala } 3259c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt); 3260ac5a488eSSridhar Samudrala 3261ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset, 3262ac5a488eSSridhar Samudrala size_t size, int flags) 3263ac5a488eSSridhar Samudrala { 3264ac5a488eSSridhar Samudrala if (sock->ops->sendpage) 3265ac5a488eSSridhar Samudrala return sock->ops->sendpage(sock, page, offset, size, flags); 3266ac5a488eSSridhar Samudrala 3267ac5a488eSSridhar Samudrala return sock_no_sendpage(sock, page, offset, size, flags); 3268ac5a488eSSridhar Samudrala } 3269c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage); 3270ac5a488eSSridhar Samudrala 3271306b13ebSTom Herbert int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset, 3272306b13ebSTom Herbert size_t size, int flags) 3273306b13ebSTom Herbert { 3274306b13ebSTom Herbert struct socket *sock = sk->sk_socket; 3275306b13ebSTom Herbert 3276306b13ebSTom Herbert if (sock->ops->sendpage_locked) 3277306b13ebSTom Herbert return sock->ops->sendpage_locked(sk, page, offset, size, 3278306b13ebSTom Herbert flags); 3279306b13ebSTom Herbert 3280306b13ebSTom Herbert return sock_no_sendpage_locked(sk, page, offset, size, flags); 3281306b13ebSTom Herbert } 3282306b13ebSTom Herbert EXPORT_SYMBOL(kernel_sendpage_locked); 3283306b13ebSTom Herbert 328491cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how) 328591cf45f0STrond Myklebust { 328691cf45f0STrond Myklebust return sock->ops->shutdown(sock, how); 328791cf45f0STrond Myklebust } 328891cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown); 3289113c3075SR. Parameswaran 3290113c3075SR. Parameswaran /* This routine returns the IP overhead imposed by a socket i.e. 3291113c3075SR. Parameswaran * the length of the underlying IP header, depending on whether 3292113c3075SR. Parameswaran * this is an IPv4 or IPv6 socket and the length from IP options turned 329357240d00SR. Parameswaran * on at the socket. Assumes that the caller has a lock on the socket. 3294113c3075SR. Parameswaran */ 3295113c3075SR. Parameswaran u32 kernel_sock_ip_overhead(struct sock *sk) 3296113c3075SR. Parameswaran { 3297113c3075SR. Parameswaran struct inet_sock *inet; 3298113c3075SR. Parameswaran struct ip_options_rcu *opt; 3299113c3075SR. Parameswaran u32 overhead = 0; 3300113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6) 3301113c3075SR. Parameswaran struct ipv6_pinfo *np; 3302113c3075SR. Parameswaran struct ipv6_txoptions *optv6 = NULL; 3303113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */ 3304113c3075SR. Parameswaran 3305113c3075SR. Parameswaran if (!sk) 3306113c3075SR. Parameswaran return overhead; 3307113c3075SR. Parameswaran 3308113c3075SR. Parameswaran switch (sk->sk_family) { 3309113c3075SR. Parameswaran case AF_INET: 3310113c3075SR. Parameswaran inet = inet_sk(sk); 3311113c3075SR. Parameswaran overhead += sizeof(struct iphdr); 3312113c3075SR. Parameswaran opt = rcu_dereference_protected(inet->inet_opt, 3313614d79c0Sstephen hemminger sock_owned_by_user(sk)); 3314113c3075SR. Parameswaran if (opt) 3315113c3075SR. Parameswaran overhead += opt->opt.optlen; 3316113c3075SR. Parameswaran return overhead; 3317113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6) 3318113c3075SR. Parameswaran case AF_INET6: 3319113c3075SR. Parameswaran np = inet6_sk(sk); 3320113c3075SR. Parameswaran overhead += sizeof(struct ipv6hdr); 3321113c3075SR. Parameswaran if (np) 3322113c3075SR. Parameswaran optv6 = rcu_dereference_protected(np->opt, 3323614d79c0Sstephen hemminger sock_owned_by_user(sk)); 3324113c3075SR. Parameswaran if (optv6) 3325113c3075SR. Parameswaran overhead += (optv6->opt_flen + optv6->opt_nflen); 3326113c3075SR. Parameswaran return overhead; 3327113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */ 3328113c3075SR. Parameswaran default: /* Returns 0 overhead if the socket is not ipv4 or ipv6 */ 3329113c3075SR. Parameswaran return overhead; 3330113c3075SR. Parameswaran } 3331113c3075SR. Parameswaran } 3332113c3075SR. Parameswaran EXPORT_SYMBOL(kernel_sock_ip_overhead); 3333